Initial work on mult and friends. Fix another bug.

This commit is contained in:
Henrik Rydgard 2016-05-07 22:27:58 +02:00
parent 3c5510e5a3
commit 750d520cc7
6 changed files with 133 additions and 31 deletions

View file

@ -153,21 +153,6 @@ void IRJit::CompType3(MIPSGPReg rd, MIPSGPReg rs, MIPSGPReg rt, IROp op, IROp co
}
return;
}
/*
if (gpr.IsImm(rt) || (gpr.IsImm(rs) && symmetric)) {
MIPSGPReg lhs = gpr.IsImm(rs) ? rt : rs;
MIPSGPReg rhs = gpr.IsImm(rs) ? rs : rt;
u32 rhsImm = gpr.GetImm(rhs);
gpr.MapDirtyIn(rd, lhs);
ir.Write(constOp, rd, lhs, ir.AddConstant(rhsImm));
// If rd is rhs, we may have lost it in the MapDirtyIn(). lhs was kept.
// This means the rhsImm value was never flushed to rhs, and would be garbage.
if (rd == rhs) {
// Luckily, it was just an imm.
gpr.SetImm(rhs, rhsImm);
}
return;
}*/
// Can't do the RSB optimization on ARM64 - no RSB!
@ -463,15 +448,77 @@ void IRJit::Comp_Allegrex2(MIPSOpcode op) {
void IRJit::Comp_MulDivType(MIPSOpcode op) {
CONDITIONAL_DISABLE;
DISABLE;
MIPSGPReg rt = _RT;
MIPSGPReg rs = _RS;
MIPSGPReg rd = _RD;
// Note that in all cases below, LO is actually mapped to HI:LO.
// That is, the host reg is 64 bits and has HI at the top.
// HI is not mappable.
switch (op & 63) {
case 16: // R(rd) = HI; //mfhi
if (rd != MIPS_REG_ZERO) {
gpr.MapDirty(rd);
ir.Write(IROp::MfHi, rd);
}
break;
DISABLE;
case 17: // HI = R(rs); //mthi
gpr.MapIn(rs);
ir.Write(IROp::MtHi, 0, rs);
break;
case 18: // R(rd) = LO; break; //mflo
if (rd != MIPS_REG_ZERO) {
gpr.MapDirty(rd);
ir.Write(IROp::MfLo, rd);
}
break;
case 19: // LO = R(rs); break; //mtlo
gpr.MapIn(rs);
ir.Write(IROp::MtLo, 0, rs);
break;
case 24: //mult (the most popular one). lo,hi = signed mul (rs * rt)
ir.Write(IROp::Mult, 0, rs, rt);
break;
case 25: //multu (2nd) lo,hi = unsigned mul (rs * rt)
ir.Write(IROp::MultU, 0, rs, rt);
break;
case 26: //div
DISABLE;
ir.Write(IROp::Div, 0, rs, rt);
break;
case 27: //divu
DISABLE;
ir.Write(IROp::DivU, 0, rs, rt);
break;
case 28: //madd
DISABLE;
ir.Write(IROp::Madd, 0, rs, rt);
break;
case 29: //maddu
DISABLE;
ir.Write(IROp::MaddU, 0, rs, rt);
break;
case 46: // msub
DISABLE;
ir.Write(IROp::Msub, 0, rs, rt);
break;
case 47: // msubu
DISABLE;
ir.Write(IROp::MsubU, 0, rs, rt);
break;
default:
DISABLE;
}
}
}

View file

@ -380,7 +380,7 @@ void IRJit::Comp_Syscall(MIPSOpcode op) {
}
void IRJit::Comp_Break(MIPSOpcode op) {
Comp_Generic(op);
ir.Write(IROp::Break);
js.compiling = false;
}

View file

@ -8,7 +8,7 @@
#include "math/math_util.h"
IRMeta meta[] = {
static const IRMeta irMeta[] = {
{ IROp::SetConst, "SetConst", "GC_" },
{ IROp::Mov, "Mov", "GG" },
{ IROp::Add, "Add", "GGG" },
@ -42,7 +42,18 @@ IRMeta meta[] = {
{ IROp::Min, "Min", "GGG" },
{ IROp::BSwap16, "BSwap16", "GG" },
{ IROp::BSwap32, "BSwap32", "GG" },
{ IROp::Mul, "Mul", "_GG" },
{ IROp::Mult, "Mult", "_GG" },
{ IROp::MultU, "MultU", "_GG" },
{ IROp::Madd, "Madd", "_GG" },
{ IROp::MaddU, "MaddU", "_GG" },
{ IROp::Msub, "Msub", "_GG" },
{ IROp::MsubU, "MsubU", "_GG" },
{ IROp::Div, "Div", "_GG" },
{ IROp::DivU, "DivU", "_GG" },
{ IROp::MtLo, "MtLo", "_G" },
{ IROp::MtHi, "MtHi", "_G" },
{ IROp::MfLo, "MfLo", "G" },
{ IROp::MfHi, "MfHi", "G" },
{ IROp::Ext8to32, "Ext8to32", "GG" },
{ IROp::Ext16to32, "Ext16to32", "GG" },
{ IROp::Load8, "Load8", "GGC" },
@ -81,15 +92,16 @@ IRMeta meta[] = {
{ IROp::ExitToConstIfLeZ, "ExitIfLeZ", "CG" },
{ IROp::ExitToConstIfLtZ, "ExitIfLtZ", "CG" },
{ IROp::ExitToReg, "ExitToReg", "G" },
{ IROp::Syscall, "Syscall", "_C"},
{ IROp::Syscall, "Syscall", "_C" },
{ IROp::Break, "Break", ""},
{ IROp::SetPC, "SetPC", "_G"},
};
const IRMeta *metaIndex[256];
void InitIR() {
for (size_t i = 0; i < ARRAY_SIZE(meta); i++) {
metaIndex[(int)meta[i].op] = &meta[i];
for (size_t i = 0; i < ARRAY_SIZE(irMeta); i++) {
metaIndex[(int)irMeta[i].op] = &irMeta[i];
}
}
@ -251,6 +263,32 @@ u32 IRInterpret(MIPSState *mips, const IRInst *inst, const u32 *constPool, int c
mips->r[inst->dest] = (s32)mips->r[inst->src1] < (s32)mips->r[inst->src2] ? mips->r[inst->src1] : mips->r[inst->src2];
break;
case IROp::MtLo:
mips->lo = mips->r[inst->src1];
break;
case IROp::MtHi:
mips->hi = mips->r[inst->src1];
break;
case IROp::MfLo:
mips->r[inst->dest] = mips->lo;
break;
case IROp::MfHi:
mips->r[inst->dest] = mips->hi;
break;
case IROp::Mult:
{
s64 result = (s64)(s32)mips->r[inst->src1] * (s64)(s32)mips->r[inst->src2];
memcpy(&mips->lo, &result, 8);
break;
}
case IROp::MultU:
{
u64 result = (u64)mips->r[inst->src1] * (u64)mips->r[inst->src2];
memcpy(&mips->lo, &result, 8);
break;
}
case IROp::BSwap16:
{
u32 x = mips->r[inst->src1];
@ -381,6 +419,10 @@ u32 IRInterpret(MIPSState *mips, const IRInst *inst, const u32 *constPool, int c
mips->pc = mips->r[inst->src1];
break;
case IROp::SetPCConst:
mips->pc = constPool[inst->src1];
break;
case IROp::Syscall:
// SetPC was executed before.
{
@ -402,9 +444,13 @@ u32 IRInterpret(MIPSState *mips, const IRInst *inst, const u32 *constPool, int c
const ReplacementTableEntry *f = GetReplacementFunc(funcIndex);
int cycles = f->replaceFunc();
mips->downcount -= cycles;
break;
return mips->r[MIPS_REG_RA];
}
case IROp::Break:
Crash();
break;
default:
Crash();
}
@ -412,7 +458,7 @@ u32 IRInterpret(MIPSState *mips, const IRInst *inst, const u32 *constPool, int c
}
// If we got here, the block was badly constructed.
// Crash();
Crash();
return 0;
}

View file

@ -66,13 +66,19 @@ enum class IROp : u8 {
BSwap16, // Swaps both the high and low byte pairs.
BSwap32,
// Hi/Lo semantics preserved.
Mul,
MulU,
// Weird Hi/Lo semantics preserved. Too annoying to do something more generic.
MtLo,
MtHi,
MfLo,
MfHi,
Mult,
MultU,
Madd,
MaddU,
Msub,
MsubU,
Div,
DivU,
// These take a constant from the pool as an offset.
// Loads from a constant address can be represented by using r0.
@ -152,6 +158,7 @@ enum class IROp : u8 {
Syscall,
SetPC, // hack to make syscall returns work
SetPCConst, // hack to make replacement know PC
CallReplacement,
Break,
};

View file

@ -273,6 +273,7 @@ void IRJit::DoJit(u32 em_address, IRBlock *b) {
}
}
if (logBlocks > 0 && dontLogBlocks == 0) {
ILOG("=============== IR (%d instructions) ===============", js.numInstructions);
for (int i = 0; i < ir.GetInstructions().size(); i++) {
@ -326,7 +327,7 @@ void IRJit::Comp_ReplacementFunc(MIPSOpcode op) {
} else if (entry->replaceFunc) {
FlushAll();
RestoreRoundingMode();
ir.Write(IROp::SetPC, 0, ir.AddConstant(GetCompilerPC()));
ir.Write(IROp::SetPCConst, 0, ir.AddConstant(GetCompilerPC()));
ir.Write(IROp::CallReplacement, 0, ir.AddConstant(index));
if (entry->flags & (REPFLAG_HOOKENTER | REPFLAG_HOOKEXIT)) {

View file

@ -2,4 +2,5 @@
#include "Core/MIPS/IR/IRInst.h"
// Dumb example of a simplification pass that can't add or remove instructions.
void SimplifyInPlace(IRInst *inst, int count, const u32 *constPool);