mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-11 00:29:11 +01:00
Initial unoptimized JITIL flag optimization.
This commit is contained in:
parent
5506e57ab8
commit
1429fccb97
@ -85,7 +85,7 @@ static unsigned regReadUse(RegInfo& R, InstLoc I) {
|
|||||||
return R.IInfo[I - R.FirstI] & 3;
|
return R.IInfo[I - R.FirstI] & 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned SlotSet[1000];
|
static u64 SlotSet[1000];
|
||||||
static u8 GC_ALIGNED16(FSlotSet[16*1000]);
|
static u8 GC_ALIGNED16(FSlotSet[16*1000]);
|
||||||
|
|
||||||
static OpArg regLocForSlot(RegInfo& RI, unsigned slot) {
|
static OpArg regLocForSlot(RegInfo& RI, unsigned slot) {
|
||||||
@ -107,7 +107,7 @@ static void regSpill(RegInfo& RI, X64Reg reg) {
|
|||||||
unsigned slot = regGetSpill(RI, RI.regs[reg]);
|
unsigned slot = regGetSpill(RI, RI.regs[reg]);
|
||||||
if (!slot) {
|
if (!slot) {
|
||||||
slot = regCreateSpill(RI, RI.regs[reg]);
|
slot = regCreateSpill(RI, RI.regs[reg]);
|
||||||
RI.Jit->MOV(32, regLocForSlot(RI, slot), R(reg));
|
RI.Jit->MOV(64, regLocForSlot(RI, slot), R(reg));
|
||||||
}
|
}
|
||||||
RI.regs[reg] = nullptr;
|
RI.regs[reg] = nullptr;
|
||||||
}
|
}
|
||||||
@ -621,6 +621,8 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, u32 exitAddress) {
|
|||||||
case FPDup1:
|
case FPDup1:
|
||||||
case FSNeg:
|
case FSNeg:
|
||||||
case FDNeg:
|
case FDNeg:
|
||||||
|
case ConvertFromFastCR:
|
||||||
|
case ConvertToFastCR:
|
||||||
if (thisUsed)
|
if (thisUsed)
|
||||||
regMarkUse(RI, I, getOp1(I), 1);
|
regMarkUse(RI, I, getOp1(I), 1);
|
||||||
break;
|
break;
|
||||||
@ -763,8 +765,7 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, u32 exitAddress) {
|
|||||||
if (!thisUsed) break;
|
if (!thisUsed) break;
|
||||||
X64Reg reg = regFindFreeReg(RI);
|
X64Reg reg = regFindFreeReg(RI);
|
||||||
unsigned ppcreg = *I >> 8;
|
unsigned ppcreg = *I >> 8;
|
||||||
// TODO(delroth): unbreak
|
Jit->MOV(64, R(reg), M(&PowerPC::ppcState.cr_val[ppcreg]));
|
||||||
//Jit->MOVZX(32, 8, reg, M(&PowerPC::ppcState.cr_fast[ppcreg]));
|
|
||||||
RI.regs[reg] = I;
|
RI.regs[reg] = I;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -814,11 +815,9 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, u32 exitAddress) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case StoreCR: {
|
case StoreCR: {
|
||||||
Jit->MOV(32, R(ECX), regLocForInst(RI, getOp1(I)));
|
Jit->MOV(64, R(RCX), regLocForInst(RI, getOp1(I)));
|
||||||
unsigned ppcreg = *I >> 16;
|
unsigned ppcreg = *I >> 16;
|
||||||
// CAUTION: uses 8-bit reg!
|
Jit->MOV(64, M(&PowerPC::ppcState.cr_val[ppcreg]), R(RCX));
|
||||||
// TODO(delroth): Unbreak.
|
|
||||||
//Jit->MOV(8, M(&PowerPC::ppcState.cr_fast[ppcreg]), R(ECX));
|
|
||||||
regNormalRegClear(RI, I);
|
regNormalRegClear(RI, I);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1116,6 +1115,84 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, u32 exitAddress) {
|
|||||||
regNormalRegClear(RI, I);
|
regNormalRegClear(RI, I);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case ConvertFromFastCR:
|
||||||
|
{
|
||||||
|
if (!thisUsed) break;
|
||||||
|
X64Reg cr_val = regUReg(RI, I);
|
||||||
|
Jit->MOV(64, R(cr_val), regLocForInst(RI, getOp1(I)));
|
||||||
|
|
||||||
|
Jit->XOR(32, R(EAX), R(EAX));
|
||||||
|
|
||||||
|
// SO: Bit 61 set.
|
||||||
|
Jit->MOV(64, R(RCX), R(cr_val));
|
||||||
|
Jit->SHR(64, R(RCX), Imm8(61));
|
||||||
|
Jit->AND(32, R(ECX), Imm8(1));
|
||||||
|
Jit->OR(32, R(EAX), R(ECX));
|
||||||
|
|
||||||
|
// EQ: Bits 31-0 == 0.
|
||||||
|
Jit->XOR(32, R(ECX), R(ECX));
|
||||||
|
Jit->TEST(32, R(cr_val), R(cr_val));
|
||||||
|
Jit->SETcc(CC_Z, R(ECX));
|
||||||
|
Jit->SHL(32, R(ECX), Imm8(1));
|
||||||
|
Jit->OR(32, R(EAX), R(ECX));
|
||||||
|
|
||||||
|
// GT: Value > 0.
|
||||||
|
Jit->XOR(32, R(ECX), R(ECX));
|
||||||
|
Jit->TEST(64, R(cr_val), R(cr_val));
|
||||||
|
Jit->SETcc(CC_G, R(ECX));
|
||||||
|
Jit->SHL(32, R(ECX), Imm8(2));
|
||||||
|
Jit->OR(32, R(EAX), R(ECX));
|
||||||
|
|
||||||
|
// LT: Bit 62 set.
|
||||||
|
Jit->MOV(64, R(ECX), R(cr_val));
|
||||||
|
Jit->SHR(64, R(ECX), Imm8(62 - 3));
|
||||||
|
Jit->AND(32, R(ECX), Imm8(0x8));
|
||||||
|
Jit->OR(32, R(EAX), R(ECX));
|
||||||
|
|
||||||
|
Jit->MOV(32, R(cr_val), R(EAX));
|
||||||
|
RI.regs[cr_val] = I;
|
||||||
|
regNormalRegClear(RI, I);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ConvertToFastCR:
|
||||||
|
{
|
||||||
|
if (!thisUsed) break;
|
||||||
|
X64Reg cr_val = regUReg(RI, I);
|
||||||
|
Jit->MOV(64, R(cr_val), regLocForInst(RI, getOp1(I)));
|
||||||
|
|
||||||
|
Jit->MOV(64, R(RCX), Imm64(1ull << 32));
|
||||||
|
|
||||||
|
// SO
|
||||||
|
Jit->MOV(64, R(RAX), R(cr_val));
|
||||||
|
Jit->SHL(64, R(RAX), Imm8(63));
|
||||||
|
Jit->SHR(64, R(RAX), Imm8(63 - 61));
|
||||||
|
Jit->OR(64, R(RCX), R(RAX));
|
||||||
|
|
||||||
|
// EQ
|
||||||
|
Jit->MOV(64, R(RAX), R(cr_val));
|
||||||
|
Jit->NOT(64, R(RAX));
|
||||||
|
Jit->AND(64, R(RAX), Imm8(CR_EQ));
|
||||||
|
Jit->OR(64, R(RCX), R(RAX));
|
||||||
|
|
||||||
|
// GT
|
||||||
|
Jit->MOV(64, R(RAX), R(cr_val));
|
||||||
|
Jit->NOT(64, R(RAX));
|
||||||
|
Jit->AND(64, R(RAX), Imm8(CR_GT));
|
||||||
|
Jit->SHL(64, R(RAX), Imm8(63 - 2));
|
||||||
|
Jit->OR(64, R(RCX), R(RAX));
|
||||||
|
|
||||||
|
// LT
|
||||||
|
Jit->MOV(64, R(RAX), R(cr_val));
|
||||||
|
Jit->AND(64, R(RAX), Imm8(CR_LT));
|
||||||
|
Jit->SHL(64, R(RAX), Imm8(62 - 3));
|
||||||
|
Jit->OR(64, R(RCX), R(RAX));
|
||||||
|
|
||||||
|
Jit->MOV(64, R(cr_val), R(RCX));
|
||||||
|
|
||||||
|
RI.regs[cr_val] = I;
|
||||||
|
regNormalRegClear(RI, I);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case LoadSingle: {
|
case LoadSingle: {
|
||||||
if (!thisUsed) break;
|
if (!thisUsed) break;
|
||||||
X64Reg reg = fregFindFreeReg(RI);
|
X64Reg reg = fregFindFreeReg(RI);
|
||||||
|
@ -1130,7 +1130,7 @@ unsigned IRBuilder::getNumberOfOperands(InstLoc I) const {
|
|||||||
numberOfOperands[CInt32] = 0;
|
numberOfOperands[CInt32] = 0;
|
||||||
|
|
||||||
static unsigned ZeroOp[] = {LoadCR, LoadLink, LoadMSR, LoadGReg, LoadCTR, InterpreterBranch, LoadCarry, RFIExit, LoadFReg, LoadFRegDENToZero, LoadGQR, Int3, };
|
static unsigned ZeroOp[] = {LoadCR, LoadLink, LoadMSR, LoadGReg, LoadCTR, InterpreterBranch, LoadCarry, RFIExit, LoadFReg, LoadFRegDENToZero, LoadGQR, Int3, };
|
||||||
static unsigned UOp[] = {StoreLink, BranchUncond, StoreCR, StoreMSR, StoreFPRF, StoreGReg, StoreCTR, Load8, Load16, Load32, SExt16, SExt8, Cntlzw, Not, StoreCarry, SystemCall, ShortIdleLoop, LoadSingle, LoadDouble, LoadPaired, StoreFReg, DupSingleToMReg, DupSingleToPacked, ExpandPackedToMReg, CompactMRegToPacked, FSNeg, FDNeg, FPDup0, FPDup1, FPNeg, DoubleToSingle, StoreGQR, StoreSRR, };
|
static unsigned UOp[] = {StoreLink, BranchUncond, StoreCR, StoreMSR, StoreFPRF, StoreGReg, StoreCTR, Load8, Load16, Load32, SExt16, SExt8, Cntlzw, Not, StoreCarry, SystemCall, ShortIdleLoop, LoadSingle, LoadDouble, LoadPaired, StoreFReg, DupSingleToMReg, DupSingleToPacked, ExpandPackedToMReg, CompactMRegToPacked, FSNeg, FDNeg, FPDup0, FPDup1, FPNeg, DoubleToSingle, StoreGQR, StoreSRR, ConvertFromFastCR, ConvertToFastCR};
|
||||||
static unsigned BiOp[] = {BranchCond, IdleBranch, And, Xor, Sub, Or, Add, Mul, Rol, Shl, Shrl, Sarl, ICmpEq, ICmpNe, ICmpUgt, ICmpUlt, ICmpSgt, ICmpSlt, ICmpSge, ICmpSle, Store8, Store16, Store32, ICmpCRSigned, ICmpCRUnsigned, FallBackToInterpreter, StoreSingle, StoreDouble, StorePaired, InsertDoubleInMReg, FSMul, FSAdd, FSSub, FDMul, FDAdd, FDSub, FPAdd, FPMul, FPSub, FPMerge00, FPMerge01, FPMerge10, FPMerge11, FDCmpCR, };
|
static unsigned BiOp[] = {BranchCond, IdleBranch, And, Xor, Sub, Or, Add, Mul, Rol, Shl, Shrl, Sarl, ICmpEq, ICmpNe, ICmpUgt, ICmpUlt, ICmpSgt, ICmpSlt, ICmpSge, ICmpSle, Store8, Store16, Store32, ICmpCRSigned, ICmpCRUnsigned, FallBackToInterpreter, StoreSingle, StoreDouble, StorePaired, InsertDoubleInMReg, FSMul, FSAdd, FSSub, FDMul, FDAdd, FDSub, FPAdd, FPMul, FPSub, FPMerge00, FPMerge01, FPMerge10, FPMerge11, FDCmpCR, };
|
||||||
for (auto& op : ZeroOp) {
|
for (auto& op : ZeroOp) {
|
||||||
numberOfOperands[op] = 0;
|
numberOfOperands[op] = 0;
|
||||||
@ -1235,10 +1235,11 @@ static std::unique_ptr<Writer> writer;
|
|||||||
static const std::string opcodeNames[] = {
|
static const std::string opcodeNames[] = {
|
||||||
"Nop", "LoadGReg", "LoadLink", "LoadCR", "LoadCarry", "LoadCTR",
|
"Nop", "LoadGReg", "LoadLink", "LoadCR", "LoadCarry", "LoadCTR",
|
||||||
"LoadMSR", "LoadGQR", "SExt8", "SExt16", "BSwap32", "BSwap16", "Cntlzw",
|
"LoadMSR", "LoadGQR", "SExt8", "SExt16", "BSwap32", "BSwap16", "Cntlzw",
|
||||||
"Not", "Load8", "Load16", "Load32", "BranchUncond", "StoreGReg",
|
"Not", "Load8", "Load16", "Load32", "BranchUncond", "ConvertFromFastCR",
|
||||||
"StoreCR", "StoreLink", "StoreCarry", "StoreCTR", "StoreMSR", "StoreFPRF",
|
"ConvertToFastCR", "StoreGReg", "StoreCR", "StoreLink", "StoreCarry",
|
||||||
"StoreGQR", "StoreSRR", "FallBackToInterpreter", "Add", "Mul", "And", "Or",
|
"StoreCTR", "StoreMSR", "StoreFPRF", "StoreGQR", "StoreSRR",
|
||||||
"Xor", "MulHighUnsigned", "Sub", "Shl", "Shrl", "Sarl", "Rol",
|
"FallBackToInterpreter", "Add", "Mul", "And", "Or", "Xor",
|
||||||
|
"MulHighUnsigned", "Sub", "Shl", "Shrl", "Sarl", "Rol",
|
||||||
"ICmpCRSigned", "ICmpCRUnsigned", "ICmpEq", "ICmpNe", "ICmpUgt",
|
"ICmpCRSigned", "ICmpCRUnsigned", "ICmpEq", "ICmpNe", "ICmpUgt",
|
||||||
"ICmpUlt", "ICmpUge", "ICmpUle", "ICmpSgt", "ICmpSlt", "ICmpSge",
|
"ICmpUlt", "ICmpUge", "ICmpUle", "ICmpSgt", "ICmpSlt", "ICmpSge",
|
||||||
"ICmpSle", "Store8", "Store16", "Store32", "BranchCond", "FResult_Start",
|
"ICmpSle", "Store8", "Store16", "Store32", "BranchCond", "FResult_Start",
|
||||||
|
@ -33,6 +33,9 @@ enum Opcode {
|
|||||||
Load8, // These loads zext
|
Load8, // These loads zext
|
||||||
Load16,
|
Load16,
|
||||||
Load32,
|
Load32,
|
||||||
|
// CR conversions
|
||||||
|
ConvertFromFastCR,
|
||||||
|
ConvertToFastCR,
|
||||||
// Branches
|
// Branches
|
||||||
BranchUncond,
|
BranchUncond,
|
||||||
// Register store operators
|
// Register store operators
|
||||||
@ -373,6 +376,12 @@ public:
|
|||||||
InstLoc EmitICmpCRUnsigned(InstLoc op1, InstLoc op2) {
|
InstLoc EmitICmpCRUnsigned(InstLoc op1, InstLoc op2) {
|
||||||
return FoldBiOp(ICmpCRUnsigned, op1, op2);
|
return FoldBiOp(ICmpCRUnsigned, op1, op2);
|
||||||
}
|
}
|
||||||
|
InstLoc EmitConvertFromFastCR(InstLoc op1) {
|
||||||
|
return FoldUOp(ConvertFromFastCR, op1);
|
||||||
|
}
|
||||||
|
InstLoc EmitConvertToFastCR(InstLoc op1) {
|
||||||
|
return FoldUOp(ConvertToFastCR, op1);
|
||||||
|
}
|
||||||
InstLoc EmitFallBackToInterpreter(InstLoc op1, InstLoc op2) {
|
InstLoc EmitFallBackToInterpreter(InstLoc op1, InstLoc op2) {
|
||||||
return FoldBiOp(FallBackToInterpreter, op1, op2);
|
return FoldBiOp(FallBackToInterpreter, op1, op2);
|
||||||
}
|
}
|
||||||
|
@ -66,6 +66,7 @@ static IREmitter::InstLoc TestBranch(IREmitter::IRBuilder& ibuild, UGeckoInstruc
|
|||||||
if ((inst.BO & 16) == 0) // Test a CR bit
|
if ((inst.BO & 16) == 0) // Test a CR bit
|
||||||
{
|
{
|
||||||
IREmitter::InstLoc CRReg = ibuild.EmitLoadCR(inst.BI >> 2);
|
IREmitter::InstLoc CRReg = ibuild.EmitLoadCR(inst.BI >> 2);
|
||||||
|
CRReg = ibuild.EmitConvertFromFastCR(CRReg);
|
||||||
IREmitter::InstLoc CRCmp = ibuild.EmitIntConst(8 >> (inst.BI & 3));
|
IREmitter::InstLoc CRCmp = ibuild.EmitIntConst(8 >> (inst.BI & 3));
|
||||||
CRTest = ibuild.EmitAnd(CRReg, CRCmp);
|
CRTest = ibuild.EmitAnd(CRReg, CRCmp);
|
||||||
if (!(inst.BO & 8))
|
if (!(inst.BO & 8))
|
||||||
@ -141,6 +142,7 @@ void JitILBase::bcctrx(UGeckoInstruction inst)
|
|||||||
if ((inst.BO & 16) == 0) // Test a CR bit
|
if ((inst.BO & 16) == 0) // Test a CR bit
|
||||||
{
|
{
|
||||||
IREmitter::InstLoc CRReg = ibuild.EmitLoadCR(inst.BI >> 2);
|
IREmitter::InstLoc CRReg = ibuild.EmitLoadCR(inst.BI >> 2);
|
||||||
|
CRReg = ibuild.EmitConvertFromFastCR(CRReg);
|
||||||
IREmitter::InstLoc CRCmp = ibuild.EmitIntConst(8 >> (inst.BI & 3));
|
IREmitter::InstLoc CRCmp = ibuild.EmitIntConst(8 >> (inst.BI & 3));
|
||||||
test = ibuild.EmitAnd(CRReg, CRCmp);
|
test = ibuild.EmitAnd(CRReg, CRCmp);
|
||||||
if (!(inst.BO & 8))
|
if (!(inst.BO & 8))
|
||||||
|
@ -86,7 +86,7 @@ void JitILBase::fcmpx(UGeckoInstruction inst)
|
|||||||
int ordered = (inst.SUBOP10 == 32) ? 1 : 0;
|
int ordered = (inst.SUBOP10 == 32) ? 1 : 0;
|
||||||
res = ibuild.EmitFDCmpCR(lhs, rhs, ordered);
|
res = ibuild.EmitFDCmpCR(lhs, rhs, ordered);
|
||||||
ibuild.EmitStoreFPRF(res);
|
ibuild.EmitStoreFPRF(res);
|
||||||
ibuild.EmitStoreCR(res, inst.CRFD);
|
ibuild.EmitStoreCR(ibuild.EmitConvertToFastCR(res), inst.CRFD);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JitILBase::fsign(UGeckoInstruction inst)
|
void JitILBase::fsign(UGeckoInstruction inst)
|
||||||
|
@ -12,7 +12,7 @@ static void ComputeRC(IREmitter::IRBuilder& ibuild, IREmitter::InstLoc val)
|
|||||||
{
|
{
|
||||||
IREmitter::InstLoc res =
|
IREmitter::InstLoc res =
|
||||||
ibuild.EmitICmpCRSigned(val, ibuild.EmitIntConst(0));
|
ibuild.EmitICmpCRSigned(val, ibuild.EmitIntConst(0));
|
||||||
ibuild.EmitStoreCR(res, 0);
|
ibuild.EmitStoreCR(ibuild.EmitConvertToFastCR(res), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JitILBase::reg_imm(UGeckoInstruction inst)
|
void JitILBase::reg_imm(UGeckoInstruction inst)
|
||||||
@ -114,7 +114,7 @@ void JitILBase::cmpXX(UGeckoInstruction inst)
|
|||||||
|
|
||||||
js.downcountAmount++; //TODO: should this be somewhere else?
|
js.downcountAmount++; //TODO: should this be somewhere else?
|
||||||
|
|
||||||
ibuild.EmitStoreCR(res, inst.CRFD);
|
ibuild.EmitStoreCR(ibuild.EmitConvertToFastCR(res), inst.CRFD);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JitILBase::boolX(UGeckoInstruction inst)
|
void JitILBase::boolX(UGeckoInstruction inst)
|
||||||
|
@ -107,8 +107,10 @@ void JitILBase::mfcr(UGeckoInstruction inst)
|
|||||||
IREmitter::InstLoc d = ibuild.EmitIntConst(0);
|
IREmitter::InstLoc d = ibuild.EmitIntConst(0);
|
||||||
for (int i = 0; i < 8; ++i)
|
for (int i = 0; i < 8; ++i)
|
||||||
{
|
{
|
||||||
d = ibuild.EmitShl(d, ibuild.EmitIntConst(4));
|
IREmitter::InstLoc cr = ibuild.EmitLoadCR(i);
|
||||||
d = ibuild.EmitOr(d, ibuild.EmitLoadCR(i));
|
cr = ibuild.EmitConvertFromFastCR(cr);
|
||||||
|
cr = ibuild.EmitShl(cr, ibuild.EmitIntConst(28 - 4 * i));
|
||||||
|
d = ibuild.EmitOr(d, cr);
|
||||||
}
|
}
|
||||||
ibuild.EmitStoreGReg(d, inst.RD);
|
ibuild.EmitStoreGReg(d, inst.RD);
|
||||||
}
|
}
|
||||||
@ -126,6 +128,7 @@ void JitILBase::mtcrf(UGeckoInstruction inst)
|
|||||||
IREmitter::InstLoc value;
|
IREmitter::InstLoc value;
|
||||||
value = ibuild.EmitShrl(s, ibuild.EmitIntConst(28 - i * 4));
|
value = ibuild.EmitShrl(s, ibuild.EmitIntConst(28 - i * 4));
|
||||||
value = ibuild.EmitAnd(value, ibuild.EmitIntConst(0xF));
|
value = ibuild.EmitAnd(value, ibuild.EmitIntConst(0xF));
|
||||||
|
value = ibuild.EmitConvertToFastCR(value);
|
||||||
ibuild.EmitStoreCR(value, i);
|
ibuild.EmitStoreCR(value, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -150,6 +153,7 @@ void JitILBase::crXX(UGeckoInstruction inst)
|
|||||||
// Get bit CRBA in EAX aligned with bit CRBD
|
// Get bit CRBA in EAX aligned with bit CRBD
|
||||||
const int shiftA = (inst.CRBD & 3) - (inst.CRBA & 3);
|
const int shiftA = (inst.CRBD & 3) - (inst.CRBA & 3);
|
||||||
IREmitter::InstLoc eax = ibuild.EmitLoadCR(inst.CRBA >> 2);
|
IREmitter::InstLoc eax = ibuild.EmitLoadCR(inst.CRBA >> 2);
|
||||||
|
eax = ibuild.EmitConvertFromFastCR(eax);
|
||||||
if (shiftA < 0)
|
if (shiftA < 0)
|
||||||
eax = ibuild.EmitShl(eax, ibuild.EmitIntConst(-shiftA));
|
eax = ibuild.EmitShl(eax, ibuild.EmitIntConst(-shiftA));
|
||||||
else if (shiftA > 0)
|
else if (shiftA > 0)
|
||||||
@ -158,6 +162,7 @@ void JitILBase::crXX(UGeckoInstruction inst)
|
|||||||
// Get bit CRBB in ECX aligned with bit CRBD
|
// Get bit CRBB in ECX aligned with bit CRBD
|
||||||
const int shiftB = (inst.CRBD & 3) - (inst.CRBB & 3);
|
const int shiftB = (inst.CRBD & 3) - (inst.CRBB & 3);
|
||||||
IREmitter::InstLoc ecx = ibuild.EmitLoadCR(inst.CRBB >> 2);
|
IREmitter::InstLoc ecx = ibuild.EmitLoadCR(inst.CRBB >> 2);
|
||||||
|
ecx = ibuild.EmitConvertFromFastCR(ecx);
|
||||||
if (shiftB < 0)
|
if (shiftB < 0)
|
||||||
ecx = ibuild.EmitShl(ecx, ibuild.EmitIntConst(-shiftB));
|
ecx = ibuild.EmitShl(ecx, ibuild.EmitIntConst(-shiftB));
|
||||||
else if (shiftB > 0)
|
else if (shiftB > 0)
|
||||||
@ -211,7 +216,9 @@ void JitILBase::crXX(UGeckoInstruction inst)
|
|||||||
// Store result bit in CRBD
|
// Store result bit in CRBD
|
||||||
eax = ibuild.EmitAnd(eax, ibuild.EmitIntConst(0x8 >> (inst.CRBD & 3)));
|
eax = ibuild.EmitAnd(eax, ibuild.EmitIntConst(0x8 >> (inst.CRBD & 3)));
|
||||||
IREmitter::InstLoc bd = ibuild.EmitLoadCR(inst.CRBD >> 2);
|
IREmitter::InstLoc bd = ibuild.EmitLoadCR(inst.CRBD >> 2);
|
||||||
|
bd = ibuild.EmitConvertFromFastCR(bd);
|
||||||
bd = ibuild.EmitAnd(bd, ibuild.EmitIntConst(~(0x8 >> (inst.CRBD & 3))));
|
bd = ibuild.EmitAnd(bd, ibuild.EmitIntConst(~(0x8 >> (inst.CRBD & 3))));
|
||||||
bd = ibuild.EmitOr(bd, eax);
|
bd = ibuild.EmitOr(bd, eax);
|
||||||
|
bd = ibuild.EmitConvertToFastCR(bd);
|
||||||
ibuild.EmitStoreCR(bd, inst.CRBD >> 2);
|
ibuild.EmitStoreCR(bd, inst.CRBD >> 2);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user