From 0ec6e40a67c935efc7d4dbdb15c522bca994c53d Mon Sep 17 00:00:00 2001 From: Scott Mansell Date: Thu, 26 Nov 2020 12:41:37 +1300 Subject: [PATCH] IR: Remove 8/16bit ROR Opcode Dispatcher will now explictly emualte them --- .../Core/Interpreter/InterpreterCore.cpp | 10 +--- .../Interface/Core/JIT/Arm64/ALUOps.cpp | 30 +----------- .../Interface/Core/JIT/x86_64/ALUOps.cpp | 30 +++--------- .../Interface/Core/OpcodeDispatcher.cpp | 46 ++++++++++++++----- 4 files changed, 43 insertions(+), 73 deletions(-) diff --git a/External/FEXCore/Source/Interface/Core/Interpreter/InterpreterCore.cpp b/External/FEXCore/Source/Interface/Core/Interpreter/InterpreterCore.cpp index eb0f5abe1..946ef7a0d 100644 --- a/External/FEXCore/Source/Interface/Core/Interpreter/InterpreterCore.cpp +++ b/External/FEXCore/Source/Interface/Core/Interpreter/InterpreterCore.cpp @@ -1170,12 +1170,6 @@ void InterpreterCore::ExecuteCode(FEXCore::Core::InternalThreadState *Thread) { }; switch (OpSize) { - case 1: - GD = Ror(static_cast(Src1), static_cast(Src2)); - break; - case 2: - GD = Ror(static_cast(Src1), static_cast(Src2)); - break; case 4: GD = Ror(static_cast(Src1), static_cast(Src2)); break; @@ -1642,7 +1636,7 @@ void InterpreterCore::ExecuteCode(FEXCore::Core::InternalThreadState *Thread) { } case IR::OP_SELECT: { auto Op = IROp->C(); - + uint64_t Src1 = *GetSrc(SSAData, Op->Header.Args[0]); uint64_t Src2 = *GetSrc(SSAData, Op->Header.Args[1]); @@ -1656,7 +1650,7 @@ void InterpreterCore::ExecuteCode(FEXCore::Core::InternalThreadState *Thread) { ArgTrue = *GetSrc(SSAData, Op->Header.Args[2]); ArgFalse = *GetSrc(SSAData, Op->Header.Args[3]); } - + bool CompResult; if (Op->CompareSize == 4) diff --git a/External/FEXCore/Source/Interface/Core/JIT/Arm64/ALUOps.cpp b/External/FEXCore/Source/Interface/Core/JIT/Arm64/ALUOps.cpp index 0c1f40d66..3c774dc7f 100644 --- a/External/FEXCore/Source/Interface/Core/JIT/Arm64/ALUOps.cpp +++ b/External/FEXCore/Source/Interface/Core/JIT/Arm64/ALUOps.cpp @@ -561,20 +561,6 @@ DEF_OP(Ror) { uint64_t Const; if (IsInlineConstant(Op->Header.Args[1], &Const)) { switch (OpSize) { - case 1: { - mov(TMP1.W(), GetReg(Op->Header.Args[0].ID())); - bfi(TMP1.W(), GetReg(Op->Header.Args[0].ID()), 8, 8); - bfi(TMP1.W(), GetReg(Op->Header.Args[0].ID()), 16, 8); - bfi(TMP1.W(), GetReg(Op->Header.Args[0].ID()), 24, 8); - ror(GetReg(Node), TMP1.W(), (unsigned int)Const); - break; - } - case 2: { - mov(TMP1.W(), GetReg(Op->Header.Args[0].ID())); - bfi(TMP1.W(), GetReg(Op->Header.Args[0].ID()), 16, 16); - ror(GetReg(Node), TMP1.W(), (unsigned int)Const); - break; - } case 4: { ror(GetReg(Node), GetReg(Op->Header.Args[0].ID()), (unsigned int)Const); break; @@ -588,20 +574,6 @@ DEF_OP(Ror) { } } else { switch (OpSize) { - case 1: { - mov(TMP1.W(), GetReg(Op->Header.Args[0].ID())); - bfi(TMP1.W(), GetReg(Op->Header.Args[0].ID()), 8, 8); - bfi(TMP1.W(), GetReg(Op->Header.Args[0].ID()), 16, 8); - bfi(TMP1.W(), GetReg(Op->Header.Args[0].ID()), 24, 8); - rorv(GetReg(Node), TMP1.W(), GetReg(Op->Header.Args[1].ID())); - break; - } - case 2: { - mov(TMP1.W(), GetReg(Op->Header.Args[0].ID())); - bfi(TMP1.W(), GetReg(Op->Header.Args[0].ID()), 16, 16); - rorv(GetReg(Node), TMP1.W(), GetReg(Op->Header.Args[1].ID())); - break; - } case 4: { rorv(GetReg(Node), GetReg(Op->Header.Args[0].ID()), GetReg(Op->Header.Args[1].ID())); break; @@ -1127,7 +1099,7 @@ DEF_OP(Select) { uint64_t const_true, const_false; bool is_const_true = IsInlineConstant(Op->Header.Args[2], &const_true); bool is_const_false = IsInlineConstant(Op->Header.Args[3], &const_false); - + if (is_const_true || is_const_false) { if (is_const_false != true || is_const_true != true || const_true != 1 || const_false != 0) { LogMan::Msg::A("Select: Unsupported compare inline parameters"); diff --git a/External/FEXCore/Source/Interface/Core/JIT/x86_64/ALUOps.cpp b/External/FEXCore/Source/Interface/Core/JIT/x86_64/ALUOps.cpp index 16cb48012..e1d3d003a 100644 --- a/External/FEXCore/Source/Interface/Core/JIT/x86_64/ALUOps.cpp +++ b/External/FEXCore/Source/Interface/Core/JIT/x86_64/ALUOps.cpp @@ -683,16 +683,6 @@ DEF_OP(Ror) { if (IsInlineConstant(Op->Header.Args[1], &Const)) { Const &= Mask; switch (OpSize) { - case 1: { - movzx(rax, GetSrc(Op->Header.Args[0].ID())); - ror(al, Const); - break; - } - case 2: { - movzx(rax, GetSrc(Op->Header.Args[0].ID())); - ror(ax, Const); - break; - } case 4: { mov(eax, GetSrc(Op->Header.Args[0].ID())); ror(eax, Const); @@ -703,21 +693,12 @@ DEF_OP(Ror) { ror(rax, Const); break; } + default: LogMan::Msg::A("Unknown ROR Size: %d\n", OpSize); break; } } else { mov (rcx, GetSrc(Op->Header.Args[1].ID())); and(rcx, Mask); switch (OpSize) { - case 1: { - movzx(rax, GetSrc(Op->Header.Args[0].ID())); - ror(al, cl); - break; - } - case 2: { - movzx(rax, GetSrc(Op->Header.Args[0].ID())); - ror(ax, cl); - break; - } case 4: { mov(eax, GetSrc(Op->Header.Args[0].ID())); ror(eax, cl); @@ -728,6 +709,7 @@ DEF_OP(Ror) { ror(rax, cl); break; } + default: LogMan::Msg::A("Unknown ROR Size: %d\n", OpSize); break; } } mov(GetDst(Node), rax); @@ -1193,11 +1175,11 @@ DEF_OP(Select) { } else { cmp(GRCMP(Op->Cmp1.ID()), GRCMP(Op->Cmp2.ID())); } - + uint64_t const_true, const_false; bool is_const_true = IsInlineConstant(Op->TrueVal, &const_true); bool is_const_false = IsInlineConstant(Op->FalseVal, &const_false); - + if (is_const_true || is_const_false) { if (is_const_false != true || is_const_true != true || const_true != 1 || const_false != 0) { LogMan::Msg::A("Select: Unsupported compare inline parameters"); @@ -1214,7 +1196,7 @@ DEF_OP(Select) { case FEXCore::IR::COND_ULT: setb(al); break; case FEXCore::IR::COND_UGT: seta(al); break; case FEXCore::IR::COND_ULE: setna(al); break; - + case FEXCore::IR::COND_MI: case FEXCore::IR::COND_PL: case FEXCore::IR::COND_VS: @@ -1237,7 +1219,7 @@ DEF_OP(Select) { case FEXCore::IR::COND_ULT: cmovb(rax, GetSrc(Op->TrueVal.ID())); break; case FEXCore::IR::COND_UGT: cmova(rax, GetSrc(Op->TrueVal.ID())); break; case FEXCore::IR::COND_ULE: cmovna(rax, GetSrc(Op->TrueVal.ID())); break; - + case FEXCore::IR::COND_MI: case FEXCore::IR::COND_PL: case FEXCore::IR::COND_VS: diff --git a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp index 600996816..af1be3a26 100644 --- a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp +++ b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp @@ -148,7 +148,7 @@ void OpDispatchBuilder::RETOp(OpcodeArgs) { if (CTX->Config.ABILocalFlags) { _InvalidateFlags(); } - + auto Constant = _Constant(GPRSize); auto OldSP = _LoadContext(GPRSize, offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RSP]), GPRClass); @@ -183,9 +183,9 @@ SS */ void OpDispatchBuilder::IRETOp(OpcodeArgs) { LogMan::Throw::A(CTX->Config.Is64BitMode == true, "IRET only implemented for x64"); - + uint8_t GPRSize = CTX->Config.Is64BitMode ? 8 : 4; - + auto Constant = _Constant(GPRSize); OrderedNode* SP = _LoadContext(GPRSize, offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RSP]), GPRClass); @@ -206,7 +206,7 @@ void OpDispatchBuilder::IRETOp(OpcodeArgs) { //ss _StoreContext(GPRClass, 2, offsetof(FEXCore::Core::CPUState, ss), _LoadMem(GPRClass, GPRSize, SP, GPRSize)); SP = _Add(SP, Constant); - + _ExitFunction(); BlockSetRIP = true; } @@ -681,7 +681,7 @@ void OpDispatchBuilder::CALLAbsoluteOp(OpcodeArgs) { OrderedNode *OpDispatchBuilder::SelectCC(uint8_t OP, OrderedNode *TrueValue, OrderedNode *FalseValue) { OrderedNode *SrcCond = nullptr; - + auto ZeroConst = _Constant(0); auto OneConst = _Constant(1); @@ -822,12 +822,12 @@ OrderedNode *OpDispatchBuilder::SelectCC(uint8_t OP, OrderedNode *TrueValue, Ord case 0xD: SrcCond = _Select(FEXCore::IR::COND_SGE, flagsOpDestSigned, flagsOpSrcSigned, TrueValue, FalseValue, flagsOpSize); break; // SL case 0xC: SrcCond = _Select(FEXCore::IR::COND_SLT, flagsOpDestSigned, flagsOpSrcSigned, TrueValue, FalseValue, flagsOpSize); 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(FEXCore::IR::COND_UGT, flagsOpDest, flagsOpSrc, TrueValue, FalseValue, flagsOpSize); break; // UBE @@ -1139,9 +1139,9 @@ void OpDispatchBuilder::TESTOp(OpcodeArgs) { auto ALUOp = _And(Dest, Src); GenerateFlags_Logical(Op, ALUOp, Dest, Src); - + auto Size = GetDstSize(Op); - + if (Size >=4) { flagsOp = FLAGS_OP_AND; flagsOpDest = ALUOp; @@ -1837,7 +1837,7 @@ void OpDispatchBuilder::ROROp(OpcodeArgs) { auto Size = GetSrcSize(Op) * 8; if (Is1Bit) { - Src = _Constant(Size, 1); + Src = _Constant(std::max(32, Size), 1); } else { Src = LoadSource(GPRClass, Op, Op->Src[1], Op->Flags, -1); @@ -1849,6 +1849,17 @@ void OpDispatchBuilder::ROROp(OpcodeArgs) { else Src = _And(Src, _Constant(Size, 0x1F)); + if (Size < 32) { + // ARM doesn't support 8/16bit rotates. Emulate with an insert + // StoreResult truncates back to a 8/16 bit value + Dest = _Bfi(4, Size, Size, Dest, Dest); + if (Size == 8 && !Is1Bit) { + // And because the shift size isn't masked to 8 bits, we need to fill the + // the full 32bits to get the correct result. + Dest = _Bfi(4, 16, 16, Dest, Dest); + } + } + auto ALUOp = _Ror(Dest, Src); StoreResult(GPRClass, Op, ALUOp, -1); @@ -1875,7 +1886,18 @@ void OpDispatchBuilder::RORImmediateOp(OpcodeArgs) { else Shift &= 0x1F; - OrderedNode *Src = _Constant(Size, Shift); + OrderedNode *Src = _Constant(std::max(32, Size), Shift); + + if (Size < 32) { + // ARM doesn't support 8/16bit rotates. Emulate with an insert + // StoreResult truncates back to a 8/16 bit value + Dest = _Bfi(4, Size, Size, Dest, Dest); + if (Size == 8 && Shift > 8) { + // And because the shift size isn't masked to 8 bits, we need to fill the + // the full 32bits to get the correct result. + Dest = _Bfi(4, 16, 16, Dest, Dest); + } + } auto ALUOp = _Ror(Dest, Src); @@ -5129,7 +5151,7 @@ void OpDispatchBuilder::GenerateFlags_ShiftLeft(FEXCore::X86Tables::DecodedOp Op // Extract the last bit shifted in to CF auto Size = _Constant(GetSrcSize(Op) * 8); auto ShiftAmt = _Sub(Size, Src2); - auto LastBit = _And(_Lshr(Src1, ShiftAmt), _Constant(1)); + auto LastBit = _And(_Lshr(Src1, ShiftAmt), _Constant(1)); COND_FLAG_SET(Src2, RFLAG_CF_LOC, LastBit); }