| ... | @@ -1781,18 +1781,70 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type | ... | @@ -1781,18 +1781,70 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 1781 | } | 1781 | } |
| 1782 | }, | 1782 | }, |
| 1783 | .memory => |addr| { | 1783 | .memory => |addr| { |
| 1784 | const reg = try self.copyToTmpRegister(ptr_ty, .{ .memory = addr }); | 1784 | // TODO: in case the address fits in an imm32 we can use [ds:imm32] |
| | 1785 | // instead of wasting an instruction copying the address to a register |
| | 1786 | |
| | 1787 | const addr_reg = try self.copyToTmpRegister(ptr_ty, .{ .immediate = addr }); |
| | 1788 | // to get the actual address of the value we want to modify we have to go through the GOT |
| 1785 | // mov reg, [reg] | 1789 | // mov reg, [reg] |
| 1786 | _ = try self.addInst(.{ | 1790 | _ = try self.addInst(.{ |
| 1787 | .tag = .mov, | 1791 | .tag = .mov, |
| 1788 | .ops = (Mir.Ops{ | 1792 | .ops = (Mir.Ops{ |
| 1789 | .reg1 = reg.to64(), | 1793 | .reg1 = addr_reg.to64(), |
| 1790 | .reg2 = reg.to64(), | 1794 | .reg2 = addr_reg.to64(), |
| 1791 | .flags = 0b10, | 1795 | .flags = 0b01, |
| 1792 | }).encode(), | 1796 | }).encode(), |
| 1793 | .data = .{ .imm = 0 }, | 1797 | .data = .{ .imm = 0 }, |
| 1794 | }); | 1798 | }); |
| 1795 | return self.store(.{ .register = reg }, value, ptr_ty, value_ty); | 1799 | |
| | 1800 | const abi_size = value_ty.abiSize(self.target.*); |
| | 1801 | switch (value) { |
| | 1802 | .immediate => |imm| { |
| | 1803 | const payload = try self.addExtra(Mir.ImmPair{ |
| | 1804 | .dest_off = 0, |
| | 1805 | .operand = @intCast(u32, imm), |
| | 1806 | }); |
| | 1807 | _ = try self.addInst(.{ |
| | 1808 | .tag = .mov_mem_imm, |
| | 1809 | .ops = (Mir.Ops{ |
| | 1810 | .reg1 = addr_reg.to64(), |
| | 1811 | .flags = switch (abi_size) { |
| | 1812 | 1 => 0b00, |
| | 1813 | 2 => 0b01, |
| | 1814 | 4 => 0b10, |
| | 1815 | 8 => flag: { |
| | 1816 | const top_bits: u32 = @intCast(u32, imm >> 32); |
| | 1817 | const can_extend = if (value_ty.isUnsignedInt()) |
| | 1818 | (top_bits == 0) and (imm & 0x8000_0000) == 0 |
| | 1819 | else |
| | 1820 | top_bits == 0xffff_ffff; |
| | 1821 | |
| | 1822 | if (!can_extend) { |
| | 1823 | return self.fail("TODO imm64 would get incorrectly sign extended", .{}); |
| | 1824 | } |
| | 1825 | break :flag 0b11; |
| | 1826 | }, |
| | 1827 | else => { |
| | 1828 | return self.fail("TODO saving imm to memory for abi_size {}", .{abi_size}); |
| | 1829 | }, |
| | 1830 | }, |
| | 1831 | }).encode(), |
| | 1832 | .data = .{ .payload = payload }, |
| | 1833 | }); |
| | 1834 | }, |
| | 1835 | .register => |reg| { |
| | 1836 | _ = try self.addInst(.{ |
| | 1837 | .tag = .mov, |
| | 1838 | .ops = (Mir.Ops{ |
| | 1839 | .reg1 = addr_reg.to64(), |
| | 1840 | .reg2 = reg, |
| | 1841 | .flags = 0b10, |
| | 1842 | }).encode(), |
| | 1843 | .data = .{ .imm = 0 }, |
| | 1844 | }); |
| | 1845 | }, |
| | 1846 | else => return self.fail("TODO implement storing {} to MCValue.memory", .{value}), |
| | 1847 | } |
| 1796 | }, | 1848 | }, |
| 1797 | .stack_offset => { | 1849 | .stack_offset => { |
| 1798 | return self.fail("TODO implement storing to MCValue.stack_offset", .{}); | 1850 | return self.fail("TODO implement storing to MCValue.stack_offset", .{}); |