| ... | ... | @@ -2601,7 +2601,13 @@ fn genIntMulDivOpMir( |
| 2601 | 2601 | else => unreachable, |
| 2602 | 2602 | .mul, .imul => {}, |
| 2603 | 2603 | .div => try self.asmRegisterRegister(.xor, .edx, .edx), |
| 2604 | | .idiv => try self.asmOpOnly(.cqo), |
| 2604 | .idiv => switch (self.regBitSize(ty)) { |
| 2605 | 8 => try self.asmOpOnly(.cbw), |
| 2606 | 16 => try self.asmOpOnly(.cwd), |
| 2607 | 32 => try self.asmOpOnly(.cdq), |
| 2608 | 64 => try self.asmOpOnly(.cqo), |
| 2609 | else => unreachable, |
| 2610 | }, |
| 2605 | 2611 | } |
| 2606 | 2612 | |
| 2607 | 2613 | const mat_rhs: MCValue = switch (rhs) { |
| ... | ... | @@ -2631,7 +2637,8 @@ fn genIntMulDivOpMir( |
| 2631 | 2637 | /// Always returns a register. |
| 2632 | 2638 | /// Clobbers .rax and .rdx registers. |
| 2633 | 2639 | fn genInlineIntDivFloor(self: *Self, ty: Type, lhs: MCValue, rhs: MCValue) !MCValue { |
| 2634 | | const signedness = ty.intInfo(self.target.*).signedness; |
| 2640 | const abi_size = @intCast(u32, ty.abiSize(self.target.*)); |
| 2641 | const int_info = ty.intInfo(self.target.*); |
| 2635 | 2642 | const dividend: Register = switch (lhs) { |
| 2636 | 2643 | .register => |reg| reg, |
| 2637 | 2644 | else => try self.copyToTmpRegister(ty, lhs), |
| ... | ... | @@ -2646,16 +2653,32 @@ fn genInlineIntDivFloor(self: *Self, ty: Type, lhs: MCValue, rhs: MCValue) !MCVa |
| 2646 | 2653 | const divisor_lock = self.register_manager.lockReg(divisor); |
| 2647 | 2654 | defer if (divisor_lock) |lock| self.register_manager.unlockReg(lock); |
| 2648 | 2655 | |
| 2649 | | try self.genIntMulDivOpMir(switch (signedness) { |
| 2656 | try self.genIntMulDivOpMir(switch (int_info.signedness) { |
| 2650 | 2657 | .signed => .idiv, |
| 2651 | 2658 | .unsigned => .div, |
| 2652 | | }, Type.isize, .{ .register = dividend }, .{ .register = divisor }); |
| 2659 | }, ty, .{ .register = dividend }, .{ .register = divisor }); |
| 2653 | 2660 | |
| 2654 | | try self.asmRegisterRegister(.xor, divisor.to64(), dividend.to64()); |
| 2655 | | try self.asmRegisterImmediate(.sar, divisor.to64(), Immediate.u(63)); |
| 2656 | | try self.asmRegisterRegister(.@"test", .rdx, .rdx); |
| 2657 | | try self.asmCmovccRegisterRegister(divisor.to64(), .rdx, .e); |
| 2658 | | try self.genBinOpMir(.add, Type.isize, .{ .register = divisor }, .{ .register = .rax }); |
| 2661 | try self.asmRegisterRegister( |
| 2662 | .xor, |
| 2663 | registerAlias(divisor, abi_size), |
| 2664 | registerAlias(dividend, abi_size), |
| 2665 | ); |
| 2666 | try self.asmRegisterImmediate( |
| 2667 | .sar, |
| 2668 | registerAlias(divisor, abi_size), |
| 2669 | Immediate.u(int_info.bits - 1), |
| 2670 | ); |
| 2671 | try self.asmRegisterRegister( |
| 2672 | .@"test", |
| 2673 | registerAlias(.rdx, abi_size), |
| 2674 | registerAlias(.rdx, abi_size), |
| 2675 | ); |
| 2676 | try self.asmCmovccRegisterRegister( |
| 2677 | registerAlias(divisor, abi_size), |
| 2678 | registerAlias(.rdx, abi_size), |
| 2679 | .z, |
| 2680 | ); |
| 2681 | try self.genBinOpMir(.add, ty, .{ .register = divisor }, .{ .register = .rax }); |
| 2659 | 2682 | return MCValue{ .register = divisor }; |
| 2660 | 2683 | } |
| 2661 | 2684 | |
| ... | ... | @@ -4928,8 +4951,24 @@ fn genMulDivBinOp( |
| 4928 | 4951 | |
| 4929 | 4952 | switch (signedness) { |
| 4930 | 4953 | .signed => { |
| 4954 | const lhs_lock = switch (lhs) { |
| 4955 | .register => |reg| self.register_manager.lockReg(reg), |
| 4956 | else => null, |
| 4957 | }; |
| 4958 | defer if (lhs_lock) |lock| self.register_manager.unlockReg(lock); |
| 4959 | const rhs_lock = switch (rhs) { |
| 4960 | .register => |reg| self.register_manager.lockReg(reg), |
| 4961 | else => null, |
| 4962 | }; |
| 4963 | defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock); |
| 4964 | |
| 4965 | // hack around hazard between rhs and div_floor by copying rhs to another register |
| 4966 | const rhs_copy = try self.copyToTmpRegister(ty, rhs); |
| 4967 | const rhs_copy_lock = self.register_manager.lockRegAssumeUnused(rhs_copy); |
| 4968 | defer self.register_manager.unlockReg(rhs_copy_lock); |
| 4969 | |
| 4931 | 4970 | const div_floor = try self.genInlineIntDivFloor(ty, lhs, rhs); |
| 4932 | | try self.genIntMulComplexOpMir(ty, div_floor, rhs); |
| 4971 | try self.genIntMulComplexOpMir(ty, div_floor, .{ .register = rhs_copy }); |
| 4933 | 4972 | const div_floor_lock = self.register_manager.lockReg(div_floor.register); |
| 4934 | 4973 | defer if (div_floor_lock) |lock| self.register_manager.unlockReg(lock); |
| 4935 | 4974 | |