|
|
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.