| ... | @@ -2745,11 +2745,11 @@ fn airFptrunc(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2745,11 +2745,11 @@ fn airFptrunc(self: *Self, inst: Air.Inst.Index) !void { |
| 2745 | }, | 2745 | }, |
| 2746 | else => unreachable, | 2746 | else => unreachable, |
| 2747 | }) { | 2747 | }) { |
| 2748 | var callee: ["__trunc?f?f2".len]u8 = undefined; | 2748 | var callee_buf: ["__trunc?f?f2".len]u8 = undefined; |
| 2749 | break :result try self.genCall(.{ .lib = .{ | 2749 | break :result try self.genCall(.{ .lib = .{ |
| 2750 | .return_type = self.floatCompilerRtAbiType(dst_ty, src_ty).toIntern(), | 2750 | .return_type = self.floatCompilerRtAbiType(dst_ty, src_ty).toIntern(), |
| 2751 | .param_types = &.{self.floatCompilerRtAbiType(src_ty, dst_ty).toIntern()}, | 2751 | .param_types = &.{self.floatCompilerRtAbiType(src_ty, dst_ty).toIntern()}, |
| 2752 | .callee = std.fmt.bufPrint(&callee, "__trunc{c}f{c}f2", .{ | 2752 | .callee = std.fmt.bufPrint(&callee_buf, "__trunc{c}f{c}f2", .{ |
| 2753 | floatCompilerRtAbiName(src_bits), | 2753 | floatCompilerRtAbiName(src_bits), |
| 2754 | floatCompilerRtAbiName(dst_bits), | 2754 | floatCompilerRtAbiName(dst_bits), |
| 2755 | }) catch unreachable, | 2755 | }) catch unreachable, |
| ... | @@ -2777,7 +2777,7 @@ fn airFptrunc(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2777,7 +2777,7 @@ fn airFptrunc(self: *Self, inst: Air.Inst.Index) !void { |
| 2777 | .{ .v_, .cvtps2ph }, | 2777 | .{ .v_, .cvtps2ph }, |
| 2778 | dst_reg, | 2778 | dst_reg, |
| 2779 | mat_src_reg.to128(), | 2779 | mat_src_reg.to128(), |
| 2780 | Immediate.u(0b1_00), | 2780 | Immediate.u(@as(u5, @bitCast(RoundMode{ .mode = .mxcsr }))), |
| 2781 | ); | 2781 | ); |
| 2782 | }, | 2782 | }, |
| 2783 | else => unreachable, | 2783 | else => unreachable, |
| ... | @@ -2844,11 +2844,11 @@ fn airFpext(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2844,11 +2844,11 @@ fn airFpext(self: *Self, inst: Air.Inst.Index) !void { |
| 2844 | }, | 2844 | }, |
| 2845 | else => unreachable, | 2845 | else => unreachable, |
| 2846 | }) { | 2846 | }) { |
| 2847 | var callee: ["__extend?f?f2".len]u8 = undefined; | 2847 | var callee_buf: ["__extend?f?f2".len]u8 = undefined; |
| 2848 | break :result try self.genCall(.{ .lib = .{ | 2848 | break :result try self.genCall(.{ .lib = .{ |
| 2849 | .return_type = self.floatCompilerRtAbiType(dst_ty, src_ty).toIntern(), | 2849 | .return_type = self.floatCompilerRtAbiType(dst_ty, src_ty).toIntern(), |
| 2850 | .param_types = &.{self.floatCompilerRtAbiType(src_ty, dst_ty).toIntern()}, | 2850 | .param_types = &.{self.floatCompilerRtAbiType(src_ty, dst_ty).toIntern()}, |
| 2851 | .callee = std.fmt.bufPrint(&callee, "__extend{c}f{c}f2", .{ | 2851 | .callee = std.fmt.bufPrint(&callee_buf, "__extend{c}f{c}f2", .{ |
| 2852 | floatCompilerRtAbiName(src_bits), | 2852 | floatCompilerRtAbiName(src_bits), |
| 2853 | floatCompilerRtAbiName(dst_bits), | 2853 | floatCompilerRtAbiName(dst_bits), |
| 2854 | }) catch unreachable, | 2854 | }) catch unreachable, |
| ... | @@ -5347,7 +5347,7 @@ const RoundMode = packed struct(u5) { | ... | @@ -5347,7 +5347,7 @@ const RoundMode = packed struct(u5) { |
| 5347 | precision: enum(u1) { | 5347 | precision: enum(u1) { |
| 5348 | normal = 0b0, | 5348 | normal = 0b0, |
| 5349 | inexact = 0b1, | 5349 | inexact = 0b1, |
| 5350 | }, | 5350 | } = .normal, |
| 5351 | }; | 5351 | }; |
| 5352 | | 5352 | |
| 5353 | fn airRound(self: *Self, inst: Air.Inst.Index, mode: RoundMode) !void { | 5353 | fn airRound(self: *Self, inst: Air.Inst.Index, mode: RoundMode) !void { |
| ... | @@ -5413,11 +5413,11 @@ fn genRoundLibcall(self: *Self, ty: Type, src_mcv: MCValue, mode: RoundMode) !MC | ... | @@ -5413,11 +5413,11 @@ fn genRoundLibcall(self: *Self, ty: Type, src_mcv: MCValue, mode: RoundMode) !MC |
| 5413 | if (ty.zigTypeTag(mod) != .Float) | 5413 | if (ty.zigTypeTag(mod) != .Float) |
| 5414 | return self.fail("TODO implement genRound for {}", .{ty.fmt(mod)}); | 5414 | return self.fail("TODO implement genRound for {}", .{ty.fmt(mod)}); |
| 5415 | | 5415 | |
| 5416 | var callee: ["__trunc?".len]u8 = undefined; | 5416 | var callee_buf: ["__trunc?".len]u8 = undefined; |
| 5417 | return try self.genCall(.{ .lib = .{ | 5417 | return try self.genCall(.{ .lib = .{ |
| 5418 | .return_type = ty.toIntern(), | 5418 | .return_type = ty.toIntern(), |
| 5419 | .param_types = &.{ty.toIntern()}, | 5419 | .param_types = &.{ty.toIntern()}, |
| 5420 | .callee = std.fmt.bufPrint(&callee, "{s}{s}{s}", .{ | 5420 | .callee = std.fmt.bufPrint(&callee_buf, "{s}{s}{s}", .{ |
| 5421 | floatLibcAbiPrefix(ty), | 5421 | floatLibcAbiPrefix(ty), |
| 5422 | switch (mode.mode) { | 5422 | switch (mode.mode) { |
| 5423 | .down => "floor", | 5423 | .down => "floor", |
| ... | @@ -5628,11 +5628,11 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -5628,11 +5628,11 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void { |
| 5628 | 80, 128 => true, | 5628 | 80, 128 => true, |
| 5629 | else => unreachable, | 5629 | else => unreachable, |
| 5630 | }) { | 5630 | }) { |
| 5631 | var callee: ["__sqrt?".len]u8 = undefined; | 5631 | var callee_buf: ["__sqrt?".len]u8 = undefined; |
| 5632 | break :result try self.genCall(.{ .lib = .{ | 5632 | break :result try self.genCall(.{ .lib = .{ |
| 5633 | .return_type = ty.toIntern(), | 5633 | .return_type = ty.toIntern(), |
| 5634 | .param_types = &.{ty.toIntern()}, | 5634 | .param_types = &.{ty.toIntern()}, |
| 5635 | .callee = std.fmt.bufPrint(&callee, "{s}sqrt{s}", .{ | 5635 | .callee = std.fmt.bufPrint(&callee_buf, "{s}sqrt{s}", .{ |
| 5636 | floatLibcAbiPrefix(ty), | 5636 | floatLibcAbiPrefix(ty), |
| 5637 | floatLibcAbiSuffix(ty), | 5637 | floatLibcAbiSuffix(ty), |
| 5638 | }) catch unreachable, | 5638 | }) catch unreachable, |
| ... | @@ -5665,7 +5665,7 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -5665,7 +5665,7 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void { |
| 5665 | .{ .v_, .cvtps2ph }, | 5665 | .{ .v_, .cvtps2ph }, |
| 5666 | dst_reg, | 5666 | dst_reg, |
| 5667 | dst_reg, | 5667 | dst_reg, |
| 5668 | Immediate.u(0b1_00), | 5668 | Immediate.u(@as(u5, @bitCast(RoundMode{ .mode = .mxcsr }))), |
| 5669 | ); | 5669 | ); |
| 5670 | break :result dst_mcv; | 5670 | break :result dst_mcv; |
| 5671 | }, | 5671 | }, |
| ... | @@ -5695,7 +5695,7 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -5695,7 +5695,7 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void { |
| 5695 | .{ .v_, .cvtps2ph }, | 5695 | .{ .v_, .cvtps2ph }, |
| 5696 | dst_reg, | 5696 | dst_reg, |
| 5697 | dst_reg, | 5697 | dst_reg, |
| 5698 | Immediate.u(0b1_00), | 5698 | Immediate.u(@as(u5, @bitCast(RoundMode{ .mode = .mxcsr }))), |
| 5699 | ); | 5699 | ); |
| 5700 | break :result dst_mcv; | 5700 | break :result dst_mcv; |
| 5701 | }, | 5701 | }, |
| ... | @@ -5720,7 +5720,7 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -5720,7 +5720,7 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void { |
| 5720 | .{ .v_, .cvtps2ph }, | 5720 | .{ .v_, .cvtps2ph }, |
| 5721 | dst_reg, | 5721 | dst_reg, |
| 5722 | wide_reg, | 5722 | wide_reg, |
| 5723 | Immediate.u(0b1_00), | 5723 | Immediate.u(@as(u5, @bitCast(RoundMode{ .mode = .mxcsr }))), |
| 5724 | ); | 5724 | ); |
| 5725 | break :result dst_mcv; | 5725 | break :result dst_mcv; |
| 5726 | }, | 5726 | }, |
| ... | @@ -5783,11 +5783,11 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -5783,11 +5783,11 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void { |
| 5783 | fn airUnaryMath(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void { | 5783 | fn airUnaryMath(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void { |
| 5784 | const un_op = self.air.instructions.items(.data)[inst].un_op; | 5784 | const un_op = self.air.instructions.items(.data)[inst].un_op; |
| 5785 | const ty = self.typeOf(un_op); | 5785 | const ty = self.typeOf(un_op); |
| 5786 | var callee: ["__round?".len]u8 = undefined; | 5786 | var callee_buf: ["__round?".len]u8 = undefined; |
| 5787 | const result = try self.genCall(.{ .lib = .{ | 5787 | const result = try self.genCall(.{ .lib = .{ |
| 5788 | .return_type = ty.toIntern(), | 5788 | .return_type = ty.toIntern(), |
| 5789 | .param_types = &.{ty.toIntern()}, | 5789 | .param_types = &.{ty.toIntern()}, |
| 5790 | .callee = std.fmt.bufPrint(&callee, "{s}{s}{s}", .{ | 5790 | .callee = std.fmt.bufPrint(&callee_buf, "{s}{s}{s}", .{ |
| 5791 | floatLibcAbiPrefix(ty), | 5791 | floatLibcAbiPrefix(ty), |
| 5792 | switch (tag) { | 5792 | switch (tag) { |
| 5793 | .sin, | 5793 | .sin, |
| ... | @@ -6978,11 +6978,11 @@ fn genMulDivBinOp( | ... | @@ -6978,11 +6978,11 @@ fn genMulDivBinOp( |
| 6978 | ), | 6978 | ), |
| 6979 | else => {}, | 6979 | else => {}, |
| 6980 | }; | 6980 | }; |
| 6981 | var callee: ["__udiv?i3".len]u8 = undefined; | 6981 | var callee_buf: ["__udiv?i3".len]u8 = undefined; |
| 6982 | return try self.genCall(.{ .lib = .{ | 6982 | return try self.genCall(.{ .lib = .{ |
| 6983 | .return_type = dst_ty.toIntern(), | 6983 | .return_type = dst_ty.toIntern(), |
| 6984 | .param_types = &.{ src_ty.toIntern(), src_ty.toIntern() }, | 6984 | .param_types = &.{ src_ty.toIntern(), src_ty.toIntern() }, |
| 6985 | .callee = std.fmt.bufPrint(&callee, "__{s}{s}{c}i3", .{ | 6985 | .callee = std.fmt.bufPrint(&callee_buf, "__{s}{s}{c}i3", .{ |
| 6986 | if (signed) "" else "u", | 6986 | if (signed) "" else "u", |
| 6987 | switch (tag) { | 6987 | switch (tag) { |
| 6988 | .div_trunc, .div_exact => "div", | 6988 | .div_trunc, .div_exact => "div", |
| ... | @@ -7205,43 +7205,163 @@ fn genBinOp( | ... | @@ -7205,43 +7205,163 @@ fn genBinOp( |
| 7205 | const rhs_ty = self.typeOf(rhs_air); | 7205 | const rhs_ty = self.typeOf(rhs_air); |
| 7206 | const abi_size: u32 = @intCast(lhs_ty.abiSize(mod)); | 7206 | const abi_size: u32 = @intCast(lhs_ty.abiSize(mod)); |
| 7207 | | 7207 | |
| 7208 | if (lhs_ty.isRuntimeFloat() and (air_tag == .rem or switch (lhs_ty.floatBits(self.target.*)) { | 7208 | if (lhs_ty.isRuntimeFloat()) libcall: { |
| 7209 | 16 => !self.hasFeature(.f16c), | 7209 | const float_bits = lhs_ty.floatBits(self.target.*); |
| 7210 | 32, 64 => false, | 7210 | const type_needs_libcall = switch (float_bits) { |
| 7211 | 80, 128 => true, | 7211 | 16 => !self.hasFeature(.f16c), |
| 7212 | else => unreachable, | 7212 | 32, 64 => false, |
| 7213 | })) { | 7213 | 80, 128 => true, |
| 7214 | var callee: ["__mod?f3".len]u8 = undefined; | 7214 | else => unreachable, |
| | 7215 | }; |
| | 7216 | switch (air_tag) { |
| | 7217 | .rem, .mod => {}, |
| | 7218 | else => if (!type_needs_libcall) break :libcall, |
| | 7219 | } |
| | 7220 | var callee_buf: ["__mod?f3".len]u8 = undefined; |
| | 7221 | const callee = switch (air_tag) { |
| | 7222 | .add, |
| | 7223 | .sub, |
| | 7224 | .mul, |
| | 7225 | .div_float, |
| | 7226 | .div_trunc, |
| | 7227 | .div_floor, |
| | 7228 | => std.fmt.bufPrint(&callee_buf, "__{s}{c}f3", .{ |
| | 7229 | @tagName(air_tag)[0..3], |
| | 7230 | floatCompilerRtAbiName(float_bits), |
| | 7231 | }), |
| | 7232 | .rem, .mod, .min, .max => std.fmt.bufPrint(&callee_buf, "{s}f{s}{s}", .{ |
| | 7233 | floatLibcAbiPrefix(lhs_ty), |
| | 7234 | switch (air_tag) { |
| | 7235 | .rem, .mod => "mod", |
| | 7236 | .min => "min", |
| | 7237 | .max => "max", |
| | 7238 | else => unreachable, |
| | 7239 | }, |
| | 7240 | floatLibcAbiSuffix(lhs_ty), |
| | 7241 | }), |
| | 7242 | else => return self.fail("TODO implement genBinOp for {s} {}", .{ |
| | 7243 | @tagName(air_tag), lhs_ty.fmt(mod), |
| | 7244 | }), |
| | 7245 | } catch unreachable; |
| 7215 | const result = try self.genCall(.{ .lib = .{ | 7246 | const result = try self.genCall(.{ .lib = .{ |
| 7216 | .return_type = lhs_ty.toIntern(), | 7247 | .return_type = lhs_ty.toIntern(), |
| 7217 | .param_types = &.{ lhs_ty.toIntern(), rhs_ty.toIntern() }, | 7248 | .param_types = &.{ lhs_ty.toIntern(), rhs_ty.toIntern() }, |
| 7218 | .callee = switch (air_tag) { | 7249 | .callee = callee, |
| 7219 | .add, | | |
| 7220 | .sub, | | |
| 7221 | .mul, | | |
| 7222 | .div_float, | | |
| 7223 | .div_trunc, | | |
| 7224 | .div_floor, | | |
| 7225 | => std.fmt.bufPrint(&callee, "__{s}{c}f3", .{ | | |
| 7226 | @tagName(air_tag)[0..3], | | |
| 7227 | floatCompilerRtAbiName(lhs_ty.floatBits(self.target.*)), | | |
| 7228 | }), | | |
| 7229 | .rem, .min, .max => std.fmt.bufPrint(&callee, "{s}f{s}{s}", .{ | | |
| 7230 | floatLibcAbiPrefix(lhs_ty), | | |
| 7231 | switch (air_tag) { | | |
| 7232 | .rem => "mod", | | |
| 7233 | .min => "min", | | |
| 7234 | .max => "max", | | |
| 7235 | else => unreachable, | | |
| 7236 | }, | | |
| 7237 | floatLibcAbiSuffix(lhs_ty), | | |
| 7238 | }), | | |
| 7239 | else => return self.fail("TODO implement genBinOp for {s} {}", .{ | | |
| 7240 | @tagName(air_tag), lhs_ty.fmt(mod), | | |
| 7241 | }), | | |
| 7242 | } catch unreachable, | | |
| 7243 | } }, &.{ lhs_ty, rhs_ty }, &.{ .{ .air_ref = lhs_air }, .{ .air_ref = rhs_air } }); | 7250 | } }, &.{ lhs_ty, rhs_ty }, &.{ .{ .air_ref = lhs_air }, .{ .air_ref = rhs_air } }); |
| 7244 | return switch (air_tag) { | 7251 | return switch (air_tag) { |
| | 7252 | .mod => result: { |
| | 7253 | const adjusted: MCValue = if (type_needs_libcall) adjusted: { |
| | 7254 | var add_callee_buf: ["__add?f3".len]u8 = undefined; |
| | 7255 | break :adjusted try self.genCall(.{ .lib = .{ |
| | 7256 | .return_type = lhs_ty.toIntern(), |
| | 7257 | .param_types = &.{ |
| | 7258 | lhs_ty.toIntern(), |
| | 7259 | rhs_ty.toIntern(), |
| | 7260 | }, |
| | 7261 | .callee = std.fmt.bufPrint(&add_callee_buf, "__add{c}f3", .{ |
| | 7262 | floatCompilerRtAbiName(float_bits), |
| | 7263 | }) catch unreachable, |
| | 7264 | } }, &.{ lhs_ty, rhs_ty }, &.{ result, .{ .air_ref = rhs_air } }); |
| | 7265 | } else switch (float_bits) { |
| | 7266 | 16, 32, 64 => adjusted: { |
| | 7267 | const dst_reg = switch (result) { |
| | 7268 | .register => |reg| reg, |
| | 7269 | else => if (maybe_inst) |inst| |
| | 7270 | (try self.copyToRegisterWithInstTracking(inst, lhs_ty, result)).register |
| | 7271 | else |
| | 7272 | try self.copyToTmpRegister(lhs_ty, result), |
| | 7273 | }; |
| | 7274 | const dst_lock = self.register_manager.lockReg(dst_reg); |
| | 7275 | defer if (dst_lock) |lock| self.register_manager.unlockReg(lock); |
| | 7276 | |
| | 7277 | const rhs_mcv = try self.resolveInst(rhs_air); |
| | 7278 | const src_mcv: MCValue = if (float_bits == 16) src: { |
| | 7279 | assert(self.hasFeature(.f16c)); |
| | 7280 | const tmp_reg = (try self.register_manager.allocReg( |
| | 7281 | null, |
| | 7282 | abi.RegisterClass.sse, |
| | 7283 | )).to128(); |
| | 7284 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); |
| | 7285 | defer self.register_manager.unlockReg(tmp_lock); |
| | 7286 | |
| | 7287 | if (rhs_mcv.isMemory()) try self.asmRegisterRegisterMemoryImmediate( |
| | 7288 | .{ .vp_w, .insr }, |
| | 7289 | dst_reg, |
| | 7290 | dst_reg, |
| | 7291 | rhs_mcv.mem(.word), |
| | 7292 | Immediate.u(1), |
| | 7293 | ) else try self.asmRegisterRegisterRegister( |
| | 7294 | .{ .vp_, .unpcklwd }, |
| | 7295 | dst_reg, |
| | 7296 | dst_reg, |
| | 7297 | (if (rhs_mcv.isRegister()) |
| | 7298 | rhs_mcv.getReg().? |
| | 7299 | else |
| | 7300 | try self.copyToTmpRegister(rhs_ty, rhs_mcv)).to128(), |
| | 7301 | ); |
| | 7302 | try self.asmRegisterRegister(.{ .v_ps, .cvtph2 }, dst_reg, dst_reg); |
| | 7303 | break :src .{ .register = tmp_reg }; |
| | 7304 | } else rhs_mcv; |
| | 7305 | |
| | 7306 | if (self.hasFeature(.avx)) { |
| | 7307 | const mir_tag: Mir.Inst.FixedTag = switch (float_bits) { |
| | 7308 | 16, 32 => .{ .v_ss, .add }, |
| | 7309 | 64 => .{ .v_sd, .add }, |
| | 7310 | else => unreachable, |
| | 7311 | }; |
| | 7312 | if (src_mcv.isMemory()) try self.asmRegisterRegisterMemory( |
| | 7313 | mir_tag, |
| | 7314 | dst_reg, |
| | 7315 | dst_reg, |
| | 7316 | src_mcv.mem(Memory.PtrSize.fromBitSize(float_bits)), |
| | 7317 | ) else try self.asmRegisterRegisterRegister( |
| | 7318 | mir_tag, |
| | 7319 | dst_reg, |
| | 7320 | dst_reg, |
| | 7321 | (if (src_mcv.isRegister()) |
| | 7322 | src_mcv.getReg().? |
| | 7323 | else |
| | 7324 | try self.copyToTmpRegister(rhs_ty, src_mcv)).to128(), |
| | 7325 | ); |
| | 7326 | } else { |
| | 7327 | const mir_tag: Mir.Inst.FixedTag = switch (float_bits) { |
| | 7328 | 32 => .{ ._ss, .add }, |
| | 7329 | 64 => .{ ._sd, .add }, |
| | 7330 | else => unreachable, |
| | 7331 | }; |
| | 7332 | if (src_mcv.isMemory()) try self.asmRegisterMemory( |
| | 7333 | mir_tag, |
| | 7334 | dst_reg, |
| | 7335 | src_mcv.mem(Memory.PtrSize.fromBitSize(float_bits)), |
| | 7336 | ) else try self.asmRegisterRegister( |
| | 7337 | mir_tag, |
| | 7338 | dst_reg, |
| | 7339 | (if (src_mcv.isRegister()) |
| | 7340 | src_mcv.getReg().? |
| | 7341 | else |
| | 7342 | try self.copyToTmpRegister(rhs_ty, src_mcv)).to128(), |
| | 7343 | ); |
| | 7344 | } |
| | 7345 | |
| | 7346 | if (float_bits == 16) try self.asmRegisterRegisterImmediate( |
| | 7347 | .{ .v_, .cvtps2ph }, |
| | 7348 | dst_reg, |
| | 7349 | dst_reg, |
| | 7350 | Immediate.u(@as(u5, @bitCast(RoundMode{ .mode = .mxcsr }))), |
| | 7351 | ); |
| | 7352 | break :adjusted .{ .register = dst_reg }; |
| | 7353 | }, |
| | 7354 | 80, 128 => return self.fail("TODO implement genBinOp for {s} of {}", .{ |
| | 7355 | @tagName(air_tag), lhs_ty.fmt(mod), |
| | 7356 | }), |
| | 7357 | else => unreachable, |
| | 7358 | }; |
| | 7359 | break :result try self.genCall(.{ .lib = .{ |
| | 7360 | .return_type = lhs_ty.toIntern(), |
| | 7361 | .param_types = &.{ lhs_ty.toIntern(), rhs_ty.toIntern() }, |
| | 7362 | .callee = callee, |
| | 7363 | } }, &.{ lhs_ty, rhs_ty }, &.{ adjusted, .{ .air_ref = rhs_air } }); |
| | 7364 | }, |
| 7245 | .div_trunc, .div_floor => try self.genRoundLibcall(lhs_ty, result, .{ | 7365 | .div_trunc, .div_floor => try self.genRoundLibcall(lhs_ty, result, .{ |
| 7246 | .mode = switch (air_tag) { | 7366 | .mode = switch (air_tag) { |
| 7247 | .div_trunc => .zero, | 7367 | .div_trunc => .zero, |
| ... | @@ -7263,6 +7383,7 @@ fn genBinOp( | ... | @@ -7263,6 +7383,7 @@ fn genBinOp( |
| 7263 | | 7383 | |
| 7264 | const maybe_mask_reg = switch (air_tag) { | 7384 | const maybe_mask_reg = switch (air_tag) { |
| 7265 | else => null, | 7385 | else => null, |
| | 7386 | .rem, .mod => unreachable, |
| 7266 | .max, .min => if (lhs_ty.scalarType(mod).isRuntimeFloat()) registerAlias( | 7387 | .max, .min => if (lhs_ty.scalarType(mod).isRuntimeFloat()) registerAlias( |
| 7267 | if (!self.hasFeature(.avx) and self.hasFeature(.sse4_1)) mask: { | 7388 | if (!self.hasFeature(.avx) and self.hasFeature(.sse4_1)) mask: { |
| 7268 | try self.register_manager.getReg(.xmm0, null); | 7389 | try self.register_manager.getReg(.xmm0, null); |
| ... | @@ -7270,9 +7391,6 @@ fn genBinOp( | ... | @@ -7270,9 +7391,6 @@ fn genBinOp( |
| 7270 | } else try self.register_manager.allocReg(null, abi.RegisterClass.sse), | 7391 | } else try self.register_manager.allocReg(null, abi.RegisterClass.sse), |
| 7271 | abi_size, | 7392 | abi_size, |
| 7272 | ) else null, | 7393 | ) else null, |
| 7273 | .rem, .mod => return self.fail("TODO implement genBinOp for {s} {}", .{ | | |
| 7274 | @tagName(air_tag), lhs_ty.fmt(mod), | | |
| 7275 | }), | | |
| 7276 | }; | 7394 | }; |
| 7277 | const mask_lock = | 7395 | const mask_lock = |
| 7278 | if (maybe_mask_reg) |mask_reg| self.register_manager.lockRegAssumeUnused(mask_reg) else null; | 7396 | if (maybe_mask_reg) |mask_reg| self.register_manager.lockRegAssumeUnused(mask_reg) else null; |
| ... | @@ -7667,7 +7785,7 @@ fn genBinOp( | ... | @@ -7667,7 +7785,7 @@ fn genBinOp( |
| 7667 | .{ .v_, .cvtps2ph }, | 7785 | .{ .v_, .cvtps2ph }, |
| 7668 | dst_reg, | 7786 | dst_reg, |
| 7669 | dst_reg, | 7787 | dst_reg, |
| 7670 | Immediate.u(0b1_00), | 7788 | Immediate.u(@as(u5, @bitCast(RoundMode{ .mode = .mxcsr }))), |
| 7671 | ); | 7789 | ); |
| 7672 | return dst_mcv; | 7790 | return dst_mcv; |
| 7673 | }, | 7791 | }, |
| ... | @@ -8096,7 +8214,7 @@ fn genBinOp( | ... | @@ -8096,7 +8214,7 @@ fn genBinOp( |
| 8096 | .{ .v_, .cvtps2ph }, | 8214 | .{ .v_, .cvtps2ph }, |
| 8097 | dst_reg, | 8215 | dst_reg, |
| 8098 | dst_reg, | 8216 | dst_reg, |
| 8099 | Immediate.u(0b1_00), | 8217 | Immediate.u(@as(u5, @bitCast(RoundMode{ .mode = .mxcsr }))), |
| 8100 | ); | 8218 | ); |
| 8101 | return dst_mcv; | 8219 | return dst_mcv; |
| 8102 | }, | 8220 | }, |
| ... | @@ -8147,7 +8265,7 @@ fn genBinOp( | ... | @@ -8147,7 +8265,7 @@ fn genBinOp( |
| 8147 | .{ .v_, .cvtps2ph }, | 8265 | .{ .v_, .cvtps2ph }, |
| 8148 | dst_reg, | 8266 | dst_reg, |
| 8149 | dst_reg, | 8267 | dst_reg, |
| 8150 | Immediate.u(0b1_00), | 8268 | Immediate.u(@as(u5, @bitCast(RoundMode{ .mode = .mxcsr }))), |
| 8151 | ); | 8269 | ); |
| 8152 | return dst_mcv; | 8270 | return dst_mcv; |
| 8153 | }, | 8271 | }, |
| ... | @@ -8190,7 +8308,7 @@ fn genBinOp( | ... | @@ -8190,7 +8308,7 @@ fn genBinOp( |
| 8190 | .{ .v_, .cvtps2ph }, | 8308 | .{ .v_, .cvtps2ph }, |
| 8191 | dst_reg, | 8309 | dst_reg, |
| 8192 | dst_reg, | 8310 | dst_reg, |
| 8193 | Immediate.u(0b1_00), | 8311 | Immediate.u(@as(u5, @bitCast(RoundMode{ .mode = .mxcsr }))), |
| 8194 | ); | 8312 | ); |
| 8195 | return dst_mcv; | 8313 | return dst_mcv; |
| 8196 | }, | 8314 | }, |
| ... | @@ -8233,7 +8351,7 @@ fn genBinOp( | ... | @@ -8233,7 +8351,7 @@ fn genBinOp( |
| 8233 | .{ .v_, .cvtps2ph }, | 8351 | .{ .v_, .cvtps2ph }, |
| 8234 | dst_reg, | 8352 | dst_reg, |
| 8235 | dst_reg.to256(), | 8353 | dst_reg.to256(), |
| 8236 | Immediate.u(0b1_00), | 8354 | Immediate.u(@as(u5, @bitCast(RoundMode{ .mode = .mxcsr }))), |
| 8237 | ); | 8355 | ); |
| 8238 | return dst_mcv; | 8356 | return dst_mcv; |
| 8239 | }, | 8357 | }, |
| ... | @@ -9607,11 +9725,11 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { | ... | @@ -9607,11 +9725,11 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { |
| 9607 | 80, 128 => true, | 9725 | 80, 128 => true, |
| 9608 | else => unreachable, | 9726 | else => unreachable, |
| 9609 | }) { | 9727 | }) { |
| 9610 | var callee: ["__???f2".len]u8 = undefined; | 9728 | var callee_buf: ["__???f2".len]u8 = undefined; |
| 9611 | const ret = try self.genCall(.{ .lib = .{ | 9729 | const ret = try self.genCall(.{ .lib = .{ |
| 9612 | .return_type = .i32_type, | 9730 | .return_type = .i32_type, |
| 9613 | .param_types = &.{ ty.toIntern(), ty.toIntern() }, | 9731 | .param_types = &.{ ty.toIntern(), ty.toIntern() }, |
| 9614 | .callee = std.fmt.bufPrint(&callee, "__{s}{c}f2", .{ | 9732 | .callee = std.fmt.bufPrint(&callee_buf, "__{s}{c}f2", .{ |
| 9615 | switch (op) { | 9733 | switch (op) { |
| 9616 | .eq => "eq", | 9734 | .eq => "eq", |
| 9617 | .neq => "ne", | 9735 | .neq => "ne", |
| ... | @@ -12224,11 +12342,11 @@ fn airFloatFromInt(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -12224,11 +12342,11 @@ fn airFloatFromInt(self: *Self, inst: Air.Inst.Index) !void { |
| 12224 | src_ty.fmt(mod), dst_ty.fmt(mod), | 12342 | src_ty.fmt(mod), dst_ty.fmt(mod), |
| 12225 | }); | 12343 | }); |
| 12226 | | 12344 | |
| 12227 | var callee: ["__floatun?i?f".len]u8 = undefined; | 12345 | var callee_buf: ["__floatun?i?f".len]u8 = undefined; |
| 12228 | break :result try self.genCall(.{ .lib = .{ | 12346 | break :result try self.genCall(.{ .lib = .{ |
| 12229 | .return_type = dst_ty.toIntern(), | 12347 | .return_type = dst_ty.toIntern(), |
| 12230 | .param_types = &.{src_ty.toIntern()}, | 12348 | .param_types = &.{src_ty.toIntern()}, |
| 12231 | .callee = std.fmt.bufPrint(&callee, "__float{s}{c}i{c}f", .{ | 12349 | .callee = std.fmt.bufPrint(&callee_buf, "__float{s}{c}i{c}f", .{ |
| 12232 | switch (src_signedness) { | 12350 | switch (src_signedness) { |
| 12233 | .signed => "", | 12351 | .signed => "", |
| 12234 | .unsigned => "un", | 12352 | .unsigned => "un", |
| ... | @@ -12303,11 +12421,11 @@ fn airIntFromFloat(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -12303,11 +12421,11 @@ fn airIntFromFloat(self: *Self, inst: Air.Inst.Index) !void { |
| 12303 | src_ty.fmt(mod), dst_ty.fmt(mod), | 12421 | src_ty.fmt(mod), dst_ty.fmt(mod), |
| 12304 | }); | 12422 | }); |
| 12305 | | 12423 | |
| 12306 | var callee: ["__fixuns?f?i".len]u8 = undefined; | 12424 | var callee_buf: ["__fixuns?f?i".len]u8 = undefined; |
| 12307 | break :result try self.genCall(.{ .lib = .{ | 12425 | break :result try self.genCall(.{ .lib = .{ |
| 12308 | .return_type = dst_ty.toIntern(), | 12426 | .return_type = dst_ty.toIntern(), |
| 12309 | .param_types = &.{src_ty.toIntern()}, | 12427 | .param_types = &.{src_ty.toIntern()}, |
| 12310 | .callee = std.fmt.bufPrint(&callee, "__fix{s}{c}f{c}i", .{ | 12428 | .callee = std.fmt.bufPrint(&callee_buf, "__fix{s}{c}f{c}i", .{ |
| 12311 | switch (dst_signedness) { | 12429 | switch (dst_signedness) { |
| 12312 | .signed => "", | 12430 | .signed => "", |
| 12313 | .unsigned => "uns", | 12431 | .unsigned => "uns", |
| ... | @@ -13516,11 +13634,11 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -13516,11 +13634,11 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void { |
| 13516 | ty.fmt(mod), | 13634 | ty.fmt(mod), |
| 13517 | }); | 13635 | }); |
| 13518 | | 13636 | |
| 13519 | var callee: ["__fma?".len]u8 = undefined; | 13637 | var callee_buf: ["__fma?".len]u8 = undefined; |
| 13520 | break :result try self.genCall(.{ .lib = .{ | 13638 | break :result try self.genCall(.{ .lib = .{ |
| 13521 | .return_type = ty.toIntern(), | 13639 | .return_type = ty.toIntern(), |
| 13522 | .param_types = &.{ ty.toIntern(), ty.toIntern(), ty.toIntern() }, | 13640 | .param_types = &.{ ty.toIntern(), ty.toIntern(), ty.toIntern() }, |
| 13523 | .callee = std.fmt.bufPrint(&callee, "{s}fma{s}", .{ | 13641 | .callee = std.fmt.bufPrint(&callee_buf, "{s}fma{s}", .{ |
| 13524 | floatLibcAbiPrefix(ty), | 13642 | floatLibcAbiPrefix(ty), |
| 13525 | floatLibcAbiSuffix(ty), | 13643 | floatLibcAbiSuffix(ty), |
| 13526 | }) catch unreachable, | 13644 | }) catch unreachable, |