| ... | @@ -1210,6 +1210,28 @@ fn asmRegisterMemory(self: *Self, tag: Mir.Inst.Tag, reg: Register, m: Memory) ! | ... | @@ -1210,6 +1210,28 @@ fn asmRegisterMemory(self: *Self, tag: Mir.Inst.Tag, reg: Register, m: Memory) ! |
| 1210 | }); | 1210 | }); |
| 1211 | } | 1211 | } |
| 1212 | | 1212 | |
| | 1213 | fn asmRegisterMemoryImmediate( |
| | 1214 | self: *Self, |
| | 1215 | tag: Mir.Inst.Tag, |
| | 1216 | reg: Register, |
| | 1217 | m: Memory, |
| | 1218 | imm: Immediate, |
| | 1219 | ) !void { |
| | 1220 | _ = try self.addInst(.{ |
| | 1221 | .tag = tag, |
| | 1222 | .ops = switch (m) { |
| | 1223 | .sib => .rmi_sib, |
| | 1224 | .rip => .rmi_rip, |
| | 1225 | else => unreachable, |
| | 1226 | }, |
| | 1227 | .data = .{ .rix = .{ .r = reg, .i = @intCast(u8, imm.unsigned), .payload = switch (m) { |
| | 1228 | .sib => try self.addExtra(Mir.MemorySib.encode(m)), |
| | 1229 | .rip => try self.addExtra(Mir.MemoryRip.encode(m)), |
| | 1230 | else => unreachable, |
| | 1231 | } } }, |
| | 1232 | }); |
| | 1233 | } |
| | 1234 | |
| 1213 | fn asmMemoryRegister(self: *Self, tag: Mir.Inst.Tag, m: Memory, reg: Register) !void { | 1235 | fn asmMemoryRegister(self: *Self, tag: Mir.Inst.Tag, m: Memory, reg: Register) !void { |
| 1214 | _ = try self.addInst(.{ | 1236 | _ = try self.addInst(.{ |
| 1215 | .tag = tag, | 1237 | .tag = tag, |
| ... | @@ -1951,7 +1973,7 @@ fn allocRegOrMemAdvanced(self: *Self, elem_ty: Type, inst: ?Air.Inst.Index, reg_ | ... | @@ -1951,7 +1973,7 @@ fn allocRegOrMemAdvanced(self: *Self, elem_ty: Type, inst: ?Air.Inst.Index, reg_ |
| 1951 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); | 1973 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); |
| 1952 | const ptr_bytes: u64 = @divExact(ptr_bits, 8); | 1974 | const ptr_bytes: u64 = @divExact(ptr_bits, 8); |
| 1953 | if (abi_size <= ptr_bytes) { | 1975 | if (abi_size <= ptr_bytes) { |
| 1954 | if (self.register_manager.tryAllocReg(inst, try self.regClassForType(elem_ty))) |reg| { | 1976 | if (self.register_manager.tryAllocReg(inst, regClassForType(elem_ty))) |reg| { |
| 1955 | return MCValue{ .register = registerAlias(reg, abi_size) }; | 1977 | return MCValue{ .register = registerAlias(reg, abi_size) }; |
| 1956 | } | 1978 | } |
| 1957 | } | 1979 | } |
| ... | @@ -1961,14 +1983,9 @@ fn allocRegOrMemAdvanced(self: *Self, elem_ty: Type, inst: ?Air.Inst.Index, reg_ | ... | @@ -1961,14 +1983,9 @@ fn allocRegOrMemAdvanced(self: *Self, elem_ty: Type, inst: ?Air.Inst.Index, reg_ |
| 1961 | return .{ .load_frame = .{ .index = frame_index } }; | 1983 | return .{ .load_frame = .{ .index = frame_index } }; |
| 1962 | } | 1984 | } |
| 1963 | | 1985 | |
| 1964 | fn regClassForType(self: *Self, ty: Type) !RegisterManager.RegisterBitSet { | 1986 | fn regClassForType(ty: Type) RegisterManager.RegisterBitSet { |
| 1965 | return switch (ty.zigTypeTag()) { | 1987 | return switch (ty.zigTypeTag()) { |
| 1966 | .Vector => self.fail("TODO regClassForType for {}", .{ty.fmt(self.bin_file.options.module.?)}), | 1988 | .Float, .Vector => sse, |
| 1967 | .Float => switch (ty.floatBits(self.target.*)) { | | |
| 1968 | 32 => if (Target.x86.featureSetHas(self.target.cpu.features, .sse)) sse else gp, | | |
| 1969 | 64 => if (Target.x86.featureSetHas(self.target.cpu.features, .sse2)) sse else gp, | | |
| 1970 | else => gp, | | |
| 1971 | }, | | |
| 1972 | else => gp, | 1989 | else => gp, |
| 1973 | }; | 1990 | }; |
| 1974 | } | 1991 | } |
| ... | @@ -2111,7 +2128,7 @@ pub fn spillRegisters(self: *Self, registers: []const Register) !void { | ... | @@ -2111,7 +2128,7 @@ pub fn spillRegisters(self: *Self, registers: []const Register) !void { |
| 2111 | /// allocated. A second call to `copyToTmpRegister` may return the same register. | 2128 | /// allocated. A second call to `copyToTmpRegister` may return the same register. |
| 2112 | /// This can have a side effect of spilling instructions to the stack to free up a register. | 2129 | /// This can have a side effect of spilling instructions to the stack to free up a register. |
| 2113 | fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register { | 2130 | fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register { |
| 2114 | const reg = try self.register_manager.allocReg(null, try self.regClassForType(ty)); | 2131 | const reg = try self.register_manager.allocReg(null, regClassForType(ty)); |
| 2115 | try self.genSetReg(reg, ty, mcv); | 2132 | try self.genSetReg(reg, ty, mcv); |
| 2116 | return reg; | 2133 | return reg; |
| 2117 | } | 2134 | } |
| ... | @@ -2126,7 +2143,7 @@ fn copyToRegisterWithInstTracking( | ... | @@ -2126,7 +2143,7 @@ fn copyToRegisterWithInstTracking( |
| 2126 | ty: Type, | 2143 | ty: Type, |
| 2127 | mcv: MCValue, | 2144 | mcv: MCValue, |
| 2128 | ) !MCValue { | 2145 | ) !MCValue { |
| 2129 | const reg: Register = try self.register_manager.allocReg(reg_owner, try self.regClassForType(ty)); | 2146 | const reg: Register = try self.register_manager.allocReg(reg_owner, regClassForType(ty)); |
| 2130 | try self.genSetReg(reg, ty, mcv); | 2147 | try self.genSetReg(reg, ty, mcv); |
| 2131 | return MCValue{ .register = reg }; | 2148 | return MCValue{ .register = reg }; |
| 2132 | } | 2149 | } |
| ... | @@ -2159,8 +2176,7 @@ fn airFptrunc(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2159,8 +2176,7 @@ fn airFptrunc(self: *Self, inst: Air.Inst.Index) !void { |
| 2159 | if (dst_ty.floatBits(self.target.*) != 32 or src_ty.floatBits(self.target.*) != 64 or | 2176 | if (dst_ty.floatBits(self.target.*) != 32 or src_ty.floatBits(self.target.*) != 64 or |
| 2160 | !Target.x86.featureSetHas(self.target.cpu.features, .sse2)) | 2177 | !Target.x86.featureSetHas(self.target.cpu.features, .sse2)) |
| 2161 | return self.fail("TODO implement airFptrunc from {} to {}", .{ | 2178 | return self.fail("TODO implement airFptrunc from {} to {}", .{ |
| 2162 | src_ty.fmt(self.bin_file.options.module.?), | 2179 | src_ty.fmt(self.bin_file.options.module.?), dst_ty.fmt(self.bin_file.options.module.?), |
| 2163 | dst_ty.fmt(self.bin_file.options.module.?), | | |
| 2164 | }); | 2180 | }); |
| 2165 | | 2181 | |
| 2166 | const src_mcv = try self.resolveInst(ty_op.operand); | 2182 | const src_mcv = try self.resolveInst(ty_op.operand); |
| ... | @@ -2182,8 +2198,7 @@ fn airFpext(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2182,8 +2198,7 @@ fn airFpext(self: *Self, inst: Air.Inst.Index) !void { |
| 2182 | if (dst_ty.floatBits(self.target.*) != 64 or src_ty.floatBits(self.target.*) != 32 or | 2198 | if (dst_ty.floatBits(self.target.*) != 64 or src_ty.floatBits(self.target.*) != 32 or |
| 2183 | !Target.x86.featureSetHas(self.target.cpu.features, .sse2)) | 2199 | !Target.x86.featureSetHas(self.target.cpu.features, .sse2)) |
| 2184 | return self.fail("TODO implement airFpext from {} to {}", .{ | 2200 | return self.fail("TODO implement airFpext from {} to {}", .{ |
| 2185 | src_ty.fmt(self.bin_file.options.module.?), | 2201 | src_ty.fmt(self.bin_file.options.module.?), dst_ty.fmt(self.bin_file.options.module.?), |
| 2186 | dst_ty.fmt(self.bin_file.options.module.?), | | |
| 2187 | }); | 2202 | }); |
| 2188 | | 2203 | |
| 2189 | const src_mcv = try self.resolveInst(ty_op.operand); | 2204 | const src_mcv = try self.resolveInst(ty_op.operand); |
| ... | @@ -4436,8 +4451,8 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4436,8 +4451,8 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void { |
| 4436 | const ptr_ty = self.air.typeOf(ty_op.operand); | 4451 | const ptr_ty = self.air.typeOf(ty_op.operand); |
| 4437 | const elem_size = elem_ty.abiSize(self.target.*); | 4452 | const elem_size = elem_ty.abiSize(self.target.*); |
| 4438 | | 4453 | |
| 4439 | const elem_rc = try self.regClassForType(elem_ty); | 4454 | const elem_rc = regClassForType(elem_ty); |
| 4440 | const ptr_rc = try self.regClassForType(ptr_ty); | 4455 | const ptr_rc = regClassForType(ptr_ty); |
| 4441 | | 4456 | |
| 4442 | const ptr_mcv = try self.resolveInst(ty_op.operand); | 4457 | const ptr_mcv = try self.resolveInst(ty_op.operand); |
| 4443 | const dst_mcv = if (elem_size <= 8 and elem_rc.supersetOf(ptr_rc) and | 4458 | const dst_mcv = if (elem_size <= 8 and elem_rc.supersetOf(ptr_rc) and |
| ... | @@ -5257,8 +5272,7 @@ fn genMulDivBinOp( | ... | @@ -5257,8 +5272,7 @@ fn genMulDivBinOp( |
| 5257 | .mul, .mulwrap => dst_abi_size != src_abi_size and dst_abi_size != src_abi_size * 2, | 5272 | .mul, .mulwrap => dst_abi_size != src_abi_size and dst_abi_size != src_abi_size * 2, |
| 5258 | .div_trunc, .div_floor, .div_exact, .rem, .mod => dst_abi_size != src_abi_size, | 5273 | .div_trunc, .div_floor, .div_exact, .rem, .mod => dst_abi_size != src_abi_size, |
| 5259 | } or src_abi_size > 8) return self.fail("TODO implement genMulDivBinOp from {} to {}", .{ | 5274 | } or src_abi_size > 8) return self.fail("TODO implement genMulDivBinOp from {} to {}", .{ |
| 5260 | src_ty.fmt(self.bin_file.options.module.?), | 5275 | src_ty.fmt(self.bin_file.options.module.?), dst_ty.fmt(self.bin_file.options.module.?), |
| 5261 | dst_ty.fmt(self.bin_file.options.module.?), | | |
| 5262 | }); | 5276 | }); |
| 5263 | const ty = if (dst_abi_size <= 8) dst_ty else src_ty; | 5277 | const ty = if (dst_abi_size <= 8) dst_ty else src_ty; |
| 5264 | const abi_size = if (dst_abi_size <= 8) dst_abi_size else src_abi_size; | 5278 | const abi_size = if (dst_abi_size <= 8) dst_abi_size else src_abi_size; |
| ... | @@ -5558,7 +5572,9 @@ fn genBinOp( | ... | @@ -5558,7 +5572,9 @@ fn genBinOp( |
| 5558 | }, lhs_ty, dst_mcv, src_mcv), | 5572 | }, lhs_ty, dst_mcv, src_mcv), |
| 5559 | | 5573 | |
| 5560 | .mul => try self.genBinOpMir(switch (lhs_ty.zigTypeTag()) { | 5574 | .mul => try self.genBinOpMir(switch (lhs_ty.zigTypeTag()) { |
| 5561 | else => return self.fail("TODO implement genBinOp for {s} {}", .{ @tagName(tag), lhs_ty.fmt(self.bin_file.options.module.?) }), | 5575 | else => return self.fail("TODO implement genBinOp for {s} {}", .{ |
| | 5576 | @tagName(tag), lhs_ty.fmt(self.bin_file.options.module.?), |
| | 5577 | }), |
| 5562 | .Float => switch (lhs_ty.floatBits(self.target.*)) { | 5578 | .Float => switch (lhs_ty.floatBits(self.target.*)) { |
| 5563 | 32 => if (Target.x86.featureSetHas(self.target.cpu.features, .sse)) | 5579 | 32 => if (Target.x86.featureSetHas(self.target.cpu.features, .sse)) |
| 5564 | .mulss | 5580 | .mulss |
| ... | @@ -5761,9 +5777,13 @@ fn genBinOp( | ... | @@ -5761,9 +5777,13 @@ fn genBinOp( |
| 5761 | .max => .maxsd, | 5777 | .max => .maxsd, |
| 5762 | else => unreachable, | 5778 | else => unreachable, |
| 5763 | }, | 5779 | }, |
| 5764 | else => return self.fail("TODO implement genBinOp for {s} {}", .{ @tagName(tag), lhs_ty.fmt(self.bin_file.options.module.?) }), | 5780 | else => return self.fail("TODO implement genBinOp for {s} {}", .{ |
| | 5781 | @tagName(tag), lhs_ty.fmt(self.bin_file.options.module.?), |
| | 5782 | }), |
| 5765 | }, lhs_ty, dst_mcv, src_mcv), | 5783 | }, lhs_ty, dst_mcv, src_mcv), |
| 5766 | else => return self.fail("TODO implement genBinOp for {s} {}", .{ @tagName(tag), lhs_ty.fmt(self.bin_file.options.module.?) }), | 5784 | else => return self.fail("TODO implement genBinOp for {s} {}", .{ |
| | 5785 | @tagName(tag), lhs_ty.fmt(self.bin_file.options.module.?), |
| | 5786 | }), |
| 5767 | }, | 5787 | }, |
| 5768 | | 5788 | |
| 5769 | else => unreachable, | 5789 | else => unreachable, |
| ... | @@ -5802,8 +5822,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s | ... | @@ -5802,8 +5822,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s |
| 5802 | .Float => { | 5822 | .Float => { |
| 5803 | if (!Target.x86.featureSetHas(self.target.cpu.features, .sse)) | 5823 | if (!Target.x86.featureSetHas(self.target.cpu.features, .sse)) |
| 5804 | return self.fail("TODO genBinOpMir for {s} {} without sse", .{ | 5824 | return self.fail("TODO genBinOpMir for {s} {} without sse", .{ |
| 5805 | @tagName(mir_tag), | 5825 | @tagName(mir_tag), ty.fmt(self.bin_file.options.module.?), |
| 5806 | ty.fmt(self.bin_file.options.module.?), | | |
| 5807 | }); | 5826 | }); |
| 5808 | return self.asmRegisterRegister(mir_tag, dst_reg.to128(), src_reg.to128()); | 5827 | return self.asmRegisterRegister(mir_tag, dst_reg.to128(), src_reg.to128()); |
| 5809 | }, | 5828 | }, |
| ... | @@ -7588,10 +7607,11 @@ fn movMirTag(self: *Self, ty: Type) !Mir.Inst.Tag { | ... | @@ -7588,10 +7607,11 @@ fn movMirTag(self: *Self, ty: Type) !Mir.Inst.Tag { |
| 7588 | return switch (ty.zigTypeTag()) { | 7607 | return switch (ty.zigTypeTag()) { |
| 7589 | else => .mov, | 7608 | else => .mov, |
| 7590 | .Float => switch (ty.floatBits(self.target.*)) { | 7609 | .Float => switch (ty.floatBits(self.target.*)) { |
| 7591 | 16 => .mov, | 7610 | 16 => unreachable, // needs special handling |
| 7592 | 32 => if (Target.x86.featureSetHas(self.target.cpu.features, .sse)) .movss else .mov, | 7611 | 32 => .movss, |
| 7593 | 64 => if (Target.x86.featureSetHas(self.target.cpu.features, .sse2)) .movsd else .mov, | 7612 | 64 => .movsd, |
| 7594 | else => return self.fail("TODO movMirTag for {}", .{ | 7613 | 128 => .movaps, |
| | 7614 | else => return self.fail("TODO movMirTag from {}", .{ |
| 7595 | ty.fmt(self.bin_file.options.module.?), | 7615 | ty.fmt(self.bin_file.options.module.?), |
| 7596 | }), | 7616 | }), |
| 7597 | }, | 7617 | }, |
| ... | @@ -7700,8 +7720,17 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr | ... | @@ -7700,8 +7720,17 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr |
| 7700 | }, | 7720 | }, |
| 7701 | .register => |src_reg| if (dst_reg.id() != src_reg.id()) try self.asmRegisterRegister( | 7721 | .register => |src_reg| if (dst_reg.id() != src_reg.id()) try self.asmRegisterRegister( |
| 7702 | if ((dst_reg.class() == .floating_point) == (src_reg.class() == .floating_point)) | 7722 | if ((dst_reg.class() == .floating_point) == (src_reg.class() == .floating_point)) |
| 7703 | try self.movMirTag(ty) | 7723 | switch (ty.zigTypeTag()) { |
| | 7724 | else => .mov, |
| | 7725 | .Float, .Vector => .movaps, |
| | 7726 | } |
| 7704 | else switch (abi_size) { | 7727 | else switch (abi_size) { |
| | 7728 | 2 => return try self.asmRegisterRegisterImmediate( |
| | 7729 | if (dst_reg.class() == .floating_point) .pinsrw else .pextrw, |
| | 7730 | registerAlias(dst_reg, abi_size), |
| | 7731 | registerAlias(src_reg, abi_size), |
| | 7732 | Immediate.u(0), |
| | 7733 | ), |
| 7705 | 4 => .movd, | 7734 | 4 => .movd, |
| 7706 | 8 => .movq, | 7735 | 8 => .movq, |
| 7707 | else => return self.fail( | 7736 | else => return self.fail( |
| ... | @@ -7712,18 +7741,12 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr | ... | @@ -7712,18 +7741,12 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr |
| 7712 | registerAlias(dst_reg, abi_size), | 7741 | registerAlias(dst_reg, abi_size), |
| 7713 | registerAlias(src_reg, abi_size), | 7742 | registerAlias(src_reg, abi_size), |
| 7714 | ), | 7743 | ), |
| 7715 | .register_offset, .indirect, .load_frame, .lea_frame => try self.asmRegisterMemory( | 7744 | .register_offset, |
| 7716 | switch (src_mcv) { | 7745 | .indirect, |
| 7717 | .register_offset => |reg_off| switch (reg_off.off) { | 7746 | .load_frame, |
| 7718 | 0 => return self.genSetReg(dst_reg, ty, .{ .register = reg_off.reg }), | 7747 | .lea_frame, |
| 7719 | else => .lea, | 7748 | => { |
| 7720 | }, | 7749 | const src_mem = Memory.sib(Memory.PtrSize.fromSize(abi_size), switch (src_mcv) { |
| 7721 | .indirect, .load_frame => try self.movMirTag(ty), | | |
| 7722 | .lea_frame => .lea, | | |
| 7723 | else => unreachable, | | |
| 7724 | }, | | |
| 7725 | registerAlias(dst_reg, abi_size), | | |
| 7726 | Memory.sib(Memory.PtrSize.fromSize(abi_size), switch (src_mcv) { | | |
| 7727 | .register_offset, .indirect => |reg_off| .{ | 7750 | .register_offset, .indirect => |reg_off| .{ |
| 7728 | .base = .{ .reg = reg_off.reg }, | 7751 | .base = .{ .reg = reg_off.reg }, |
| 7729 | .disp = reg_off.off, | 7752 | .disp = reg_off.off, |
| ... | @@ -7733,20 +7756,51 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr | ... | @@ -7733,20 +7756,51 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr |
| 7733 | .disp = frame_addr.off, | 7756 | .disp = frame_addr.off, |
| 7734 | }, | 7757 | }, |
| 7735 | else => unreachable, | 7758 | else => unreachable, |
| 7736 | }), | 7759 | }); |
| 7737 | ), | 7760 | if (ty.isRuntimeFloat() and ty.floatBits(self.target.*) == 16) |
| | 7761 | try self.asmRegisterMemoryImmediate( |
| | 7762 | .pinsrw, |
| | 7763 | registerAlias(dst_reg, abi_size), |
| | 7764 | src_mem, |
| | 7765 | Immediate.u(0), |
| | 7766 | ) |
| | 7767 | else |
| | 7768 | try self.asmRegisterMemory( |
| | 7769 | switch (src_mcv) { |
| | 7770 | .register_offset => |reg_off| switch (reg_off.off) { |
| | 7771 | 0 => return self.genSetReg(dst_reg, ty, .{ .register = reg_off.reg }), |
| | 7772 | else => .lea, |
| | 7773 | }, |
| | 7774 | .indirect, .load_frame => try self.movMirTag(ty), |
| | 7775 | .lea_frame => .lea, |
| | 7776 | else => unreachable, |
| | 7777 | }, |
| | 7778 | registerAlias(dst_reg, abi_size), |
| | 7779 | src_mem, |
| | 7780 | ); |
| | 7781 | }, |
| 7738 | .memory, .load_direct, .load_got, .load_tlv => { | 7782 | .memory, .load_direct, .load_got, .load_tlv => { |
| 7739 | switch (src_mcv) { | 7783 | switch (src_mcv) { |
| 7740 | .memory => |addr| if (math.cast(i32, @bitCast(i64, addr))) |small_addr| | 7784 | .memory => |addr| if (math.cast(i32, @bitCast(i64, addr))) |small_addr| { |
| 7741 | return self.asmRegisterMemory( | 7785 | const src_mem = Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ |
| 7742 | try self.movMirTag(ty), | 7786 | .base = .{ .reg = .ds }, |
| 7743 | registerAlias(dst_reg, abi_size), | 7787 | .disp = small_addr, |
| 7744 | Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ | 7788 | }); |
| 7745 | .base = .{ .reg = .ds }, | 7789 | return if (ty.isRuntimeFloat() and ty.floatBits(self.target.*) == 16) |
| 7746 | .disp = small_addr, | 7790 | self.asmRegisterMemoryImmediate( |
| 7747 | }), | 7791 | .pinsrw, |
| 7748 | ), | 7792 | registerAlias(dst_reg, abi_size), |
| 7749 | .load_direct => |sym_index| if (try self.movMirTag(ty) == .mov) { | 7793 | src_mem, |
| | 7794 | Immediate.u(0), |
| | 7795 | ) |
| | 7796 | else |
| | 7797 | self.asmRegisterMemory( |
| | 7798 | try self.movMirTag(ty), |
| | 7799 | registerAlias(dst_reg, abi_size), |
| | 7800 | src_mem, |
| | 7801 | ); |
| | 7802 | }, |
| | 7803 | .load_direct => |sym_index| if (!ty.isRuntimeFloat()) { |
| 7750 | const atom_index = try self.owner.getSymbolIndex(self); | 7804 | const atom_index = try self.owner.getSymbolIndex(self); |
| 7751 | _ = try self.addInst(.{ | 7805 | _ = try self.addInst(.{ |
| 7752 | .tag = .mov_linker, | 7806 | .tag = .mov_linker, |
| ... | @@ -7767,11 +7821,22 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr | ... | @@ -7767,11 +7821,22 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr |
| 7767 | const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg); | 7821 | const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg); |
| 7768 | defer self.register_manager.unlockReg(addr_lock); | 7822 | defer self.register_manager.unlockReg(addr_lock); |
| 7769 | | 7823 | |
| 7770 | try self.asmRegisterMemory( | 7824 | const src_mem = Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ |
| 7771 | try self.movMirTag(ty), | 7825 | .base = .{ .reg = addr_reg }, |
| 7772 | registerAlias(dst_reg, abi_size), | 7826 | }); |
| 7773 | Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = .{ .reg = addr_reg } }), | 7827 | if (ty.isRuntimeFloat() and ty.floatBits(self.target.*) == 16) |
| 7774 | ); | 7828 | try self.asmRegisterMemoryImmediate( |
| | 7829 | .pinsrw, |
| | 7830 | registerAlias(dst_reg, abi_size), |
| | 7831 | src_mem, |
| | 7832 | Immediate.u(0), |
| | 7833 | ) |
| | 7834 | else |
| | 7835 | try self.asmRegisterMemory( |
| | 7836 | try self.movMirTag(ty), |
| | 7837 | registerAlias(dst_reg, abi_size), |
| | 7838 | src_mem, |
| | 7839 | ); |
| 7775 | }, | 7840 | }, |
| 7776 | .lea_direct, .lea_got => |sym_index| { | 7841 | .lea_direct, .lea_got => |sym_index| { |
| 7777 | const atom_index = try self.owner.getSymbolIndex(self); | 7842 | const atom_index = try self.owner.getSymbolIndex(self); |
| ... | @@ -7864,11 +7929,25 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal | ... | @@ -7864,11 +7929,25 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal |
| 7864 | }, | 7929 | }, |
| 7865 | }, | 7930 | }, |
| 7866 | .eflags => |cc| try self.asmSetccMemory(Memory.sib(.byte, .{ .base = base, .disp = disp }), cc), | 7931 | .eflags => |cc| try self.asmSetccMemory(Memory.sib(.byte, .{ .base = base, .disp = disp }), cc), |
| 7867 | .register => |reg| try self.asmMemoryRegister( | 7932 | .register => |src_reg| { |
| 7868 | try self.movMirTag(ty), | 7933 | const dst_mem = Memory.sib( |
| 7869 | Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = base, .disp = disp }), | 7934 | Memory.PtrSize.fromSize(abi_size), |
| 7870 | registerAlias(reg, abi_size), | 7935 | .{ .base = base, .disp = disp }, |
| 7871 | ), | 7936 | ); |
| | 7937 | if (ty.isRuntimeFloat() and ty.floatBits(self.target.*) == 16) |
| | 7938 | try self.asmMemoryRegisterImmediate( |
| | 7939 | .pextrw, |
| | 7940 | dst_mem, |
| | 7941 | registerAlias(src_reg, abi_size), |
| | 7942 | Immediate.u(0), |
| | 7943 | ) |
| | 7944 | else |
| | 7945 | try self.asmMemoryRegister( |
| | 7946 | try self.movMirTag(ty), |
| | 7947 | dst_mem, |
| | 7948 | registerAlias(src_reg, abi_size), |
| | 7949 | ); |
| | 7950 | }, |
| 7872 | .register_overflow => |ro| { | 7951 | .register_overflow => |ro| { |
| 7873 | try self.genSetMem( | 7952 | try self.genSetMem( |
| 7874 | base, | 7953 | base, |
| ... | @@ -8071,8 +8150,8 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -8071,8 +8150,8 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void { |
| 8071 | const src_ty = self.air.typeOf(ty_op.operand); | 8150 | const src_ty = self.air.typeOf(ty_op.operand); |
| 8072 | | 8151 | |
| 8073 | const result = result: { | 8152 | const result = result: { |
| 8074 | const dst_rc = try self.regClassForType(dst_ty); | 8153 | const dst_rc = regClassForType(dst_ty); |
| 8075 | const src_rc = try self.regClassForType(src_ty); | 8154 | const src_rc = regClassForType(src_ty); |
| 8076 | const operand = try self.resolveInst(ty_op.operand); | 8155 | const operand = try self.resolveInst(ty_op.operand); |
| 8077 | if (dst_rc.supersetOf(src_rc) and self.reuseOperand(inst, ty_op.operand, 0, operand)) | 8156 | if (dst_rc.supersetOf(src_rc) and self.reuseOperand(inst, ty_op.operand, 0, operand)) |
| 8078 | break :result operand; | 8157 | break :result operand; |
| ... | @@ -8127,8 +8206,7 @@ fn airIntToFloat(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -8127,8 +8206,7 @@ fn airIntToFloat(self: *Self, inst: Air.Inst.Index) !void { |
| 8127 | .unsigned => src_bits + 1, | 8206 | .unsigned => src_bits + 1, |
| 8128 | }, 32), 8) catch unreachable; | 8207 | }, 32), 8) catch unreachable; |
| 8129 | if (src_size > 8) return self.fail("TODO implement airIntToFloat from {} to {}", .{ | 8208 | if (src_size > 8) return self.fail("TODO implement airIntToFloat from {} to {}", .{ |
| 8130 | src_ty.fmt(self.bin_file.options.module.?), | 8209 | src_ty.fmt(self.bin_file.options.module.?), dst_ty.fmt(self.bin_file.options.module.?), |
| 8131 | dst_ty.fmt(self.bin_file.options.module.?), | | |
| 8132 | }); | 8210 | }); |
| 8133 | | 8211 | |
| 8134 | const src_mcv = try self.resolveInst(ty_op.operand); | 8212 | const src_mcv = try self.resolveInst(ty_op.operand); |
| ... | @@ -8141,7 +8219,7 @@ fn airIntToFloat(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -8141,7 +8219,7 @@ fn airIntToFloat(self: *Self, inst: Air.Inst.Index) !void { |
| 8141 | | 8219 | |
| 8142 | if (src_bits < src_size * 8) try self.truncateRegister(src_ty, src_reg); | 8220 | if (src_bits < src_size * 8) try self.truncateRegister(src_ty, src_reg); |
| 8143 | | 8221 | |
| 8144 | const dst_reg = try self.register_manager.allocReg(inst, try self.regClassForType(dst_ty)); | 8222 | const dst_reg = try self.register_manager.allocReg(inst, regClassForType(dst_ty)); |
| 8145 | const dst_mcv = MCValue{ .register = dst_reg }; | 8223 | const dst_mcv = MCValue{ .register = dst_reg }; |
| 8146 | const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg); | 8224 | const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg); |
| 8147 | defer self.register_manager.unlockReg(dst_lock); | 8225 | defer self.register_manager.unlockReg(dst_lock); |
| ... | @@ -8151,19 +8229,16 @@ fn airIntToFloat(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -8151,19 +8229,16 @@ fn airIntToFloat(self: *Self, inst: Air.Inst.Index) !void { |
| 8151 | .cvtsi2ss | 8229 | .cvtsi2ss |
| 8152 | else | 8230 | else |
| 8153 | return self.fail("TODO implement airIntToFloat from {} to {} without sse", .{ | 8231 | return self.fail("TODO implement airIntToFloat from {} to {} without sse", .{ |
| 8154 | src_ty.fmt(self.bin_file.options.module.?), | 8232 | src_ty.fmt(self.bin_file.options.module.?), dst_ty.fmt(self.bin_file.options.module.?), |
| 8155 | dst_ty.fmt(self.bin_file.options.module.?), | | |
| 8156 | }), | 8233 | }), |
| 8157 | 64 => if (Target.x86.featureSetHas(self.target.cpu.features, .sse2)) | 8234 | 64 => if (Target.x86.featureSetHas(self.target.cpu.features, .sse2)) |
| 8158 | .cvtsi2sd | 8235 | .cvtsi2sd |
| 8159 | else | 8236 | else |
| 8160 | return self.fail("TODO implement airIntToFloat from {} to {} without sse2", .{ | 8237 | return self.fail("TODO implement airIntToFloat from {} to {} without sse2", .{ |
| 8161 | src_ty.fmt(self.bin_file.options.module.?), | 8238 | src_ty.fmt(self.bin_file.options.module.?), dst_ty.fmt(self.bin_file.options.module.?), |
| 8162 | dst_ty.fmt(self.bin_file.options.module.?), | | |
| 8163 | }), | 8239 | }), |
| 8164 | else => return self.fail("TODO implement airIntToFloat from {} to {}", .{ | 8240 | else => return self.fail("TODO implement airIntToFloat from {} to {}", .{ |
| 8165 | src_ty.fmt(self.bin_file.options.module.?), | 8241 | src_ty.fmt(self.bin_file.options.module.?), dst_ty.fmt(self.bin_file.options.module.?), |
| 8166 | dst_ty.fmt(self.bin_file.options.module.?), | | |
| 8167 | }), | 8242 | }), |
| 8168 | }, dst_reg.to128(), registerAlias(src_reg, src_size)); | 8243 | }, dst_reg.to128(), registerAlias(src_reg, src_size)); |
| 8169 | | 8244 | |