MCPcopy Create free account
hub / github.com/FEX-Emu/FEX / BTOp

Method BTOp

FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp:2389–2541  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

2387}
2388
2389void OpDispatchBuilder::BTOp(OpcodeArgs, uint32_t SrcIndex, BTAction Action) {
2390 Ref Value;
2391 ArithRef Src;
2392 bool IsNonconstant = Op->Src[SrcIndex].IsGPR();
2393
2394 const uint32_t Size = GetDstBitSize(Op);
2395 const uint32_t Mask = Size - 1;
2396
2397 if (IsNonconstant) {
2398 // Because we mask explicitly with And/Bfe/Sbfe after, we can allow garbage here.
2399 Src = ARef(LoadSource(GPRClass, Op, Op->Src[SrcIndex], Op->Flags, {.AllowUpperGarbage = true}));
2400 } else {
2401 // Can only be an immediate
2402 // Masked by operand size
2403 Src = ARef(Op->Src[SrcIndex].Data.Literal.Value & Mask);
2404 }
2405
2406 if (Op->Dest.IsGPR()) {
2407 // When the destination is a GPR, we don't care about garbage in the upper bits.
2408 // Load the full register.
2409 auto Dest = LoadSource_WithOpSize(GPRClass, Op, Op->Dest, GetGPROpSize(), Op->Flags);
2410 Value = Dest;
2411
2412 // Get the bit selection from the src. We need to mask for 8/16-bit, but
2413 // rely on the implicit masking of Lshr for native sizes.
2414 unsigned LshrSize = std::max<uint8_t>(IR::OpSizeToSize(OpSize::i32Bit), Size / 8);
2415 auto BitSelect = (Size == (LshrSize * 8)) ? Src : Src.And(Mask);
2416 auto LshrOpSize = IR::SizeToOpSize(LshrSize);
2417
2418 // OF/SF/AF/PF undefined. ZF must be preserved. We choose to preserve OF/SF
2419 // too since we just use an rmif to insert into CF directly. We could
2420 // optimize perhaps.
2421 //
2422 // Set CF before the action to save a move, except for complements where we
2423 // can reuse the invert.
2424 if (Action != BTAction::BTComplement) {
2425 if (IsNonconstant) {
2426 Value = _Lshr(IR::SizeToOpSize(LshrSize), Value, BitSelect.Ref());
2427 }
2428
2429 SetRFLAG(Value, X86State::RFLAG_CF_RAW_LOC, Src.IsConstant ? Src.C : 0, true);
2430 CFInverted = false;
2431 }
2432
2433 switch (Action) {
2434 case BTAction::BTNone: {
2435 /* Nothing to do */
2436 break;
2437 }
2438
2439 case BTAction::BTClear: {
2440 Dest = _Andn(LshrOpSize, Dest, BitSelect.MaskBit(LshrOpSize).Ref());
2441 StoreResult(GPRClass, Op, Dest, OpSize::iInvalid);
2442 break;
2443 }
2444
2445 case BTAction::BTSet: {
2446 Dest = _Or(LshrOpSize, Dest, BitSelect.MaskBit(LshrOpSize).Ref());

Callers

nothing calls this directly

Calls 10

OpSizeToSizeFunction · 0.85
SizeToOpSizeFunction · 0.85
LoadEffectiveAddressFunction · 0.85
AndMethod · 0.80
RefMethod · 0.80
MaskBitMethod · 0.80
BfeMethod · 0.80
SbfeMethod · 0.80
IsDefinitelyZeroMethod · 0.80
IsGPRMethod · 0.45

Tested by

no test coverage detected