| 2671 | } |
| 2672 | |
| 2673 | void OpDispatchBuilder::MULOp(OpcodeArgs) { |
| 2674 | const auto Size = OpSizeFromSrc(Op); |
| 2675 | const auto SizeBits = IR::OpSizeAsBits(Size); |
| 2676 | |
| 2677 | Ref Src1 = LoadSource(GPRClass, Op, Op->Dest, Op->Flags, {.AllowUpperGarbage = true}); |
| 2678 | Ref Src2 = LoadGPRRegister(X86State::REG_RAX); |
| 2679 | Ref Result {}; |
| 2680 | |
| 2681 | if (Size != OpSize::i64Bit) { |
| 2682 | Src1 = _Bfe(OpSize::i64Bit, SizeBits, 0, Src1); |
| 2683 | Src2 = _Bfe(OpSize::i64Bit, SizeBits, 0, Src2); |
| 2684 | Result = _UMul(OpSize::i64Bit, Src1, Src2); |
| 2685 | } |
| 2686 | Ref ResultHigh {}; |
| 2687 | |
| 2688 | if (Size == OpSize::i8Bit) { |
| 2689 | // Result is stored in AX |
| 2690 | StoreGPRRegister(X86State::REG_RAX, Result, OpSize::i16Bit); |
| 2691 | ResultHigh = _Bfe(OpSize::i64Bit, 8, 8, Result); |
| 2692 | } else if (Size == OpSize::i16Bit) { |
| 2693 | // 16bits stored in AX |
| 2694 | // 16bits stored in DX |
| 2695 | StoreGPRRegister(X86State::REG_RAX, Result, Size); |
| 2696 | ResultHigh = _Bfe(OpSize::i64Bit, 16, 16, Result); |
| 2697 | StoreGPRRegister(X86State::REG_RDX, ResultHigh, Size); |
| 2698 | } else if (Size == OpSize::i32Bit) { |
| 2699 | // 32bits stored in EAX |
| 2700 | // 32bits stored in EDX |
| 2701 | Ref ResultLow = _Bfe(OpSize::i64Bit, 32, 0, Result); |
| 2702 | ResultHigh = _Bfe(OpSize::i64Bit, 32, 32, Result); |
| 2703 | StoreGPRRegister(X86State::REG_RAX, ResultLow); |
| 2704 | StoreGPRRegister(X86State::REG_RDX, ResultHigh); |
| 2705 | } else if (Size == OpSize::i64Bit) { |
| 2706 | if (!Is64BitMode) { |
| 2707 | LogMan::Msg::EFmt("Doesn't exist in 32bit mode"); |
| 2708 | DecodeFailure = true; |
| 2709 | return; |
| 2710 | } |
| 2711 | // 64bits stored in RAX |
| 2712 | // 64bits stored in RDX |
| 2713 | // |
| 2714 | // Calculate high first to allow better RA. |
| 2715 | ResultHigh = _UMulH(OpSize::i64Bit, Src1, Src2); |
| 2716 | Result = _UMul(OpSize::i64Bit, Src1, Src2); |
| 2717 | StoreGPRRegister(X86State::REG_RAX, Result); |
| 2718 | StoreGPRRegister(X86State::REG_RDX, ResultHigh); |
| 2719 | } |
| 2720 | |
| 2721 | CalculateFlags_UMUL(ResultHigh); |
| 2722 | } |
| 2723 | |
| 2724 | void OpDispatchBuilder::NOTOp(OpcodeArgs) { |
| 2725 | const auto Size = OpSizeFromSrc(Op); |
nothing calls this directly
no test coverage detected