aboutsummaryrefslogtreecommitdiff
path: root/indev/psn00bdbg-mk2/testutil/mips_disassembler.c
diff options
context:
space:
mode:
authorlameguy64 <lameguy64@github.com>2024-05-04 18:55:05 +0800
committerlameguy64 <lameguy64@github.com>2024-05-04 18:55:05 +0800
commit702bb601fb5712e2ae962a34b89204c646fe98f5 (patch)
tree765f400d1535d37c5ff4df61d01229a7dc7d8207 /indev/psn00bdbg-mk2/testutil/mips_disassembler.c
parent00abe5963fbead092f91935b90390aa5a9111c43 (diff)
downloadpsn00bsdk-702bb601fb5712e2ae962a34b89204c646fe98f5.tar.gz
Included PSn00bDBG-mk2 monitor and test utility
Diffstat (limited to 'indev/psn00bdbg-mk2/testutil/mips_disassembler.c')
-rw-r--r--indev/psn00bdbg-mk2/testutil/mips_disassembler.c663
1 files changed, 663 insertions, 0 deletions
diff --git a/indev/psn00bdbg-mk2/testutil/mips_disassembler.c b/indev/psn00bdbg-mk2/testutil/mips_disassembler.c
new file mode 100644
index 0000000..c7effb7
--- /dev/null
+++ b/indev/psn00bdbg-mk2/testutil/mips_disassembler.c
@@ -0,0 +1,663 @@
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <stdlib.h>
+#include "mips_disassembler.h"
+#include "pstypes.h"
+
+#define OPCODE1(p) ( (p>>26)&0x3F )
+#define OPCODE2(p) ( p&0x3F )
+#define OPREGS(p) ( (p>>21)&0x1f )
+#define OPREGT(p) ( (p>>16)&0x1f )
+#define OPREGD(p) ( (p>>11)&0x1f )
+
+#define OPIMM5(p) ( (p>>6)&0x1f )
+#define OPIMM16(p) ( p&0xffff )
+#define OPIMM20(p) ( (p>>6)&0x1FFFFF )
+#define OPIMM25(p) ( p&0x1FFFFFF )
+#define OPIMM26(p) ( p&0x3FFFFFF )
+#define EXTEND26(p) (((int)(p<<6))>>6)
+#define EXTEND16(p) (((int)(p<<16))>>16)
+
+static const char* regs[] = {
+ "r0","at","v0","v1",
+ "a0","a1","a2","a3",
+ "t0","t1","t2","t3",
+ "t4","t5","t6","t7",
+ "s0","s1","s2","s3",
+ "s4","s5","s6","s7",
+ "t8","t9","k0","k1",
+ "gp","sp","fp","ra"
+};
+
+static void Decode_cop(unsigned int opcode, char* output) {
+
+ int copnum = OPCODE1(opcode)&0x3;
+
+ const char* cop0_nick[32] = {
+ "N/A","N/A","N/A","BPC", // r0-r3
+ "N/A","BDA","JUMPDEST","DCIC", // r4-r7
+ "BadVaddr","BDAM","N/A","BPCM", // r8-r11
+ "SR","CAUSE","EPC","PRID", // r12-r15
+ "N/A","N/A","N/A","N/A",
+ "N/A","N/A","N/A","N/A",
+ "N/A","N/A","N/A","N/A",
+ "N/A","N/A","N/A","N/A",
+ };
+
+ const char* cop2_data_nick[32] = {
+ "VXY0","VZ0","VXY1","VZ1", // r0-r3
+ "VXY2","VZ2","RGBC","OTZ", // r4-r7
+ "IR0","IR1","IR2","IR3", // r8-r11
+ "SXY0","SXY1","SXY2","SXYP", // r12-r15
+ "SZ0","SZ1","SZ2","SZ3",
+ "RGB0","RGB1","RGB2","RES1",
+ "MAC0","MAC1","MAC2","MAC3",
+ "IRGB","ORGB","LZCS","LZCR",
+ };
+
+ const char* cop2_ctrl_nick[32] = {
+ "RT11","RT12","RT13","RT21", // r0-r3
+ "RT22","RT23","RT31","RT32", // r4-r7
+ "RT33","TRX","TRY","TRZ", // r8-r11
+ "LR1","LR2","LR3","LG1", // r12-r15
+ "LG2","LG3","LB1","LB2",
+ "LB3","RFC","GFC","BFC",
+ "OFX","OFY","H","DQA",
+ "DQB","ZSF3","ZSF4","FLAG",
+ };
+
+ char temp[16];
+
+ if( (OPCODE1(opcode)&0x20) == 0 ) {
+
+ switch(OPREGS(opcode)) {
+ case 0x0: // mfc?
+ sprintf( output, "mfc%d %s, r%d", copnum,
+ regs[OPREGT(opcode)],
+ OPREGD(opcode) );
+
+ if ( copnum == 0 ) {
+
+ sprintf( temp, " (%s)", cop0_nick[OPREGD(opcode)] );
+ strcat( output, temp );
+
+ } else if ( copnum == 2 ) {
+
+ sprintf( temp, " (%s)", cop2_data_nick[OPREGD(opcode)] );
+ strcat( output, temp );
+
+ }
+
+ break;
+ case 0x2: // cfc?
+
+ sprintf( output, "cfc%d %s, r%d", copnum,
+ regs[OPREGT(opcode)],
+ OPREGD(opcode) );
+
+ if ( copnum == 2 ) {
+
+ sprintf( temp, " (%s)", cop2_ctrl_nick[OPREGD(opcode)] );
+ strcat( output, temp );
+
+ }
+
+ break;
+ case 0x4: // mtc?
+
+ sprintf( output, "mtc%d %s, r%d", copnum,
+ regs[OPREGT(opcode)],
+ OPREGD(opcode) );
+
+ if ( copnum == 0 ) {
+
+ sprintf( temp, " (%s)", cop0_nick[OPREGD(opcode)] );
+ strcat( output, temp );
+
+ } else if ( copnum == 2 ) {
+
+ sprintf( temp, " (%s)", cop2_data_nick[OPREGD(opcode)] );
+ strcat( output, temp );
+
+ }
+
+ break;
+ case 0x6: // ctc?
+
+ sprintf( output, "ctc%d %s, r%d", copnum,
+ regs[OPREGT(opcode)], OPREGT(opcode) );
+
+ if ( copnum == 2 )
+ {
+ sprintf( temp, " (%s)", cop2_ctrl_nick[OPREGT(opcode)] );
+ strcat( output, temp );
+ }
+
+ break;
+
+ case 0x8: // bc?f bc?t
+ if( OPREGT(opcode) == 1 )
+ {
+ sprintf( output, "bc%dt $%X", copnum,
+ OPIMM16(opcode) );
+ }
+ else
+ {
+ sprintf( output, "bc%df $%X", copnum,
+ OPIMM16(opcode) );
+ }
+ break;
+
+ default: // cop?
+
+ //strcpy( output, "cp" );
+ //sprintf( output, "%x", OPREGS(opcode) );
+
+ if( OPREGS(opcode)&0x10 )
+ {
+ sprintf( output, "cop%d $%X", copnum, OPIMM25(opcode) );
+ }
+ break;
+ }
+
+ } else {
+
+ if( (OPCODE1(opcode)&0x8) == 0 ) {
+
+ sprintf( output, "lwc%d r%d,%d(%s)", copnum,
+ OPREGT(opcode), EXTEND16(OPIMM16(opcode)),
+ regs[OPREGS(opcode)] );
+
+ if ( copnum == 0 ) {
+
+ sprintf( temp, " (%s)", cop0_nick[OPREGT(opcode)] );
+ strcat( output, temp );
+
+ } else if ( copnum == 2 ) {
+
+ sprintf( temp, " (%s)", cop2_data_nick[OPREGT(opcode)] );
+ strcat( output, temp );
+
+ }
+
+ } else {
+
+ sprintf( output, "swc%d r%d,%d(%s)", copnum,
+ OPREGT(opcode), EXTEND16(OPIMM16(opcode)),
+ regs[OPREGS(opcode)] );
+
+ if ( copnum == 0 ) {
+
+ sprintf( temp, " (%s)", cop0_nick[OPREGT(opcode)] );
+ strcat( output, temp );
+
+ } else if ( copnum == 2 ) {
+
+ sprintf( temp, " (%s)", cop2_data_nick[OPREGT(opcode)] );
+ strcat( output, temp );
+
+ }
+
+ }
+
+ }
+
+}
+
+void mips_Decode(unsigned int opcode, unsigned int addr, char* output, int arrows) {
+
+ char temp[32];
+ int immval;
+
+ const char* pri_op[] = {
+ NULL ,NULL ,"j " ,"jal ",//4
+ "beq " ,"bne " ,"blez " ,"bgtz ",//8
+ "addi " ,"addiu " ,"slti " ,"sltiu ",//12
+ "andi " ,"ori " ,"xori " ,"lui ",//16
+ "cop0 " ,"cop1<!> " ,"cop2 " ,"cop3<!> ",//24
+ NULL , NULL ,NULL , NULL, //32
+ NULL , NULL ,NULL , NULL, //36
+ NULL , NULL ,NULL , NULL, //40
+ "lb " ,"lh " ,"lwl " ,"lw ",//44
+ "lbu " ,"lhu " ,"lwr " ,NULL, //48
+ "sb " ,"sh " ,"swl " ,"sw ",
+ NULL ,NULL ,"swr " ,NULL,
+ };
+
+ const char* sc_op[] = {
+ "sll " ,NULL ,"srl " ,"sra " , //0
+ "sllv " ,NULL ,"srlv " ,"srav " , //4
+ "jr " ,"jalr " ,NULL ,NULL , //8
+ "syscall " ,"break " ,NULL ,NULL , //12
+ "mfhi " ,"mthi " ,"mflo " ,"mtlo " , //16
+ NULL ,NULL ,NULL ,NULL , //20
+ "mult " ,"multu " ,"div " ,"divu " , //24
+ NULL ,NULL ,NULL ,NULL , //28
+ "add " ,"addu " ,"sub " ,"subu " , //32
+ "and " ,"or " ,"xor " ,"nor " , //36
+ NULL ,NULL ,"slt " ,"sltu " , //38
+ };
+
+ strcpy( output, "???" );
+
+ if( opcode ) {
+
+ // Secondary codes
+ if( OPCODE1(opcode) == 0 ) {
+
+ switch( OPCODE2(opcode) ) {
+ case 0x0: // sll, srl, sra
+ case 0x2:
+ case 0x3:
+ strcpy( output, sc_op[OPCODE2(opcode)] );
+ sprintf( temp, "%s, %s, %d",
+ regs[OPREGD(opcode)], regs[OPREGT(opcode)], OPIMM5(opcode) );
+ strcat( output, temp );
+ break;
+ case 0x4: // sllv, srlv, srav
+ case 0x6:
+ case 0x7:
+ strcpy( output, sc_op[OPCODE2(opcode)] );
+ sprintf( temp, "%s, %s, %s", regs[OPREGT(opcode)],
+ regs[OPREGD(opcode)], regs[OPREGS(opcode)] );
+ strcat( output, temp );
+ break;
+ case 0x8: // jr
+ strcpy( output, sc_op[OPCODE2(opcode)] );
+ strcat( output, regs[OPREGS(opcode)] );
+ break;
+ case 0x9: // jalr
+ strcpy( output, sc_op[OPCODE2(opcode)] );
+ sprintf( temp, "%s, %s", regs[OPREGD(opcode)],
+ regs[OPREGS(opcode)] );
+ strcat( output, temp );
+ break;
+ case 0xc: // syscall, break
+ case 0xd:
+ strcpy( output, sc_op[OPCODE2(opcode)] );
+ sprintf( temp, "$%x", OPIMM20(opcode) );
+ strcat( output, temp );
+ break;
+ case 0x10: // mfhi, mflo
+ case 0x12:
+ strcpy( output, sc_op[OPCODE2(opcode)] );
+ strcat( output, regs[OPREGD(opcode)] );
+ break;
+ case 0x11: // mthi, mtlo
+ case 0x13:
+ strcpy( output, sc_op[OPCODE2(opcode)] );
+ strcat( output, regs[OPREGS(opcode)] );
+ break;
+ case 0x18: // mult, multu, div, divu
+ case 0x19:
+ case 0x1a:
+ case 0x1b:
+ strcpy( output, sc_op[OPCODE2(opcode)] );
+ sprintf( temp, "%s, %s", regs[OPREGS(opcode)],
+ regs[OPREGT(opcode)] );
+ strcat( output, temp );
+ break;
+ case 0x2a: // slt, sltu
+ case 0x2b:
+ strcpy( output, sc_op[OPCODE2(opcode)] );
+ sprintf( temp, "%s, %s, %s", regs[OPREGD(opcode)],
+ regs[OPREGS(opcode)], regs[OPREGT(opcode)] );
+ strcat( output, temp );
+ break;
+ default:
+
+ if( ( OPCODE2(opcode) >= 0x20 ) && ( OPCODE2(opcode) <= 0x27 ) ) {
+ strcpy( output, sc_op[OPCODE2(opcode)] );
+ sprintf( temp, "%s, %s, %s", regs[OPREGD(opcode)],
+ regs[OPREGT(opcode)], regs[OPREGS(opcode)] );
+ strcat( output, temp );
+ }
+
+ break;
+ }
+
+ // Primary
+ } else {
+
+ if( OPCODE1(opcode) == 0x1 ) { // Branches
+
+ switch((opcode>>16)&0x1f) {
+ case 0x0:
+ strcpy(output, "bltz ");
+ break;
+ case 0x1:
+ strcpy(output, "bgez ");
+ break;
+ case 0x10:
+ strcpy(output, "bltzal ");
+ break;
+ case 0x11:
+ strcpy(output, "bgtzal ");
+ break;
+ }
+
+ sprintf( temp, "%s,$%08X ", regs[OPREGS(opcode)],
+ addr+4+(EXTEND16(OPIMM16(opcode))*4) );
+ strcat( output, temp );
+
+ if( arrows ) {
+ if ( addr+4+(EXTEND16(OPIMM16(opcode))*4) > addr ) {
+ strcat( output, "▼" );
+ } else {
+ strcat( output, "▲" );
+ }
+ }
+
+ } else if( ( OPCODE1(opcode) == 0x2 ) || ( OPCODE1(opcode) == 0x3 ) ) { // j, jal
+
+ unsigned int dest = (OPIMM26(opcode)*4)|(addr&0xf0000000);
+
+ strcpy( output, pri_op[OPCODE1(opcode)] );
+ sprintf( temp, "$%08X ", dest );
+ strcat( output, temp );
+
+ if( arrows ) {
+ if ( dest > addr ) {
+ strcat( output, "▼" );
+ } else {
+ strcat( output, "▲" );
+ }
+ }
+ } else if( ( OPCODE1(opcode) >= 0x8 ) &&
+ ( OPCODE1(opcode) <= 0x9 ) ) {
+
+ strcpy( output, pri_op[OPCODE1(opcode)] );
+
+ sprintf( temp, "%s, %s, %d", regs[OPREGT(opcode)],
+ regs[OPREGS(opcode)], EXTEND16(OPIMM16(opcode)) );
+ strcat( output, temp );
+
+ } else if( ( OPCODE1(opcode) >= 0xa ) &&
+ ( OPCODE1(opcode) <= 0xe ) ) {
+
+ strcpy( output, pri_op[OPCODE1(opcode)] );
+
+ sprintf( temp, "%s, %s, $%lX", regs[OPREGT(opcode)],
+ regs[OPREGS(opcode)], labs( OPIMM16(opcode) ) );
+ strcat( output, temp );
+
+ } else if( OPCODE1(opcode) == 0xf ) {
+
+ strcpy( output, pri_op[OPCODE1(opcode)] );
+ sprintf( temp, "%s, $%X",
+ regs[OPREGT(opcode)], OPIMM16(opcode) );
+ strcat( output, temp );
+
+ } else if( ( OPCODE1(opcode) >= 0x20 ) &&
+ ( OPCODE1(opcode) <= 0x2e ) ) {
+
+ switch( OPCODE1(opcode) ) {
+ case 0x27:
+ case 0x2c:
+ case 0x2d:
+ return;
+ }
+
+ strcpy( output, pri_op[OPCODE1(opcode)] );
+ sprintf( temp, "%s,",
+ regs[OPREGT(opcode)] );
+ strcat( output, temp );
+
+ immval = EXTEND16(OPIMM16(opcode));
+ sprintf( temp, "$%lX", labs( immval ) );
+ if( immval < 0 ) {
+ strcat( output, "-" );
+ } else {
+ strcat( output, " " );
+ }
+ strcat( output, temp );
+
+ sprintf( temp, "(%s)", regs[OPREGS(opcode)] );
+ strcat( output, temp );
+
+ } else if ( OPCODE1(opcode)&0x10 ) {
+
+ Decode_cop( opcode, output );
+
+ } else {
+
+ switch( OPCODE1(opcode) ) {
+ case 0x4:
+ case 0x5:
+ strcpy( output, pri_op[OPCODE1(opcode)] );
+ sprintf( temp, "%s, %s, $%08X ",
+ regs[OPREGS(opcode)],
+ regs[OPREGT(opcode)],
+ addr+4+(EXTEND16(OPIMM16(opcode))*4) );
+ strcat( output, temp );
+
+ if( arrows ) {
+ if ( addr+4+(EXTEND16(OPIMM16(opcode))*4) > addr ) {
+ strcat( output, "▼" );
+ } else {
+ strcat( output, "▲" );
+ }
+ }
+
+ break;
+ case 0x6:
+ case 0x7:
+ strcpy( output, pri_op[OPCODE1(opcode)] );
+ sprintf( temp, "%s, $%08X ",
+ regs[OPREGS(opcode)],
+ addr+4+(EXTEND16(OPIMM16(opcode))*4) );
+ strcat( output, temp );
+
+ if( arrows ) {
+ if ( addr+4+(EXTEND16(OPIMM16(opcode))*4) > addr ) {
+ strcat( output, "▼" );
+ } else {
+ strcat( output, "▲" );
+ }
+ }
+
+ break;
+ }
+
+ }
+
+ }
+
+ } else {
+
+ strcpy( output, "nop" );
+
+ }
+
+}
+
+unsigned int mips_GetNextPc(unsigned int *regs, int stepover) {
+
+ unsigned int dest = regs[PS_REG_epc]+4;
+ unsigned int opcode = regs[PS_REG_opcode];
+ unsigned int rv,rt;
+
+ if( OPCODE1(opcode) == 0 ) {
+
+ if( ( OPCODE2(opcode) == 8 )||( OPCODE2(opcode) == 9 ) ) { // jr, jalr
+
+ if( ( OPCODE2(opcode) == 9 ) && ( stepover ) ) {
+
+ dest += 4;
+
+ } else {
+
+ if( OPREGS(opcode) == 0 )
+ dest = 0;
+ else
+ dest = regs[OPREGS(opcode)-1];
+
+ }
+
+ }
+
+ } else if( OPCODE1(opcode) == 1 ) {
+
+ if( OPREGS(opcode) == 0 )
+ rv = 0;
+ else
+ rv = regs[OPREGS(opcode)-1];
+
+ switch(OPREGT(opcode)) {
+ case 0x0: // bltz
+ if ( (((int)0)|rv) < 0 ) {
+ dest = regs[PS_REG_epc]+4+(EXTEND16(OPIMM16(opcode))*4);
+ } else {
+ dest += 4;
+ }
+ break;
+ case 0x1: // bgez
+ if ( (((int)0)|rv) >= 0 ) {
+ dest = regs[PS_REG_epc]+4+(EXTEND16(OPIMM16(opcode))*4);
+ } else {
+ dest += 4;
+ }
+ break;
+ case 0x8: // bltzal
+ if ( (((int)0)|rv) < 0 ) {
+ dest = regs[PS_REG_epc]+4+(EXTEND16(OPIMM16(opcode))*4);
+ } else {
+ dest += 4;
+ }
+ break;
+ case 0x9: // bgezal
+ if ( (((int)0)|rv) >= 0 ) {
+ dest = regs[PS_REG_epc]+4+(EXTEND16(OPIMM16(opcode))*4);
+ } else {
+ dest += 4;
+ }
+ break;
+ }
+
+ } else if( ( OPCODE1(opcode) == 2 ) || ( OPCODE1(opcode) == 3 ) ) { // j,jal
+
+ if( ( OPCODE1(opcode) == 3 ) && ( stepover ) ) {
+
+ dest += 4;
+
+ } else {
+
+ dest = (regs[PS_REG_epc]&0xf0000000)|(OPIMM26(opcode)*4);
+
+ }
+
+ } else if( OPCODE1(opcode) == 4 ) { // beq
+
+ if( OPREGS(opcode) == 0 ) {
+ rv = 0;
+ } else {
+ rv = regs[OPREGS(opcode)-1];
+ }
+
+ if( OPREGT(opcode) == 0 ) {
+ rt = 0;
+ } else {
+ rt = regs[OPREGT(opcode)-1];
+ }
+
+ if( rv == rt ) {
+
+ dest = regs[PS_REG_epc]+4+(EXTEND16(OPIMM16(opcode))*4);
+
+ } else {
+
+ dest += 4;
+
+ }
+
+ } else if( OPCODE1(opcode) == 5 ) { // bne
+
+ if( OPREGS(opcode) == 0 ) {
+ rv = 0;
+ } else {
+ rv = regs[OPREGS(opcode)-1];
+ }
+
+ if( OPREGT(opcode) == 0 ) {
+ rt = 0;
+ } else {
+ rt = regs[OPREGT(opcode)-1];
+ }
+
+ if( rv != rt ) {
+
+ dest = regs[PS_REG_epc]+4+(EXTEND16(OPIMM16(opcode))*4);
+
+ } else {
+
+ dest += 4;
+
+ }
+
+ } else if( OPCODE1(opcode) == 6 ) { // blez
+
+ if( OPREGS(opcode) == 0 ) {
+ rv = 0;
+ } else {
+ rv = regs[OPREGS(opcode)-1];
+ }
+
+ if( (((int)0)|rv) <= 0 ) {
+
+ dest = regs[PS_REG_epc]+4+(EXTEND16(OPIMM16(opcode))*4);
+
+ } else {
+
+ dest += 4;
+
+ }
+
+ } else if( OPCODE1(opcode) == 7 ) { // bgtz
+
+ if( OPREGS(opcode) == 0 ) {
+ rv = 0;
+ } else {
+ rv = regs[OPREGS(opcode)-1];
+ }
+
+ if( (((int)0)|rv) > 0 ) {
+
+ dest = regs[PS_REG_epc]+4+(EXTEND16(OPIMM16(opcode))*4);
+
+ } else {
+
+ dest += 4;
+
+ }
+
+ }
+
+ return dest;
+}
+
+unsigned int mips_GetJumpAddr(unsigned int addr, unsigned int opcode) {
+
+ if( OPCODE1(opcode) == 1 ) {
+
+ switch(OPREGT(opcode)) {
+ case 0x0: // bltz
+ case 0x1: // bgez
+ case 0x8: // bltzal
+ case 0x9: // bgezal
+ return addr+4+(EXTEND16(OPIMM16(opcode))*4);
+ }
+
+ } else if( ( OPCODE1(opcode) == 2 ) || ( OPCODE1(opcode) == 3 ) ) { // j,jal
+
+ return (addr&0xf0000000)|(OPIMM26(opcode)*4);
+
+ } else if( ( OPCODE1(opcode) >= 4 ) && ( OPCODE1(opcode) <= 7 ) ) { // beq
+
+ return addr+4+(EXTEND16(OPIMM16(opcode))*4);
+
+ }
+
+ return 0;
+
+}