Implemented a new optimized version of recPLZCW, though it probably doesn't make much actual difference to performance (but it was fun! :)

Applied a small patch from Pseudonym that repairs the Debugger (sorta).

git-svn-id: http://pcsx2-playground.googlecode.com/svn/trunk@679 a6443dda-0b58-4228-96e9-037be469359c
This commit is contained in:
Jake.Stine 2009-02-01 20:44:35 +00:00 committed by Gregory Hainaut
parent 6ec4518d35
commit f8b274ddfe
4 changed files with 57 additions and 77 deletions

View File

@ -610,18 +610,14 @@ void disR5900Fasm(string& output, u32 code, u32 pc)
{
string dbuf;
char obuf[48];
const R5900::OPCODE *op;
const u32 scode = cpuRegs.code;
opcode_addr = pc;
cpuRegs.code = code;
op = &R5900::OpcodeTables::tbl_Standard[(code) >> 26];
while (op->getsubclass)
op = &op->getsubclass();
sprintf(obuf, "%08X:\t", pc );
output.assign( obuf );
op->disasm( output );
GetCurrentInstruction().disasm( output );
cpuRegs.code = scode;
}
@ -727,8 +723,8 @@ void ANDI( string& output ) { _sap("andi\t%s, %s, 0x%04X") GPR_REG[DECODE_RT
void ORI( string& output ) { _sap("ori\t%s, %s, 0x%04X") GPR_REG[DECODE_RT], GPR_REG[DECODE_RS], DECODE_IMMED); }
void XORI( string& output ) { _sap("xori\t%s, %s, 0x%04X") GPR_REG[DECODE_RT], GPR_REG[DECODE_RS], DECODE_IMMED); }
void LUI( string& output ) { _sap("lui\t%s, 0x%04X") GPR_REG[DECODE_RT], DECODE_IMMED); }
void BEQL( string& output ) { _sap("beql\t%s, %s, %s") GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); offset_decode(output); }
void BNEL( string& output ) { _sap("bnel\t%s, %s, %s") GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); offset_decode(output); }
void BEQL( string& output ) { _sap("beql\t%s, %s, ") GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); offset_decode(output); }
void BNEL( string& output ) { _sap("bnel\t%s, %s, ") GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); offset_decode(output); }
void BLEZL( string& output ) { _sap("blezl\t%s, ") GPR_REG[DECODE_RS]); offset_decode(output); }
void BGTZL( string& output ) { _sap("bgtzl\t%s, ") GPR_REG[DECODE_RS]); offset_decode(output); }
void DADDI( string& output ) { _sap("daddi\t%s, %s, 0x%04X") GPR_REG[DECODE_RT], GPR_REG[DECODE_RS], DECODE_IMMED); }
@ -1193,4 +1189,4 @@ void P_VRINIT( string& output ){_sap("vrinit R, %s%s") COP2_REG_CTL[DECODE_FS],
void P_VRXOR( string& output ){_sap("vrxor R, %s%s") COP2_REG_CTL[DECODE_FS], dest_string());}
//************************************END OF SPECIAL2 VUO TABLE****************************
}
}

View File

@ -132,17 +132,21 @@ namespace MMI {
__forceinline void _PLZCW(int n)
{
int i;
u32 sign;
sign = cpuRegs.GPR.r[_Rs_].UL[n] >> 31;
for (i=30; i>=0; i--) {
if (((cpuRegs.GPR.r[_Rs_].UL[n] >> i) & 0x1) != sign)
break;
}
cpuRegs.GPR.r[_Rd_].UL[n] = 30 - i;
// This function counts the number of "like" bits in the source register, starting
// with the MSB and working its way down, and returns the result MINUS ONE.
// So 0xff00 would return 7, not 8.
int c = 0;
s32 i = cpuRegs.GPR.r[_Rs_].SL[n];
// Negate the source based on the sign bit. This allows us to use a simple
// unified bit test of the MSB for either condition.
if( i >= 0 ) i = ~i;
// shift first, compare, then increment. This excludes the sign bit from our final count.
while( i <<= 1, i < 0 ) c++;
cpuRegs.GPR.r[_Rd_].UL[n] = c;
}
void PLZCW() {

View File

@ -117,7 +117,7 @@ extern void EEDumpRegs(FILE * fp);
extern void IOPDumpRegs(FILE * fp);
BOOL APIENTRY DumpProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
char start[16], end[16], fname[128], tmp[128], buf[128];
char start[16], end[16], fname[128], tmp[128];
unsigned long start_pc, end_pc, temp;
FILE *fp;
@ -125,14 +125,14 @@ BOOL APIENTRY DumpProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
switch (message)
{
case WM_INITDIALOG:
sprintf(buf, "%08X", cpuRegs.pc);
SetDlgItemText(hDlg, IDC_DUMP_START, buf);
SetDlgItemText(hDlg, IDC_DUMP_END, buf);
sprintf(tmp, "%08X", cpuRegs.pc);
SetDlgItemText(hDlg, IDC_DUMP_START, tmp);
SetDlgItemText(hDlg, IDC_DUMP_END, tmp);
SetDlgItemText(hDlg, IDC_DUMP_FNAME, "EEdisasm.txt");
sprintf(buf, "%08X", psxRegs.pc);
SetDlgItemText(hDlg, IDC_DUMP_STARTIOP, buf);
SetDlgItemText(hDlg, IDC_DUMP_ENDIOP, buf);
sprintf(tmp, "%08X", psxRegs.pc);
SetDlgItemText(hDlg, IDC_DUMP_STARTIOP, tmp);
SetDlgItemText(hDlg, IDC_DUMP_ENDIOP, tmp);
SetDlgItemText(hDlg, IDC_DUMP_FNAMEIOP, "IOPdisasm.txt");
return TRUE;
@ -168,13 +168,9 @@ BOOL APIENTRY DumpProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
MakeDebugOpcode();
output.assign( HasBreakpoint() ? "*" : "" );
sprintf(buf, "%08X %08X: %s", temp, cpuRegs.code, tmp);
output.append( buf );
R5900::GetCurrentInstruction().disasm( output );
R5900::OpcodeTables::tbl_Standard[_Opcode_].disasm( output );
fprintf(fp, "%s\n", buf);
fprintf(fp, "%08X %08X: %s\n", temp, cpuRegs.code, output.c_str());
}
@ -213,8 +209,7 @@ BOOL APIENTRY DumpProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
opcode_addr=temp;
MakeIOPDebugOpcode();
R3000A::IOP_DEBUG_BSC[(psxRegs.code) >> 26](tmp);
sprintf(buf, "%08X %08X: %s", temp, psxRegs.code, tmp);
fprintf(fp, "%s\n", buf);
fprintf(fp, "%08X %08X: %s\n", temp, psxRegs.code, tmp);
}
fprintf(fp,"\n\n\n----------------------------------\n");

View File

@ -110,35 +110,28 @@ void recPLZCW()
_deleteEEreg(_Rd_, 0);
}
// first word
// Count the number of leading bits (MSB) that match the sign bit, excluding the sign
// bit itself.
TEST32ItoR(EAX, 0x80000000);
j8Ptr[0] = JZ8(0);
// Strategy: If the sign bit is set, then negate the value. And that way the same
// bitcompare can be used for either bit status. but be warned! BSR returns undefined
// results if the EAX is zero, so we need to have special checks for zeros before
// using it.
// --- first word ---
MOV32ItoR(ECX,31);
TEST32RtoR(EAX, EAX); // TEST sets the sign flag accordingly.
u8* label_notSigned = JNS8(0);
NOT32R(EAX);
x86SetJ8(j8Ptr[0]);
x86SetJ8(label_notSigned);
TEST32RtoR(EAX, EAX);
j8Ptr[0] = JNZ8(0);
// zero, so put 31
if( EEINST_ISLIVE1(_Rd_) || regd < 0 ) {
MOV32ItoM((uptr)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], 31);
}
else {
SetMMXstate();
PCMPEQDRtoR(regd, regd);
PSRLQItoR(regd, 59);
}
j8Ptr[1] = JMP8(0);
x86SetJ8(j8Ptr[0]);
// not zero
x86SetJ8(j8Ptr[0]);
BSRRtoR(EAX, EAX);
MOV32ItoR(ECX, 30);
u8* label_Zeroed = JZ8(0); // If BSR sets the ZF, eax is "trash"
SUB32RtoR(ECX, EAX);
DEC32R(ECX); // PS2 doesn't count the first bit
x86SetJ8(label_Zeroed);
if( EEINST_ISLIVE1(_Rd_) || regd < 0 ) {
MOV32RtoM((uptr)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], ECX);
}
@ -147,9 +140,8 @@ void recPLZCW()
MOVD32RtoMMX(regd, ECX);
}
x86SetJ8(j8Ptr[1]);
// second word
if( EEINST_ISLIVE1(_Rd_) ) {
if( regs >= 0 && (regs & MEM_XMMTAG) ) {
SSE2_PSHUFD_XMM_to_XMM(regs&0xf, regs&0xf, 0x4e);
@ -164,26 +156,19 @@ void recPLZCW()
}
else MOV32MtoR(EAX, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ]);
TEST32ItoR(EAX, 0x80000000);
j8Ptr[0] = JZ8(0);
MOV32ItoR(ECX, 31);
TEST32RtoR(EAX, EAX); // TEST sets the sign flag accordingly.
label_notSigned = JNS8(0);
NOT32R(EAX);
x86SetJ8(j8Ptr[0]);
x86SetJ8(label_notSigned);
TEST32RtoR(EAX, EAX);
j8Ptr[0] = JNZ8(0);
// zero, so put 31
MOV32ItoM((uptr)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], 31);
j8Ptr[1] = JMP8(0);
x86SetJ8(j8Ptr[0]);
// not zero
x86SetJ8(j8Ptr[0]);
BSRRtoR(EAX, EAX);
MOV32ItoR(ECX, 30);
u8* label_Zeroed = JZ8(0); // If BSR sets the ZF, eax is "trash"
SUB32RtoR(ECX, EAX);
MOV32RtoM((uptr)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], ECX);
x86SetJ8(j8Ptr[1]);
DEC32R(ECX); // PS2 doesn't count the first bit
x86SetJ8(label_Zeroed);
MOV32ItoM((uptr)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], ECX);
}
else {
EEINST_RESETHASLIVE1(_Rd_);
@ -265,7 +250,7 @@ CPU_SSE2_XMMCACHE_START(XMMINFO_WRITED|XMMINFO_READLO|XMMINFO_READHI)
CPU_SSE_XMMCACHE_END
recCall( Interp::PMFHL, _Rd_ );
recCall( Interp::PMFHL, _Rd_ );
}
void recPMTHL()