| ... | ... | @@ -958,16 +958,17 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) !void { |
| 958 | 958 | return self.fail("TODO implement trunc for abi sizes larger than 8", .{}); |
| 959 | 959 | } |
| 960 | 960 | |
| 961 | | const dst_mcv = blk: { |
| 962 | | const reg = switch (operand) { |
| 963 | | .register => |reg| reg, |
| 964 | | else => inner: { |
| 965 | | const reg = try self.register_manager.allocReg(inst); |
| 966 | | try self.genSetReg(src_ty, reg, operand); |
| 967 | | break :inner reg; |
| 968 | | }, |
| 969 | | }; |
| 970 | | break :blk .{ .register = registerAlias(reg, @intCast(u32, dst_ty_size)) }; |
| 961 | operand.freezeIfRegister(&self.register_manager); |
| 962 | defer operand.unfreezeIfRegister(&self.register_manager); |
| 963 | |
| 964 | const reg: Register = blk: { |
| 965 | if (operand.isRegister()) { |
| 966 | if (self.reuseOperand(inst, ty_op.operand, 0, operand)) { |
| 967 | break :blk operand.register; |
| 968 | } |
| 969 | } |
| 970 | const mcv = try self.copyToNewRegister(inst, src_ty, operand); |
| 971 | break :blk mcv.register.to64(); |
| 971 | 972 | }; |
| 972 | 973 | |
| 973 | 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 | 976 | const dst_bit_size = dst_ty.bitSize(self.target.*); |
| 976 | 977 | const is_power_of_two = (dst_bit_size & (dst_bit_size - 1)) == 0; |
| 977 | 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 | | try self.genBinMathOpMir(.@"and", dst_ty, dst_mcv, .{ .immediate = mask }); |
| 979 | const shift = @intCast(u6, 64 - dst_ty.bitSize(self.target.*)); |
| 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 | 1006 | fn airBoolToInt(self: *Self, inst: Air.Inst.Index) !void { |