diff options
| author | mparadinha <miguel.p.paradinha@gmail.com> | 2022-02-02 08:48:00 +0000 |
|---|---|---|
| committer | mparadinha <miguel.p.paradinha@gmail.com> | 2022-02-02 09:24:39 +0000 |
| commit | ef4c54ba3836ecb4962f64f10b0b5c12188c9ff4 (patch) | |
| tree | 48b21c8ce57fa9615a256b7e58e341b0c73c7744 | |
| parent | b67b89025cc12785f78a7908e321f8ed0b83afc6 (diff) | |
| download | zig-ef4c54ba3836ecb4962f64f10b0b5c12188c9ff4.tar.gz zig-ef4c54ba3836ecb4962f64f10b0b5c12188c9ff4.zip | |
need to go through the GOT, and use a temporary register
| -rw-r--r-- | src/arch/x86_64/CodeGen.zig | 62 |
1 files changed, 57 insertions, 5 deletions
diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index 9356cf49ac..e926968e5b 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -1781,18 +1781,70 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type } }, .memory => |addr| { - const reg = try self.copyToTmpRegister(ptr_ty, .{ .memory = addr }); + // TODO: in case the address fits in an imm32 we can use [ds:imm32] + // instead of wasting an instruction copying the address to a register + + const addr_reg = try self.copyToTmpRegister(ptr_ty, .{ .immediate = addr }); + // to get the actual address of the value we want to modify we have to go through the GOT // mov reg, [reg] _ = try self.addInst(.{ .tag = .mov, .ops = (Mir.Ops{ - .reg1 = reg.to64(), - .reg2 = reg.to64(), - .flags = 0b10, + .reg1 = addr_reg.to64(), + .reg2 = addr_reg.to64(), + .flags = 0b01, }).encode(), .data = .{ .imm = 0 }, }); - return self.store(.{ .register = reg }, value, ptr_ty, value_ty); + + const abi_size = value_ty.abiSize(self.target.*); + switch (value) { + .immediate => |imm| { + const payload = try self.addExtra(Mir.ImmPair{ + .dest_off = 0, + .operand = @intCast(u32, imm), + }); + _ = try self.addInst(.{ + .tag = .mov_mem_imm, + .ops = (Mir.Ops{ + .reg1 = addr_reg.to64(), + .flags = switch (abi_size) { + 1 => 0b00, + 2 => 0b01, + 4 => 0b10, + 8 => flag: { + const top_bits: u32 = @intCast(u32, imm >> 32); + const can_extend = if (value_ty.isUnsignedInt()) + (top_bits == 0) and (imm & 0x8000_0000) == 0 + else + top_bits == 0xffff_ffff; + + if (!can_extend) { + return self.fail("TODO imm64 would get incorrectly sign extended", .{}); + } + break :flag 0b11; + }, + else => { + return self.fail("TODO saving imm to memory for abi_size {}", .{abi_size}); + }, + }, + }).encode(), + .data = .{ .payload = payload }, + }); + }, + .register => |reg| { + _ = try self.addInst(.{ + .tag = .mov, + .ops = (Mir.Ops{ + .reg1 = addr_reg.to64(), + .reg2 = reg, + .flags = 0b10, + }).encode(), + .data = .{ .imm = 0 }, + }); + }, + else => return self.fail("TODO implement storing {} to MCValue.memory", .{value}), + } }, .stack_offset => { return self.fail("TODO implement storing to MCValue.stack_offset", .{}); |
