diff --git a/src/arch/aarch64/CodeGen.zig b/src/arch/aarch64/CodeGen.zig index 1027c28ce1..971c144338 100644 --- a/src/arch/aarch64/CodeGen.zig +++ b/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), } }, }); diff --git a/src/arch/aarch64/Emit.zig b/src/arch/aarch64/Emit.zig index 77f400ea78..dd297d048d 100644 --- a/src/arch/aarch64/Emit.zig +++ b/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( diff --git a/src/arch/aarch64/bits.zig b/src/arch/aarch64/bits.zig index a5d56cfcc7..1670f88c76 100644 --- a/src/arch/aarch64/bits.zig +++ b/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()) {