Commit 4d15284c3c

Koakuma <koachan@protonmail.com>
2022-06-16 18:53:22
stage2: sparc64: Implement SPARCv9 shifts
1 parent 513ab4e
Changed files (4)
src/arch/sparc64/bits.zig
@@ -1313,6 +1313,54 @@ pub const Instruction = union(enum) {
         return format2a(0b100, imm, rd);
     }
 
+    pub fn sll(comptime s2: type, rs1: Register, rs2: s2, rd: Register) Instruction {
+        return switch (s2) {
+            Register => format3k(0b11, 0b10_0101, .shift32, rs1, rs2, rd),
+            u5 => format3l(0b11, 0b10_0101, rs1, rs2, rd),
+            else => unreachable,
+        };
+    }
+
+    pub fn srl(comptime s2: type, rs1: Register, rs2: s2, rd: Register) Instruction {
+        return switch (s2) {
+            Register => format3k(0b11, 0b10_0110, .shift32, rs1, rs2, rd),
+            u5 => format3l(0b11, 0b10_0110, rs1, rs2, rd),
+            else => unreachable,
+        };
+    }
+
+    pub fn sra(comptime s2: type, rs1: Register, rs2: s2, rd: Register) Instruction {
+        return switch (s2) {
+            Register => format3k(0b11, 0b10_0111, .shift32, rs1, rs2, rd),
+            u5 => format3l(0b11, 0b10_0111, rs1, rs2, rd),
+            else => unreachable,
+        };
+    }
+
+    pub fn sllx(comptime s2: type, rs1: Register, rs2: s2, rd: Register) Instruction {
+        return switch (s2) {
+            Register => format3k(0b11, 0b10_0101, .shift64, rs1, rs2, rd),
+            u6 => format3m(0b11, 0b10_0101, rs1, rs2, rd),
+            else => unreachable,
+        };
+    }
+
+    pub fn srlx(comptime s2: type, rs1: Register, rs2: s2, rd: Register) Instruction {
+        return switch (s2) {
+            Register => format3k(0b11, 0b10_0110, .shift64, rs1, rs2, rd),
+            u6 => format3m(0b11, 0b10_0110, rs1, rs2, rd),
+            else => unreachable,
+        };
+    }
+
+    pub fn srax(comptime s2: type, rs1: Register, rs2: s2, rd: Register) Instruction {
+        return switch (s2) {
+            Register => format3k(0b11, 0b10_0111, .shift64, rs1, rs2, rd),
+            u6 => format3m(0b11, 0b10_0111, rs1, rs2, rd),
+            else => unreachable,
+        };
+    }
+
     pub fn stb(comptime s2: type, rs1: Register, rs2: s2, rd: Register) Instruction {
         return switch (s2) {
             Register => format3a(0b11, 0b00_0101, rs1, rs2, rd),
src/arch/sparc64/CodeGen.zig
@@ -2337,7 +2337,6 @@ fn binOpImmediate(
         .sllx => .{
             .shift = .{
                 .is_imm = true,
-                .width = ShiftWidth.shift64,
                 .rd = dest_reg,
                 .rs1 = lhs_reg,
                 .rs2_or_imm = .{ .imm = @intCast(u6, rhs.immediate) },
@@ -2459,7 +2458,6 @@ fn binOpRegister(
         .sllx => .{
             .shift = .{
                 .is_imm = false,
-                .width = ShiftWidth.shift64,
                 .rd = dest_reg,
                 .rs1 = lhs_reg,
                 .rs2_or_imm = .{ .rs2 = rhs_reg },
@@ -2940,7 +2938,6 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
                     .data = .{
                         .shift = .{
                             .is_imm = true,
-                            .width = .shift64,
                             .rd = reg,
                             .rs1 = reg,
                             .rs2_or_imm = .{ .imm = 12 },
@@ -2971,7 +2968,6 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
                     .data = .{
                         .shift = .{
                             .is_imm = true,
-                            .width = .shift64,
                             .rd = reg,
                             .rs1 = reg,
                             .rs2_or_imm = .{ .imm = 32 },
@@ -3768,7 +3764,6 @@ fn truncRegister(
                 .data = .{
                     .shift = .{
                         .is_imm = true,
-                        .width = ShiftWidth.shift64,
                         .rd = dest_reg,
                         .rs1 = operand_reg,
                         .rs2_or_imm = .{ .imm = @intCast(u6, 64 - int_bits) },
@@ -3783,7 +3778,6 @@ fn truncRegister(
                 .data = .{
                     .shift = .{
                         .is_imm = true,
-                        .width = ShiftWidth.shift32,
                         .rd = dest_reg,
                         .rs1 = dest_reg,
                         .rs2_or_imm = .{ .imm = @intCast(u6, int_bits) },
@@ -3800,7 +3794,6 @@ fn truncRegister(
                 .data = .{
                     .shift = .{
                         .is_imm = true,
-                        .width = ShiftWidth.shift32,
                         .rd = dest_reg,
                         .rs1 = operand_reg,
                         .rs2_or_imm = .{ .imm = 0 },
src/arch/sparc64/Emit.zig
@@ -115,12 +115,12 @@ pub fn emitMir(
 
             .sethi => try emit.mirSethi(inst),
 
-            .sll => @panic("TODO implement sparc64 sll"),
-            .srl => @panic("TODO implement sparc64 srl"),
-            .sra => @panic("TODO implement sparc64 sra"),
-            .sllx => @panic("TODO implement sparc64 sllx"),
-            .srlx => @panic("TODO implement sparc64 srlx"),
-            .srax => @panic("TODO implement sparc64 srax"),
+            .sll => try emit.mirShift(inst),
+            .srl => try emit.mirShift(inst),
+            .sra => try emit.mirShift(inst),
+            .sllx => try emit.mirShift(inst),
+            .srlx => try emit.mirShift(inst),
+            .srax => try emit.mirShift(inst),
 
             .stb => try emit.mirArithmetic3Op(inst),
             .sth => try emit.mirArithmetic3Op(inst),
@@ -370,6 +370,38 @@ fn mirSethi(emit: *Emit, inst: Mir.Inst.Index) !void {
     try emit.writeInstruction(Instruction.sethi(imm, rd));
 }
 
+fn mirShift(emit: *Emit, inst: Mir.Inst.Index) !void {
+    const tag = emit.mir.instructions.items(.tag)[inst];
+    const data = emit.mir.instructions.items(.data)[inst].shift;
+
+    const rd = data.rd;
+    const rs1 = data.rs1;
+
+    if (data.is_imm) {
+        const imm = data.rs2_or_imm.imm;
+        switch (tag) {
+            .sll => try emit.writeInstruction(Instruction.sll(u5, rs1, @truncate(u5, imm), rd)),
+            .srl => try emit.writeInstruction(Instruction.srl(u5, rs1, @truncate(u5, imm), rd)),
+            .sra => try emit.writeInstruction(Instruction.sra(u5, rs1, @truncate(u5, imm), rd)),
+            .sllx => try emit.writeInstruction(Instruction.sllx(u6, rs1, imm, rd)),
+            .srlx => try emit.writeInstruction(Instruction.srlx(u6, rs1, imm, rd)),
+            .srax => try emit.writeInstruction(Instruction.srax(u6, rs1, imm, rd)),
+            else => unreachable,
+        }
+    } else {
+        const rs2 = data.rs2_or_imm.rs2;
+        switch (tag) {
+            .sll => try emit.writeInstruction(Instruction.sll(Register, rs1, rs2, rd)),
+            .srl => try emit.writeInstruction(Instruction.srl(Register, rs1, rs2, rd)),
+            .sra => try emit.writeInstruction(Instruction.sra(Register, rs1, rs2, rd)),
+            .sllx => try emit.writeInstruction(Instruction.sllx(Register, rs1, rs2, rd)),
+            .srlx => try emit.writeInstruction(Instruction.srlx(Register, rs1, rs2, rd)),
+            .srax => try emit.writeInstruction(Instruction.srax(Register, rs1, rs2, rd)),
+            else => unreachable,
+        }
+    }
+}
+
 fn mirTrap(emit: *Emit, inst: Mir.Inst.Index) !void {
     const tag = emit.mir.instructions.items(.tag)[inst];
     const data = emit.mir.instructions.items(.data)[inst].trap;
src/arch/sparc64/Mir.zig
@@ -299,7 +299,6 @@ pub const Inst = struct {
         /// Used by e.g. sllx
         shift: struct {
             is_imm: bool,
-            width: Instruction.ShiftWidth,
             rd: Register,
             rs1: Register,
             rs2_or_imm: union {