jit-ir: Implement bit reverse instruction.

This commit is contained in:
Unknown W. Brackets 2016-05-14 18:20:55 -07:00
parent d4e45f4e0a
commit 4ac773e8b4
6 changed files with 42 additions and 11 deletions

View File

@ -54,7 +54,7 @@ void IRFrontend::Comp_IType(MIPSOpcode op) {
MIPSGPReg rs = _RS;
// noop, won't write to ZERO.
if (rt == 0)
if (rt == MIPS_REG_ZERO)
return;
switch (op >> 26) {
@ -92,7 +92,7 @@ void IRFrontend::Comp_RType2(MIPSOpcode op) {
MIPSGPReg rd = _RD;
// Don't change $zr.
if (rd == 0)
if (rd == MIPS_REG_ZERO)
return;
switch (op & 63) {
@ -104,7 +104,8 @@ void IRFrontend::Comp_RType2(MIPSOpcode op) {
ir.Write(IROp::Clz, rd, IRTEMP_0);
break;
default:
DISABLE;
Comp_Generic(op);
break;
}
}
@ -198,23 +199,22 @@ void IRFrontend::Comp_ShiftType(MIPSOpcode op) {
CONDITIONAL_DISABLE;
MIPSGPReg rs = _RS;
MIPSGPReg rd = _RD;
int fd = _FD;
int sa = _SA;
// noop, won't write to ZERO.
if (rd == 0)
if (rd == MIPS_REG_ZERO)
return;
// WARNING : ROTR
// WARNING: srl/rotr and srlv/rotrv share encodings (differentiated using unused bits.)
switch (op & 0x3f) {
case 0: CompShiftImm(op, IROp::ShlImm, sa); break; //sll
case 2: CompShiftImm(op, (rs == 1 ? IROp::RorImm : IROp::ShrImm), sa); break; //srl
case 3: CompShiftImm(op, IROp::SarImm, sa); break; //sra
case 4: CompShiftVar(op, IROp::Shl, IROp::ShlImm); break; //sllv
case 6: CompShiftVar(op, (fd == 1 ? IROp::Ror : IROp::Shr), (fd == 1 ? IROp::RorImm : IROp::ShrImm)); break; //srlv
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:
DISABLE;
Comp_Generic(op);
break;
}
}
@ -229,7 +229,7 @@ void IRFrontend::Comp_Special3(MIPSOpcode op) {
u32 mask = 0xFFFFFFFFUL >> (32 - size);
// Don't change $zr.
if (rt == 0)
if (rt == MIPS_REG_ZERO)
return;
switch (op & 0x3f) {
@ -254,6 +254,10 @@ void IRFrontend::Comp_Special3(MIPSOpcode op) {
ir.Write(IROp::Or, rt, rt, IRTEMP_0);
}
break;
default:
Comp_Generic(op);
break;
}
}
@ -262,8 +266,9 @@ void IRFrontend::Comp_Allegrex(MIPSOpcode op) {
CONDITIONAL_DISABLE;
MIPSGPReg rt = _RT;
MIPSGPReg rd = _RD;
// Don't change $zr.
if (rd == 0)
if (rd == MIPS_REG_ZERO)
return;
switch ((op >> 6) & 31) {
@ -275,7 +280,10 @@ void IRFrontend::Comp_Allegrex(MIPSOpcode op) {
ir.Write(IROp::Ext16to32, rd, rt);
break;
case 20: //bitrev
case 20: // bitrev
ir.Write(IROp::ReverseBits, rd, rt);
break;
default:
Comp_Generic(op);
return;

View File

@ -53,6 +53,7 @@ static const IRMeta irMeta[] = {
{ IROp::MfHi, "MfHi", "G" },
{ IROp::Ext8to32, "Ext8to32", "GG" },
{ IROp::Ext16to32, "Ext16to32", "GG" },
{ IROp::ReverseBits, "ReverseBits", "GG" },
{ IROp::Load8, "Load8", "GGC" },
{ IROp::Load8Ext, "Load8", "GGC" },
{ IROp::Load16, "Load16", "GGC" },

View File

@ -111,6 +111,7 @@ enum class IROp : u8 {
Ext8to32,
Ext16to32,
ReverseBits,
FAdd,
FSub,

View File

@ -87,6 +87,9 @@ u32 IRInterpret(MIPSState *mips, const IRInst *inst, const u32 *constPool, int c
case IROp::Ext16to32:
mips->r[inst->dest] = (s32)(s16)mips->r[inst->src1];
break;
case IROp::ReverseBits:
mips->r[inst->dest] = ReverseBits32(mips->r[inst->src1]);
break;
case IROp::Load8:
mips->r[inst->dest] = Memory::ReadUnchecked_U8(mips->r[inst->src1] + constPool[inst->src2]);

View File

@ -5,4 +5,19 @@
class MIPSState;
struct IRInst;
inline static u32 ReverseBits32(u32 v) {
// http://graphics.stanford.edu/~seander/bithacks.html#ReverseParallel
// swap odd and even bits
v = ((v >> 1) & 0x55555555) | ((v & 0x55555555) << 1);
// swap consecutive pairs
v = ((v >> 2) & 0x33333333) | ((v & 0x33333333) << 2);
// swap nibbles ...
v = ((v >> 4) & 0x0F0F0F0F) | ((v & 0x0F0F0F0F) << 4);
// swap bytes
v = ((v >> 8) & 0x00FF00FF) | ((v & 0x00FF00FF) << 8);
// swap 2-byte long pairs
v = ( v >> 16 ) | ( v << 16);
return v;
}
u32 IRInterpret(MIPSState *mips, const IRInst *inst, const u32 *constPool, int count);

View File

@ -1,6 +1,7 @@
#include <utility>
#include "Common/Log.h"
#include "Core/MIPS/IR/IRInterpreter.h"
#include "Core/MIPS/IR/IRPassSimplify.h"
#include "Core/MIPS/IR/IRRegCache.h"
@ -51,6 +52,7 @@ u32 Evaluate(u32 a, IROp op) {
case IROp::BSwap32: return swap32(a);
case IROp::Ext8to32: return (u32)(s32)(s8)(u8)a;
case IROp::Ext16to32: return (u32)(s32)(s16)(u16)a;
case IROp::ReverseBits: return ReverseBits32(a);
case IROp::Clz: {
int x = 31;
int count = 0;
@ -277,6 +279,7 @@ bool PropagateConstants(const IRWriter &in, IRWriter &out) {
case IROp::BSwap32:
case IROp::Ext8to32:
case IROp::Ext16to32:
case IROp::ReverseBits:
case IROp::Clz:
if (gpr.IsImm(inst.src1)) {
gpr.SetImm(inst.dest, Evaluate(gpr.GetImm(inst.src1), inst.op));