| 283 | } |
| 284 | |
| 285 | void OpDispatchBuilder::ADCOp(OpcodeArgs, uint32_t SrcIndex) { |
| 286 | // Calculate flags early. |
| 287 | CalculateDeferredFlags(); |
| 288 | |
| 289 | Ref Src = LoadSource(GPRClass, Op, Op->Src[SrcIndex], Op->Flags, {.AllowUpperGarbage = true}); |
| 290 | const auto Size = OpSizeFromDst(Op); |
| 291 | const auto OpSize = std::max(OpSize::i32Bit, Size); |
| 292 | |
| 293 | Ref Before {}; |
| 294 | if (DestIsLockedMem(Op)) { |
| 295 | auto ALUOp = IncrementByCarry(OpSize, Src); |
| 296 | HandledLock = true; |
| 297 | |
| 298 | Ref DestMem = MakeSegmentAddress(Op, Op->Dest); |
| 299 | Before = _AtomicFetchAdd(Size, ALUOp, DestMem); |
| 300 | } else { |
| 301 | Before = LoadSource(GPRClass, Op, Op->Dest, Op->Flags, {.AllowUpperGarbage = true}); |
| 302 | } |
| 303 | |
| 304 | Ref Result; |
| 305 | if (!DestIsLockedMem(Op) && Op->Src[SrcIndex].IsLiteral() && Op->Src[SrcIndex].Literal() == 0 && Size >= OpSize::i32Bit) { |
| 306 | HandleNZCV_RMW(); |
| 307 | RectifyCarryInvert(true); |
| 308 | Result = _AdcZeroWithFlags(OpSize, Before); |
| 309 | SetRFLAG<FEXCore::X86State::RFLAG_AF_RAW_LOC>(Before); |
| 310 | CalculatePF(Result); |
| 311 | CFInverted = false; |
| 312 | } else { |
| 313 | Result = CalculateFlags_ADC(Size, Before, Src); |
| 314 | } |
| 315 | |
| 316 | if (!DestIsLockedMem(Op)) { |
| 317 | StoreResult(GPRClass, Op, Result, OpSize::iInvalid); |
| 318 | } |
| 319 | } |
| 320 | |
| 321 | void OpDispatchBuilder::SBBOp(OpcodeArgs, uint32_t SrcIndex) { |
| 322 | // Calculate flags early. |