mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-14 15:00:30 +02:00
Decode the unused bits of shifts and Allegrex bit ops as the PSP does
srl/srlv rotate when the low bit of their unused field (rs or sa) is set and shift when it's clear, whatever the other bits hold (cpu/cpu_alu/shift_encodings). The interpreter treated values above 1 as invalid and the other cores shifted. The Allegrex bit ops decode only some bits of sa, so all 32 values are one of wsbh, wsbw, seb, seh and bitrev (cpu/cpu_alu/allegrex_encodings). AllegrexBitOp() gives the canonical one for every core. Special3 function 0x18 does nothing on the PSP, where it was decoded as an alias of 0x20. The interpreter dispatch is regenerated, and its generator now lists each instruction name once. CPUEquivalence no longer skips the srl/srlv encodings. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
5ca12f0050
commit
4849ef020e
10 files changed
+132
-88
No files matched your search
@@ -519,10 +519,10 @@ namespace MIPSComp
|
||||
// WARNING : ROTR
|
||||
switch (op & 0x3f) {
|
||||
case 0: CompShiftImm(op, ST_LSL, sa); break; //sll
|
||||
case 2: CompShiftImm(op, rs == 1 ? ST_ROR : ST_LSR, sa); break; //srl
|
||||
case 2: CompShiftImm(op, (rs & 1) ? ST_ROR : ST_LSR, sa); break; //srl
|
||||
case 3: CompShiftImm(op, ST_ASR, sa); break; //sra
|
||||
case 4: CompShiftVar(op, ST_LSL); break; //sllv
|
||||
case 6: CompShiftVar(op, fd == 1 ? ST_ROR : ST_LSR); break; //srlv
|
||||
case 6: CompShiftVar(op, (fd & 1) ? ST_ROR : ST_LSR); break; //srlv
|
||||
case 7: CompShiftVar(op, ST_ASR); break; //srav
|
||||
|
||||
default:
|
||||
@@ -602,7 +602,7 @@ namespace MIPSComp
|
||||
if (rd == 0)
|
||||
return;
|
||||
|
||||
switch ((op >> 6) & 31) {
|
||||
switch (AllegrexBitOp(op)) {
|
||||
case 16: // seb // R(rd) = SignExtend8ToU32(R(rt));
|
||||
if (gpr.IsImm(rt)) {
|
||||
gpr.SetImm(rd, SignExtend8ToU32(gpr.GetImm(rt)));
|
||||
@@ -656,8 +656,8 @@ namespace MIPSComp
|
||||
if (rd == 0)
|
||||
return;
|
||||
|
||||
switch (op & 0x3ff) {
|
||||
case 0xA0: //wsbh
|
||||
switch (AllegrexBitOp(op)) {
|
||||
case 2: //wsbh
|
||||
if (gpr.IsImm(rt)) {
|
||||
gpr.SetImm(rd, ((gpr.GetImm(rt) & 0xFF00FF00) >> 8) | ((gpr.GetImm(rt) & 0x00FF00FF) << 8));
|
||||
} else {
|
||||
@@ -665,7 +665,7 @@ namespace MIPSComp
|
||||
REV16(gpr.R(rd), gpr.R(rt));
|
||||
}
|
||||
break;
|
||||
case 0xE0: //wsbw
|
||||
case 3: //wsbw
|
||||
if (gpr.IsImm(rt)) {
|
||||
gpr.SetImm(rd, swap32(gpr.GetImm(rt)));
|
||||
} else {
|
||||
|
||||
@@ -422,10 +422,10 @@ void Arm64Jit::Comp_ShiftType(MIPSOpcode op) {
|
||||
// WARNING : ROTR
|
||||
switch (op & 0x3f) {
|
||||
case 0: CompShiftImm(op, ST_LSL, sa); break; //sll
|
||||
case 2: CompShiftImm(op, rs == 1 ? ST_ROR : ST_LSR, sa); break; //srl
|
||||
case 2: CompShiftImm(op, (rs & 1) ? ST_ROR : ST_LSR, sa); break; //srl
|
||||
case 3: CompShiftImm(op, ST_ASR, sa); break; //sra
|
||||
case 4: CompShiftVar(op, ST_LSL); break; //sllv
|
||||
case 6: CompShiftVar(op, fd == 1 ? ST_ROR : ST_LSR); break; //srlv
|
||||
case 6: CompShiftVar(op, (fd & 1) ? ST_ROR : ST_LSR); break; //srlv
|
||||
case 7: CompShiftVar(op, ST_ASR); break; //srav
|
||||
default:
|
||||
DISABLE;
|
||||
@@ -493,7 +493,7 @@ void Arm64Jit::Comp_Allegrex(MIPSOpcode op) {
|
||||
if (rd == 0)
|
||||
return;
|
||||
|
||||
switch ((op >> 6) & 31) {
|
||||
switch (AllegrexBitOp(op)) {
|
||||
case 16: // seb // R(rd) = SignExtend8ToU32(R(rt));
|
||||
if (gpr.IsImm(rt)) {
|
||||
gpr.SetImm(rd, SignExtend8ToU32(gpr.GetImm(rt)));
|
||||
@@ -543,8 +543,8 @@ void Arm64Jit::Comp_Allegrex2(MIPSOpcode op) {
|
||||
if (rd == 0)
|
||||
return;
|
||||
|
||||
switch (op & 0x3ff) {
|
||||
case 0xA0: //wsbh
|
||||
switch (AllegrexBitOp(op)) {
|
||||
case 2: //wsbh
|
||||
if (gpr.IsImm(rt)) {
|
||||
gpr.SetImm(rd, ((gpr.GetImm(rt) & 0xFF00FF00) >> 8) | ((gpr.GetImm(rt) & 0x00FF00FF) << 8));
|
||||
} else {
|
||||
@@ -552,7 +552,7 @@ void Arm64Jit::Comp_Allegrex2(MIPSOpcode op) {
|
||||
REV16(gpr.R(rd), gpr.R(rt));
|
||||
}
|
||||
break;
|
||||
case 0xE0: //wsbw
|
||||
case 3: //wsbw
|
||||
if (gpr.IsImm(rt)) {
|
||||
gpr.SetImm(rd, swap32(gpr.GetImm(rt)));
|
||||
} else {
|
||||
|
||||
@@ -212,13 +212,13 @@ void IRFrontend::Comp_ShiftType(MIPSOpcode op) {
|
||||
if (rd == MIPS_REG_ZERO)
|
||||
return;
|
||||
|
||||
// WARNING: srl/rotr and srlv/rotrv share encodings (differentiated using unused bits.)
|
||||
// WARNING: srl/rotr and srlv/rotrv share encodings, told apart by the low bit of the unused field.
|
||||
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 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); break; //sllv
|
||||
case 6: CompShiftVar(op, (sa == 1 ? IROp::Ror : IROp::Shr)); break; //srlv
|
||||
case 6: CompShiftVar(op, ((sa & 1) ? IROp::Ror : IROp::Shr)); break; //srlv
|
||||
case 7: CompShiftVar(op, IROp::Sar); break; //srav
|
||||
|
||||
default:
|
||||
@@ -292,7 +292,7 @@ void IRFrontend::Comp_Allegrex(MIPSOpcode op) {
|
||||
if (rd == MIPS_REG_ZERO)
|
||||
return;
|
||||
|
||||
switch ((op >> 6) & 31) {
|
||||
switch (AllegrexBitOp(op)) {
|
||||
case 16: // seb // R(rd) = SignExtend8ToU32(R(rt));
|
||||
ir.Write(IROp::Ext8to32, rd, rt);
|
||||
break;
|
||||
@@ -320,11 +320,11 @@ void IRFrontend::Comp_Allegrex2(MIPSOpcode op) {
|
||||
if (rd == MIPS_REG_ZERO)
|
||||
return;
|
||||
|
||||
switch (op & 0x3ff) {
|
||||
case 0xA0: //wsbh
|
||||
switch (AllegrexBitOp(op)) {
|
||||
case 2: //wsbh
|
||||
ir.Write(IROp::BSwap16, rd, rt);
|
||||
break;
|
||||
case 0xE0: //wsbw
|
||||
case 3: //wsbw
|
||||
ir.Write(IROp::BSwap32, rd, rt);
|
||||
break;
|
||||
default:
|
||||
|
||||
+14
-22
@@ -967,34 +967,26 @@ namespace MIPSInt {
|
||||
{
|
||||
case 0: R(rd) = R(rt) << sa; break; //sll
|
||||
case 2:
|
||||
if (_RS == 0) //srl
|
||||
{
|
||||
R(rd) = R(rt) >> sa;
|
||||
break;
|
||||
}
|
||||
else if (_RS == 1) //rotr
|
||||
{
|
||||
// Only the low bit of the unused rs field counts (cpu/cpu_alu/shift_encodings).
|
||||
if (_RS & 1) { //rotr
|
||||
R(rd) = __rotr(R(rt), sa);
|
||||
break;
|
||||
} else { //srl
|
||||
R(rd) = R(rt) >> sa;
|
||||
}
|
||||
else
|
||||
goto wrong;
|
||||
break;
|
||||
|
||||
case 3: R(rd) = (u32)(((s32)R(rt)) >> sa); break; //sra
|
||||
case 4: R(rd) = R(rt) << (R(rs) & 0x1F); break; //sllv
|
||||
case 6:
|
||||
if (_FD == 0) { //srlv
|
||||
R(rd) = R(rt) >> (R(rs)&0x1F);
|
||||
break;
|
||||
} else if (_FD == 1) { // rotrv
|
||||
// Same for the unused sa field.
|
||||
if (_FD & 1) { // rotrv
|
||||
R(rd) = __rotr(R(rt), R(rs));
|
||||
break;
|
||||
} else {
|
||||
goto wrong;
|
||||
} else { //srlv
|
||||
R(rd) = R(rt) >> (R(rs) & 0x1F);
|
||||
}
|
||||
break;
|
||||
case 7: R(rd) = (u32)(((s32)R(rt)) >> (R(rs) & 0x1F)); break; //srav
|
||||
default:
|
||||
wrong:
|
||||
_dbg_assert_msg_(false,"Trying to interpret instruction that can't be interpreted");
|
||||
break;
|
||||
}
|
||||
@@ -1011,7 +1003,7 @@ namespace MIPSInt {
|
||||
return;
|
||||
}
|
||||
|
||||
switch ((op >> 6) & 31) {
|
||||
switch (AllegrexBitOp(op)) {
|
||||
case 16: // seb
|
||||
R(rd) = SignExtend8ToU32(R(rt));
|
||||
break;
|
||||
@@ -1041,11 +1033,11 @@ namespace MIPSInt {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (op & 0x3ff) {
|
||||
case 0xA0: //wsbh
|
||||
switch (AllegrexBitOp(op)) {
|
||||
case 2: //wsbh
|
||||
R(rd) = ((R(rt) & 0xFF00FF00) >> 8) | ((R(rt) & 0x00FF00FF) << 8);
|
||||
break;
|
||||
case 0xE0: //wsbw
|
||||
case 3: //wsbw
|
||||
R(rd) = swap32(R(rt));
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -399,19 +399,49 @@ int ExecInstruction(MIPSState *mips, MIPSOpcode op) {
|
||||
case 4:
|
||||
MIPSInt::Int_Special3(mips, op);
|
||||
return 1;
|
||||
// nop
|
||||
case 24:
|
||||
MIPSInt::Int_Sync(mips, op);
|
||||
return 1;
|
||||
case 32:
|
||||
{
|
||||
switch ((op.encoding >> 6) & 0x1f) {
|
||||
// wsbh, wsbw
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
case 8:
|
||||
case 9:
|
||||
case 10:
|
||||
case 11:
|
||||
case 12:
|
||||
case 13:
|
||||
case 14:
|
||||
case 15:
|
||||
MIPSInt::Int_Allegrex2(mips, op);
|
||||
return 1;
|
||||
// seb, bitrev, seh
|
||||
case 16:
|
||||
case 17:
|
||||
case 18:
|
||||
case 19:
|
||||
case 20:
|
||||
case 21:
|
||||
case 22:
|
||||
case 23:
|
||||
case 24:
|
||||
case 25:
|
||||
case 26:
|
||||
case 27:
|
||||
case 28:
|
||||
case 29:
|
||||
case 30:
|
||||
case 31:
|
||||
MIPSInt::Int_Allegrex(mips, op);
|
||||
return 1;
|
||||
default:
|
||||
@@ -622,7 +652,7 @@ int ExecInstruction(MIPSState *mips, MIPSOpcode op) {
|
||||
case 21:
|
||||
MIPSInt::Int_Vcmov(mips, op);
|
||||
return 2;
|
||||
// vwbn, vwbn, vwbn, vwbn, vwbn, vwbn, vwbn, vwbn
|
||||
// vwbn
|
||||
case 24:
|
||||
case 25:
|
||||
case 26:
|
||||
@@ -647,7 +677,7 @@ int ExecInstruction(MIPSState *mips, MIPSOpcode op) {
|
||||
case 55:
|
||||
{
|
||||
switch ((op.encoding >> 23) & 0x7) {
|
||||
// vpfxs, vpfxs, vpfxt, vpfxt, vpfxd, vpfxd
|
||||
// vpfxs, vpfxt, vpfxd
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
@@ -668,14 +698,14 @@ int ExecInstruction(MIPSState *mips, MIPSOpcode op) {
|
||||
case 60:
|
||||
{
|
||||
switch ((op.encoding >> 21) & 0x1f) {
|
||||
// vmmul, vmmul, vmmul, vmmul
|
||||
// vmmul
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
MIPSInt::Int_Vmmul(mips, op);
|
||||
return 2;
|
||||
// v(h)tfm2, v(h)tfm2, v(h)tfm2, v(h)tfm2, v(h)tfm3, v(h)tfm3, v(h)tfm3, v(h)tfm3, v(h)tfm4, v(h)tfm4, v(h)tfm4, v(h)tfm4
|
||||
// v(h)tfm2, v(h)tfm3, v(h)tfm4
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
@@ -690,14 +720,14 @@ int ExecInstruction(MIPSState *mips, MIPSOpcode op) {
|
||||
case 15:
|
||||
MIPSInt::Int_Vtfm(mips, op);
|
||||
return 2;
|
||||
// vmscl, vmscl, vmscl, vmscl
|
||||
// vmscl
|
||||
case 16:
|
||||
case 17:
|
||||
case 18:
|
||||
case 19:
|
||||
MIPSInt::Int_Vmscl(mips, op);
|
||||
return 2;
|
||||
// vcrsp.t/vqmul.q, vcrsp.t/vqmul.q, vcrsp.t/vqmul.q, vcrsp.t/vqmul.q
|
||||
// vcrsp.t/vqmul.q
|
||||
case 20:
|
||||
case 21:
|
||||
case 22:
|
||||
|
||||
@@ -73,6 +73,20 @@ inline uint32_t SignExtend16ToU32(MIPSOpcode op) {
|
||||
return SignExtend16ToU32(op.encoding);
|
||||
}
|
||||
|
||||
// The Allegrex bit ops (special3, function 0x20) only decode some bits of the sa field, so every
|
||||
// value is one of them (cpu/cpu_alu/allegrex_encodings). Returns the canonical sa: 2 wsbh, 3 wsbw,
|
||||
// 16 seb, 20 bitrev, 24 seh.
|
||||
inline int AllegrexBitOp(MIPSOpcode op) {
|
||||
int sa = (op >> 6) & 31;
|
||||
if (!(sa & 0x10)) {
|
||||
return 2 | (sa & 1);
|
||||
}
|
||||
if (sa & 4) {
|
||||
return 20;
|
||||
}
|
||||
return (sa & 8) ? 24 : 16;
|
||||
}
|
||||
|
||||
namespace MIPSCodeUtils
|
||||
{
|
||||
u32 GetCallTarget(u32 addr);
|
||||
|
||||
@@ -254,9 +254,9 @@ namespace MIPSDis
|
||||
int rd = _RD;
|
||||
int sa = (op>>6) & 0x1F;
|
||||
const char *name = MIPSGetName(op);
|
||||
if (((op & 0x3f) == 2) && rs == 1)
|
||||
if (((op & 0x3f) == 2) && (rs & 1))
|
||||
name = "rotr";
|
||||
if (((op & 0x3f) == 6) && sa == 1)
|
||||
if (((op & 0x3f) == 6) && (sa & 1))
|
||||
name = "rotrv";
|
||||
snprintf(out, outSize, "%s\t%s, %s, 0x%X", name, RN(rd), RN(rt), sa);
|
||||
}
|
||||
@@ -267,7 +267,7 @@ namespace MIPSDis
|
||||
int rd = _RD;
|
||||
int sa = (op>>6) & 0x1F;
|
||||
const char *name = MIPSGetName(op);
|
||||
if (((op & 0x3f) == 6) && sa == 1)
|
||||
if (((op & 0x3f) == 6) && (sa & 1))
|
||||
name = "rotrv";
|
||||
snprintf(out, outSize, "%s\t%s, %s, %s", name, RN(rd), RN(rt), RN(rs));
|
||||
}
|
||||
|
||||
+40
-24
@@ -287,8 +287,8 @@ static const MIPSInstruction tableSpecial3[64] = // 011111 ..... ..... ..... ...
|
||||
//16
|
||||
INVALID_X_8,
|
||||
//24
|
||||
// TODO: Is this right? Or should it only be 32? Comment above (24) was mistakenly 32 before.
|
||||
ENCODING(ALLEGREX0),
|
||||
// Does nothing, whatever the other fields hold (cpu/cpu_alu/allegrex_encodings).
|
||||
INSTR("nop", JITFUNC(Comp_DoNothing), Dis_Generic, Int_Sync, 0),
|
||||
INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID,
|
||||
//32
|
||||
ENCODING(ALLEGREX0),
|
||||
@@ -773,35 +773,46 @@ static const MIPSInstruction tableVFPU9[32] = // 110100 00010 xxxxx . ....... .
|
||||
INVALID, INVALID, INVALID, INVALID,
|
||||
};
|
||||
|
||||
static const MIPSInstruction tableALLEGREX0[32] = // 011111 ..... ..... ..... xxxxx 100000 - or ending with 011000?
|
||||
// Only some bits of the op are decoded, so every value is one of the five (see AllegrexBitOp).
|
||||
static const MIPSInstruction tableALLEGREX0[32] = // 011111 ..... ..... ..... xxxxx 100000
|
||||
{
|
||||
INVALID,
|
||||
INVALID,
|
||||
INSTR("wsbh", JITFUNC(Comp_Allegrex2), Dis_Allegrex2, Int_Allegrex2, IN_RT|OUT_RD),
|
||||
INSTR("wsbw", JITFUNC(Comp_Allegrex2), Dis_Allegrex2, Int_Allegrex2, IN_RT|OUT_RD),
|
||||
INVALID, INVALID, INVALID, INVALID,
|
||||
INSTR("wsbh", JITFUNC(Comp_Allegrex2), Dis_Allegrex2, Int_Allegrex2, IN_RT|OUT_RD),
|
||||
INSTR("wsbw", JITFUNC(Comp_Allegrex2), Dis_Allegrex2, Int_Allegrex2, IN_RT|OUT_RD),
|
||||
INSTR("wsbh", JITFUNC(Comp_Allegrex2), Dis_Allegrex2, Int_Allegrex2, IN_RT|OUT_RD),
|
||||
INSTR("wsbw", JITFUNC(Comp_Allegrex2), Dis_Allegrex2, Int_Allegrex2, IN_RT|OUT_RD),
|
||||
INSTR("wsbh", JITFUNC(Comp_Allegrex2), Dis_Allegrex2, Int_Allegrex2, IN_RT|OUT_RD),
|
||||
INSTR("wsbw", JITFUNC(Comp_Allegrex2), Dis_Allegrex2, Int_Allegrex2, IN_RT|OUT_RD),
|
||||
//8
|
||||
INVALID_X_8,
|
||||
INSTR("wsbh", JITFUNC(Comp_Allegrex2), Dis_Allegrex2, Int_Allegrex2, IN_RT|OUT_RD),
|
||||
INSTR("wsbw", JITFUNC(Comp_Allegrex2), Dis_Allegrex2, Int_Allegrex2, IN_RT|OUT_RD),
|
||||
INSTR("wsbh", JITFUNC(Comp_Allegrex2), Dis_Allegrex2, Int_Allegrex2, IN_RT|OUT_RD),
|
||||
INSTR("wsbw", JITFUNC(Comp_Allegrex2), Dis_Allegrex2, Int_Allegrex2, IN_RT|OUT_RD),
|
||||
INSTR("wsbh", JITFUNC(Comp_Allegrex2), Dis_Allegrex2, Int_Allegrex2, IN_RT|OUT_RD),
|
||||
INSTR("wsbw", JITFUNC(Comp_Allegrex2), Dis_Allegrex2, Int_Allegrex2, IN_RT|OUT_RD),
|
||||
INSTR("wsbh", JITFUNC(Comp_Allegrex2), Dis_Allegrex2, Int_Allegrex2, IN_RT|OUT_RD),
|
||||
INSTR("wsbw", JITFUNC(Comp_Allegrex2), Dis_Allegrex2, Int_Allegrex2, IN_RT|OUT_RD),
|
||||
//16
|
||||
INSTR("seb", JITFUNC(Comp_Allegrex), Dis_Allegrex,Int_Allegrex, IN_RT|OUT_RD),
|
||||
INVALID,
|
||||
INVALID,
|
||||
INVALID,
|
||||
INSTR("seb", JITFUNC(Comp_Allegrex), Dis_Allegrex, Int_Allegrex, IN_RT|OUT_RD),
|
||||
INSTR("seb", JITFUNC(Comp_Allegrex), Dis_Allegrex, Int_Allegrex, IN_RT|OUT_RD),
|
||||
INSTR("seb", JITFUNC(Comp_Allegrex), Dis_Allegrex, Int_Allegrex, IN_RT|OUT_RD),
|
||||
INSTR("seb", JITFUNC(Comp_Allegrex), Dis_Allegrex, Int_Allegrex, IN_RT|OUT_RD),
|
||||
//20
|
||||
INSTR("bitrev", JITFUNC(Comp_Allegrex), Dis_Allegrex,Int_Allegrex, IN_RT|OUT_RD),
|
||||
INVALID,
|
||||
INVALID,
|
||||
INVALID,
|
||||
INSTR("bitrev", JITFUNC(Comp_Allegrex), Dis_Allegrex, Int_Allegrex, IN_RT|OUT_RD),
|
||||
INSTR("bitrev", JITFUNC(Comp_Allegrex), Dis_Allegrex, Int_Allegrex, IN_RT|OUT_RD),
|
||||
INSTR("bitrev", JITFUNC(Comp_Allegrex), Dis_Allegrex, Int_Allegrex, IN_RT|OUT_RD),
|
||||
INSTR("bitrev", JITFUNC(Comp_Allegrex), Dis_Allegrex, Int_Allegrex, IN_RT|OUT_RD),
|
||||
//24
|
||||
INSTR("seh", JITFUNC(Comp_Allegrex), Dis_Allegrex,Int_Allegrex, IN_RT|OUT_RD),
|
||||
INVALID,
|
||||
INVALID,
|
||||
INVALID,
|
||||
INSTR("seh", JITFUNC(Comp_Allegrex), Dis_Allegrex, Int_Allegrex, IN_RT|OUT_RD),
|
||||
INSTR("seh", JITFUNC(Comp_Allegrex), Dis_Allegrex, Int_Allegrex, IN_RT|OUT_RD),
|
||||
INSTR("seh", JITFUNC(Comp_Allegrex), Dis_Allegrex, Int_Allegrex, IN_RT|OUT_RD),
|
||||
INSTR("seh", JITFUNC(Comp_Allegrex), Dis_Allegrex, Int_Allegrex, IN_RT|OUT_RD),
|
||||
//28
|
||||
INVALID,
|
||||
INVALID,
|
||||
INVALID,
|
||||
INVALID,
|
||||
INSTR("bitrev", JITFUNC(Comp_Allegrex), Dis_Allegrex, Int_Allegrex, IN_RT|OUT_RD),
|
||||
INSTR("bitrev", JITFUNC(Comp_Allegrex), Dis_Allegrex, Int_Allegrex, IN_RT|OUT_RD),
|
||||
INSTR("bitrev", JITFUNC(Comp_Allegrex), Dis_Allegrex, Int_Allegrex, IN_RT|OUT_RD),
|
||||
INSTR("bitrev", JITFUNC(Comp_Allegrex), Dis_Allegrex, Int_Allegrex, IN_RT|OUT_RD),
|
||||
};
|
||||
|
||||
static const MIPSInstruction tableEMU[4] = {
|
||||
@@ -973,10 +984,15 @@ static void EmitDispatchLevel(std::string &out, MipsEncoding encoding, int inden
|
||||
|
||||
if (instr.altEncoding == Instruc) {
|
||||
std::string names;
|
||||
std::vector<std::string_view> seen;
|
||||
for (u32 idx : group) {
|
||||
std::string_view name = table[idx].name;
|
||||
if (std::find(seen.begin(), seen.end(), name) != seen.end())
|
||||
continue;
|
||||
seen.push_back(name);
|
||||
if (!names.empty())
|
||||
names += ", ";
|
||||
names += table[idx].name;
|
||||
names += name;
|
||||
}
|
||||
out += ind + StringFromFormat("// %s\n", names.c_str());
|
||||
for (u32 idx : group)
|
||||
|
||||
@@ -706,11 +706,11 @@ namespace MIPSComp
|
||||
switch (op & 0x3f)
|
||||
{
|
||||
case 0: CompShiftImm(op, &XEmitter::SHL, &ShiftType_ImmLogicalLeft); break;
|
||||
case 2: CompShiftImm(op, rs == 1 ? &XEmitter::ROR : &XEmitter::SHR, rs == 1 ? &ShiftType_ImmRotateRight : &ShiftType_ImmLogicalRight); break; // srl, rotr
|
||||
case 2: CompShiftImm(op, (rs & 1) ? &XEmitter::ROR : &XEmitter::SHR, (rs & 1) ? &ShiftType_ImmRotateRight : &ShiftType_ImmLogicalRight); break; // srl, rotr
|
||||
case 3: CompShiftImm(op, &XEmitter::SAR, &ShiftType_ImmArithRight); break; // sra
|
||||
|
||||
case 4: CompShiftVar(op, &XEmitter::SHL, &ShiftType_ImmLogicalLeft); break; //sllv
|
||||
case 6: CompShiftVar(op, fd == 1 ? &XEmitter::ROR : &XEmitter::SHR, fd == 1 ? &ShiftType_ImmRotateRight : &ShiftType_ImmLogicalRight); break; //srlv
|
||||
case 6: CompShiftVar(op, (fd & 1) ? &XEmitter::ROR : &XEmitter::SHR, (fd & 1) ? &ShiftType_ImmRotateRight : &ShiftType_ImmLogicalRight); break; //srlv
|
||||
case 7: CompShiftVar(op, &XEmitter::SAR, &ShiftType_ImmArithRight); break; //srav
|
||||
|
||||
default:
|
||||
@@ -818,7 +818,7 @@ namespace MIPSComp
|
||||
if (rd == MIPS_REG_ZERO)
|
||||
return;
|
||||
|
||||
switch ((op >> 6) & 31)
|
||||
switch (AllegrexBitOp(op))
|
||||
{
|
||||
case 16: // seb // R(rd) = SignExtend8ToU32(R(rt));
|
||||
if (gpr.IsImm(rt))
|
||||
@@ -926,9 +926,9 @@ namespace MIPSComp
|
||||
if (rd == MIPS_REG_ZERO)
|
||||
return;
|
||||
|
||||
switch (op & 0x3ff)
|
||||
switch (AllegrexBitOp(op))
|
||||
{
|
||||
case 0xA0: //wsbh
|
||||
case 2: //wsbh
|
||||
if (gpr.IsImm(rt)) {
|
||||
u32 rtImm = gpr.GetImm(rt);
|
||||
gpr.SetImm(rd, ((rtImm & 0xFF00FF00) >> 8) | ((rtImm & 0x00FF00FF) << 8));
|
||||
@@ -943,7 +943,7 @@ namespace MIPSComp
|
||||
ROR(32, gpr.R(rd), Imm8(16));
|
||||
gpr.UnlockAll();
|
||||
break;
|
||||
case 0xE0: //wsbw
|
||||
case 3: //wsbw
|
||||
if (gpr.IsImm(rt)) {
|
||||
gpr.SetImm(rd, swap32(gpr.GetImm(rt)));
|
||||
break;
|
||||
|
||||
@@ -567,14 +567,6 @@ static u32 GenerateFuzzOp(FuzzRng &rng, const char *classes) {
|
||||
if (!IsFuzzableName(MIPSGetName(MIPSOpcode(op)))) {
|
||||
continue;
|
||||
}
|
||||
// srl and srlv with other bits than rotr's set in the unused field: the interpreter does
|
||||
// nothing, the rest shift. TODO: Test on hardware.
|
||||
if (top == 0 && (op & 0x3F) == 2 && ((op >> 21) & 0x1F) > 1) {
|
||||
continue;
|
||||
}
|
||||
if (top == 0 && (op & 0x3F) == 6 && ((op >> 6) & 0x1F) > 1) {
|
||||
continue;
|
||||
}
|
||||
// Not by MEMTYPE, which movz and movn alias with their CONDTYPE.
|
||||
if (std::find(std::begin(memOps), std::end(memOps), top) != std::end(memOps)) {
|
||||
op = FixupMemOp(op, rng);
|
||||
|
||||
Reference in new issue
Block a user