| ... | @@ -958,16 +958,17 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -958,16 +958,17 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) !void { |
| 958 | return self.fail("TODO implement trunc for abi sizes larger than 8", .{}); | 958 | return self.fail("TODO implement trunc for abi sizes larger than 8", .{}); |
| 959 | } | 959 | } |
| 960 | | 960 | |
| 961 | const dst_mcv = blk: { | 961 | operand.freezeIfRegister(&self.register_manager); |
| 962 | const reg = switch (operand) { | 962 | defer operand.unfreezeIfRegister(&self.register_manager); |
| 963 | .register => |reg| reg, | 963 | |
| 964 | else => inner: { | 964 | const reg: Register = blk: { |
| 965 | const reg = try self.register_manager.allocReg(inst); | 965 | if (operand.isRegister()) { |
| 966 | try self.genSetReg(src_ty, reg, operand); | 966 | if (self.reuseOperand(inst, ty_op.operand, 0, operand)) { |
| 967 | break :inner reg; | 967 | break :blk operand.register; |
| 968 | }, | 968 | } |
| 969 | }; | 969 | } |
| 970 | break :blk .{ .register = registerAlias(reg, @intCast(u32, dst_ty_size)) }; | 970 | const mcv = try self.copyToNewRegister(inst, src_ty, operand); |
| | 971 | break :blk mcv.register.to64(); |
| 971 | }; | 972 | }; |
| 972 | | 973 | |
| 973 | // when truncating a `u16` to `u5`, for example, those top 3 bits in the result | 974 | // when truncating a `u16` to `u5`, for example, those top 3 bits in the result |
| ... | @@ -975,11 +976,31 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -975,11 +976,31 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) !void { |
| 975 | const dst_bit_size = dst_ty.bitSize(self.target.*); | 976 | const dst_bit_size = dst_ty.bitSize(self.target.*); |
| 976 | const is_power_of_two = (dst_bit_size & (dst_bit_size - 1)) == 0; | 977 | const is_power_of_two = (dst_bit_size & (dst_bit_size - 1)) == 0; |
| 977 | if (!is_power_of_two or dst_bit_size < 8) { | 978 | if (!is_power_of_two or dst_bit_size < 8) { |
| 978 | const mask = (~@as(u64, 0)) >> @intCast(u6, (64 - dst_ty.bitSize(self.target.*))); | 979 | const shift = @intCast(u6, 64 - dst_ty.bitSize(self.target.*)); |
| 979 | try self.genBinMathOpMir(.@"and", dst_ty, dst_mcv, .{ .immediate = mask }); | 980 | const mask = (~@as(u64, 0)) >> shift; |
| | 981 | try self.genBinMathOpMir(.@"and", Type.usize, .{ .register = reg }, .{ .immediate = mask }); |
| | 982 | |
| | 983 | if (src_ty.intInfo(self.target.*).signedness == .signed) { |
| | 984 | _ = try self.addInst(.{ |
| | 985 | .tag = .sal, |
| | 986 | .ops = (Mir.Ops{ |
| | 987 | .reg1 = reg, |
| | 988 | .flags = 0b10, |
| | 989 | }).encode(), |
| | 990 | .data = .{ .imm = shift }, |
| | 991 | }); |
| | 992 | _ = try self.addInst(.{ |
| | 993 | .tag = .sar, |
| | 994 | .ops = (Mir.Ops{ |
| | 995 | .reg1 = reg, |
| | 996 | .flags = 0b10, |
| | 997 | }).encode(), |
| | 998 | .data = .{ .imm = shift }, |
| | 999 | }); |
| | 1000 | } |
| 980 | } | 1001 | } |
| 981 | | 1002 | |
| 982 | return self.finishAir(inst, dst_mcv, .{ ty_op.operand, .none, .none }); | 1003 | return self.finishAir(inst, .{ .register = reg }, .{ ty_op.operand, .none, .none }); |
| 983 | } | 1004 | } |
| 984 | | 1005 | |
| 985 | fn airBoolToInt(self: *Self, inst: Air.Inst.Index) !void { | 1006 | fn airBoolToInt(self: *Self, inst: Air.Inst.Index) !void { |