mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-06 09:00:17 +02:00
Merge pull request #3100 from Sonicadvance1/optimize_cmov
OpcodeDispatcher: Optimize cmov
This commit is contained in:
7 files changed
+1341
-1268
No files matched your search
@@ -1061,6 +1061,233 @@ OrderedNode *OpDispatchBuilder::SelectCC(uint8_t OP, OrderedNode *TrueValue, Ord
|
||||
return SrcCond;
|
||||
}
|
||||
|
||||
OrderedNode *OpDispatchBuilder::SelectCCExplicitSize(uint8_t OP, IR::OpSize ResultSize, OrderedNode *TrueValue, OrderedNode *FalseValue) {
|
||||
OrderedNode *SrcCond = nullptr;
|
||||
|
||||
auto ZeroConst = _Constant(0);
|
||||
auto OneConst = _Constant(1);
|
||||
|
||||
switch (OP) {
|
||||
case 0x0: { // JO - Jump if OF == 1
|
||||
auto Flag = GetRFLAG(FEXCore::X86State::RFLAG_OF_LOC);
|
||||
SrcCond = _Select(ResultSize, OpSize::i32Bit, CondClassType{COND_NEQ},
|
||||
Flag, ZeroConst, TrueValue, FalseValue);
|
||||
break;
|
||||
}
|
||||
case 0x1:{ // JNO - Jump if OF == 0
|
||||
auto Flag = GetRFLAG(FEXCore::X86State::RFLAG_OF_LOC);
|
||||
SrcCond = _Select(ResultSize, OpSize::i32Bit, CondClassType{COND_EQ},
|
||||
Flag, ZeroConst, TrueValue, FalseValue);
|
||||
break;
|
||||
}
|
||||
case 0x2: { // JC - Jump if CF == 1
|
||||
auto Flag = GetRFLAG(FEXCore::X86State::RFLAG_CF_LOC);
|
||||
SrcCond = _Select(ResultSize, OpSize::i32Bit, CondClassType{COND_NEQ},
|
||||
Flag, ZeroConst, TrueValue, FalseValue);
|
||||
break;
|
||||
}
|
||||
case 0x3: { // JNC - Jump if CF == 0
|
||||
auto Flag = GetRFLAG(FEXCore::X86State::RFLAG_CF_LOC);
|
||||
SrcCond = _Select(ResultSize, OpSize::i32Bit, CondClassType{COND_EQ},
|
||||
Flag, ZeroConst, TrueValue, FalseValue);
|
||||
break;
|
||||
}
|
||||
case 0x4: { // JE - Jump if ZF == 1
|
||||
auto Flag = GetRFLAG(FEXCore::X86State::RFLAG_ZF_LOC);
|
||||
SrcCond = _Select(ResultSize, OpSize::i32Bit, CondClassType{COND_NEQ},
|
||||
Flag, ZeroConst, TrueValue, FalseValue);
|
||||
break;
|
||||
}
|
||||
case 0x5: { // JNE - Jump if ZF == 0
|
||||
auto Flag = GetRFLAG(FEXCore::X86State::RFLAG_ZF_LOC);
|
||||
SrcCond = _Select(ResultSize, OpSize::i32Bit, CondClassType{COND_EQ},
|
||||
Flag, ZeroConst, TrueValue, FalseValue);
|
||||
break;
|
||||
}
|
||||
case 0x6: { // JNA - Jump if CF == 1 || ZC == 1
|
||||
auto Flag1 = GetRFLAG(FEXCore::X86State::RFLAG_ZF_LOC);
|
||||
auto Flag2 = GetRFLAG(FEXCore::X86State::RFLAG_CF_LOC);
|
||||
auto Check = _Or(OpSize::i32Bit, Flag1, Flag2);
|
||||
SrcCond = _Select(ResultSize, OpSize::i32Bit, CondClassType{COND_EQ},
|
||||
Check, OneConst, TrueValue, FalseValue);
|
||||
break;
|
||||
}
|
||||
case 0x7: { // JA - Jump if CF == 0 && ZF == 0
|
||||
auto Flag1 = GetRFLAG(FEXCore::X86State::RFLAG_ZF_LOC);
|
||||
auto Flag2 = GetRFLAG(FEXCore::X86State::RFLAG_CF_LOC);
|
||||
auto Check = _Or(OpSize::i32Bit, Flag1, Flag2);
|
||||
SrcCond = _Select(ResultSize, OpSize::i32Bit, CondClassType{COND_EQ},
|
||||
Check, ZeroConst, TrueValue, FalseValue);
|
||||
break;
|
||||
}
|
||||
case 0x8: { // JS - Jump if SF == 1
|
||||
auto Flag = GetRFLAG(FEXCore::X86State::RFLAG_SF_LOC);
|
||||
SrcCond = _Select(ResultSize, OpSize::i32Bit, CondClassType{COND_NEQ},
|
||||
Flag, ZeroConst, TrueValue, FalseValue);
|
||||
break;
|
||||
}
|
||||
case 0x9: { // JNS - Jump if SF == 0
|
||||
auto Flag = GetRFLAG(FEXCore::X86State::RFLAG_SF_LOC);
|
||||
SrcCond = _Select(ResultSize, OpSize::i32Bit, CondClassType{COND_EQ},
|
||||
Flag, ZeroConst, TrueValue, FalseValue);
|
||||
break;
|
||||
}
|
||||
case 0xA: { // JP - Jump if PF == 1
|
||||
SrcCond = _Select(ResultSize, OpSize::i32Bit, CondClassType{COND_NEQ}, LoadPF(), ZeroConst, TrueValue, FalseValue);
|
||||
break;
|
||||
}
|
||||
case 0xB: { // JNP - Jump if PF == 0
|
||||
SrcCond = _Select(ResultSize, OpSize::i32Bit, CondClassType{COND_EQ}, LoadPF(), ZeroConst, TrueValue, FalseValue);
|
||||
break;
|
||||
}
|
||||
case 0xC: { // SF <> OF
|
||||
auto Flag1 = GetRFLAG(FEXCore::X86State::RFLAG_SF_LOC);
|
||||
auto Flag2 = GetRFLAG(FEXCore::X86State::RFLAG_OF_LOC);
|
||||
SrcCond = _Select(ResultSize, OpSize::i32Bit, CondClassType{COND_NEQ},
|
||||
Flag1, Flag2, TrueValue, FalseValue);
|
||||
break;
|
||||
}
|
||||
case 0xD: { // SF = OF
|
||||
auto Flag1 = GetRFLAG(FEXCore::X86State::RFLAG_SF_LOC);
|
||||
auto Flag2 = GetRFLAG(FEXCore::X86State::RFLAG_OF_LOC);
|
||||
SrcCond = _Select(ResultSize, OpSize::i32Bit, CondClassType{COND_EQ},
|
||||
Flag1, Flag2, TrueValue, FalseValue);
|
||||
break;
|
||||
}
|
||||
case 0xE: {// ZF = 1 || SF <> OF
|
||||
auto Flag1 = GetRFLAG(FEXCore::X86State::RFLAG_ZF_LOC);
|
||||
auto Flag2 = GetRFLAG(FEXCore::X86State::RFLAG_SF_LOC);
|
||||
auto Flag3 = GetRFLAG(FEXCore::X86State::RFLAG_OF_LOC);
|
||||
|
||||
auto Select1 = _Select(OpSize::i32Bit, OpSize::i32Bit, CondClassType{COND_EQ},
|
||||
Flag1, OneConst, OneConst, ZeroConst);
|
||||
|
||||
auto Select2 = _Select(OpSize::i32Bit, OpSize::i32Bit, CondClassType{COND_NEQ},
|
||||
Flag2, Flag3, OneConst, ZeroConst);
|
||||
|
||||
auto Check = _Or(OpSize::i32Bit, Select1, Select2);
|
||||
SrcCond = _Select(ResultSize, OpSize::i32Bit, CondClassType{COND_EQ},
|
||||
Check, OneConst, TrueValue, FalseValue);
|
||||
break;
|
||||
}
|
||||
case 0xF: {// ZF = 0 && SF = OF
|
||||
auto Flag1 = GetRFLAG(FEXCore::X86State::RFLAG_ZF_LOC);
|
||||
auto Flag2 = GetRFLAG(FEXCore::X86State::RFLAG_SF_LOC);
|
||||
auto Flag3 = GetRFLAG(FEXCore::X86State::RFLAG_OF_LOC);
|
||||
|
||||
auto Select1 = _Select(OpSize::i32Bit, OpSize::i32Bit, CondClassType{COND_EQ},
|
||||
Flag1, ZeroConst, OneConst, ZeroConst);
|
||||
|
||||
auto Select2 = _Select(OpSize::i32Bit, OpSize::i32Bit, CondClassType{COND_EQ},
|
||||
Flag2, Flag3, OneConst, ZeroConst);
|
||||
|
||||
auto Check = _And(OpSize::i32Bit, Select1, Select2);
|
||||
SrcCond = _Select(ResultSize, OpSize::i32Bit, CondClassType{COND_EQ},
|
||||
Check, OneConst, TrueValue, FalseValue);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
LOGMAN_MSG_A_FMT("Unknown CC Op: 0x{:x}\n", OP);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Try folding the flags generation in the select op
|
||||
if (flagsOp == SelectionFlag::CMP) {
|
||||
switch(OP) {
|
||||
// SGT
|
||||
case 0xF: SrcCond = _Select(ResultSize, IR::SizeToOpSize(flagsOpSize), CondClassType{COND_SGT}, flagsOpDestSigned, flagsOpSrcSigned, TrueValue, FalseValue); break;
|
||||
// SLE
|
||||
case 0xE: SrcCond = _Select(ResultSize, IR::SizeToOpSize(flagsOpSize), CondClassType{COND_SLE}, flagsOpDestSigned, flagsOpSrcSigned, TrueValue, FalseValue); break;
|
||||
// SGE
|
||||
case 0xD: SrcCond = _Select(ResultSize, IR::SizeToOpSize(flagsOpSize), CondClassType{COND_SGE}, flagsOpDestSigned, flagsOpSrcSigned, TrueValue, FalseValue); break;
|
||||
// SL
|
||||
case 0xC: SrcCond = _Select(ResultSize, IR::SizeToOpSize(flagsOpSize), CondClassType{COND_SLT}, flagsOpDestSigned, flagsOpSrcSigned, TrueValue, FalseValue); break;
|
||||
|
||||
// not sign
|
||||
//case 0x99: SrcCond = _Select(FEXCore::IR::COND_, flagsOpDestSigned, flagsOpSrcSigned, TrueValue, FalseValue, flagsOpSize); break;
|
||||
// sign
|
||||
//case 0x98: SrcCond = _Select(FEXCore::IR::COND_, flagsOpDestSigned, flagsOpSrcSigned, TrueValue, FalseValue, flagsOpSize); break;
|
||||
|
||||
// UABove
|
||||
case 0x7: SrcCond = _Select(ResultSize, IR::SizeToOpSize(flagsOpSize), CondClassType{COND_UGT}, flagsOpDest, flagsOpSrc, TrueValue, FalseValue); break;
|
||||
// UBE
|
||||
case 0x6: SrcCond = _Select(ResultSize, IR::SizeToOpSize(flagsOpSize), CondClassType{COND_ULE}, flagsOpDest, flagsOpSrc, TrueValue, FalseValue); break;
|
||||
// NE
|
||||
case 0x5: SrcCond = _Select(ResultSize, IR::SizeToOpSize(flagsOpSize), CondClassType{COND_NEQ}, flagsOpDest, flagsOpSrc, TrueValue, FalseValue); break;
|
||||
// EQ/Zero
|
||||
case 0x4: SrcCond = _Select(ResultSize, IR::SizeToOpSize(flagsOpSize), CondClassType{COND_EQ}, flagsOpDest, flagsOpSrc, TrueValue, FalseValue); break;
|
||||
// UAE
|
||||
case 0x3: SrcCond = _Select(ResultSize, IR::SizeToOpSize(flagsOpSize), CondClassType{COND_UGE}, flagsOpDest, flagsOpSrc, TrueValue, FalseValue); break;
|
||||
// UBelow
|
||||
case 0x2: SrcCond = _Select(ResultSize, IR::SizeToOpSize(flagsOpSize), CondClassType{COND_ULT}, flagsOpDest, flagsOpSrc, TrueValue, FalseValue); break;
|
||||
|
||||
//default: printf("Missed Condition %04X OP_CMP\n", OP); break;
|
||||
}
|
||||
}
|
||||
else if (flagsOp == SelectionFlag::AND) {
|
||||
switch(OP) {
|
||||
case 0x4: SrcCond = _Select(ResultSize, IR::SizeToOpSize(flagsOpSize), CondClassType{COND_EQ}, flagsOpDest, ZeroConst, TrueValue, FalseValue); break;
|
||||
case 0x5: SrcCond = _Select(ResultSize, IR::SizeToOpSize(flagsOpSize), CondClassType{COND_NEQ}, flagsOpDest, ZeroConst, TrueValue, FalseValue); break;
|
||||
//default: printf("Missed Condition %04X OP_AND\n", OP); break;
|
||||
}
|
||||
} else if (flagsOp == SelectionFlag::FCMP) {
|
||||
/*
|
||||
x86:ZCP
|
||||
unordered { 11 1 }
|
||||
greater { 00 0 }
|
||||
less { 01 0 }
|
||||
equal { 10 0 }
|
||||
aarch64: NZCV
|
||||
unordered { 0 01 1 }
|
||||
greater { 0 01 0 }
|
||||
less { 1 00 0 }
|
||||
equal { 0 11 0 }
|
||||
*/
|
||||
|
||||
/*
|
||||
eq = 0, // Z set Equal.
|
||||
ne = 1, // Z clear Not equal.
|
||||
cs = 2, // C set Carry set.
|
||||
cc = 3, // C clear Carry clear.
|
||||
mi = 4, // N set Negative.
|
||||
pl = 5, // N clear Positive or zero.
|
||||
vs = 6, // V set Overflow.
|
||||
vc = 7, // V clear No overflow.
|
||||
hi = 8, // C set, Z clear Unsigned higher.
|
||||
ls = 9, // C clear or Z set Unsigned lower or same.
|
||||
ge = 10, // N == V Greater or equal.
|
||||
lt = 11, // N != V Less than.
|
||||
gt = 12, // Z clear, N == V Greater than.
|
||||
le = 13, // Z set or N != V Less then or equal
|
||||
*/
|
||||
switch(OP) {
|
||||
case 0x2: // CF == 1 // less or unordered // N==1 OR V==1 // lt
|
||||
SrcCond = _Select(ResultSize, IR::SizeToOpSize(flagsOpSize), CondClassType{COND_FLU}, flagsOpDest, flagsOpSrc, TrueValue, FalseValue);
|
||||
break;
|
||||
case 0x3: // CF == 0 // greater or equal (and not unordered) // N==V // ge
|
||||
SrcCond = _Select(ResultSize, IR::SizeToOpSize(flagsOpSize), CondClassType{COND_FGE}, flagsOpDest, flagsOpSrc, TrueValue, FalseValue);
|
||||
break;
|
||||
case 0x6: // CF == 1 || ZF == 1 // less or equal or unordered // Z==1 OR N!=V // le
|
||||
SrcCond = _Select(ResultSize, IR::SizeToOpSize(flagsOpSize), CondClassType{COND_FLEU}, flagsOpDest, flagsOpSrc, TrueValue, FalseValue);
|
||||
break;
|
||||
case 0x7: // CF == 0 && ZF == 0 // greater (and not unordered) // C==1 AND V=0 // hi
|
||||
SrcCond = _Select(ResultSize, IR::SizeToOpSize(flagsOpSize), CondClassType{COND_FGT}, flagsOpDest, flagsOpSrc, TrueValue, FalseValue);
|
||||
break;
|
||||
case 0xA: // PF = 1 // unordered // V==1 // vs
|
||||
SrcCond = _Select(ResultSize, IR::SizeToOpSize(flagsOpSize), CondClassType{COND_FU}, flagsOpDest, flagsOpSrc, TrueValue, FalseValue);
|
||||
break;
|
||||
case 0xB: // PF = 0 // not unordered // V==0 // vc
|
||||
SrcCond = _Select(ResultSize, IR::SizeToOpSize(flagsOpSize), CondClassType{COND_FNU}, flagsOpDest, flagsOpSrc, TrueValue, FalseValue);
|
||||
break;
|
||||
default:
|
||||
// TODO: Add more optimized cases
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return SrcCond;
|
||||
}
|
||||
|
||||
void OpDispatchBuilder::SETccOp(OpcodeArgs) {
|
||||
// Calculate flags early.
|
||||
CalculateDeferredFlags();
|
||||
@@ -1074,13 +1301,22 @@ void OpDispatchBuilder::SETccOp(OpcodeArgs) {
|
||||
}
|
||||
|
||||
void OpDispatchBuilder::CMOVOp(OpcodeArgs) {
|
||||
const uint8_t GPRSize = CTX->GetGPRSize();
|
||||
|
||||
// Calculate flags early.
|
||||
CalculateDeferredFlags();
|
||||
|
||||
OrderedNode *Src = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags, -1);
|
||||
OrderedNode *Dest = LoadSource(GPRClass, Op, Op->Dest, Op->Flags, -1);
|
||||
// Destination is always a GPR.
|
||||
OrderedNode *Dest = LoadSource_WithOpSize(GPRClass, Op, Op->Dest, GPRSize, Op->Flags, -1);
|
||||
OrderedNode *Src{};
|
||||
if (Op->Src[0].IsGPR()) {
|
||||
Src = LoadSource_WithOpSize(GPRClass, Op, Op->Src[0], GPRSize, Op->Flags, -1);
|
||||
}
|
||||
else {
|
||||
Src = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags, -1);
|
||||
}
|
||||
|
||||
auto SrcCond = SelectCC(Op->OP & 0xF, Src, Dest);
|
||||
auto SrcCond = SelectCCExplicitSize(Op->OP & 0xF, IR::SizeToOpSize(std::max<uint8_t>(4u, GetSrcSize(Op))), Src, Dest);
|
||||
|
||||
StoreResult(GPRClass, Op, SrcCond, -1);
|
||||
}
|
||||
|
||||
@@ -869,8 +869,9 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
OrderedNode* CachedNZCV = {};
|
||||
uint32_t PossiblySetNZCVBits = 0;
|
||||
OrderedNode* CachedNZCV{};
|
||||
bool NZCVDirty{};
|
||||
uint32_t PossiblySetNZCVBits{};
|
||||
|
||||
fextl::map<uint64_t, JumpTargetInfo> JumpTargets;
|
||||
bool HandledLock{false};
|
||||
@@ -1115,11 +1116,13 @@ private:
|
||||
|
||||
void SetNZCV(OrderedNode *Value) {
|
||||
CachedNZCV = Value;
|
||||
NZCVDirty = true;
|
||||
}
|
||||
|
||||
void ZeroNZCV() {
|
||||
CachedNZCV = _Constant(0);
|
||||
PossiblySetNZCVBits = 0;
|
||||
NZCVDirty = true;
|
||||
}
|
||||
|
||||
void ZeroCV() {
|
||||
@@ -1152,6 +1155,7 @@ private:
|
||||
// Mask off just the N bit, which now equals the sign bit
|
||||
CachedNZCV = _And(OpSize::i32Bit, Shifted, _Constant(1u << NBit));
|
||||
PossiblySetNZCVBits = (1u << NBit);
|
||||
NZCVDirty = true;
|
||||
}
|
||||
|
||||
void SetNZ_ZeroCV(unsigned SrcSize, OrderedNode *Res) {
|
||||
@@ -1160,6 +1164,7 @@ private:
|
||||
if (SrcSize >= 4) {
|
||||
CachedNZCV = _TestNZ(SrcSize, Res);
|
||||
PossiblySetNZCVBits = (1u << 31) | (1u << 30);
|
||||
NZCVDirty = true;
|
||||
} else {
|
||||
// N
|
||||
SetN_ZeroZCV(SrcSize, Res);
|
||||
@@ -1274,7 +1279,9 @@ private:
|
||||
CachedIndexedNamedVectorConstants.clear();
|
||||
}
|
||||
|
||||
// TODO: SelectCC is duplicated SelectCCExplicitSize. Should get removed once all users are removed.
|
||||
OrderedNode *SelectCC(uint8_t OP, OrderedNode *TrueValue, OrderedNode *FalseValue);
|
||||
OrderedNode *SelectCCExplicitSize(uint8_t OP, IR::OpSize ResultSize, OrderedNode *TrueValue, OrderedNode *FalseValue);
|
||||
|
||||
/**
|
||||
* @name Deferred RFLAG calculation and generation.
|
||||
|
||||
@@ -272,10 +272,11 @@ void OpDispatchBuilder::CalculateAF(OpSize OpSize, OrderedNode *Res, OrderedNode
|
||||
void OpDispatchBuilder::CalculateDeferredFlags(uint32_t FlagsToCalculateMask) {
|
||||
if (CurrentDeferredFlags.Type == FlagsGenerationType::TYPE_NONE) {
|
||||
// Nothing to do
|
||||
if (CachedNZCV)
|
||||
if (NZCVDirty && CachedNZCV)
|
||||
_StoreFlag(CachedNZCV, FEXCore::X86State::RFLAG_NZCV_LOC);
|
||||
|
||||
CachedNZCV = nullptr;
|
||||
NZCVDirty = false;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -459,10 +460,11 @@ void OpDispatchBuilder::CalculateDeferredFlags(uint32_t FlagsToCalculateMask) {
|
||||
// Done calculating
|
||||
CurrentDeferredFlags.Type = FlagsGenerationType::TYPE_NONE;
|
||||
|
||||
if (CachedNZCV)
|
||||
if (NZCVDirty && CachedNZCV)
|
||||
_StoreFlag(CachedNZCV, FEXCore::X86State::RFLAG_NZCV_LOC);
|
||||
|
||||
CachedNZCV = nullptr;
|
||||
NZCVDirty = false;
|
||||
}
|
||||
|
||||
void OpDispatchBuilder::CalculateFlags_ADC(uint8_t SrcSize, OrderedNode *Res, OrderedNode *Src1, OrderedNode *Src2, OrderedNode *CF) {
|
||||
|
||||
@@ -3100,7 +3100,7 @@
|
||||
"ExpectedArm64ASM": []
|
||||
},
|
||||
"pushf": {
|
||||
"ExpectedInstructionCount": 43,
|
||||
"ExpectedInstructionCount": 42,
|
||||
"Optimal": "No",
|
||||
"Comment": "0x9c",
|
||||
"ExpectedArm64ASM": [
|
||||
@@ -3142,15 +3142,14 @@
|
||||
"orr x21, x21, x22, lsl #20",
|
||||
"ldrb w22, [x28, #725]",
|
||||
"orr x21, x21, x22, lsl #21",
|
||||
"and x22, x20, #0xc0000000",
|
||||
"orr x21, x21, x22, lsr #24",
|
||||
"orr x21, x21, #0x2",
|
||||
"str x21, [x8, #-8]!",
|
||||
"str w20, [x28, #728]"
|
||||
"and x20, x20, #0xc0000000",
|
||||
"orr x20, x21, x20, lsr #24",
|
||||
"orr x20, x20, #0x2",
|
||||
"str x20, [x8, #-8]!"
|
||||
]
|
||||
},
|
||||
"pushfq": {
|
||||
"ExpectedInstructionCount": 43,
|
||||
"ExpectedInstructionCount": 42,
|
||||
"Optimal": "No",
|
||||
"Comment": "0x9c",
|
||||
"ExpectedArm64ASM": [
|
||||
@@ -3192,11 +3191,10 @@
|
||||
"orr x21, x21, x22, lsl #20",
|
||||
"ldrb w22, [x28, #725]",
|
||||
"orr x21, x21, x22, lsl #21",
|
||||
"and x22, x20, #0xc0000000",
|
||||
"orr x21, x21, x22, lsr #24",
|
||||
"orr x21, x21, #0x2",
|
||||
"str x21, [x8, #-8]!",
|
||||
"str w20, [x28, #728]"
|
||||
"and x20, x20, #0xc0000000",
|
||||
"orr x20, x21, x20, lsr #24",
|
||||
"orr x20, x20, #0x2",
|
||||
"str x20, [x8, #-8]!"
|
||||
]
|
||||
},
|
||||
"popf": {
|
||||
@@ -3273,7 +3271,7 @@
|
||||
]
|
||||
},
|
||||
"lahf": {
|
||||
"ExpectedInstructionCount": 19,
|
||||
"ExpectedInstructionCount": 18,
|
||||
"Optimal": "Yes",
|
||||
"Comment": "0x9f",
|
||||
"ExpectedArm64ASM": [
|
||||
@@ -3291,11 +3289,10 @@
|
||||
"eor w22, w22, w23",
|
||||
"ubfx w22, w22, #4, #1",
|
||||
"orr x21, x21, x22, lsl #4",
|
||||
"and x22, x20, #0xc0000000",
|
||||
"orr x21, x21, x22, lsr #24",
|
||||
"orr x21, x21, #0x2",
|
||||
"bfi x4, x21, #8, #8",
|
||||
"str w20, [x28, #728]"
|
||||
"and x20, x20, #0xc0000000",
|
||||
"orr x20, x21, x20, lsr #24",
|
||||
"orr x20, x20, #0x2",
|
||||
"bfi x4, x20, #8, #8"
|
||||
]
|
||||
},
|
||||
"db 0x48, 0xa1; dq 0x00000000e0000008": {
|
||||
@@ -3736,12 +3733,12 @@
|
||||
"and w21, w21, w22",
|
||||
"ubfx w21, w21, #7, #1",
|
||||
"orr w21, w24, w21, lsl #28",
|
||||
"str w21, [x28, #728]",
|
||||
"sub x5, x5, #0x1 (1)",
|
||||
"add x11, x11, x20",
|
||||
"add x10, x10, x20",
|
||||
"ubfx w22, w21, #30, #1",
|
||||
"str w21, [x28, #728]",
|
||||
"cbnz w22, #-0x68"
|
||||
"ubfx w21, w21, #30, #1",
|
||||
"cbnz w21, #-0x68"
|
||||
]
|
||||
},
|
||||
"repz cmpsw": {
|
||||
@@ -3775,12 +3772,12 @@
|
||||
"and w21, w21, w22",
|
||||
"ubfx w21, w21, #15, #1",
|
||||
"orr w21, w24, w21, lsl #28",
|
||||
"str w21, [x28, #728]",
|
||||
"sub x5, x5, #0x1 (1)",
|
||||
"add x11, x11, x20",
|
||||
"add x10, x10, x20",
|
||||
"ubfx w22, w21, #30, #1",
|
||||
"str w21, [x28, #728]",
|
||||
"cbnz w22, #-0x68"
|
||||
"ubfx w21, w21, #30, #1",
|
||||
"cbnz w21, #-0x68"
|
||||
]
|
||||
},
|
||||
"repz cmpsd": {
|
||||
@@ -3803,12 +3800,12 @@
|
||||
"cmp w22, w21",
|
||||
"mrs x21, nzcv",
|
||||
"eor w21, w21, #0x20000000",
|
||||
"str w21, [x28, #728]",
|
||||
"sub x5, x5, #0x1 (1)",
|
||||
"add x11, x11, x20",
|
||||
"add x10, x10, x20",
|
||||
"ubfx w22, w21, #30, #1",
|
||||
"str w21, [x28, #728]",
|
||||
"cbnz w22, #-0x3c"
|
||||
"ubfx w21, w21, #30, #1",
|
||||
"cbnz w21, #-0x3c"
|
||||
]
|
||||
},
|
||||
"repz cmpsq": {
|
||||
@@ -3831,12 +3828,12 @@
|
||||
"cmp x22, x21",
|
||||
"mrs x21, nzcv",
|
||||
"eor w21, w21, #0x20000000",
|
||||
"str w21, [x28, #728]",
|
||||
"sub x5, x5, #0x1 (1)",
|
||||
"add x11, x11, x20",
|
||||
"add x10, x10, x20",
|
||||
"ubfx w22, w21, #30, #1",
|
||||
"str w21, [x28, #728]",
|
||||
"cbnz w22, #-0x3c"
|
||||
"ubfx w21, w21, #30, #1",
|
||||
"cbnz w21, #-0x3c"
|
||||
]
|
||||
},
|
||||
"repnz cmpsb": {
|
||||
@@ -3870,12 +3867,12 @@
|
||||
"and w21, w21, w22",
|
||||
"ubfx w21, w21, #7, #1",
|
||||
"orr w21, w24, w21, lsl #28",
|
||||
"str w21, [x28, #728]",
|
||||
"sub x5, x5, #0x1 (1)",
|
||||
"add x11, x11, x20",
|
||||
"add x10, x10, x20",
|
||||
"ubfx w22, w21, #30, #1",
|
||||
"str w21, [x28, #728]",
|
||||
"cbz w22, #-0x68"
|
||||
"ubfx w21, w21, #30, #1",
|
||||
"cbz w21, #-0x68"
|
||||
]
|
||||
},
|
||||
"repnz cmpsw": {
|
||||
@@ -3909,12 +3906,12 @@
|
||||
"and w21, w21, w22",
|
||||
"ubfx w21, w21, #15, #1",
|
||||
"orr w21, w24, w21, lsl #28",
|
||||
"str w21, [x28, #728]",
|
||||
"sub x5, x5, #0x1 (1)",
|
||||
"add x11, x11, x20",
|
||||
"add x10, x10, x20",
|
||||
"ubfx w22, w21, #30, #1",
|
||||
"str w21, [x28, #728]",
|
||||
"cbz w22, #-0x68"
|
||||
"ubfx w21, w21, #30, #1",
|
||||
"cbz w21, #-0x68"
|
||||
]
|
||||
},
|
||||
"repnz cmpsd": {
|
||||
@@ -3937,12 +3934,12 @@
|
||||
"cmp w22, w21",
|
||||
"mrs x21, nzcv",
|
||||
"eor w21, w21, #0x20000000",
|
||||
"str w21, [x28, #728]",
|
||||
"sub x5, x5, #0x1 (1)",
|
||||
"add x11, x11, x20",
|
||||
"add x10, x10, x20",
|
||||
"ubfx w22, w21, #30, #1",
|
||||
"str w21, [x28, #728]",
|
||||
"cbz w22, #-0x3c"
|
||||
"ubfx w21, w21, #30, #1",
|
||||
"cbz w21, #-0x3c"
|
||||
]
|
||||
},
|
||||
"repnz cmpsq": {
|
||||
@@ -3965,12 +3962,12 @@
|
||||
"cmp x22, x21",
|
||||
"mrs x21, nzcv",
|
||||
"eor w21, w21, #0x20000000",
|
||||
"str w21, [x28, #728]",
|
||||
"sub x5, x5, #0x1 (1)",
|
||||
"add x11, x11, x20",
|
||||
"add x10, x10, x20",
|
||||
"ubfx w22, w21, #30, #1",
|
||||
"str w21, [x28, #728]",
|
||||
"cbz w22, #-0x3c"
|
||||
"ubfx w21, w21, #30, #1",
|
||||
"cbz w21, #-0x3c"
|
||||
]
|
||||
},
|
||||
"test al, 1": {
|
||||
@@ -4460,11 +4457,11 @@
|
||||
"and w21, w22, w21",
|
||||
"ubfx w21, w21, #7, #1",
|
||||
"orr w21, w24, w21, lsl #28",
|
||||
"str w21, [x28, #728]",
|
||||
"sub x5, x5, #0x1 (1)",
|
||||
"add x11, x11, x20",
|
||||
"ubfx w22, w21, #30, #1",
|
||||
"str w21, [x28, #728]",
|
||||
"cbnz w22, #-0x64"
|
||||
"ubfx w21, w21, #30, #1",
|
||||
"cbnz w21, #-0x64"
|
||||
]
|
||||
},
|
||||
"repz scasw": {
|
||||
@@ -4498,11 +4495,11 @@
|
||||
"and w21, w22, w21",
|
||||
"ubfx w21, w21, #15, #1",
|
||||
"orr w21, w24, w21, lsl #28",
|
||||
"str w21, [x28, #728]",
|
||||
"sub x5, x5, #0x1 (1)",
|
||||
"add x11, x11, x20",
|
||||
"ubfx w22, w21, #30, #1",
|
||||
"str w21, [x28, #728]",
|
||||
"cbnz w22, #-0x64"
|
||||
"ubfx w21, w21, #30, #1",
|
||||
"cbnz w21, #-0x64"
|
||||
]
|
||||
},
|
||||
"repz scasd": {
|
||||
@@ -4525,11 +4522,11 @@
|
||||
"cmp w21, w22",
|
||||
"mrs x21, nzcv",
|
||||
"eor w21, w21, #0x20000000",
|
||||
"str w21, [x28, #728]",
|
||||
"sub x5, x5, #0x1 (1)",
|
||||
"add x11, x11, x20",
|
||||
"ubfx w22, w21, #30, #1",
|
||||
"str w21, [x28, #728]",
|
||||
"cbnz w22, #-0x38"
|
||||
"ubfx w21, w21, #30, #1",
|
||||
"cbnz w21, #-0x38"
|
||||
]
|
||||
},
|
||||
"repz scasq": {
|
||||
@@ -4551,11 +4548,11 @@
|
||||
"cmp x4, x21",
|
||||
"mrs x21, nzcv",
|
||||
"eor w21, w21, #0x20000000",
|
||||
"str w21, [x28, #728]",
|
||||
"sub x5, x5, #0x1 (1)",
|
||||
"add x11, x11, x20",
|
||||
"ubfx w22, w21, #30, #1",
|
||||
"str w21, [x28, #728]",
|
||||
"cbnz w22, #-0x34"
|
||||
"ubfx w21, w21, #30, #1",
|
||||
"cbnz w21, #-0x34"
|
||||
]
|
||||
},
|
||||
"repnz scasb": {
|
||||
@@ -4589,11 +4586,11 @@
|
||||
"and w21, w22, w21",
|
||||
"ubfx w21, w21, #7, #1",
|
||||
"orr w21, w24, w21, lsl #28",
|
||||
"str w21, [x28, #728]",
|
||||
"sub x5, x5, #0x1 (1)",
|
||||
"add x11, x11, x20",
|
||||
"ubfx w22, w21, #30, #1",
|
||||
"str w21, [x28, #728]",
|
||||
"cbz w22, #-0x64"
|
||||
"ubfx w21, w21, #30, #1",
|
||||
"cbz w21, #-0x64"
|
||||
]
|
||||
},
|
||||
"repnz scasw": {
|
||||
@@ -4627,11 +4624,11 @@
|
||||
"and w21, w22, w21",
|
||||
"ubfx w21, w21, #15, #1",
|
||||
"orr w21, w24, w21, lsl #28",
|
||||
"str w21, [x28, #728]",
|
||||
"sub x5, x5, #0x1 (1)",
|
||||
"add x11, x11, x20",
|
||||
"ubfx w22, w21, #30, #1",
|
||||
"str w21, [x28, #728]",
|
||||
"cbz w22, #-0x64"
|
||||
"ubfx w21, w21, #30, #1",
|
||||
"cbz w21, #-0x64"
|
||||
]
|
||||
},
|
||||
"repnz scasd": {
|
||||
@@ -4654,11 +4651,11 @@
|
||||
"cmp w21, w22",
|
||||
"mrs x21, nzcv",
|
||||
"eor w21, w21, #0x20000000",
|
||||
"str w21, [x28, #728]",
|
||||
"sub x5, x5, #0x1 (1)",
|
||||
"add x11, x11, x20",
|
||||
"ubfx w22, w21, #30, #1",
|
||||
"str w21, [x28, #728]",
|
||||
"cbz w22, #-0x38"
|
||||
"ubfx w21, w21, #30, #1",
|
||||
"cbz w21, #-0x38"
|
||||
]
|
||||
},
|
||||
"repnz scasq": {
|
||||
@@ -4680,11 +4677,11 @@
|
||||
"cmp x4, x21",
|
||||
"mrs x21, nzcv",
|
||||
"eor w21, w21, #0x20000000",
|
||||
"str w21, [x28, #728]",
|
||||
"sub x5, x5, #0x1 (1)",
|
||||
"add x11, x11, x20",
|
||||
"ubfx w22, w21, #30, #1",
|
||||
"str w21, [x28, #728]",
|
||||
"cbz w22, #-0x34"
|
||||
"ubfx w21, w21, #30, #1",
|
||||
"cbz w21, #-0x34"
|
||||
]
|
||||
},
|
||||
"mov al, 0xff": {
|
||||
|
||||
@@ -563,18 +563,17 @@
|
||||
]
|
||||
},
|
||||
"salc": {
|
||||
"ExpectedInstructionCount": 8,
|
||||
"ExpectedInstructionCount": 7,
|
||||
"Optimal": "No",
|
||||
"Comment": "0xd6",
|
||||
"ExpectedArm64ASM": [
|
||||
"uxtb w20, w4",
|
||||
"ldr w21, [x28, #728]",
|
||||
"ubfx w22, w21, #29, #1",
|
||||
"add w20, w20, w22",
|
||||
"uxtb w22, w4",
|
||||
"sub w20, w22, w20",
|
||||
"bfxil w4, w20, #0, #8",
|
||||
"str w21, [x28, #728]"
|
||||
"ubfx w21, w21, #29, #1",
|
||||
"add w20, w20, w21",
|
||||
"uxtb w21, w4",
|
||||
"sub w20, w21, w20",
|
||||
"bfxil w4, w20, #0, #8"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user