| 1051 | } |
| 1052 | |
| 1053 | void OpDispatchBuilder::MOVSXDOp(OpcodeArgs) { |
| 1054 | // This instruction is a bit special |
| 1055 | // if SrcSize == 2 |
| 1056 | // Then lower 16 bits of destination is written without changing the upper 48 bits |
| 1057 | // else /* Size == 4 */ |
| 1058 | // if REX_WIDENING: |
| 1059 | // Sext(32, Src) |
| 1060 | // else |
| 1061 | // Zext(32, Src) |
| 1062 | // |
| 1063 | auto Size = std::min<IR::OpSize>(OpSize::i32Bit, OpSizeFromSrc(Op)); |
| 1064 | bool Sext = (Size != OpSize::i16Bit) && Op->Flags & FEXCore::X86Tables::DecodeFlags::FLAG_REX_WIDENING; |
| 1065 | |
| 1066 | Ref Src = LoadSource_WithOpSize(GPRClass, Op, Op->Src[0], Size, Op->Flags, {.AllowUpperGarbage = Sext}); |
| 1067 | if (Size == OpSize::i16Bit) { |
| 1068 | // This'll make sure to insert in to the lower 16bits without modifying upper bits |
| 1069 | StoreResult_WithOpSize(GPRClass, Op, Op->Dest, Src, Size, OpSize::iInvalid); |
| 1070 | } else if (Sext) { |
| 1071 | // With REX.W then Sext |
| 1072 | Src = _Sbfe(OpSize::i64Bit, IR::OpSizeAsBits(Size), 0, Src); |
| 1073 | StoreResult(GPRClass, Op, Src, OpSize::iInvalid); |
| 1074 | } else { |
| 1075 | // Without REX.W then Zext (store result implicitly zero extends) |
| 1076 | StoreResult(GPRClass, Op, Src, OpSize::iInvalid); |
| 1077 | } |
| 1078 | } |
| 1079 | |
| 1080 | void OpDispatchBuilder::MOVSXOp(OpcodeArgs) { |
| 1081 | // Load garbage in upper bits, since we're sign extending anyway |
nothing calls this directly
no test coverage detected