| ... | @@ -203,6 +203,13 @@ pub const Instruction = union(enum) { | ... | @@ -203,6 +203,13 @@ pub const Instruction = union(enum) { |
| 203 | opc: u2, | 203 | opc: u2, |
| 204 | sf: u1, | 204 | sf: u1, |
| 205 | }, | 205 | }, |
| | 206 | PCRelativeAddress: packed struct { |
| | 207 | rd: u5, |
| | 208 | immhi: u19, |
| | 209 | fixed: u5 = 0b10000, |
| | 210 | immlo: u2, |
| | 211 | op: u1, |
| | 212 | }, |
| 206 | LoadStoreRegister: packed struct { | 213 | LoadStoreRegister: packed struct { |
| 207 | rt: u5, | 214 | rt: u5, |
| 208 | rn: u5, | 215 | rn: u5, |
| ... | @@ -245,6 +252,7 @@ pub const Instruction = union(enum) { | ... | @@ -245,6 +252,7 @@ pub const Instruction = union(enum) { |
| 245 | pub fn toU32(self: Instruction) u32 { | 252 | pub fn toU32(self: Instruction) u32 { |
| 246 | return switch (self) { | 253 | return switch (self) { |
| 247 | .MoveWideImmediate => |v| @bitCast(u32, v), | 254 | .MoveWideImmediate => |v| @bitCast(u32, v), |
| | 255 | .PCRelativeAddress => |v| @bitCast(u32, v), |
| 248 | .LoadStoreRegister => |v| @bitCast(u32, v), | 256 | .LoadStoreRegister => |v| @bitCast(u32, v), |
| 249 | .LoadLiteral => |v| @bitCast(u32, v), | 257 | .LoadLiteral => |v| @bitCast(u32, v), |
| 250 | .ExceptionGeneration => |v| @bitCast(u32, v), | 258 | .ExceptionGeneration => |v| @bitCast(u32, v), |
| ... | @@ -408,6 +416,18 @@ pub const Instruction = union(enum) { | ... | @@ -408,6 +416,18 @@ pub const Instruction = union(enum) { |
| 408 | } | 416 | } |
| 409 | } | 417 | } |
| 410 | | 418 | |
| | 419 | fn pcRelativeAddress(rd: Register, imm21: i21, op: u1) Instruction { |
| | 420 | const imm21_u = @bitCast(u21, imm21); |
| | 421 | return Instruction{ |
| | 422 | .PCRelativeAddress = .{ |
| | 423 | .rd = rd.id(), |
| | 424 | .immlo = @truncate(u2, imm21_u), |
| | 425 | .immhi = @truncate(u19, imm21_u >> 2), |
| | 426 | .op = op, |
| | 427 | }, |
| | 428 | }; |
| | 429 | } |
| | 430 | |
| 411 | fn loadStoreRegister(rt: Register, rn: Register, offset: Offset, load: bool) Instruction { | 431 | fn loadStoreRegister(rt: Register, rn: Register, offset: Offset, load: bool) Instruction { |
| 412 | const off = offset.toU12(); | 432 | const off = offset.toU12(); |
| 413 | const op1: u2 = blk: { | 433 | const op1: u2 = blk: { |
| ... | @@ -536,6 +556,16 @@ pub const Instruction = union(enum) { | ... | @@ -536,6 +556,16 @@ pub const Instruction = union(enum) { |
| 536 | return moveWideImmediate(0b11, rd, imm16, shift); | 556 | return moveWideImmediate(0b11, rd, imm16, shift); |
| 537 | } | 557 | } |
| 538 | | 558 | |
| | 559 | // PC relative address |
| | 560 | |
| | 561 | pub fn adr(rd: Register, imm21: i21) Instruction { |
| | 562 | return pcRelativeAddress(rd, imm21, 0b0); |
| | 563 | } |
| | 564 | |
| | 565 | pub fn adrp(rd: Register, imm21: i21) Instruction { |
| | 566 | return pcRelativeAddress(rd, imm21, 0b1); |
| | 567 | } |
| | 568 | |
| 539 | // Load or store register | 569 | // Load or store register |
| 540 | | 570 | |
| 541 | pub const LdrArgs = struct { | 571 | pub const LdrArgs = struct { |
| ... | @@ -690,6 +720,22 @@ test "serialize instructions" { | ... | @@ -690,6 +720,22 @@ test "serialize instructions" { |
| 690 | .inst = Instruction.str(.x2, .x1, .{ .offset = Instruction.Offset.reg(.x3) }), | 720 | .inst = Instruction.str(.x2, .x1, .{ .offset = Instruction.Offset.reg(.x3) }), |
| 691 | .expected = 0b11_111_0_00_00_1_00011_011_0_10_00001_00010, | 721 | .expected = 0b11_111_0_00_00_1_00011_011_0_10_00001_00010, |
| 692 | }, | 722 | }, |
| | 723 | .{ // adr x2, #0x8 |
| | 724 | .inst = Instruction.adr(.x2, 0x8), |
| | 725 | .expected = 0b0_00_10000_0000000000000000010_00010, |
| | 726 | }, |
| | 727 | .{ // adr x2, -#0x8 |
| | 728 | .inst = Instruction.adr(.x2, -0x8), |
| | 729 | .expected = 0b0_00_10000_1111111111111111110_00010, |
| | 730 | }, |
| | 731 | .{ // adrp x2, #0x8 |
| | 732 | .inst = Instruction.adrp(.x2, 0x8), |
| | 733 | .expected = 0b1_00_10000_0000000000000000010_00010, |
| | 734 | }, |
| | 735 | .{ // adrp x2, -#0x8 |
| | 736 | .inst = Instruction.adrp(.x2, -0x8), |
| | 737 | .expected = 0b1_00_10000_1111111111111111110_00010, |
| | 738 | }, |
| 693 | }; | 739 | }; |
| 694 | | 740 | |
| 695 | for (testcases) |case| { | 741 | for (testcases) |case| { |