| 3403 | } |
| 3404 | |
| 3405 | void OpDispatchBuilder::LODSOp(OpcodeArgs) { |
| 3406 | if (Op->Flags & FEXCore::X86Tables::DecodeFlags::FLAG_ADDRESS_SIZE) { |
| 3407 | LogMan::Msg::EFmt("Can't handle adddress size"); |
| 3408 | DecodeFailure = true; |
| 3409 | return; |
| 3410 | } |
| 3411 | |
| 3412 | const auto Size = OpSizeFromSrc(Op); |
| 3413 | const bool Repeat = (Op->Flags & (FEXCore::X86Tables::DecodeFlags::FLAG_REP_PREFIX | FEXCore::X86Tables::DecodeFlags::FLAG_REPNE_PREFIX)) != 0; |
| 3414 | |
| 3415 | if (!Repeat) { |
| 3416 | Ref Dest_RSI = MakeSegmentAddress(X86State::REG_RSI, Op->Flags, X86Tables::DecodeFlags::FLAG_DS_PREFIX); |
| 3417 | |
| 3418 | auto Src = _LoadMemAutoTSO(GPRClass, Size, Dest_RSI, Size); |
| 3419 | |
| 3420 | StoreResult(GPRClass, Op, Src, OpSize::iInvalid); |
| 3421 | |
| 3422 | // Offset the pointer |
| 3423 | Ref TailDest_RSI = LoadGPRRegister(X86State::REG_RSI); |
| 3424 | StoreGPRRegister(X86State::REG_RSI, OffsetByDir(TailDest_RSI, IR::OpSizeToSize(Size))); |
| 3425 | } else { |
| 3426 | // Calculate flags early. because end of block |
| 3427 | CalculateDeferredFlags(); |
| 3428 | |
| 3429 | ForeachDirection([this, Op, Size](int32_t PtrDir) { |
| 3430 | // XXX: Theoretically LODS could be optimized to |
| 3431 | // RSI += {-}(RCX * Size) |
| 3432 | // RAX = [RSI - Size] |
| 3433 | // But this might violate the case of an application scanning pages for read permission and catching the fault |
| 3434 | // May or may not matter |
| 3435 | |
| 3436 | auto JumpStart = Jump(); |
| 3437 | // Make sure to start a new block after ending this one |
| 3438 | auto LoopStart = CreateNewCodeBlockAfter(GetCurrentBlock()); |
| 3439 | SetJumpTarget(JumpStart, LoopStart); |
| 3440 | SetCurrentCodeBlock(LoopStart); |
| 3441 | StartNewBlock(); |
| 3442 | |
| 3443 | Ref Counter = LoadGPRRegister(X86State::REG_RCX); |
| 3444 | |
| 3445 | // Can we end the block? |
| 3446 | |
| 3447 | // We leave if RCX = 0 |
| 3448 | auto CondJump_ = CondJump(Counter, {COND_EQ}); |
| 3449 | |
| 3450 | auto LoopTail = CreateNewCodeBlockAfter(LoopStart); |
| 3451 | SetFalseJumpTarget(CondJump_, LoopTail); |
| 3452 | SetCurrentCodeBlock(LoopTail); |
| 3453 | StartNewBlock(); |
| 3454 | |
| 3455 | // Working loop |
| 3456 | { |
| 3457 | Ref Dest_RSI = MakeSegmentAddress(X86State::REG_RSI, Op->Flags, X86Tables::DecodeFlags::FLAG_DS_PREFIX); |
| 3458 | |
| 3459 | auto Src = _LoadMemAutoTSO(GPRClass, Size, Dest_RSI, Size); |
| 3460 | |
| 3461 | StoreResult(GPRClass, Op, Src, OpSize::iInvalid); |
| 3462 |
nothing calls this directly
no test coverage detected