|
|
1.1 ! root 1: /*++ ! 2: ! 3: Copyright (c) 1993 Microsoft Corporation ! 4: ! 5: Module Name: ! 6: ! 7: disasm.c ! 8: ! 9: Abstract: ! 10: ! 11: This file provides support disassembly ( mips ). ! 12: ! 13: Author: ! 14: ! 15: Gerd Immeyer 19-Oct-1989 ! 16: Wesley Witt (wesw) 1-May-1993 ( ported from ntsd to drwatson) ! 17: ! 18: Environment: ! 19: ! 20: User Mode ! 21: ! 22: --*/ ! 23: ! 24: #include <windows.h> ! 25: #include <stddef.h> ! 26: #include <string.h> ! 27: #include "regs.h" ! 28: #include "disasm.h" ! 29: #include "drwatson.h" ! 30: #include "proto.h" ! 31: ! 32: ! 33: #define OPCODE 18 ! 34: #define OPSTART 26 ! 35: ! 36: typedef struct optabentry { ! 37: PUCHAR pszOpcode; ! 38: ULONG fInstruction; ! 39: } OPTABENTRY, *POPTABENTRY; ! 40: ! 41: ! 42: static ULONG ProcessorType = 0; ! 43: INSTR disinstr; ! 44: ULONG EAaddr = 0; ! 45: DWORD EA; ! 46: ! 47: UCHAR pszUndef[] = "????"; ! 48: UCHAR pszNull[] = ""; ! 49: ! 50: UCHAR pszAbs_s[] = "abs.s"; ! 51: UCHAR pszAdd[] = "add"; ! 52: UCHAR pszAdd_s[] = "add.s"; ! 53: UCHAR pszAddi[] = "addi"; ! 54: UCHAR pszAddiu[] = "addiu"; ! 55: UCHAR pszAddu[] = "addu"; ! 56: UCHAR pszAnd[] = "and"; ! 57: UCHAR pszAndi[] = "andi"; ! 58: UCHAR pszBc0f[] = "bc0f"; ! 59: UCHAR pszBc0fl[] = "bc0fl"; ! 60: UCHAR pszBc0t[] = "bc0t"; ! 61: UCHAR pszBc0tl[] = "bc0tl"; ! 62: UCHAR pszBc1f[] = "bc1f"; ! 63: UCHAR pszBc1fl[] = "bc1fl"; ! 64: UCHAR pszBc1t[] = "bc1t"; ! 65: UCHAR pszBc1tl[] = "bc1tl"; ! 66: UCHAR pszBc2f[] = "bc2f"; ! 67: UCHAR pszBc2fl[] = "bc2fl"; ! 68: UCHAR pszBc2t[] = "bc2t"; ! 69: UCHAR pszBc2tl[] = "bc2tl"; ! 70: UCHAR pszBc3f[] = "bc3f"; ! 71: UCHAR pszBc3fl[] = "bc3fl"; ! 72: UCHAR pszBc3t[] = "bc3t"; ! 73: UCHAR pszBc3tl[] = "bc3tl"; ! 74: UCHAR pszBgez[] = "bgez"; ! 75: UCHAR pszBgezal[] = "bgezal"; ! 76: UCHAR pszBgezall[] = "bgezall"; ! 77: UCHAR pszBgezl[] = "bgezl"; ! 78: UCHAR pszBgtz[] = "bgtz"; ! 79: UCHAR pszBgtzl[] = "bgtzl"; ! 80: UCHAR pszBeq[] = "beq"; ! 81: UCHAR pszBeql[] = "beql"; ! 82: UCHAR pszBlez[] = "blez"; ! 83: UCHAR pszBlezl[] = "blezl"; ! 84: UCHAR pszBltz[] = "bltz"; ! 85: UCHAR pszBltzal[] = "bltzal"; ! 86: UCHAR pszBltzall[] = "bltzall"; ! 87: UCHAR pszBltzl[] = "bltzl"; ! 88: UCHAR pszBne[] = "bne"; ! 89: UCHAR pszBnel[] = "bnel"; ! 90: UCHAR pszBreak[] = "break"; ! 91: UCHAR pszCache[] = "cache"; ! 92: UCHAR pszCeil_w_s[] = "ceil.w.s"; ! 93: UCHAR pszCfc0[] = "cfc0"; ! 94: UCHAR pszCfc1[] = "cfc1"; ! 95: UCHAR pszCfc2[] = "cfc2"; ! 96: UCHAR pszCfc3[] = "cfc3"; ! 97: UCHAR pszCtc0[] = "ctc0"; ! 98: UCHAR pszCtc1[] = "ctc1"; ! 99: UCHAR pszCtc2[] = "ctc2"; ! 100: UCHAR pszCtc3[] = "ctc3"; ! 101: UCHAR pszCop0[] = "cop0"; ! 102: UCHAR pszCop1[] = "cop1"; ! 103: UCHAR pszCop2[] = "cop2"; ! 104: UCHAR pszCop3[] = "cop3"; ! 105: UCHAR pszCvt_d_s[] = "cvt.d.s"; ! 106: UCHAR pszCvt_e_s[] = "cvt.e.s"; ! 107: UCHAR pszCvt_q_s[] = "cvt.q.s"; ! 108: UCHAR pszCvt_s_s[] = "cvt.s.s"; ! 109: UCHAR pszCvt_w_s[] = "cvt.w.s"; ! 110: UCHAR pszC_eq_s[] = "c.eq.s"; ! 111: UCHAR pszC_f_s[] = "c.f.s"; ! 112: UCHAR pszC_le_s[] = "c.le.s"; ! 113: UCHAR pszC_lt_s[] = "c.lt.s"; ! 114: UCHAR pszC_nge_s[] = "c.nge.s"; ! 115: UCHAR pszC_ngl_s[] = "c.ngl.s"; ! 116: UCHAR pszC_ngle_s[] = "c.ngle.s"; ! 117: UCHAR pszC_ngt_s[] = "c.ngt.s"; ! 118: UCHAR pszC_ole_s[] = "c.ole.s"; ! 119: UCHAR pszC_olt_s[] = "c.olt.s"; ! 120: UCHAR pszC_seq_s[] = "c.seq.s"; ! 121: UCHAR pszC_sf_s[] = "c.sf.s"; ! 122: UCHAR pszC_ueq_s[] = "c.ueq.s"; ! 123: UCHAR pszC_ule_s[] = "c.ule.s"; ! 124: UCHAR pszC_ult_s[] = "c.ult.s"; ! 125: UCHAR pszC_un_s[] = "c.un.s"; ! 126: UCHAR pszDiv[] = "div"; ! 127: UCHAR pszDivu[] = "divu"; ! 128: UCHAR pszDiv_s[] = "div.s"; ! 129: UCHAR pszEret[] = "eret"; ! 130: UCHAR pszFloor_w_s[] = "floor.w.s"; ! 131: UCHAR pszJ[] = "j"; ! 132: UCHAR pszJal[] = "jal"; ! 133: UCHAR pszJalr[] = "jalr"; ! 134: UCHAR pszJr[] = "jr"; ! 135: UCHAR pszLb[] = "lb"; ! 136: UCHAR pszLbu[] = "lbu"; ! 137: UCHAR pszLdc1[] = "ldc1"; ! 138: UCHAR pszLdc2[] = "ldc2"; ! 139: UCHAR pszLdc3[] = "ldc3"; ! 140: UCHAR pszLh[] = "lh"; ! 141: UCHAR pszLhu[] = "lhu"; ! 142: UCHAR pszLui[] = "lui"; ! 143: UCHAR pszLw[] = "lw"; ! 144: UCHAR pszLwc0[] = "lwc0"; ! 145: UCHAR pszLwc1[] = "lwc1"; ! 146: UCHAR pszLwc2[] = "lwc2"; ! 147: UCHAR pszLwc3[] = "lwc3"; ! 148: UCHAR pszLwl[] = "lwl"; ! 149: UCHAR pszLwr[] = "lwr"; ! 150: UCHAR pszMfc0[] = "mfc0"; ! 151: UCHAR pszMfc1[] = "mfc1"; ! 152: UCHAR pszMfc2[] = "mfc2"; ! 153: UCHAR pszMfc3[] = "mfc3"; ! 154: UCHAR pszMfhi[] = "mfhi"; ! 155: UCHAR pszMflo[] = "mflo"; ! 156: UCHAR pszMov_s[] = "mov.s"; ! 157: UCHAR pszMtc0[] = "mtc0"; ! 158: UCHAR pszMtc1[] = "mtc1"; ! 159: UCHAR pszMtc2[] = "mtc2"; ! 160: UCHAR pszMtc3[] = "mtc3"; ! 161: UCHAR pszMthi[] = "mthi"; ! 162: UCHAR pszMtlo[] = "mtlo"; ! 163: UCHAR pszMul_s[] = "mul.s"; ! 164: UCHAR pszMult[] = "mult"; ! 165: UCHAR pszMultu[] = "multu"; ! 166: UCHAR pszNeg_s[] = "neg.s"; ! 167: UCHAR pszNop[] = "nop"; ! 168: UCHAR pszNor[] = "nor"; ! 169: UCHAR pszOr[] = "or"; ! 170: UCHAR pszOri[] = "ori"; ! 171: UCHAR pszRfe[] = "rfe"; ! 172: UCHAR pszRound_w_s[] = "round.w.s"; ! 173: UCHAR pszSb[] = "sb"; ! 174: UCHAR pszSdc1[] = "sdc1"; ! 175: UCHAR pszSdc2[] = "sdc2"; ! 176: UCHAR pszSdc3[] = "sdc3"; ! 177: UCHAR pszSh[] = "sh"; ! 178: UCHAR pszSll[] = "sll"; ! 179: UCHAR pszSllv[] = "sllv"; ! 180: UCHAR pszSlt[] = "slt"; ! 181: UCHAR pszSlti[] = "slti"; ! 182: UCHAR pszSltiu[] = "sltiu"; ! 183: UCHAR pszSltu[] = "sltu"; ! 184: UCHAR pszSqrt_s[] = "sqrt.s"; ! 185: UCHAR pszSra[] = "sra"; ! 186: UCHAR pszSrav[] = "srav"; ! 187: UCHAR pszSrl[] = "srl"; ! 188: UCHAR pszSrlv[] = "srlv"; ! 189: UCHAR pszSub[] = "sub"; ! 190: UCHAR pszSub_s[] = "sub.s"; ! 191: UCHAR pszSubu[] = "subu"; ! 192: UCHAR pszSw[] = "sw"; ! 193: UCHAR pszSwc0[] = "swc0"; ! 194: UCHAR pszSwc1[] = "swc1"; ! 195: UCHAR pszSwc2[] = "swc2"; ! 196: UCHAR pszSwc3[] = "swc3"; ! 197: UCHAR pszSwl[] = "swl"; ! 198: UCHAR pszSwr[] = "swr"; ! 199: UCHAR pszSync[] = "sync"; ! 200: UCHAR pszSyscall[] = "syscall"; ! 201: UCHAR pszTeq[] = "teq"; ! 202: UCHAR pszTeqi[] = "teqi"; ! 203: UCHAR pszTge[] = "tge"; ! 204: UCHAR pszTgei[] = "tgei"; ! 205: UCHAR pszTgeiu[] = "tgeiu"; ! 206: UCHAR pszTgeu[] = "tgeu"; ! 207: UCHAR pszTlbp[] = "tlbp"; ! 208: UCHAR pszTlbr[] = "tlbr"; ! 209: UCHAR pszTlbwi[] = "tlbwi"; ! 210: UCHAR pszTlbwr[] = "tlbwr"; ! 211: UCHAR pszTlt[] = "tlt"; ! 212: UCHAR pszTlti[] = "tlti"; ! 213: UCHAR pszTltiu[] = "tltiu"; ! 214: UCHAR pszTltu[] = "tltu"; ! 215: UCHAR pszTne[] = "tne"; ! 216: UCHAR pszTnei[] = "tnei"; ! 217: UCHAR pszTrunc_w_s[] = "trunc.w.s"; ! 218: UCHAR pszXor[] = "xor"; ! 219: UCHAR pszXori[] = "xori"; ! 220: ! 221: OPTABENTRY opTable[] = { ! 222: { pszNull, 0 }, // 00 ! 223: { pszNull, 0 }, // 01 ! 224: { pszJ, opnAddr26 }, // 02 ! 225: { pszJal, opnAddr26 }, // 03 ! 226: { pszBeq, opnRsRtRel16 }, // 04 ! 227: { pszBne, opnRsRtRel16 }, // 05 ! 228: { pszBlez, opnRsRel16 }, // 06 ! 229: { pszBgtz, opnRsRel16 }, // 07 ! 230: { pszAddi, opnRtRsImm16 }, // 08 ! 231: { pszAddiu, opnRtRsImm16 }, // 09 ! 232: { pszSlti, opnRtRsImm16 }, // 0a ! 233: { pszSltiu, opnRtRsImm16 }, // 0b ! 234: { pszAndi, opnRtRsImm16 }, // 0c ! 235: { pszOri, opnRtRsImm16 }, // 0d ! 236: { pszXori, opnRtRsImm16 }, // 0e ! 237: { pszLui, opnRtImm16 }, // 0f ! 238: { pszCop0, opnImm26 }, // 10 ! 239: { pszCop1, opnImm26 }, // 11 ! 240: { pszCop2, opnImm26 }, // 12 ! 241: { pszCop3, opnImm26 }, // 13 ! 242: { pszBeql, opnRsRtRel16 + opnR4000 }, // 14 ! 243: { pszBnel, opnRsRtRel16 + opnR4000 }, // 15 ! 244: { pszBlezl, opnRsRel16 + opnR4000 }, // 16 ! 245: { pszBgtzl, opnRsRel16 + opnR4000 }, // 17 ! 246: { pszUndef, 0 }, // 18 ! 247: { pszUndef, 0 }, // 19 ! 248: { pszUndef, 0 }, // 1a ! 249: { pszUndef, 0 }, // 1b ! 250: { pszUndef, 0 }, // 1c ! 251: { pszUndef, 0 }, // 1d ! 252: { pszUndef, 0 }, // 1e ! 253: { pszUndef, 0 }, // 1f ! 254: { pszLb, opnRtByteIndex }, // 20 ! 255: { pszLh, opnRtWordIndex }, // 21 ! 256: { pszLwl, opnRtLeftIndex }, // 22 ! 257: { pszLw, opnRtDwordIndex }, // 23 ! 258: { pszLbu, opnRtByteIndex }, // 24 ! 259: { pszLhu, opnRtWordIndex }, // 25 ! 260: { pszLwr, opnRtRightIndex }, // 26 ! 261: { pszUndef, 0 }, // 27 ! 262: { pszSb, opnRtByteIndex }, // 28 ! 263: { pszSh, opnRtWordIndex }, // 29 ! 264: { pszSwl, opnRtLeftIndex }, // 2a ! 265: { pszSw, opnRtDwordIndex }, // 2b ! 266: { pszUndef, 0 }, // 2c ! 267: { pszUndef, 0 }, // 2d ! 268: { pszSwr, opnRtRightIndex }, // 2e ! 269: { pszCache, opnCacheRightIndex + opnR4000 }, // 2f ! 270: { pszLwc0, opnRtDwordIndex }, // 30 ! 271: { pszLwc1, opnFtDwordIndex }, // 31 ! 272: { pszLwc2, opnRtDwordIndex }, // 32 ! 273: { pszLwc3, opnRtDwordIndex }, // 33 ! 274: { pszUndef, 0 }, // 34 ! 275: { pszLdc1, opnFtDwordIndex + opnR4000 }, // 35 Qword? ! 276: { pszLdc2, opnRtDwordIndex + opnR4000 }, // 36 Qword? ! 277: { pszLdc3, opnRtDwordIndex + opnR4000 }, // 37 Qword? ! 278: { pszSwc0, opnRtDwordIndex }, // 38 ! 279: { pszSwc1, opnFtDwordIndex }, // 39 ! 280: { pszSwc2, opnRtDwordIndex }, // 3a ! 281: { pszSwc3, opnRtDwordIndex }, // 3b ! 282: { pszUndef, 0 }, // 3c ! 283: { pszSdc1, opnFtDwordIndex + opnR4000 }, // 3d Qword? ! 284: { pszSdc2, opnRtDwordIndex + opnR4000 }, // 3e Qword? ! 285: { pszSdc3, opnRtDwordIndex + opnR4000 }, // 3f Qword? ! 286: }; ! 287: ! 288: OPTABENTRY opSpecialTable[] = { ! 289: { pszSll, opnRdRtShift }, // 00 ! 290: { pszUndef, 0 }, // 01 ! 291: { pszSrl, opnRdRtShift }, // 02 ! 292: { pszSra, opnRdRtShift }, // 03 ! 293: { pszSllv, opnRdRtRs }, // 04 ! 294: { pszUndef, 0 }, // 05 ! 295: { pszSrlv, opnRdRtRs }, // 06 ! 296: { pszSrav, opnRdRtRs }, // 07 ! 297: { pszJr, opnRs }, // 08 ! 298: { pszJalr, opnRdOptRs }, // 09 ! 299: { pszUndef, 0 }, // 0a ! 300: { pszUndef, 0 }, // 0b ! 301: { pszSyscall, opnNone }, // 0c ! 302: { pszBreak, opnImm20 }, // 0d ! 303: { pszUndef, 0 }, // 0e ! 304: { pszSync, opnNone + opnR4000 }, // 0f ! 305: { pszMfhi, opnRd }, // 10 ! 306: { pszMthi, opnRs }, // 11 ! 307: { pszMflo, opnRd }, // 12 ! 308: { pszMtlo, opnRs }, // 13 ! 309: { pszUndef, 0 }, // 14 ! 310: { pszUndef, 0 }, // 15 ! 311: { pszUndef, 0 }, // 16 ! 312: { pszUndef, 0 }, // 17 ! 313: { pszMult, opnRsRt }, // 18 ! 314: { pszMultu, opnRsRt }, // 19 ! 315: { pszDiv, opnRsRt }, // 1a ! 316: { pszDivu, opnRsRt }, // 1b ! 317: { pszUndef, 0 }, // 1c ! 318: { pszUndef, 0 }, // 1d ! 319: { pszUndef, 0 }, // 1e ! 320: { pszUndef, 0 }, // 1f ! 321: { pszAdd, opnRdRsRt }, // 20 ! 322: { pszAddu, opnRdRsRt }, // 21 ! 323: { pszSub, opnRdRsRt }, // 22 ! 324: { pszSubu, opnRdRsRt }, // 23 ! 325: { pszAnd, opnRdRsRt }, // 24 ! 326: { pszOr, opnRdRsRt }, // 25 ! 327: { pszXor, opnRdRsRt }, // 26 ! 328: { pszNor, opnRdRsRt }, // 27 ! 329: { pszUndef, 0 }, // 28 ! 330: { pszUndef, 0 }, // 29 ! 331: { pszSlt, opnRdRsRt }, // 2a ! 332: { pszSltu, opnRdRsRt }, // 2b ! 333: { pszUndef, 0 }, // 2c ! 334: { pszUndef, 0 }, // 2d ! 335: { pszUndef, 0 }, // 2e ! 336: { pszUndef, 0 }, // 2f ! 337: { pszTge, opnRsRtImm10 + opnR4000 }, // 30 ! 338: { pszTgeu, opnRsRtImm10 + opnR4000 }, // 31 ! 339: { pszTlt, opnRsRtImm10 + opnR4000 }, // 32 ! 340: { pszTltu, opnRsRtImm10 + opnR4000 }, // 33 ! 341: { pszTeq, opnRsRtImm10 + opnR4000 }, // 34 ! 342: { pszUndef, 0 }, // 35 ! 343: { pszTne, opnRsRtImm10 + opnR4000 }, // 36 ! 344: { pszUndef, 0 }, // 37 ! 345: { pszUndef, 0 }, // 38 ! 346: { pszUndef, 0 }, // 39 ! 347: { pszUndef, 0 }, // 3a ! 348: { pszUndef, 0 }, // 3b ! 349: { pszUndef, 0 }, // 3c ! 350: { pszUndef, 0 }, // 3d ! 351: { pszUndef, 0 }, // 3e ! 352: { pszUndef, 0 } // 3f ! 353: }; ! 354: ! 355: OPTABENTRY opBcondTable[] = { ! 356: { pszBltz, opnRsRel16 }, // 00 ! 357: { pszBgez, opnRsRel16 }, // 01 ! 358: { pszBltzl, opnRsRel16 + opnR4000 }, // 02 ! 359: { pszBgezl, opnRsRel16 + opnR4000 }, // 03 ! 360: { pszUndef, 0 }, // 04 ! 361: { pszUndef, 0 }, // 05 ! 362: { pszUndef, 0 }, // 06 ! 363: { pszUndef, 0 }, // 07 ! 364: { pszTgei, opnRsImm16 + opnR4000 }, // 08 ! 365: { pszTgeiu, opnRsImm16 + opnR4000 }, // 09 ! 366: { pszTlti, opnRsImm16 + opnR4000 }, // 0a ! 367: { pszTltiu, opnRsImm16 + opnR4000 }, // 0b ! 368: { pszTeqi, opnRsImm16 + opnR4000 }, // 0c ! 369: { pszUndef, 0 }, // 0d ! 370: { pszTnei, opnRsImm16 + opnR4000 }, // 0e ! 371: { pszUndef, 0 }, // 0f ! 372: { pszBltzal, opnRsRel16 }, // 10 ! 373: { pszBgezal, opnRsRel16 }, // 11 ! 374: { pszBltzall, opnRsRel16 + opnR4000 }, // 12 ! 375: { pszBgezall, opnRsRel16 + opnR4000 } // 13 ! 376: }; ! 377: ! 378: OPTABENTRY opCopnTable[] = { ! 379: { pszMfc0, opnRtRd }, // 00 ! 380: { pszMfc1, opnRtFs }, // 01 ! 381: { pszMfc2, opnRtRd }, // 02 ! 382: { pszMfc3, opnRtRd }, // 03 ! 383: { pszCfc0, opnRtRd }, // 04 ! 384: { pszCfc1, opnRtFs }, // 05 ! 385: { pszCfc2, opnRtRd }, // 06 ! 386: { pszCfc3, opnRtRd }, // 07 ! 387: { pszMtc0, opnRtRd }, // 08 ! 388: { pszMtc1, opnRtFs }, // 09 ! 389: { pszMtc2, opnRtRd }, // 0a ! 390: { pszMtc3, opnRtRd }, // 0b ! 391: { pszCtc0, opnRtRd }, // 0c ! 392: { pszCtc1, opnRtFs }, // 0d ! 393: { pszCtc2, opnRtRd }, // 0e ! 394: { pszCtc3, opnRtRd }, // 0f ! 395: { pszBc0f, opnRel16 }, // 10 ! 396: { pszBc1f, opnRel16 }, // 11 ! 397: { pszBc2f, opnRel16 }, // 12 ! 398: { pszBc3f, opnRel16 }, // 13 ! 399: { pszBc0t, opnRel16 }, // 14 ! 400: { pszBc1t, opnRel16 }, // 15 ! 401: { pszBc2t, opnRel16 }, // 16 ! 402: { pszBc3t, opnRel16 }, // 17 ! 403: { pszBc0fl, opnRel16 + opnR4000 }, // 18 ! 404: { pszBc1fl, opnRel16 + opnR4000 }, // 19 ! 405: { pszBc2fl, opnRel16 + opnR4000 }, // 1a ! 406: { pszBc3fl, opnRel16 + opnR4000 }, // 1b ! 407: { pszBc0tl, opnRel16 + opnR4000 }, // 1c ! 408: { pszBc1tl, opnRel16 + opnR4000 }, // 1d ! 409: { pszBc2tl, opnRel16 + opnR4000 }, // 1e ! 410: { pszBc3tl, opnRel16 + opnR4000 } // 1f ! 411: }; ! 412: ! 413: OPTABENTRY opFloatTable[] = { ! 414: { pszAdd_s, opnFdFsFt }, // 00 ! 415: { pszSub_s, opnFdFsFt }, // 01 ! 416: { pszMul_s, opnFdFsFt }, // 02 ! 417: { pszDiv_s, opnFdFsFt }, // 03 ! 418: { pszSqrt_s, opnFdFs + opnR4000 }, // 04 ! 419: { pszAbs_s, opnFdFs }, // 05 ! 420: { pszMov_s, opnFdFs }, // 06 ! 421: { pszNeg_s, opnFdFs }, // 07 ! 422: { pszUndef, 0 }, // 08 ! 423: { pszUndef, 0 }, // 09 ! 424: { pszUndef, 0 }, // 0a ! 425: { pszUndef, 0 }, // 0b ! 426: { pszRound_w_s, opnFdFs + opnR4000 }, // 0c ! 427: { pszTrunc_w_s, opnFdFs + opnR4000 }, // 0d ! 428: { pszCeil_w_s, opnFdFs + opnR4000 }, // 0e ! 429: { pszFloor_w_s, opnFdFs + opnR4000 }, // 0f ! 430: { pszUndef, 0 }, // 10 ! 431: { pszUndef, 0 }, // 11 ! 432: { pszUndef, 0 }, // 12 ! 433: { pszUndef, 0 }, // 13 ! 434: { pszUndef, 0 }, // 14 ! 435: { pszUndef, 0 }, // 15 ! 436: { pszUndef, 0 }, // 16 ! 437: { pszUndef, 0 }, // 17 ! 438: { pszUndef, 0 }, // 18 ! 439: { pszUndef, 0 }, // 19 ! 440: { pszUndef, 0 }, // 1a ! 441: { pszUndef, 0 }, // 1b ! 442: { pszUndef, 0 }, // 1c ! 443: { pszUndef, 0 }, // 1d ! 444: { pszUndef, 0 }, // 1e ! 445: { pszUndef, 0 }, // 1f ! 446: { pszCvt_s_s, opnFdFs }, // 20 ! 447: { pszCvt_d_s, opnFdFs }, // 21 ! 448: { pszCvt_e_s, opnFdFs + opnR4000 }, // 22 ! 449: { pszCvt_q_s, opnFdFs + opnR4000 }, // 23 ! 450: { pszCvt_w_s, opnFdFs }, // 24 ! 451: { pszUndef, 0 }, // 25 ! 452: { pszUndef, 0 }, // 26 ! 453: { pszUndef, 0 }, // 27 ! 454: { pszUndef, 0 }, // 28 ! 455: { pszUndef, 0 }, // 29 ! 456: { pszUndef, 0 }, // 2a ! 457: { pszUndef, 0 }, // 2b ! 458: { pszUndef, 0 }, // 2c ! 459: { pszUndef, 0 }, // 2d ! 460: { pszUndef, 0 }, // 2e ! 461: { pszUndef, 0 }, // 2f ! 462: { pszC_f_s, opnFsFt }, // 30 ! 463: { pszC_un_s, opnFsFt }, // 31 ! 464: { pszC_eq_s, opnFsFt }, // 32 ! 465: { pszC_ueq_s, opnFsFt }, // 33 ! 466: { pszC_olt_s, opnFsFt }, // 34 ! 467: { pszC_ult_s, opnFsFt }, // 35 ! 468: { pszC_ole_s, opnFsFt }, // 36 ! 469: { pszC_ule_s, opnFsFt }, // 37 ! 470: { pszC_sf_s, opnFsFt }, // 38 ! 471: { pszC_ngle_s, opnFsFt }, // 39 ! 472: { pszC_seq_s, opnFsFt }, // 3a ! 473: { pszC_ngl_s, opnFsFt }, // 3b ! 474: { pszC_lt_s, opnFsFt }, // 3c ! 475: { pszC_nge_s, opnFsFt }, // 3d ! 476: { pszC_le_s, opnFsFt }, // 3e ! 477: { pszC_ngt_s, opnFsFt } // 3f ! 478: }; ! 479: ! 480: OPTABENTRY TlbrEntry = { pszTlbr, opnNone }; ! 481: OPTABENTRY TlbwiEntry = { pszTlbwi, opnNone }; ! 482: OPTABENTRY TlbwrEntry = { pszTlbwr, opnNone }; ! 483: OPTABENTRY TlbpEntry = { pszTlbp, opnNone }; ! 484: OPTABENTRY RfeEntry = { pszRfe, opnNone }; ! 485: OPTABENTRY EretEntry = { pszEret, opnNone }; ! 486: OPTABENTRY UndefEntry = { pszUndef, 0 }; ! 487: OPTABENTRY NopEntry = { pszNop, opnNone }; ! 488: ! 489: static PUCHAR pBufStart; ! 490: static PUCHAR pBuf; ! 491: static ULONG InstrOffset; ! 492: ! 493: UCHAR HexDigit[16] = { ! 494: '0', '1', '2', '3', '4', '5', '6', '7', ! 495: '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' ! 496: }; ! 497: ! 498: // ! 499: // prototypes ! 500: // ! 501: ! 502: void BlankFill(ULONG count); ! 503: void OutputHex (ULONG outvalue, ULONG length, BOOLEAN fSigned); ! 504: void OutputDisSymbol (PDEBUGPACKET dp, ULONG offset); ! 505: void OutputString (PUCHAR pStr); ! 506: void OutputReg (ULONG regnum); ! 507: void OutputFReg (ULONG regnum); ! 508: void GetNextOffset (PDEBUGPACKET dp, PULONG result, BOOLEAN fStep); ! 509: BOOLEAN fDelayInstruction (PDEBUGPACKET dp); ! 510: PUCHAR RegNameFromIndex (ULONG index); ! 511: ! 512: ! 513: ! 514: BOOLEAN ! 515: disasm (PDEBUGPACKET dp, PDWORD poffset, PUCHAR bufptr, BOOLEAN fEAout) ! 516: { ! 517: ULONG opcode; ! 518: ULONG temp; ! 519: POPTABENTRY pEntry; ! 520: UCHAR chSuffix = '\0'; ! 521: UCHAR EAsize = 0; ! 522: ! 523: pBufStart = pBuf = bufptr; ! 524: OutputHex(*poffset, 8, 0); // output hex offset ! 525: *pBuf++ = ' '; ! 526: ! 527: if (!ReadProcessMemory( dp->hProcess, ! 528: (LPVOID)*poffset, ! 529: (LPVOID)&disinstr.instruction, ! 530: sizeof(DWORD), ! 531: NULL ! 532: )) { ! 533: OutputString("???????? ????"); ! 534: *pBuf = '\0'; ! 535: return FALSE; ! 536: } ! 537: ! 538: OutputHex(disinstr.instruction, 8, 0); // output hex contents ! 539: *pBuf++ = ' '; ! 540: ! 541: // output the opcode in the table entry ! 542: ! 543: opcode = disinstr.jump_instr.Opcode; ! 544: pEntry = &opTable[opcode]; // default value ! 545: ! 546: if (opcode == 0x00) // special opcodes ! 547: if (disinstr.instruction) ! 548: pEntry = &opSpecialTable[disinstr.special_instr.Funct]; ! 549: else ! 550: pEntry = &NopEntry; // special opcode for no-op ! 551: ! 552: else if (opcode == 0x01) { // bcond opcodes ! 553: opcode = disinstr.immed_instr.RT; ! 554: if (opcode < 0x14) ! 555: pEntry = &opBcondTable[opcode]; ! 556: else ! 557: pEntry = &UndefEntry; ! 558: } ! 559: ! 560: else if ((opcode & ~0x3) == 0x10) { // coprocessor opcodes ! 561: temp = disinstr.immed_instr.RS; ! 562: if (temp & 0x10) { // test for CO bit ! 563: if (opcode == 0x10) { // test if COP0 ! 564: temp = disinstr.special_instr.Funct; ! 565: if (temp == 0x01) ! 566: pEntry = &TlbrEntry; ! 567: else if (temp == 0x02) ! 568: pEntry = &TlbwiEntry; ! 569: else if (temp == 0x06) ! 570: pEntry = &TlbwrEntry; ! 571: else if (temp == 0x08) ! 572: pEntry = &TlbpEntry; ! 573: else if (temp == 0x10) ! 574: pEntry = &RfeEntry; ! 575: else if (temp == 0x18) ! 576: pEntry = &EretEntry; ! 577: } ! 578: else if (opcode == 0x11) { // coprocessor operations ! 579: opcode = disinstr.float_instr.Funct; ! 580: pEntry = &opFloatTable[opcode]; // get opcode ! 581: if (temp == 0x11) ! 582: chSuffix = 'd'; ! 583: else if (temp == 0x12) { ! 584: chSuffix = 'e'; ! 585: pEntry->fInstruction |= opnR4000; ! 586: } ! 587: else if (temp == 0x13) { ! 588: chSuffix = 'q'; ! 589: pEntry->fInstruction |= opnR4000; ! 590: } ! 591: else if (temp == 0x14) ! 592: chSuffix = 'w'; ! 593: else if (temp != 0x10) ! 594: pEntry = &UndefEntry; ! 595: } ! 596: } ! 597: else { // no CO bit, general COPz ops ! 598: if (!(temp & ~0x06)) // rs = 0, 2, 4, 6 ! 599: pEntry = &opCopnTable[temp * 2 + (opcode - 0x10)]; ! 600: else if ((temp & ~0x04) == 0x08) // rs = 8 or 0xc, rt = 0 to 3 ! 601: pEntry = &opCopnTable[(4 + (disinstr.immed_instr.RT & 3)) * 4 ! 602: + (opcode - 0x10)]; ! 603: } ! 604: } ! 605: ! 606: // pEntry has the opcode string and operand template needed to ! 607: // output the instruction. ! 608: ! 609: OutputString(pEntry->pszOpcode); ! 610: if (*(pBuf - 1) != '?' && chSuffix) ! 611: *(pBuf - 1) = chSuffix; // change xxx.s to xxx.d, xxx.w, ! 612: // xxx.e, or xxx.q (R4000 for e, q) ! 613: ! 614: BlankFill(OPSTART); ! 615: ! 616: // cache instruction has special codes for RT field value: ! 617: // 0 = 'i'; 1 = 'd'; 2 = 'si'; 3 = 'sd' ! 618: ! 619: if (pEntry->fInstruction & opnCache) { ! 620: temp = disinstr.special_instr.RT; ! 621: if (temp > 3) ! 622: *pBuf++ = '?'; ! 623: else { ! 624: if (temp > 1) { ! 625: *pBuf++ = 's'; ! 626: temp -= 2; ! 627: } ! 628: if (temp == 0) ! 629: *pBuf++ = 'i'; ! 630: else ! 631: *pBuf++ = 'd'; ! 632: } ! 633: *pBuf++ = ','; ! 634: } ! 635: ! 636: if (pEntry->fInstruction & opnPreRt) { ! 637: OutputReg(disinstr.special_instr.RT); ! 638: *pBuf++ = ','; ! 639: } ! 640: ! 641: if (pEntry->fInstruction & opnRd) ! 642: OutputReg(disinstr.special_instr.RD); ! 643: ! 644: if (pEntry->fInstruction & opnFd) ! 645: OutputFReg(disinstr.float_instr.FD); ! 646: ! 647: if (pEntry->fInstruction & opnRdOptRs) { ! 648: if (disinstr.special_instr.RD != 0x1f) { ! 649: OutputReg(disinstr.special_instr.RD); ! 650: *pBuf++ = ','; ! 651: } ! 652: OutputReg(disinstr.immed_instr.RS); ! 653: } ! 654: ! 655: if (pEntry->fInstruction & opnRdComma) ! 656: *pBuf++ = ','; ! 657: ! 658: if (pEntry->fInstruction & opnRs) ! 659: OutputReg(disinstr.immed_instr.RS); ! 660: ! 661: if (pEntry->fInstruction & opnFs) ! 662: OutputFReg(disinstr.float_instr.FS); ! 663: ! 664: if (pEntry->fInstruction & opnRsComma) ! 665: *pBuf++ = ','; ! 666: ! 667: if (pEntry->fInstruction & opnRt) ! 668: OutputReg(disinstr.immed_instr.RT); ! 669: ! 670: if (pEntry->fInstruction & opnFt) ! 671: OutputFReg(disinstr.float_instr.FT); ! 672: ! 673: if (pEntry->fInstruction & opnRtComma) ! 674: *pBuf++ = ','; ! 675: ! 676: if (pEntry->fInstruction & opnPostRs) ! 677: OutputReg(disinstr.immed_instr.RS); ! 678: ! 679: if (pEntry->fInstruction & opnImm10) ! 680: OutputHex((long)(short)disinstr.trap_instr.Value, 0, TRUE); ! 681: ! 682: if (pEntry->fInstruction & opnImm16) ! 683: OutputHex((long)(short)disinstr.immed_instr.Value, 0, TRUE); ! 684: ! 685: if (pEntry->fInstruction & opnRel16) ! 686: OutputDisSymbol(dp,((long)(short)disinstr.immed_instr.Value << 2) ! 687: + *poffset + sizeof(ULONG)); ! 688: ! 689: if (pEntry->fInstruction & opnImm20) ! 690: OutputHex(disinstr.break_instr.Value, 0, TRUE); ! 691: ! 692: if (pEntry->fInstruction & opnImm26) ! 693: OutputHex(disinstr.jump_instr.Target, 0, TRUE); ! 694: ! 695: if (pEntry->fInstruction & opnAddr26) ! 696: OutputDisSymbol(dp,(disinstr.jump_instr.Target << 2) ! 697: + (*poffset & 0xf0000000)); ! 698: ! 699: if (pEntry->fInstruction & opnAnyIndex) { ! 700: OutputHex((long)(short)disinstr.immed_instr.Value, 0, TRUE); ! 701: *pBuf++ = '('; ! 702: OutputReg(disinstr.immed_instr.RS); ! 703: *pBuf++ = ')'; ! 704: ! 705: // if instruction is for R4000 only, output " (4) " ! 706: ! 707: if (ProcessorType == 0 && (pEntry->fInstruction & opnR4000)) ! 708: OutputString(" (R4000!) "); ! 709: ! 710: if (fEAout) { ! 711: EAaddr = GetRegValue(dp, disinstr.immed_instr.RS + REGBASE) ! 712: + (long)(short)disinstr.immed_instr.Value; ! 713: if (pEntry->fInstruction & opnByteIndex) ! 714: EAsize = 1; ! 715: else if (pEntry->fInstruction & opnWordIndex) ! 716: EAsize = 2; ! 717: else if (pEntry->fInstruction & opnDwordIndex) ! 718: EAsize = 4; ! 719: else if (pEntry->fInstruction & opnLeftIndex) ! 720: EAsize = (UCHAR)(4 - (EAaddr & 3)); ! 721: else // if (pEntry->fInstruction & opnRightIndex) ! 722: EAsize = (UCHAR)((EAaddr & 3) + 1); ! 723: BlankFill(79 - 12 - (EAsize * 2)); ! 724: OutputString("EA:"); ! 725: OutputHex(EAaddr, 8, FALSE); ! 726: *pBuf++ = '='; ! 727: ! 728: if (!ReadProcessMemory( dp->hProcess, ! 729: (LPVOID)EAaddr, ! 730: (LPVOID)&temp, ! 731: EAsize, ! 732: NULL ! 733: )) { ! 734: while (EAsize--) { ! 735: *pBuf++ = '?'; ! 736: *pBuf++ = '?'; ! 737: } ! 738: } ! 739: } ! 740: else { ! 741: OutputHex(temp, (ULONG)(EAsize * 2), FALSE); ! 742: } ! 743: } ! 744: ! 745: if (pEntry->fInstruction & opnShift) ! 746: OutputHex(disinstr.special_instr.RE, 2, FALSE); ! 747: ! 748: *poffset += sizeof(ULONG); ! 749: *pBuf = '\0'; ! 750: return TRUE; ! 751: } ! 752: ! 753: /*** BlankFill - blank-fill buffer ! 754: * ! 755: * Purpose: ! 756: * To fill the buffer at *pBuf with blanks until ! 757: * position count is reached. ! 758: * ! 759: * Input: ! 760: * None. ! 761: * ! 762: * Output: ! 763: * None. ! 764: * ! 765: *************************************************************************/ ! 766: ! 767: void ! 768: BlankFill(ULONG count) ! 769: { ! 770: do ! 771: *pBuf++ = ' '; ! 772: while (pBuf < pBufStart + count); ! 773: } ! 774: ! 775: /*** OutputHex - output hex value ! 776: * ! 777: * Purpose: ! 778: * Output the value in outvalue into the buffer ! 779: * pointed by *pBuf. The value may be signed ! 780: * or unsigned depending on the value fSigned. ! 781: * ! 782: * Input: ! 783: * outvalue - value to output ! 784: * length - length in digits ! 785: * fSigned - TRUE if signed else FALSE ! 786: * ! 787: * Output: ! 788: * None. ! 789: * ! 790: *************************************************************************/ ! 791: ! 792: void ! 793: OutputHex (ULONG outvalue, ULONG length, BOOLEAN fSigned) ! 794: { ! 795: UCHAR digit[8]; ! 796: LONG index = 0; ! 797: ! 798: if (fSigned && (long)outvalue < 0) { ! 799: *pBuf++ = '-'; ! 800: outvalue = (ULONG)(-(long)outvalue); ! 801: } ! 802: if (fSigned) { ! 803: *pBuf++ = '0'; ! 804: *pBuf++ = 'x'; ! 805: } ! 806: do { ! 807: digit[index++] = HexDigit[outvalue & 0xf]; ! 808: outvalue >>= 4; ! 809: } ! 810: while ((fSigned && outvalue) || (!fSigned && index < (LONG)length)); ! 811: while (--index >= 0) ! 812: *pBuf++ = digit[index]; ! 813: } ! 814: ! 815: /*** OutputDisSymbol - output symbol for disassembly ! 816: * ! 817: * Purpose: ! 818: * Access symbol table with given offset and put string into buffer. ! 819: * ! 820: * Input: ! 821: * offset - offset of address to output ! 822: * ! 823: * Output: ! 824: * buffer pointed by pBuf updated with string: ! 825: * if symbol, no disp: <symbol>(<offset>) ! 826: * if symbol, disp: <symbol>+<disp>(<offset>) ! 827: * if no symbol, no disp: <offset> ! 828: * ! 829: *************************************************************************/ ! 830: ! 831: void ! 832: OutputDisSymbol (PDEBUGPACKET dp, ULONG offset) ! 833: { ! 834: ULONG displacement; ! 835: PUCHAR pszTemp; ! 836: UCHAR ch; ! 837: PSYMBOL sym; ! 838: ! 839: sym = GetSymFromAddrAllContexts( offset, &displacement, dp ); ! 840: if (sym) { ! 841: pszTemp = UnDName( &sym->szName[1] ); ! 842: while (ch = *pszTemp++) { ! 843: *pBuf++ = ch; ! 844: } ! 845: if (displacement) { ! 846: *pBuf++ = '+'; ! 847: OutputHex(displacement, 8, TRUE); ! 848: } ! 849: *pBuf++ = '('; ! 850: OutputHex(offset, 8, FALSE); ! 851: *pBuf++ = ')'; ! 852: } ! 853: else { ! 854: OutputHex(offset, 8, FALSE); ! 855: } ! 856: } ! 857: ! 858: /*** OutputString - output string ! 859: * ! 860: * Purpose: ! 861: * Copy the string into the buffer pointed by pBuf. ! 862: * ! 863: * Input: ! 864: * *pStr - pointer to string ! 865: * ! 866: * Output: ! 867: * None. ! 868: * ! 869: *************************************************************************/ ! 870: ! 871: void ! 872: OutputString (PUCHAR pStr) ! 873: { ! 874: while (*pStr) ! 875: *pBuf++ = *pStr++; ! 876: } ! 877: ! 878: void ! 879: OutputReg (ULONG regnum) ! 880: { ! 881: OutputString(RegNameFromIndex(regnum + REGBASE)); ! 882: } ! 883: ! 884: void ! 885: OutputFReg (ULONG regnum) ! 886: { ! 887: *pBuf++ = 'f'; ! 888: if (regnum > 9) ! 889: *pBuf++ = (UCHAR)('0' + regnum / 10); ! 890: *pBuf++ = (UCHAR)('0' + regnum % 10); ! 891: } ! 892: ! 893: /*** GetNextOffset - compute offset for trace or step ! 894: * ! 895: * Purpose: ! 896: * From a limited disassembly of the instruction pointed ! 897: * by the FIR register, compute the offset of the next ! 898: * instruction for either a trace or step operation. ! 899: * ! 900: * Input: ! 901: * fStep - TRUE for step offset; FALSE for trace offset ! 902: * ! 903: * Returns: ! 904: * step or trace offset if input is TRUE or FALSE, respectively ! 905: * ! 906: *************************************************************************/ ! 907: ! 908: void ! 909: GetNextOffset (PDEBUGPACKET dp, PULONG result, BOOLEAN fStep) ! 910: { ! 911: ULONG returnvalue; ! 912: ULONG opcode; ! 913: ULONG firaddr; ! 914: ! 915: firaddr = GetRegValue(dp,REGFIR); ! 916: ! 917: ReadProcessMemory( dp->hProcess, ! 918: (LPVOID)firaddr, ! 919: (LPVOID)&disinstr.instruction, ! 920: sizeof(ULONG), ! 921: NULL ! 922: ); ! 923: ! 924: opcode = disinstr.jump_instr.Opcode; ! 925: returnvalue = firaddr + sizeof(ULONG) * 2; // assume delay slot ! 926: ! 927: if (disinstr.instruction == 0x0000000c) { ! 928: // stepping over a syscall instruction must set the breakpoint ! 929: // at the caller's return address, not the inst after the syscall ! 930: returnvalue = GetRegValue(dp,REGRA); ! 931: } ! 932: else ! 933: if (opcode == 0x00L // SPECIAL ! 934: && (disinstr.special_instr.Funct & ~0x01L) == 0x08L) { ! 935: // jr/jalr only ! 936: if (disinstr.special_instr.Funct == 0x08L || !fStep) // jr or trace ! 937: returnvalue = GetRegValue(dp,disinstr.special_instr.RS + REGBASE); ! 938: } ! 939: else if (opcode == 0x01L) { ! 940: // For BCOND opcode, RT values 0x00 - 0x03, 0x10 - 0x13 ! 941: // are defined as conditional jumps. A 16-bit relative ! 942: // offset is taken if: ! 943: // ! 944: // (RT is even and (RS) < 0 (0x00 = BLTZ, 0x02 = BLTZL, ! 945: // 0x10 = BLTZAL, 0x12 = BLTZALL) ! 946: // OR ! 947: // RT is odd and (RS) >= 0 (0x01 = BGEZ, 0x03 = BGEZL ! 948: // 0x11 = BGEZAL, 0x13 = BGEZALL)) ! 949: // AND ! 950: // (RT is 0x00 to 0x03 (BLTZ BGEZ BLTZL BGEZL non-linking) ! 951: // OR ! 952: // fStep is FALSE (linking and not stepping over)) ! 953: // ! 954: if (((disinstr.immed_instr.RT & ~0x13) == 0x00) && ! 955: (((LONG)GetRegValue(dp,disinstr.immed_instr.RS + REGBASE) >= 0) == ! 956: (BOOLEAN)(disinstr.immed_instr.RT & 0x01)) && ! 957: (((disinstr.immed_instr.RT & 0x10) == 0x00) || !fStep)) ! 958: returnvalue = ((LONG)(SHORT)disinstr.immed_instr.Value << 2) ! 959: + firaddr + sizeof(ULONG); ! 960: } ! 961: else if ((opcode & ~0x01L) == 0x02) { ! 962: // J and JAL opcodes (0x02 and 0x03). Target is ! 963: // 26-bit absolute offset using high four bits of the ! 964: // instruction location. Return target if J opcode or ! 965: // not stepping over JAL. ! 966: // ! 967: if (opcode == 0x02 || !fStep) ! 968: returnvalue = (disinstr.jump_instr.Target << 2) ! 969: + (firaddr & 0xf0000000); ! 970: } ! 971: else if ((opcode & ~0x11L) == 0x04) { ! 972: // BEQ, BNE, BEQL, BNEL opcodes (0x04, 0x05, 0x14, 0x15). ! 973: // Target is 16-bit relative offset to next instruction. ! 974: // Return target if (BEQ or BEQL) and (RS) == (RT), ! 975: // or (BNE or BNEL) and (RS) != (RT). ! 976: // ! 977: if ((BOOLEAN)(opcode & 0x01) == ! 978: (BOOLEAN)(GetRegValue(dp,disinstr.immed_instr.RS + REGBASE) ! 979: != GetRegValue(dp,disinstr.immed_instr.RT + REGBASE))) ! 980: returnvalue = ((long)(short)disinstr.immed_instr.Value << 2) ! 981: + firaddr + sizeof(ULONG); ! 982: } ! 983: else if ((opcode & ~0x11L) == 0x06) { ! 984: // BLEZ, BGTZ, BLEZL, BGTZL opcodes (0x06, 0x07, 0x16, 0x17). ! 985: // Target is 16-bit relative offset to next instruction. ! 986: // Return target if (BLEZ or BLEZL) and (RS) <= 0, ! 987: // or (BGTZ or BGTZL) and (RS) > 0. ! 988: // ! 989: if ((BOOLEAN)(opcode & 0x01) == ! 990: (BOOLEAN)((long)GetRegValue(dp,disinstr.immed_instr.RS ! 991: + REGBASE) > 0)) ! 992: returnvalue = ((long)(short)disinstr.immed_instr.Value << 2) ! 993: + firaddr + sizeof(ULONG); ! 994: } ! 995: else if (opcode == 0x11L ! 996: && (disinstr.immed_instr.RS & ~0x04L) == 0x08L ! 997: && (disinstr.immed_instr.RT & ~0x03L) == 0x00L) { ! 998: // COP1 opcode (0x11) with (RS) == 0x08 or (RS) == 0x0c and ! 999: // (RT) == 0x00 to 0x03, producing BC1F, BC1T, BC1FL, BC1TL ! 1000: // instructions. Return target if (BC1F or BC1FL) and floating ! 1001: // point condition is FALSE or if (BC1T or BC1TL) and condition TRUE. ! 1002: // ! 1003: if ((disinstr.immed_instr.RT & 0x01) == GetRegFlagValue(dp,FLAGFPC)) ! 1004: returnvalue = ((long)(short)disinstr.immed_instr.Value << 2) ! 1005: + firaddr + sizeof(ULONG); ! 1006: } ! 1007: else if ((opcode == 0x38) && (fStep)) { ! 1008: // ! 1009: // stepping over an SC instruction, so skip the immediately following ! 1010: // BEQ instruction. The SC will fail because we are tracing over it, ! 1011: // the branch will be taken, and we will run through the LL/SC again ! 1012: // until the SC succeeds. Then the branch won't be taken, and we ! 1013: // will hit our breakpoint. ! 1014: // ! 1015: ! 1016: returnvalue += sizeof(ULONG); // skip BEQ and BEQ's delay slot ! 1017: } ! 1018: else ! 1019: returnvalue -= sizeof(ULONG); // remove delay slot ! 1020: ! 1021: *result = returnvalue; ! 1022: } ! 1023: ! 1024: /*** fDelayInstruction - returns flag TRUE if delayed instruction ! 1025: * ! 1026: * Purpose: ! 1027: * From a limited disassembly of the instruction pointed ! 1028: * by the FIR register, return TRUE if delayed, else FALSE. ! 1029: * ! 1030: * Input: ! 1031: * None. ! 1032: * ! 1033: * Returns: ! 1034: * set if instruction is delayed execution ! 1035: * ! 1036: *************************************************************************/ ! 1037: ! 1038: BOOLEAN ! 1039: fDelayInstruction (PDEBUGPACKET dp) ! 1040: { ! 1041: BOOLEAN returnvalue; ! 1042: ULONG opcode; ! 1043: ULONG firaddr = GetRegValue(dp,REGFIR); ! 1044: ! 1045: ! 1046: ReadProcessMemory( dp->hProcess, ! 1047: (LPVOID)firaddr, ! 1048: (LPVOID)&disinstr.instruction, ! 1049: sizeof(ULONG), ! 1050: NULL ! 1051: ); ! 1052: ! 1053: opcode = disinstr.jump_instr.Opcode; ! 1054: ! 1055: if (opcode == 0x00) ! 1056: // for SPECIAL opcode, JR and JALR use a delay slot ! 1057: // ! 1058: returnvalue = (BOOLEAN)((disinstr.special_instr.Funct & ~1L) ! 1059: == 0x08); ! 1060: else if (opcode == 0x01) ! 1061: // for BCOND opcode, RT == 0x00 to 0x03 or 0x10 to 0x13 have slot ! 1062: // BLTZ, BGEZ, BLTZL, BGEZL, BLTZAL, BGEZAL, BLTZALL, BGEZALL ! 1063: // ! 1064: returnvalue = (BOOLEAN)((disinstr.special_instr.RT & ~0x13L) ! 1065: == 0x00); ! 1066: else if ((opcode & ~0x07L) == 0x00) ! 1067: // opcodes 0x02 to 0x07 have delay slot (0x00 and 0x01 tested above) ! 1068: // J, JAL, BEQ, BNE, BLEZ, BGTZ ! 1069: // ! 1070: returnvalue = TRUE; ! 1071: else if ((opcode & ~0x03L) == 0x14) ! 1072: // opcodes 0x14 to 0x17 have delay slot - BEQL, BNEL, BLEZL, BGTZL ! 1073: // ! 1074: returnvalue = TRUE; ! 1075: else ! 1076: // opcodes 0x10 to 0x13 - COPn - BCxF, BCxT, BCxFL, BCxTL ! 1077: // ! 1078: returnvalue = (BOOLEAN)((opcode & ~0x03L) == 0x10 ! 1079: && (disinstr.special_instr.RS & ~0x04L) == 0x08 ! 1080: && (disinstr.special_instr.RT & ~0x03L) == 0x00); ! 1081: ! 1082: return returnvalue; ! 1083: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.