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;