From 5ff8dd179e0ccb17f894d8d76a9079e3080653cd Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Tue, 17 Nov 2020 22:16:26 +0100 Subject: [PATCH] stage2 aarch64: add PC relative address instructions --- src/codegen/aarch64.zig | 46 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/src/codegen/aarch64.zig b/src/codegen/aarch64.zig index ab5b5da604..256c3129dc 100644 --- a/src/codegen/aarch64.zig +++ b/src/codegen/aarch64.zig @@ -203,6 +203,13 @@ pub const Instruction = union(enum) { opc: u2, sf: u1, }, + PCRelativeAddress: packed struct { + rd: u5, + immhi: u19, + fixed: u5 = 0b10000, + immlo: u2, + op: u1, + }, LoadStoreRegister: packed struct { rt: u5, rn: u5, @@ -245,6 +252,7 @@ pub const Instruction = union(enum) { pub fn toU32(self: Instruction) u32 { return switch (self) { .MoveWideImmediate => |v| @bitCast(u32, v), + .PCRelativeAddress => |v| @bitCast(u32, v), .LoadStoreRegister => |v| @bitCast(u32, v), .LoadLiteral => |v| @bitCast(u32, v), .ExceptionGeneration => |v| @bitCast(u32, v), @@ -408,6 +416,18 @@ pub const Instruction = union(enum) { } } + fn pcRelativeAddress(rd: Register, imm21: i21, op: u1) Instruction { + const imm21_u = @bitCast(u21, imm21); + return Instruction{ + .PCRelativeAddress = .{ + .rd = rd.id(), + .immlo = @truncate(u2, imm21_u), + .immhi = @truncate(u19, imm21_u >> 2), + .op = op, + }, + }; + } + fn loadStoreRegister(rt: Register, rn: Register, offset: Offset, load: bool) Instruction { const off = offset.toU12(); const op1: u2 = blk: { @@ -536,6 +556,16 @@ pub const Instruction = union(enum) { return moveWideImmediate(0b11, rd, imm16, shift); } + // PC relative address + + pub fn adr(rd: Register, imm21: i21) Instruction { + return pcRelativeAddress(rd, imm21, 0b0); + } + + pub fn adrp(rd: Register, imm21: i21) Instruction { + return pcRelativeAddress(rd, imm21, 0b1); + } + // Load or store register pub const LdrArgs = struct { @@ -690,6 +720,22 @@ test "serialize instructions" { .inst = Instruction.str(.x2, .x1, .{ .offset = Instruction.Offset.reg(.x3) }), .expected = 0b11_111_0_00_00_1_00011_011_0_10_00001_00010, }, + .{ // adr x2, #0x8 + .inst = Instruction.adr(.x2, 0x8), + .expected = 0b0_00_10000_0000000000000000010_00010, + }, + .{ // adr x2, -#0x8 + .inst = Instruction.adr(.x2, -0x8), + .expected = 0b0_00_10000_1111111111111111110_00010, + }, + .{ // adrp x2, #0x8 + .inst = Instruction.adrp(.x2, 0x8), + .expected = 0b1_00_10000_0000000000000000010_00010, + }, + .{ // adrp x2, -#0x8 + .inst = Instruction.adrp(.x2, -0x8), + .expected = 0b1_00_10000_1111111111111111110_00010, + }, }; for (testcases) |case| {