authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-10-31 23:52:48+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-11-11 14:34:53+01:00
logd542e8870688eeaa46f84efe892c9ab5d51d09c9
tree261de0e7279f9300bb1224eb531d99629606dbce
parent5ad501c00b59205154caeec95685351ee613ea5e

Implement genAsm on aarch64

Add remaining PCS info: param and return registers in procedure calls.

2 files changed, 44 insertions(+), 1 deletions(-)

src/codegen.zig+41
...@@ -2114,6 +2114,47 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -2114,6 +2114,47 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
2114 return MCValue.none;2114 return MCValue.none;
2115 }2115 }
2116 },2116 },
2117 .aarch64 => {
2118 for (inst.inputs) |input, i| {
2119 if (input.len < 3 or input[0] != '{' or input[input.len - 1] != '}') {
2120 return self.fail(inst.base.src, "unrecognized asm input constraint: '{}'", .{input});
2121 }
2122 const reg_name = input[1 .. input.len - 1];
2123 const reg = parseRegName(reg_name) orelse
2124 return self.fail(inst.base.src, "unrecognized register: '{}'", .{reg_name});
2125 const arg = try self.resolveInst(inst.args[i]);
2126 try self.genSetReg(inst.base.src, reg, arg);
2127 }
2128
2129 // TODO move this to lib/std/{elf, macho}.zig, etc.
2130 const is_syscall_inst = switch (self.bin_file.tag) {
2131 .macho => mem.eql(u8, inst.asm_source, "svc #0x80"),
2132 .elf => mem.eql(u8, inst.asm_source, "svc #0"),
2133 else => |tag| return self.fail(inst.base.src, "TODO implement aarch64 support for other syscall instructions for file format: '{}'", .{tag}),
2134 };
2135 if (is_syscall_inst) {
2136 const imm16: u16 = switch (self.bin_file.tag) {
2137 .macho => 0x80,
2138 .elf => 0,
2139 else => unreachable,
2140 };
2141 mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.svc(imm16).toU32());
2142 } else {
2143 return self.fail(inst.base.src, "TODO implement support for more aarch64 assembly instructions", .{});
2144 }
2145
2146 if (inst.output) |output| {
2147 if (output.len < 4 or output[0] != '=' or output[1] != '{' or output[output.len - 1] != '}') {
2148 return self.fail(inst.base.src, "unrecognized asm output constraint: '{}'", .{output});
2149 }
2150 const reg_name = output[2 .. output.len - 1];
2151 const reg = parseRegName(reg_name) orelse
2152 return self.fail(inst.base.src, "unrecognized register: '{}'", .{reg_name});
2153 return MCValue{ .register = reg };
2154 } else {
2155 return MCValue.none;
2156 }
2157 },
2117 .riscv64 => {2158 .riscv64 => {
2118 for (inst.inputs) |input, i| {2159 for (inst.inputs) |input, i| {
2119 if (input.len < 3 or input[0] != '{' or input[input.len - 1] != '}') {2160 if (input.len < 3 or input[0] != '{' or input[input.len - 1] != '}') {
src/codegen/aarch64.zig+3-1
...@@ -59,6 +59,8 @@ pub const callee_preserved_regs = [_]Register{...@@ -59,6 +59,8 @@ pub const callee_preserved_regs = [_]Register{
59 .x19, .x20, .x21, .x22, .x23,59 .x19, .x20, .x21, .x22, .x23,
60 .x24, .x25, .x26, .x27, .x28,60 .x24, .x25, .x26, .x27, .x28,
61};61};
62pub const c_abi_int_param_regs = [_]Register{ .x0, .x1, .x2, .x3, .x4, .x5, .x6, .x7 };
63pub const c_abi_int_return_regs = [_]Register{ .x0, .x1 };
6264
63test "Register.id" {65test "Register.id" {
64 testing.expectEqual(@as(u5, 0), Register.x0.id());66 testing.expectEqual(@as(u5, 0), Register.x0.id());
...@@ -215,7 +217,7 @@ pub const Instruction = union(enum) {...@@ -215,7 +217,7 @@ pub const Instruction = union(enum) {
215217
216 // Supervisor Call218 // Supervisor Call
217219
218 fn svc(imm16: u16) Instruction {220 pub fn svc(imm16: u16) Instruction {
219 return supervisorCall(imm16);221 return supervisorCall(imm16);
220 }222 }
221};223};