| ... | ... | @@ -2967,20 +2967,43 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void { |
| 2967 | 2967 | defer self.register_manager.unlockReg(limit_lock); |
| 2968 | 2968 | |
| 2969 | 2969 | const reg_bits = self.regBitSize(ty); |
| 2970 | const reg_extra_bits = self.regExtraBits(ty); |
| 2970 | 2971 | const cc: Condition = if (ty.isSignedInt()) cc: { |
| 2972 | if (reg_extra_bits > 0) { |
| 2973 | try self.genShiftBinOpMir(.{ ._l, .sa }, ty, dst_mcv, .{ .immediate = reg_extra_bits }); |
| 2974 | } |
| 2971 | 2975 | try self.genSetReg(limit_reg, ty, dst_mcv); |
| 2972 | 2976 | try self.genShiftBinOpMir(.{ ._r, .sa }, ty, limit_mcv, .{ .immediate = reg_bits - 1 }); |
| 2973 | 2977 | try self.genBinOpMir(.{ ._, .xor }, ty, limit_mcv, .{ |
| 2974 | 2978 | .immediate = (@as(u64, 1) << @intCast(u6, reg_bits - 1)) - 1, |
| 2975 | 2979 | }); |
| 2980 | if (reg_extra_bits > 0) { |
| 2981 | const shifted_rhs_reg = try self.copyToTmpRegister(ty, rhs_mcv); |
| 2982 | const shifted_rhs_mcv = MCValue{ .register = shifted_rhs_reg }; |
| 2983 | const shifted_rhs_lock = self.register_manager.lockRegAssumeUnused(shifted_rhs_reg); |
| 2984 | defer self.register_manager.unlockReg(shifted_rhs_lock); |
| 2985 | |
| 2986 | try self.genShiftBinOpMir( |
| 2987 | .{ ._l, .sa }, |
| 2988 | ty, |
| 2989 | shifted_rhs_mcv, |
| 2990 | .{ .immediate = reg_extra_bits }, |
| 2991 | ); |
| 2992 | try self.genBinOpMir(.{ ._, .add }, ty, dst_mcv, shifted_rhs_mcv); |
| 2993 | } else try self.genBinOpMir(.{ ._, .add }, ty, dst_mcv, rhs_mcv); |
| 2976 | 2994 | break :cc .o; |
| 2977 | 2995 | } else cc: { |
| 2978 | 2996 | try self.genSetReg(limit_reg, ty, .{ |
| 2979 | | .immediate = @as(u64, math.maxInt(u64)) >> @intCast(u6, 64 - reg_bits), |
| 2997 | .immediate = @as(u64, math.maxInt(u64)) >> @intCast(u6, 64 - ty.bitSize(self.target.*)), |
| 2980 | 2998 | }); |
| 2999 | |
| 3000 | try self.genBinOpMir(.{ ._, .add }, ty, dst_mcv, rhs_mcv); |
| 3001 | if (reg_extra_bits > 0) { |
| 3002 | try self.genBinOpMir(.{ ._, .cmp }, ty, dst_mcv, limit_mcv); |
| 3003 | break :cc .a; |
| 3004 | } |
| 2981 | 3005 | break :cc .c; |
| 2982 | 3006 | }; |
| 2983 | | try self.genBinOpMir(.{ ._, .add }, ty, dst_mcv, rhs_mcv); |
| 2984 | 3007 | |
| 2985 | 3008 | const cmov_abi_size = @max(@intCast(u32, ty.abiSize(self.target.*)), 2); |
| 2986 | 3009 | try self.asmCmovccRegisterRegister( |
| ... | ... | @@ -2989,6 +3012,10 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void { |
| 2989 | 3012 | cc, |
| 2990 | 3013 | ); |
| 2991 | 3014 | |
| 3015 | if (reg_extra_bits > 0 and ty.isSignedInt()) { |
| 3016 | try self.genShiftBinOpMir(.{ ._r, .sa }, ty, dst_mcv, .{ .immediate = reg_extra_bits }); |
| 3017 | } |
| 3018 | |
| 2992 | 3019 | return self.finishAir(inst, dst_mcv, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 2993 | 3020 | } |
| 2994 | 3021 | |
| ... | ... | @@ -3018,18 +3045,36 @@ fn airSubSat(self: *Self, inst: Air.Inst.Index) !void { |
| 3018 | 3045 | defer self.register_manager.unlockReg(limit_lock); |
| 3019 | 3046 | |
| 3020 | 3047 | const reg_bits = self.regBitSize(ty); |
| 3048 | const reg_extra_bits = self.regExtraBits(ty); |
| 3021 | 3049 | const cc: Condition = if (ty.isSignedInt()) cc: { |
| 3050 | if (reg_extra_bits > 0) { |
| 3051 | try self.genShiftBinOpMir(.{ ._l, .sa }, ty, dst_mcv, .{ .immediate = reg_extra_bits }); |
| 3052 | } |
| 3022 | 3053 | try self.genSetReg(limit_reg, ty, dst_mcv); |
| 3023 | 3054 | try self.genShiftBinOpMir(.{ ._r, .sa }, ty, limit_mcv, .{ .immediate = reg_bits - 1 }); |
| 3024 | 3055 | try self.genBinOpMir(.{ ._, .xor }, ty, limit_mcv, .{ |
| 3025 | 3056 | .immediate = (@as(u64, 1) << @intCast(u6, reg_bits - 1)) - 1, |
| 3026 | 3057 | }); |
| 3058 | if (reg_extra_bits > 0) { |
| 3059 | const shifted_rhs_reg = try self.copyToTmpRegister(ty, rhs_mcv); |
| 3060 | const shifted_rhs_mcv = MCValue{ .register = shifted_rhs_reg }; |
| 3061 | const shifted_rhs_lock = self.register_manager.lockRegAssumeUnused(shifted_rhs_reg); |
| 3062 | defer self.register_manager.unlockReg(shifted_rhs_lock); |
| 3063 | |
| 3064 | try self.genShiftBinOpMir( |
| 3065 | .{ ._l, .sa }, |
| 3066 | ty, |
| 3067 | shifted_rhs_mcv, |
| 3068 | .{ .immediate = reg_extra_bits }, |
| 3069 | ); |
| 3070 | try self.genBinOpMir(.{ ._, .sub }, ty, dst_mcv, shifted_rhs_mcv); |
| 3071 | } else try self.genBinOpMir(.{ ._, .sub }, ty, dst_mcv, rhs_mcv); |
| 3027 | 3072 | break :cc .o; |
| 3028 | 3073 | } else cc: { |
| 3029 | 3074 | try self.genSetReg(limit_reg, ty, .{ .immediate = 0 }); |
| 3075 | try self.genBinOpMir(.{ ._, .sub }, ty, dst_mcv, rhs_mcv); |
| 3030 | 3076 | break :cc .c; |
| 3031 | 3077 | }; |
| 3032 | | try self.genBinOpMir(.{ ._, .sub }, ty, dst_mcv, rhs_mcv); |
| 3033 | 3078 | |
| 3034 | 3079 | const cmov_abi_size = @max(@intCast(u32, ty.abiSize(self.target.*)), 2); |
| 3035 | 3080 | try self.asmCmovccRegisterRegister( |
| ... | ... | @@ -3038,6 +3083,10 @@ fn airSubSat(self: *Self, inst: Air.Inst.Index) !void { |
| 3038 | 3083 | cc, |
| 3039 | 3084 | ); |
| 3040 | 3085 | |
| 3086 | if (reg_extra_bits > 0 and ty.isSignedInt()) { |
| 3087 | try self.genShiftBinOpMir(.{ ._r, .sa }, ty, dst_mcv, .{ .immediate = reg_extra_bits }); |
| 3088 | } |
| 3089 | |
| 3041 | 3090 | return self.finishAir(inst, dst_mcv, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 3042 | 3091 | } |
| 3043 | 3092 | |