| ... | @@ -1659,6 +1659,8 @@ fn airShlShrBinOp(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1659,6 +1659,8 @@ fn airShlShrBinOp(self: *Self, inst: Air.Inst.Index) !void { |
| 1659 | return self.finishAir(inst, .dead, .{ bin_op.lhs, bin_op.rhs, .none }); | 1659 | return self.finishAir(inst, .dead, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 1660 | } | 1660 | } |
| 1661 | | 1661 | |
| | 1662 | try self.spillRegisters(1, .{.rcx}); |
| | 1663 | |
| 1662 | const tag = self.air.instructions.items(.tag)[inst]; | 1664 | const tag = self.air.instructions.items(.tag)[inst]; |
| 1663 | const lhs = try self.resolveInst(bin_op.lhs); | 1665 | const lhs = try self.resolveInst(bin_op.lhs); |
| 1664 | const rhs = try self.resolveInst(bin_op.rhs); | 1666 | const rhs = try self.resolveInst(bin_op.rhs); |
| ... | @@ -2981,7 +2983,7 @@ fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2981,7 +2983,7 @@ fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 2981 | } | 2983 | } |
| 2982 | | 2984 | |
| 2983 | /// Result is always a register. | 2985 | /// Result is always a register. |
| 2984 | /// Clobbers .rcx therefore care is needed to spill .rcx upfront. | 2986 | /// Clobbers .rcx for non-immediate rhs, therefore care is needed to spill .rcx upfront. |
| 2985 | /// Asserts .rcx is free. | 2987 | /// Asserts .rcx is free. |
| 2986 | fn genShiftBinOp( | 2988 | fn genShiftBinOp( |
| 2987 | self: *Self, | 2989 | self: *Self, |
| ... | @@ -2999,12 +3001,7 @@ fn genShiftBinOp( | ... | @@ -2999,12 +3001,7 @@ fn genShiftBinOp( |
| 2999 | return self.fail("TODO implement genShiftBinOp for {}", .{lhs_ty.fmtDebug()}); | 3001 | return self.fail("TODO implement genShiftBinOp for {}", .{lhs_ty.fmtDebug()}); |
| 3000 | } | 3002 | } |
| 3001 | | 3003 | |
| 3002 | assert(self.register_manager.isRegFree(.rcx)); | 3004 | assert(rhs_ty.abiSize(self.target.*) == 1); |
| 3003 | | | |
| 3004 | try self.register_manager.getReg(.rcx, null); | | |
| 3005 | try self.genSetReg(rhs_ty, .rcx, rhs); | | |
| 3006 | const rcx_lock = self.register_manager.lockRegAssumeUnused(.rcx); | | |
| 3007 | defer self.register_manager.unlockReg(rcx_lock); | | |
| 3008 | | 3005 | |
| 3009 | const int_info = lhs_ty.intInfo(self.target.*); | 3006 | const int_info = lhs_ty.intInfo(self.target.*); |
| 3010 | const signedness = int_info.signedness; | 3007 | const signedness = int_info.signedness; |
| ... | @@ -3021,6 +3018,29 @@ fn genShiftBinOp( | ... | @@ -3021,6 +3018,29 @@ fn genShiftBinOp( |
| 3021 | }; | 3018 | }; |
| 3022 | defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock); | 3019 | defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock); |
| 3023 | | 3020 | |
| | 3021 | const flags: u2 = blk: { |
| | 3022 | if (rhs.isImmediate()) { |
| | 3023 | const flags: u2 = switch (rhs.immediate) { |
| | 3024 | 0 => unreachable, // TODO is this valid? |
| | 3025 | 1 => 0b00, |
| | 3026 | else => 0b10, |
| | 3027 | }; |
| | 3028 | break :blk flags; |
| | 3029 | } |
| | 3030 | |
| | 3031 | assert(self.register_manager.isRegFree(.rcx)); |
| | 3032 | |
| | 3033 | try self.register_manager.getReg(.rcx, null); |
| | 3034 | try self.genSetReg(rhs_ty, .rcx, rhs); |
| | 3035 | const rcx_lock = self.register_manager.lockRegAssumeUnused(.rcx); |
| | 3036 | defer self.register_manager.unlockReg(rcx_lock); |
| | 3037 | |
| | 3038 | break :blk 0b01; |
| | 3039 | }; |
| | 3040 | const data: Mir.Inst.Data = if (rhs.isImmediate()) .{ |
| | 3041 | .imm = @intCast(u8, rhs.immediate), |
| | 3042 | } else undefined; |
| | 3043 | |
| 3024 | const dst: MCValue = blk: { | 3044 | const dst: MCValue = blk: { |
| 3025 | if (maybe_inst) |inst| { | 3045 | if (maybe_inst) |inst| { |
| 3026 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 3046 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| ... | @@ -3040,9 +3060,9 @@ fn genShiftBinOp( | ... | @@ -3040,9 +3060,9 @@ fn genShiftBinOp( |
| 3040 | .tag = .sal, | 3060 | .tag = .sal, |
| 3041 | .ops = (Mir.Ops{ | 3061 | .ops = (Mir.Ops{ |
| 3042 | .reg1 = dst.register, | 3062 | .reg1 = dst.register, |
| 3043 | .flags = 0b01, | 3063 | .flags = flags, |
| 3044 | }).encode(), | 3064 | }).encode(), |
| 3045 | .data = undefined, | 3065 | .data = data, |
| 3046 | }); | 3066 | }); |
| 3047 | }, | 3067 | }, |
| 3048 | .unsigned => { | 3068 | .unsigned => { |
| ... | @@ -3050,9 +3070,9 @@ fn genShiftBinOp( | ... | @@ -3050,9 +3070,9 @@ fn genShiftBinOp( |
| 3050 | .tag = .shl, | 3070 | .tag = .shl, |
| 3051 | .ops = (Mir.Ops{ | 3071 | .ops = (Mir.Ops{ |
| 3052 | .reg1 = dst.register, | 3072 | .reg1 = dst.register, |
| 3053 | .flags = 0b01, | 3073 | .flags = flags, |
| 3054 | }).encode(), | 3074 | }).encode(), |
| 3055 | .data = undefined, | 3075 | .data = data, |
| 3056 | }); | 3076 | }); |
| 3057 | }, | 3077 | }, |
| 3058 | }, | 3078 | }, |
| ... | @@ -3062,9 +3082,9 @@ fn genShiftBinOp( | ... | @@ -3062,9 +3082,9 @@ fn genShiftBinOp( |
| 3062 | .tag = .sar, | 3082 | .tag = .sar, |
| 3063 | .ops = (Mir.Ops{ | 3083 | .ops = (Mir.Ops{ |
| 3064 | .reg1 = dst.register, | 3084 | .reg1 = dst.register, |
| 3065 | .flags = 0b01, | 3085 | .flags = flags, |
| 3066 | }).encode(), | 3086 | }).encode(), |
| 3067 | .data = undefined, | 3087 | .data = data, |
| 3068 | }); | 3088 | }); |
| 3069 | }, | 3089 | }, |
| 3070 | .unsigned => { | 3090 | .unsigned => { |
| ... | @@ -3072,9 +3092,9 @@ fn genShiftBinOp( | ... | @@ -3072,9 +3092,9 @@ fn genShiftBinOp( |
| 3072 | .tag = .shr, | 3092 | .tag = .shr, |
| 3073 | .ops = (Mir.Ops{ | 3093 | .ops = (Mir.Ops{ |
| 3074 | .reg1 = dst.register, | 3094 | .reg1 = dst.register, |
| 3075 | .flags = 0b01, | 3095 | .flags = flags, |
| 3076 | }).encode(), | 3096 | }).encode(), |
| 3077 | .data = undefined, | 3097 | .data = data, |
| 3078 | }); | 3098 | }); |
| 3079 | }, | 3099 | }, |
| 3080 | }, | 3100 | }, |