Commit 5ff8dd179e

Jakub Konka <kubkon@jakubkonka.com>
2020-11-17 22:16:26
stage2 aarch64: add PC relative address instructions
1 parent a0226ab
Changed files (1)
src
codegen
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| {