mirror of https://github.com/PCSX2/pcsx2.git
- Various fixes to MMI and more changes to opcodes to mimic ps2 behavior, thanks to Nneeve.
- Brought back a gamefix for Persona games. They still have missing geometry without it (VU clip flag problem) git-svn-id: http://pcsx2.googlecode.com/svn/trunk@835 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
95c7ce1dbc
commit
157e696182
|
@ -66,6 +66,7 @@ extern SessionOverrideFlags g_Session;
|
|||
//------------ SPECIAL GAME FIXES!!! ---------------
|
||||
#define CHECK_VUADDSUBHACK (Config.GameFixes & 0x1) // Special Fix for Tri-ace games, they use an encryption algorithm that requires VU addi opcode to be bit-accurate.
|
||||
#define CHECK_FPUCOMPAREHACK (Config.GameFixes & 0x4) // Special Fix for Digimon Rumble Arena 2, fixes spinning/hanging on intro-menu.
|
||||
#define CHECK_VUCLIPFLAGHACK (Config.GameFixes & 0x2) // Special Fix for Persona games, maybe others. It's to do with the VU clip flag (again).
|
||||
#define CHECK_FPUMULHACK (Config.GameFixes & 0x8) // Special Fix for Tales of Destiny hangs.
|
||||
//------------ Advanced Options!!! ---------------
|
||||
#define CHECK_VU_OVERFLOW (Config.vuOptions & 0x1)
|
||||
|
|
145
pcsx2/MMI.cpp
145
pcsx2/MMI.cpp
|
@ -113,11 +113,22 @@ namespace OpcodeImpl {
|
|||
if (_Rd_) cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.LO.UD[1];
|
||||
}
|
||||
|
||||
void DIV1() {
|
||||
if (cpuRegs.GPR.r[_Rt_].SL[0] != 0) {
|
||||
void DIV1() {
|
||||
if (cpuRegs.GPR.r[_Rs_].UL[0] == 0x80000000 && cpuRegs.GPR.r[_Rt_].UL[0] == 0xffffffff)
|
||||
{
|
||||
cpuRegs.LO.SD[1] = (s32)0x80000000;
|
||||
cpuRegs.HI.SD[1] = (s32)0x0;
|
||||
}
|
||||
else if (cpuRegs.GPR.r[_Rt_].SL[0] != 0)
|
||||
{
|
||||
cpuRegs.LO.SD[1] = cpuRegs.GPR.r[_Rs_].SL[0] / cpuRegs.GPR.r[_Rt_].SL[0];
|
||||
cpuRegs.HI.SD[1] = cpuRegs.GPR.r[_Rs_].SL[0] % cpuRegs.GPR.r[_Rt_].SL[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
cpuRegs.LO.SD[1] = (cpuRegs.GPR.r[_Rs_].SL[0] < 0) ? 1 : -1;
|
||||
cpuRegs.HI.SD[1] = cpuRegs.GPR.r[_Rs_].SL[0];
|
||||
}
|
||||
}
|
||||
|
||||
void DIVU1()
|
||||
|
@ -129,6 +140,11 @@ namespace OpcodeImpl {
|
|||
cpuRegs.LO.SD[1] = (s32)(cpuRegs.GPR.r[_Rs_].UL[0] / cpuRegs.GPR.r[_Rt_].UL[0]);
|
||||
cpuRegs.HI.SD[1] = (s32)(cpuRegs.GPR.r[_Rs_].UL[0] % cpuRegs.GPR.r[_Rt_].UL[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
cpuRegs.LO.SD[1] = -1;
|
||||
cpuRegs.HI.SD[1] = cpuRegs.GPR.r[_Rs_].SL[0];
|
||||
}
|
||||
}
|
||||
|
||||
namespace MMI {
|
||||
|
@ -187,19 +203,19 @@ void PMFHL() {
|
|||
|
||||
case 0x02: // SLW
|
||||
{
|
||||
u64 TempU64 = ((u64)cpuRegs.HI.UL[0] << 32) | (u64)cpuRegs.LO.UL[0];
|
||||
if (TempU64 >= 0x000000007fffffffLL) {
|
||||
s64 TempS64 = ((u64)cpuRegs.HI.UL[0] << 32) | (u64)cpuRegs.LO.UL[0];
|
||||
if (TempS64 >= 0x000000007fffffffLL) {
|
||||
cpuRegs.GPR.r[_Rd_].UD[0] = 0x000000007fffffffLL;
|
||||
} else if (TempU64 <= 0xffffffff80000000LL) {
|
||||
} else if (TempS64 <= 0xffffffff80000000LL) {
|
||||
cpuRegs.GPR.r[_Rd_].UD[0] = 0xffffffff80000000LL;
|
||||
} else {
|
||||
cpuRegs.GPR.r[_Rd_].UD[0] = (s64)cpuRegs.LO.SL[0];
|
||||
}
|
||||
|
||||
TempU64 = ((u64)cpuRegs.HI.UL[2] << 32) | (u64)cpuRegs.LO.UL[2];
|
||||
if (TempU64 >= 0x000000007fffffffLL) {
|
||||
TempS64 = ((u64)cpuRegs.HI.UL[2] << 32) | (u64)cpuRegs.LO.UL[2];
|
||||
if (TempS64 >= 0x000000007fffffffLL) {
|
||||
cpuRegs.GPR.r[_Rd_].UD[1] = 0x000000007fffffffLL;
|
||||
} else if (TempU64 <= 0xffffffff80000000LL) {
|
||||
} else if (TempS64 <= 0xffffffff80000000LL) {
|
||||
cpuRegs.GPR.r[_Rd_].UD[1] = 0xffffffff80000000LL;
|
||||
} else {
|
||||
cpuRegs.GPR.r[_Rd_].UD[1] = (s64)cpuRegs.LO.SL[2];
|
||||
|
@ -603,7 +619,7 @@ __forceinline void _PADDSB(int n)
|
|||
|
||||
if (sTemp16 > 0x7F)
|
||||
cpuRegs.GPR.r[_Rd_].UC[n] = 0x7F;
|
||||
else if ((sTemp16 < 0x180) && (sTemp16 >= 0x100))
|
||||
else if (sTemp16 < (s16)0xff80)
|
||||
cpuRegs.GPR.r[_Rd_].UC[n] = 0x80;
|
||||
else
|
||||
cpuRegs.GPR.r[_Rd_].UC[n] = (s8)sTemp16;
|
||||
|
@ -624,7 +640,7 @@ static __forceinline void _PSUBSB( u8 n )
|
|||
|
||||
if (sTemp16 >= 0x7F)
|
||||
cpuRegs.GPR.r[_Rd_].UC[n] = 0x7F;
|
||||
else if ((sTemp16 < 0x180) && (sTemp16 >= 0x100))
|
||||
else if (sTemp16 <= (s16)0xff80)
|
||||
cpuRegs.GPR.r[_Rd_].UC[n] = 0x80;
|
||||
else
|
||||
cpuRegs.GPR.r[_Rd_].UC[n] = (s8)sTemp16;
|
||||
|
@ -727,7 +743,12 @@ void PPAC5() {
|
|||
|
||||
__forceinline void _PABSW(int n)
|
||||
{
|
||||
cpuRegs.GPR.r[_Rd_].UL[n] = abs(cpuRegs.GPR.r[_Rt_].SL[n]);
|
||||
if (cpuRegs.GPR.r[_Rt_].UL[n] == 0x80000000)
|
||||
cpuRegs.GPR.r[_Rd_].UL[n] = 0x7fffffff; //clamp
|
||||
else if (cpuRegs.GPR.r[_Rt_].SL[n] < 0)
|
||||
cpuRegs.GPR.r[_Rd_].UL[n] = - cpuRegs.GPR.r[_Rt_].SL[n];
|
||||
else
|
||||
cpuRegs.GPR.r[_Rd_].UL[n] = cpuRegs.GPR.r[_Rt_].SL[n];
|
||||
}
|
||||
|
||||
void PABSW() {
|
||||
|
@ -773,7 +794,12 @@ void PADSBH() {
|
|||
|
||||
__forceinline void _PABSH(int n)
|
||||
{
|
||||
cpuRegs.GPR.r[_Rd_].US[n] = abs(cpuRegs.GPR.r[_Rt_].SS[n]);
|
||||
if (cpuRegs.GPR.r[_Rt_].US[n] == 0x8000)
|
||||
cpuRegs.GPR.r[_Rd_].US[n] = 0x7fff; //clamp
|
||||
else if (cpuRegs.GPR.r[_Rt_].SS[n] < 0)
|
||||
cpuRegs.GPR.r[_Rd_].US[n] = - cpuRegs.GPR.r[_Rt_].SS[n];
|
||||
else
|
||||
cpuRegs.GPR.r[_Rd_].US[n] = cpuRegs.GPR.r[_Rt_].SS[n];
|
||||
}
|
||||
|
||||
void PABSH() {
|
||||
|
@ -994,38 +1020,39 @@ void QFSRV() { // JayteeMaster: changed a bit to avoid screw up
|
|||
GPR_reg Rd;
|
||||
if (!_Rd_) return;
|
||||
|
||||
if (cpuRegs.sa == 0) {
|
||||
u32 sa_amt = cpuRegs.sa << 3;
|
||||
if (sa_amt == 0) {
|
||||
cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rt_].UD[0];
|
||||
cpuRegs.GPR.r[_Rd_].UD[1] = cpuRegs.GPR.r[_Rt_].UD[1];
|
||||
//saZero++;
|
||||
//if( saZero >= 388800 )
|
||||
//Console::WriteLn( "SA Is Zero, Bitch: %d zeros and counting.", params saZero );
|
||||
} else {
|
||||
//Console::WriteLn( "SA Properly Valued at: %d (after %d zeros)", params cpuRegs.sa, saZero );
|
||||
//Console::WriteLn( "SA Properly Valued at: %d (after %d zeros)", params sa_amt, saZero );
|
||||
//saZero = 0;
|
||||
if (cpuRegs.sa < 64) {
|
||||
if (sa_amt < 64) {
|
||||
/*
|
||||
cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rt_].UD[0] >> cpuRegs.sa;
|
||||
cpuRegs.GPR.r[_Rd_].UD[1] = cpuRegs.GPR.r[_Rt_].UD[1] >> cpuRegs.sa;
|
||||
cpuRegs.GPR.r[_Rd_].UD[0]|= cpuRegs.GPR.r[_Rt_].UD[1] << (64 - cpuRegs.sa);
|
||||
cpuRegs.GPR.r[_Rd_].UD[1]|= cpuRegs.GPR.r[_Rs_].UD[0] << (64 - cpuRegs.sa);
|
||||
cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rt_].UD[0] >> sa_amt;
|
||||
cpuRegs.GPR.r[_Rd_].UD[1] = cpuRegs.GPR.r[_Rt_].UD[1] >> sa_amt;
|
||||
cpuRegs.GPR.r[_Rd_].UD[0]|= cpuRegs.GPR.r[_Rt_].UD[1] << (64 - sa_amt);
|
||||
cpuRegs.GPR.r[_Rd_].UD[1]|= cpuRegs.GPR.r[_Rs_].UD[0] << (64 - sa_amt);
|
||||
*/
|
||||
Rd.UD[0] = cpuRegs.GPR.r[_Rt_].UD[0] >> cpuRegs.sa;
|
||||
Rd.UD[1] = cpuRegs.GPR.r[_Rt_].UD[1] >> cpuRegs.sa;
|
||||
Rd.UD[0]|= cpuRegs.GPR.r[_Rt_].UD[1] << (64 - cpuRegs.sa);
|
||||
Rd.UD[1]|= cpuRegs.GPR.r[_Rs_].UD[0] << (64 - cpuRegs.sa);
|
||||
Rd.UD[0] = cpuRegs.GPR.r[_Rt_].UD[0] >> sa_amt;
|
||||
Rd.UD[1] = cpuRegs.GPR.r[_Rt_].UD[1] >> sa_amt;
|
||||
Rd.UD[0]|= cpuRegs.GPR.r[_Rt_].UD[1] << (64 - sa_amt);
|
||||
Rd.UD[1]|= cpuRegs.GPR.r[_Rs_].UD[0] << (64 - sa_amt);
|
||||
cpuRegs.GPR.r[_Rd_] = Rd;
|
||||
} else {
|
||||
/*
|
||||
cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rt_].UD[1] >> (cpuRegs.sa - 64);
|
||||
cpuRegs.GPR.r[_Rd_].UD[1] = cpuRegs.GPR.r[_Rs_].UD[0] >> (cpuRegs.sa - 64);
|
||||
cpuRegs.GPR.r[_Rd_].UD[0]|= cpuRegs.GPR.r[_Rs_].UD[0] << (128 - cpuRegs.sa);
|
||||
cpuRegs.GPR.r[_Rd_].UD[1]|= cpuRegs.GPR.r[_Rs_].UD[1] << (128 - cpuRegs.sa);
|
||||
cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rt_].UD[1] >> (sa_amt - 64);
|
||||
cpuRegs.GPR.r[_Rd_].UD[1] = cpuRegs.GPR.r[_Rs_].UD[0] >> (sa_amt - 64);
|
||||
cpuRegs.GPR.r[_Rd_].UD[0]|= cpuRegs.GPR.r[_Rs_].UD[0] << (128 - sa_amt);
|
||||
cpuRegs.GPR.r[_Rd_].UD[1]|= cpuRegs.GPR.r[_Rs_].UD[1] << (128 - sa_amt);
|
||||
*/
|
||||
Rd.UD[0] = cpuRegs.GPR.r[_Rt_].UD[1] >> (cpuRegs.sa - 64);
|
||||
Rd.UD[1] = cpuRegs.GPR.r[_Rs_].UD[0] >> (cpuRegs.sa - 64);
|
||||
Rd.UD[0]|= cpuRegs.GPR.r[_Rs_].UD[0] << (128 - cpuRegs.sa);
|
||||
Rd.UD[1]|= cpuRegs.GPR.r[_Rs_].UD[1] << (128 - cpuRegs.sa);
|
||||
Rd.UD[0] = cpuRegs.GPR.r[_Rt_].UD[1] >> (sa_amt - 64);
|
||||
Rd.UD[1] = cpuRegs.GPR.r[_Rs_].UD[0] >> (sa_amt - 64);
|
||||
Rd.UD[0]|= cpuRegs.GPR.r[_Rs_].UD[0] << (128 - sa_amt);
|
||||
Rd.UD[1]|= cpuRegs.GPR.r[_Rs_].UD[1] << (128 - sa_amt);
|
||||
cpuRegs.GPR.r[_Rd_] = Rd;
|
||||
}
|
||||
}
|
||||
|
@ -1132,11 +1159,21 @@ void PMULTW() {
|
|||
|
||||
__forceinline void _PDIVW(int dd, int ss)
|
||||
{
|
||||
if (cpuRegs.GPR.r[_Rt_].UL[ss] != 0)
|
||||
if (cpuRegs.GPR.r[_Rs_].UL[ss] == 0x80000000 && cpuRegs.GPR.r[_Rt_].UL[ss] == 0xffffffff)
|
||||
{
|
||||
cpuRegs.LO.SD[dd] = (s32)0x80000000;
|
||||
cpuRegs.HI.SD[dd] = (s32)0;
|
||||
}
|
||||
else if (cpuRegs.GPR.r[_Rt_].SL[ss] != 0)
|
||||
{
|
||||
cpuRegs.LO.SD[dd] = cpuRegs.GPR.r[_Rs_].SL[ss] / cpuRegs.GPR.r[_Rt_].SL[ss];
|
||||
cpuRegs.HI.SD[dd] = cpuRegs.GPR.r[_Rs_].SL[ss] % cpuRegs.GPR.r[_Rt_].SL[ss];
|
||||
}
|
||||
else
|
||||
{
|
||||
cpuRegs.LO.SD[dd] = (cpuRegs.GPR.r[_Rs_].SL[ss] < 0) ? 1 : -1;
|
||||
cpuRegs.HI.SD[dd] = cpuRegs.GPR.r[_Rs_].SL[ss];
|
||||
}
|
||||
}
|
||||
|
||||
void PDIVW() {
|
||||
|
@ -1196,18 +1233,20 @@ void PMADDH() { // JayteeMaster: changed a bit to avoid screw up
|
|||
// JayteeMaster: changed a bit to avoid screw up
|
||||
__forceinline void _PHMADH_LO(int dd, int n)
|
||||
{
|
||||
s32 temp = (s32)cpuRegs.GPR.r[_Rs_].SS[n+1] * (s32)cpuRegs.GPR.r[_Rt_].SS[n+1] + \
|
||||
(s32)cpuRegs.GPR.r[_Rs_].SS[n] * (s32)cpuRegs.GPR.r[_Rt_].SS[n];
|
||||
s32 firsttemp = (s32)cpuRegs.GPR.r[_Rs_].SS[n+1] * (s32)cpuRegs.GPR.r[_Rt_].SS[n+1];
|
||||
s32 temp = firsttemp + (s32)cpuRegs.GPR.r[_Rs_].SS[n] * (s32)cpuRegs.GPR.r[_Rt_].SS[n];
|
||||
|
||||
cpuRegs.LO.UL[dd] = temp;
|
||||
cpuRegs.LO.UL[dd+1] = firsttemp;
|
||||
}
|
||||
|
||||
__forceinline void _PHMADH_HI(int dd, int n)
|
||||
{
|
||||
s32 temp = (s32)cpuRegs.GPR.r[_Rs_].SS[n+1] * (s32)cpuRegs.GPR.r[_Rt_].SS[n+1] + \
|
||||
(s32)cpuRegs.GPR.r[_Rs_].SS[n] * (s32)cpuRegs.GPR.r[_Rt_].SS[n];
|
||||
s32 firsttemp = (s32)cpuRegs.GPR.r[_Rs_].SS[n+1] * (s32)cpuRegs.GPR.r[_Rt_].SS[n+1];
|
||||
s32 temp = firsttemp + (s32)cpuRegs.GPR.r[_Rs_].SS[n] * (s32)cpuRegs.GPR.r[_Rt_].SS[n];
|
||||
|
||||
cpuRegs.HI.UL[dd] = temp;
|
||||
cpuRegs.HI.UL[dd+1] = firsttemp;
|
||||
}
|
||||
|
||||
void PHMADH() { // JayteeMaster: changed a bit to avoid screw up. Also used 0,2,4,6 instead of 0,1,2,3
|
||||
|
@ -1279,17 +1318,19 @@ void PMSUBH() { // JayteeMaster: changed a bit to avoid screw up
|
|||
// JayteeMaster: changed a bit to avoid screw up
|
||||
__forceinline void _PHMSBH_LO(int dd, int n, int rdd)
|
||||
{
|
||||
s32 temp = (s32)cpuRegs.GPR.r[_Rs_].SS[n+1] * (s32)cpuRegs.GPR.r[_Rt_].SS[n+1] - \
|
||||
(s32)cpuRegs.GPR.r[_Rs_].SS[n] * (s32)cpuRegs.GPR.r[_Rt_].SS[n];
|
||||
s32 firsttemp = (s32)cpuRegs.GPR.r[_Rs_].SS[n+1] * (s32)cpuRegs.GPR.r[_Rt_].SS[n+1];
|
||||
s32 temp = firsttemp - (s32)cpuRegs.GPR.r[_Rs_].SS[n] * (s32)cpuRegs.GPR.r[_Rt_].SS[n];
|
||||
|
||||
cpuRegs.LO.UL[dd] = temp;
|
||||
cpuRegs.LO.UL[dd+1] = ~firsttemp;
|
||||
}
|
||||
__forceinline void _PHMSBH_HI(int dd, int n, int rdd)
|
||||
{
|
||||
s32 temp = (s32)cpuRegs.GPR.r[_Rs_].SS[n+1] * (s32)cpuRegs.GPR.r[_Rt_].SS[n+1] - \
|
||||
(s32)cpuRegs.GPR.r[_Rs_].SS[n] * (s32)cpuRegs.GPR.r[_Rt_].SS[n];
|
||||
s32 firsttemp = (s32)cpuRegs.GPR.r[_Rs_].SS[n+1] * (s32)cpuRegs.GPR.r[_Rt_].SS[n+1];
|
||||
s32 temp = firsttemp - (s32)cpuRegs.GPR.r[_Rs_].SS[n] * (s32)cpuRegs.GPR.r[_Rt_].SS[n];
|
||||
|
||||
cpuRegs.HI.UL[dd] = temp;
|
||||
cpuRegs.HI.UL[dd+1] = ~firsttemp;
|
||||
}
|
||||
|
||||
void PHMSBH() { // JayteeMaster: changed a bit to avoid screw up
|
||||
|
@ -1378,13 +1419,24 @@ void PMULTH() { // JayteeMaster: changed a bit to avoid screw up
|
|||
|
||||
__forceinline void _PDIVBW(int n)
|
||||
{
|
||||
cpuRegs.LO.UL[n] = (s32)(cpuRegs.GPR.r[_Rs_].SL[n] / cpuRegs.GPR.r[_Rt_].SS[0]);
|
||||
cpuRegs.HI.UL[n] = (s16)(cpuRegs.GPR.r[_Rs_].SL[n] % cpuRegs.GPR.r[_Rt_].SS[0]);
|
||||
if (cpuRegs.GPR.r[_Rs_].UL[n] == 0x80000000 && cpuRegs.GPR.r[_Rt_].US[0] == 0xffff)
|
||||
{
|
||||
cpuRegs.LO.SL[n] = (s32)0x80000000;
|
||||
cpuRegs.HI.SL[n] = (s32)0x0;
|
||||
}
|
||||
else if (cpuRegs.GPR.r[_Rt_].US[0] != 0)
|
||||
{
|
||||
cpuRegs.LO.SL[n] = cpuRegs.GPR.r[_Rs_].SL[n] / cpuRegs.GPR.r[_Rt_].SS[0];
|
||||
cpuRegs.HI.SL[n] = cpuRegs.GPR.r[_Rs_].SL[n] % cpuRegs.GPR.r[_Rt_].SS[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
cpuRegs.LO.SL[n] = (cpuRegs.GPR.r[_Rs_].SL[n] < 0) ? 1 : -1;
|
||||
cpuRegs.HI.SL[n] = cpuRegs.GPR.r[_Rs_].SL[n];
|
||||
}
|
||||
}
|
||||
|
||||
void PDIVBW() {
|
||||
if (cpuRegs.GPR.r[_Rt_].US[0] == 0) return;
|
||||
|
||||
_PDIVBW(0); _PDIVBW(1); _PDIVBW(2); _PDIVBW(3);
|
||||
}
|
||||
|
||||
|
@ -1489,6 +1541,11 @@ __forceinline void _PDIVUW(int dd, int ss)
|
|||
cpuRegs.LO.SD[dd] = (s32)(cpuRegs.GPR.r[_Rs_].UL[ss] / cpuRegs.GPR.r[_Rt_].UL[ss]);
|
||||
cpuRegs.HI.SD[dd] = (s32)(cpuRegs.GPR.r[_Rs_].UL[ss] % cpuRegs.GPR.r[_Rt_].UL[ss]);
|
||||
}
|
||||
else
|
||||
{
|
||||
cpuRegs.LO.SD[dd] = -1;
|
||||
cpuRegs.HI.SD[dd] = cpuRegs.GPR.r[_Rs_].SL[ss];
|
||||
}
|
||||
}
|
||||
|
||||
void PDIVUW() {
|
||||
|
|
|
@ -247,14 +247,29 @@ void SLTU() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = (cpuRegs.GPR.r[_Rs
|
|||
* Format: OP rs, rt *
|
||||
*********************************************************/
|
||||
|
||||
// Signed division "overflows" on (0x80000000 / -1), here (LO = 0x80000000, HI = 0) is returned by MIPS
|
||||
// in division by zero on MIPS, it appears that:
|
||||
// LO gets 1 if rs is negative (and the division is signed) and -1 otherwise.
|
||||
// HI gets the value of rs.
|
||||
|
||||
// Result is stored in HI/LO [no arithmetic exceptions]
|
||||
void DIV()
|
||||
{
|
||||
if (cpuRegs.GPR.r[_Rt_].SL[0] != 0)
|
||||
if (cpuRegs.GPR.r[_Rs_].UL[0] == 0x80000000 && cpuRegs.GPR.r[_Rt_].UL[0] == 0xffffffff)
|
||||
{
|
||||
cpuRegs.LO.SD[0] = (s32)0x80000000;
|
||||
cpuRegs.HI.SD[0] = (s32)0x0;
|
||||
}
|
||||
else if (cpuRegs.GPR.r[_Rt_].SL[0] != 0)
|
||||
{
|
||||
cpuRegs.LO.SD[0] = cpuRegs.GPR.r[_Rs_].SL[0] / cpuRegs.GPR.r[_Rt_].SL[0];
|
||||
cpuRegs.HI.SD[0] = cpuRegs.GPR.r[_Rs_].SL[0] % cpuRegs.GPR.r[_Rt_].SL[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
cpuRegs.LO.SD[0] = (cpuRegs.GPR.r[_Rs_].SL[0] < 0) ? 1 : -1;
|
||||
cpuRegs.HI.SD[0] = cpuRegs.GPR.r[_Rs_].SL[0];
|
||||
}
|
||||
}
|
||||
|
||||
// Result is stored in HI/LO [no arithmetic exceptions]
|
||||
|
@ -267,6 +282,11 @@ void DIVU()
|
|||
cpuRegs.LO.SD[0] = (s32)(cpuRegs.GPR.r[_Rs_].UL[0] / cpuRegs.GPR.r[_Rt_].UL[0]);
|
||||
cpuRegs.HI.SD[0] = (s32)(cpuRegs.GPR.r[_Rs_].UL[0] % cpuRegs.GPR.r[_Rt_].UL[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
cpuRegs.LO.SD[0] = -1;
|
||||
cpuRegs.HI.SD[0] = cpuRegs.GPR.r[_Rs_].SL[0];
|
||||
}
|
||||
}
|
||||
|
||||
// Result is written to both HI/LO and to the _Rd_ (Lo only)
|
||||
|
@ -858,7 +878,7 @@ void MFSA( void ) {
|
|||
}
|
||||
|
||||
void MTSA( void ) {
|
||||
cpuRegs.sa = (s32)cpuRegs.GPR.r[_Rs_].SD[0];
|
||||
cpuRegs.sa = (s32)cpuRegs.GPR.r[_Rs_].SD[0] & 0xf;
|
||||
}
|
||||
|
||||
// SNY supports three basic modes, two which synchronize memory accesses (related
|
||||
|
@ -907,11 +927,11 @@ void TLTIU() { if (cpuRegs.GPR.r[_Rs_].UD[0] < (u64)_Imm_) throw R5900Exception
|
|||
*********************************************************/
|
||||
|
||||
void MTSAB() {
|
||||
cpuRegs.sa = ((cpuRegs.GPR.r[_Rs_].UL[0] & 0xF) ^ (_Imm_ & 0xF)) << 3;
|
||||
cpuRegs.sa = ((cpuRegs.GPR.r[_Rs_].UL[0] & 0xF) ^ (_Imm_ & 0xF));
|
||||
}
|
||||
|
||||
void MTSAH() {
|
||||
cpuRegs.sa = ((cpuRegs.GPR.r[_Rs_].UL[0] & 0x7) ^ (_Imm_ & 0x7)) << 4;
|
||||
cpuRegs.sa = ((cpuRegs.GPR.r[_Rs_].UL[0] & 0x7) ^ (_Imm_ & 0x7)) << 1;
|
||||
}
|
||||
|
||||
} } } // end namespace R5900::Interpreter::OpcodeImpl
|
||||
|
|
|
@ -525,6 +525,7 @@ BOOL APIENTRY GameFixes(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
|||
case WM_INITDIALOG:
|
||||
if(Config.GameFixes & 0x1) CheckDlgButton(hDlg, IDC_GAMEFIX2, TRUE);//Tri-Ace fix
|
||||
if(Config.GameFixes & 0x4) CheckDlgButton(hDlg, IDC_GAMEFIX3, TRUE);//Digimon FPU compare fix
|
||||
if(Config.GameFixes & 0x2) CheckDlgButton(hDlg, IDC_GAMEFIX4, TRUE);//Persona3/4 fix
|
||||
if(Config.GameFixes & 0x8) CheckDlgButton(hDlg, IDC_GAMEFIX5, TRUE);//Tales of Destiny fix
|
||||
return TRUE;
|
||||
|
||||
|
@ -534,6 +535,7 @@ BOOL APIENTRY GameFixes(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
|||
uint newfixes = 0;
|
||||
newfixes |= IsDlgButtonChecked(hDlg, IDC_GAMEFIX2) ? 0x1 : 0;
|
||||
newfixes |= IsDlgButtonChecked(hDlg, IDC_GAMEFIX3) ? 0x4 : 0;
|
||||
newfixes |= IsDlgButtonChecked(hDlg, IDC_GAMEFIX4) ? 0x2 : 0;
|
||||
newfixes |= IsDlgButtonChecked(hDlg, IDC_GAMEFIX5) ? 0x8 : 0;
|
||||
|
||||
EndDialog(hDlg, TRUE);
|
||||
|
|
|
@ -74,21 +74,23 @@ LANGUAGE LANG_GERMAN, SUBLANG_GERMAN
|
|||
// Dialog
|
||||
//
|
||||
|
||||
IDD_GAMEFIXES DIALOGEX 0, 0, 279, 118
|
||||
IDD_GAMEFIXES DIALOGEX 0, 0, 279, 123
|
||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Game Special Fixes"
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
DEFPUSHBUTTON "OK",IDOK,87,89,50,14
|
||||
PUSHBUTTON "Cancel",IDCANCEL,142,89,50,14
|
||||
DEFPUSHBUTTON "OK",IDOK,87,96,50,14
|
||||
PUSHBUTTON "Cancel",IDCANCEL,142,96,50,14
|
||||
CTEXT "Some games need special settings.\nConfigure them here.",IDC_STATIC,7,7,265,17
|
||||
GROUPBOX "PCSX2 Gamefixes",IDC_STATIC,7,28,265,83
|
||||
GROUPBOX "PCSX2 Gamefixes",IDC_STATIC,7,22,265,94
|
||||
CONTROL "FPU Compare Hack - Special fix for Digimon Rumble Arena 2.",IDC_GAMEFIX3,
|
||||
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,43,249,10
|
||||
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,36,249,10
|
||||
CONTROL "VU Add Hack - Special fix for Tri-Ace games!",IDC_GAMEFIX2,
|
||||
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,72,252,10
|
||||
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,65,252,10
|
||||
CONTROL "VU Clip Hack - Fixes missing ground geometry in Persona.",IDC_GAMEFIX4,
|
||||
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,79,238,10
|
||||
CONTROL "FPU Mul Hack - Special fix for Tales of Destiny (possibly other games).",IDC_GAMEFIX5,
|
||||
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,57,249,10
|
||||
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,50,249,10
|
||||
END
|
||||
|
||||
|
||||
|
@ -106,7 +108,7 @@ BEGIN
|
|||
RIGHTMARGIN, 272
|
||||
VERTGUIDE, 14
|
||||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 111
|
||||
BOTTOMMARGIN, 116
|
||||
HORZGUIDE, 103
|
||||
END
|
||||
END
|
||||
|
|
|
@ -1617,23 +1617,29 @@ REC_FUNC_DEL( QFSRV, _Rd_);
|
|||
PCSX2_ALIGNED16(int s_MaskHighBitD[4]) = { 0x80000000, 0x80000000, 0x80000000, 0x80000000 };
|
||||
PCSX2_ALIGNED16(int s_MaskHighBitW[4]) = { 0x80008000, 0x80008000, 0x80008000, 0x80008000 };
|
||||
|
||||
void recPABSW()
|
||||
void recPABSW() //needs clamping
|
||||
{
|
||||
if( !_Rd_ ) return;
|
||||
|
||||
CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED)
|
||||
int t0reg = _allocTempXMMreg(XMMT_INT, -1);
|
||||
SSE2_PCMPEQD_XMM_to_XMM(t0reg, t0reg);
|
||||
SSE2_PSLLD_I8_to_XMM(t0reg, 31);
|
||||
SSE2_PCMPEQD_XMM_to_XMM(t0reg, EEREC_T); //0xffffffff if equal to 0x80000000
|
||||
if( cpucaps.hasSupplementalStreamingSIMD3Extensions ) {
|
||||
SSSE3_PABSD_XMM_to_XMM(EEREC_D, EEREC_T);
|
||||
SSSE3_PABSD_XMM_to_XMM(EEREC_D, EEREC_T); //0x80000000 -> 0x80000000
|
||||
}
|
||||
else {
|
||||
int t0reg = _allocTempXMMreg(XMMT_INT, -1);
|
||||
SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_T);
|
||||
int t1reg = _allocTempXMMreg(XMMT_INT, -1);
|
||||
SSEX_MOVDQA_XMM_to_XMM(t1reg, EEREC_T);
|
||||
SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T);
|
||||
SSE2_PSRAD_I8_to_XMM(t0reg, 31);
|
||||
SSEX_PXOR_XMM_to_XMM(EEREC_D, t0reg);
|
||||
SSE2_PSUBD_XMM_to_XMM(EEREC_D, t0reg);
|
||||
_freeXMMreg(t0reg);
|
||||
SSE2_PSRAD_I8_to_XMM(t1reg, 31);
|
||||
SSEX_PXOR_XMM_to_XMM(EEREC_D, t1reg);
|
||||
SSE2_PSUBD_XMM_to_XMM(EEREC_D, t1reg); //0x80000000 -> 0x80000000
|
||||
_freeXMMreg(t1reg);
|
||||
}
|
||||
SSE2_PXOR_XMM_to_XMM(EEREC_D, t0reg); //0x80000000 -> 0x7fffffff
|
||||
_freeXMMreg(t0reg);
|
||||
CPU_SSE_XMMCACHE_END
|
||||
|
||||
_deleteEEreg(_Rt_, 1);
|
||||
|
@ -1645,24 +1651,31 @@ CPU_SSE_XMMCACHE_END
|
|||
CALLFunc( (uptr)R5900::Interpreter::OpcodeImpl::MMI::PABSW );
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
void recPABSH()
|
||||
void recPABSH()
|
||||
{
|
||||
if( !_Rd_ ) return;
|
||||
|
||||
CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED)
|
||||
int t0reg = _allocTempXMMreg(XMMT_INT, -1);
|
||||
SSE2_PCMPEQW_XMM_to_XMM(t0reg, t0reg);
|
||||
SSE2_PSLLW_I8_to_XMM(t0reg, 15);
|
||||
SSE2_PCMPEQW_XMM_to_XMM(t0reg, EEREC_T); //0xffff if equal to 0x8000
|
||||
if( cpucaps.hasSupplementalStreamingSIMD3Extensions ) {
|
||||
SSSE3_PABSW_XMM_to_XMM(EEREC_D, EEREC_T);
|
||||
SSSE3_PABSW_XMM_to_XMM(EEREC_D, EEREC_T); //0x8000 -> 0x8000
|
||||
}
|
||||
else {
|
||||
int t0reg = _allocTempXMMreg(XMMT_INT, -1);
|
||||
SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_T);
|
||||
int t1reg = _allocTempXMMreg(XMMT_INT, -1);
|
||||
SSEX_MOVDQA_XMM_to_XMM(t1reg, EEREC_T);
|
||||
SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T);
|
||||
SSE2_PSRAW_I8_to_XMM(t0reg, 15);
|
||||
SSEX_PXOR_XMM_to_XMM(EEREC_D, t0reg);
|
||||
SSE2_PSUBW_XMM_to_XMM(EEREC_D, t0reg);
|
||||
_freeXMMreg(t0reg);
|
||||
SSE2_PSRAW_I8_to_XMM(t1reg, 15);
|
||||
SSEX_PXOR_XMM_to_XMM(EEREC_D, t1reg);
|
||||
SSE2_PSUBW_XMM_to_XMM(EEREC_D, t1reg); //0x8000 -> 0x8000
|
||||
_freeXMMreg(t1reg);
|
||||
}
|
||||
SSE2_PXOR_XMM_to_XMM(EEREC_D, t0reg); //0x8000 -> 0x7fff
|
||||
_freeXMMreg(t0reg);
|
||||
CPU_SSE_XMMCACHE_END
|
||||
|
||||
_deleteEEreg(_Rt_, 1);
|
||||
|
@ -1968,7 +1981,7 @@ void recQFSRV()
|
|||
SSE2_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T);
|
||||
|
||||
MOV32MtoR(EAX, (uptr)&cpuRegs.sa);
|
||||
SHL32ItoR(EAX, 1); // Multiply SA bytes by 16 bytes (the amount of bytes in QFSRVhelper() macros)
|
||||
SHL32ItoR(EAX, 4); // Multiply SA bytes by 16 bytes (the amount of bytes in QFSRVhelper() macros)
|
||||
AND32I8toR(EAX, 0xf0); // This can possibly be removed but keeping it incase theres garbage in SA (cottonvibes)
|
||||
ADD32ItoEAX((uptr)x86Ptr[0] + 7); // ADD32 = 5 bytes, JMPR = 2 bytes
|
||||
JMPR(EAX); // Jumps to a QFSRVhelper() case below (a total of 16 different cases)
|
||||
|
@ -2402,8 +2415,8 @@ CPU_SSE2_XMMCACHE_START((_Rs_?XMMINFO_READS:0)|(_Rt_?XMMINFO_READT:0)|XMMINFO_WR
|
|||
|
||||
// shamt is 5-bit
|
||||
SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_S);
|
||||
SSE2_PSLLQ_I8_to_XMM(t0reg, 27);
|
||||
SSE2_PSRLQ_I8_to_XMM(t0reg, 27);
|
||||
SSE2_PSLLQ_I8_to_XMM(t0reg, 27+32);
|
||||
SSE2_PSRLQ_I8_to_XMM(t0reg, 27+32);
|
||||
|
||||
// EEREC_D[0] <- Rt[0], t1reg[0] <- Rt[2]
|
||||
SSE_MOVHLPS_XMM_to_XMM(t1reg, EEREC_T);
|
||||
|
@ -2470,8 +2483,8 @@ CPU_SSE2_XMMCACHE_START((_Rs_?XMMINFO_READS:0)|(_Rt_?XMMINFO_READT:0)|XMMINFO_WR
|
|||
|
||||
// shamt is 5-bit
|
||||
SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_S);
|
||||
SSE2_PSLLQ_I8_to_XMM(t0reg, 27);
|
||||
SSE2_PSRLQ_I8_to_XMM(t0reg, 27);
|
||||
SSE2_PSLLQ_I8_to_XMM(t0reg, 27+32);
|
||||
SSE2_PSRLQ_I8_to_XMM(t0reg, 27+32);
|
||||
|
||||
// EEREC_D[0] <- Rt[0], t1reg[0] <- Rt[2]
|
||||
SSE_MOVHLPS_XMM_to_XMM(t1reg, EEREC_T);
|
||||
|
@ -2619,9 +2632,18 @@ void recPDIVBW()
|
|||
////////////////////////////////////////////////////
|
||||
PCSX2_ALIGNED16(int s_mask1[4]) = {~0, 0, ~0, 0};
|
||||
|
||||
//upper word of each doubleword in LO and HI is undocumented/undefined
|
||||
//contains the upper multiplication result (before the addition with the lower multiplication result)
|
||||
void recPHMADH()
|
||||
{
|
||||
CPU_SSE2_XMMCACHE_START((_Rd_?XMMINFO_WRITED:0)|XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITELO|XMMINFO_WRITEHI)
|
||||
int t0reg = _allocTempXMMreg(XMMT_INT, -1);
|
||||
|
||||
SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_S);
|
||||
SSE2_PSRLD_I8_to_XMM(t0reg, 16);
|
||||
SSE2_PSLLD_I8_to_XMM(t0reg, 16);
|
||||
SSE2_PMADDWD_XMM_to_XMM(t0reg, EEREC_T);
|
||||
|
||||
if( _Rd_ ) {
|
||||
if( EEREC_D == EEREC_S ) {
|
||||
SSE2_PMADDWD_XMM_to_XMM(EEREC_D, EEREC_T);
|
||||
|
@ -2641,14 +2663,22 @@ CPU_SSE2_XMMCACHE_START((_Rd_?XMMINFO_WRITED:0)|XMMINFO_READS|XMMINFO_READT|XMMI
|
|||
}
|
||||
|
||||
SSEX_MOVDQA_XMM_to_XMM(EEREC_HI, EEREC_LO);
|
||||
SSE2_PSRLQ_I8_to_XMM(EEREC_HI, 32);
|
||||
|
||||
SSE_SHUFPS_XMM_to_XMM(EEREC_LO, t0reg, 0x88);
|
||||
SSE_SHUFPS_XMM_to_XMM(EEREC_LO, EEREC_LO, 0xd8);
|
||||
|
||||
SSE_SHUFPS_XMM_to_XMM(EEREC_HI, t0reg, 0xdd);
|
||||
SSE_SHUFPS_XMM_to_XMM(EEREC_HI, EEREC_HI, 0xd8);
|
||||
|
||||
_freeXMMreg(t0reg);
|
||||
CPU_SSE_XMMCACHE_END
|
||||
|
||||
recCall( Interp::PHMADH, _Rd_ );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//upper word of each doubleword in LO and HI is undocumented/undefined
|
||||
//contains the NOT of the upper multiplication result (before the substraction of the lower multiplication result)
|
||||
void recPMSUBH()
|
||||
{
|
||||
CPU_SSE2_XMMCACHE_START((_Rd_?XMMINFO_WRITED:0)|XMMINFO_READS|XMMINFO_READT|XMMINFO_READLO|XMMINFO_READHI|XMMINFO_WRITELO|XMMINFO_WRITEHI)
|
||||
|
@ -2710,22 +2740,41 @@ CPU_SSE_XMMCACHE_END
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
|
||||
// rs = ... a1 a0
|
||||
// rt = ... b1 b0
|
||||
// rd = ... a1*b1 - a0*b0
|
||||
// hi = ...
|
||||
// lo = ... (undefined by doc)NOT(a1*b1), a1*b1 - a0*b0
|
||||
void recPHMSBH()
|
||||
{
|
||||
CPU_SSE2_XMMCACHE_START((_Rd_?XMMINFO_WRITED:0)|XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITELO|XMMINFO_WRITEHI)
|
||||
int t0reg = _allocTempXMMreg(XMMT_INT, -1);
|
||||
|
||||
SSE2_PCMPEQD_XMM_to_XMM(EEREC_LO, EEREC_LO);
|
||||
SSE2_PSRLD_XMM_to_XMM(EEREC_LO, 16);
|
||||
SSE2_PSRLD_I8_to_XMM(EEREC_LO, 16);
|
||||
SSEX_MOVDQA_XMM_to_XMM(EEREC_HI, EEREC_S);
|
||||
SSE2_PAND_XMM_to_XMM(EEREC_HI, EEREC_LO);
|
||||
SSE2_PMADDWD_XMM_to_XMM(EEREC_HI, EEREC_T);
|
||||
SSE2_PSLLD_XMM_to_XMM(EEREC_LO, 16);
|
||||
SSE2_PSLLD_I8_to_XMM(EEREC_LO, 16);
|
||||
SSE2_PAND_XMM_to_XMM(EEREC_LO, EEREC_S);
|
||||
SSE2_PMADDWD_XMM_to_XMM(EEREC_LO, EEREC_T);
|
||||
SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_LO);
|
||||
SSE2_PSUBD_XMM_to_XMM(EEREC_LO, EEREC_HI);
|
||||
if( _Rd_ ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_LO);
|
||||
|
||||
SSE2_PCMPEQD_XMM_to_XMM(EEREC_HI, EEREC_HI);
|
||||
SSE2_PXOR_XMM_to_XMM(t0reg, EEREC_HI);
|
||||
|
||||
SSEX_MOVDQA_XMM_to_XMM(EEREC_HI, EEREC_LO);
|
||||
SSE2_PSRLQ_I8_to_XMM(EEREC_HI, 32);
|
||||
|
||||
SSE_SHUFPS_XMM_to_XMM(EEREC_LO, t0reg, 0x88);
|
||||
SSE_SHUFPS_XMM_to_XMM(EEREC_LO, EEREC_LO, 0xd8);
|
||||
|
||||
SSE_SHUFPS_XMM_to_XMM(EEREC_HI, t0reg, 0xdd);
|
||||
SSE_SHUFPS_XMM_to_XMM(EEREC_HI, EEREC_HI, 0xd8);
|
||||
|
||||
_freeXMMreg(t0reg);
|
||||
CPU_SSE_XMMCACHE_END
|
||||
|
||||
recCall( Interp::PHMSBH, _Rd_ );
|
||||
|
@ -3278,8 +3327,8 @@ CPU_SSE2_XMMCACHE_START((_Rs_?XMMINFO_READS:0)|(_Rt_?XMMINFO_READT:0)|XMMINFO_WR
|
|||
|
||||
// shamt is 5-bit
|
||||
SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_S);
|
||||
SSE2_PSLLQ_I8_to_XMM(t0reg, 27);
|
||||
SSE2_PSRLQ_I8_to_XMM(t0reg, 27);
|
||||
SSE2_PSLLQ_I8_to_XMM(t0reg, 27+32);
|
||||
SSE2_PSRLQ_I8_to_XMM(t0reg, 27+32);
|
||||
|
||||
// EEREC_D[0] <- Rt[0], t1reg[0] <- Rt[2]
|
||||
SSE_MOVHLPS_XMM_to_XMM(t1reg, EEREC_T);
|
||||
|
|
|
@ -94,10 +94,11 @@ void recMFSA( void )
|
|||
}
|
||||
}
|
||||
|
||||
// SA is 4-bit and contains the amount of bytes to shift
|
||||
void recMTSA( void )
|
||||
{
|
||||
if( GPR_IS_CONST1(_Rs_) ) {
|
||||
MOV32ItoM((uptr)&cpuRegs.sa, g_cpuConstRegs[_Rs_].UL[0] );
|
||||
MOV32ItoM((uptr)&cpuRegs.sa, g_cpuConstRegs[_Rs_].UL[0] & 0xf );
|
||||
}
|
||||
else {
|
||||
int mmreg;
|
||||
|
@ -113,19 +114,19 @@ void recMTSA( void )
|
|||
MOV32MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rs_].UL[0]);
|
||||
MOV32RtoM((uptr)&cpuRegs.sa, EAX);
|
||||
}
|
||||
AND32ItoM((uptr)&cpuRegs.sa, 0xf);
|
||||
}
|
||||
}
|
||||
|
||||
void recMTSAB( void )
|
||||
{
|
||||
if( GPR_IS_CONST1(_Rs_) ) {
|
||||
MOV32ItoM((uptr)&cpuRegs.sa, ((g_cpuConstRegs[_Rs_].UL[0] & 0xF) ^ (_Imm_ & 0xF)) << 3);
|
||||
MOV32ItoM((uptr)&cpuRegs.sa, ((g_cpuConstRegs[_Rs_].UL[0] & 0xF) ^ (_Imm_ & 0xF)) );
|
||||
}
|
||||
else {
|
||||
_eeMoveGPRtoR(EAX, _Rs_);
|
||||
AND32ItoR(EAX, 0xF);
|
||||
XOR32ItoR(EAX, _Imm_&0xf);
|
||||
SHL32ItoR(EAX, 3);
|
||||
MOV32RtoM((uptr)&cpuRegs.sa, EAX);
|
||||
}
|
||||
}
|
||||
|
@ -133,13 +134,13 @@ void recMTSAB( void )
|
|||
void recMTSAH( void )
|
||||
{
|
||||
if( GPR_IS_CONST1(_Rs_) ) {
|
||||
MOV32ItoM((uptr)&cpuRegs.sa, ((g_cpuConstRegs[_Rs_].UL[0] & 0x7) ^ (_Imm_ & 0x7)) << 4);
|
||||
MOV32ItoM((uptr)&cpuRegs.sa, ((g_cpuConstRegs[_Rs_].UL[0] & 0x7) ^ (_Imm_ & 0x7)) << 1);
|
||||
}
|
||||
else {
|
||||
_eeMoveGPRtoR(EAX, _Rs_);
|
||||
AND32ItoR(EAX, 0x7);
|
||||
XOR32ItoR(EAX, _Imm_&0x7);
|
||||
SHL32ItoR(EAX, 4);
|
||||
SHL32ItoR(EAX, 1);
|
||||
MOV32RtoM((uptr)&cpuRegs.sa, EAX);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3000,7 +3000,7 @@ void VuInstruction::Recompile(list<VuInstruction>::iterator& itinst, u32 vuxyz)
|
|||
if( type & INST_CLIP_WRITE ) {
|
||||
if( nParentPc < s_pCurBlock->startpc || nParentPc >= (int)pc ) {
|
||||
|
||||
if( pparentinst != NULL ) {
|
||||
if( !CHECK_VUCLIPFLAGHACK && pparentinst != NULL ) {
|
||||
|
||||
if( nParentCheckForExecution >= 0 ) {
|
||||
if( pparentinst->pClipWrite == 0 )
|
||||
|
|
|
@ -595,14 +595,31 @@ void recMULTU1_constt(int info)
|
|||
EERECOMPILE_CODE0(MULTU1, XMMINFO_READS|XMMINFO_READT|(_Rd_?XMMINFO_WRITED:0));
|
||||
|
||||
//// DIV
|
||||
|
||||
void recDIVconst(int upper)
|
||||
{
|
||||
s32 quot, rem;
|
||||
if (g_cpuConstRegs[_Rs_].UL[0] == 0x80000000 && g_cpuConstRegs[_Rt_].SL[0] == -1)
|
||||
{
|
||||
quot = (s32)0x80000000;
|
||||
rem = 0;
|
||||
}
|
||||
else if (g_cpuConstRegs[_Rt_].SL[0] != 0)
|
||||
{
|
||||
quot = g_cpuConstRegs[_Rs_].SL[0] / g_cpuConstRegs[_Rt_].SL[0];
|
||||
rem = g_cpuConstRegs[_Rs_].SL[0] % g_cpuConstRegs[_Rt_].SL[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
quot = (g_cpuConstRegs[_Rs_].SL[0] < 0) ? 1 : -1;
|
||||
rem = g_cpuConstRegs[_Rs_].SL[0];
|
||||
}
|
||||
recWritebackConstHILO((u64)quot|((u64)rem<<32), 0, upper);
|
||||
}
|
||||
|
||||
void recDIV_const()
|
||||
{
|
||||
if (g_cpuConstRegs[_Rt_].SL[0] != 0) {
|
||||
s32 quot = g_cpuConstRegs[_Rs_].SL[0] / g_cpuConstRegs[_Rt_].SL[0];
|
||||
s32 rem = g_cpuConstRegs[_Rs_].SL[0] % g_cpuConstRegs[_Rt_].SL[0];
|
||||
|
||||
recWritebackConstHILO((u64)quot|((u64)rem<<32), 0, 0);
|
||||
}
|
||||
recDIVconst(0);
|
||||
}
|
||||
|
||||
void recDIVsuper(int info, int sign, int upper, int process)
|
||||
|
@ -610,24 +627,46 @@ void recDIVsuper(int info, int sign, int upper, int process)
|
|||
EEINST_SETSIGNEXT(_Rs_);
|
||||
EEINST_SETSIGNEXT(_Rt_);
|
||||
|
||||
if( process & PROCESS_CONSTT ) {
|
||||
if( !g_cpuConstRegs[_Rt_].UL[0] )
|
||||
return;
|
||||
if( process & PROCESS_CONSTT )
|
||||
MOV32ItoR( ECX, g_cpuConstRegs[_Rt_].UL[0] );
|
||||
}
|
||||
else {
|
||||
else
|
||||
MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] );
|
||||
|
||||
OR32RtoR( ECX, ECX );
|
||||
j8Ptr[ 0 ] = JE8( 0 );
|
||||
}
|
||||
|
||||
if( process & PROCESS_CONSTS )
|
||||
MOV32ItoR( EAX, g_cpuConstRegs[_Rs_].UL[0] );
|
||||
else {
|
||||
else
|
||||
MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] );
|
||||
|
||||
u8 *end1;
|
||||
if (sign) //test for overflow (x86 will just throw an exception)
|
||||
{
|
||||
CMP32ItoR( EAX, 0x80000000 );
|
||||
u8 *cont1 = JNE8(0);
|
||||
CMP32ItoR( ECX, 0xffffffff );
|
||||
u8 *cont2 = JNE8(0);
|
||||
//overflow case:
|
||||
XOR32RtoR( EDX, EDX ); //EAX remains 0x80000000
|
||||
end1 = JMP8(0);
|
||||
|
||||
x86SetJ8(cont1);
|
||||
x86SetJ8(cont2);
|
||||
}
|
||||
|
||||
CMP32ItoR( ECX, 0 );
|
||||
u8 *cont3 = JNE8(0);
|
||||
//divide by zero
|
||||
MOV32RtoR( EDX, EAX );
|
||||
if (sign) //set EAX to (EAX < 0)?1:-1
|
||||
{
|
||||
SAR32ItoR( EAX, 31 ); //(EAX < 0)?-1:0
|
||||
SHL32ItoR( EAX, 1 ); //(EAX < 0)?-2:0
|
||||
NOT32R( EAX ); //(EAX < 0)?1:-1
|
||||
}
|
||||
else
|
||||
MOV32ItoR( EAX, 0xffffffff );
|
||||
u8 *end2 = JMP8(0);
|
||||
|
||||
x86SetJ8(cont3);
|
||||
if( sign ) {
|
||||
CDQ();
|
||||
IDIV32R( ECX );
|
||||
|
@ -636,7 +675,9 @@ void recDIVsuper(int info, int sign, int upper, int process)
|
|||
XOR32RtoR( EDX, EDX );
|
||||
DIV32R( ECX );
|
||||
}
|
||||
if( !(process & PROCESS_CONSTT) ) x86SetJ8( j8Ptr[ 0 ] );
|
||||
|
||||
if (sign) x86SetJ8( end1 );
|
||||
x86SetJ8( end2 );
|
||||
|
||||
// need to execute regardless of bad divide
|
||||
recWritebackHILO(info, 0, upper);
|
||||
|
@ -660,14 +701,25 @@ void recDIV_constt(int info)
|
|||
EERECOMPILE_CODE0(DIV, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITELO|XMMINFO_WRITEHI);
|
||||
|
||||
//// DIVU
|
||||
void recDIVUconst(int upper)
|
||||
{
|
||||
u32 quot, rem;
|
||||
if (g_cpuConstRegs[_Rt_].UL[0] != 0) {
|
||||
quot = g_cpuConstRegs[_Rs_].UL[0] / g_cpuConstRegs[_Rt_].UL[0];
|
||||
rem = g_cpuConstRegs[_Rs_].UL[0] % g_cpuConstRegs[_Rt_].UL[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
quot = 0xffffffff;
|
||||
rem = g_cpuConstRegs[_Rs_].UL[0];
|
||||
}
|
||||
|
||||
recWritebackConstHILO((u64)quot|((u64)rem<<32), 0, upper);
|
||||
}
|
||||
|
||||
void recDIVU_const()
|
||||
{
|
||||
if (g_cpuConstRegs[_Rt_].UL[0] != 0) {
|
||||
u32 quot = g_cpuConstRegs[_Rs_].UL[0] / g_cpuConstRegs[_Rt_].UL[0];
|
||||
u32 rem = g_cpuConstRegs[_Rs_].UL[0] % g_cpuConstRegs[_Rt_].UL[0];
|
||||
|
||||
recWritebackConstHILO((u64)quot|((u64)rem<<32), 0, 0);
|
||||
}
|
||||
recDIVUconst(0);
|
||||
}
|
||||
|
||||
void recDIVU_(int info)
|
||||
|
@ -689,12 +741,7 @@ EERECOMPILE_CODE0(DIVU, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITELO|XMMINFO_WRIT
|
|||
|
||||
void recDIV1_const()
|
||||
{
|
||||
if (g_cpuConstRegs[_Rt_].SL[0] != 0) {
|
||||
s32 quot = g_cpuConstRegs[_Rs_].SL[0] / g_cpuConstRegs[_Rt_].SL[0];
|
||||
s32 rem = g_cpuConstRegs[_Rs_].SL[0] % g_cpuConstRegs[_Rt_].SL[0];
|
||||
|
||||
recWritebackConstHILO((u64)quot|((u64)rem<<32), 0, 1);
|
||||
}
|
||||
recDIVconst(1);
|
||||
}
|
||||
|
||||
void recDIV1_(int info)
|
||||
|
@ -716,12 +763,7 @@ EERECOMPILE_CODE0(DIV1, XMMINFO_READS|XMMINFO_READT);
|
|||
|
||||
void recDIVU1_const()
|
||||
{
|
||||
if (g_cpuConstRegs[_Rt_].UL[0] != 0) {
|
||||
u32 quot = g_cpuConstRegs[_Rs_].UL[0] / g_cpuConstRegs[_Rt_].UL[0];
|
||||
u32 rem = g_cpuConstRegs[_Rs_].UL[0] % g_cpuConstRegs[_Rt_].UL[0];
|
||||
|
||||
recWritebackConstHILO((u64)quot|((u64)rem<<32), 0, 1);
|
||||
}
|
||||
recDIVUconst(1);
|
||||
}
|
||||
|
||||
void recDIVU1_(int info)
|
||||
|
|
Loading…
Reference in New Issue