| ... | @@ -2730,13 +2730,10 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -2730,13 +2730,10 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 2730 | // For MachO, the binary, with the exception of object files, has to be a PIE. | 2730 | // For MachO, the binary, with the exception of object files, has to be a PIE. |
| 2731 | // Therefore we cannot load an absolute address. | 2731 | // Therefore we cannot load an absolute address. |
| 2732 | // Instead, we need to make use of PC-relative addressing. | 2732 | // Instead, we need to make use of PC-relative addressing. |
| 2733 | // TODO This needs to be optimised in the stack usage (perhaps use a shadow stack | | |
| 2734 | // like described here: | | |
| 2735 | // https://community.arm.com/developer/ip-products/processors/b/processors-ip-blog/posts/using-the-stack-in-aarch64-implementing-push-and-pop) | | |
| 2736 | // TODO As far as branching is concerned, instead of saving the return address | | |
| 2737 | // in a register, I'm thinking here of immitating x86_64, and having the address | | |
| 2738 | // passed on the stack. | | |
| 2739 | if (reg.id() == 0) { // x0 is special-cased | 2733 | if (reg.id() == 0) { // x0 is special-cased |
| | 2734 | // TODO This needs to be optimised in the stack usage (perhaps use a shadow stack |
| | 2735 | // like described here: |
| | 2736 | // https://community.arm.com/developer/ip-products/processors/b/processors-ip-blog/posts/using-the-stack-in-aarch64-implementing-push-and-pop) |
| 2740 | // str x28, [sp, #-16] | 2737 | // str x28, [sp, #-16] |
| 2741 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.str(.x28, Register.sp, .{ | 2738 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.str(.x28, Register.sp, .{ |
| 2742 | .offset = Instruction.Offset.imm_pre_index(-16), | 2739 | .offset = Instruction.Offset.imm_pre_index(-16), |
| ... | @@ -2755,21 +2752,25 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -2755,21 +2752,25 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 2755 | // b [label] | 2752 | // b [label] |
| 2756 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.b(0).toU32()); | 2753 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.b(0).toU32()); |
| 2757 | // mov r, x0 | 2754 | // mov r, x0 |
| 2758 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.orr(reg, .x0, Instruction.RegisterShift.none()).toU32()); | 2755 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.orr( |
| | 2756 | reg, |
| | 2757 | .x0, |
| | 2758 | Instruction.RegisterShift.none(), |
| | 2759 | ).toU32()); |
| 2759 | // ldr x28, [sp], #16 | 2760 | // ldr x28, [sp], #16 |
| 2760 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.ldr(.x28, .{ | 2761 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.ldr(.x28, .{ |
| 2761 | .rn = Register.sp, | 2762 | .rn = Register.sp, |
| 2762 | .offset = Instruction.Offset.imm_post_index(16), | 2763 | .offset = Instruction.Offset.imm_post_index(16), |
| 2763 | }).toU32()); | 2764 | }).toU32()); |
| 2764 | } else { | 2765 | } else { |
| 2765 | // str x28, [sp, #-16] | 2766 | // stp x0, x28, [sp, #-16] |
| 2766 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.str(.x28, Register.sp, .{ | 2767 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.stp( |
| 2767 | .offset = Instruction.Offset.imm_pre_index(-16), | 2768 | .x0, |
| 2768 | }).toU32()); | 2769 | .x28, |
| 2769 | // str x0, [sp, #-16] | 2770 | Register.sp, |
| 2770 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.str(.x0, Register.sp, .{ | 2771 | -2, |
| 2771 | .offset = Instruction.Offset.imm_pre_index(-16), | 2772 | .SignedOffset, |
| 2772 | }).toU32()); | 2773 | ).toU32()); |
| 2773 | // adr x28, #8 | 2774 | // adr x28, #8 |
| 2774 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.adr(.x28, 8).toU32()); | 2775 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.adr(.x28, 8).toU32()); |
| 2775 | if (self.bin_file.cast(link.File.MachO)) |macho_file| { | 2776 | if (self.bin_file.cast(link.File.MachO)) |macho_file| { |
| ... | @@ -2784,17 +2785,19 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -2784,17 +2785,19 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 2784 | // b [label] | 2785 | // b [label] |
| 2785 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.b(0).toU32()); | 2786 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.b(0).toU32()); |
| 2786 | // mov r, x0 | 2787 | // mov r, x0 |
| 2787 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.orr(reg, .x0, Instruction.RegisterShift.none()).toU32()); | 2788 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.orr( |
| 2788 | // ldr x0, [sp], #16 | 2789 | reg, |
| 2789 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.ldr(.x0, .{ | 2790 | .x0, |
| 2790 | .rn = Register.sp, | 2791 | Instruction.RegisterShift.none(), |
| 2791 | .offset = Instruction.Offset.imm_post_index(16), | 2792 | ).toU32()); |
| 2792 | }).toU32()); | 2793 | // ldp x0, x28, [sp, #16] |
| 2793 | // ldr x28, [sp], #16 | 2794 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.ldp( |
| 2794 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.ldr(.x28, .{ | 2795 | .x0, |
| 2795 | .rn = Register.sp, | 2796 | .x28, |
| 2796 | .offset = Instruction.Offset.imm_post_index(16), | 2797 | Register.sp, |
| 2797 | }).toU32()); | 2798 | 2, |
| | 2799 | .SignedOffset, |
| | 2800 | ).toU32()); |
| 2798 | } | 2801 | } |
| 2799 | } else { | 2802 | } else { |
| 2800 | // The value is in memory at a hard-coded address. | 2803 | // The value is in memory at a hard-coded address. |