mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Initial work on mult and friends. Fix another bug.
This commit is contained in:
parent
3c5510e5a3
commit
750d520cc7
6 changed files with 133 additions and 31 deletions
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Reference in a new issue