authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-11-11 00:27:58+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-11-11 14:34:53+01:00
logf512676d0b4220a5f771110982657140c363a146
treef5e65489a49396f13468ce7b9b760d67b4cf5a9a
parentf1960302d115cf42554481871d22393998b87338

stage2 aarch64: add str instruction


1 files changed, 36 insertions(+), 10 deletions(-)

src/codegen/aarch64.zig+36-10
......@@ -203,11 +203,11 @@ pub const Instruction = union(enum) {
203203 opc: u2,
204204 sf: u1,
205205 },
206 LoadRegister: packed struct {
206 LoadStoreRegister: packed struct {
207207 rt: u5,
208208 rn: u5,
209209 offset: u12,
210 opc: u2 = 0b01,
210 opc: u2,
211211 op1: u2,
212212 fixed: u4 = 0b111_0,
213213 size: u2,
......@@ -242,7 +242,7 @@ pub const Instruction = union(enum) {
242242 pub fn toU32(self: Instruction) u32 {
243243 return switch (self) {
244244 .MoveWideImmediate => |v| @bitCast(u32, v),
245 .LoadRegister => |v| @bitCast(u32, v),
245 .LoadStoreRegister => |v| @bitCast(u32, v),
246246 .LoadLiteral => |v| @bitCast(u32, v),
247247 .ExceptionGeneration => |v| @bitCast(u32, v),
248248 .UnconditionalBranchRegister => |v| @bitCast(u32, v),
......@@ -276,8 +276,8 @@ pub const Instruction = union(enum) {
276276 pub fn toU12(self: Offset) u12 {
277277 return switch (self) {
278278 .Immediate => |imm_type| switch (imm_type) {
279 .PostIndex => |v| @intCast(u12, @bitCast(u9, v)) << 2 + 1,
280 .PreIndex => |v| @intCast(u12, @bitCast(u9, v)) << 2 + 3,
279 .PostIndex => |v| (@intCast(u12, @bitCast(u9, v)) << 2) + 1,
280 .PreIndex => |v| (@intCast(u12, @bitCast(u9, v)) << 2) + 3,
281281 .Unsigned => |v| v,
282282 },
283283 .Register => |r| switch (r.shift) {
......@@ -404,7 +404,7 @@ pub const Instruction = union(enum) {
404404 }
405405 }
406406
407 fn loadRegister(rt: Register, rn: Register, offset: Offset) Instruction {
407 fn loadStoreRegister(rt: Register, rn: Register, offset: Offset, load: bool) Instruction {
408408 const off = offset.toU12();
409409 const op1: u2 = blk: {
410410 switch (offset) {
......@@ -416,13 +416,15 @@ pub const Instruction = union(enum) {
416416 }
417417 break :blk 0b00;
418418 };
419 const opc: u2 = if (load) 0b01 else 0b00;
419420 switch (rt.size()) {
420421 32 => {
421422 return Instruction{
422 .LoadRegister = .{
423 .LoadStoreRegister = .{
423424 .rt = rt.id(),
424425 .rn = rn.id(),
425426 .offset = offset.toU12(),
427 .opc = opc,
426428 .op1 = op1,
427429 .size = 0b10,
428430 },
......@@ -430,10 +432,11 @@ pub const Instruction = union(enum) {
430432 },
431433 64 => {
432434 return Instruction{
433 .LoadRegister = .{
435 .LoadStoreRegister = .{
434436 .rt = rt.id(),
435437 .rn = rn.id(),
436438 .offset = offset.toU12(),
439 .opc = opc,
437440 .op1 = op1,
438441 .size = 0b11,
439442 },
......@@ -529,7 +532,7 @@ pub const Instruction = union(enum) {
529532 return moveWideImmediate(0b11, rd, imm16, shift);
530533 }
531534
532 // Load register
535 // Load or store register
533536
534537 pub const LdrArgs = struct {
535538 rn: ?Register = null,
......@@ -538,12 +541,19 @@ pub const Instruction = union(enum) {
538541 };
539542 pub fn ldr(rt: Register, args: LdrArgs) Instruction {
540543 if (args.rn) |rn| {
541 return loadRegister(rt, rn, args.offset);
544 return loadStoreRegister(rt, rn, args.offset, true);
542545 } else {
543546 return loadLiteral(rt, args.literal.?);
544547 }
545548 }
546549
550 pub const StrArgs = struct {
551 offset: Offset = Offset.none,
552 };
553 pub fn str(rt: Register, rn: Register, args: StrArgs) Instruction {
554 return loadStoreRegister(rt, rn, args.offset, false);
555 }
556
547557 // Exception generation
548558
549559 pub fn svc(imm16: u16) Instruction {
......@@ -646,6 +656,14 @@ test "serialize instructions" {
646656 .inst = Instruction.ldr(.x2, .{ .rn = .x1 }),
647657 .expected = 0b11_111_0_01_01_000000000000_00001_00010,
648658 },
659 .{ // ldr x2, [x1, #1]!
660 .inst = Instruction.ldr(.x2, .{ .rn = .x1, .offset = Instruction.Offset.imm_pre_index(1) }),
661 .expected = 0b11_111_0_00_01_0_000000001_11_00001_00010,
662 },
663 .{ // ldr x2, [x1], #-1
664 .inst = Instruction.ldr(.x2, .{ .rn = .x1, .offset = Instruction.Offset.imm_post_index(-1) }),
665 .expected = 0b11_111_0_00_01_0_111111111_01_00001_00010,
666 },
649667 .{ // ldr x2, [x1], (x3)
650668 .inst = Instruction.ldr(.x2, .{ .rn = .x1, .offset = Instruction.Offset.reg(.x3) }),
651669 .expected = 0b11_111_0_00_01_1_00011_011_0_10_00001_00010,
......@@ -654,6 +672,14 @@ test "serialize instructions" {
654672 .inst = Instruction.ldr(.x2, .{ .literal = 0x1 }),
655673 .expected = 0b01_011_0_00_0000000000000000001_00010,
656674 },
675 .{ // str x2, [x1]
676 .inst = Instruction.str(.x2, .x1, .{}),
677 .expected = 0b11_111_0_01_00_000000000000_00001_00010,
678 },
679 .{ // str x2, [x1], (x3)
680 .inst = Instruction.str(.x2, .x1, .{ .offset = Instruction.Offset.reg(.x3) }),
681 .expected = 0b11_111_0_00_00_1_00011_011_0_10_00001_00010,
682 },
657683 };
658684
659685 for (testcases) |case| {