1 /*###################################################################################################
2 **
3 **
4 ** jagdasm.c
5 ** Disassembler for the portable R3000 emulator.
6 ** Written by Aaron Giles
7 **
8 **
9 **#################################################################################################*/
10
11 #include <stdio.h>
12
13 #include "driver.h"
14 #include "r3000.h"
15
16
17 static const char *reg[32] =
18 {
19 "0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
20 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
21 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
22 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31"
23 };
24
25 #define COP0_Index 0
26 #define COP0_Random 1
27 #define COP0_EntryLo 2
28 #define COP0_Context 4
29 #define COP0_BadVAddr 8
30 #define COP0_Status 12
31 #define COP0_Cause 13
32 #define COP0_EPC 14
33 #define COP0_PRId 15
34
35 static const char *cpreg[4][32] =
36 {
37 {
38 "Index","Random","EntryLo","cpr3", "Context", "cpr5", "cpr6", "cpr7",
39 "BadVAddr", "cpr9", "cpr10","cpr11","SR","Cause","EPC","PRId",
40 "cpr16","cpr17","cpr18","cpr19","cpr20","cpr21","cpr22","cpr23",
41 "cpr24","cpr25","cpr26","cpr27","cpr28","cpr29","cpr30","cpr31"
42 },
43 {
44 "cpr0", "cpr1", "cpr2", "cpr3", "cpr4", "cpr5", "cpr6", "cpr7",
45 "cpr8", "cpr9", "cpr10","cpr11","cpr12","cpr13","cpr14","cpr15",
46 "cpr16","cpr17","cpr18","cpr19","cpr20","cpr21","cpr22","cpr23",
47 "cpr24","cpr25","cpr26","cpr27","cpr28","cpr29","cpr30","cpr31"
48 },
49 {
50 "cpr0", "cpr1", "cpr2", "cpr3", "cpr4", "cpr5", "cpr6", "cpr7",
51 "cpr8", "cpr9", "cpr10","cpr11","cpr12","cpr13","cpr14","cpr15",
52 "cpr16","cpr17","cpr18","cpr19","cpr20","cpr21","cpr22","cpr23",
53 "cpr24","cpr25","cpr26","cpr27","cpr28","cpr29","cpr30","cpr31"
54 },
55 {
56 "cpr0", "cpr1", "cpr2", "cpr3", "cpr4", "cpr5", "cpr6", "cpr7",
57 "cpr8", "cpr9", "cpr10","cpr11","cpr12","cpr13","cpr14","cpr15",
58 "cpr16","cpr17","cpr18","cpr19","cpr20","cpr21","cpr22","cpr23",
59 "cpr24","cpr25","cpr26","cpr27","cpr28","cpr29","cpr30","cpr31"
60 }
61 };
62
63
64 static const char *ccreg[4][32] =
65 {
66 {
67 "ccr0", "ccr1", "ccr2", "ccr3", "ccr4", "ccr5", "ccr6", "ccr7",
68 "ccr8", "ccr9", "ccr10","ccr11","ccr12","ccr13","ccr14","ccr15",
69 "ccr16","ccr17","ccr18","ccr19","ccr20","ccr21","ccr22","ccr23",
70 "ccr24","ccr25","ccr26","ccr27","ccr28","ccr29","ccr30","ccr31"
71 },
72 {
73 "ccr0", "ccr1", "ccr2", "ccr3", "ccr4", "ccr5", "ccr6", "ccr7",
74 "ccr8", "ccr9", "ccr10","ccr11","ccr12","ccr13","ccr14","ccr15",
75 "ccr16","ccr17","ccr18","ccr19","ccr20","ccr21","ccr22","ccr23",
76 "ccr24","ccr25","ccr26","ccr27","ccr28","ccr29","ccr30","ccr31"
77 },
78 {
79 "ccr0", "ccr1", "ccr2", "ccr3", "ccr4", "ccr5", "ccr6", "ccr7",
80 "ccr8", "ccr9", "ccr10","ccr11","ccr12","ccr13","ccr14","ccr15",
81 "ccr16","ccr17","ccr18","ccr19","ccr20","ccr21","ccr22","ccr23",
82 "ccr24","ccr25","ccr26","ccr27","ccr28","ccr29","ccr30","ccr31"
83 },
84 {
85 "ccr0", "ccr1", "ccr2", "ccr3", "ccr4", "ccr5", "ccr6", "ccr7",
86 "ccr8", "ccr9", "ccr10","ccr11","ccr12","ccr13","ccr14","ccr15",
87 "ccr16","ccr17","ccr18","ccr19","ccr20","ccr21","ccr22","ccr23",
88 "ccr24","ccr25","ccr26","ccr27","ccr28","ccr29","ccr30","ccr31"
89 }
90 };
91
92
93 /*###################################################################################################
94 ** MEMORY ACCESSORS
95 **#################################################################################################*/
96
97 #define ROPCODE(pc) cpu_readop32(pc)
98
99
100 /*###################################################################################################
101 ** CODE CODE
102 **#################################################################################################*/
103
signed_16bit(INT16 val)104 static INLINE char *signed_16bit(INT16 val)
105 {
106 static char temp[10];
107 if (val < 0)
108 sprintf(temp, "-$%x", -val);
109 else
110 sprintf(temp, "$%x", val);
111 return temp;
112 }
113
dasm_cop(UINT32 pc,int cop,UINT32 op,char * buffer)114 static void dasm_cop(UINT32 pc, int cop, UINT32 op, char *buffer)
115 {
116 int rt = (op >> 16) & 31;
117 int rd = (op >> 11) & 31;
118
119 switch ((op >> 21) & 31)
120 {
121 case 0x00: sprintf(buffer, "mfc%d %s,%s", cop, reg[rt], cpreg[cop][rd]); break;
122 case 0x02: sprintf(buffer, "cfc%d %s,%s", cop, reg[rt], ccreg[cop][rd]); break;
123 case 0x04: sprintf(buffer, "mtc%d %s,%s", cop, reg[rt], cpreg[cop][rd]); break;
124 case 0x06: sprintf(buffer, "ctc%d %s,%s", cop, reg[rt], ccreg[cop][rd]); break;
125 case 0x08: /* BC */
126 switch (rt)
127 {
128 case 0x00: sprintf(buffer, "bc%df $%08x", cop, pc + 4 + ((INT16)op << 2)); break;
129 case 0x01: sprintf(buffer, "bc%dt $%08x", cop, pc + 4 + ((INT16)op << 2)); break;
130 case 0x02: sprintf(buffer, "bc%dfl [invalid]", cop); break;
131 case 0x03: sprintf(buffer, "bc%dtl [invalid]", cop); break;
132 default: sprintf(buffer, "dc.l $%08x [invalid]", op); break;
133 }
134 break;
135 case 0x10:
136 case 0x11:
137 case 0x12:
138 case 0x13:
139 case 0x14:
140 case 0x15:
141 case 0x16:
142 case 0x17:
143 case 0x18:
144 case 0x19:
145 case 0x1a:
146 case 0x1b:
147 case 0x1c:
148 case 0x1d:
149 case 0x1e:
150 case 0x1f: /* COP */
151 if (cop == 0)
152 {
153 switch (op & 0x01ffffff)
154 {
155 case 0x01: sprintf(buffer, "tlbr"); break;
156 case 0x02: sprintf(buffer, "tlbwi"); break;
157 case 0x06: sprintf(buffer, "tlbwr"); break;
158 case 0x08: sprintf(buffer, "tlbp"); break;
159 case 0x10: sprintf(buffer, "rfe"); break;
160 case 0x18: sprintf(buffer, "eret [invalid]"); break;
161 default: sprintf(buffer, "cop%d $%07x", cop, op & 0x01ffffff); break;
162 }
163 }
164 else
165 sprintf(buffer, "cop%d $%07x", cop, op & 0x01ffffff); break;
166 default: sprintf(buffer, "dc.l $%08x [invalid]", op); break;
167 }
168 }
169
dasmr3k(char * buffer,unsigned pc)170 unsigned dasmr3k(char *buffer, unsigned pc)
171 {
172 UINT32 op = ROPCODE(pc);
173 int rs = (op >> 21) & 31;
174 int rt = (op >> 16) & 31;
175 int rd = (op >> 11) & 31;
176 int shift = (op >> 6) & 31;
177
178 switch (op >> 26)
179 {
180 case 0x00: /* SPECIAL */
181 switch (op & 63)
182 {
183 case 0x00: if (op == 0)
184 sprintf(buffer, "nop");
185 else
186 sprintf(buffer, "sll %s,%s,%d", reg[rd], reg[rt], shift); break;
187 case 0x02: sprintf(buffer, "srl %s,%s,%d", reg[rd], reg[rt], shift); break;
188 case 0x03: sprintf(buffer, "sra %s,%s,%d", reg[rd], reg[rt], shift); break;
189 case 0x04: sprintf(buffer, "sllv %s,%s,%s", reg[rd], reg[rt], reg[rs]); break;
190 case 0x06: sprintf(buffer, "srlv %s,%s,%s", reg[rd], reg[rt], reg[rs]); break;
191 case 0x07: sprintf(buffer, "srav %s,%s,%s", reg[rd], reg[rt], reg[rs]); break;
192 case 0x08: sprintf(buffer, "jr %s", reg[rs]); break;
193 case 0x09: if (rd == 31)
194 sprintf(buffer, "jalr %s", reg[rs]);
195 else
196 sprintf(buffer, "jalr %s,%s", reg[rs], reg[rd]); break;
197 case 0x0c: sprintf(buffer, "syscall"); break;
198 case 0x0d: sprintf(buffer, "break"); break;
199 case 0x0f: sprintf(buffer, "sync [invalid]"); break;
200 case 0x10: sprintf(buffer, "mfhi %s", reg[rd]); break;
201 case 0x11: sprintf(buffer, "mthi %s", reg[rs]); break;
202 case 0x12: sprintf(buffer, "mflo %s", reg[rd]); break;
203 case 0x13: sprintf(buffer, "mtlo %s", reg[rs]); break;
204 case 0x18: sprintf(buffer, "mult %s,%s", reg[rs], reg[rt]); break;
205 case 0x19: sprintf(buffer, "multu %s,%s", reg[rs], reg[rt]); break;
206 case 0x1a: sprintf(buffer, "div %s,%s", reg[rs], reg[rt]); break;
207 case 0x1b: sprintf(buffer, "divu %s,%s", reg[rs], reg[rt]); break;
208 case 0x20: sprintf(buffer, "add %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
209 case 0x21: sprintf(buffer, "addu %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
210 case 0x22: sprintf(buffer, "sub %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
211 case 0x23: sprintf(buffer, "subu %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
212 case 0x24: sprintf(buffer, "and %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
213 case 0x25: sprintf(buffer, "or %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
214 case 0x26: sprintf(buffer, "xor %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
215 case 0x27: sprintf(buffer, "nor %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
216 case 0x2a: sprintf(buffer, "slt %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
217 case 0x2b: sprintf(buffer, "sltu %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
218 case 0x30: sprintf(buffer, "teq [invalid]"); break;
219 case 0x31: sprintf(buffer, "tgeu [invalid]"); break;
220 case 0x32: sprintf(buffer, "tlt [invalid]"); break;
221 case 0x33: sprintf(buffer, "tltu [invalid]"); break;
222 case 0x34: sprintf(buffer, "tge [invalid]"); break;
223 case 0x36: sprintf(buffer, "tne [invalid]"); break;
224 default: sprintf(buffer, "dc.l $%08x [invalid]", op); break;
225 }
226 break;
227
228 case 0x01: /* REGIMM */
229 switch ((op >> 16) & 31)
230 {
231 case 0x00: sprintf(buffer, "bltz %s,$%08x", reg[rs], pc + 4 + ((INT16)op << 2)); break;
232 case 0x01: sprintf(buffer, "bgez %s,$%08x", reg[rs], pc + 4 + ((INT16)op << 2)); break;
233 case 0x02: sprintf(buffer, "bltzl [invalid]"); break;
234 case 0x03: sprintf(buffer, "bgezl [invalid]"); break;
235 case 0x08: sprintf(buffer, "tgei [invalid]"); break;
236 case 0x09: sprintf(buffer, "tgeiu [invalid]"); break;
237 case 0x0a: sprintf(buffer, "tlti [invalid]"); break;
238 case 0x0b: sprintf(buffer, "tltiu [invalid]"); break;
239 case 0x0c: sprintf(buffer, "teqi [invalid]"); break;
240 case 0x0e: sprintf(buffer, "tnei [invalid]"); break;
241 case 0x10: sprintf(buffer, "bltzal %s,$%08x", reg[rs], pc + 4 + ((INT16)op << 2)); break;
242 case 0x11: sprintf(buffer, "bgezal %s,$%08x", reg[rs], pc + 4 + ((INT16)op << 2)); break;
243 case 0x12: sprintf(buffer, "bltzall [invalid]"); break;
244 case 0x13: sprintf(buffer, "bgezall [invalid]"); break;
245 default: sprintf(buffer, "dc.l $%08x [invalid]", op); break;
246 }
247 break;
248
249 case 0x02: sprintf(buffer, "j $%08x", (pc & 0xf0000000) | ((op & 0x0fffffff) << 2)); break;
250 case 0x03: sprintf(buffer, "jal $%08x", (pc & 0xf0000000) | ((op & 0x0fffffff) << 2)); break;
251 case 0x04: if (rs == 0 && rt == 0)
252 sprintf(buffer, "b $%08x", pc + 4 + ((INT16)op << 2));
253 else
254 sprintf(buffer, "beq %s,%s,$%08x", reg[rs], reg[rt], pc + 4 + ((INT16)op << 2));break;
255 case 0x05: sprintf(buffer, "bne %s,%s,$%08x", reg[rs], reg[rt], pc + 4 + ((INT16)op << 2));break;
256 case 0x06: sprintf(buffer, "blez %s,$%08x", reg[rs], pc + 4 + ((INT16)op << 2)); break;
257 case 0x07: sprintf(buffer, "bgtz %s,$%08x", reg[rs], pc + 4 + ((INT16)op << 2)); break;
258 case 0x08: sprintf(buffer, "addi %s,%s,%s", reg[rt], reg[rs], signed_16bit(op)); break;
259 case 0x09: sprintf(buffer, "addiu %s,%s,%s", reg[rt], reg[rs], signed_16bit(op)); break;
260 case 0x0a: sprintf(buffer, "slti %s,%s,%s", reg[rt], reg[rs], signed_16bit(op)); break;
261 case 0x0b: sprintf(buffer, "sltiu %s,%s,%s", reg[rt], reg[rs], signed_16bit(op)); break;
262 case 0x0c: sprintf(buffer, "andi %s,%s,$%04x", reg[rt], reg[rs], (UINT16)op); break;
263 case 0x0d: sprintf(buffer, "ori %s,%s,$%04x", reg[rt], reg[rs], (UINT16)op); break;
264 case 0x0e: sprintf(buffer, "xori %s,%s,$%04x", reg[rt], reg[rs], (UINT16)op); break;
265 case 0x0f: sprintf(buffer, "lui %s,$%04x", reg[rt], (UINT16)op); break;
266 case 0x10: dasm_cop(pc, 0, op, buffer); break;
267 case 0x11: dasm_cop(pc, 1, op, buffer); break;
268 case 0x12: dasm_cop(pc, 2, op, buffer); break;
269 case 0x13: dasm_cop(pc, 3, op, buffer); break;
270 case 0x14: sprintf(buffer, "beql [invalid]"); break;
271 case 0x15: sprintf(buffer, "bnel [invalid]"); break;
272 case 0x16: sprintf(buffer, "blezl [invalid]"); break;
273 case 0x17: sprintf(buffer, "bgtzl [invalid]"); break;
274 case 0x20: sprintf(buffer, "lb %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
275 case 0x21: sprintf(buffer, "lh %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
276 case 0x22: sprintf(buffer, "lwl %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
277 case 0x23: sprintf(buffer, "lw %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
278 case 0x24: sprintf(buffer, "lbu %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
279 case 0x25: sprintf(buffer, "lhu %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
280 case 0x26: sprintf(buffer, "lwr %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
281 case 0x28: sprintf(buffer, "sb %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
282 case 0x29: sprintf(buffer, "sh %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
283 case 0x2a: sprintf(buffer, "swl %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
284 case 0x2b: sprintf(buffer, "sw %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
285 case 0x2e: sprintf(buffer, "swr %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
286 case 0x2f: sprintf(buffer, "cache [invalid]"); break;
287 case 0x30: sprintf(buffer, "ll [invalid]"); break;
288 case 0x31: sprintf(buffer, "lwc1 %s,%s(%s)", cpreg[1][rt], signed_16bit(op), reg[rs]); break;
289 case 0x32: sprintf(buffer, "lwc2 %s,%s(%s)", cpreg[2][rt], signed_16bit(op), reg[rs]); break;
290 case 0x33: sprintf(buffer, "lwc3 %s,%s(%s)", cpreg[3][rt], signed_16bit(op), reg[rs]); break;
291 case 0x34: sprintf(buffer, "ldc0 [invalid]"); break;
292 case 0x35: sprintf(buffer, "ldc1 [invalid]"); break;
293 case 0x36: sprintf(buffer, "ldc2 [invalid]"); break;
294 case 0x37: sprintf(buffer, "ldc3 [invalid]"); break;
295 case 0x38: sprintf(buffer, "sc [invalid]"); break;
296 case 0x39: sprintf(buffer, "swc1 %s,%s(%s)", cpreg[1][rt], signed_16bit(op), reg[rs]); break;
297 case 0x3a: sprintf(buffer, "swc2 %s,%s(%s)", cpreg[2][rt], signed_16bit(op), reg[rs]); break;
298 case 0x3b: sprintf(buffer, "swc3 %s,%s(%s)", cpreg[3][rt], signed_16bit(op), reg[rs]); break;
299 case 0x3c: sprintf(buffer, "sdc0 [invalid]"); break;
300 case 0x3d: sprintf(buffer, "sdc1 [invalid]"); break;
301 case 0x3e: sprintf(buffer, "sdc2 [invalid]"); break;
302 case 0x3f: sprintf(buffer, "sdc3 [invalid]"); break;
303 default: sprintf(buffer, "dc.l $%08x [invalid]", op); break;
304 }
305 return 4;
306 }
307