Commit eca0727417

Jakub Konka <kubkon@jakubkonka.com>
2020-12-09 07:56:49
stage2+aarch64: use stp and ldp to navigate MachO jump table
1 parent 21dae53
Changed files (1)
src/codegen.zig
@@ -2730,13 +2730,10 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
                             // For MachO, the binary, with the exception of object files, has to be a PIE.
                             // Therefore we cannot load an absolute address.
                             // Instead, we need to make use of PC-relative addressing.
-                            // TODO This needs to be optimised in the stack usage (perhaps use a shadow stack
-                            // like described here:
-                            // https://community.arm.com/developer/ip-products/processors/b/processors-ip-blog/posts/using-the-stack-in-aarch64-implementing-push-and-pop)
-                            // TODO As far as branching is concerned, instead of saving the return address
-                            // in a register, I'm thinking here of immitating x86_64, and having the address
-                            // passed on the stack.
                             if (reg.id() == 0) { // x0 is special-cased
+                                // TODO This needs to be optimised in the stack usage (perhaps use a shadow stack
+                                // like described here:
+                                // https://community.arm.com/developer/ip-products/processors/b/processors-ip-blog/posts/using-the-stack-in-aarch64-implementing-push-and-pop)
                                 // str x28, [sp, #-16]
                                 mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.str(.x28, Register.sp, .{
                                     .offset = Instruction.Offset.imm_pre_index(-16),
@@ -2755,21 +2752,25 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
                                 // b [label]
                                 mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.b(0).toU32());
                                 // mov r, x0
-                                mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.orr(reg, .x0, Instruction.RegisterShift.none()).toU32());
+                                mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.orr(
+                                    reg,
+                                    .x0,
+                                    Instruction.RegisterShift.none(),
+                                ).toU32());
                                 // ldr x28, [sp], #16
                                 mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.ldr(.x28, .{
                                     .rn = Register.sp,
                                     .offset = Instruction.Offset.imm_post_index(16),
                                 }).toU32());
                             } else {
-                                // str x28, [sp, #-16]
-                                mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.str(.x28, Register.sp, .{
-                                    .offset = Instruction.Offset.imm_pre_index(-16),
-                                }).toU32());
-                                // str x0, [sp, #-16]
-                                mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.str(.x0, Register.sp, .{
-                                    .offset = Instruction.Offset.imm_pre_index(-16),
-                                }).toU32());
+                                // stp x0, x28, [sp, #-16]
+                                mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.stp(
+                                    .x0,
+                                    .x28,
+                                    Register.sp,
+                                    -2,
+                                    .SignedOffset,
+                                ).toU32());
                                 // adr x28, #8
                                 mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.adr(.x28, 8).toU32());
                                 if (self.bin_file.cast(link.File.MachO)) |macho_file| {
@@ -2784,17 +2785,19 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
                                 // b [label]
                                 mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.b(0).toU32());
                                 // mov r, x0
-                                mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.orr(reg, .x0, Instruction.RegisterShift.none()).toU32());
-                                // ldr x0, [sp], #16
-                                mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.ldr(.x0, .{
-                                    .rn = Register.sp,
-                                    .offset = Instruction.Offset.imm_post_index(16),
-                                }).toU32());
-                                // ldr x28, [sp], #16
-                                mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.ldr(.x28, .{
-                                    .rn = Register.sp,
-                                    .offset = Instruction.Offset.imm_post_index(16),
-                                }).toU32());
+                                mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.orr(
+                                    reg,
+                                    .x0,
+                                    Instruction.RegisterShift.none(),
+                                ).toU32());
+                                // ldp x0, x28, [sp, #16]
+                                mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.ldp(
+                                    .x0,
+                                    .x28,
+                                    Register.sp,
+                                    2,
+                                    .SignedOffset,
+                                ).toU32());
                             }
                         } else {
                             // The value is in memory at a hard-coded address.