Commit 0310d88d7e

Koakuma <koachan@protonmail.com>
2022-05-26 08:08:39
stage2: sparc64: Add cmp and mov synthetic instructions
1 parent ab88165
Changed files (3)
src/arch/sparc64/CodeGen.zig
@@ -1677,7 +1677,7 @@ fn binOp(
 
                         const mir_tag: Mir.Inst.Tag = switch (tag) {
                             .add => .add,
-                            .cmp_eq => .subcc,
+                            .cmp_eq => .cmp,
                             else => unreachable,
                         };
 
@@ -1903,6 +1903,13 @@ fn binOpImmediate(
                 .rs2_or_imm = .{ .imm = @intCast(u6, rhs.immediate) },
             },
         },
+        .cmp => .{
+            .arithmetic_2op = .{
+                .is_imm = true,
+                .rs1 = lhs_reg,
+                .rs2_or_imm = .{ .imm = @intCast(i13, rhs.immediate) },
+            },
+        },
         else => unreachable,
     };
 
@@ -2012,6 +2019,13 @@ fn binOpRegister(
                 .rs2_or_imm = .{ .rs2 = rhs_reg },
             },
         },
+        .cmp => .{
+            .arithmetic_2op = .{
+                .is_imm = false,
+                .rs1 = lhs_reg,
+                .rs2_or_imm = .{ .rs2 = rhs_reg },
+            },
+        },
         else => unreachable,
     };
 
@@ -2303,12 +2317,11 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
         .immediate => |x| {
             if (x <= math.maxInt(u12)) {
                 _ = try self.addInst(.{
-                    .tag = .@"or",
+                    .tag = .mov,
                     .data = .{
-                        .arithmetic_3op = .{
+                        .arithmetic_2op = .{
                             .is_imm = true,
-                            .rd = reg,
-                            .rs1 = .g0,
+                            .rs1 = reg,
                             .rs2_or_imm = .{ .imm = @truncate(u12, x) },
                         },
                     },
@@ -2400,14 +2413,12 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
             if (src_reg.id() == reg.id())
                 return;
 
-            // or %g0, src, dst (aka mov src, dst)
             _ = try self.addInst(.{
-                .tag = .@"or",
+                .tag = .mov,
                 .data = .{
-                    .arithmetic_3op = .{
+                    .arithmetic_2op = .{
                         .is_imm = false,
-                        .rd = reg,
-                        .rs1 = .g0,
+                        .rs1 = reg,
                         .rs2_or_imm = .{ .rs2 = src_reg },
                     },
                 },
@@ -2625,12 +2636,11 @@ fn isErr(self: *Self, ty: Type, operand: MCValue) !MCValue {
             };
 
             _ = try self.addInst(.{
-                .tag = .subcc,
-                .data = .{ .arithmetic_3op = .{
+                .tag = .cmp,
+                .data = .{ .arithmetic_2op = .{
                     .is_imm = true,
                     .rs1 = reg_mcv.register,
                     .rs2_or_imm = .{ .imm = 0 },
-                    .rd = .g0,
                 } },
             });
 
@@ -3163,12 +3173,11 @@ fn truncRegister(
         },
         64 => {
             _ = try self.addInst(.{
-                .tag = .@"or",
+                .tag = .mov,
                 .data = .{
-                    .arithmetic_3op = .{
+                    .arithmetic_2op = .{
                         .is_imm = true,
-                        .rd = dest_reg,
-                        .rs1 = .g0,
+                        .rs1 = dest_reg,
                         .rs2_or_imm = .{ .rs2 = operand_reg },
                     },
                 },
src/arch/sparc64/Emit.zig
@@ -121,6 +121,10 @@ pub fn emitMir(
             .subcc => try emit.mirArithmetic3Op(inst),
 
             .tcc => try emit.mirTrap(inst),
+
+            .cmp => try emit.mirArithmetic2Op(inst),
+
+            .mov => try emit.mirArithmetic2Op(inst),
         }
     }
 }
@@ -179,12 +183,16 @@ fn mirArithmetic2Op(emit: *Emit, inst: Mir.Inst.Index) !void {
         const imm = data.rs2_or_imm.imm;
         switch (tag) {
             .@"return" => try emit.writeInstruction(Instruction.@"return"(i13, rs1, imm)),
+            .cmp => try emit.writeInstruction(Instruction.subcc(i13, rs1, imm, .g0)),
+            .mov => try emit.writeInstruction(Instruction.@"or"(i13, .g0, imm, rs1)),
             else => unreachable,
         }
     } else {
         const rs2 = data.rs2_or_imm.rs2;
         switch (tag) {
             .@"return" => try emit.writeInstruction(Instruction.@"return"(Register, rs1, rs2)),
+            .cmp => try emit.writeInstruction(Instruction.subcc(Register, rs1, rs2, .g0)),
+            .mov => try emit.writeInstruction(Instruction.@"or"(Register, .g0, rs2, rs1)),
             else => unreachable,
         }
     }
src/arch/sparc64/Mir.zig
@@ -125,9 +125,23 @@ pub const Inst = struct {
         /// This uses the trap field.
         tcc,
 
-        // TODO add synthetic instructions
-        // TODO add cmp synthetic instruction to avoid wasting a register when
-        // comparing with subcc
+        // SPARCv9 synthetic instructions
+        // Note that the instructions that is added here are only those that
+        // will simplify backend development. Synthetic instructions that is
+        // only used to provide syntactic sugar in, e.g. inline assembly should
+        // be deconstructed inside the parser instead.
+        // See also: G.3 Synthetic Instructions
+        // TODO add more synthetic instructions
+
+        /// Comparison
+        /// This uses the arithmetic_2op field.
+        cmp, // cmp rs1, rs2/imm -> subcc rs1, rs2/imm, %g0
+
+        /// Copy register/immediate contents to another register
+        /// This uses the arithmetic_2op field, with rs1
+        /// being the *destination* register.
+        // TODO is it okay to abuse rs1 in this way?
+        mov, // mov rs2/imm, rs1 -> or %g0, rs2/imm, rs1
     };
 
     /// The position of an MIR instruction within the `Mir` instructions array.