| ... | @@ -2967,20 +2967,43 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2967,20 +2967,43 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void { |
| 2967 | defer self.register_manager.unlockReg(limit_lock); | 2967 | defer self.register_manager.unlockReg(limit_lock); |
| 2968 | | 2968 | |
| 2969 | const reg_bits = self.regBitSize(ty); | 2969 | const reg_bits = self.regBitSize(ty); |
| | 2970 | const reg_extra_bits = self.regExtraBits(ty); |
| 2970 | const cc: Condition = if (ty.isSignedInt()) cc: { | 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 | try self.genSetReg(limit_reg, ty, dst_mcv); | 2975 | try self.genSetReg(limit_reg, ty, dst_mcv); |
| 2972 | try self.genShiftBinOpMir(.{ ._r, .sa }, ty, limit_mcv, .{ .immediate = reg_bits - 1 }); | 2976 | try self.genShiftBinOpMir(.{ ._r, .sa }, ty, limit_mcv, .{ .immediate = reg_bits - 1 }); |
| 2973 | try self.genBinOpMir(.{ ._, .xor }, ty, limit_mcv, .{ | 2977 | try self.genBinOpMir(.{ ._, .xor }, ty, limit_mcv, .{ |
| 2974 | .immediate = (@as(u64, 1) << @intCast(u6, reg_bits - 1)) - 1, | 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 | break :cc .o; | 2994 | break :cc .o; |
| 2977 | } else cc: { | 2995 | } else cc: { |
| 2978 | try self.genSetReg(limit_reg, ty, .{ | 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 | break :cc .c; | 3005 | break :cc .c; |
| 2982 | }; | 3006 | }; |
| 2983 | try self.genBinOpMir(.{ ._, .add }, ty, dst_mcv, rhs_mcv); | | |
| 2984 | | 3007 | |
| 2985 | const cmov_abi_size = @max(@intCast(u32, ty.abiSize(self.target.*)), 2); | 3008 | const cmov_abi_size = @max(@intCast(u32, ty.abiSize(self.target.*)), 2); |
| 2986 | try self.asmCmovccRegisterRegister( | 3009 | try self.asmCmovccRegisterRegister( |
| ... | @@ -2989,6 +3012,10 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2989,6 +3012,10 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void { |
| 2989 | cc, | 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 | return self.finishAir(inst, dst_mcv, .{ bin_op.lhs, bin_op.rhs, .none }); | 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,18 +3045,36 @@ fn airSubSat(self: *Self, inst: Air.Inst.Index) !void { |
| 3018 | defer self.register_manager.unlockReg(limit_lock); | 3045 | defer self.register_manager.unlockReg(limit_lock); |
| 3019 | | 3046 | |
| 3020 | const reg_bits = self.regBitSize(ty); | 3047 | const reg_bits = self.regBitSize(ty); |
| | 3048 | const reg_extra_bits = self.regExtraBits(ty); |
| 3021 | const cc: Condition = if (ty.isSignedInt()) cc: { | 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 | try self.genSetReg(limit_reg, ty, dst_mcv); | 3053 | try self.genSetReg(limit_reg, ty, dst_mcv); |
| 3023 | try self.genShiftBinOpMir(.{ ._r, .sa }, ty, limit_mcv, .{ .immediate = reg_bits - 1 }); | 3054 | try self.genShiftBinOpMir(.{ ._r, .sa }, ty, limit_mcv, .{ .immediate = reg_bits - 1 }); |
| 3024 | try self.genBinOpMir(.{ ._, .xor }, ty, limit_mcv, .{ | 3055 | try self.genBinOpMir(.{ ._, .xor }, ty, limit_mcv, .{ |
| 3025 | .immediate = (@as(u64, 1) << @intCast(u6, reg_bits - 1)) - 1, | 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 | break :cc .o; | 3072 | break :cc .o; |
| 3028 | } else cc: { | 3073 | } else cc: { |
| 3029 | try self.genSetReg(limit_reg, ty, .{ .immediate = 0 }); | 3074 | try self.genSetReg(limit_reg, ty, .{ .immediate = 0 }); |
| | 3075 | try self.genBinOpMir(.{ ._, .sub }, ty, dst_mcv, rhs_mcv); |
| 3030 | break :cc .c; | 3076 | break :cc .c; |
| 3031 | }; | 3077 | }; |
| 3032 | try self.genBinOpMir(.{ ._, .sub }, ty, dst_mcv, rhs_mcv); | | |
| 3033 | | 3078 | |
| 3034 | const cmov_abi_size = @max(@intCast(u32, ty.abiSize(self.target.*)), 2); | 3079 | const cmov_abi_size = @max(@intCast(u32, ty.abiSize(self.target.*)), 2); |
| 3035 | try self.asmCmovccRegisterRegister( | 3080 | try self.asmCmovccRegisterRegister( |
| ... | @@ -3038,6 +3083,10 @@ fn airSubSat(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3038,6 +3083,10 @@ fn airSubSat(self: *Self, inst: Air.Inst.Index) !void { |
| 3038 | cc, | 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 | return self.finishAir(inst, dst_mcv, .{ bin_op.lhs, bin_op.rhs, .none }); | 3090 | return self.finishAir(inst, dst_mcv, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 3042 | } | 3091 | } |
| 3043 | | 3092 | |