1 // Copyright (c) 2012- PPSSPP Project. 2 3 // This program is free software: you can redistribute it and/or modify 4 // it under the terms of the GNU General Public License as published by 5 // the Free Software Foundation, version 2.0 or later versions. 6 7 // This program is distributed in the hope that it will be useful, 8 // but WITHOUT ANY WARRANTY; without even the implied warranty of 9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 // GNU General Public License 2.0 for more details. 11 12 // A copy of the GPL 2.0 should have been included with the program. 13 // If not, see http://www.gnu.org/licenses/ 14 15 // Official git repository and contact information can be found at 16 // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. 17 18 #include <cstring> 19 #include "Core/HLE/HLE.h" 20 #include "Core/MemMap.h" 21 #include "Core/MIPS/MIPS.h" 22 #include "Core/MIPS/MIPSCodeUtils.h" 23 #include "Core/MIPS/MIPSDis.h" 24 #include "Core/MIPS/MIPSTables.h" 25 #include "Core/MIPS/MIPSDebugInterface.h" 26 27 #define _RS ((op>>21) & 0x1F) 28 #define _RT ((op>>16) & 0x1F) 29 #define _RD ((op>>11) & 0x1F) 30 #define _FS ((op>>11) & 0x1F) 31 #define _FT ((op>>16) & 0x1F) 32 #define _FD ((op>>6 ) & 0x1F) 33 #define _POS ((op>>6 ) & 0x1F) 34 #define _SIZE ((op>>11) & 0x1F) 35 36 #define RN(i) currentDebugMIPS->GetRegName(0,i) 37 #define FN(i) currentDebugMIPS->GetRegName(1,i) 38 //#define VN(i) currentMIPS->GetRegName(2,i) 39 40 u32 disPC; 41 42 namespace MIPSDis 43 { 44 // One shot, not re-entrant. SignedHex(int i)45 const char *SignedHex(int i) 46 { 47 static char temp[32]; 48 int offset = 0; 49 if (i < 0) 50 { 51 temp[0] = '-'; 52 offset = 1; 53 i = -i; 54 } 55 56 sprintf(&temp[offset], "0x%X", i); 57 return temp; 58 } 59 Dis_Generic(MIPSOpcode op,char * out)60 void Dis_Generic(MIPSOpcode op, char *out) 61 { 62 sprintf(out, "%s\t --- unknown ---", MIPSGetName(op)); 63 } 64 Dis_Cache(MIPSOpcode op,char * out)65 void Dis_Cache(MIPSOpcode op, char *out) 66 { 67 int imm = (s16)(op & 0xFFFF); 68 int rs = _RS; 69 int func = (op >> 16) & 0x1F; 70 sprintf(out, "%s\tfunc=%i, %s(%s)", MIPSGetName(op), func, RN(rs), SignedHex(imm)); 71 } 72 Dis_mxc1(MIPSOpcode op,char * out)73 void Dis_mxc1(MIPSOpcode op, char *out) 74 { 75 int fs = _FS; 76 int rt = _RT; 77 const char *name = MIPSGetName(op); 78 sprintf(out, "%s\t%s, %s",name,RN(rt),FN(fs)); 79 } 80 Dis_FPU3op(MIPSOpcode op,char * out)81 void Dis_FPU3op(MIPSOpcode op, char *out) 82 { 83 int ft = _FT; 84 int fs = _FS; 85 int fd = _FD; 86 const char *name = MIPSGetName(op); 87 sprintf(out, "%s\t%s, %s, %s",name,FN(fd),FN(fs),FN(ft)); 88 } 89 Dis_FPU2op(MIPSOpcode op,char * out)90 void Dis_FPU2op(MIPSOpcode op, char *out) 91 { 92 int fs = _FS; 93 int fd = _FD; 94 const char *name = MIPSGetName(op); 95 sprintf(out, "%s\t%s, %s",name,FN(fd),FN(fs)); 96 } 97 Dis_FPULS(MIPSOpcode op,char * out)98 void Dis_FPULS(MIPSOpcode op, char *out) 99 { 100 int offset = (signed short)(op&0xFFFF); 101 int ft = _FT; 102 int rs = _RS; 103 const char *name = MIPSGetName(op); 104 sprintf(out, "%s\t%s, %s(%s)",name,FN(ft),SignedHex(offset),RN(rs)); 105 } Dis_FPUComp(MIPSOpcode op,char * out)106 void Dis_FPUComp(MIPSOpcode op, char *out) 107 { 108 int fs = _FS; 109 int ft = _FT; 110 const char *name = MIPSGetName(op); 111 sprintf(out, "%s\t%s, %s",name,FN(fs),FN(ft)); 112 } 113 Dis_FPUBranch(MIPSOpcode op,char * out)114 void Dis_FPUBranch(MIPSOpcode op, char *out) 115 { 116 u32 off = disPC; 117 int imm = (signed short)(op&0xFFFF)<<2; 118 off += imm + 4; 119 const char *name = MIPSGetName(op); 120 sprintf(out, "%s\t->$%08x",name,off); 121 } 122 Dis_RelBranch(MIPSOpcode op,char * out)123 void Dis_RelBranch(MIPSOpcode op, char *out) 124 { 125 u32 off = disPC; 126 int imm = (signed short)(op&0xFFFF)<<2; 127 int rs = _RS; 128 off += imm + 4; 129 130 const char *name = MIPSGetName(op); 131 sprintf(out, "%s\t%s, ->$%08x", name, RN(rs), off); 132 } 133 Dis_Syscall(MIPSOpcode op,char * out)134 void Dis_Syscall(MIPSOpcode op, char *out) 135 { 136 u32 callno = (op>>6) & 0xFFFFF; //20 bits 137 int funcnum = callno & 0xFFF; 138 int modulenum = (callno & 0xFF000) >> 12; 139 sprintf(out, "syscall\t %s",/*PSPHLE::GetModuleName(modulenum),*/GetFuncName(modulenum, funcnum)); 140 } 141 Dis_ToHiloTransfer(MIPSOpcode op,char * out)142 void Dis_ToHiloTransfer(MIPSOpcode op, char *out) 143 { 144 int rs = _RS; 145 const char *name = MIPSGetName(op); 146 sprintf(out, "%s\t%s",name,RN(rs)); 147 } Dis_FromHiloTransfer(MIPSOpcode op,char * out)148 void Dis_FromHiloTransfer(MIPSOpcode op, char *out) 149 { 150 int rd = _RD; 151 const char *name = MIPSGetName(op); 152 sprintf(out, "%s\t%s",name,RN(rd)); 153 } 154 Dis_RelBranch2(MIPSOpcode op,char * out)155 void Dis_RelBranch2(MIPSOpcode op, char *out) 156 { 157 u32 off = disPC; 158 int imm = (signed short)(op&0xFFFF)<<2; 159 int rt = _RT; 160 int rs = _RS; 161 off += imm + 4; 162 163 const char *name = MIPSGetName(op); 164 int o = op>>26; 165 if (o==4 && rs == rt)//beq 166 sprintf(out, "b\t->$%08x", off); 167 else if (o==20 && rs == rt)//beql 168 sprintf(out, "bl\t->$%08x", off); 169 else 170 sprintf(out, "%s\t%s, %s, ->$%08x", name, RN(rs), RN(rt), off); 171 } 172 Dis_IType(MIPSOpcode op,char * out)173 void Dis_IType(MIPSOpcode op, char *out) 174 { 175 u32 uimm = op & 0xFFFF; 176 u32 suimm = SignExtend16ToU32(op); 177 s32 simm = SignExtend16ToS32(op); 178 179 int rt = _RT; 180 int rs = _RS; 181 const char *name = MIPSGetName(op); 182 switch (op >> 26) 183 { 184 case 8: //addi 185 case 9: //addiu 186 case 10: //slti 187 sprintf(out, "%s\t%s, %s, %s",name,RN(rt),RN(rs),SignedHex(simm)); 188 break; 189 case 11: //sltiu 190 sprintf(out, "%s\t%s, %s, 0x%X",name,RN(rt),RN(rs),suimm); 191 break; 192 default: 193 sprintf(out, "%s\t%s, %s, 0x%X",name,RN(rt),RN(rs),uimm); 194 break; 195 } 196 } Dis_ori(MIPSOpcode op,char * out)197 void Dis_ori(MIPSOpcode op, char *out) 198 { 199 u32 uimm = (u32)(u16)(op & 0xFFFF); 200 int rt = _RT; 201 int rs = _RS; 202 const char *name = MIPSGetName(op); 203 if (rs == 0) 204 sprintf(out, "li\t%s, 0x%X",RN(rt),uimm); 205 else 206 sprintf(out, "%s\t%s, %s, 0x%X",name,RN(rt),RN(rs),uimm); 207 } 208 Dis_IType1(MIPSOpcode op,char * out)209 void Dis_IType1(MIPSOpcode op, char *out) 210 { 211 u32 uimm = (u32)(u16)(op & 0xFFFF); 212 int rt = _RT; 213 const char *name = MIPSGetName(op); 214 sprintf(out, "%s\t%s, 0x%X",name,RN(rt),uimm); 215 } 216 Dis_addi(MIPSOpcode op,char * out)217 void Dis_addi(MIPSOpcode op, char *out) 218 { 219 int imm = (signed short)(op&0xFFFF); 220 int rt = _RT; 221 int rs = _RS; 222 if (rs == 0) 223 sprintf(out, "li\t%s, %s",RN(rt),SignedHex(imm)); 224 else 225 Dis_IType(op,out); 226 } 227 Dis_ITypeMem(MIPSOpcode op,char * out)228 void Dis_ITypeMem(MIPSOpcode op, char *out) 229 { 230 int imm = (signed short)(op&0xFFFF); 231 int rt = _RT; 232 int rs = _RS; 233 const char *name = MIPSGetName(op); 234 sprintf(out, "%s\t%s, %s(%s)",name,RN(rt),SignedHex(imm),RN(rs)); 235 } 236 Dis_RType2(MIPSOpcode op,char * out)237 void Dis_RType2(MIPSOpcode op, char *out) 238 { 239 int rs = _RS; 240 int rd = _RD; 241 const char *name = MIPSGetName(op); 242 sprintf(out, "%s\t%s, %s",name,RN(rd),RN(rs)); 243 } 244 Dis_RType3(MIPSOpcode op,char * out)245 void Dis_RType3(MIPSOpcode op, char *out) 246 { 247 int rt = _RT; 248 int rs = _RS; 249 int rd = _RD; 250 const char *name = MIPSGetName(op); 251 sprintf(out, "%s\t%s, %s, %s",name,RN(rd),RN(rs),RN(rt)); 252 } 253 Dis_addu(MIPSOpcode op,char * out)254 void Dis_addu(MIPSOpcode op, char *out) 255 { 256 int rt = _RT; 257 int rs = _RS; 258 int rd = _RD; 259 const char *name = MIPSGetName(op); 260 if (rs==0 && rt==0) 261 sprintf(out,"li\t%s, 0",RN(rd)); 262 else if (rs == 0) 263 sprintf(out,"move\t%s, %s",RN(rd),RN(rt)); 264 else if (rt == 0) 265 sprintf(out,"move\t%s, %s",RN(rd),RN(rs)); 266 else 267 sprintf(out, "%s\t%s, %s, %s",name,RN(rd),RN(rs),RN(rt)); 268 } 269 Dis_ShiftType(MIPSOpcode op,char * out)270 void Dis_ShiftType(MIPSOpcode op, char *out) 271 { 272 int rt = _RT; 273 int rs = _RS; 274 int rd = _RD; 275 int sa = (op>>6) & 0x1F; 276 const char *name = MIPSGetName(op); 277 if (((op & 0x3f) == 2) && rs == 1) 278 name = "rotr"; 279 if (((op & 0x3f) == 6) && sa == 1) 280 name = "rotrv"; 281 sprintf(out, "%s\t%s, %s, 0x%X",name,RN(rd),RN(rt),sa); 282 } 283 Dis_VarShiftType(MIPSOpcode op,char * out)284 void Dis_VarShiftType(MIPSOpcode op, char *out) 285 { 286 int rt = _RT; 287 int rs = _RS; 288 int rd = _RD; 289 int sa = (op>>6) & 0x1F; 290 const char *name = MIPSGetName(op); 291 if (((op & 0x3f) == 6) && sa == 1) 292 name = "rotrv"; 293 sprintf(out, "%s\t%s, %s, %s",name,RN(rd),RN(rt),RN(rs)); 294 } 295 296 Dis_MulDivType(MIPSOpcode op,char * out)297 void Dis_MulDivType(MIPSOpcode op, char *out) 298 { 299 int rt = _RT; 300 int rs = _RS; 301 const char *name = MIPSGetName(op); 302 sprintf(out, "%s\t%s, %s",name,RN(rs),RN(rt)); 303 } 304 305 Dis_Special3(MIPSOpcode op,char * out)306 void Dis_Special3(MIPSOpcode op, char *out) 307 { 308 int rs = _RS; 309 int Rt = _RT; 310 int pos = _POS; 311 const char *name = MIPSGetName(op); 312 313 switch (op & 0x3f) 314 { 315 case 0x0: //ext 316 { 317 int size = _SIZE + 1; 318 sprintf(out,"%s\t%s, %s, 0x%X, 0x%X",name,RN(Rt),RN(rs),pos,size); 319 } 320 break; 321 case 0x4: // ins 322 { 323 int size = (_SIZE + 1) - pos; 324 sprintf(out,"%s\t%s, %s, 0x%X, 0x%X",name,RN(Rt),RN(rs),pos,size); 325 } 326 break; 327 } 328 } 329 Dis_JumpType(MIPSOpcode op,char * out)330 void Dis_JumpType(MIPSOpcode op, char *out) 331 { 332 u32 off = ((op & 0x03FFFFFF) << 2); 333 u32 addr = (disPC & 0xF0000000) | off; 334 const char *name = MIPSGetName(op); 335 sprintf(out, "%s\t->$%08x",name,addr); 336 } 337 Dis_JumpRegType(MIPSOpcode op,char * out)338 void Dis_JumpRegType(MIPSOpcode op, char *out) 339 { 340 int rs = _RS; 341 int rd = _RD; 342 const char *name = MIPSGetName(op); 343 if ((op & 0x3f) == 9 && rd != MIPS_REG_RA) 344 sprintf(out, "%s\t%s,->%s", name, RN(rd), RN(rs)); 345 else 346 sprintf(out, "%s\t->%s", name, RN(rs)); 347 } 348 Dis_Allegrex(MIPSOpcode op,char * out)349 void Dis_Allegrex(MIPSOpcode op, char *out) 350 { 351 int rt = _RT; 352 int rd = _RD; 353 const char *name = MIPSGetName(op); 354 sprintf(out,"%s\t%s,%s",name,RN(rd),RN(rt)); 355 } 356 Dis_Allegrex2(MIPSOpcode op,char * out)357 void Dis_Allegrex2(MIPSOpcode op, char *out) 358 { 359 int rt = _RT; 360 int rd = _RD; 361 const char *name = MIPSGetName(op); 362 sprintf(out,"%s\t%s,%s",name,RN(rd),RN(rt)); 363 } 364 Dis_Emuhack(MIPSOpcode op,char * out)365 void Dis_Emuhack(MIPSOpcode op, char *out) 366 { 367 auto resolved = Memory::Read_Instruction(disPC, true); 368 char disasm[256]; 369 if (MIPS_IS_EMUHACK(resolved)) { 370 strcpy(disasm, "(invalid emuhack)"); 371 } else { 372 MIPSDisAsm(resolved, disPC, disasm, true); 373 } 374 375 switch (op.encoding >> 24) { 376 case 0x68: 377 snprintf(out, 256, "* jitblock: %s", disasm); 378 break; 379 case 0x6a: 380 snprintf(out, 256, "* replacement: %s", disasm); 381 break; 382 default: 383 snprintf(out, 256, "* (invalid): %s", disasm); 384 break; 385 } 386 } 387 388 389 } 390