| 614 | } |
| 615 | |
| 616 | void Jit::dynamic_M(DecodedOp* op, JitWidth width, InstReg callback, LazyFlagType flagType, bool writeback, RegPtr tmp) { |
| 617 | const LazyFlags* flags = lazyFlags[flagType]; |
| 618 | if (writeback) { |
| 619 | // daytona installer can trigger this path with dec and flags needed, this is the hard one for the number of tmp regs required since it will need to preserve cf |
| 620 | U32 needsToSetFlags = 0; |
| 621 | if (flags) { |
| 622 | needsToSetFlags = op->needsToSetFlags(cpu); |
| 623 | } |
| 624 | RegPtr cf; |
| 625 | if (needsToSetFlags) { |
| 626 | if (flags && !(instructionInfo[op->inst].flagsSets & CF) && op->getNeededFlagsAfter(CF)) { |
| 627 | cf = getCF(); |
| 628 | } |
| 629 | } |
| 630 | |
| 631 | readWriteMem(width, calculateEaa(op), [&cf, needsToSetFlags, flagType, flags, op, width, callback, this](RegPtr value) { |
| 632 | if (needsToSetFlags) { |
| 633 | // don't commit flags until after after read/write permission check in case emulateSingleOp is called |
| 634 | if (cf) { |
| 635 | storeLazyFlagsOldCF(std::move(cf)); |
| 636 | } |
| 637 | storeLazyFlagType(flagType); |
| 638 | currentLazyFlags = flagType; |
| 639 | } |
| 640 | if (flags && flags->usesDst(needsToSetFlags)) { |
| 641 | storeLazyFlagsDest(value); |
| 642 | } |
| 643 | if (flags && flags->usesSrc(needsToSetFlags)) { |
| 644 | storeLazyFlagsSrc(value); |
| 645 | } |
| 646 | (this->*callback)(width, value); |
| 647 | if (flags && flags->usesResult(needsToSetFlags)) { |
| 648 | storeLazyFlagsResult(value); |
| 649 | } |
| 650 | }); |
| 651 | } else { |
| 652 | RegPtr dest = read(width, calculateEaa(op), nullptr, nullptr, tmp); |
| 653 | U32 needsToSetFlags = 0; |
| 654 | arithSetup(op, needsToSetFlags, flagType, nullptr); // must check after read permission in case emulateSingleOp is called, we can't update things like lazyFlags before this |
| 655 | |
| 656 | if (flags && flags->usesDst(needsToSetFlags)) { |
| 657 | storeLazyFlagsDest(dest); |
| 658 | } |
| 659 | if (flags && flags->usesSrc(needsToSetFlags)) { |
| 660 | storeLazyFlagsSrc(dest); |
| 661 | } |
| 662 | (this->*callback)(width, dest); |
| 663 | if (flags && flags->usesResult(needsToSetFlags)) { |
| 664 | kpanic("Jit::dynamic_M"); |
| 665 | } |
| 666 | } |
| 667 | } |
| 668 | |
| 669 | // SHL/SHR/SAR use this |
| 670 | // The CF flag contains the value of the last bit shifted out of the destination operand; it is undefined for SHL and SHR instructions where the count is greater than |
nothing calls this directly
no test coverage detected