stage2 AArch64: distinguish between sp/wsp and xzr/wzr

This commit is contained in:
joachimschmidt557
2022-02-19 20:13:46 +01:00
parent a9154a7eaf
commit 19c683fab0
3 changed files with 84 additions and 56 deletions

View File

@@ -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),
} },
});

View File

@@ -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(

View File

@@ -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()) {