| ... | ... | @@ -203,6 +203,13 @@ pub const Instruction = union(enum) { |
| 203 | 203 | opc: u2, |
| 204 | 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 | 213 | LoadStoreRegister: packed struct { |
| 207 | 214 | rt: u5, |
| 208 | 215 | rn: u5, |
| ... | ... | @@ -245,6 +252,7 @@ pub const Instruction = union(enum) { |
| 245 | 252 | pub fn toU32(self: Instruction) u32 { |
| 246 | 253 | return switch (self) { |
| 247 | 254 | .MoveWideImmediate => |v| @bitCast(u32, v), |
| 255 | .PCRelativeAddress => |v| @bitCast(u32, v), |
| 248 | 256 | .LoadStoreRegister => |v| @bitCast(u32, v), |
| 249 | 257 | .LoadLiteral => |v| @bitCast(u32, v), |
| 250 | 258 | .ExceptionGeneration => |v| @bitCast(u32, v), |
| ... | ... | @@ -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 | 431 | fn loadStoreRegister(rt: Register, rn: Register, offset: Offset, load: bool) Instruction { |
| 412 | 432 | const off = offset.toU12(); |
| 413 | 433 | const op1: u2 = blk: { |
| ... | ... | @@ -536,6 +556,16 @@ pub const Instruction = union(enum) { |
| 536 | 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 | 569 | // Load or store register |
| 540 | 570 | |
| 541 | 571 | pub const LdrArgs = struct { |
| ... | ... | @@ -690,6 +720,22 @@ test "serialize instructions" { |
| 690 | 720 | .inst = Instruction.str(.x2, .x1, .{ .offset = Instruction.Offset.reg(.x3) }), |
| 691 | 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 | 741 | for (testcases) |case| { |