| 3283 | } |
| 3284 | |
| 3285 | void OpDispatchBuilder::CMPSOp(OpcodeArgs) { |
| 3286 | if (Op->Flags & FEXCore::X86Tables::DecodeFlags::FLAG_ADDRESS_SIZE) { |
| 3287 | LogMan::Msg::EFmt("Can't handle adddress size"); |
| 3288 | DecodeFailure = true; |
| 3289 | return; |
| 3290 | } |
| 3291 | |
| 3292 | const auto Size = OpSizeFromSrc(Op); |
| 3293 | |
| 3294 | bool Repeat = Op->Flags & (FEXCore::X86Tables::DecodeFlags::FLAG_REPNE_PREFIX | FEXCore::X86Tables::DecodeFlags::FLAG_REP_PREFIX); |
| 3295 | if (!Repeat) { |
| 3296 | // Default DS prefix |
| 3297 | Ref Dest_RSI = MakeSegmentAddress(X86State::REG_RSI, Op->Flags, X86Tables::DecodeFlags::FLAG_DS_PREFIX); |
| 3298 | // Only ES prefix |
| 3299 | Ref Dest_RDI = MakeSegmentAddress(X86State::REG_RDI, 0, X86Tables::DecodeFlags::FLAG_ES_PREFIX, true); |
| 3300 | |
| 3301 | auto Src1 = _LoadMemAutoTSO(GPRClass, Size, Dest_RDI, Size); |
| 3302 | auto Src2 = _LoadMemAutoTSO(GPRClass, Size, Dest_RSI, Size); |
| 3303 | |
| 3304 | CalculateFlags_SUB(OpSizeFromSrc(Op), Src2, Src1); |
| 3305 | |
| 3306 | auto PtrDir = LoadDir(IR::OpSizeToSize(Size)); |
| 3307 | |
| 3308 | // Offset the pointer |
| 3309 | Dest_RDI = Add(OpSize::i64Bit, Dest_RDI, PtrDir); |
| 3310 | StoreGPRRegister(X86State::REG_RDI, Dest_RDI); |
| 3311 | |
| 3312 | // Offset second pointer |
| 3313 | Dest_RSI = Add(OpSize::i64Bit, Dest_RSI, PtrDir); |
| 3314 | StoreGPRRegister(X86State::REG_RSI, Dest_RSI); |
| 3315 | } else { |
| 3316 | // Calculate flags early. |
| 3317 | CalculateDeferredFlags(); |
| 3318 | |
| 3319 | bool REPE = Op->Flags & FEXCore::X86Tables::DecodeFlags::FLAG_REP_PREFIX; |
| 3320 | |
| 3321 | // If rcx = 0, skip the whole loop. |
| 3322 | Ref Counter = LoadGPRRegister(X86State::REG_RCX); |
| 3323 | auto OuterJump = CondJump(Counter, {COND_EQ}); |
| 3324 | |
| 3325 | auto BeforeLoop = CreateNewCodeBlockAfter(GetCurrentBlock()); |
| 3326 | SetFalseJumpTarget(OuterJump, BeforeLoop); |
| 3327 | SetCurrentCodeBlock(BeforeLoop); |
| 3328 | StartNewBlock(); |
| 3329 | |
| 3330 | ForeachDirection([this, Op, Size, REPE](int32_t PtrDir) { |
| 3331 | IRPair<IROp_CondJump> InnerJump; |
| 3332 | auto JumpIntoLoop = Jump(); |
| 3333 | |
| 3334 | // Setup for the loop |
| 3335 | auto LoopHeader = CreateNewCodeBlockAfter(GetCurrentBlock()); |
| 3336 | SetCurrentCodeBlock(LoopHeader); |
| 3337 | StartNewBlock(); |
| 3338 | SetJumpTarget(JumpIntoLoop, LoopHeader); |
| 3339 | |
| 3340 | // Working loop |
| 3341 | { |
| 3342 | // Default DS prefix |
nothing calls this directly
no test coverage detected