Permalink
Browse files

Merge pull request #10494 from unknownbrackets/irjit

irjit: Implement lwl/etc.
  • Loading branch information...
hrydgard committed Jan 1, 2018
2 parents 3e40db0 + 3abcc4d commit 263941e9e04b4ac1eaf194ae592fde12dcca577b
View
@@ -218,7 +218,7 @@ void ArmJit::Compile(u32 em_address) {
// Drat. The VFPU hit an uneaten prefix at the end of a block.
if (js.startDefaultPrefix && js.MayHavePrefix()) {
WARN_LOG(JIT, "An uneaten prefix at end of block: %08x", GetCompilerPC() - 4);
WARN_LOG_REPORT(JIT, "An uneaten prefix at end of block: %08x", GetCompilerPC() - 4);
js.LogPrefix();
// Let's try that one more time. We won't get back here because we toggled the value.
@@ -180,7 +180,7 @@ namespace MIPSComp {
gpr.SpillLock(rs);
// Need to get temps before skipping safe mem.
ARM64Reg LR_SCRATCH3 = gpr.GetAndLockTempR();
ARM64Reg LR_SCRATCH4 = gpr.GetAndLockTempR();
ARM64Reg LR_SCRATCH4 = o == 42 || o == 46 ? gpr.GetAndLockTempR() : INVALID_REG;
if (!g_Config.bFastMemory && rs != MIPS_REG_SP) {
skips = SetScratch1ForSafeAddress(rs, offset, SCRATCH2);
@@ -204,7 +204,7 @@ void Arm64Jit::Compile(u32 em_address) {
// Drat. The VFPU hit an uneaten prefix at the end of a block.
if (js.startDefaultPrefix && js.MayHavePrefix()) {
WARN_LOG(JIT, "An uneaten prefix at end of block: %08x", GetCompilerPC() - 4);
WARN_LOG_REPORT(JIT, "An uneaten prefix at end of block: %08x", GetCompilerPC() - 4);
js.LogPrefix();
// Let's try that one more time. We won't get back here because we toggled the value.
View
@@ -40,14 +40,15 @@
// #define CONDITIONAL_DISABLE { Comp_Generic(op); return; }
#define CONDITIONAL_DISABLE ;
#define DISABLE { Comp_Generic(op); return; }
#define INVALIDOP { Comp_Generic(op); return; }
namespace MIPSComp {
void IRFrontend::Comp_IType(MIPSOpcode op) {
CONDITIONAL_DISABLE;
s32 simm = (s32)(s16)(op & 0xFFFF); // sign extension
u32 uimm = op & 0xFFFF;
s32 simm = (s32)_IMM16; // sign extension
u32 uimm = (u16)_IMM16;
u32 suimm = (u32)(s32)simm;
MIPSGPReg rt = _RT;
@@ -80,7 +81,7 @@ void IRFrontend::Comp_IType(MIPSOpcode op) {
break;
default:
Comp_Generic(op);
INVALIDOP;
break;
}
}
@@ -104,7 +105,7 @@ void IRFrontend::Comp_RType2(MIPSOpcode op) {
ir.Write(IROp::Clz, rd, IRTEMP_0);
break;
default:
Comp_Generic(op);
INVALIDOP;
break;
}
}
@@ -176,7 +177,7 @@ void IRFrontend::Comp_RType3(MIPSOpcode op) {
break;
default:
Comp_Generic(op);
INVALIDOP;
break;
}
}
@@ -213,8 +214,9 @@ void IRFrontend::Comp_ShiftType(MIPSOpcode op) {
case 4: CompShiftVar(op, IROp::Shl, IROp::ShlImm); break; //sllv
case 6: CompShiftVar(op, (sa == 1 ? IROp::Ror : IROp::Shr), (sa == 1 ? IROp::RorImm : IROp::ShrImm)); break; //srlv
case 7: CompShiftVar(op, IROp::Sar, IROp::SarImm); break; //srav
default:
Comp_Generic(op);
INVALIDOP;
break;
}
}
@@ -256,7 +258,7 @@ void IRFrontend::Comp_Special3(MIPSOpcode op) {
break;
default:
Comp_Generic(op);
INVALIDOP;
break;
}
}
@@ -285,7 +287,7 @@ void IRFrontend::Comp_Allegrex(MIPSOpcode op) {
break;
default:
Comp_Generic(op);
INVALIDOP;
return;
}
}
@@ -307,7 +309,7 @@ void IRFrontend::Comp_Allegrex2(MIPSOpcode op) {
ir.Write(IROp::BSwap32, rd, rt);
break;
default:
Comp_Generic(op);
INVALIDOP;
break;
}
}
@@ -372,7 +374,7 @@ void IRFrontend::Comp_MulDivType(MIPSOpcode op) {
break;
default:
DISABLE;
INVALIDOP;
}
}
View
@@ -51,6 +51,7 @@
// #define CONDITIONAL_DISABLE { Comp_Generic(op); return; }
#define CONDITIONAL_DISABLE ;
#define DISABLE { Comp_Generic(op); return; }
#define INVALIDOP { Comp_Generic(op); return; }
namespace MIPSComp {
@@ -67,7 +68,7 @@ void IRFrontend::Comp_FPU3op(MIPSOpcode op) {
case 2: ir.Write(IROp::FMul, fd, fs, ft); break; //F(fd) = F(fs) * F(ft); //mul
case 3: ir.Write(IROp::FDiv, fd, fs, ft); break; //F(fd) = F(fs) / F(ft); //div
default:
DISABLE;
INVALIDOP;
return;
}
}
@@ -90,7 +91,7 @@ void IRFrontend::Comp_FPULS(MIPSOpcode op) {
break;
default:
_dbg_assert_msg_(CPU, 0, "Trying to interpret FPULS instruction that can't be interpreted");
INVALIDOP;
break;
}
}
@@ -131,7 +132,7 @@ void IRFrontend::Comp_FPUComp(MIPSOpcode op) {
mode = IRFpCompareMode::LessEqualUnordered;
break;
default:
DISABLE;
INVALIDOP;
return;
}
ir.Write(IROp::FCmp, (int)mode, fs, ft);
@@ -158,27 +159,17 @@ void IRFrontend::Comp_FPU2op(MIPSOpcode op) {
break;
case 12: //FsI(fd) = (int)floorf(F(fs)+0.5f); break; //round.w.s
{
ir.Write(IROp::FRound, fd, fs);
break;
}
case 13: //FsI(fd) = Rto0(F(fs))); break; //trunc.w.s
{
ir.Write(IROp::FTrunc, fd, fs);
break;
}
case 14://FsI(fd) = (int)ceilf (F(fs)); break; //ceil.w.s
{
ir.Write(IROp::FCeil, fd, fs);
break;
}
case 15: //FsI(fd) = (int)floorf(F(fs)); break; //floor.w.s
{
ir.Write(IROp::FFloor, fd, fs);
break;
}
case 32: //F(fd) = (float)FsI(fs); break; //cvt.s.w
ir.Write(IROp::FCvtSW, fd, fs);
@@ -189,7 +180,7 @@ void IRFrontend::Comp_FPU2op(MIPSOpcode op) {
break;
default:
DISABLE;
INVALIDOP;
}
}
@@ -234,7 +225,7 @@ void IRFrontend::Comp_mxc1(MIPSOpcode op) {
}
return;
default:
DISABLE;
INVALIDOP;
break;
}
}
@@ -41,16 +41,124 @@
// #define CONDITIONAL_DISABLE { Comp_Generic(op); return; }
#define CONDITIONAL_DISABLE ;
#define DISABLE { Comp_Generic(op); return; }
#define INVALIDOP { Comp_Generic(op); return; }
namespace MIPSComp {
void IRFrontend::Comp_ITypeMemLR(MIPSOpcode op, bool load) {
DISABLE;
CONDITIONAL_DISABLE;
int offset = _IMM16;
MIPSGPReg rt = _RT;
MIPSGPReg rs = _RS;
int o = op >> 26;
if (!js.inDelaySlot && opts.unalignedLoadStore) {
// Optimisation: Combine to single unaligned load/store.
const bool isLeft = (o == 34 || o == 42);
MIPSOpcode nextOp = GetOffsetInstruction(1);
// Find a matching shifted load/store in opposite direction with opposite offset.
if (nextOp == (isLeft ? (op.encoding + (4 << 26) - 3) : (op.encoding - (4 << 26) + 3))) {
EatInstruction(nextOp);
if (isLeft) {
// Get the unaligned base offset from the lwr/swr instruction.
offset = (signed short)(nextOp & 0xFFFF);
// Already checked it if we're on the lwr.
CheckMemoryBreakpoint(rs, offset);
}
if (load) {
ir.Write(IROp::Load32, rt, rs, ir.AddConstant(offset));
} else {
ir.Write(IROp::Store32, rt, rs, ir.AddConstant(offset));
}
return;
}
}
int addrReg = IRTEMP_0;
int valueReg = IRTEMP_1;
int maskReg = IRTEMP_2;
int shiftReg = IRTEMP_3;
// addrReg = rs + imm
ir.Write(IROp::AddConst, addrReg, rs, ir.AddConstant(offset));
// shiftReg = (addr & 3) * 8
ir.Write(IROp::AndConst, shiftReg, addrReg, ir.AddConstant(3));
ir.Write(IROp::ShlImm, shiftReg, shiftReg, 3);
// addrReg = addr & 0xfffffffc (for stores, later)
ir.Write(IROp::AndConst, addrReg, addrReg, ir.AddConstant(0xFFFFFFFC));
// valueReg = RAM(addrReg)
ir.Write(IROp::Load32, valueReg, addrReg, ir.AddConstant(0));
switch (o) {
case 34: //lwl
// rt &= (0x00ffffff >> shift)
// Alternatively, could shift to a wall and back (but would require two shifts each way.)
ir.WriteSetConstant(maskReg, 0x00ffffff);
ir.Write(IROp::Shr, maskReg, maskReg, shiftReg);
ir.Write(IROp::And, rt, rt, maskReg);
// valueReg <<= (24 - shift)
ir.Write(IROp::Neg, shiftReg, shiftReg);
ir.Write(IROp::AddConst, shiftReg, shiftReg, ir.AddConstant(24));
ir.Write(IROp::Shl, valueReg, valueReg, shiftReg);
// rt |= valueReg
ir.Write(IROp::Or, rt, rt, valueReg);
break;
case 38: //lwr
// valueReg >>= shift
ir.Write(IROp::Shr, valueReg, valueReg, shiftReg);
// shiftReg = 24 - shift
ir.Write(IROp::Neg, shiftReg, shiftReg);
ir.Write(IROp::AddConst, shiftReg, shiftReg, ir.AddConstant(24));
// rt &= (0xffffff00 << (24 - shift))
// Alternatively, could shift to a wall and back (but would require two shifts each way.)
ir.WriteSetConstant(maskReg, 0xffffff00);
ir.Write(IROp::Shl, maskReg, maskReg, shiftReg);
ir.Write(IROp::And, rt, rt, maskReg);
// rt |= valueReg
ir.Write(IROp::Or, rt, rt, valueReg);
break;
case 42: //swl
// valueReg &= 0xffffff00 << shift
ir.WriteSetConstant(maskReg, 0xffffff00);
ir.Write(IROp::Shl, maskReg, maskReg, shiftReg);
ir.Write(IROp::And, valueReg, valueReg, maskReg);
// shiftReg = 24 - shift
ir.Write(IROp::Neg, shiftReg, shiftReg);
ir.Write(IROp::AddConst, shiftReg, shiftReg, ir.AddConstant(24));
// valueReg |= rt >> (24 - shift)
ir.Write(IROp::Shr, maskReg, rt, shiftReg);
ir.Write(IROp::Or, valueReg, valueReg, maskReg);
break;
case 46: //swr
// valueReg &= 0x00ffffff << (24 - shift)
ir.WriteSetConstant(maskReg, 0x00ffffff);
ir.Write(IROp::Neg, shiftReg, shiftReg);
ir.Write(IROp::AddConst, shiftReg, shiftReg, ir.AddConstant(24));
ir.Write(IROp::Shl, maskReg, maskReg, shiftReg);
ir.Write(IROp::And, valueReg, valueReg, maskReg);
ir.Write(IROp::Neg, shiftReg, shiftReg);
ir.Write(IROp::AddConst, shiftReg, shiftReg, ir.AddConstant(24));
// valueReg |= rt << shift
ir.Write(IROp::Shl, maskReg, rt, shiftReg);
ir.Write(IROp::Or, valueReg, valueReg, maskReg);
break;
default:
INVALIDOP;
return;
}
if (!load) {
// RAM(addrReg) = valueReg
ir.Write(IROp::Store32, valueReg, addrReg, ir.AddConstant(0));
}
}
void IRFrontend::Comp_ITypeMem(MIPSOpcode op) {
CONDITIONAL_DISABLE;
int offset = (signed short)(op & 0xFFFF);
int offset = _IMM16;
MIPSGPReg rt = _RT;
MIPSGPReg rs = _RS;
int o = op >> 26;
@@ -61,7 +169,6 @@ namespace MIPSComp {
CheckMemoryBreakpoint(rs, offset);
int addrReg = IRTEMP_0;
switch (o) {
// Load
case 35:
@@ -92,17 +199,22 @@ namespace MIPSComp {
case 34: //lwl
case 38: //lwr
Comp_ITypeMemLR(op, true);
break;
case 42: //swl
case 46: //swr
DISABLE;
Comp_ITypeMemLR(op, false);
break;
default:
Comp_Generic(op);
INVALIDOP;
return;
}
}
void IRFrontend::Comp_Cache(MIPSOpcode op) {
CONDITIONAL_DISABLE;
// int imm = (s16)(op & 0xFFFF);
// int rs = _RS;
// int addr = R(rs) + imm;
@@ -1929,7 +1929,7 @@ namespace MIPSComp {
ir.Write(IROp::FSub, tempregs[3], sregs[2], sregs[3]);
}
} else {
DISABLE;
INVALIDOP;
}
for (int i = 0; i < n; ++i) {
Oops, something went wrong.

0 comments on commit 263941e

Please sign in to comment.