authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2020-09-24 19:10:12+02:00
committergravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2020-10-02 19:39:17+02:00
log35b228630cf1972868fe820baeb41a09801f2fbb
tree8a7004ac9f4e3b02ed8ea9f94b08902760187f5e
parent0a54f04dbc4ce9a0a1d1b5fe9d1a5a502030b47e

stage2 ARM: Add stm, ldm variants and misc. additions


2 files changed, 84 insertions(+), 13 deletions(-)

src/codegen.zig+36-5
...@@ -570,6 +570,35 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -570,6 +570,35 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
570 try self.dbgSetEpilogueBegin();570 try self.dbgSetEpilogueBegin();
571 }571 }
572 },572 },
573 .arm => {
574 const cc = self.fn_type.fnCallingConvention();
575 if (cc != .Naked) {
576 // push {fp, lr}
577 // mov fp, sp
578 // sub sp, sp, #reloc
579 // mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.mov(.al, .fp, Instruction.Operand.reg(.sp, Instruction.Operand.Shift.none)).toU32());
580 // const backpatch_reloc = try self.code.addManyAsArray(4);
581
582 try self.dbgSetPrologueEnd();
583
584 try self.genBody(self.mod_fn.analysis.success);
585
586 // Backpatch stack offset
587 // const stack_end = self.max_end_stack;
588 // const aligned_stack_end = mem.alignForward(stack_end, self.stack_align);
589 // mem.writeIntLittle(u32, backpatch_reloc, Instruction.sub(.al, .sp, .sp, Instruction.Operand.imm()));
590
591 try self.dbgSetEpilogueBegin();
592
593 // mov sp, fp
594 // pop {fp, pc}
595 mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.mov(.al, .sp, Instruction.Operand.reg(.fp, Instruction.Operand.Shift.none)).toU32());
596 } else {
597 try self.dbgSetPrologueEnd();
598 try self.genBody(self.mod_fn.analysis.success);
599 try self.dbgSetEpilogueBegin();
600 }
601 },
573 else => {602 else => {
574 try self.dbgSetPrologueEnd();603 try self.dbgSetPrologueEnd();
575 try self.genBody(self.mod_fn.analysis.success);604 try self.genBody(self.mod_fn.analysis.success);
...@@ -1504,13 +1533,10 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -1504,13 +1533,10 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
1504 else1533 else
1505 unreachable;1534 unreachable;
15061535
1507 // TODO only works with leaf functions
1508 // at the moment, which works fine for
1509 // Hello World, but not for real code
1510 // of course. Add pushing lr to stack
1511 // and popping after call
1512 try self.genSetReg(inst.base.src, .lr, .{ .memory = got_addr });1536 try self.genSetReg(inst.base.src, .lr, .{ .memory = got_addr });
15131537
1538 // TODO: add Instruction.supportedOn
1539 // function for ARM
1514 if (Target.arm.featureSetHas(self.target.cpu.features, .has_v5t)) {1540 if (Target.arm.featureSetHas(self.target.cpu.features, .has_v5t)) {
1515 mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.blx(.al, .lr).toU32());1541 mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.blx(.al, .lr).toU32());
1516 } else {1542 } else {
...@@ -1636,6 +1662,9 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -1636,6 +1662,9 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
1636 },1662 },
1637 .arm => {1663 .arm => {
1638 mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.bx(.al, .lr).toU32());1664 mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.bx(.al, .lr).toU32());
1665 // // Just add space for an instruction, patch this later
1666 // try self.code.resize(self.code.items.len + 4);
1667 // try self.exitlude_jump_relocs.append(self.gpa, self.code.items.len - 4);
1639 },1668 },
1640 else => return self.fail(src, "TODO implement return for {}", .{self.target.cpu.arch}),1669 else => return self.fail(src, "TODO implement return for {}", .{self.target.cpu.arch}),
1641 }1670 }
...@@ -2771,6 +2800,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -2771,6 +2800,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
2771 } else {2800 } else {
2772 return self.fail(src, "TODO MCValues with multiple registers", .{});2801 return self.fail(src, "TODO MCValues with multiple registers", .{});
2773 }2802 }
2803 } else if (ncrn < 4 and nsaa == 0) {
2804 return self.fail(src, "TODO MCValues split between registers and stack", .{});
2774 } else {2805 } else {
2775 ncrn = 4;2806 ncrn = 4;
2776 if (ty.abiAlignment(self.target.*) == 8) {2807 if (ty.abiAlignment(self.target.*) == 8) {
src/codegen/arm.zig+48-8
...@@ -446,7 +446,7 @@ pub const Instruction = union(enum) {...@@ -446,7 +446,7 @@ pub const Instruction = union(enum) {
446 pre_post: u1,446 pre_post: u1,
447 up_down: u1,447 up_down: u1,
448 psr_or_user: u1,448 psr_or_user: u1,
449 write_back: u1,449 write_back: bool,
450 load_store: u1,450 load_store: u1,
451 ) Instruction {451 ) Instruction {
452 return Instruction{452 return Instruction{
...@@ -454,7 +454,7 @@ pub const Instruction = union(enum) {...@@ -454,7 +454,7 @@ pub const Instruction = union(enum) {
454 .register_list = @bitCast(u16, reg_list),454 .register_list = @bitCast(u16, reg_list),
455 .rn = rn.id(),455 .rn = rn.id(),
456 .load_store = load_store,456 .load_store = load_store,
457 .write_back = write_back,457 .write_back = if (write_back) 1 else 0,
458 .psr_or_user = psr_or_user,458 .psr_or_user = psr_or_user,
459 .up_down = up_down,459 .up_down = up_down,
460 .pre_post = pre_post,460 .pre_post = pre_post,
...@@ -644,14 +644,50 @@ pub const Instruction = union(enum) {...@@ -644,14 +644,50 @@ pub const Instruction = union(enum) {
644644
645 // Block data transfer645 // Block data transfer
646646
647 pub fn ldm(cond: Condition, rn: Register, reg_list: RegisterList) Instruction {647 pub fn ldmda(cond: Condition, rn: Register, write_back: bool, reg_list: RegisterList) Instruction {
648 return blockDataTransfer(cond, rn, reg_list, 1, 0, 0, 0, 1);648 return blockDataTransfer(cond, rn, reg_list, 0, 0, 0, write_back, 1);
649 }649 }
650650
651 pub fn stm(cond: Condition, rn: Register, reg_list: RegisterList) Instruction {651 pub fn ldmdb(cond: Condition, rn: Register, write_back: bool, reg_list: RegisterList) Instruction {
652 return blockDataTransfer(cond, rn, reg_list, 1, 0, 0, 0, 0);652 return blockDataTransfer(cond, rn, reg_list, 1, 0, 0, write_back, 1);
653 }
654
655 pub fn ldmib(cond: Condition, rn: Register, write_back: bool, reg_list: RegisterList) Instruction {
656 return blockDataTransfer(cond, rn, reg_list, 1, 1, 0, write_back, 1);
657 }
658
659 pub fn ldmia(cond: Condition, rn: Register, write_back: bool, reg_list: RegisterList) Instruction {
660 return blockDataTransfer(cond, rn, reg_list, 0, 1, 0, write_back, 1);
661 }
662
663 pub const ldmfa = ldmda;
664 pub const ldmea = ldmdb;
665 pub const ldmed = ldmib;
666 pub const ldmfd = ldmia;
667 pub const ldm = ldmia;
668
669 pub fn stmda(cond: Condition, rn: Register, write_back: bool, reg_list: RegisterList) Instruction {
670 return blockDataTransfer(cond, rn, reg_list, 0, 0, 0, write_back, 0);
653 }671 }
654672
673 pub fn stmdb(cond: Condition, rn: Register, write_back: bool, reg_list: RegisterList) Instruction {
674 return blockDataTransfer(cond, rn, reg_list, 1, 0, 0, write_back, 0);
675 }
676
677 pub fn stmib(cond: Condition, rn: Register, write_back: bool, reg_list: RegisterList) Instruction {
678 return blockDataTransfer(cond, rn, reg_list, 1, 1, 0, write_back, 0);
679 }
680
681 pub fn stmia(cond: Condition, rn: Register, write_back: bool, reg_list: RegisterList) Instruction {
682 return blockDataTransfer(cond, rn, reg_list, 0, 1, 0, write_back, 0);
683 }
684
685 pub const stmed = stmda;
686 pub const stmfd = stmdb;
687 pub const stmfa = stmib;
688 pub const stmea = stmia;
689 pub const stm = stmia;
690
655 // Branch691 // Branch
656692
657 pub fn b(cond: Condition, offset: i24) Instruction {693 pub fn b(cond: Condition, offset: i24) Instruction {
...@@ -738,10 +774,14 @@ test "serialize instructions" {...@@ -738,10 +774,14 @@ test "serialize instructions" {
738 .inst = Instruction.bkpt(42),774 .inst = Instruction.bkpt(42),
739 .expected = 0b1110_0001_0010_000000000010_0111_1010,775 .expected = 0b1110_0001_0010_000000000010_0111_1010,
740 },776 },
741 .{ // stmfd r9, {r0}777 .{ // stmdb r9, {r0}
742 .inst = Instruction.stm(.al, .r9, .{ .r0 = true }),778 .inst = Instruction.stmdb(.al, .r9, false, .{ .r0 = true }),
743 .expected = 0b1110_100_1_0_0_0_0_1001_0000000000000001,779 .expected = 0b1110_100_1_0_0_0_0_1001_0000000000000001,
744 },780 },
781 .{ // ldmea r4!, {r2, r5}
782 .inst = Instruction.ldmea(.al, .r4, true, .{ .r2 = true, .r5 = true }),
783 .expected = 0b1110_100_1_0_0_1_1_0100_0000000000100100,
784 },
745 };785 };
746786
747 for (testcases) |case| {787 for (testcases) |case| {