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

Method ADXOp

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

Source from the content-addressed store, hash-verified

1921}
1922
1923void OpDispatchBuilder::ADXOp(OpcodeArgs) {
1924 const auto OpSize = OpSizeFromSrc(Op);
1925
1926 // Only 32/64-bit anyway so allow garbage, we use 32-bit ops.
1927 auto* Src = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags, {.AllowUpperGarbage = true});
1928 auto* Before = LoadSource(GPRClass, Op, Op->Dest, Op->Flags, {.AllowUpperGarbage = true});
1929
1930 // Handles ADCX and ADOX
1931 const bool IsADCX = Op->OP == 0x1F6;
1932 auto Zero = Constant(0);
1933
1934 // Before we go trashing NZCV, save the current NZCV state.
1935 Ref OldNZCV = GetNZCV();
1936
1937 // We want to use arm64 adc. For ADOX, copy the overflow flag into CF. For
1938 // ADCX, we just rectify the carry.
1939 if (IsADCX) {
1940 RectifyCarryInvert(false);
1941 } else {
1942 // If overflow, 0 - 0 sets carry. Else, forces carry to 0.
1943 _CondSubNZCV(OpSize::i32Bit, Zero, Zero, {COND_FU}, 0x0 /* nzcv */);
1944 }
1945
1946 // Do the actual add.
1947 HandleNZCV_RMW();
1948 auto Result = _AdcWithFlags(OpSize, Src, Before);
1949 StoreResult(GPRClass, Op, Result, OpSize::iInvalid);
1950
1951 // Now restore all flags except the one we're updating.
1952 if (CTX->HostFeatures.SupportsFlagM) {
1953 // For ADOX, we need to copy the new carry into the overflow flag. If carry is clear (ULT with uninverted
1954 // carry), 0 - 0 clears overflow. Else, force overflow on.
1955 if (!IsADCX) {
1956 _CondSubNZCV(OpSize::i32Bit, Zero, Zero, {COND_ULT}, 0x1 /* nzcV */);
1957 }
1958
1959 _RmifNZCV(OldNZCV, 28, IsADCX ? 0xd /* NzcV */ : 0xe /* NZCv */);
1960 } else {
1961 // For either operation, insert the new flag into the old NZCV.
1962 bool SavedCFInvert = CFInverted;
1963 CFInverted = false;
1964 Ref OutputCF = GetRFLAG(X86State::RFLAG_CF_RAW_LOC, IsADCX);
1965 CFInverted = IsADCX ? true : SavedCFInvert;
1966
1967 Ref NewNZCV = _Bfi(OpSize::i32Bit, 1, IsADCX ? 29 : 28, OldNZCV, OutputCF);
1968 SetNZCV(NewNZCV);
1969 }
1970}
1971
1972void OpDispatchBuilder::RCROp1Bit(OpcodeArgs) {
1973 // Calculate flags early.

Callers

nothing calls this directly

Calls

no outgoing calls

Tested by

no test coverage detected