Commit 9ad74b6087

Koakuma <koachan@protonmail.com>
2022-06-01 04:41:40
stage2: sparc64: Implement SPARCv9 addcc and movcc
1 parent 97c43af
Changed files (2)
src
arch
src/arch/sparc64/bits.zig
@@ -1141,6 +1141,14 @@ pub const Instruction = union(enum) {
         };
     }
 
+    pub fn addcc(comptime s2: type, rs1: Register, rs2: s2, rd: Register) Instruction {
+        return switch (s2) {
+            Register => format3a(0b10, 0b01_0000, rs1, rs2, rd),
+            i13 => format3b(0b10, 0b01_0000, rs1, rs2, rd),
+            else => unreachable,
+        };
+    }
+
     pub fn bpcc(cond: ICondition, annul: bool, pt: bool, ccr: CCR, disp: i21) Instruction {
         return format2c(0b001, .{ .icond = cond }, annul, pt, ccr, disp);
     }
@@ -1197,6 +1205,14 @@ pub const Instruction = union(enum) {
         };
     }
 
+    pub fn movcc(comptime s2: type, cond: Condition, ccr: CCR, rs2: s2, rd: Register) Instruction {
+        return switch (s2) {
+            Register => format4c(0b10_1100, cond, ccr, rs2, rd),
+            i11 => format4d(0b10_1100, cond, ccr, rs2, rd),
+            else => unreachable,
+        };
+    }
+
     pub fn mulx(comptime s2: type, rs1: Register, rs2: s2, rd: Register) Instruction {
         return switch (s2) {
             Register => format3a(0b10, 0b00_1001, rs1, rs2, rd),
src/arch/sparc64/Emit.zig
@@ -79,7 +79,7 @@ pub fn emitMir(
             .dbg_epilogue_begin => try emit.mirDebugEpilogueBegin(),
 
             .add => try emit.mirArithmetic3Op(inst),
-            .addcc => @panic("TODO implement sparc64 addcc"),
+            .addcc => try emit.mirArithmetic3Op(inst),
 
             .bpr => try emit.mirConditionalBranch(inst),
             .bpcc => try emit.mirConditionalBranch(inst),
@@ -95,7 +95,7 @@ pub fn emitMir(
 
             .@"or" => try emit.mirArithmetic3Op(inst),
 
-            .movcc => @panic("TODO implement sparc64 movcc"),
+            .movcc => try emit.mirConditionalMove(inst),
 
             .mulx => try emit.mirArithmetic3Op(inst),
 
@@ -212,6 +212,7 @@ fn mirArithmetic3Op(emit: *Emit, inst: Mir.Inst.Index) !void {
         const imm = data.rs2_or_imm.imm;
         switch (tag) {
             .add => try emit.writeInstruction(Instruction.add(i13, rs1, imm, rd)),
+            .addcc => try emit.writeInstruction(Instruction.addcc(i13, rs1, imm, rd)),
             .jmpl => try emit.writeInstruction(Instruction.jmpl(i13, rs1, imm, rd)),
             .ldub => try emit.writeInstruction(Instruction.ldub(i13, rs1, imm, rd)),
             .lduh => try emit.writeInstruction(Instruction.lduh(i13, rs1, imm, rd)),
@@ -233,6 +234,7 @@ fn mirArithmetic3Op(emit: *Emit, inst: Mir.Inst.Index) !void {
         const rs2 = data.rs2_or_imm.rs2;
         switch (tag) {
             .add => try emit.writeInstruction(Instruction.add(Register, rs1, rs2, rd)),
+            .addcc => try emit.writeInstruction(Instruction.addcc(Register, rs1, rs2, rd)),
             .jmpl => try emit.writeInstruction(Instruction.jmpl(Register, rs1, rs2, rd)),
             .ldub => try emit.writeInstruction(Instruction.ldub(Register, rs1, rs2, rd)),
             .lduh => try emit.writeInstruction(Instruction.lduh(Register, rs1, rs2, rd)),
@@ -297,6 +299,34 @@ fn mirConditionalBranch(emit: *Emit, inst: Mir.Inst.Index) !void {
     }
 }
 
+fn mirConditionalMove(emit: *Emit, inst: Mir.Inst.Index) !void {
+    const tag = emit.mir.instructions.items(.tag)[inst];
+
+    switch (tag) {
+        .movcc => {
+            const data = emit.mir.instructions.items(.data)[inst].conditional_move;
+            if (data.is_imm) {
+                try emit.writeInstruction(Instruction.movcc(
+                    i11,
+                    data.cond,
+                    data.ccr,
+                    data.rs2_or_imm.imm,
+                    data.rd,
+                ));
+            } else {
+                try emit.writeInstruction(Instruction.movcc(
+                    Register,
+                    data.cond,
+                    data.ccr,
+                    data.rs2_or_imm.rs2,
+                    data.rd,
+                ));
+            }
+        },
+        else => unreachable,
+    }
+}
+
 fn mirNop(emit: *Emit) !void {
     try emit.writeInstruction(Instruction.nop());
 }