| author | |
| committer | |
| log | 0310d88d7e6a855b3641b59c25f5b0f13726d14f |
| tree | 22bd5154426108c2e24a21a943d35004d328377a |
| parent | ab88165326abfd81c5046e8c064bd6603198ed94 |
3 files changed, 51 insertions(+), 20 deletions(-)
src/arch/sparc64/CodeGen.zig+26-17| ... | ... | @@ -1677,7 +1677,7 @@ fn binOp( |
| 1677 | 1677 | |
| 1678 | 1678 | const mir_tag: Mir.Inst.Tag = switch (tag) { |
| 1679 | 1679 | .add => .add, |
| 1680 | .cmp_eq => .subcc, | |
| 1680 | .cmp_eq => .cmp, | |
| 1681 | 1681 | else => unreachable, |
| 1682 | 1682 | }; |
| 1683 | 1683 | |
| ... | ... | @@ -1903,6 +1903,13 @@ fn binOpImmediate( |
| 1903 | 1903 | .rs2_or_imm = .{ .imm = @intCast(u6, rhs.immediate) }, |
| 1904 | 1904 | }, |
| 1905 | 1905 | }, |
| 1906 | .cmp => .{ | |
| 1907 | .arithmetic_2op = .{ | |
| 1908 | .is_imm = true, | |
| 1909 | .rs1 = lhs_reg, | |
| 1910 | .rs2_or_imm = .{ .imm = @intCast(i13, rhs.immediate) }, | |
| 1911 | }, | |
| 1912 | }, | |
| 1906 | 1913 | else => unreachable, |
| 1907 | 1914 | }; |
| 1908 | 1915 | |
| ... | ... | @@ -2012,6 +2019,13 @@ fn binOpRegister( |
| 2012 | 2019 | .rs2_or_imm = .{ .rs2 = rhs_reg }, |
| 2013 | 2020 | }, |
| 2014 | 2021 | }, |
| 2022 | .cmp => .{ | |
| 2023 | .arithmetic_2op = .{ | |
| 2024 | .is_imm = false, | |
| 2025 | .rs1 = lhs_reg, | |
| 2026 | .rs2_or_imm = .{ .rs2 = rhs_reg }, | |
| 2027 | }, | |
| 2028 | }, | |
| 2015 | 2029 | else => unreachable, |
| 2016 | 2030 | }; |
| 2017 | 2031 | |
| ... | ... | @@ -2303,12 +2317,11 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 2303 | 2317 | .immediate => |x| { |
| 2304 | 2318 | if (x <= math.maxInt(u12)) { |
| 2305 | 2319 | _ = try self.addInst(.{ |
| 2306 | .tag = .@"or", | |
| 2320 | .tag = .mov, | |
| 2307 | 2321 | .data = .{ |
| 2308 | .arithmetic_3op = .{ | |
| 2322 | .arithmetic_2op = .{ | |
| 2309 | 2323 | .is_imm = true, |
| 2310 | .rd = reg, | |
| 2311 | .rs1 = .g0, | |
| 2324 | .rs1 = reg, | |
| 2312 | 2325 | .rs2_or_imm = .{ .imm = @truncate(u12, x) }, |
| 2313 | 2326 | }, |
| 2314 | 2327 | }, |
| ... | ... | @@ -2400,14 +2413,12 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 2400 | 2413 | if (src_reg.id() == reg.id()) |
| 2401 | 2414 | return; |
| 2402 | 2415 | |
| 2403 | // or %g0, src, dst (aka mov src, dst) | |
| 2404 | 2416 | _ = try self.addInst(.{ |
| 2405 | .tag = .@"or", | |
| 2417 | .tag = .mov, | |
| 2406 | 2418 | .data = .{ |
| 2407 | .arithmetic_3op = .{ | |
| 2419 | .arithmetic_2op = .{ | |
| 2408 | 2420 | .is_imm = false, |
| 2409 | .rd = reg, | |
| 2410 | .rs1 = .g0, | |
| 2421 | .rs1 = reg, | |
| 2411 | 2422 | .rs2_or_imm = .{ .rs2 = src_reg }, |
| 2412 | 2423 | }, |
| 2413 | 2424 | }, |
| ... | ... | @@ -2625,12 +2636,11 @@ fn isErr(self: *Self, ty: Type, operand: MCValue) !MCValue { |
| 2625 | 2636 | }; |
| 2626 | 2637 | |
| 2627 | 2638 | _ = try self.addInst(.{ |
| 2628 | .tag = .subcc, | |
| 2629 | .data = .{ .arithmetic_3op = .{ | |
| 2639 | .tag = .cmp, | |
| 2640 | .data = .{ .arithmetic_2op = .{ | |
| 2630 | 2641 | .is_imm = true, |
| 2631 | 2642 | .rs1 = reg_mcv.register, |
| 2632 | 2643 | .rs2_or_imm = .{ .imm = 0 }, |
| 2633 | .rd = .g0, | |
| 2634 | 2644 | } }, |
| 2635 | 2645 | }); |
| 2636 | 2646 | |
| ... | ... | @@ -3163,12 +3173,11 @@ fn truncRegister( |
| 3163 | 3173 | }, |
| 3164 | 3174 | 64 => { |
| 3165 | 3175 | _ = try self.addInst(.{ |
| 3166 | .tag = .@"or", | |
| 3176 | .tag = .mov, | |
| 3167 | 3177 | .data = .{ |
| 3168 | .arithmetic_3op = .{ | |
| 3178 | .arithmetic_2op = .{ | |
| 3169 | 3179 | .is_imm = true, |
| 3170 | .rd = dest_reg, | |
| 3171 | .rs1 = .g0, | |
| 3180 | .rs1 = dest_reg, | |
| 3172 | 3181 | .rs2_or_imm = .{ .rs2 = operand_reg }, |
| 3173 | 3182 | }, |
| 3174 | 3183 | }, |
src/arch/sparc64/Emit.zig+8| ... | ... | @@ -121,6 +121,10 @@ pub fn emitMir( |
| 121 | 121 | .subcc => try emit.mirArithmetic3Op(inst), |
| 122 | 122 | |
| 123 | 123 | .tcc => try emit.mirTrap(inst), |
| 124 | ||
| 125 | .cmp => try emit.mirArithmetic2Op(inst), | |
| 126 | ||
| 127 | .mov => try emit.mirArithmetic2Op(inst), | |
| 124 | 128 | } |
| 125 | 129 | } |
| 126 | 130 | } |
| ... | ... | @@ -179,12 +183,16 @@ fn mirArithmetic2Op(emit: *Emit, inst: Mir.Inst.Index) !void { |
| 179 | 183 | const imm = data.rs2_or_imm.imm; |
| 180 | 184 | switch (tag) { |
| 181 | 185 | .@"return" => try emit.writeInstruction(Instruction.@"return"(i13, rs1, imm)), |
| 186 | .cmp => try emit.writeInstruction(Instruction.subcc(i13, rs1, imm, .g0)), | |
| 187 | .mov => try emit.writeInstruction(Instruction.@"or"(i13, .g0, imm, rs1)), | |
| 182 | 188 | else => unreachable, |
| 183 | 189 | } |
| 184 | 190 | } else { |
| 185 | 191 | const rs2 = data.rs2_or_imm.rs2; |
| 186 | 192 | switch (tag) { |
| 187 | 193 | .@"return" => try emit.writeInstruction(Instruction.@"return"(Register, rs1, rs2)), |
| 194 | .cmp => try emit.writeInstruction(Instruction.subcc(Register, rs1, rs2, .g0)), | |
| 195 | .mov => try emit.writeInstruction(Instruction.@"or"(Register, .g0, rs2, rs1)), | |
| 188 | 196 | else => unreachable, |
| 189 | 197 | } |
| 190 | 198 | } |
src/arch/sparc64/Mir.zig+17-3| ... | ... | @@ -125,9 +125,23 @@ pub const Inst = struct { |
| 125 | 125 | /// This uses the trap field. |
| 126 | 126 | tcc, |
| 127 | 127 | |
| 128 | // TODO add synthetic instructions | |
| 129 | // TODO add cmp synthetic instruction to avoid wasting a register when | |
| 130 | // comparing with subcc | |
| 128 | // SPARCv9 synthetic instructions | |
| 129 | // Note that the instructions that is added here are only those that | |
| 130 | // will simplify backend development. Synthetic instructions that is | |
| 131 | // only used to provide syntactic sugar in, e.g. inline assembly should | |
| 132 | // be deconstructed inside the parser instead. | |
| 133 | // See also: G.3 Synthetic Instructions | |
| 134 | // TODO add more synthetic instructions | |
| 135 | ||
| 136 | /// Comparison | |
| 137 | /// This uses the arithmetic_2op field. | |
| 138 | cmp, // cmp rs1, rs2/imm -> subcc rs1, rs2/imm, %g0 | |
| 139 | ||
| 140 | /// Copy register/immediate contents to another register | |
| 141 | /// This uses the arithmetic_2op field, with rs1 | |
| 142 | /// being the *destination* register. | |
| 143 | // TODO is it okay to abuse rs1 in this way? | |
| 144 | mov, // mov rs2/imm, rs1 -> or %g0, rs2/imm, rs1 | |
| 131 | 145 | }; |
| 132 | 146 | |
| 133 | 147 | /// The position of an MIR instruction within the `Mir` instructions array. |