From 0718937237db22d26e1b764b4733645c2b9f1562 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Thu, 17 Jul 2014 21:33:51 -0400 Subject: [PATCH] Common: Introduce the new Gekko disassembler to Common. This moves the Gekko disassembler to Common where it should be. Having it in the Bochs disassembly Externals is incorrect. Unlike the PowerPC disassembler prior however, this one is updated to have an API that is more fitting for C++. e.g. Not needing to specify a string buffer and size. It does all of this under the hood. This modifies all the DebuggingInterfaces as necessary to handle this. --- Externals/Bochs_disasm/Bochs_disasm.vcxproj | 4 +- Externals/Bochs_disasm/CMakeLists.txt | 11 +- Externals/Bochs_disasm/PowerPCDisasm.cpp | 2285 ---------------- Externals/Bochs_disasm/PowerPCDisasm.h | 29 - Source/Core/Common/CMakeLists.txt | 1 + Source/Core/Common/Common.vcxproj | 4 +- Source/Core/Common/Common.vcxproj.filters | 2 + Source/Core/Common/DebugInterface.h | 2 +- Source/Core/Common/GekkoDisassembler.cpp | 2299 +++++++++++++++++ Source/Core/Common/GekkoDisassembler.h | 152 ++ .../Core/Core/Debugger/PPCDebugInterface.cpp | 24 +- Source/Core/Core/Debugger/PPCDebugInterface.h | 2 +- .../Core/Core/HW/DSPLLE/DSPDebugInterface.cpp | 7 +- .../Core/Core/HW/DSPLLE/DSPDebugInterface.h | 3 +- .../Core/PowerPC/Interpreter/Interpreter.cpp | 14 +- Source/Core/Core/PowerPC/Jit64/Jit.cpp | 7 +- .../Core/Core/PowerPC/JitCommon/JitBase.cpp | 10 +- Source/Core/Core/PowerPC/PPCSymbolDB.cpp | 6 +- Source/Core/DolphinWX/Debugger/CodeView.cpp | 110 +- Source/Core/DolphinWX/Debugger/JitWindow.cpp | 7 +- .../Core/DolphinWX/Debugger/RegisterView.cpp | 8 +- 21 files changed, 2553 insertions(+), 2434 deletions(-) delete mode 100644 Externals/Bochs_disasm/PowerPCDisasm.cpp delete mode 100644 Externals/Bochs_disasm/PowerPCDisasm.h create mode 100644 Source/Core/Common/GekkoDisassembler.cpp create mode 100644 Source/Core/Common/GekkoDisassembler.h diff --git a/Externals/Bochs_disasm/Bochs_disasm.vcxproj b/Externals/Bochs_disasm/Bochs_disasm.vcxproj index 4bd9dd4a43..917b83248d 100644 --- a/Externals/Bochs_disasm/Bochs_disasm.vcxproj +++ b/Externals/Bochs_disasm/Bochs_disasm.vcxproj @@ -1,4 +1,4 @@ - + @@ -48,12 +48,10 @@ - - diff --git a/Externals/Bochs_disasm/CMakeLists.txt b/Externals/Bochs_disasm/CMakeLists.txt index 93a73f9392..a58e50e928 100644 --- a/Externals/Bochs_disasm/CMakeLists.txt +++ b/Externals/Bochs_disasm/CMakeLists.txt @@ -1,11 +1,10 @@ -set(SRCS dis_decode.cpp - dis_groups.cpp - resolve.cpp - syntax.cpp - PowerPCDisasm.cpp) +set(SRCS dis_decode.cpp + dis_groups.cpp + resolve.cpp + syntax.cpp) if(WIN32) - set(SRCS ${SRCS} stdafx.cpp) + set(SRCS ${SRCS} stdafx.cpp) endif(WIN32) add_library(bdisasm STATIC ${SRCS}) diff --git a/Externals/Bochs_disasm/PowerPCDisasm.cpp b/Externals/Bochs_disasm/PowerPCDisasm.cpp deleted file mode 100644 index f6de85d845..0000000000 --- a/Externals/Bochs_disasm/PowerPCDisasm.cpp +++ /dev/null @@ -1,2285 +0,0 @@ -/* $VER: ppc_disasm.c V1.1 (19.02.2000) -* -* Disassembler module for the PowerPC microprocessor family -* Copyright (c) 1998-2000 Frank Wille -* -* ppc_disasm.c is freeware and may be freely redistributed as long as -* no modifications are made and nothing is charged for it. -* Non-commercial usage is allowed without any restrictions. -* EVERY PRODUCT OR PROGRAM DERIVED DIRECTLY FROM MY SOURCE MAY NOT BE -* SOLD COMMERCIALLY WITHOUT PERMISSION FROM THE AUTHOR. -* -* -* v1.2 (31.07.2003) org -* modified for IBM PowerPC Gekko. -* v1.1 (19.02.2000) phx -* fabs wasn't recognized. -* v1.0 (30.01.2000) phx -* stfsx, stfdx, lfsx, lfdx, stfsux, stfdux, lfsux, lfdux, etc. -* printed "rd,ra,rb" as operands instead "fd,ra,rb". -* v0.4 (01.06.1999) phx -* 'stwm' shoud have been 'stmw'. -* v0.3 (17.11.1998) phx -* The OE-types (e.g. addo, subfeo, etc.) didn't work for all -* instructions. -* AA-form branches have an absolute destination. -* addze and subfze must not have a third operand. -* sc was not recognized. -* v0.2 (29.05.1998) phx -* Sign error. SUBI got negative immediate values. -* v0.1 (23.05.1998) phx -* First version, which implements all PowerPC instructions. -* v0.0 (09.05.1998) phx -* File created. -*/ -#include -#include -#include -#include - -#include "PowerPCDisasm.h" - -namespace PPCDisasm -{ - -/* version/revision */ -#define PPCDISASM_VER 1 -#define PPCDISASM_REV 1 - - -/* typedefs */ -typedef unsigned int ppc_word; - -#undef BIGENDIAN -#undef LITTTLEENDIAN -/* endianess */ -#define LITTLEENDIAN 0 - - -/* general defines */ -#define PPCIDXMASK 0xfc000000 -#define PPCIDX2MASK 0x000007fe -#define PPCDMASK 0x03e00000 -#define PPCAMASK 0x001f0000 -#define PPCBMASK 0x0000f800 -#define PPCCMASK 0x000007c0 -#define PPCMMASK 0x0000003e -#define PPCCRDMASK 0x03800000 -#define PPCCRAMASK 0x001c0000 -#define PPCLMASK 0x00600000 -#define PPCOE 0x00000400 - -#define PPCIDXSH 26 -#define PPCDSH 21 -#define PPCASH 16 -#define PPCBSH 11 -#define PPCCSH 6 -#define PPCMSH 1 -#define PPCCRDSH 23 -#define PPCCRASH 18 -#define PPCLSH 21 -#define PPCIDX2SH 1 - -#define PPCGETIDX(x) (((x)&PPCIDXMASK)>>PPCIDXSH) -#define PPCGETD(x) (((x)&PPCDMASK)>>PPCDSH) -#define PPCGETA(x) (((x)&PPCAMASK)>>PPCASH) -#define PPCGETB(x) (((x)&PPCBMASK)>>PPCBSH) -#define PPCGETC(x) (((x)&PPCCMASK)>>PPCCSH) -#define PPCGETM(x) (((x)&PPCMMASK)>>PPCMSH) -#define PPCGETCRD(x) (((x)&PPCCRDMASK)>>PPCCRDSH) -#define PPCGETCRA(x) (((x)&PPCCRAMASK)>>PPCCRASH) -#define PPCGETL(x) (((x)&PPCLMASK)>>PPCLSH) -#define PPCGETIDX2(x) (((x)&PPCIDX2MASK)>>PPCIDX2SH) - - - /* Disassembler structure, the interface to the application */ - - struct DisasmPara_PPC { - ppc_word *instr; /* pointer to instruction to disassemble */ - ppc_word *iaddr; /* instr.addr., usually the same as instr */ - char *opcode; /* buffer for opcode, min. 10 chars. */ - char *operands; /* operand buffer, min. 24 chars. */ - /* changed by disassembler: */ - unsigned char type; /* type of instruction, see below */ - unsigned char flags; /* additional flags */ - unsigned short sreg; /* register in load/store instructions */ - ppc_word displacement; /* branch- or load/store displacement */ - }; - -#define PPCINSTR_OTHER 0 /* no additional info for other instr. */ -#define PPCINSTR_BRANCH 1 /* branch dest. = PC+displacement */ -#define PPCINSTR_LDST 2 /* load/store instruction: displ(sreg) */ -#define PPCINSTR_IMM 3 /* 16-bit immediate val. in displacement */ - -#define PPCF_ILLEGAL (1<<0) /* illegal PowerPC instruction */ -#define PPCF_UNSIGNED (1<<1) /* unsigned immediate instruction */ -#define PPCF_SUPER (1<<2) /* supervisor level instruction */ -#define PPCF_64 (1<<3) /* 64-bit only instruction */ - - - /* ppc_disasm.o prototypes */ -#ifndef PPC_DISASM_C - extern ppc_word *PPC_Disassemble(struct DisasmPara_PPC *); -#endif - - - static const char *trap_condition[32] = { - NULL,"lgt","llt",NULL,"eq","lge","lle",NULL, - "gt",NULL,NULL,NULL,"ge",NULL,NULL,NULL, - "lt",NULL,NULL,NULL,"le",NULL,NULL,NULL, - "ne",NULL,NULL,NULL,NULL,NULL,NULL,NULL - }; - - static const char *cmpname[4] = { - "cmpw","cmpd","cmplw","cmpld" - }; - - static const char *b_ext[4] = { - "","l","a","la" - }; - - static const char *b_condition[8] = { - "ge","le","ne","ns","lt","gt","eq","so" - }; - - static const char *b_decr[16] = { - "nzf","zf",NULL,NULL,"nzt","zt",NULL,NULL, - "nz","z",NULL,NULL,"nz","z",NULL,NULL - }; - - static const char *regsel[2] = { - "","r" - }; - - static const char *oesel[2] = { - "","o" - }; - - static const char *rcsel[2] = { - "","." - }; - - static const char *ldstnames[] = { - "lwz","lwzu","lbz","lbzu","stw","stwu","stb","stbu","lhz","lhzu", - "lha","lhau","sth","sthu","lmw","stmw","lfs","lfsu","lfd","lfdu", - "stfs","stfsu","stfd","stfdu" - }; - - static const char *regnames[] = { - "r0", "sp", "rtoc", "r3", "r4", "r5", "r6", "r7", - "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", - "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", - "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31" - }; - - static const char *spr_name(int i) - { - static char def[8]; - - switch (i) - { - case 1: return "XER"; - case 8: return "LR"; - case 9: return "CTR"; - case 18: return "DSIR"; - case 19: return "DAR"; - case 22: return "DEC"; - case 25: return "SDR1"; - case 26: return "SRR0"; - case 27: return "SRR1"; - case 272: return "SPRG0"; - case 273: return "SPRG1"; - case 274: return "SPRG2"; - case 275: return "SPRG3"; - case 282: return "EAR"; - case 287: return "PVR"; - case 528: return "IBAT0U"; - case 529: return "IBAT0L"; - case 530: return "IBAT1U"; - case 531: return "IBAT1L"; - case 532: return "IBAT2U"; - case 533: return "IBAT2L"; - case 534: return "IBAT3U"; - case 535: return "IBAT3L"; - case 536: return "DBAT0U"; - case 537: return "DBAT0L"; - case 538: return "DBAT1U"; - case 539: return "DBAT1L"; - case 540: return "DBAT2U"; - case 541: return "DBAT2L"; - case 542: return "DBAT3U"; - case 543: return "DBAT3L"; - case 912: return "GQR0"; - case 913: return "GQR1"; - case 914: return "GQR2"; - case 915: return "GQR3"; - case 916: return "GQR4"; - case 917: return "GQR5"; - case 918: return "GQR6"; - case 919: return "GQR7"; - case 920: return "HID2"; - case 921: return "WPAR"; - case 922: return "DMA_U"; - case 923: return "DMA_L"; - case 924: return "ECID_U"; - case 925: return "ECID_M"; - case 926: return "ECID_L"; - case 936: return "UMMCR0"; - case 937: return "UPMC1"; - case 938: return "UPMC2"; - case 939: return "USIA"; - case 940: return "UMMCR1"; - case 941: return "UPMC3"; - case 942: return "UPMC4"; - case 943: return "USDA"; - case 952: return "MMCR0"; - case 953: return "PMC1"; - case 954: return "PMC2"; - case 955: return "SIA"; - case 956: return "MMCR1"; - case 957: return "PMC3"; - case 958: return "PMC4"; - case 959: return "SDA"; - case 1008: return "HID0"; - case 1009: return "HID1"; - case 1010: return "IABR"; - case 1011: return "HID4"; - case 1013: return "DABR"; - case 1017: return "L2CR"; - case 1019: return "ICTC"; - case 1020: return "THRM1"; - case 1021: return "THRM2"; - case 1022: return "THRM3"; - } - - sprintf(def, "%i", i); - return def; - } - - static void ierror(const char *errtxt,...) - /* display internal error and quit program */ - { - va_list vl; - - fprintf(stderr,"\nINTERNAL ERROR (PPC disassembler): "); - va_start(vl,errtxt); - vfprintf(stderr,errtxt,vl); - va_end(vl); - fprintf(stderr,".\nAborting.\n"); - exit(1); - } - - - static ppc_word swapda(ppc_word w) - { - return ((w&0xfc00ffff)|((w&PPCAMASK)<<5)|((w&PPCDMASK)>>5)); - } - - - static ppc_word swapab(ppc_word w) - { - return ((w&0xffe007ff)|((w&PPCBMASK)<<5)|((w&PPCAMASK)>>5)); - } - - - static void ill(struct DisasmPara_PPC *dp,ppc_word in) - { - if (in == 0) { - strcpy(dp->opcode, ""); - strcpy(dp->operands, "---"); - } else { - strcpy(dp->opcode, "( ill )"); - sprintf(dp->operands, "%08x", in); - } - - dp->flags |= PPCF_ILLEGAL; - } - - - static void imm(struct DisasmPara_PPC *dp,ppc_word in,int uimm,int type,int hex) - /* Generate immediate instruction operand. */ - /* type 0: D-mode, D,A,imm */ - /* type 1: S-mode, A,S,imm */ - /* type 2: S/D register is ignored (trap,cmpi) */ - /* type 3: A register is ignored (li) */ - { - int i = (int)(in & 0xffff); - - dp->type = PPCINSTR_IMM; - if (!uimm) { - if (i > 0x7fff) - i -= 0x10000; - } - else - dp->flags |= PPCF_UNSIGNED; - dp->displacement = i; - - switch (type) { - case 0: - sprintf(dp->operands,"%s, %s, %d",regnames[(int)PPCGETD(in)],regnames[(int)PPCGETA(in)],i); - break; - case 1: - if (hex) - sprintf(dp->operands,"%s, %s, 0x%.4X",regnames[(int)PPCGETA(in)],regnames[(int)PPCGETD(in)],i); - else - sprintf(dp->operands,"%s, %s, %d",regnames[(int)PPCGETA(in)],regnames[(int)PPCGETD(in)],i); - break; - case 2: - sprintf(dp->operands,"%s, %d",regnames[(int)PPCGETA(in)],i); - break; - case 3: - if (hex) - sprintf(dp->operands,"%s, 0x%.4X",regnames[(int)PPCGETD(in)],i); - else - sprintf(dp->operands,"%s, %d",regnames[(int)PPCGETD(in)],i); - break; - default: - ierror("imm(): Wrong type"); - break; - } - } - - - static void ra_rb(char *s,ppc_word in) - { - sprintf(s,"%s, %s",regnames[(int)PPCGETA(in)],regnames[(int)PPCGETB(in)]); - } - - - static char *rd_ra_rb(char *s,ppc_word in,int mask) - { - static const char *fmt = "%s, "; - - if (mask) { - if (mask & 4) - s += sprintf(s,fmt,regnames[(int)PPCGETD(in)]); - if (mask & 2) - s += sprintf(s,fmt,regnames[(int)PPCGETA(in)]); - if (mask & 1) - s += sprintf(s,fmt,regnames[(int)PPCGETB(in)]); - *--s = '\0'; - *--s = '\0'; - } - else - *s = '\0'; - return (s); - } - - - static char *fd_ra_rb(char *s,ppc_word in,int mask) - { - static const char *ffmt = "f%d,"; - static const char *rfmt = "%s,"; - - if (mask) { - if (mask & 4) - s += sprintf(s,ffmt,(int)PPCGETD(in)); - if (mask & 2) - s += sprintf(s,rfmt,regnames[(int)PPCGETA(in)]); - if (mask & 1) - s += sprintf(s,rfmt,regnames[(int)PPCGETB(in)]); - *--s = '\0'; - } - else - *s = '\0'; - return (s); - } - - - static void trapi(struct DisasmPara_PPC *dp,ppc_word in,unsigned char dmode) - { - const char *cnd; - - if ((cnd = trap_condition[PPCGETD(in)]) != NULL) { - dp->flags |= dmode; - sprintf(dp->opcode,"t%c%s",dmode?'d':'w',cnd); - imm(dp,in,0,2,0); - } - else - ill(dp,in); - } - - - static void cmpi(struct DisasmPara_PPC *dp,ppc_word in,int uimm) - { - char *oper = dp->operands; - int i = (int)PPCGETL(in); - - if (i < 2) { - if (i) - dp->flags |= PPCF_64; - sprintf(dp->opcode,"%si",cmpname[uimm*2+i]); - if ((i = (int)PPCGETCRD(in))) { - sprintf(oper,"cr%c,",'0'+i); - dp->operands += 4; - } - imm(dp,in,uimm,2,0); - dp->operands = oper; - } - else - ill(dp,in); - } - - - static void addi(struct DisasmPara_PPC *dp,ppc_word in,const char *ext) - { - if ((in&0x08000000) && !PPCGETA(in)) { - sprintf(dp->opcode,"l%s",ext); /* li, lis */ - if (!strcmp(ext, "i")) - imm(dp,in,0,3,0); - else - imm(dp,in,1,3,1); - } - else { - sprintf(dp->opcode,"%s%s",(in&0x8000)?"sub":"add",ext); - if (in & 0x8000) - in = (in^0xffff) + 1; - imm(dp,in,1,0,0); - } - } - - - static int branch(struct DisasmPara_PPC *dp,ppc_word in, const char *bname,int aform,int bdisp) - /* build a branch instr. and return number of chars written to operand */ - { - int bo = (int)PPCGETD(in); - int bi = (int)PPCGETA(in); - char y = (char)(bo & 1); - int opercnt = 0; - const char *ext = b_ext[aform*2+(int)(in&1)]; - - if (bdisp < 0) - y ^= 1; - y = y ? '+':'-'; - - if (bo & 4) { - /* standard case - no decrement */ - if (bo & 16) { - /* branch always */ - if (PPCGETIDX(in) != 16) { - sprintf(dp->opcode,"b%s%s",bname,ext); - } - else { - sprintf(dp->opcode,"bc%s",ext); - opercnt = sprintf(dp->operands,"%d, %d",bo,bi); - } - } - else { - /* branch conditional */ - sprintf(dp->opcode,"b%s%s%s%c",b_condition[((bo&8)>>1)+(bi&3)], - bname,ext,y); - if (bi >= 4) - opercnt = sprintf(dp->operands,"cr%d",bi>>2); - } - } - - else { - /* CTR is decremented and checked */ - sprintf(dp->opcode,"bd%s%s%s%c",b_decr[bo>>1],bname,ext,y); - if (!(bo & 16)) - opercnt = sprintf(dp->operands,"%d",bi); - } - - return (opercnt); - } - - - static void bc(struct DisasmPara_PPC *dp,ppc_word in) - { - unsigned int d = (int)(in & 0xfffc); - int offs; - char *oper = dp->operands; - - if (d & 0x8000) d |= 0xffff0000; - - if ((offs = branch(dp,in,"",(in&2)?1:0,d))) { - oper += offs; - *oper++ = ','; - } - if (in & 2) /* AA ? */ - sprintf(dp->operands,"->0x%.8X",(unsigned int)d); - else - sprintf(oper,"->0x%.8X",(unsigned int)(*dp->iaddr) + d); - dp->type = PPCINSTR_BRANCH; - dp->displacement = (ppc_word)d; - } - - - static void bli(struct DisasmPara_PPC *dp,ppc_word in) - { - unsigned int d = (unsigned int)(in & 0x3fffffc); - - if (d & 0x02000000) d |= 0xfc000000; - - sprintf(dp->opcode,"b%s",b_ext[in&3]); - if (in & 2) /* AA ? */ - sprintf(dp->operands,"->0x%.8X",(unsigned int)d); - else - sprintf(dp->operands,"->0x%.8X",(unsigned int)(*dp->iaddr) + d); - dp->type = PPCINSTR_BRANCH; - dp->displacement = (ppc_word)d; - } - - - static void mcrf(struct DisasmPara_PPC *dp,ppc_word in,char c) - { - if (!(in & 0x0063f801)) { - sprintf(dp->opcode,"mcrf%c",c); - sprintf(dp->operands,"cr%d, cr%d",(int)PPCGETCRD(in),(int)PPCGETCRA(in)); - } - else - ill(dp,in); - } - - - static void crop(struct DisasmPara_PPC *dp,ppc_word in,const char *n1,const char *n2) - { - int crd = (int)PPCGETD(in); - int cra = (int)PPCGETA(in); - int crb = (int)PPCGETB(in); - - if (!(in & 1)) { - sprintf(dp->opcode,"cr%s",(cra==crb && n2)?n2:n1); - if (cra == crb && n2) - sprintf(dp->operands,"%d, %d",crd,cra); - else - sprintf(dp->operands,"%d, %d, %d",crd,cra,crb); - } - else - ill(dp,in); - } - - - static void nooper(struct DisasmPara_PPC *dp,ppc_word in,const char *name, - unsigned char dmode) - { - if (in & (PPCDMASK|PPCAMASK|PPCBMASK|1)) { - ill(dp,in); - } - else { - dp->flags |= dmode; - strcpy(dp->opcode,name); - } - } - - - static unsigned int Helper_Rotate_Mask(int r, int mb, int me) - { - //first make 001111111111111 part - unsigned int begin = 0xFFFFFFFF >> mb; - //then make 000000000001111 part, which is used to flip the bits of the first one - unsigned int end = me < 31 ? (0xFFFFFFFF >> (me + 1)) : 0; - //do the bitflip - unsigned int mask = begin ^ end; - //and invert if backwards - if (me < mb) - mask = ~mask; - //rotate the mask so it can be applied to source reg - //return _rotl(mask, 32 - r); - return (mask << (32 - r)) | (mask >> r); - } - - - static void rlw(struct DisasmPara_PPC *dp,ppc_word in,const char *name,int i) - { - int s = (int)PPCGETD(in); - int a = (int)PPCGETA(in); - int bsh = (int)PPCGETB(in); - int mb = (int)PPCGETC(in); - int me = (int)PPCGETM(in); - sprintf(dp->opcode,"rlw%s%c",name,in&1?'.':'\0'); - sprintf(dp->operands,"%s, %s, %s%d, %d, %d (%08x)",regnames[a],regnames[s],regsel[i],bsh,mb,me,Helper_Rotate_Mask(bsh, mb, me)); - } - - - static void ori(struct DisasmPara_PPC *dp,ppc_word in,const char *name) - { - strcpy(dp->opcode,name); - imm(dp,in,1,1,1); - } - - - static void rld(struct DisasmPara_PPC *dp,ppc_word in,const char *name,int i) - { - int s = (int)PPCGETD(in); - int a = (int)PPCGETA(in); - int bsh = i ? (int)PPCGETB(in) : (int)(((in&2)<<4)+PPCGETB(in)); - int m = (int)(in&0x7e0)>>5; - - dp->flags |= PPCF_64; - sprintf(dp->opcode,"rld%s%c",name,in&1?'.':'\0'); - sprintf(dp->operands,"%s, %s, %s%d, %d",regnames[a],regnames[s],regsel[i],bsh,m); - } - - - static void cmp(struct DisasmPara_PPC *dp,ppc_word in) - { - char *oper = dp->operands; - int i = (int)PPCGETL(in); - - if (i < 2) { - if (i) - dp->flags |= PPCF_64; - strcpy(dp->opcode,cmpname[((in&PPCIDX2MASK)?2:0)+i]); - if ((i = (int)PPCGETCRD(in))) - oper += sprintf(oper,"cr%c,",'0'+i); - ra_rb(oper,in); - } - else - ill(dp,in); - } - - - static void trap(struct DisasmPara_PPC *dp,ppc_word in,unsigned char dmode) - { - const char *cnd; - int to = (int)PPCGETD(in); - - if ((cnd = trap_condition[to])) { - dp->flags |= dmode; - sprintf(dp->opcode,"t%c%s",dmode?'d':'w',cnd); - ra_rb(dp->operands,in); - } - else { - if (to == 31) { - if (dmode) { - dp->flags |= dmode; - strcpy(dp->opcode,"td"); - strcpy(dp->operands,"31,0,0"); - } - else - strcpy(dp->opcode,"trap"); - } - else - ill(dp,in); - } - } - - - static void dab(struct DisasmPara_PPC *dp,ppc_word in,const char *name,int mask, - int smode,int chkoe,int chkrc,unsigned char dmode) - /* standard instruction: xxxx rD,rA,rB */ - { - if (chkrc>=0 && ((in&1)!=(unsigned)chkrc)) { - ill(dp,in); - } - else { - dp->flags |= dmode; - if (smode) - in = swapda(in); /* rA,rS,rB */ - sprintf(dp->opcode,"%s%s%s",name, - oesel[chkoe&&(in&PPCOE)],rcsel[(chkrc<0)&&(in&1)]); - rd_ra_rb(dp->operands,in,mask); - } - } - - - static void rrn(struct DisasmPara_PPC *dp,ppc_word in,const char *name, - int smode,int chkoe,int chkrc,unsigned char dmode) - /* Last operand is no register: xxxx rD,rA,NB */ - { - char *s; - - if (chkrc>=0 && ((in&1)!=(unsigned)chkrc)) { - ill(dp,in); - } - else { - dp->flags |= dmode; - if (smode) - in = swapda(in); /* rA,rS,NB */ - sprintf(dp->opcode,"%s%s%s",name, - oesel[chkoe&&(in&PPCOE)],rcsel[(chkrc<0)&&(in&1)]); - s = rd_ra_rb(dp->operands,in,6); - sprintf(s,",%d",(int)PPCGETB(in)); - } - } - - - static void mtcr(struct DisasmPara_PPC *dp,ppc_word in) - { - int s = (int)PPCGETD(in); - int crm = (int)(in&0x000ff000)>>12; - char *oper = dp->operands; - - if (in & 0x00100801) { - ill(dp,in); - } - else { - sprintf(dp->opcode,"mtcr%c",crm==0xff?'\0':'f'); - if (crm != 0xff) - oper += sprintf(oper,"0x%02x,",crm); - sprintf(oper,"%s",regnames[s]); - } - } - - - static void msr(struct DisasmPara_PPC *dp,ppc_word in,int smode) - { - int s = (int)PPCGETD(in); - int sr = (int)(in&0x000f0000)>>16; - - if (in & 0x0010f801) { - ill(dp,in); - } - else { - dp->flags |= PPCF_SUPER; - sprintf(dp->opcode,"m%csr",smode?'t':'f'); - if (smode) - sprintf(dp->operands,"%d, %s",sr,regnames[s]); - else - sprintf(dp->operands,"%s, %d",regnames[s],sr); - } - } - - - static void mspr(struct DisasmPara_PPC *dp,ppc_word in,int smode) - { - int d = (int)PPCGETD(in); - int spr = (int)((PPCGETB(in)<<5)+PPCGETA(in)); - int fmt = 0; - const char *x; - - if (in & 1) { - ill(dp,in); - } - - else { - if (spr!=1 && spr!=8 && spr!=9) - dp->flags |= PPCF_SUPER; - switch (spr) { - case 1: - x = "xer"; - break; - case 8: - x = "lr"; - break; - case 9: - x = "ctr"; - break; - default: - x = "spr"; - fmt = 1; - break; - } - - sprintf(dp->opcode,"m%c%s",smode?'t':'f',x); - if (fmt) { - if (smode) - sprintf(dp->operands,"%s, %s",spr_name(spr),regnames[d]); - else - sprintf(dp->operands,"%s, %s",regnames[d],spr_name(spr)); - } - else - sprintf(dp->operands,"%s",regnames[d]); - } - } - - - static void mtb(struct DisasmPara_PPC *dp,ppc_word in) - { - int d = (int)PPCGETD(in); - int tbr = (int)((PPCGETB(in)<<5)+PPCGETA(in)); - char *s = dp->operands; - char x; - - if (in & 1) { - ill(dp,in); - } - - else { - s += sprintf(s,"%s",regnames[d]); - switch (tbr) { - case 268: - x = 'l'; - break; - case 269: - x = 'u'; - break; - default: - x = '\0'; - dp->flags |= PPCF_SUPER; - sprintf(s,",%d",tbr); - break; - } - sprintf(dp->opcode,"mftb%c",x); - } - } - - - static void sradi(struct DisasmPara_PPC *dp,ppc_word in) - { - int s = (int)PPCGETD(in); - int a = (int)PPCGETA(in); - int bsh = (int)(((in&2)<<4)+PPCGETB(in)); - - dp->flags |= PPCF_64; - sprintf(dp->opcode,"sradi%c",in&1?'.':'\0'); - sprintf(dp->operands,"%s, %s, %d",regnames[a],regnames[s],bsh); - } - - static const char *ldst_offs(unsigned int val) - { - static char buf[8]; - - if (val == 0) - { - return "0"; - } - else - { - if (val & 0x8000) - { - sprintf(buf, "-0x%.4X", ((~val) & 0xffff) + 1); - } - else - { - sprintf(buf, "0x%.4X", val); - } - - return buf; - } - } - - static void ldst(struct DisasmPara_PPC *dp,ppc_word in,const char *name, - char reg,unsigned char dmode) - { - int s = (int)PPCGETD(in); - int a = (int)PPCGETA(in); - int d = (ppc_word)(in & 0xffff); - - dp->type = PPCINSTR_LDST; - dp->flags |= dmode; - dp->sreg = (short)a; - // if (d >= 0x8000) - // d -= 0x10000; - dp->displacement = (ppc_word)d; - strcpy(dp->opcode,name); - if (reg == 'r') - { - sprintf(dp->operands,"%s, %s (%s)", regnames[s], ldst_offs(d), regnames[a]); - } - else - { - sprintf(dp->operands,"%c%d, %s (%s)",reg,s, ldst_offs(d), regnames[a]); - } - } - - - static void fdabc(struct DisasmPara_PPC *dp,ppc_word in, const char *name, - int mask,unsigned char dmode) - /* standard floating point instruction: xxxx fD,fA,fC,fB */ - { - static const char *fmt = "f%d,"; - char *s = dp->operands; - int err = 0; - - dp->flags |= dmode; - sprintf(dp->opcode,"f%s%s",name,rcsel[in&1]); - s += sprintf(s,fmt,(int)PPCGETD(in)); - if (mask & 4) - s += sprintf(s,fmt,(int)PPCGETA(in)); - else - err |= (int)PPCGETA(in); - if (mask & 2) - s += sprintf(s,fmt,(int)PPCGETC(in)); - else if (PPCGETC(in)) - err |= (int)PPCGETC(in); - if (mask & 1) - s += sprintf(s,fmt,(int)PPCGETB(in)); - else if (!(mask&8)) - err |= (int)PPCGETB(in); - *(s-1) = '\0'; - if (err) - ill(dp,in); - } - - static void fmr(struct DisasmPara_PPC *dp,ppc_word in) - { - sprintf(dp->opcode, "fmr%s", rcsel[in&1]); - sprintf(dp->operands, "f%d, f%d", (int)PPCGETD(in), (int)PPCGETB(in)); - } - - static void fdab(struct DisasmPara_PPC *dp,ppc_word in,const char *name,int mask) - /* indexed float instruction: xxxx fD,rA,rB */ - { - strcpy(dp->opcode,name); - fd_ra_rb(dp->operands,in,mask); - } - - - static void fcmp(struct DisasmPara_PPC *dp,ppc_word in,char c) - { - if (in & 0x00600001) { - ill(dp,in); - } - else { - sprintf(dp->opcode,"fcmp%c",c); - sprintf(dp->operands,"cr%d,f%d,f%d",(int)PPCGETCRD(in), - (int)PPCGETA(in),(int)PPCGETB(in)); - } - } - - - static void mtfsb(struct DisasmPara_PPC *dp,ppc_word in,int n) - { - if (in & (PPCAMASK|PPCBMASK)) { - ill(dp,in); - } - else { - sprintf(dp->opcode,"mtfsb%d%s",n,rcsel[in&1]); - sprintf(dp->operands,"%d",(int)PPCGETD(in)); - } - } - - - ////////////////////////////////////////////////////////////////////////////////// - //PAIRED - ////////////////////////////////////////////////////////////////////////////////// - - /* - sprintf(buf, "psq_lx", FD); - sprintf(buf, "psq_stx", FD); - sprintf(buf, "psq_lux", FD); - sprintf(buf, "psq_stux", FD); - */ -#define RA ((inst >> 16) & 0x1f) -#define RB ((inst >> 11) & 0x1f) -#define RC ((inst >> 6) & 0x1f) -#define RD ((inst >> 21) & 0x1f) -#define RS ((inst >> 21) & 0x1f) -#define FA ((inst >> 16) & 0x1f) -#define FB ((inst >> 11) & 0x1f) -#define FC ((inst >> 6) & 0x1f) -#define FD ((inst >> 21) & 0x1f) -#define FS ((inst >> 21) & 0x1f) -#define IMM (inst & 0xffff) -#define UIMM (inst & 0xffff) -#define OFS (inst & 0xffff) -#define OPCD ((inst >> 26) & 0x3f) -#define XO_10 ((inst >> 1) & 0x3ff) -#define XO_9 ((inst >> 1) & 0x1ff) -#define XO_5 ((inst >> 1) & 0x1f) -#define Rc (inst & 1) -#define SH ((inst >> 11) & 0x1f) -#define MB ((inst >> 6) & 0x1f) -#define ME ((inst >> 1) & 0x1f) -#define OE ((inst >> 10) & 1) -#define TO ((inst >> 21) & 0x1f) -#define CRFD ((inst >> 23) & 0x7) -#define CRFS ((inst >> 18) & 0x7) -#define CRBD ((inst >> 21) & 0x1f) -#define CRBA ((inst >> 16) & 0x1f) -#define CRBB ((inst >> 11) & 0x1f) -#define L ((inst >> 21) & 1) -#define NB ((inst >> 11) & 0x1f) -#define AA ((inst >> 1) & 1) -#define LK (inst & 1) -#define LI ((inst >> 2) & 0xffffff) -#define BO ((inst >> 21) & 0x1f) -#define BI ((inst >> 16) & 0x1f) -#define BD ((inst >> 2) & 0x3fff) - -#define MTFSFI_IMM ((inst >> 12) & 0xf) -#define FM ((inst >> 17) & 0xff) -#define SR ((inst >> 16) & 0xf) -#define SPR ((inst >> 11) & 0x3ff) -#define TBR ((inst >> 11) & 0x3ff) -#define CRM ((inst >> 12) & 0xff) - - inline int SEX12(unsigned int x) - { - return x & 0x800 ? (x|0xFFFFF000) : x; - } - - static void ps(struct DisasmPara_PPC *dp,ppc_word inst) - { - char *op = dp->opcode; - char *pr = dp->operands; - switch ((inst>>1)&0x1F) - { - case 6: - strcpy(op, "ps_lux"); - sprintf(pr, "p%u, (r%u + r%u)", FD, RA, RB); - return; - - case 18: - strcpy(op, "ps_div"); - sprintf(pr, "p%u, p%u/p%u", FD, FA, FB); - return; - case 20: - strcpy(op, "ps_sub"); - sprintf(pr, "p%u, p%u-p%u", FD, FA, FB); - return; - case 21: - strcpy(op, "ps_add"); - sprintf(pr, "p%u, p%u+p%u", FD, FA, FB); - return; - case 23: - strcpy(op, "ps_sel"); - sprintf(pr, "p%u>=0?p%u:p%u", FD, FA, FC); - return; - case 24: - strcpy(op, "ps_res"); - sprintf(pr, "p%u, (1/p%u)", FD, FB); - return; - - case 25: - strcpy(op, "ps_mul"); - sprintf(pr, "p%u, p%u*p%u", FD, FA, FC); - return; - - case 26: //rsqrte - strcpy(op, "ps_rsqrte"); - sprintf(pr, "p%u, p%u", FD, FB); - return; - case 28: //msub - strcpy(op, "ps_msub"); - sprintf(pr, "p%u, p%u*p%u-p%u", FD, FA, FC, FB); - return; - case 29: //madd - strcpy(op, "ps_madd"); - sprintf(pr, "p%u, p%u*p%u+p%u", FD, FA, FC, FB); - return; - case 30: //nmsub - strcpy(op, "ps_nmsub"); - sprintf(pr, "p%u, -(p%u*p%u-p%u)", FD, FA, FC, FB); - return; - case 31: //nmadd - strcpy(op, "ps_nmadd"); - sprintf(pr, "p%u, -(p%u*p%u+p%u)", FD, FA, FC, FB); - return; - case 10: - strcpy(op, "ps_sum0"); - sprintf(pr, "p%u, 0=p%u+p%u, 1=p%u", FD, FA, FB, FC); - return; - case 11: - strcpy(op, "ps_sum1"); - sprintf(pr, "p%u, 0=p%u, 1=p%u+p%u", FD, FC, FA, FB); - return; - case 12: - strcpy(op, "ps_muls0"); - sprintf(pr, "p%u, p%u*p%u[0]", FD, FA, FC); - return; - case 13: - strcpy(op, "ps_muls1"); - sprintf(pr, "p%u, p%u*p%u[1]", FD, FA, FC); - return; - case 14: - strcpy(op, "ps_madds0"); - sprintf(pr, "p%u, p%u*p%u[0]+p%u", FD, FA, FC, FB); - return; - case 15: - strcpy(op, "ps_madds1"); - sprintf(pr, "p%u, p%u*p%u[1]+p%u", FD, FA, FC, FB); - return; - } - - switch ((inst>>1)&0x3FF) - { - //10-bit suckers (?) - case 40: //nmadd - strcpy(op, "ps_neg"); - sprintf(pr, "p%u, -p%u", FD, FB); - return; - case 72: //nmadd - strcpy(op, "ps_mr"); - sprintf(pr, "p%u, p%u", FD, FB); - return; - case 136: - strcpy(op, "ps_nabs"); - sprintf(pr, "p%u, -|p%u|", FD, FB); - return; - case 264: - strcpy(op, "ps_abs"); - sprintf(pr, "p%u, |p%u|", FD, FB); - return; - case 0: - strcpy(op, "ps_cmpu0"); - sprintf(pr, "ps_cmpu0"); - return; - case 32: - strcpy(op,"ps_cmpq0"); - sprintf(pr, "ps_cmpo0"); - return; - case 64: - strcpy(op,"ps_cmpu1"); - sprintf(pr, "ps_cmpu1"); - return; - case 96: - strcpy(op,"ps_cmpo1"); - sprintf(pr, "ps_cmpo1"); - return; - case 528: - strcpy(op,"ps_merge00"); - sprintf(pr, "p%u, p%u[0],p%u[0]", FD, FA, FB); - return; - case 560: - strcpy(op,"ps_merge01"); - sprintf(pr, "p%u, p%u[0],p%u[1]", FD, FA, FB); - return; - case 592: - strcpy(op,"ps_merge10"); - sprintf(pr, "p%u, p%u[1],p%u[0]", FD, FA, FB); - return; - case 624: - strcpy(op,"ps_merge11"); - sprintf(pr, "p%u, p%u[1],p%u[1]", FD, FA, FB); - return; - case 1014: - strcpy(op,"dcbz_l"); - *pr = '\0'; - return; - } - - // default: - sprintf(op, "ps_%i",((inst>>1)&0x1f)); - strcpy(pr,"---"); - return; - } - - static void ps_mem(struct DisasmPara_PPC *dp,ppc_word inst) - { - char *op = dp->opcode; - char *pr = dp->operands; - switch (PPCGETIDX(inst)) - { - case 56: - strcpy(op,"psq_l"); - sprintf(pr, "p%u, %i(r%u)", RS, SEX12(inst&0xFFF), RA); - break; - case 57: - strcpy(op,"psq_lu"); - *pr = '\0'; - break; - case 60: - strcpy(op,"psq_st"); - sprintf(pr, "%i(r%u), p%u", SEX12(inst&0xFFF), RA, RS); - break; - case 61: - strcpy(op,"psq_stu"); - sprintf(pr, "r%u, p%u ?", RA, RS); - break; - } - } - - - ppc_word *PPC_Disassemble(struct DisasmPara_PPC *dp) - /* Disassemble PPC instruction and return a pointer to the next */ - /* instruction, or NULL if an error occured. */ - { - ppc_word in = *(dp->instr); - if (!dp->opcode || !dp->operands) - return NULL; /* no buffers */ - - #if LITTLEENDIAN - in = (in & 0xff)<<24 | (in & 0xff00)<<8 | (in & 0xff0000)>>8 | - (in & 0xff000000)>>24; - #endif - dp->type = PPCINSTR_OTHER; - dp->flags = 0; - *(dp->operands) = 0; - - switch (PPCGETIDX(in)) - { - case 0: - { - int block = in & 0x3FFFFFF; - if (block) { - sprintf(dp->opcode, "JITblock"); - sprintf(dp->operands, "%i", block); - } else { - strcpy(dp->opcode, ""); - strcpy(dp->operands, "---"); - } - } - break; - case 1: - sprintf(dp->opcode,"HLE"); - //HLE call - break; - case 2: - trapi(dp,in,PPCF_64); /* tdi */ - break; - - case 3: - trapi(dp,in,0); /* twi */ - break; - case 4: - ps(dp,in); - break; - case 56: - case 57: - case 60: - case 61: - ps_mem(dp,in); - break; - - - case 7: - strcpy(dp->opcode,"mulli"); - imm(dp,in,0,0,0); - break; - - case 8: - strcpy(dp->opcode,"subfic"); - imm(dp,in,0,0,0); - break; - - case 10: - cmpi(dp,in,1); /* cmpli */ - break; - - case 11: - cmpi(dp,in,0); /* cmpi */ - break; - - case 12: - addi(dp,in,"ic"); /* addic */ - break; - - case 13: - addi(dp,in,"ic."); /* addic. */ - break; - - case 14: - addi(dp,in,"i"); /* addi */ - break; - - case 15: - addi(dp,in,"is"); /* addis */ - break; - - case 16: - bc(dp,in); - break; - - case 17: - if ((in & ~PPCIDXMASK) == 2) - strcpy(dp->opcode,"sc"); - else - ill(dp,in); - break; - - case 18: - bli(dp,in); - break; - - case 19: - switch (PPCGETIDX2(in)) { - case 0: - mcrf(dp,in,'\0'); /* mcrf */ - break; - - case 16: - branch(dp,in,"lr",0,0); /* bclr */ - break; - - case 33: - crop(dp,in,"nor","not"); /* crnor */ - break; - - case 50: - nooper(dp,in,"rfi",PPCF_SUPER); - break; - - case 129: - crop(dp,in,"andc",NULL); /* crandc */ - break; - - case 150: - nooper(dp,in,"isync",0); - break; - - case 193: - crop(dp,in,"xor","clr"); /* crxor */ - break; - - case 225: - crop(dp,in,"nand",NULL); /* crnand */ - break; - - case 257: - crop(dp,in,"and",NULL); /* crand */ - break; - - case 289: - crop(dp,in,"eqv","set"); /* creqv */ - break; - - case 417: - crop(dp,in,"orc",NULL); /* crorc */ - break; - - case 449: - crop(dp,in,"or","move"); /* cror */ - break; - - case 528: - branch(dp,in,"ctr",0,0); /* bcctr */ - break; - - default: - ill(dp,in); - break; - } - break; - - case 20: - rlw(dp,in,"imi",0); /* rlwimi */ - break; - - case 21: - rlw(dp,in,"inm",0); /* rlwinm */ - break; - - case 23: - rlw(dp,in,"nm",1); /* rlwnm */ - break; - - case 24: - if (in & ~PPCIDXMASK) - ori(dp,in,"ori"); - else - strcpy(dp->opcode,"nop"); - break; - - case 25: - ori(dp,in,"oris"); - break; - - case 26: - ori(dp,in,"xori"); - break; - - case 27: - ori(dp,in,"xoris"); - break; - - case 28: - ori(dp,in,"andi."); - break; - - case 29: - ori(dp,in,"andis."); - break; - - case 30: - switch (in & 0x1c) { - case 0: - rld(dp,in,"icl",0); /* rldicl */ - break; - case 1: - rld(dp,in,"icr",0); /* rldicr */ - break; - case 2: - rld(dp,in,"ic",0); /* rldic */ - break; - case 3: - rld(dp,in,"imi",0); /* rldimi */ - break; - case 4: - rld(dp,in,in&2?"cl":"cr",1); /* rldcl, rldcr */ - break; - default: - ill(dp,in); - break; - } - break; - - case 31: - switch (PPCGETIDX2(in)) { - case 0: - case 32: - if (in & 1) - ill(dp,in); - else - cmp(dp,in); /* cmp, cmpl */ - break; - - case 4: - if (in & 1) - ill(dp,in); - else - trap(dp,in,0); /* tw */ - break; - - case 8: - case (PPCOE>>1)+8: - dab(dp,swapab(in),"subc",7,0,1,-1,0); - break; - - case 9: - dab(dp,in,"mulhdu",7,0,0,-1,PPCF_64); - break; - - case 10: - case (PPCOE>>1)+10: - dab(dp,in,"addc",7,0,1,-1,0); - break; - - case 11: - dab(dp,in,"mulhwu",7,0,0,-1,0); - break; - - case 19: - if (in & (PPCAMASK|PPCBMASK)) - ill(dp,in); - else - dab(dp,in,"mfcr",4,0,0,0,0); - break; - - case 20: - dab(dp,in,"lwarx",7,0,0,0,0); - break; - - case 21: - dab(dp,in,"ldx",7,0,0,0,PPCF_64); - break; - - case 23: - dab(dp,in,"lwzx",7,0,0,0,0); - break; - - case 24: - dab(dp,in,"slw",7,1,0,-1,0); - break; - - case 26: - if (in & PPCBMASK) - ill(dp,in); - else - dab(dp,in,"cntlzw",6,1,0,-1,0); - break; - - case 27: - dab(dp,in,"sld",7,1,0,-1,PPCF_64); - break; - - case 28: - dab(dp,in,"and",7,1,0,-1,0); - break; - - case 40: - case (PPCOE>>1)+40: - dab(dp,swapab(in),"sub",7,0,1,-1,0); - break; - - case 53: - dab(dp,in,"ldux",7,0,0,0,PPCF_64); - break; - - case 54: - if (in & PPCDMASK) - ill(dp,in); - else - dab(dp,in,"dcbst",3,0,0,0,0); - break; - - case 55: - dab(dp,in,"lwzux",7,0,0,0,0); - break; - - case 58: - if (in & PPCBMASK) - ill(dp,in); - else - dab(dp,in,"cntlzd",6,1,0,-1,PPCF_64); - break; - - case 60: - dab(dp,in,"andc",7,1,0,-1,0); - break; - - case 68: - trap(dp,in,PPCF_64); /* td */ - break; - - case 73: - dab(dp,in,"mulhd",7,0,0,-1,PPCF_64); - break; - - case 75: - dab(dp,in,"mulhw",7,0,0,-1,0); - break; - - case 83: - if (in & (PPCAMASK|PPCBMASK)) - ill(dp,in); - else - dab(dp,in,"mfmsr",4,0,0,0,PPCF_SUPER); - break; - - case 84: - dab(dp,in,"ldarx",7,0,0,0,PPCF_64); - break; - - case 86: - if (in & PPCDMASK) - ill(dp,in); - else - dab(dp,in,"dcbf",3,0,0,0,0); - break; - - case 87: - dab(dp,in,"lbzx",7,0,0,0,0); - break; - - case 104: - case (PPCOE>>1)+104: - if (in & PPCBMASK) - ill(dp,in); - else - dab(dp,in,"neg",6,0,1,-1,0); - break; - - case 119: - dab(dp,in,"lbzux",7,0,0,0,0); - break; - - case 124: - if (PPCGETD(in) == PPCGETB(in)) - dab(dp,in,"not",6,1,0,-1,0); - else - dab(dp,in,"nor",7,1,0,-1,0); - break; - - case 136: - case (PPCOE>>1)+136: - dab(dp,in,"subfe",7,0,1,-1,0); - break; - - case 138: - case (PPCOE>>1)+138: - dab(dp,in,"adde",7,0,1,-1,0); - break; - - case 144: - mtcr(dp,in); - break; - - case 146: - if (in & (PPCAMASK|PPCBMASK)) - ill(dp,in); - else - dab(dp,in,"mtmsr",4,0,0,0,PPCF_SUPER); - break; - - case 149: - dab(dp,in,"stdx",7,0,0,0,PPCF_64); - break; - - case 150: - dab(dp,in,"stwcx.",7,0,0,1,0); - break; - - case 151: - dab(dp,in,"stwx",7,0,0,0,0); - break; - - case 181: - dab(dp,in,"stdux",7,0,0,0,PPCF_64); - break; - - case 183: - dab(dp,in,"stwux",7,0,0,0,0); - break; - - case 200: - case (PPCOE>>1)+200: - if (in & PPCBMASK) - ill(dp,in); - else - dab(dp,in,"subfze",6,0,1,-1,0); - break; - - case 202: - case (PPCOE>>1)+202: - if (in & PPCBMASK) - ill(dp,in); - else - dab(dp,in,"addze",6,0,1,-1,0); - break; - - case 210: - msr(dp,in,1); /* mfsr */ - break; - - case 214: - dab(dp,in,"stdcx.",7,0,0,1,PPCF_64); - break; - - case 215: - dab(dp,in,"stbx",7,0,0,0,0); - break; - - case 232: - case (PPCOE>>1)+232: - if (in & PPCBMASK) - ill(dp,in); - else - dab(dp,in,"subfme",6,0,1,-1,0); - break; - - case 233: - case (PPCOE>>1)+233: - dab(dp,in,"mulld",7,0,1,-1,PPCF_64); - break; - - case 234: - case (PPCOE>>1)+234: - if (in & PPCBMASK) - ill(dp,in); - else - dab(dp,in,"addme",6,0,1,-1,0); - break; - - case 235: - case (PPCOE>>1)+235: - dab(dp,in,"mullw",7,0,1,-1,0); - break; - - case 242: - if (in & PPCAMASK) - ill(dp,in); - else - dab(dp,in,"mtsrin",5,0,0,0,PPCF_SUPER); - break; - - case 246: - if (in & PPCDMASK) - ill(dp,in); - else - dab(dp,in,"dcbtst",3,0,0,0,0); - break; - - case 247: - dab(dp,in,"stbux",7,0,0,0,0); - break; - - case 266: - case (PPCOE>>1)+266: - dab(dp,in,"add",7,0,1,-1,0); - break; - - case 278: - if (in & PPCDMASK) - ill(dp,in); - else - dab(dp,in,"dcbt",3,0,0,0,0); - break; - - case 279: - dab(dp,in,"lhzx",7,0,0,0,0); - break; - - case 284: - dab(dp,in,"eqv",7,1,0,-1,0); - break; - - case 306: - if (in & (PPCDMASK|PPCAMASK)) - ill(dp,in); - else - dab(dp,in,"tlbie",1,0,0,0,PPCF_SUPER); - break; - - case 310: - dab(dp,in,"eciwx",7,0,0,0,0); - break; - - case 311: - dab(dp,in,"lhzux",7,0,0,0,0); - break; - - case 316: - dab(dp,in,"xor",7,1,0,-1,0); - break; - - case 339: - mspr(dp,in,0); /* mfspr */ - break; - - case 341: - dab(dp,in,"lwax",7,0,0,0,PPCF_64); - break; - - case 343: - dab(dp,in,"lhax",7,0,0,0,0); - break; - - case 370: - nooper(dp,in,"tlbia",PPCF_SUPER); - break; - - case 371: - mtb(dp,in); /* mftb */ - break; - - case 373: - dab(dp,in,"lwaux",7,0,0,0,PPCF_64); - break; - - case 375: - dab(dp,in,"lhaux",7,0,0,0,0); - break; - - case 407: - dab(dp,in,"sthx",7,0,0,0,0); - break; - - case 412: - dab(dp,in,"orc",7,1,0,-1,0); - break; - - case 413: - sradi(dp,in); /* sradi */ - break; - - case 434: - if (in & (PPCDMASK|PPCAMASK)) - ill(dp,in); - else - dab(dp,in,"slbie",1,0,0,0,PPCF_SUPER|PPCF_64); - break; - - case 438: - dab(dp,in,"ecowx",7,0,0,0,0); - break; - - case 439: - dab(dp,in,"sthux",7,0,0,0,0); - break; - - case 444: - if (PPCGETD(in) == PPCGETB(in)) - dab(dp,in,"mr",6,1,0,-1,0); - else - dab(dp,in,"or",7,1,0,-1,0); - break; - - case 457: - case (PPCOE>>1)+457: - dab(dp,in,"divdu",7,0,1,-1,PPCF_64); - break; - - case 459: - case (PPCOE>>1)+459: - dab(dp,in,"divwu",7,0,1,-1,0); - break; - - case 467: - mspr(dp,in,1); /* mtspr */ - break; - - case 470: - if (in & PPCDMASK) - ill(dp,in); - else - dab(dp,in,"dcbi",3,0,0,0,0); - break; - - case 476: - dab(dp,in,"nand",7,1,0,-1,0); - break; - - case 489: - case (PPCOE>>1)+489: - dab(dp,in,"divd",7,0,1,-1,PPCF_64); - break; - - case 491: - case (PPCOE>>1)+491: - dab(dp,in,"divw",7,0,1,-1,0); - break; - - case 498: - nooper(dp,in,"slbia",PPCF_SUPER|PPCF_64); - break; - - case 512: - if (in & 0x007ff801) - ill(dp,in); - else { - strcpy(dp->opcode,"mcrxr"); - sprintf(dp->operands,"cr%d",(int)PPCGETCRD(in)); - } - break; - - case 533: - dab(dp,in,"lswx",7,0,0,0,0); - break; - - case 534: - dab(dp,in,"lwbrx",7,0,0,0,0); - break; - - case 535: - fdab(dp,in,"lfsx",7); - break; - - case 536: - dab(dp,in,"srw",7,1,0,-1,0); - break; - - case 539: - dab(dp,in,"srd",7,1,0,-1,PPCF_64); - break; - - case 566: - nooper(dp,in,"tlbsync",PPCF_SUPER); - break; - - case 567: - fdab(dp,in,"lfsux",7); - break; - - case 595: - msr(dp,in,0); /* mfsr */ - break; - - case 597: - rrn(dp,in,"lswi",0,0,0,0); - break; - - case 598: - nooper(dp,in,"sync",PPCF_SUPER); - break; - - case 599: - fdab(dp,in,"lfdx",7); - break; - - case 631: - fdab(dp,in,"lfdux",7); - break; - - case 659: - if (in & PPCAMASK) - ill(dp,in); - else - dab(dp,in,"mfsrin",5,0,0,0,PPCF_SUPER); - break; - - case 661: - dab(dp,in,"stswx",7,0,0,0,0); - break; - - case 662: - dab(dp,in,"stwbrx",7,0,0,0,0); - break; - - case 663: - fdab(dp,in,"stfsx",7); - break; - - case 695: - fdab(dp,in,"stfsux",7); - break; - - case 725: - rrn(dp,in,"stswi",0,0,0,0); - break; - - case 727: - fdab(dp,in,"stfdx",7); - break; - - case 759: - fdab(dp,in,"stfdux",7); - break; - - case 790: - dab(dp,in,"lhbrx",7,0,0,0,0); - break; - - case 792: - dab(dp,in,"sraw",7,1,0,-1,0); - break; - - case 794: - dab(dp,in,"srad",7,1,0,-1,PPCF_64); - break; - - case 824: - rrn(dp,in,"srawi",1,0,-1,0); - break; - - case 854: - nooper(dp,in,"eieio",PPCF_SUPER); - break; - - case 918: - dab(dp,in,"sthbrx",7,0,0,0,0); - break; - - case 922: - if (in & PPCBMASK) - ill(dp,in); - else - dab(dp,in,"extsh",6,1,0,-1,0); - break; - - case 954: - if (in & PPCBMASK) - ill(dp,in); - else - dab(dp,in,"extsb",6,1,0,-1,0); - break; - - case 982: - if (in & PPCDMASK) - ill(dp,in); - else - dab(dp,in,"icbi",3,0,0,0,0); - break; - - case 983: - fdab(dp,in,"stfiwx",7); - break; - - case 986: - if (in & PPCBMASK) - ill(dp,in); - else - dab(dp,in,"extsw",6,1,0,-1,PPCF_64); - break; - - case 1014: - if (in & PPCDMASK) - ill(dp,in); - else - dab(dp,in,"dcbz",3,0,0,0,0); - break; - - default: - ill(dp,in); - break; - } - break; - - case 32: - case 33: - case 34: - case 35: - case 36: - case 37: - case 38: - case 39: - case 40: - case 41: - case 42: - case 43: - case 44: - case 45: - case 46: - case 47: - ldst(dp,in,ldstnames[PPCGETIDX(in)-32],'r',0); - break; - - case 48: - case 49: - case 50: - case 51: - case 52: - case 53: - case 54: - case 55: - ldst(dp,in,ldstnames[PPCGETIDX(in)-32],'f',0); - break; - - case 58: - switch (in & 3) { - case 0: - ldst(dp,in&~3,"ld",'r',PPCF_64); - break; - case 1: - ldst(dp,in&~3,"ldu",'r',PPCF_64); - break; - case 2: - ldst(dp,in&~3,"lwa",'r',PPCF_64); - break; - default: - ill(dp,in); - break; - } - break; - - case 59: - switch (in & 0x3e) { - case 36: - fdabc(dp,in,"divs",5,0); - break; - - case 40: - fdabc(dp,in,"subs",5,0); - break; - - case 42: - fdabc(dp,in,"adds",5,0); - break; - - case 44: - fdabc(dp,in,"sqrts",2,0); - break; - - case 48: - fdabc(dp,in,"res",2,0); - break; - - case 50: - fdabc(dp,in,"muls",6,0); - break; - - case 56: - fdabc(dp,in,"msubs",7,0); - break; - - case 58: - fdabc(dp,in,"madds",7,0); - break; - - case 60: - fdabc(dp,in,"nmsubs",7,0); - break; - - case 62: - fdabc(dp,in,"nmadds",7,0); - break; - - default: - ill(dp,in); - break; - } - break; - - case 62: - switch (in & 3) { - case 0: - ldst(dp,in&~3,"std",'r',PPCF_64); - break; - case 1: - ldst(dp,in&~3,"stdu",'r',PPCF_64); - break; - default: - ill(dp,in); - break; - } - break; - - case 63: - if (in & 32) { - switch (in & 0x1e) { - case 4: - fdabc(dp,in,"div",5,0); - break; - - case 8: - fdabc(dp,in,"sub",5,0); - break; - - case 10: - fdabc(dp,in,"add",5,0); - break; - - case 12: - fdabc(dp,in,"sqrt",2,0); - break; - - case 14: - fdabc(dp,in,"sel",7,0); - break; - - case 18: - fdabc(dp,in,"mul",6,0); - break; - - case 20: - fdabc(dp,in,"rsqrte",1,0); - break; - - case 24: - fdabc(dp,in,"msub",7,0); - break; - - case 26: - fdabc(dp,in,"madd",7,0); - break; - - case 28: - fdabc(dp,in,"nmsub",7,0); - break; - - case 30: - fdabc(dp,in,"nmadd",7,0); - break; - - case 52: - sprintf(dp->opcode, "XXX dp 52"); - break; - - default: - ill(dp,in); - break; - } - } - else { - switch (PPCGETIDX2(in)) { - case 0: - fcmp(dp,in,'u'); - break; - - case 12: - fdabc(dp,in,"rsp",1,0); // 10 - break; - - case 14: - fdabc(dp,in,"ctiw",1,0); // 10 - break; - - case 15: - fdabc(dp,in,"ctiwz",1,0); // 10 - break; - - case 32: - fcmp(dp,in,'o'); - break; - - case 38: - mtfsb(dp,in,1); - break; - - case 40: - fdabc(dp,in,"neg",10,0); - break; - - case 64: - mcrf(dp,in,'s'); /* mcrfs */ - break; - - case 70: - mtfsb(dp,in,0); - break; - - case 72: - fmr(dp,in); - break; - - case 134: - if (!(in & 0x006f0800)) { - sprintf(dp->opcode,"mtfsfi%s",rcsel[in&1]); - sprintf(dp->operands,"cr%d,%d",(int)PPCGETCRD(in), - (int)(in & 0xf000)>>12); - } - else - ill(dp,in); - break; - - case 136: - fdabc(dp,in,"nabs",10,0); - break; - - case 264: - fdabc(dp,in,"abs",10,0); - break; - - case 583: - if (in & (PPCAMASK|PPCBMASK)) - ill(dp,in); - else - dab(dp,in,"mffs",4,0,0,-1,0); - break; - - case 711: - if (!(in & 0x02010000)) { - sprintf(dp->opcode,"mtfsf%s",rcsel[in&1]); - sprintf(dp->operands,"0x%x,%d", - (unsigned)(in & 0x01fe)>>17,(int)PPCGETB(in)); - } - else - ill(dp,in); - break; - - case 814: - fdabc(dp,in,"fctid",10,PPCF_64); - break; - - case 815: - fdabc(dp,in,"fctidz",10,PPCF_64); - break; - - case 846: - fdabc(dp,in,"fcfid",10,PPCF_64); - break; - - default: - ill(dp,in); - break; - } - } - break; - - default: - ill(dp,in); - break; - } - return (dp->instr + 1); - } - -} // namespace - -// What were MS thinking? -#ifdef _WIN32 -#define snprintf _snprintf -#endif - -// simplified interface -void DisassembleGekko(unsigned int opcode, unsigned int curInstAddr, char *dest, int max_size) -{ - char opcodeStr[64], operandStr[64]; - PPCDisasm::DisasmPara_PPC dp; - unsigned int opc, adr; - - opc = opcode; - adr = curInstAddr; - - dp.opcode = opcodeStr; - dp.operands = operandStr; - dp.instr = (PPCDisasm::ppc_word *)&opc; - dp.iaddr = (PPCDisasm::ppc_word *)&adr; - - PPCDisasm::PPC_Disassemble(&dp); - - snprintf(dest, max_size, "%s\t%s", opcodeStr, operandStr); -} - - -static const char *gprnames[] = -{ - " r0", " r1", " r2", " r3", " r4", " r5", " r6", " r7", - " r8", " r9", "r10", "r11", "r12", "r13", "r14", "r15", - "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", - "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31" -}; - -const char *GetGPRName(unsigned int index) -{ - if (index < 32) - return gprnames[index]; - return 0; -} - - -static const char *fprnames[] = -{ - " f0", " f1", " f2", " f3", " f4", " f5", " f6", " f7", - " f8", " f9", "f10", "f11", "f12", "f13", "f14", "f15", - "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", - "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31" -}; - -const char *GetFPRName(unsigned int index) -{ - if (index < 32) - return fprnames[index]; - return 0; -} diff --git a/Externals/Bochs_disasm/PowerPCDisasm.h b/Externals/Bochs_disasm/PowerPCDisasm.h deleted file mode 100644 index d78186af94..0000000000 --- a/Externals/Bochs_disasm/PowerPCDisasm.h +++ /dev/null @@ -1,29 +0,0 @@ -/* $VER: ppc_disasm V0.1 (23.05.1998) - * - * Disassembler module for the PowerPC microprocessor family - * Copyright (c) 1998-2000 Frank Wille - * - * ppc_disasm.c is freeware and may be freely redistributed as long as - * no modifications are made and nothing is charged for it. - * Non-commercial usage is allowed without any restrictions. - * EVERY PRODUCT OR PROGRAM DERIVED DIRECTLY FROM MY SOURCE MAY NOT BE - * SOLD COMMERCIALLY WITHOUT PERMISSION FROM THE AUTHOR. - * - * - * v0.1 (23.05.1998) phx - * First version, which implements all PowerPC instructions. - * v0.0 (09.05.1998) phx - * File created. - */ - - -// Yeah, this does not really belong in bochs_disasm, but hey, it's a disasm and it needed a common location... - -#ifndef _POWERPC_DISASM -#define _POWERPC_DISASM - -void DisassembleGekko(unsigned int opcode, unsigned int curInstAddr, char* dest, int max_size); -const char* GetGPRName(unsigned int index); -const char* GetFPRName(unsigned int index); - -#endif diff --git a/Source/Core/Common/CMakeLists.txt b/Source/Core/Common/CMakeLists.txt index d5974ecca6..246b5da0e7 100644 --- a/Source/Core/Common/CMakeLists.txt +++ b/Source/Core/Common/CMakeLists.txt @@ -3,6 +3,7 @@ set(SRCS BreakPoints.cpp ColorUtil.cpp FileSearch.cpp FileUtil.cpp + GekkoDisassembler.cpp Hash.cpp IniFile.cpp MathUtil.cpp diff --git a/Source/Core/Common/Common.vcxproj b/Source/Core/Common/Common.vcxproj index 31d7bcaffd..106d925365 100644 --- a/Source/Core/Common/Common.vcxproj +++ b/Source/Core/Common/Common.vcxproj @@ -56,6 +56,7 @@ + @@ -94,6 +95,7 @@ + @@ -140,4 +142,4 @@ - + \ No newline at end of file diff --git a/Source/Core/Common/Common.vcxproj.filters b/Source/Core/Common/Common.vcxproj.filters index 1afbcaa15f..3bb9f14958 100644 --- a/Source/Core/Common/Common.vcxproj.filters +++ b/Source/Core/Common/Common.vcxproj.filters @@ -70,6 +70,7 @@ Crypto + @@ -115,6 +116,7 @@ + diff --git a/Source/Core/Common/DebugInterface.h b/Source/Core/Common/DebugInterface.h index 26e0a3e2ee..96b4eec275 100644 --- a/Source/Core/Common/DebugInterface.h +++ b/Source/Core/Common/DebugInterface.h @@ -9,7 +9,7 @@ protected: virtual ~DebugInterface() {} public: - virtual void Disassemble(unsigned int /*address*/, char *dest, int /*max_size*/) {strcpy(dest, "NODEBUGGER");} + virtual std::string Disassemble(unsigned int /*address*/) { return "NODEBUGGER"; } virtual void GetRawMemoryString(int /*memory*/, unsigned int /*address*/, char *dest, int /*max_size*/) {strcpy(dest, "NODEBUGGER");} virtual int GetInstructionSize(int /*instruction*/) {return 1;} virtual bool IsAlive() {return true;} diff --git a/Source/Core/Common/GekkoDisassembler.cpp b/Source/Core/Common/GekkoDisassembler.cpp new file mode 100644 index 0000000000..464d1cb4f5 --- /dev/null +++ b/Source/Core/Common/GekkoDisassembler.cpp @@ -0,0 +1,2299 @@ +/* $VER: ppc_disasm.c V1.5 (27.05.2009) + * + * Disassembler module for the PowerPC microprocessor family + * Copyright (c) 1998-2001,2009,2011 Frank Wille + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +// Modified for use with Dolphin + +#include + +#include "Common/CommonTypes.h" +#include "Common/GekkoDisassembler.h" +#include "Common/StringUtil.h" + +// version/revision +#define PPCDISASM_VER 1 +#define PPCDISASM_REV 6 + +// general defines +#define PPCIDXMASK 0xfc000000 +#define PPCIDX2MASK 0x000007fe +#define PPCDMASK 0x03e00000 +#define PPCAMASK 0x001f0000 +#define PPCBMASK 0x0000f800 +#define PPCCMASK 0x000007c0 +#define PPCMMASK 0x0000003e +#define PPCCRDMASK 0x03800000 +#define PPCCRAMASK 0x001c0000 +#define PPCLMASK 0x00600000 +#define PPCOE 0x00000400 +#define PPCVRC 0x00000400 +#define PPCDST 0x02000000 +#define PPCSTRM 0x00600000 + +#define PPCIDXSH 26 +#define PPCDSH 21 +#define PPCASH 16 +#define PPCBSH 11 +#define PPCCSH 6 +#define PPCMSH 1 +#define PPCCRDSH 23 +#define PPCCRASH 18 +#define PPCLSH 21 +#define PPCIDX2SH 1 + +#define PPCGETIDX(x) (((x)&PPCIDXMASK)>>PPCIDXSH) +#define PPCGETD(x) (((x)&PPCDMASK)>>PPCDSH) +#define PPCGETA(x) (((x)&PPCAMASK)>>PPCASH) +#define PPCGETB(x) (((x)&PPCBMASK)>>PPCBSH) +#define PPCGETC(x) (((x)&PPCCMASK)>>PPCCSH) +#define PPCGETM(x) (((x)&PPCMMASK)>>PPCMSH) +#define PPCGETCRD(x) (((x)&PPCCRDMASK)>>PPCCRDSH) +#define PPCGETCRA(x) (((x)&PPCCRAMASK)>>PPCCRASH) +#define PPCGETL(x) (((x)&PPCLMASK)>>PPCLSH) +#define PPCGETIDX2(x) (((x)&PPCIDX2MASK)>>PPCIDX2SH) +#define PPCGETSTRM(x) (((x)&PPCSTRM)>>PPCDSH) + + +static const char* trap_condition[32] = { + nullptr, "lgt", "llt", nullptr, "eq", "lge", "lle", nullptr, + "gt", nullptr, nullptr, nullptr, "ge", nullptr, nullptr, nullptr, + "lt", nullptr, nullptr, nullptr, "le", nullptr, nullptr, nullptr, + "ne", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr +}; + +static const char* cmpname[4] = { + "cmpw", "cmpd", "cmplw", "cmpld" +}; + +static const char* b_ext[4] = { + "", "l", "a", "la" +}; + +static const char* b_condition[8] = { + "ge", "le", "ne", "ns", "lt", "gt", "eq", "so" +}; + +static const char* b_decr[16] = { + "nzf", "zf", nullptr, nullptr, "nzt", "zt", nullptr, nullptr, + "nz", "z", nullptr, nullptr, "nz", "z", nullptr, nullptr +}; + +static const char* regsel[2] = { + "", "r" +}; + +static const char* oesel[2] = { + "", "o" +}; + +static const char* rcsel[2] = { + "", "." +}; + +static const char* ldstnames[24] = { + "lwz", "lwzu", "lbz", "lbzu", "stw", "stwu", "stb", "stbu", "lhz", "lhzu", + "lha", "lhau", "sth", "sthu", "lmw", "stmw", "lfs", "lfsu", "lfd", "lfdu", + "stfs", "stfsu", "stfd", "stfdu" +}; + +static const char* regnames[32] = { + "r0", "sp", "rtoc", "r3", "r4", "r5", "r6", "r7", + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", + "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", + "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31" +}; + +// Initialize static class variables. +u32* GekkoDisassembler::m_instr = nullptr; +u32* GekkoDisassembler::m_iaddr = nullptr; +std::string GekkoDisassembler::m_opcode = ""; +std::string GekkoDisassembler::m_operands = ""; +unsigned char GekkoDisassembler::m_type = 0; +unsigned char GekkoDisassembler::m_flags = PPCF_ILLEGAL; +unsigned short GekkoDisassembler::m_sreg = 0; +u32 GekkoDisassembler::m_displacement = 0; + + +static std::string spr_name(int i) +{ + switch (i) + { + case 1: return "XER"; + case 8: return "LR"; + case 9: return "CTR"; + case 18: return "DSIR"; + case 19: return "DAR"; + case 22: return "DEC"; + case 25: return "SDR1"; + case 26: return "SRR0"; + case 27: return "SRR1"; + case 272: return "SPRG0"; + case 273: return "SPRG1"; + case 274: return "SPRG2"; + case 275: return "SPRG3"; + case 282: return "EAR"; + case 287: return "PVR"; + case 528: return "IBAT0U"; + case 529: return "IBAT0L"; + case 530: return "IBAT1U"; + case 531: return "IBAT1L"; + case 532: return "IBAT2U"; + case 533: return "IBAT2L"; + case 534: return "IBAT3U"; + case 535: return "IBAT3L"; + case 536: return "DBAT0U"; + case 537: return "DBAT0L"; + case 538: return "DBAT1U"; + case 539: return "DBAT1L"; + case 540: return "DBAT2U"; + case 541: return "DBAT2L"; + case 542: return "DBAT3U"; + case 543: return "DBAT3L"; + case 912: return "GQR0"; + case 913: return "GQR1"; + case 914: return "GQR2"; + case 915: return "GQR3"; + case 916: return "GQR4"; + case 917: return "GQR5"; + case 918: return "GQR6"; + case 919: return "GQR7"; + case 920: return "HID2"; + case 921: return "WPAR"; + case 922: return "DMA_U"; + case 923: return "DMA_L"; + case 924: return "ECID_U"; + case 925: return "ECID_M"; + case 926: return "ECID_L"; + case 936: return "UMMCR0"; + case 937: return "UPMC1"; + case 938: return "UPMC2"; + case 939: return "USIA"; + case 940: return "UMMCR1"; + case 941: return "UPMC3"; + case 942: return "UPMC4"; + case 943: return "USDA"; + case 952: return "MMCR0"; + case 953: return "PMC1"; + case 954: return "PMC2"; + case 955: return "SIA"; + case 956: return "MMCR1"; + case 957: return "PMC3"; + case 958: return "PMC4"; + case 959: return "SDA"; + case 1008: return "HID0"; + case 1009: return "HID1"; + case 1010: return "IABR"; + case 1011: return "HID4"; + case 1013: return "DABR"; + case 1017: return "L2CR"; + case 1019: return "ICTC"; + case 1020: return "THRM1"; + case 1021: return "THRM2"; + case 1022: return "THRM3"; + } + + return StringFromFormat("%d", i); +} + + +static u32 swapda(u32 w) +{ + return ((w & 0xfc00ffff) | ((w&PPCAMASK) << 5) | ((w&PPCDMASK) >> 5)); +} + + +static u32 swapab(u32 w) +{ + return ((w & 0xffe007ff) | ((w&PPCBMASK) << 5) | ((w&PPCAMASK) >> 5)); +} + + +void GekkoDisassembler::ill(u32 in) +{ + if (in == 0) + { + m_opcode = ""; + m_operands = "---"; + } + else + { + m_opcode = "(ill)"; + m_operands = StringFromFormat("%08x", in); + } + + m_flags |= PPCF_ILLEGAL; +} + +// Generate immediate instruction operand. +// +// Type 0: D-mode, D,A,imm +// Type 1: S-mode, A,S,imm +// Type 2: S/D register is ignored (trap,cmpi) +// Type 3: A register is ignored (li) +std::string GekkoDisassembler::imm(u32 in, int uimm, int type, bool hex) +{ + int i = (int)(in & 0xffff); + + m_type = PPCINSTR_IMM; + + if (uimm == 0) + { + if (i > 0x7fff) + i -= 0x10000; + } + else + { + m_flags |= PPCF_UNSIGNED; + } + m_displacement = i; + + switch (type) + { + case 0: + return StringFromFormat("%s, %s, %d", regnames[(int)PPCGETD(in)], regnames[(int)PPCGETA(in)], i); + + case 1: + if (hex) + return StringFromFormat("%s, %s, 0x%.4X", regnames[(int)PPCGETA(in)], regnames[(int)PPCGETD(in)], i); + else + return StringFromFormat("%s, %s, %d", regnames[(int)PPCGETA(in)], regnames[(int)PPCGETD(in)], i); + + case 2: + return StringFromFormat("%s, %d", regnames[(int)PPCGETA(in)], i); + + case 3: + if (hex) + return StringFromFormat("%s, 0x%.4X", regnames[(int)PPCGETD(in)], i); + else + return StringFromFormat("%s, %d", regnames[(int)PPCGETD(in)], i); + + default: + return StringFromFormat("%s", "imm(): Wrong type"); + } +} + + +std::string GekkoDisassembler::ra_rb(u32 in) +{ + return StringFromFormat("%s, %s", regnames[(int)PPCGETA(in)], regnames[(int)PPCGETB(in)]); +} + + +std::string GekkoDisassembler::rd_ra_rb(u32 in, int mask) +{ + std::string result; + + if (mask) + { + if (mask & 4) + result += StringFromFormat("%s, ", regnames[(int)PPCGETD(in)]); + if (mask & 2) + result += StringFromFormat("%s, ", regnames[(int)PPCGETA(in)]); + if (mask & 1) + result += StringFromFormat("%s, ", regnames[(int)PPCGETB(in)]); + + size_t pos = result.rfind(", "); + if (pos != std::string::npos) + { + result.erase(pos, result.length() - pos); + } + } + + return result; +} + + +std::string GekkoDisassembler::fd_ra_rb(u32 in, int mask) +{ + std::string result; + + if (mask) + { + if (mask & 4) + result += StringFromFormat("f%d,", (int)PPCGETD(in)); + if (mask & 2) + result += StringFromFormat("%s,", regnames[(int)PPCGETA(in)]); + if (mask & 1) + result += StringFromFormat("%s,", regnames[(int)PPCGETB(in)]); + + // Drop the trailing comma + result.pop_back(); + } + + return result; +} + + +void GekkoDisassembler::trapi(u32 in, unsigned char dmode) +{ + const char* cnd = trap_condition[PPCGETD(in)]; + + if (cnd != nullptr) + { + m_flags |= dmode; + m_opcode = StringFromFormat("t%c%s", dmode ? 'd' : 'w', cnd); + m_operands = imm(in, 0, 2, false); + } + else + { + ill(in); + } +} + + +void GekkoDisassembler::cmpi(u32 in, int uimm) +{ + int i = (int)PPCGETL(in); + + if (i < 2) + { + if (i != 0) + m_flags |= PPCF_64; + + m_opcode = StringFromFormat("%si", cmpname[uimm * 2 + i]); + + i = (int)PPCGETCRD(in); + if (i != 0) + { + m_operands += StringFromFormat("cr%c,", '0' + i); + } + + m_operands += imm(in, uimm, 2, false); + } + else + { + ill(in); + } +} + + +void GekkoDisassembler::addi(u32 in, const std::string& ext) +{ + if ((in & 0x08000000) && !PPCGETA(in)) + { + m_opcode = StringFromFormat("l%s", ext.c_str()); // li, lis + + if (ext == "i") + m_operands = imm(in, 0, 3, false); + else + m_operands = imm(in, 1, 3, true); + } + else + { + m_opcode = StringFromFormat("%s%s", (in & 0x8000) ? "sub" : "add", ext.c_str()); + + if (in & 0x8000) + in = (in ^ 0xffff) + 1; + + m_operands = imm(in, 1, 0, false); + } +} + +// Build a branch instr. and return number of chars written to operand. +size_t GekkoDisassembler::branch(u32 in, const char* bname, int aform, int bdisp) +{ + int bo = (int)PPCGETD(in); + int bi = (int)PPCGETA(in); + char y = (char)(bo & 1); + const char* ext = b_ext[aform * 2 + (int)(in & 1)]; + + if (bdisp < 0) + y ^= 1; + y = (y != 0) ? '+' : '-'; + + if (bo & 4) + { + // standard case - no decrement + if (bo & 16) + { + // branch always + if (PPCGETIDX(in) != 16) + { + m_opcode = StringFromFormat("b%s%s", bname, ext); + } + else + { + m_opcode = StringFromFormat("bc%s", ext); + m_operands = StringFromFormat("%d, %d", bo, bi); + } + } + else // Branch conditional + { + m_opcode = StringFromFormat("b%s%s%s%c", b_condition[((bo & 8) >> 1) + (bi & 3)], bname, ext, y); + + if (bi >= 4) + { + m_operands = StringFromFormat("cr%d", bi >> 2); + } + } + } + else + { + // CTR is decremented and checked + m_opcode = StringFromFormat("bd%s%s%s%c", b_decr[bo >> 1], bname, ext, y); + + if ((bo & 16) == 0) + { + m_operands = StringFromFormat("%d", bi); + } + } + + return m_operands.length(); +} + + +void GekkoDisassembler::bc(u32 in) +{ + unsigned int d = (int)(in & 0xfffc); + + if (d & 0x8000) + d |= 0xffff0000; + + branch(in, "", (in & 2) ? 1 : 0, d); + + if (in & 2) // AA ? + m_operands = StringFromFormat("->0x%.8X", d); + else + m_operands = StringFromFormat("->0x%.8X", *m_iaddr + d); + + m_type = PPCINSTR_BRANCH; + m_displacement = d; +} + + +void GekkoDisassembler::bli(u32 in) +{ + unsigned int d = (unsigned int)(in & 0x3fffffc); + + if (d & 0x02000000) + d |= 0xfc000000; + + m_opcode = StringFromFormat("b%s", b_ext[in & 3]); + + if (in & 2) // AA ? + m_operands = StringFromFormat("->0x%.8X", d); + else + m_operands = StringFromFormat("->0x%.8X", *m_iaddr + d); + + m_type = PPCINSTR_BRANCH; + m_displacement = d; +} + + +void GekkoDisassembler::mcrf(u32 in, char c) +{ + if ((in & 0x0063f801) == 0) + { + m_opcode = StringFromFormat("mcrf%c", c); + m_operands = StringFromFormat("cr%d, cr%d", (int)PPCGETCRD(in), (int)PPCGETCRA(in)); + } + else + { + ill(in); + } +} + + +void GekkoDisassembler::crop(u32 in, const char* n1, const char* n2) +{ + int crd = (int)PPCGETD(in); + int cra = (int)PPCGETA(in); + int crb = (int)PPCGETB(in); + + if ((in & 1) == 0) + { + m_opcode = StringFromFormat("cr%s", (cra == crb && n2) ? n2 : n1); + if (cra == crb && n2) + m_operands = StringFromFormat("%d, %d", crd, cra); + else + m_operands = StringFromFormat("%d, %d, %d", crd, cra, crb); + } + else + { + ill(in); + } +} + + +void GekkoDisassembler::nooper(u32 in, const char* name, unsigned char dmode) +{ + if (in & (PPCDMASK | PPCAMASK | PPCBMASK | 1)) + { + ill(in); + } + else + { + m_flags |= dmode; + m_opcode = name; + } +} + +void GekkoDisassembler::rlw(u32 in, const char* name, int i) +{ + int s = (int)PPCGETD(in); + int a = (int)PPCGETA(in); + int bsh = (int)PPCGETB(in); + int mb = (int)PPCGETC(in); + int me = (int)PPCGETM(in); + + m_opcode = StringFromFormat("rlw%s%c", name, in & 1 ? '.' : '\0'); + m_operands = StringFromFormat("%s, %s, %s%d, %d, %d (%08x)", regnames[a], regnames[s], regsel[i], bsh, mb, me, HelperRotateMask(bsh, mb, me)); +} + + +void GekkoDisassembler::ori(u32 in, const char* name) +{ + m_opcode = name; + m_operands = imm(in, 1, 1, true); +} + + +void GekkoDisassembler::rld(u32 in, const char* name, int i) +{ + int s = (int)PPCGETD(in); + int a = (int)PPCGETA(in); + int bsh = i ? (int)PPCGETB(in) : (int)(((in & 2) << 4) + PPCGETB(in)); + int m = (int)(in & 0x7e0) >> 5; + + m_flags |= PPCF_64; + m_opcode = StringFromFormat("rld%s%c", name, in & 1 ? '.' : '\0'); + m_operands = StringFromFormat("%s, %s, %s%d, %d", regnames[a], regnames[s], regsel[i], bsh, m); +} + + +void GekkoDisassembler::cmp(u32 in) +{ + int i = (int)PPCGETL(in); + + if (i < 2) + { + if (i != 0) + m_flags |= PPCF_64; + + m_opcode = cmpname[((in&PPCIDX2MASK) ? 2 : 0) + i]; + + i = (int)PPCGETCRD(in); + if (i != 0) + m_operands += StringFromFormat("cr%c,", '0' + i); + + m_operands += ra_rb(in); + } + else + { + ill(in); + } +} + + +void GekkoDisassembler::trap(u32 in, unsigned char dmode) +{ + int to = (int)PPCGETD(in); + const char* cnd = trap_condition[to]; + + if (cnd != nullptr) + { + m_flags |= dmode; + m_opcode = StringFromFormat("t%c%s", dmode ? 'd' : 'w', cnd); + m_operands = ra_rb(in); + } + else + { + if (to == 31) + { + if (dmode) + { + m_flags |= dmode; + m_opcode = "td"; + m_operands = "31,0,0"; + } + else + { + m_opcode = "trap"; + } + } + else + { + ill(in); + } + } +} + +// Standard instruction: xxxx rD,rA,rB +void GekkoDisassembler::dab(u32 in, const char* name, int mask, int smode, int chkoe, int chkrc, unsigned char dmode) +{ + if (chkrc >= 0 && ((in & 1) != (unsigned int)chkrc)) + { + ill(in); + } + else + { + m_flags |= dmode; + + // rA,rS,rB + if (smode) + in = swapda(in); + + m_opcode = StringFromFormat("%s%s%s", name, oesel[chkoe && (in&PPCOE)], rcsel[(chkrc < 0) && (in & 1)]); + m_operands = rd_ra_rb(in, mask); + } +} + +// Last operand is no register: xxxx rD,rA,NB +void GekkoDisassembler::rrn(u32 in, const char* name, int smode, int chkoe, int chkrc, unsigned char dmode) +{ + if (chkrc >= 0 && ((in & 1) != (unsigned int)chkrc)) + { + ill(in); + } + else + { + m_flags |= dmode; + + // rA,rS,NB + if (smode) + in = swapda(in); + + m_opcode = StringFromFormat("%s%s%s", name, oesel[chkoe && (in&PPCOE)], rcsel[(chkrc < 0) && (in & 1)]); + + m_operands = rd_ra_rb(in, 6); + m_operands += StringFromFormat(",%d",(int)PPCGETB(in)); + } +} + + +void GekkoDisassembler::mtcr(u32 in) +{ + int s = (int)PPCGETD(in); + int crm = (int)(in & 0x000ff000) >> 12; + + if (in & 0x00100801) + { + ill(in); + } + else + { + m_opcode = StringFromFormat("mtcr%c", crm == 0xff ? '\0' : 'f'); + + if (crm != 0xff) + m_operands += StringFromFormat("0x%02x,", crm); + + m_operands += regnames[s]; + } +} + + +void GekkoDisassembler::msr(u32 in, int smode) +{ + int s = (int)PPCGETD(in); + int sr = (int)(in & 0x000f0000) >> 16; + + if (in & 0x0010f801) + { + ill(in); + } + else + { + m_flags |= PPCF_SUPER; + m_opcode = StringFromFormat("m%csr", smode ? 't' : 'f'); + + if (smode) + m_operands = StringFromFormat("%d, %s", sr, regnames[s]); + else + m_operands = StringFromFormat("%s, %d", regnames[s], sr); + } +} + + +void GekkoDisassembler::mspr(u32 in, int smode) +{ + int d = (int)PPCGETD(in); + int spr = (int)((PPCGETB(in) << 5) + PPCGETA(in)); + int fmt = 0; + + if (in & 1) + { + ill(in); + } + else + { + if (spr != 1 && spr != 8 && spr != 9) + m_flags |= PPCF_SUPER; + + const char* x; + switch (spr) + { + case 1: + x = "xer"; + break; + + case 8: + x = "lr"; + break; + + case 9: + x = "ctr"; + break; + + default: + x = "spr"; + fmt = 1; + break; + } + + m_opcode = StringFromFormat("m%c%s", smode ? 't' : 'f', x); + + if (fmt) + { + if (smode) + m_operands = StringFromFormat("%s, %s", spr_name(spr).c_str(), regnames[d]); + else + m_operands = StringFromFormat("%s, %s", regnames[d], spr_name(spr).c_str()); + } + else + { + m_operands = regnames[d]; + } + } +} + + +void GekkoDisassembler::mtb(u32 in) +{ + int d = (int)PPCGETD(in); + int tbr = (int)((PPCGETB(in) << 5) + PPCGETA(in)); + + if (in & 1) + { + ill(in); + } + else + { + m_operands += regnames[d]; + + char x; + switch (tbr) + { + case 268: + x = 'l'; + break; + + case 269: + x = 'u'; + break; + + default: + x = '\0'; + m_flags |= PPCF_SUPER; + m_operands += StringFromFormat(",%d", tbr); + break; + } + + m_opcode = StringFromFormat("mftb%c", x); + } +} + + +void GekkoDisassembler::sradi(u32 in) +{ + int s = (int)PPCGETD(in); + int a = (int)PPCGETA(in); + int bsh = (int)(((in & 2) << 4) + PPCGETB(in)); + + m_flags |= PPCF_64; + m_opcode = StringFromFormat("sradi%c", in & 1 ? '.' : '\0'); + m_operands = StringFromFormat("%s, %s, %d", regnames[a], regnames[s], bsh); +} + +void GekkoDisassembler::ldst(u32 in, const char* name, char reg, unsigned char dmode) +{ + int s = (int)PPCGETD(in); + int a = (int)PPCGETA(in); + int d = (u32)(in & 0xffff); + + m_type = PPCINSTR_LDST; + m_flags |= dmode; + m_sreg = (short)a; + // if (d >= 0x8000) + // d -= 0x10000; + m_displacement = (u32)d; + m_opcode = name; + + if (reg == 'r') + { + m_operands = StringFromFormat("%s, %s (%s)", regnames[s], ldst_offs(d).c_str(), regnames[a]); + } + else + { + m_operands = StringFromFormat("%c%d, %s (%s)", reg, s, ldst_offs(d).c_str(), regnames[a]); + } +} + +// Standard floating point instruction: xxxx fD,fA,fC,fB +void GekkoDisassembler::fdabc(u32 in, const char* name, int mask, unsigned char dmode) +{ + int err = 0; + + m_flags |= dmode; + m_opcode = StringFromFormat("f%s%s", name, rcsel[in & 1]); + m_operands += StringFromFormat("f%d,", (int)PPCGETD(in)); + + if (mask & 4) + m_operands += StringFromFormat("f%d,", (int)PPCGETA(in)); + else + err |= (int)PPCGETA(in); + + if (mask & 2) + m_operands += StringFromFormat("f%d,", (int)PPCGETC(in)); + else if (PPCGETC(in)) + err |= (int)PPCGETC(in); + + if (mask & 1) + m_operands += StringFromFormat("f%d,", (int)PPCGETB(in)); + else if (!(mask & 8)) + err |= (int)PPCGETB(in); + + // Drop the trailing comma + m_operands.pop_back(); + + if (err) + ill(in); +} + +void GekkoDisassembler::fmr(u32 in) +{ + m_opcode = StringFromFormat("fmr%s", rcsel[in & 1]); + m_operands = StringFromFormat("f%d, f%d", (int)PPCGETD(in), (int)PPCGETB(in)); +} + +// Indexed float instruction: xxxx fD,rA,rB +void GekkoDisassembler::fdab(u32 in, const char* name, int mask) +{ + m_opcode = name; + m_operands = fd_ra_rb(in, mask); +} + + +void GekkoDisassembler::fcmp(u32 in, char c) +{ + if (in & 0x00600001) + { + ill(in); + } + else + { + m_opcode = StringFromFormat("fcmp%c", c); + m_operands = StringFromFormat("cr%d,f%d,f%d", (int)PPCGETCRD(in), (int)PPCGETA(in), (int)PPCGETB(in)); + } +} + + +void GekkoDisassembler::mtfsb(u32 in, int n) +{ + if (in & (PPCAMASK | PPCBMASK)) + { + ill(in); + } + else + { + m_opcode = StringFromFormat("mtfsb%d%s", n, rcsel[in & 1]); + m_operands = StringFromFormat("%d", (int)PPCGETD(in)); + } +} + + +// Paired instructions + +#define RA ((inst >> 16) & 0x1f) +#define RB ((inst >> 11) & 0x1f) +#define RC ((inst >> 6) & 0x1f) +#define RD ((inst >> 21) & 0x1f) +#define RS ((inst >> 21) & 0x1f) +#define FA ((inst >> 16) & 0x1f) +#define FB ((inst >> 11) & 0x1f) +#define FC ((inst >> 6) & 0x1f) +#define FD ((inst >> 21) & 0x1f) +#define FS ((inst >> 21) & 0x1f) +#define IMM (inst & 0xffff) +#define UIMM (inst & 0xffff) +#define OFS (inst & 0xffff) +#define OPCD ((inst >> 26) & 0x3f) +#define XO_10 ((inst >> 1) & 0x3ff) +#define XO_9 ((inst >> 1) & 0x1ff) +#define XO_5 ((inst >> 1) & 0x1f) +#define Rc (inst & 1) +#define SH ((inst >> 11) & 0x1f) +#define MB ((inst >> 6) & 0x1f) +#define ME ((inst >> 1) & 0x1f) +#define OE ((inst >> 10) & 1) +#define TO ((inst >> 21) & 0x1f) +#define CRFD ((inst >> 23) & 0x7) +#define CRFS ((inst >> 18) & 0x7) +#define CRBD ((inst >> 21) & 0x1f) +#define CRBA ((inst >> 16) & 0x1f) +#define CRBB ((inst >> 11) & 0x1f) +#define L ((inst >> 21) & 1) +#define NB ((inst >> 11) & 0x1f) +#define AA ((inst >> 1) & 1) +#define LK (inst & 1) +#define LI ((inst >> 2) & 0xffffff) +#define BO ((inst >> 21) & 0x1f) +#define BI ((inst >> 16) & 0x1f) +#define BD ((inst >> 2) & 0x3fff) + +#define MTFSFI_IMM ((inst >> 12) & 0xf) +#define FM ((inst >> 17) & 0xff) +#define SR ((inst >> 16) & 0xf) +#define SPR ((inst >> 11) & 0x3ff) +#define TBR ((inst >> 11) & 0x3ff) +#define CRM ((inst >> 12) & 0xff) + + +void GekkoDisassembler::ps(u32 inst) +{ + switch ((inst >> 1) & 0x1F) + { + case 6: + m_opcode = "ps_lux"; + m_operands = StringFromFormat("p%u, (r%u + r%u)", FD, RA, RB); + return; + + case 18: + m_opcode = "ps_div"; + m_operands = StringFromFormat("p%u, p%u/p%u", FD, FA, FB); + return; + + case 20: + m_opcode = "ps_sub"; + m_operands = StringFromFormat("p%u, p%u-p%u", FD, FA, FB); + return; + + case 21: + m_opcode = "ps_add"; + m_operands = StringFromFormat("p%u, p%u+p%u", FD, FA, FB); + return; + + case 23: + m_opcode = "ps_sel"; + m_operands = StringFromFormat("p%u>=0?p%u:p%u", FD, FA, FC); + return; + + case 24: + m_opcode = "ps_res"; + m_operands = StringFromFormat("p%u, (1/p%u)", FD, FB); + return; + + case 25: + m_opcode = "ps_mul"; + m_operands = StringFromFormat("p%u, p%u*p%u", FD, FA, FC); + return; + + case 26: // rsqrte + m_opcode = "ps_rsqrte"; + m_operands = StringFromFormat("p%u, p%u", FD, FB); + return; + + case 28: // msub + m_opcode = "ps_msub"; + m_operands = StringFromFormat("p%u, p%u*p%u-p%u", FD, FA, FC, FB); + return; + + case 29: // madd + m_opcode = "ps_madd"; + m_operands = StringFromFormat("p%u, p%u*p%u+p%u", FD, FA, FC, FB); + return; + + case 30: // nmsub + m_opcode = "ps_nmsub"; + m_operands = StringFromFormat("p%u, -(p%u*p%u-p%u)", FD, FA, FC, FB); + return; + + case 31: // nmadd + m_opcode = "ps_nmadd"; + m_operands = StringFromFormat("p%u, -(p%u*p%u+p%u)", FD, FA, FC, FB); + return; + + case 10: + m_opcode = "ps_sum0"; + m_operands = StringFromFormat("p%u, 0=p%u+p%u, 1=p%u", FD, FA, FB, FC); + return; + + case 11: + m_opcode = "ps_sum1"; + m_operands = StringFromFormat("p%u, 0=p%u, 1=p%u+p%u", FD, FC, FA, FB); + return; + + case 12: + m_opcode = "ps_muls0"; + m_operands = StringFromFormat("p%u, p%u*p%u[0]", FD, FA, FC); + return; + + case 13: + m_opcode = "ps_muls1"; + m_operands = StringFromFormat("p%u, p%u*p%u[1]", FD, FA, FC); + return; + + case 14: + m_opcode = "ps_madds0"; + m_operands = StringFromFormat("p%u, p%u*p%u[0]+p%u", FD, FA, FC, FB); + return; + + case 15: + m_opcode = "ps_madds1"; + m_operands = StringFromFormat("p%u, p%u*p%u[1]+p%u", FD, FA, FC, FB); + return; + } + + switch ((inst >> 1) & 0x3FF) + { + // 10-bit suckers (?) + case 40: // nmadd + m_opcode = "ps_neg"; + m_operands = StringFromFormat("p%u, -p%u", FD, FB); + return; + + case 72: // nmadd + m_opcode = "ps_mr"; + m_operands = StringFromFormat("p%u, p%u", FD, FB); + return; + + case 136: + m_opcode = "ps_nabs"; + m_operands = StringFromFormat("p%u, -|p%u|", FD, FB); + return; + + case 264: + m_opcode = "ps_abs"; + m_operands = StringFromFormat("p%u, |p%u|", FD, FB); + return; + + case 0: + m_opcode = "ps_cmpu0"; + m_operands = "ps_cmpu0"; + return; + + case 32: + m_opcode = "ps_cmpq0"; + m_operands = "ps_cmpo0"; + return; + + case 64: + m_opcode = "ps_cmpu1"; + m_operands = "ps_cmpu1"; + return; + + case 96: + m_opcode = "ps_cmpo1"; + m_operands = "ps_cmpo1"; + return; + + case 528: + m_opcode = "ps_merge00"; + m_operands = StringFromFormat("p%u, p%u[0],p%u[0]", FD, FA, FB); + return; + + case 560: + m_opcode = "ps_merge01"; + m_operands = StringFromFormat("p%u, p%u[0],p%u[1]", FD, FA, FB); + return; + + case 592: + m_opcode = "ps_merge10"; + m_operands = StringFromFormat("p%u, p%u[1],p%u[0]", FD, FA, FB); + return; + + case 624: + m_opcode = "ps_merge11"; + m_operands = StringFromFormat("p%u, p%u[1],p%u[1]", FD, FA, FB); + return; + + case 1014: + m_opcode = "dcbz_l"; + m_operands = ""; + return; + } + + // default: + m_opcode = StringFromFormat("ps_%i", ((inst >> 1) & 0x1f)); + m_operands = "---"; +} + +void GekkoDisassembler::ps_mem(u32 inst) +{ + switch (PPCGETIDX(inst)) + { + case 56: + m_opcode = "psq_l"; + m_operands = StringFromFormat("p%u, %i(r%u)", RS, SEX12(inst & 0xFFF), RA); + break; + + case 57: + m_opcode = "psq_lu"; + m_operands = ""; + break; + + case 60: + m_opcode = "psq_st"; + m_operands = StringFromFormat("%i(r%u), p%u", SEX12(inst & 0xFFF), RA, RS); + break; + + case 61: + m_opcode = "psq_stu"; + m_operands = StringFromFormat("r%u, p%u ?", RA, RS); + break; + } +} + +// Disassemble PPC instruction and return a pointer to the next +// instruction, or nullptr if an error occured. +u32* GekkoDisassembler::DoDisassembly(bool big_endian) +{ + u32 in = *m_instr; + + if (!big_endian) + { + in = (in & 0xff) << 24 | (in & 0xff00) << 8 | (in & 0xff0000) >> 8 | + (in & 0xff000000) >> 24; + } + + m_opcode.clear(); + m_operands.clear(); + m_type = PPCINSTR_OTHER; + m_flags = 0; + + switch (PPCGETIDX(in)) + { + case 0: + { + int block = in & 0x3FFFFFF; + if (block) + { + m_opcode = "JITblock"; + m_operands = StringFromFormat("%i", block); + } + else + { + m_opcode = ""; + m_operands = "---"; + } + } + break; + + case 1: // HLE call + m_opcode = "HLE"; + break; + + case 2: + trapi(in, PPCF_64); // tdi + break; + + case 3: + trapi(in, 0); // twi + break; + + case 4: + ps(in); + break; + + case 56: + case 57: + case 60: + case 61: + ps_mem(in); + break; + + case 7: + m_opcode = "mulli"; + m_operands = imm(in, 0, 0, false); + break; + + case 8: + m_opcode = "subfic"; + m_operands = imm(in, 0, 0, false); + break; + + case 10: + cmpi(in, 1); // cmpli + break; + + case 11: + cmpi(in, 0); // cmpi + break; + + case 12: + addi(in, "ic"); // addic + break; + + case 13: + addi(in, "ic."); // addic. + break; + + case 14: + addi(in, "i"); // addi + break; + + case 15: + addi(in, "is"); // addis + break; + + case 16: + bc(in); + break; + + case 17: + if ((in & ~PPCIDXMASK) == 2) + m_opcode = "sc"; + else + ill(in); + break; + + case 18: + bli(in); + break; + + case 19: + switch (PPCGETIDX2(in)) + { + case 0: + mcrf(in, '\0'); // mcrf + break; + + case 16: + branch(in, "lr", 0, 0); // bclr + break; + + case 33: + crop(in, "nor", "not"); // crnor + break; + + case 50: + nooper(in, "rfi", PPCF_SUPER); + break; + + case 129: + crop(in, "andc", nullptr); // crandc + break; + + case 150: + nooper(in, "isync", 0); + break; + + case 193: + crop(in, "xor", "clr"); // crxor + break; + + case 225: + crop(in, "nand", nullptr); // crnand + break; + + case 257: + crop(in, "and", nullptr); // crand + break; + + case 289: + crop(in, "eqv", "set"); // creqv + break; + + case 417: + crop(in, "orc", nullptr); // crorc + break; + + case 449: + crop(in, "or", "move"); // cror + break; + + case 528: + branch(in, "ctr", 0, 0); // bcctr + break; + + default: + ill(in); + break; + } + break; + + case 20: + rlw(in, "imi", 0); // rlwimi + break; + + case 21: + rlw(in, "inm", 0); // rlwinm + break; + + case 23: + rlw(in, "nm", 1); // rlwnm + break; + + case 24: + if (in & ~PPCIDXMASK) + ori(in, "ori"); + else + m_opcode = "nop"; + break; + + case 25: + ori(in, "oris"); + break; + + case 26: + ori(in, "xori"); + break; + + case 27: + ori(in, "xoris"); + break; + + case 28: + ori(in, "andi."); + break; + + case 29: + ori(in, "andis."); + break; + + case 30: + switch (in & 0x1c) + { + case 0: + rld(in, "icl", 0); // rldicl + break; + case 1: + rld(in, "icr", 0); // rldicr + break; + case 2: + rld(in, "ic", 0); // rldic + break; + case 3: + rld(in, "imi", 0); // rldimi + break; + case 4: + rld(in, in & 2 ? "cl" : "cr", 1); // rldcl, rldcr + break; + default: + ill(in); + break; + } + break; + + case 31: + switch (PPCGETIDX2(in)) + { + case 0: + case 32: + if (in & 1) + ill(in); + else + cmp(in); // cmp, cmpl + break; + + case 4: + if (in & 1) + ill(in); + else + trap(in, 0); // tw + break; + + case 8: + case (PPCOE >> 1) + 8: + dab(swapab(in), "subc", 7, 0, 1, -1, 0); + break; + + case 9: + dab(in, "mulhdu", 7, 0, 0, -1, PPCF_64); + break; + + case 10: + case (PPCOE >> 1) + 10: + dab(in, "addc", 7, 0, 1, -1, 0); + break; + + case 11: + dab(in, "mulhwu", 7, 0, 0, -1, 0); + break; + + case 19: + if (in & (PPCAMASK | PPCBMASK)) + ill(in); + else + dab(in, "mfcr", 4, 0, 0, 0, 0); + break; + + case 20: + dab(in, "lwarx", 7, 0, 0, 0, 0); + break; + + case 21: + dab(in, "ldx", 7, 0, 0, 0, PPCF_64); + break; + + case 23: + dab(in, "lwzx", 7, 0, 0, 0, 0); + break; + + case 24: + dab(in, "slw", 7, 1, 0, -1, 0); + break; + + case 26: + if (in & PPCBMASK) + ill(in); + else + dab(in, "cntlzw", 6, 1, 0, -1, 0); + break; + + case 27: + dab(in, "sld", 7, 1, 0, -1, PPCF_64); + break; + + case 28: + dab(in, "and", 7, 1, 0, -1, 0); + break; + + case 40: + case (PPCOE >> 1) + 40: + dab(swapab(in), "sub", 7, 0, 1, -1, 0); + break; + + case 53: + dab(in, "ldux", 7, 0, 0, 0, PPCF_64); + break; + + case 54: + if (in & PPCDMASK) + ill(in); + else + dab(in, "dcbst", 3, 0, 0, 0, 0); + break; + + case 55: + dab(in, "lwzux", 7, 0, 0, 0, 0); + break; + + case 58: + if (in & PPCBMASK) + ill(in); + else + dab(in, "cntlzd", 6, 1, 0, -1, PPCF_64); + break; + + case 60: + dab(in, "andc", 7, 1, 0, -1, 0); + break; + + case 68: + trap(in, PPCF_64); // td + break; + + case 73: + dab(in, "mulhd", 7, 0, 0, -1, PPCF_64); + break; + + case 75: + dab(in, "mulhw", 7, 0, 0, -1, 0); + break; + + case 83: + if (in & (PPCAMASK | PPCBMASK)) + ill(in); + else + dab(in, "mfmsr", 4, 0, 0, 0, PPCF_SUPER); + break; + + case 84: + dab(in, "ldarx", 7, 0, 0, 0, PPCF_64); + break; + + case 86: + if (in & PPCDMASK) + ill(in); + else + dab(in, "dcbf", 3, 0, 0, 0, 0); + break; + + case 87: + dab(in, "lbzx", 7, 0, 0, 0, 0); + break; + + case 104: + case (PPCOE >> 1) + 104: + if (in & PPCBMASK) + ill(in); + else + dab(in, "neg", 6, 0, 1, -1, 0); + break; + + case 119: + dab(in, "lbzux", 7, 0, 0, 0, 0); + break; + + case 124: + if (PPCGETD(in) == PPCGETB(in)) + dab(in, "not", 6, 1, 0, -1, 0); + else + dab(in, "nor", 7, 1, 0, -1, 0); + break; + + case 136: + case (PPCOE >> 1) + 136: + dab(in, "subfe", 7, 0, 1, -1, 0); + break; + + case 138: + case (PPCOE >> 1) + 138: + dab(in, "adde", 7, 0, 1, -1, 0); + break; + + case 144: + mtcr(in); + break; + + case 146: + if (in & (PPCAMASK | PPCBMASK)) + ill(in); + else + dab(in, "mtmsr", 4, 0, 0, 0, PPCF_SUPER); + break; + + case 149: + dab(in, "stdx", 7, 0, 0, 0, PPCF_64); + break; + + case 150: + dab(in, "stwcx.", 7, 0, 0, 1, 0); + break; + + case 151: + dab(in, "stwx", 7, 0, 0, 0, 0); + break; + + case 181: + dab(in, "stdux", 7, 0, 0, 0, PPCF_64); + break; + + case 183: + dab(in, "stwux", 7, 0, 0, 0, 0); + break; + + case 200: + case (PPCOE >> 1) + 200: + if (in & PPCBMASK) + ill(in); + else + dab(in, "subfze", 6, 0, 1, -1, 0); + break; + + case 202: + case (PPCOE >> 1) + 202: + if (in & PPCBMASK) + ill(in); + else + dab(in, "addze", 6, 0, 1, -1, 0); + break; + + case 210: + msr(in, 1); // mfsr + break; + + case 214: + dab(in, "stdcx.", 7, 0, 0, 1, PPCF_64); + break; + + case 215: + dab(in, "stbx", 7, 0, 0, 0, 0); + break; + + case 232: + case (PPCOE >> 1) + 232: + if (in & PPCBMASK) + ill(in); + else + dab(in, "subfme", 6, 0, 1, -1, 0); + break; + + case 233: + case (PPCOE >> 1) + 233: + dab(in, "mulld", 7, 0, 1, -1, PPCF_64); + break; + + case 234: + case (PPCOE >> 1) + 234: + if (in & PPCBMASK) + ill(in); + else + dab(in, "addme", 6, 0, 1, -1, 0); + break; + + case 235: + case (PPCOE >> 1) + 235: + dab(in, "mullw", 7, 0, 1, -1, 0); + break; + + case 242: + if (in & PPCAMASK) + ill(in); + else + dab(in, "mtsrin", 5, 0, 0, 0, PPCF_SUPER); + break; + + case 246: + if (in & PPCDMASK) + ill(in); + else + dab(in, "dcbtst", 3, 0, 0, 0, 0); + break; + + case 247: + dab(in, "stbux", 7, 0, 0, 0, 0); + break; + + case 266: + case (PPCOE >> 1) + 266: + dab(in, "add", 7, 0, 1, -1, 0); + break; + + case 278: + if (in & PPCDMASK) + ill(in); + else + dab(in, "dcbt", 3, 0, 0, 0, 0); + break; + + case 279: + dab(in, "lhzx", 7, 0, 0, 0, 0); + break; + + case 284: + dab(in, "eqv", 7, 1, 0, -1, 0); + break; + + case 306: + if (in & (PPCDMASK | PPCAMASK)) + ill(in); + else + dab(in, "tlbie", 1, 0, 0, 0, PPCF_SUPER); + break; + + case 310: + dab(in, "eciwx", 7, 0, 0, 0, 0); + break; + + case 311: + dab(in, "lhzux", 7, 0, 0, 0, 0); + break; + + case 316: + dab(in, "xor", 7, 1, 0, -1, 0); + break; + + case 339: + mspr(in, 0); // mfspr + break; + + case 341: + dab(in, "lwax", 7, 0, 0, 0, PPCF_64); + break; + + case 343: + dab(in, "lhax", 7, 0, 0, 0, 0); + break; + + case 370: + nooper(in, "tlbia", PPCF_SUPER); + break; + + case 371: + mtb(in); // mftb + break; + + case 373: + dab(in, "lwaux", 7, 0, 0, 0, PPCF_64); + break; + + case 375: + dab(in, "lhaux", 7, 0, 0, 0, 0); + break; + + case 407: + dab(in, "sthx", 7, 0, 0, 0, 0); + break; + + case 412: + dab(in, "orc", 7, 1, 0, -1, 0); + break; + + case 413: + sradi(in); // sradi + break; + + case 434: + if (in & (PPCDMASK | PPCAMASK)) + ill(in); + else + dab(in, "slbie", 1, 0, 0, 0, PPCF_SUPER | PPCF_64); + break; + + case 438: + dab(in, "ecowx", 7, 0, 0, 0, 0); + break; + + case 439: + dab(in, "sthux", 7, 0, 0, 0, 0); + break; + + case 444: + if (PPCGETD(in) == PPCGETB(in)) + dab(in, "mr", 6, 1, 0, -1, 0); + else + dab(in, "or", 7, 1, 0, -1, 0); + break; + + case 457: + case (PPCOE >> 1) + 457: + dab(in, "divdu", 7, 0, 1, -1, PPCF_64); + break; + + case 459: + case (PPCOE >> 1) + 459: + dab(in, "divwu", 7, 0, 1, -1, 0); + break; + + case 467: + mspr(in, 1); // mtspr + break; + + case 470: + if (in & PPCDMASK) + ill(in); + else + dab(in, "dcbi", 3, 0, 0, 0, 0); + break; + + case 476: + dab(in, "nand", 7, 1, 0, -1, 0); + break; + + case 489: + case (PPCOE >> 1) + 489: + dab(in, "divd", 7, 0, 1, -1, PPCF_64); + break; + + case 491: + case (PPCOE >> 1) + 491: + dab(in, "divw", 7, 0, 1, -1, 0); + break; + + case 498: + nooper(in, "slbia", PPCF_SUPER | PPCF_64); + break; + + case 512: + if (in & 0x007ff801) + { + ill(in); + } + else + { + m_opcode = "mcrxr"; + m_operands = StringFromFormat("cr%d", (int)PPCGETCRD(in)); + } + break; + + case 533: + dab(in, "lswx", 7, 0, 0, 0, 0); + break; + + case 534: + dab(in, "lwbrx", 7, 0, 0, 0, 0); + break; + + case 535: + fdab(in, "lfsx", 7); + break; + + case 536: + dab(in, "srw", 7, 1, 0, -1, 0); + break; + + case 539: + dab(in, "srd", 7, 1, 0, -1, PPCF_64); + break; + + case 566: + nooper(in, "tlbsync", PPCF_SUPER); + break; + + case 567: + fdab(in, "lfsux", 7); + break; + + case 595: + msr(in, 0); // mfsr + break; + + case 597: + rrn(in, "lswi", 0, 0, 0, 0); + break; + + case 598: + nooper(in, "sync", PPCF_SUPER); + break; + + case 599: + fdab(in, "lfdx", 7); + break; + + case 631: + fdab(in, "lfdux", 7); + break; + + case 659: + if (in & PPCAMASK) + ill(in); + else + dab(in, "mfsrin", 5, 0, 0, 0, PPCF_SUPER); + break; + + case 661: + dab(in, "stswx", 7, 0, 0, 0, 0); + break; + + case 662: + dab(in, "stwbrx", 7, 0, 0, 0, 0); + break; + + case 663: + fdab(in, "stfsx", 7); + break; + + case 695: + fdab(in, "stfsux", 7); + break; + + case 725: + rrn(in, "stswi", 0, 0, 0, 0); + break; + + case 727: + fdab(in, "stfdx", 7); + break; + + case 759: + fdab(in, "stfdux", 7); + break; + + case 790: + dab(in, "lhbrx", 7, 0, 0, 0, 0); + break; + + case 792: + dab(in, "sraw", 7, 1, 0, -1, 0); + break; + + case 794: + dab(in, "srad", 7, 1, 0, -1, PPCF_64); + break; + + case 824: + rrn(in, "srawi", 1, 0, -1, 0); + break; + + case 854: + nooper(in, "eieio", PPCF_SUPER); + break; + + case 918: + dab(in, "sthbrx", 7, 0, 0, 0, 0); + break; + + case 922: + if (in & PPCBMASK) + ill(in); + else + dab(in, "extsh", 6, 1, 0, -1, 0); + break; + + case 954: + if (in & PPCBMASK) + ill(in); + else + dab(in, "extsb", 6, 1, 0, -1, 0); + break; + + case 982: + if (in & PPCDMASK) + ill(in); + else + dab(in, "icbi", 3, 0, 0, 0, 0); + break; + + case 983: + fdab(in, "stfiwx", 7); + break; + + case 986: + if (in & PPCBMASK) + ill(in); + else + dab(in, "extsw", 6, 1, 0, -1, PPCF_64); + break; + + case 1014: + if (in & PPCDMASK) + ill(in); + else + dab(in, "dcbz", 3, 0, 0, 0, 0); + break; + + default: + ill(in); + break; + } + break; + + case 32: + case 33: + case 34: + case 35: + case 36: + case 37: + case 38: + case 39: + case 40: + case 41: + case 42: + case 43: + case 44: + case 45: + case 46: + case 47: + ldst(in, ldstnames[PPCGETIDX(in) - 32], 'r', 0); + break; + + case 48: + case 49: + case 50: + case 51: + case 52: + case 53: + case 54: + case 55: + ldst(in, ldstnames[PPCGETIDX(in) - 32], 'f', 0); + break; + + case 58: + switch (in & 3) + { + case 0: + ldst(in&~3, "ld", 'r', PPCF_64); + break; + case 1: + ldst(in&~3, "ldu", 'r', PPCF_64); + break; + case 2: + ldst(in&~3, "lwa", 'r', PPCF_64); + break; + default: + ill(in); + break; + } + break; + + case 59: + switch (in & 0x3e) + { + case 36: + fdabc(in, "divs", 5, 0); + break; + + case 40: + fdabc(in, "subs", 5, 0); + break; + + case 42: + fdabc(in, "adds", 5, 0); + break; + + case 44: + fdabc(in, "sqrts", 2, 0); + break; + + case 48: + fdabc(in, "res", 2, 0); + break; + + case 50: + fdabc(in, "muls", 6, 0); + break; + + case 56: + fdabc(in, "msubs", 7, 0); + break; + + case 58: + fdabc(in, "madds", 7, 0); + break; + + case 60: + fdabc(in, "nmsubs", 7, 0); + break; + + case 62: + fdabc(in, "nmadds", 7, 0); + break; + + default: + ill(in); + break; + } + break; + + case 62: + switch (in & 3) + { + case 0: + ldst(in&~3, "std", 'r', PPCF_64); + break; + case 1: + ldst(in&~3, "stdu", 'r', PPCF_64); + break; + default: + ill(in); + break; + } + break; + + case 63: + if (in & 32) + { + switch (in & 0x1e) + { + case 4: + fdabc(in, "div", 5, 0); + break; + + case 8: + fdabc(in, "sub", 5, 0); + break; + + case 10: + fdabc(in, "add", 5, 0); + break; + + case 12: + fdabc(in, "sqrt", 2, 0); + break; + + case 14: + fdabc(in, "sel", 7, 0); + break; + + case 18: + fdabc(in, "mul", 6, 0); + break; + + case 20: + fdabc(in, "rsqrte", 1, 0); + break; + + case 24: + fdabc(in, "msub", 7, 0); + break; + + case 26: + fdabc(in, "madd", 7, 0); + break; + + case 28: + fdabc(in, "nmsub", 7, 0); + break; + + case 30: + fdabc(in, "nmadd", 7, 0); + break; + + case 52: + m_opcode = "XXX dp 52"; + break; + + default: + ill(in); + break; + } + } + else + { + switch (PPCGETIDX2(in)) + { + case 0: + fcmp(in, 'u'); + break; + + case 12: + fdabc(in, "rsp", 1, 0); + break; + + case 14: + fdabc(in, "ctiw", 1, 0); + break; + + case 15: + fdabc(in, "ctiwz", 1, 0); + break; + + case 32: + fcmp(in, 'o'); + break; + + case 38: + mtfsb(in, 1); + break; + + case 40: + fdabc(in, "neg", 10, 0); + break; + + case 64: + mcrf(in, 's'); // mcrfs + break; + + case 70: + mtfsb(in, 0); + break; + + case 72: + fmr(in); + break; + + case 134: + if ((in & 0x006f0800) == 0) + { + m_opcode = StringFromFormat("mtfsfi%s", rcsel[in & 1]); + m_operands = StringFromFormat("cr%d,%d", (int)PPCGETCRD(in), (int)(in & 0xf000) >> 12); + } + else + { + ill(in); + } + break; + + case 136: + fdabc(in, "nabs", 10, 0); + break; + + case 264: + fdabc(in, "abs", 10, 0); + break; + + case 583: + if (in & (PPCAMASK | PPCBMASK)) + ill(in); + else + dab(in, "mffs", 4, 0, 0, -1, 0); + break; + + case 711: + if ((in & 0x02010000) == 0) + { + m_opcode = StringFromFormat("mtfsf%s", rcsel[in & 1]); + m_operands = StringFromFormat("0x%x,%u", (unsigned int)(in & 0x01fe) >> 17, (int)PPCGETB(in)); + } + else + { + ill(in); + } + break; + + case 814: + fdabc(in, "fctid", 10, PPCF_64); + break; + + case 815: + fdabc(in, "fctidz", 10, PPCF_64); + break; + + case 846: + fdabc(in, "fcfid", 10, PPCF_64); + break; + + default: + ill(in); + break; + } + } + break; + + default: + ill(in); + break; + } + return (m_instr + 1); +} + +// simplified interface +std::string GekkoDisassembler::Disassemble(u32 opcode, u32 current_instruction_address, bool big_endian) +{ + u32 opc = opcode; + u32 addr = current_instruction_address; + + m_instr = (u32*)&opc; + m_iaddr = (u32*)&addr; + + DoDisassembly(big_endian); + + return m_opcode.append("\t").append(m_operands); +} + +static const char* gprnames[] = +{ + " r0", " r1", " r2", " r3", " r4", " r5", " r6", " r7", + " r8", " r9", "r10", "r11", "r12", "r13", "r14", "r15", + "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", + "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31" +}; + +const char* GekkoDisassembler::GetGPRName(u32 index) +{ + if (index < 32) + return gprnames[index]; + + return 0; +} + +static const char* fprnames[] = +{ + " f0", " f1", " f2", " f3", " f4", " f5", " f6", " f7", + " f8", " f9", "f10", "f11", "f12", "f13", "f14", "f15", + "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", + "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31" +}; + +const char* GekkoDisassembler::GetFPRName(u32 index) +{ + if (index < 32) + return fprnames[index]; + + return 0; +} diff --git a/Source/Core/Common/GekkoDisassembler.h b/Source/Core/Common/GekkoDisassembler.h new file mode 100644 index 0000000000..113c843baa --- /dev/null +++ b/Source/Core/Common/GekkoDisassembler.h @@ -0,0 +1,152 @@ +/* $VER: ppc_disasm.h V1.6 (09.12.2011) + * + * Disassembler module for the PowerPC microprocessor family + * Copyright (c) 1998-2001,2009,2011 Frank Wille + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +// Modified for use with Dolphin + +#pragma once + +#include +#include + +#include "Common/CommonTypes.h" +#include "Common/StringUtil.h" + +class GekkoDisassembler final +{ +public: + static std::string Disassemble(u32 opcode, u32 current_instruction_address, bool big_endian = true); + static const char* GetGPRName(u32 index); + static const char* GetFPRName(u32 index); + +private: + GekkoDisassembler() = delete; + + static void ill(u32 in); + static std::string imm(u32 in, int uimm, int type, bool hex); + + static std::string ra_rb(u32 in); + static std::string rd_ra_rb(u32 in, int mask); + static std::string fd_ra_rb(u32 in, int mask); + + static void trapi(u32 in, unsigned char dmode); + static void cmpi(u32 in, int uimm); + static void addi(u32 in, const std::string& ext); + static size_t branch(u32 in, const char* bname, int aform, int bdisp); + static void bc(u32 in); + static void bli(u32 in); + static void mcrf(u32 in, char c); + static void crop(u32 in, const char* n1, const char* n2); + static void nooper(u32 in, const char* name, unsigned char dmode); + static void rlw(u32 in, const char* name, int i); + static void ori(u32 in, const char* name); + static void rld(u32 in, const char* name, int i); + static void cmp(u32 in); + static void trap(u32 in, unsigned char dmode); + static void dab(u32 in, const char* name, int mask, int smode, int chkoe, int chkrc, unsigned char dmode); + static void rrn(u32 in, const char* name, int smode, int chkoe, int chkrc, unsigned char dmode); + static void mtcr(u32 in); + static void msr(u32 in, int smode); + static void mspr(u32 in, int smode); + static void mtb(u32 in); + static void sradi(u32 in); + static void ldst(u32 in, const char* name, char reg, unsigned char dmode); + static void fdabc(u32 in, const char* name, int mask, unsigned char dmode); + static void fmr(u32 in); + static void fdab(u32 in, const char* name, int mask); + static void fcmp(u32 in, char c); + static void mtfsb(u32 in, int n); + static void ps(u32 inst); + static void ps_mem(u32 inst); + + static u32* DoDisassembly(bool big_endian); + + static u32 HelperRotateMask(int r, int mb, int me) + { + //first make 001111111111111 part + unsigned int begin = 0xFFFFFFFF >> mb; + //then make 000000000001111 part, which is used to flip the bits of the first one + unsigned int end = me < 31 ? (0xFFFFFFFF >> (me + 1)) : 0; + //do the bitflip + unsigned int mask = begin ^ end; + //and invert if backwards + if (me < mb) + mask = ~mask; + //rotate the mask so it can be applied to source reg + //return _rotl(mask, 32 - r); + return (mask << (32 - r)) | (mask >> r); + } + + static std::string ldst_offs(u32 val) + { + if (val == 0) + { + return "0"; + } + else + { + if (val & 0x8000) + { + return StringFromFormat("-0x%.4X", ((~val) & 0xffff) + 1); + } + else + { + return StringFromFormat("0x%.4X", val); + } + } + } + + static int SEX12(u32 x) + { + return x & 0x800 ? (x | 0xFFFFF000) : x; + } + + enum InstructionType + { + PPCINSTR_OTHER = 0, // No additional info for other instr. + PPCINSTR_BRANCH = 1, // Branch dest. = PC+displacement + PPCINSTR_LDST = 2, // Load/store instruction: displ(sreg) + PPCINSTR_IMM = 3, // 16-bit immediate val. in displacement + }; + + enum Flags + { + PPCF_ILLEGAL = (1 << 0), // Illegal PowerPC instruction + PPCF_UNSIGNED = (1 << 1), // Unsigned immediate instruction + PPCF_SUPER = (1 << 2), // Supervisor level instruction + PPCF_64 = (1 << 3), // 64-bit only instruction + }; + + static u32* m_instr; // Pointer to instruction to disassemble + static u32* m_iaddr; // Instruction.address., usually the same as instr + static std::string m_opcode; // Buffer for opcode, min. 10 chars. + static std::string m_operands; // Operand buffer, min. 24 chars. + static unsigned char m_type; // Type of instruction, see below + static unsigned char m_flags; // Additional flags + static unsigned short m_sreg; // Register in load/store instructions + static u32 m_displacement; // Branch- or load/store displacement +}; diff --git a/Source/Core/Core/Debugger/PPCDebugInterface.cpp b/Source/Core/Core/Debugger/PPCDebugInterface.cpp index d07d49c097..ed46e18db3 100644 --- a/Source/Core/Core/Debugger/PPCDebugInterface.cpp +++ b/Source/Core/Core/Debugger/PPCDebugInterface.cpp @@ -2,7 +2,9 @@ // Licensed under GPLv2 // Refer to the license.txt file included. -#include "PowerPCDisasm.h" +#include + +#include "Common/GekkoDisassembler.h" #include "Core/Core.h" #include "Core/Host.h" @@ -15,31 +17,37 @@ #include "Core/PowerPC/PPCSymbolDB.h" #include "Core/PowerPC/JitCommon/JitBase.h" -void PPCDebugInterface::Disassemble(unsigned int address, char *dest, int max_size) +std::string PPCDebugInterface::Disassemble(unsigned int address) { // Memory::ReadUnchecked_U32 seemed to crash on shutdown - if (PowerPC::GetState() == PowerPC::CPU_POWERDOWN) return; + if (PowerPC::GetState() == PowerPC::CPU_POWERDOWN) + return ""; if (Core::GetState() != Core::CORE_UNINITIALIZED) { if (Memory::IsRAMAddress(address, true, true)) { u32 op = Memory::Read_Instruction(address); - DisassembleGekko(op, address, dest, max_size); + std::string disasm = GekkoDisassembler::Disassemble(op, address); + UGeckoInstruction inst; inst.hex = Memory::ReadUnchecked_U32(address); - if (inst.OPCD == 1) { - strcat(dest, " (hle)"); + + if (inst.OPCD == 1) + { + disasm += " (hle)"; } + + return disasm; } else { - strcpy(dest, "(No RAM here)"); + return "(No RAM here)"; } } else { - strcpy(dest, ""); + return ""; } } diff --git a/Source/Core/Core/Debugger/PPCDebugInterface.h b/Source/Core/Core/Debugger/PPCDebugInterface.h index ba362694f1..c80416d58b 100644 --- a/Source/Core/Core/Debugger/PPCDebugInterface.h +++ b/Source/Core/Core/Debugger/PPCDebugInterface.h @@ -14,7 +14,7 @@ class PPCDebugInterface final : public DebugInterface { public: PPCDebugInterface(){} - virtual void Disassemble(unsigned int address, char *dest, int max_size) override; + virtual std::string Disassemble(unsigned int address) override; virtual void GetRawMemoryString(int memory, unsigned int address, char *dest, int max_size) override; virtual int GetInstructionSize(int /*instruction*/) override {return 4;} virtual bool IsAlive() override; diff --git a/Source/Core/Core/HW/DSPLLE/DSPDebugInterface.cpp b/Source/Core/Core/HW/DSPLLE/DSPDebugInterface.cpp index 4520ddf80a..3ccd46a589 100644 --- a/Source/Core/Core/HW/DSPLLE/DSPDebugInterface.cpp +++ b/Source/Core/Core/HW/DSPLLE/DSPDebugInterface.cpp @@ -2,17 +2,18 @@ // Licensed under GPLv2 // Refer to the license.txt file included. +#include + #include "Core/DSP/DSPCore.h" #include "Core/DSP/DSPDisassembler.h" #include "Core/DSP/DSPMemoryMap.h" #include "Core/HW/DSPLLE/DSPDebugInterface.h" #include "Core/HW/DSPLLE/DSPSymbols.h" -void DSPDebugInterface::Disassemble(unsigned int address, char *dest, int max_size) +std::string DSPDebugInterface::Disassemble(unsigned int address) { // we'll treat addresses as line numbers. - strncpy(dest, DSPSymbols::GetLineText(address), max_size); - dest[max_size-1] = 0; + return DSPSymbols::GetLineText(address); } void DSPDebugInterface::GetRawMemoryString(int memory, unsigned int address, char *dest, int max_size) diff --git a/Source/Core/Core/HW/DSPLLE/DSPDebugInterface.h b/Source/Core/Core/HW/DSPLLE/DSPDebugInterface.h index f4a2494481..2342b940f0 100644 --- a/Source/Core/Core/HW/DSPLLE/DSPDebugInterface.h +++ b/Source/Core/Core/HW/DSPLLE/DSPDebugInterface.h @@ -5,7 +5,6 @@ #pragma once #include -#include #include "Common/Common.h" #include "Common/DebugInterface.h" @@ -14,7 +13,7 @@ class DSPDebugInterface final : public DebugInterface { public: DSPDebugInterface(){} - virtual void Disassemble(unsigned int address, char *dest, int max_size) override; + virtual std::string Disassemble(unsigned int address) override; virtual void GetRawMemoryString(int memory, unsigned int address, char *dest, int max_size) override; virtual int GetInstructionSize(int instruction) override { return 1; } virtual bool IsAlive() override; diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter.cpp index ff3bd8c4f8..070c369394 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter.cpp +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter.cpp @@ -5,8 +5,7 @@ #include #include -#include "PowerPCDisasm.h" - +#include "Common/GekkoDisassembler.h" #include "Common/StringUtil.h" #include "Core/Host.h" #include "Core/Debugger/Debugger_SymbolMap.h" @@ -82,10 +81,8 @@ static void Trace(UGeckoInstruction& instCode) fregs += StringFromFormat("f%02d: %08" PRIx64 " %08" PRIx64 " ", i, PowerPC::ppcState.ps[i][0], PowerPC::ppcState.ps[i][1]); } - char ppcInst[256]; - DisassembleGekko(instCode.hex, PC, ppcInst, 256); - - DEBUG_LOG(POWERPC, "INTER PC: %08x SRR0: %08x SRR1: %08x CRval: %016lx FPSCR: %08x MSR: %08x LR: %08x %s %08x %s", PC, SRR0, SRR1, PowerPC::ppcState.cr_val[0], PowerPC::ppcState.fpscr, PowerPC::ppcState.msr, PowerPC::ppcState.spr[8], regs.c_str(), instCode.hex, ppcInst); + std::string ppc_inst = GekkoDisassembler::Disassemble(instCode.hex, PC); + DEBUG_LOG(POWERPC, "INTER PC: %08x SRR0: %08x SRR1: %08x CRval: %016lx FPSCR: %08x MSR: %08x LR: %08x %s %08x %s", PC, SRR0, SRR1, PowerPC::ppcState.cr_val[0], PowerPC::ppcState.fpscr, PowerPC::ppcState.msr, PowerPC::ppcState.spr[8], regs.c_str(), instCode.hex, ppc_inst.c_str()); } int Interpreter::SingleStepInner(void) @@ -312,9 +309,8 @@ void Interpreter::unknown_instruction(UGeckoInstruction _inst) { if (_inst.hex != 0) { - char disasm[256]; - DisassembleGekko(Memory::ReadUnchecked_U32(last_pc), last_pc, disasm, 256); - NOTICE_LOG(POWERPC, "Last PC = %08x : %s", last_pc, disasm); + std::string disasm = GekkoDisassembler::Disassemble(Memory::ReadUnchecked_U32(last_pc), last_pc); + NOTICE_LOG(POWERPC, "Last PC = %08x : %s", last_pc, disasm.c_str()); Dolphin_Debugger::PrintCallstack(); _dbg_assert_msg_(POWERPC, 0, "\nIntCPU: Unknown instruction %08x at PC = %08x last_PC = %08x LR = %08x\n", _inst.hex, PC, last_pc, LR); } diff --git a/Source/Core/Core/PowerPC/Jit64/Jit.cpp b/Source/Core/Core/PowerPC/Jit64/Jit.cpp index 405d183a80..11a6e39b0c 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit.cpp @@ -21,7 +21,7 @@ #include "Core/PowerPC/Jit64/JitAsm.h" #include "Core/PowerPC/Jit64/JitRegCache.h" #if defined(_DEBUG) || defined(DEBUGFAST) -#include "PowerPCDisasm.h" +#include "Common/GekkoDisassembler.h" #endif using namespace Gen; @@ -613,9 +613,8 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc #if defined(_DEBUG) || defined(DEBUGFAST) if (gpr.SanityCheck() || fpr.SanityCheck()) { - char ppcInst[256]; - DisassembleGekko(ops[i].inst.hex, em_address, ppcInst, 256); - //NOTICE_LOG(DYNA_REC, "Unflushed register: %s", ppcInst); + std::string ppc_inst = GekkoDisassembler::Disassemble(ops[i].inst.hex, em_address); + //NOTICE_LOG(DYNA_REC, "Unflushed register: %s", ppc_inst.c_str()); } #endif if (js.skipnext) { diff --git a/Source/Core/Core/PowerPC/JitCommon/JitBase.cpp b/Source/Core/Core/PowerPC/JitCommon/JitBase.cpp index 440d507ace..097895ef85 100644 --- a/Source/Core/Core/PowerPC/JitCommon/JitBase.cpp +++ b/Source/Core/Core/PowerPC/JitCommon/JitBase.cpp @@ -6,8 +6,8 @@ #include #include "disasm.h" -#include "PowerPCDisasm.h" +#include "Common/GekkoDisassembler.h" #include "Common/StringUtil.h" #include "Core/PowerPC/JitCommon/JitBase.h" @@ -29,15 +29,11 @@ u32 Helper_Mask(u8 mb, u8 me) void LogGeneratedX86(int size, PPCAnalyst::CodeBuffer *code_buffer, const u8 *normalEntry, JitBlock *b) { - std::string ppcdisasm; - for (int i = 0; i < size; i++) { - char temp[256] = ""; const PPCAnalyst::CodeOp &op = code_buffer->codebuffer[i]; - DisassembleGekko(op.inst.hex, op.address, temp, 256); - ppcdisasm += StringFromFormat("%08x %s", op.address, temp); - DEBUG_LOG(DYNA_REC, "IR_X86 PPC: %s\n", ppcdisasm.c_str()); + std::string temp = StringFromFormat("%08x %s", op.address, GekkoDisassembler::Disassemble(op.inst.hex, op.address).c_str()); + DEBUG_LOG(DYNA_REC, "IR_X86 PPC: %s\n", temp.c_str()); } disassembler x64disasm; diff --git a/Source/Core/Core/PowerPC/PPCSymbolDB.cpp b/Source/Core/Core/PowerPC/PPCSymbolDB.cpp index 982b246f83..a63c586d97 100644 --- a/Source/Core/Core/PowerPC/PPCSymbolDB.cpp +++ b/Source/Core/Core/PowerPC/PPCSymbolDB.cpp @@ -334,9 +334,9 @@ bool PPCSymbolDB::SaveMap(const std::string& filename, bool WithCodes) const for (int i = 0; i < space; i += 4) { int Address = LastAddress + i; - char disasm[256]; - debugger->Disassemble(Address, disasm, 256); - fprintf(f.GetHandle(),"%08x %i %20s %s\n", Address, 0, TempSym.c_str(), disasm); + + std::string disasm = debugger->Disassemble(Address); + fprintf(f.GetHandle(),"%08x %i %20s %s\n", Address, 0, TempSym.c_str(), disasm.c_str()); } // Write a blank line after each block fprintf(f.GetHandle(), "\n"); diff --git a/Source/Core/DolphinWX/Debugger/CodeView.cpp b/Source/Core/DolphinWX/Debugger/CodeView.cpp index 9d7b869518..7b18a5e9d8 100644 --- a/Source/Core/DolphinWX/Debugger/CodeView.cpp +++ b/Source/Core/DolphinWX/Debugger/CodeView.cpp @@ -2,6 +2,7 @@ // Licensed under GPLv2 // Refer to the license.txt file included. +#include #include #include #include @@ -189,15 +190,15 @@ void CCodeView::OnMouseUpL(wxMouseEvent& event) u32 CCodeView::AddrToBranch(u32 addr) { - char disasm[256]; - m_debugger->Disassemble(addr, disasm, 256); - const char *mojs = strstr(disasm, "->0x"); - if (mojs) + std::string disasm = m_debugger->Disassemble(addr); + size_t pos = disasm.find("->0x"); + + if (pos != std::string::npos) { - u32 dest; - sscanf(mojs+4,"%08x", &dest); - return dest; + std::string hex = disasm.substr(pos + 2); + return std::stoul(hex, nullptr, 16); } + return 0; } @@ -253,16 +254,14 @@ void CCodeView::OnPopupMenu(wxCommandEvent& event) case IDM_COPYCODE: { - char disasm[256]; - m_debugger->Disassemble(m_selection, disasm, 256); + std::string disasm = m_debugger->Disassemble(m_selection); wxTheClipboard->SetData(new wxTextDataObject(StrToWxStr(disasm))); } break; case IDM_COPYHEX: { - char temp[24]; - sprintf(temp, "%08x", m_debugger->ReadInstruction(m_selection)); + std::string temp = StringFromFormat("%08x", m_debugger->ReadInstruction(m_selection)); wxTheClipboard->SetData(new wxTextDataObject(StrToWxStr(temp))); } break; @@ -280,9 +279,8 @@ void CCodeView::OnPopupMenu(wxCommandEvent& event) u32 end = start + symbol->size; for (u32 addr = start; addr != end; addr += 4) { - char disasm[256]; - m_debugger->Disassemble(addr, disasm, 256); - text = text + StringFromFormat("%08x: ", addr) + disasm + "\r\n"; + std::string disasm = m_debugger->Disassemble(addr); + text += StringFromFormat("%08x: ", addr) + disasm + "\r\n"; } wxTheClipboard->SetData(new wxTextDataObject(StrToWxStr(text))); } @@ -478,65 +476,51 @@ void CCodeView::OnPaint(wxPaintEvent& event) // If running if (m_debugger->IsAlive()) { - char dis[256]; - m_debugger->Disassemble(address, dis, 256); - char* dis2 = strchr(dis, '\t'); - char desc[256] = ""; + std::vector dis; + SplitString(m_debugger->Disassemble(address), '\t', dis); - // If we have a code - if (dis2) + static const size_t VALID_BRANCH_LENGTH = 10; + const std::string& opcode = dis[0]; + const std::string& operands = dis[1]; + std::string desc; + + // look for hex strings to decode branches + std::string hex_str; + size_t pos = operands.find("0x8"); + if (pos != std::string::npos) { - *dis2 = 0; - dis2++; - // look for hex strings to decode branches - const char* mojs = strstr(dis2, "0x8"); - if (mojs) - { - for (int k = 0; k < 8; k++) - { - bool found = false; - for (int j = 0; j < 22; j++) - { - if (mojs[k + 2] == "0123456789ABCDEFabcdef"[j]) - found = true; - } - if (!found) - { - mojs = nullptr; - break; - } - } - } - if (mojs) - { - int offs; - sscanf(mojs + 2, "%08x", &offs); - branches[numBranches].src = rowY1 + m_rowHeight / 2; - branches[numBranches].srcAddr = address / m_align; - branches[numBranches++].dst = (int)(rowY1 + ((s64)(u32)offs - (s64)(u32)address) * m_rowHeight / m_align + m_rowHeight / 2); - sprintf(desc, "-->%s", m_debugger->GetDescription(offs).c_str()); - dc.SetTextForeground(wxTheColourDatabase->Find("PURPLE")); // the -> arrow illustrations are purple - } - else - { - dc.SetTextForeground(*wxBLACK); - } - - dc.DrawText(StrToWxStr(dis2), 17 + 17*charWidth, rowY1); - // ------------ + hex_str = operands.substr(pos); } + if (hex_str.length() == VALID_BRANCH_LENGTH) + { + u32 offs = std::stoul(hex_str, nullptr, 16); + + branches[numBranches].src = rowY1 + m_rowHeight / 2; + branches[numBranches].srcAddr = address / m_align; + branches[numBranches++].dst = (int)(rowY1 + ((s64)(u32)offs - (s64)(u32)address) * m_rowHeight / m_align + m_rowHeight / 2); + desc = StringFromFormat("-->%s", m_debugger->GetDescription(offs).c_str()); + dc.SetTextForeground(wxTheColourDatabase->Find("PURPLE")); // the -> arrow illustrations are purple + } + else + { + dc.SetTextForeground(*wxBLACK); + } + + dc.DrawText(StrToWxStr(operands), 17 + 17*charWidth, rowY1); + // ------------ + // Show blr as its' own color - if (strcmp(dis, "blr")) + if (opcode == "blr") dc.SetTextForeground(wxTheColourDatabase->Find("DARK GREEN")); else dc.SetTextForeground(wxTheColourDatabase->Find("VIOLET")); - dc.DrawText(StrToWxStr(dis), 17 + (m_plain ? 1*charWidth : 9*charWidth), rowY1); + dc.DrawText(StrToWxStr(opcode), 17 + (m_plain ? 1*charWidth : 9*charWidth), rowY1); - if (desc[0] == 0) + if (desc.empty()) { - strcpy(desc, m_debugger->GetDescription(address).c_str()); + desc = m_debugger->GetDescription(address); } if (!m_plain) @@ -545,7 +529,7 @@ void CCodeView::OnPaint(wxPaintEvent& event) //char temp[256]; //UnDecorateSymbolName(desc,temp,255,UNDNAME_COMPLETE); - if (strlen(desc)) + if (!desc.empty()) { dc.DrawText(StrToWxStr(desc), 17 + 35 * charWidth, rowY1); } diff --git a/Source/Core/DolphinWX/Debugger/JitWindow.cpp b/Source/Core/DolphinWX/Debugger/JitWindow.cpp index dc10d4ac5c..0ef374ddbe 100644 --- a/Source/Core/DolphinWX/Debugger/JitWindow.cpp +++ b/Source/Core/DolphinWX/Debugger/JitWindow.cpp @@ -5,7 +5,6 @@ #include #include #include // Bochs -#include // Bochs #include #include #include @@ -22,6 +21,7 @@ #include #include "Common/Common.h" +#include "Common/GekkoDisassembler.h" #include "Common/StringUtil.h" #include "Core/PowerPC/Gekko.h" #include "Core/PowerPC/PPCAnalyst.h" @@ -161,9 +161,8 @@ void CJitWindow::Compare(u32 em_address) for (u32 i = 0; i < code_block.m_num_instructions; i++) { const PPCAnalyst::CodeOp &op = code_buffer.codebuffer[i]; - char temp[256]; - DisassembleGekko(op.inst.hex, op.address, temp, 256); - sptr += sprintf(sptr, "%08x %s\n", op.address, temp); + std::string temp = GekkoDisassembler::Disassemble(op.inst.hex, op.address); + sptr += sprintf(sptr, "%08x %s\n", op.address, temp.c_str()); } // Add stats to the end of the ppc box since it's generally the shortest. diff --git a/Source/Core/DolphinWX/Debugger/RegisterView.cpp b/Source/Core/DolphinWX/Debugger/RegisterView.cpp index a2338d5bd7..25635db528 100644 --- a/Source/Core/DolphinWX/Debugger/RegisterView.cpp +++ b/Source/Core/DolphinWX/Debugger/RegisterView.cpp @@ -10,6 +10,7 @@ #include #include "Common/CommonTypes.h" +#include "Common/GekkoDisassembler.h" #include "Common/StringUtil.h" #include "Core/HW/ProcessorInterface.h" #include "Core/PowerPC/Gekko.h" @@ -22,9 +23,6 @@ class wxWindow; // F-zero 80005e60 wtf?? -extern const char* GetGPRName(unsigned int index); -extern const char* GetFPRName(unsigned int index); - static const char *special_reg_names[] = { "PC", "LR", "CTR", "CR", "FPSCR", "MSR", "SRR0", "SRR1", "Exceptions", "Int Mask", "Int Cause", }; @@ -54,9 +52,9 @@ wxString CRegTable::GetValue(int row, int col) { switch (col) { - case 0: return StrToWxStr(GetGPRName(row)); + case 0: return StrToWxStr(GekkoDisassembler::GetGPRName(row)); case 1: return wxString::Format("%08x", GPR(row)); - case 2: return StrToWxStr(GetFPRName(row)); + case 2: return StrToWxStr(GekkoDisassembler::GetFPRName(row)); case 3: return wxString::Format("%016llx", riPS0(row)); case 4: return wxString::Format("%016llx", riPS1(row)); default: return wxEmptyString;