aboutsummaryrefslogtreecommitdiff
path: root/src/codegen.zig
diff options
context:
space:
mode:
authorJakub Konka <kubkon@jakubkonka.com>2020-11-25 19:58:15 +0100
committerJakub Konka <kubkon@jakubkonka.com>2020-11-26 11:50:09 +0100
commitc749b78df50160bedae40f90765442dd1f49de3a (patch)
tree18db7b29753f67f787ff2c3de696af673ce0b5cf /src/codegen.zig
parent10942e3f86c03d30833cc221371f30b78a4bd710 (diff)
downloadzig-c749b78df50160bedae40f90765442dd1f49de3a.tar.gz
zig-c749b78df50160bedae40f90765442dd1f49de3a.zip
stage2 macho: add orr and orn instructions
Diffstat (limited to 'src/codegen.zig')
-rw-r--r--src/codegen.zig59
1 files changed, 53 insertions, 6 deletions
diff --git a/src/codegen.zig b/src/codegen.zig
index 1482e8de7e..35443ba0b1 100644
--- a/src/codegen.zig
+++ b/src/codegen.zig
@@ -2588,17 +2588,64 @@ 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.
- // 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)
+ // 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
+ // 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());
+ // adr x28, #8
+ mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.adr(.x28, 8).toU32());
try self.mod_fn.owner_decl.link.macho.addPieFixup(self.bin_file.allocator, .{
.address = addr,
.start = self.code.items.len,
.len = 4,
});
- // bl [label]
- mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.bl(0).toU32());
- // } else {
- // unreachable; // TODO
- // }
+ // 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 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());
+ // adr x28, #8
+ mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.adr(.x28, 8).toU32());
+ try self.mod_fn.owner_decl.link.macho.addPieFixup(self.bin_file.allocator, .{
+ .address = addr,
+ .start = self.code.items.len,
+ .len = 4,
+ });
+ // 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());
+ }
} else {
// The value is in memory at a hard-coded address.
// If the type is a pointer, it means the pointer address is at this memory location.