Commit 19c683fab0

joachimschmidt557 <joachim.schmidt557@outlook.com>
2022-02-19 20:13:46
stage2 AArch64: distinguish between sp/wsp and xzr/wzr
1 parent a9154a7
Changed files (3)
src/arch/aarch64/bits.zig
@@ -7,7 +7,7 @@ const testing = std.testing;
 // zig fmt: off
 
 /// General purpose registers in the AArch64 instruction set
-pub const Register = enum(u6) {
+pub const Register = enum(u7) {
     // 64-bit registers
     x0, x1, x2, x3, x4, x5, x6, x7,
     x8, x9, x10, x11, x12, x13, x14, x15,
@@ -20,10 +20,23 @@ pub const Register = enum(u6) {
     w16, w17, w18, w19, w20, w21, w22, w23,
     w24, w25, w26, w27, w28, w29, w30, wzr,
 
-    pub const sp = Register.xzr;
+    // Stack pointer
+    sp, wsp,
 
-    pub fn id(self: Register) u5 {
-        return @truncate(u5, @enumToInt(self));
+    pub fn id(self: Register) u6 {
+        return switch (@enumToInt(self)) {
+            0...63 => return @as(u6, @truncate(u5, @enumToInt(self))),
+            64...65 => 32,
+            else => unreachable,
+        };
+    }
+
+    pub fn enc(self: Register) u5 {
+        return switch (@enumToInt(self)) {
+            0...63 => return @truncate(u5, @enumToInt(self)),
+            64...65 => 31,
+            else => unreachable,
+        };
     }
 
     /// Returns the bit-width of the register.
@@ -31,17 +44,32 @@ pub const Register = enum(u6) {
         return switch (@enumToInt(self)) {
             0...31 => 64,
             32...63 => 32,
+            64 => 64,
+            65 => 32,
+            else => unreachable,
         };
     }
 
     /// Convert from any register to its 64 bit alias.
     pub fn to64(self: Register) Register {
-        return @intToEnum(Register, self.id());
+        return switch (@enumToInt(self)) {
+            0...31 => self,
+            32...63 => @intToEnum(Register, @enumToInt(self) - 32),
+            64 => .sp,
+            65 => .sp,
+            else => unreachable,
+        };
     }
 
     /// Convert from any register to its 32 bit alias.
     pub fn to32(self: Register) Register {
-        return @intToEnum(Register, @as(u6, self.id()) + 32);
+        return switch (@enumToInt(self)) {
+            0...31 => @intToEnum(Register, @enumToInt(self) + 32),
+            32...63 => self,
+            64 => .wsp,
+            65 => .wsp,
+            else => unreachable,
+        };
     }
 
     /// Returns the index into `callee_preserved_regs`.
@@ -53,7 +81,7 @@ pub const Register = enum(u6) {
     }
 
     pub fn dwarfLocOp(self: Register) u8 {
-        return @as(u8, self.id()) + DW.OP.reg0;
+        return @as(u8, self.enc()) + DW.OP.reg0;
     }
 };
 
@@ -76,15 +104,15 @@ pub const callee_preserved_regs = callee_preserved_regs_impl.callee_preserved_re
 pub const c_abi_int_param_regs = [_]Register{ .x0, .x1, .x2, .x3, .x4, .x5, .x6, .x7 };
 pub const c_abi_int_return_regs = [_]Register{ .x0, .x1, .x2, .x3, .x4, .x5, .x6, .x7 };
 
-test "Register.id" {
-    try testing.expectEqual(@as(u5, 0), Register.x0.id());
-    try testing.expectEqual(@as(u5, 0), Register.w0.id());
+test "Register.enc" {
+    try testing.expectEqual(@as(u5, 0), Register.x0.enc());
+    try testing.expectEqual(@as(u5, 0), Register.w0.enc());
 
-    try testing.expectEqual(@as(u5, 31), Register.xzr.id());
-    try testing.expectEqual(@as(u5, 31), Register.wzr.id());
+    try testing.expectEqual(@as(u5, 31), Register.xzr.enc());
+    try testing.expectEqual(@as(u5, 31), Register.wzr.enc());
 
-    try testing.expectEqual(@as(u5, 31), Register.sp.id());
-    try testing.expectEqual(@as(u5, 31), Register.sp.id());
+    try testing.expectEqual(@as(u5, 31), Register.sp.enc());
+    try testing.expectEqual(@as(u5, 31), Register.sp.enc());
 }
 
 test "Register.size" {
@@ -479,7 +507,7 @@ pub const Instruction = union(enum) {
                 assert(shift % 16 == 0 and shift <= 16);
                 return Instruction{
                     .move_wide_immediate = .{
-                        .rd = rd.id(),
+                        .rd = rd.enc(),
                         .imm16 = imm16,
                         .hw = @intCast(u2, shift / 16),
                         .opc = opc,
@@ -491,7 +519,7 @@ pub const Instruction = union(enum) {
                 assert(shift % 16 == 0 and shift <= 48);
                 return Instruction{
                     .move_wide_immediate = .{
-                        .rd = rd.id(),
+                        .rd = rd.enc(),
                         .imm16 = imm16,
                         .hw = @intCast(u2, shift / 16),
                         .opc = opc,
@@ -508,7 +536,7 @@ pub const Instruction = union(enum) {
         const imm21_u = @bitCast(u21, imm21);
         return Instruction{
             .pc_relative_address = .{
-                .rd = rd.id(),
+                .rd = rd.enc(),
                 .immlo = @truncate(u2, imm21_u),
                 .immhi = @truncate(u19, imm21_u >> 2),
                 .op = op,
@@ -580,7 +608,7 @@ pub const Instruction = union(enum) {
         pub fn reg(rm: Register) LoadStoreOffset {
             return .{
                 .register = .{
-                    .rm = rm.id(),
+                    .rm = rm.enc(),
                     .shift = .{
                         .lsl = 0,
                     },
@@ -592,7 +620,7 @@ pub const Instruction = union(enum) {
             assert(rm.size() == 32 and (shift == 0 or shift == 2));
             return .{
                 .register = .{
-                    .rm = rm.id(),
+                    .rm = rm.enc(),
                     .shift = .{
                         .uxtw = shift,
                     },
@@ -604,7 +632,7 @@ pub const Instruction = union(enum) {
             assert(rm.size() == 64 and (shift == 0 or shift == 3));
             return .{
                 .register = .{
-                    .rm = rm.id(),
+                    .rm = rm.enc(),
                     .shift = .{
                         .lsl = shift,
                     },
@@ -616,7 +644,7 @@ pub const Instruction = union(enum) {
             assert(rm.size() == 32 and (shift == 0 or shift == 2));
             return .{
                 .register = .{
-                    .rm = rm.id(),
+                    .rm = rm.enc(),
                     .shift = .{
                         .sxtw = shift,
                     },
@@ -628,7 +656,7 @@ pub const Instruction = union(enum) {
             assert(rm.size() == 64 and (shift == 0 or shift == 3));
             return .{
                 .register = .{
-                    .rm = rm.id(),
+                    .rm = rm.enc(),
                     .shift = .{
                         .sxtx = shift,
                     },
@@ -676,8 +704,8 @@ pub const Instruction = union(enum) {
         };
         return Instruction{
             .load_store_register = .{
-                .rt = rt.id(),
-                .rn = rn.id(),
+                .rt = rt.enc(),
+                .rn = rn.enc(),
                 .offset = off,
                 .opc = opc,
                 .op1 = op1,
@@ -711,9 +739,9 @@ pub const Instruction = union(enum) {
                 const imm7 = @truncate(u7, @bitCast(u9, offset >> 2));
                 return Instruction{
                     .load_store_register_pair = .{
-                        .rt1 = rt1.id(),
-                        .rn = rn.id(),
-                        .rt2 = rt2.id(),
+                        .rt1 = rt1.enc(),
+                        .rn = rn.enc(),
+                        .rt2 = rt2.enc(),
                         .imm7 = imm7,
                         .load = @boolToInt(load),
                         .encoding = encoding,
@@ -726,9 +754,9 @@ pub const Instruction = union(enum) {
                 const imm7 = @truncate(u7, @bitCast(u9, offset >> 3));
                 return Instruction{
                     .load_store_register_pair = .{
-                        .rt1 = rt1.id(),
-                        .rn = rn.id(),
-                        .rt2 = rt2.id(),
+                        .rt1 = rt1.enc(),
+                        .rn = rn.enc(),
+                        .rt2 = rt2.enc(),
                         .imm7 = imm7,
                         .load = @boolToInt(load),
                         .encoding = encoding,
@@ -743,7 +771,7 @@ pub const Instruction = union(enum) {
     fn loadLiteral(rt: Register, imm19: u19) Instruction {
         return Instruction{
             .load_literal = .{
-                .rt = rt.id(),
+                .rt = rt.enc(),
                 .imm19 = imm19,
                 .opc = switch (rt.size()) {
                     32 => 0b00,
@@ -782,7 +810,7 @@ pub const Instruction = union(enum) {
         return Instruction{
             .unconditional_branch_register = .{
                 .op4 = op4,
-                .rn = rn.id(),
+                .rn = rn.enc(),
                 .op3 = op3,
                 .op2 = op2,
                 .opc = opc,
@@ -818,10 +846,10 @@ pub const Instruction = union(enum) {
                 assert(amount < 32);
                 return Instruction{
                     .logical_shifted_register = .{
-                        .rd = rd.id(),
-                        .rn = rn.id(),
+                        .rd = rd.enc(),
+                        .rn = rn.enc(),
                         .imm6 = amount,
-                        .rm = rm.id(),
+                        .rm = rm.enc(),
                         .n = n,
                         .shift = @enumToInt(shift),
                         .opc = opc,
@@ -832,10 +860,10 @@ pub const Instruction = union(enum) {
             64 => {
                 return Instruction{
                     .logical_shifted_register = .{
-                        .rd = rd.id(),
-                        .rn = rn.id(),
+                        .rd = rd.enc(),
+                        .rn = rn.enc(),
                         .imm6 = amount,
-                        .rm = rm.id(),
+                        .rm = rm.enc(),
                         .n = n,
                         .shift = @enumToInt(shift),
                         .opc = opc,
@@ -857,8 +885,8 @@ pub const Instruction = union(enum) {
     ) Instruction {
         return Instruction{
             .add_subtract_immediate = .{
-                .rd = rd.id(),
-                .rn = rn.id(),
+                .rd = rd.enc(),
+                .rn = rn.enc(),
                 .imm12 = imm12,
                 .sh = @boolToInt(shift),
                 .s = s,
@@ -885,10 +913,10 @@ pub const Instruction = union(enum) {
     ) Instruction {
         return Instruction{
             .add_subtract_shifted_register = .{
-                .rd = rd.id(),
-                .rn = rn.id(),
+                .rd = rd.enc(),
+                .rn = rn.enc(),
                 .imm6 = imm6,
-                .rm = rm.id(),
+                .rm = rm.enc(),
                 .shift = @enumToInt(shift),
                 .s = s,
                 .op = op,
@@ -926,7 +954,7 @@ pub const Instruction = union(enum) {
         assert(offset & 0b11 == 0b00);
         return Instruction{
             .compare_and_branch = .{
-                .rt = rt.id(),
+                .rt = rt.enc(),
                 .imm19 = @bitCast(u19, @intCast(i19, offset >> 2)),
                 .op = op,
                 .sf = switch (rt.size()) {
@@ -949,11 +977,11 @@ pub const Instruction = union(enum) {
     ) Instruction {
         return Instruction{
             .conditional_select = .{
-                .rd = rd.id(),
-                .rn = rn.id(),
+                .rd = rd.enc(),
+                .rn = rn.enc(),
                 .op2 = op2,
                 .cond = @enumToInt(cond),
-                .rm = rm.id(),
+                .rm = rm.enc(),
                 .s = s,
                 .op = op,
                 .sf = switch (rd.size()) {
@@ -976,11 +1004,11 @@ pub const Instruction = union(enum) {
     ) Instruction {
         return Instruction{
             .data_processing_3_source = .{
-                .rd = rd.id(),
-                .rn = rn.id(),
-                .ra = ra.id(),
+                .rd = rd.enc(),
+                .rn = rn.enc(),
+                .ra = ra.enc(),
                 .o0 = o0,
-                .rm = rm.id(),
+                .rm = rm.enc(),
                 .op31 = op31,
                 .op54 = op54,
                 .sf = switch (rd.size()) {
src/arch/aarch64/CodeGen.zig
@@ -372,7 +372,7 @@ fn gen(self: *Self) !void {
             .data = .{ .load_store_register_pair = .{
                 .rt = .x29,
                 .rt2 = .x30,
-                .rn = Register.sp,
+                .rn = .sp,
                 .offset = Instruction.LoadStorePairOffset.pre_index(-16),
             } },
         });
@@ -407,7 +407,7 @@ fn gen(self: *Self) !void {
         self.saved_regs_stack_space = 16;
         inline for (callee_preserved_regs) |reg| {
             if (self.register_manager.isRegAllocated(reg)) {
-                saved_regs |= @as(u32, 1) << reg.id();
+                saved_regs |= @as(u32, 1) << @intCast(u5, reg.id());
                 self.saved_regs_stack_space += 8;
             }
         }
@@ -475,7 +475,7 @@ fn gen(self: *Self) !void {
             .data = .{ .load_store_register_pair = .{
                 .rt = .x29,
                 .rt2 = .x30,
-                .rn = Register.sp,
+                .rn = .sp,
                 .offset = Instruction.LoadStorePairOffset.post_index(16),
             } },
         });
src/arch/aarch64/Emit.zig
@@ -909,7 +909,7 @@ fn mirPushPopRegs(emit: *Emit, inst: Mir.Inst.Index) !void {
             var other_reg: Register = undefined;
             while (i > 0) : (i -= 1) {
                 const reg = @intToEnum(Register, i - 1);
-                if (reg_list & @as(u32, 1) << reg.id() != 0) {
+                if (reg_list & @as(u32, 1) << @intCast(u5, reg.id()) != 0) {
                     if (count % 2 == 0) {
                         if (count == number_of_regs - 1) {
                             try emit.writeInstruction(Instruction.ldr(
@@ -939,7 +939,7 @@ fn mirPushPopRegs(emit: *Emit, inst: Mir.Inst.Index) !void {
             var other_reg: Register = undefined;
             while (i < 32) : (i += 1) {
                 const reg = @intToEnum(Register, i);
-                if (reg_list & @as(u32, 1) << reg.id() != 0) {
+                if (reg_list & @as(u32, 1) << @intCast(u5, reg.id()) != 0) {
                     if (count % 2 == 0) {
                         if (count == number_of_regs - 1) {
                             try emit.writeInstruction(Instruction.str(