aboutsummaryrefslogtreecommitdiff
path: root/src/arch/aarch64/CodeGen.zig
diff options
context:
space:
mode:
authorjoachimschmidt557 <joachim.schmidt557@outlook.com>2022-02-01 20:26:23 +0100
committerjoachimschmidt557 <joachim.schmidt557@outlook.com>2022-02-14 22:09:43 +0100
commit77cf000438c8f65f089e9c64fbb881a9136f2931 (patch)
tree3ee9587288b52cd62e5b9d945c0d3ccb6f8a0b46 /src/arch/aarch64/CodeGen.zig
parent0d16e908fbb93cdaee80bc2514f76a09736bfa04 (diff)
downloadzig-77cf000438c8f65f089e9c64fbb881a9136f2931.tar.gz
zig-77cf000438c8f65f089e9c64fbb881a9136f2931.zip
stage2 AArch64: implement loading from register
Diffstat (limited to 'src/arch/aarch64/CodeGen.zig')
-rw-r--r--src/arch/aarch64/CodeGen.zig138
1 files changed, 136 insertions, 2 deletions
diff --git a/src/arch/aarch64/CodeGen.zig b/src/arch/aarch64/CodeGen.zig
index fd9211d919..39eaa77ad5 100644
--- a/src/arch/aarch64/CodeGen.zig
+++ b/src/arch/aarch64/CodeGen.zig
@@ -1301,8 +1301,64 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
.embedded_in_code => {
return self.fail("TODO implement loading from MCValue.embedded_in_code", .{});
},
- .register => {
- return self.fail("TODO implement loading from MCValue.register for {}", .{self.target.cpu.arch});
+ .register => |addr_reg| {
+ self.register_manager.freezeRegs(&.{addr_reg});
+ defer self.register_manager.unfreezeRegs(&.{addr_reg});
+
+ switch (dst_mcv) {
+ .dead => unreachable,
+ .undef => unreachable,
+ .compare_flags_signed, .compare_flags_unsigned => unreachable,
+ .embedded_in_code => unreachable,
+ .stack_offset => |off| {
+ if (elem_ty.abiSize(self.target.*) <= 8) {
+ const tmp_reg = try self.register_manager.allocReg(null);
+ self.register_manager.freezeRegs(&.{tmp_reg});
+ defer self.register_manager.unfreezeRegs(&.{tmp_reg});
+
+ try self.load(.{ .register = tmp_reg }, ptr, ptr_ty);
+ try self.genSetStack(elem_ty, off, MCValue{ .register = tmp_reg });
+ } else {
+ // TODO optimize the register allocation
+ const regs = try self.register_manager.allocRegs(4, .{ null, null, null, null });
+ self.register_manager.freezeRegs(&regs);
+ defer self.register_manager.unfreezeRegs(&regs);
+
+ const src_reg = addr_reg;
+ const dst_reg = regs[0];
+ const len_reg = regs[1];
+ const count_reg = regs[2];
+ const tmp_reg = regs[3];
+
+ // sub dst_reg, fp, #off
+ const elem_size = @intCast(u32, elem_ty.abiSize(self.target.*));
+ const adj_off = off + elem_size;
+ const offset = math.cast(u12, adj_off) catch return self.fail("TODO load: larger stack offsets", .{});
+ _ = try self.addInst(.{
+ .tag = .sub_immediate,
+ .data = .{ .rr_imm12_sh = .{
+ .rd = dst_reg,
+ .rn = .x29,
+ .imm12 = offset,
+ } },
+ });
+
+ // mov len, #elem_size
+ const len_imm = math.cast(u16, elem_size) catch return self.fail("TODO load: larger stack offsets", .{});
+ _ = try self.addInst(.{
+ .tag = .movk,
+ .data = .{ .r_imm16_sh = .{
+ .rd = len_reg,
+ .imm16 = len_imm,
+ } },
+ });
+
+ // memcpy(src, dst, len)
+ try self.genInlineMemcpy(src_reg, dst_reg, len_reg, count_reg, tmp_reg);
+ }
+ },
+ else => return self.fail("TODO load from register into {}", .{dst_mcv}),
+ }
},
.memory,
.stack_offset,
@@ -1317,6 +1373,84 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
}
}
+fn genInlineMemcpy(
+ self: *Self,
+ src: Register,
+ dst: Register,
+ len: Register,
+ count: Register,
+ tmp: Register,
+) !void {
+ // movk count, #0
+ _ = try self.addInst(.{
+ .tag = .movk,
+ .data = .{ .r_imm16_sh = .{
+ .rd = count,
+ .imm16 = 0,
+ } },
+ });
+
+ // loop:
+ // cmp count, len
+ _ = try self.addInst(.{
+ .tag = .cmp_shifted_register,
+ .data = .{ .rrr_imm6_shift = .{
+ .rd = .xzr,
+ .rn = count,
+ .rm = len,
+ .imm6 = 0,
+ .shift = .lsl,
+ } },
+ });
+
+ // bge end
+ _ = try self.addInst(.{
+ .tag = .b_cond,
+ .data = .{ .inst_cond = .{
+ .inst = @intCast(u32, self.mir_instructions.len + 5),
+ .cond = .ge,
+ } },
+ });
+
+ // ldrb tmp, [src, count]
+ _ = try self.addInst(.{
+ .tag = .ldrb_register,
+ .data = .{ .load_store_register_register = .{
+ .rt = tmp,
+ .rn = src,
+ .offset = Instruction.LoadStoreOffset.reg(count).register,
+ } },
+ });
+
+ // strb tmp, [dest, count]
+ _ = try self.addInst(.{
+ .tag = .strb_register,
+ .data = .{ .load_store_register_register = .{
+ .rt = tmp,
+ .rn = dst,
+ .offset = Instruction.LoadStoreOffset.reg(count).register,
+ } },
+ });
+
+ // add count, count, #1
+ _ = try self.addInst(.{
+ .tag = .add_immediate,
+ .data = .{ .rr_imm12_sh = .{
+ .rd = count,
+ .rn = count,
+ .imm12 = 1,
+ } },
+ });
+
+ // b loop
+ _ = try self.addInst(.{
+ .tag = .b,
+ .data = .{ .inst = @intCast(u32, self.mir_instructions.len - 5) },
+ });
+
+ // end:
+}
+
fn airLoad(self: *Self, inst: Air.Inst.Index) !void {
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
const elem_ty = self.air.typeOfIndex(inst);