| 3714 | } |
| 3715 | |
| 3716 | void OpDispatchBuilder::BSFOp(OpcodeArgs) { |
| 3717 | const auto GPRSize = GetGPROpSize(); |
| 3718 | const auto DstSize = OpSizeFromDst(Op) == OpSize::i16Bit ? OpSize::i16Bit : GPRSize; |
| 3719 | Ref Dest = LoadSource_WithOpSize(GPRClass, Op, Op->Dest, DstSize, Op->Flags, {.AllowUpperGarbage = true}); |
| 3720 | Ref Src = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags, {.AllowUpperGarbage = true}); |
| 3721 | |
| 3722 | // Find the LSB of this source |
| 3723 | auto Result = _FindLSB(OpSizeFromSrc(Op), Src); |
| 3724 | |
| 3725 | // OF, SF, AF, PF, CF all undefined |
| 3726 | // ZF is set to 1 if the source was zero |
| 3727 | SetZ_InvalidateNCV(OpSizeFromSrc(Op), Src); |
| 3728 | |
| 3729 | // If Src was zero then the destination doesn't get modified. |
| 3730 | // |
| 3731 | // Although Intel does not guarantee that semantic, AMD does and Intel |
| 3732 | // hardware satisfies it. We provide the stronger AMD behaviour as |
| 3733 | // applications might rely on that in the wild. |
| 3734 | auto SelectOp = NZCVSelect(GPRSize, {COND_EQ}, Dest, Result); |
| 3735 | StoreResult_WithOpSize(GPRClass, Op, Op->Dest, SelectOp, DstSize, OpSize::iInvalid); |
| 3736 | } |
| 3737 | |
| 3738 | void OpDispatchBuilder::BSROp(OpcodeArgs) { |
| 3739 | const auto GPRSize = GetGPROpSize(); |
nothing calls this directly
no outgoing calls
no test coverage detected