stage2 AArch64: implement strb and strh

This commit is contained in:
joachimschmidt557 2021-03-27 21:39:55 +01:00 committed by Jakub Konka
parent 501b4aff99
commit e088a17f56
2 changed files with 63 additions and 33 deletions

View File

@ -3111,7 +3111,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
const adj_off = stack_offset + abi_size; const adj_off = stack_offset + abi_size;
switch (abi_size) { switch (abi_size) {
4, 8 => { 1, 2, 4, 8 => {
const offset = if (math.cast(i9, adj_off)) |imm| const offset = if (math.cast(i9, adj_off)) |imm|
Instruction.LoadStoreOffset.imm_post_index(-imm) Instruction.LoadStoreOffset.imm_post_index(-imm)
else |_| else |_|
@ -3121,8 +3121,14 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
.aarch64_32 => .w29, .aarch64_32 => .w29,
else => unreachable, else => unreachable,
}; };
const str = switch (abi_size) {
1 => Instruction.strb,
2 => Instruction.strh,
4, 8 => Instruction.str,
else => unreachable, // unexpected abi size
};
writeInt(u32, try self.code.addManyAsArray(4), Instruction.str(reg, rn, .{ writeInt(u32, try self.code.addManyAsArray(4), str(reg, rn, .{
.offset = offset, .offset = offset,
}).toU32()); }).toU32());
}, },

View File

@ -484,7 +484,23 @@ pub const Instruction = union(enum) {
} }
}; };
fn loadStoreRegister(rt: Register, rn: Register, offset: LoadStoreOffset, load: bool) Instruction { /// Which kind of load/store to perform
const LoadStoreVariant = enum {
/// 32-bit or 64-bit
normal,
/// 16-bit
half,
/// 8-bit
byte,
};
fn loadStoreRegister(
rt: Register,
rn: Register,
offset: LoadStoreOffset,
variant: LoadStoreVariant,
load: bool,
) Instruction {
const off = offset.toU12(); const off = offset.toU12();
const op1: u2 = blk: { const op1: u2 = blk: {
switch (offset) { switch (offset) {
@ -497,35 +513,27 @@ pub const Instruction = union(enum) {
break :blk 0b00; break :blk 0b00;
}; };
const opc: u2 = if (load) 0b01 else 0b00; const opc: u2 = if (load) 0b01 else 0b00;
switch (rt.size()) { return Instruction{
32 => { .LoadStoreRegister = .{
return Instruction{ .rt = rt.id(),
.LoadStoreRegister = .{ .rn = rn.id(),
.rt = rt.id(), .offset = off,
.rn = rn.id(), .opc = opc,
.offset = offset.toU12(), .op1 = op1,
.opc = opc, .v = 0,
.op1 = op1, .size = blk: {
.v = 0, switch (variant) {
.size = 0b10, .normal => switch (rt.size()) {
}, 32 => break :blk 0b10,
}; 64 => break :blk 0b11,
else => unreachable, // unexpected register size
},
.half => break :blk 0b01,
.byte => break :blk 0b00,
}
},
}, },
64 => { };
return Instruction{
.LoadStoreRegister = .{
.rt = rt.id(),
.rn = rn.id(),
.offset = offset.toU12(),
.opc = opc,
.op1 = op1,
.v = 0,
.size = 0b11,
},
};
},
else => unreachable, // unexpected register size
}
} }
fn loadStorePairOfRegisters( fn loadStorePairOfRegisters(
@ -748,7 +756,7 @@ pub const Instruction = union(enum) {
pub fn ldr(rt: Register, args: LdrArgs) Instruction { pub fn ldr(rt: Register, args: LdrArgs) Instruction {
switch (args) { switch (args) {
.register => |info| return loadStoreRegister(rt, info.rn, info.offset, true), .register => |info| return loadStoreRegister(rt, info.rn, info.offset, .normal, true),
.literal => |literal| return loadLiteral(rt, literal), .literal => |literal| return loadLiteral(rt, literal),
} }
} }
@ -758,7 +766,15 @@ pub const Instruction = union(enum) {
}; };
pub fn str(rt: Register, rn: Register, args: StrArgs) Instruction { pub fn str(rt: Register, rn: Register, args: StrArgs) Instruction {
return loadStoreRegister(rt, rn, args.offset, false); return loadStoreRegister(rt, rn, args.offset, .normal, false);
}
pub fn strh(rt: Register, rn: Register, args: StrArgs) Instruction {
return loadStoreRegister(rt, rn, args.offset, .half, false);
}
pub fn strb(rt: Register, rn: Register, args: StrArgs) Instruction {
return loadStoreRegister(rt, rn, args.offset, .byte, false);
} }
// Load or store pair of registers // Load or store pair of registers
@ -996,6 +1012,14 @@ test "serialize instructions" {
.inst = Instruction.str(.x2, .x1, .{ .offset = Instruction.LoadStoreOffset.reg(.x3) }), .inst = Instruction.str(.x2, .x1, .{ .offset = Instruction.LoadStoreOffset.reg(.x3) }),
.expected = 0b11_111_0_00_00_1_00011_011_0_10_00001_00010, .expected = 0b11_111_0_00_00_1_00011_011_0_10_00001_00010,
}, },
.{ // strh w0, [x1]
.inst = Instruction.strh(.w0, .x1, .{}),
.expected = 0b01_111_0_01_00_000000000000_00001_00000,
},
.{ // strb w8, [x9]
.inst = Instruction.strb(.w8, .x9, .{}),
.expected = 0b00_111_0_01_00_000000000000_01001_01000,
},
.{ // adr x2, #0x8 .{ // adr x2, #0x8
.inst = Instruction.adr(.x2, 0x8), .inst = Instruction.adr(.x2, 0x8),
.expected = 0b0_00_10000_0000000000000000010_00010, .expected = 0b0_00_10000_0000000000000000010_00010,