authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2021-03-27 21:39:55+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-03-31 23:26:49+02:00
loge088a17f56a154ecc43c36e8308833d657e6f43e
tree776c36bb528ac145d96dda5ede95ec3d3e8ef3d0
parent501b4aff9968e691283dd6ce637b503a12b03d38

stage2 AArch64: implement strb and strh


2 files changed, 63 insertions(+), 33 deletions(-)

src/codegen.zig+8-2
...@@ -3111,7 +3111,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -3111,7 +3111,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
3111 const adj_off = stack_offset + abi_size;3111 const adj_off = stack_offset + abi_size;
31123112
3113 switch (abi_size) {3113 switch (abi_size) {
3114 4, 8 => {3114 1, 2, 4, 8 => {
3115 const offset = if (math.cast(i9, adj_off)) |imm|3115 const offset = if (math.cast(i9, adj_off)) |imm|
3116 Instruction.LoadStoreOffset.imm_post_index(-imm)3116 Instruction.LoadStoreOffset.imm_post_index(-imm)
3117 else |_|3117 else |_|
...@@ -3121,8 +3121,14 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -3121,8 +3121,14 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
3121 .aarch64_32 => .w29,3121 .aarch64_32 => .w29,
3122 else => unreachable,3122 else => unreachable,
3123 };3123 };
3124 const str = switch (abi_size) {
3125 1 => Instruction.strb,
3126 2 => Instruction.strh,
3127 4, 8 => Instruction.str,
3128 else => unreachable, // unexpected abi size
3129 };
31243130
3125 writeInt(u32, try self.code.addManyAsArray(4), Instruction.str(reg, rn, .{3131 writeInt(u32, try self.code.addManyAsArray(4), str(reg, rn, .{
3126 .offset = offset,3132 .offset = offset,
3127 }).toU32());3133 }).toU32());
3128 },3134 },
src/codegen/aarch64.zig+55-31
...@@ -484,7 +484,23 @@ pub const Instruction = union(enum) {...@@ -484,7 +484,23 @@ pub const Instruction = union(enum) {
484 }484 }
485 };485 };
486486
487 fn loadStoreRegister(rt: Register, rn: Register, offset: LoadStoreOffset, load: bool) Instruction {487 /// Which kind of load/store to perform
488 const LoadStoreVariant = enum {
489 /// 32-bit or 64-bit
490 normal,
491 /// 16-bit
492 half,
493 /// 8-bit
494 byte,
495 };
496
497 fn loadStoreRegister(
498 rt: Register,
499 rn: Register,
500 offset: LoadStoreOffset,
501 variant: LoadStoreVariant,
502 load: bool,
503 ) Instruction {
488 const off = offset.toU12();504 const off = offset.toU12();
489 const op1: u2 = blk: {505 const op1: u2 = blk: {
490 switch (offset) {506 switch (offset) {
...@@ -497,35 +513,27 @@ pub const Instruction = union(enum) {...@@ -497,35 +513,27 @@ pub const Instruction = union(enum) {
497 break :blk 0b00;513 break :blk 0b00;
498 };514 };
499 const opc: u2 = if (load) 0b01 else 0b00;515 const opc: u2 = if (load) 0b01 else 0b00;
500 switch (rt.size()) {516 return Instruction{
501 32 => {517 .LoadStoreRegister = .{
502 return Instruction{518 .rt = rt.id(),
503 .LoadStoreRegister = .{519 .rn = rn.id(),
504 .rt = rt.id(),520 .offset = off,
505 .rn = rn.id(),521 .opc = opc,
506 .offset = offset.toU12(),522 .op1 = op1,
507 .opc = opc,523 .v = 0,
508 .op1 = op1,524 .size = blk: {
509 .v = 0,525 switch (variant) {
510 .size = 0b10,526 .normal => switch (rt.size()) {
511 },527 32 => break :blk 0b10,
512 };528 64 => break :blk 0b11,
513 },529 else => unreachable, // unexpected register size
514 64 => {530 },
515 return Instruction{531 .half => break :blk 0b01,
516 .LoadStoreRegister = .{532 .byte => break :blk 0b00,
517 .rt = rt.id(),533 }
518 .rn = rn.id(),534 },
519 .offset = offset.toU12(),
520 .opc = opc,
521 .op1 = op1,
522 .v = 0,
523 .size = 0b11,
524 },
525 };
526 },535 },
527 else => unreachable, // unexpected register size536 };
528 }
529 }537 }
530538
531 fn loadStorePairOfRegisters(539 fn loadStorePairOfRegisters(
...@@ -748,7 +756,7 @@ pub const Instruction = union(enum) {...@@ -748,7 +756,7 @@ pub const Instruction = union(enum) {
748756
749 pub fn ldr(rt: Register, args: LdrArgs) Instruction {757 pub fn ldr(rt: Register, args: LdrArgs) Instruction {
750 switch (args) {758 switch (args) {
751 .register => |info| return loadStoreRegister(rt, info.rn, info.offset, true),759 .register => |info| return loadStoreRegister(rt, info.rn, info.offset, .normal, true),
752 .literal => |literal| return loadLiteral(rt, literal),760 .literal => |literal| return loadLiteral(rt, literal),
753 }761 }
754 }762 }
...@@ -758,7 +766,15 @@ pub const Instruction = union(enum) {...@@ -758,7 +766,15 @@ pub const Instruction = union(enum) {
758 };766 };
759767
760 pub fn str(rt: Register, rn: Register, args: StrArgs) Instruction {768 pub fn str(rt: Register, rn: Register, args: StrArgs) Instruction {
761 return loadStoreRegister(rt, rn, args.offset, false);769 return loadStoreRegister(rt, rn, args.offset, .normal, false);
770 }
771
772 pub fn strh(rt: Register, rn: Register, args: StrArgs) Instruction {
773 return loadStoreRegister(rt, rn, args.offset, .half, false);
774 }
775
776 pub fn strb(rt: Register, rn: Register, args: StrArgs) Instruction {
777 return loadStoreRegister(rt, rn, args.offset, .byte, false);
762 }778 }
763779
764 // Load or store pair of registers780 // Load or store pair of registers
...@@ -996,6 +1012,14 @@ test "serialize instructions" {...@@ -996,6 +1012,14 @@ test "serialize instructions" {
996 .inst = Instruction.str(.x2, .x1, .{ .offset = Instruction.LoadStoreOffset.reg(.x3) }),1012 .inst = Instruction.str(.x2, .x1, .{ .offset = Instruction.LoadStoreOffset.reg(.x3) }),
997 .expected = 0b11_111_0_00_00_1_00011_011_0_10_00001_00010,1013 .expected = 0b11_111_0_00_00_1_00011_011_0_10_00001_00010,
998 },1014 },
1015 .{ // strh w0, [x1]
1016 .inst = Instruction.strh(.w0, .x1, .{}),
1017 .expected = 0b01_111_0_01_00_000000000000_00001_00000,
1018 },
1019 .{ // strb w8, [x9]
1020 .inst = Instruction.strb(.w8, .x9, .{}),
1021 .expected = 0b00_111_0_01_00_000000000000_01001_01000,
1022 },
999 .{ // adr x2, #0x81023 .{ // adr x2, #0x8
1000 .inst = Instruction.adr(.x2, 0x8),1024 .inst = Instruction.adr(.x2, 0x8),
1001 .expected = 0b0_00_10000_0000000000000000010_00010,1025 .expected = 0b0_00_10000_0000000000000000010_00010,