From e088a17f56a154ecc43c36e8308833d657e6f43e Mon Sep 17 00:00:00 2001 From: joachimschmidt557 Date: Sat, 27 Mar 2021 21:39:55 +0100 Subject: [PATCH] stage2 AArch64: implement strb and strh --- src/codegen.zig | 10 ++++- src/codegen/aarch64.zig | 86 ++++++++++++++++++++++++++--------------- 2 files changed, 63 insertions(+), 33 deletions(-) diff --git a/src/codegen.zig b/src/codegen.zig index 858a1e6559..6365d66ec6 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -3111,7 +3111,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { const adj_off = stack_offset + abi_size; switch (abi_size) { - 4, 8 => { + 1, 2, 4, 8 => { const offset = if (math.cast(i9, adj_off)) |imm| Instruction.LoadStoreOffset.imm_post_index(-imm) else |_| @@ -3121,8 +3121,14 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { .aarch64_32 => .w29, 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, }).toU32()); }, diff --git a/src/codegen/aarch64.zig b/src/codegen/aarch64.zig index d06abeac07..b80606fe93 100644 --- a/src/codegen/aarch64.zig +++ b/src/codegen/aarch64.zig @@ -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 op1: u2 = blk: { switch (offset) { @@ -497,35 +513,27 @@ pub const Instruction = union(enum) { break :blk 0b00; }; const opc: u2 = if (load) 0b01 else 0b00; - switch (rt.size()) { - 32 => { - return Instruction{ - .LoadStoreRegister = .{ - .rt = rt.id(), - .rn = rn.id(), - .offset = offset.toU12(), - .opc = opc, - .op1 = op1, - .v = 0, - .size = 0b10, - }, - }; + return Instruction{ + .LoadStoreRegister = .{ + .rt = rt.id(), + .rn = rn.id(), + .offset = off, + .opc = opc, + .op1 = op1, + .v = 0, + .size = blk: { + switch (variant) { + .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( @@ -748,7 +756,7 @@ pub const Instruction = union(enum) { pub fn ldr(rt: Register, args: LdrArgs) Instruction { 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), } } @@ -758,7 +766,15 @@ pub const Instruction = union(enum) { }; 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 @@ -996,6 +1012,14 @@ test "serialize instructions" { .inst = Instruction.str(.x2, .x1, .{ .offset = Instruction.LoadStoreOffset.reg(.x3) }), .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 .inst = Instruction.adr(.x2, 0x8), .expected = 0b0_00_10000_0000000000000000010_00010,