1 /*###################################################################################################
2 **
3 **
4 **		4600dasm.c
5 **		Disassembler for the portable R4600 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 
26 static const char *cpreg[4][32] =
27 {
28 	{
29 		"Index","Random","EntryLo0","EntryLo1","Context","PageMask","Wired","Error",
30 		"BadVAddr","Count","EntryHi","Compare","SR","Cause","EPC","PRId",
31 		"Config","LLAddr","WatchLo","WatchHi","XContext","cpr21","cpr22","cpr23",
32 		"cpr24","cpr25","ECC","CacheError","TagLo","TagHi","ErrorEPC","cpr31"
33 	},
34 	{
35 		"f0",	"f1",	"f2",	"f3",	"f4",	"f5",	"f6",	"f7",
36 		"f8",	"f9",	"f10",	"f11",	"f12",	"f13",	"f14",	"f15",
37 		"f16",	"f17",	"f18",	"f19",	"f20",	"f21",	"f22",	"f23",
38 		"f24",	"f25",	"f26",	"f27",	"f28",	"f29",	"f30",	"f31"
39 	},
40 	{
41 		"cpr0",	"cpr1",	"cpr2",	"cpr3",	"cpr4",	"cpr5",	"cpr6",	"cpr7",
42 		"cpr8",	"cpr9",	"cpr10","cpr11","cpr12","cpr13","cpr14","cpr15",
43 		"cpr16","cpr17","cpr18","cpr19","cpr20","cpr21","cpr22","cpr23",
44 		"cpr24","cpr25","cpr26","cpr27","cpr28","cpr29","cpr30","cpr31"
45 	},
46 	{
47 		"cpr0",	"cpr1",	"cpr2",	"cpr3",	"cpr4",	"cpr5",	"cpr6",	"cpr7",
48 		"cpr8",	"cpr9",	"cpr10","cpr11","cpr12","cpr13","cpr14","cpr15",
49 		"cpr16","cpr17","cpr18","cpr19","cpr20","cpr21","cpr22","cpr23",
50 		"cpr24","cpr25","cpr26","cpr27","cpr28","cpr29","cpr30","cpr31"
51 	}
52 };
53 
54 
55 static const char *ccreg[4][32] =
56 {
57 	{
58 		"ccr0",	"ccr1",	"ccr2",	"ccr3",	"ccr4",	"ccr5",	"ccr6",	"ccr7",
59 		"ccr8",	"ccr9",	"ccr10","ccr11","ccr12","ccr13","ccr14","ccr15",
60 		"ccr16","ccr17","ccr18","ccr19","ccr20","ccr21","ccr22","ccr23",
61 		"ccr24","ccr25","ccr26","ccr27","ccr28","ccr29","ccr30","ccr31"
62 	},
63 	{
64 		"ccr0",	"ccr1",	"ccr2",	"ccr3",	"ccr4",	"ccr5",	"ccr6",	"ccr7",
65 		"ccr8",	"ccr9",	"ccr10","ccr11","ccr12","ccr13","ccr14","ccr15",
66 		"ccr16","ccr17","ccr18","ccr19","ccr20","ccr21","ccr22","ccr23",
67 		"ccr24","ccr25","ccr26","ccr27","ccr28","ccr29","ccr30","ccr31"
68 	},
69 	{
70 		"ccr0",	"ccr1",	"ccr2",	"ccr3",	"ccr4",	"ccr5",	"ccr6",	"ccr7",
71 		"ccr8",	"ccr9",	"ccr10","ccr11","ccr12","ccr13","ccr14","ccr15",
72 		"ccr16","ccr17","ccr18","ccr19","ccr20","ccr21","ccr22","ccr23",
73 		"ccr24","ccr25","ccr26","ccr27","ccr28","ccr29","ccr30","ccr31"
74 	},
75 	{
76 		"ccr0",	"ccr1",	"ccr2",	"ccr3",	"ccr4",	"ccr5",	"ccr6",	"ccr7",
77 		"ccr8",	"ccr9",	"ccr10","ccr11","ccr12","ccr13","ccr14","ccr15",
78 		"ccr16","ccr17","ccr18","ccr19","ccr20","ccr21","ccr22","ccr23",
79 		"ccr24","ccr25","ccr26","ccr27","ccr28","ccr29","ccr30","ccr31"
80 	}
81 };
82 
83 
84 /*###################################################################################################
85 **	MEMORY ACCESSORS
86 **#################################################################################################*/
87 
88 #define ROPCODE(pc)		cpu_readop32(pc)
89 
90 
91 /*###################################################################################################
92 **	CODE CODE
93 **#################################################################################################*/
94 
signed_16bit(INT16 val)95 static INLINE char *signed_16bit(INT16 val)
96 {
97 	static char temp[10];
98 	if (val < 0)
99 		sprintf(temp, "-$%x", -val);
100 	else
101 		sprintf(temp, "$%x", val);
102 	return temp;
103 }
104 
dasm_cop0(UINT32 pc,UINT32 op,char * buffer)105 static void dasm_cop0(UINT32 pc, UINT32 op, char *buffer)
106 {
107 	int rt = (op >> 16) & 31;
108 	int rd = (op >> 11) & 31;
109 
110 	switch ((op >> 21) & 31)
111 	{
112 		case 0x00:	sprintf(buffer, "mfc0   %s,%s", reg[rt], cpreg[0][rd]);					break;
113 		case 0x01:	sprintf(buffer, "dmfc0  %s,%s", reg[rt], cpreg[0][rd]);					break;
114 		case 0x02:	sprintf(buffer, "cfc0   %s,%s", reg[rt], ccreg[0][rd]);					break;
115 		case 0x04:	sprintf(buffer, "mtc0   %s,%s", reg[rt], cpreg[0][rd]);					break;
116 		case 0x05:	sprintf(buffer, "dmtc0  %s,%s", reg[rt], cpreg[0][rd]);					break;
117 		case 0x06:	sprintf(buffer, "ctc0   %s,%s", reg[rt], ccreg[0][rd]);					break;
118 		case 0x08:	/* BC */
119 			switch (rt)
120 			{
121 				case 0x00:	sprintf(buffer, "bc0f   $%08x", pc + 4 + ((INT16)op << 2));		break;
122 				case 0x01:	sprintf(buffer, "bc0t   $%08x", pc + 4 + ((INT16)op << 2));		break;
123 				case 0x02:	sprintf(buffer, "bc0fl [invalid]");								break;
124 				case 0x03:	sprintf(buffer, "bc0tl [invalid]");								break;
125 				default:	sprintf(buffer, "dc.l   $%08x [invalid]", op);					break;
126 			}
127 			break;
128 		case 0x10:
129 		case 0x11:
130 		case 0x12:
131 		case 0x13:
132 		case 0x14:
133 		case 0x15:
134 		case 0x16:
135 		case 0x17:
136 		case 0x18:
137 		case 0x19:
138 		case 0x1a:
139 		case 0x1b:
140 		case 0x1c:
141 		case 0x1d:
142 		case 0x1e:
143 		case 0x1f:	/* COP */
144 			switch (op & 0x01ffffff)
145 			{
146 				case 0x01:	sprintf(buffer, "tlbr");											break;
147 				case 0x02:	sprintf(buffer, "tlbwi");											break;
148 				case 0x06:	sprintf(buffer, "tlbwr");											break;
149 				case 0x08:	sprintf(buffer, "tlbp");											break;
150 				case 0x10:	sprintf(buffer, "rfe");												break;
151 				case 0x18:	sprintf(buffer, "eret [invalid]");									break;
152 				default:	sprintf(buffer, "cop0  $%07x", op & 0x01ffffff);					break;
153 			}
154 			break;
155 		default:	sprintf(buffer, "dc.l   $%08x [invalid]", op);								break;
156 	}
157 }
158 
dasm_cop1(UINT32 pc,UINT32 op,char * buffer)159 static void dasm_cop1(UINT32 pc, UINT32 op, char *buffer)
160 {
161 	static const char *format_table[] =
162 	{
163 		"?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?",
164 		"s","d","?","?","w","l","?","?","?","?","?","?","?","?","?","?"
165 	};
166 	const char *fmt = format_table[(op >> 21) & 31];
167 	int ft = (op >> 16) & 31;
168 	int fs = (op >> 11) & 31;
169 	int fd = (op >> 6) & 31;
170 	int rt = (op >> 16) & 31;
171 	int rd = (op >> 11) & 31;
172 
173 	switch ((op >> 21) & 31)
174 	{
175 		case 0x00:	sprintf(buffer, "mfc1   %s,%s", reg[rt], cpreg[1][rd]);						break;
176 		case 0x01:	sprintf(buffer, "dmfc1  %s,%s", reg[rt], cpreg[1][rd]);						break;
177 		case 0x02:	sprintf(buffer, "cfc1   %s,%s", reg[rt], ccreg[1][rd]);						break;
178 		case 0x04:	sprintf(buffer, "mtc1   %s,%s", reg[rt], cpreg[1][rd]);						break;
179 		case 0x05:	sprintf(buffer, "dmtc1  %s,%s", reg[rt], cpreg[1][rd]);						break;
180 		case 0x06:	sprintf(buffer, "ctc1   %s,%s", reg[rt], ccreg[1][rd]);						break;
181 		case 0x08:	/* BC */
182 			switch (rt & 3)
183 			{
184 				case 0x00:	sprintf(buffer, "bc1f   $%08x,%d", pc + 4 + ((INT16)op << 2), (op >> 18) & 7);		break;
185 				case 0x01:	sprintf(buffer, "bc1t   $%08x,%d", pc + 4 + ((INT16)op << 2), (op >> 18) & 7);		break;
186 				case 0x02:	sprintf(buffer, "bc1fl  $%08x,%d", pc + 4 + ((INT16)op << 2), (op >> 18) & 7);		break;
187 				case 0x03:	sprintf(buffer, "bc1tl  $%08x,%d", pc + 4 + ((INT16)op << 2), (op >> 18) & 7);		break;
188 			}
189 			break;
190 		default:	/* COP */
191 			switch (op & 0x3f)
192 			{
193 				case 0x00:	sprintf(buffer, "add.%s  %s,%s,%s", fmt, cpreg[1][fd], cpreg[1][fs], cpreg[1][ft]);	break;
194 				case 0x01:	sprintf(buffer, "sub.%s  %s,%s,%s", fmt, cpreg[1][fd], cpreg[1][fs], cpreg[1][ft]);	break;
195 				case 0x02:	sprintf(buffer, "mul.%s  %s,%s,%s", fmt, cpreg[1][fd], cpreg[1][fs], cpreg[1][ft]);	break;
196 				case 0x03:	sprintf(buffer, "div.%s  %s,%s,%s", fmt, cpreg[1][fd], cpreg[1][fs], cpreg[1][ft]);	break;
197 				case 0x04:	sprintf(buffer, "sqrt.%s %s,%s,%s", fmt, cpreg[1][fd], cpreg[1][fs], cpreg[1][ft]);	break;
198 				case 0x05:	sprintf(buffer, "abs.%s  %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]);					break;
199 				case 0x06:	sprintf(buffer, "mov.%s  %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]);					break;
200 				case 0x07:	sprintf(buffer, "neg.%s  %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]);					break;
201 				case 0x08:	sprintf(buffer, "round.l.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]);				break;
202 				case 0x09:	sprintf(buffer, "trunc.l.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]);				break;
203 				case 0x0a:	sprintf(buffer, "ceil.l.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]);				break;
204 				case 0x0b:	sprintf(buffer, "floor.l.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]);				break;
205 				case 0x0c:	sprintf(buffer, "round.w.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]);				break;
206 				case 0x0d:	sprintf(buffer, "trunc.w.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]);				break;
207 				case 0x0e:	sprintf(buffer, "ceil.w.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]);				break;
208 				case 0x0f:	sprintf(buffer, "floor.w.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]);				break;
209 				case 0x11:	sprintf(buffer, "mov%c.%s  %s,%s,%d", ((op >> 16) & 1) ? 't' : 'f', fmt, cpreg[1][fd], cpreg[1][fs], (op >> 18) & 7);	break;
210 				case 0x12:	sprintf(buffer, "movz.%s  %s,%s,%s", fmt, cpreg[1][fd], cpreg[1][fs], reg[rt]);		break;
211 				case 0x13:	sprintf(buffer, "movn.%s  %s,%s,%s", fmt, cpreg[1][fd], cpreg[1][fs], reg[rt]);		break;
212 				case 0x15:	sprintf(buffer, "recip.%s  %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]);				break;
213 				case 0x16:	sprintf(buffer, "rsqrt.%s  %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]);				break;
214 				case 0x20:	sprintf(buffer, "cvt.s.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]);					break;
215 				case 0x21:	sprintf(buffer, "cvt.d.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]);					break;
216 				case 0x24:	sprintf(buffer, "cvt.w.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]);					break;
217 				case 0x25:	sprintf(buffer, "cvt.l.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]);					break;
218 				case 0x30:	sprintf(buffer, "c.f.%s  %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7);	break;
219 				case 0x31:	sprintf(buffer, "c.un.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7);	break;
220 				case 0x32:	sprintf(buffer, "c.eq.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7);	break;
221 				case 0x33:	sprintf(buffer, "c.ueq.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7);	break;
222 				case 0x34:	sprintf(buffer, "c.olt.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7);	break;
223 				case 0x35:	sprintf(buffer, "c.ult.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7);	break;
224 				case 0x36:	sprintf(buffer, "c.ole.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7);	break;
225 				case 0x37:	sprintf(buffer, "c.ule.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7);	break;
226 				case 0x38:	sprintf(buffer, "c.sf.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7);	break;
227 				case 0x39:	sprintf(buffer, "c.ngle.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7);break;
228 				case 0x3a:	sprintf(buffer, "c.seq.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7);	break;
229 				case 0x3b:	sprintf(buffer, "c.ngl.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7);	break;
230 				case 0x3c:	sprintf(buffer, "c.lt.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7);	break;
231 				case 0x3d:	sprintf(buffer, "c.nge.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7);	break;
232 				case 0x3e:	sprintf(buffer, "c.le.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7);	break;
233 				case 0x3f:	sprintf(buffer, "c.ngt.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7);	break;
234 				default:	sprintf(buffer, "cop1   $%07x", op & 0x01ffffff);									break;
235 			}
236 			break;
237 	}
238 }
239 
dasm_cop1x(UINT32 pc,UINT32 op,char * buffer)240 static void dasm_cop1x(UINT32 pc, UINT32 op, char *buffer)
241 {
242 	static const char *format3_table[] =
243 	{
244 		"s","d","?","?","w","l","?","?"
245 	};
246 	const char *fmt3 = format3_table[op & 7];
247 	int fr = (op >> 21) & 31;
248 	int ft = (op >> 16) & 31;
249 	int fs = (op >> 11) & 31;
250 	int fd = (op >> 6) & 31;
251 	int rs = (op >> 21) & 31;
252 	int rt = (op >> 16) & 31;
253 	int rd = (op >> 11) & 31;
254 
255 	switch (op & 0x3f)
256 	{
257 		case 0x00:	sprintf(buffer, "lwxc1   %s,%s(%s)", cpreg[1][fd], reg[rt], reg[rs]);				break;
258 		case 0x01:	sprintf(buffer, "ldxc1   %s,%s(%s)", cpreg[1][fd], reg[rt], reg[rs]);				break;
259 		case 0x08:	sprintf(buffer, "swxc1   %s,%s(%s)", cpreg[1][fd], reg[rt], reg[rs]);				break;
260 		case 0x09:	sprintf(buffer, "sdxc1   %s,%s(%s)", cpreg[1][fd], reg[rt], reg[rs]);				break;
261 		case 0x0f:	sprintf(buffer, "prefx   %d,%s(%s)", rd, reg[rt], reg[rs]);							break;
262 		case 0x20:
263 		case 0x21:
264 		case 0x22:
265 		case 0x23:
266 		case 0x24:
267 		case 0x25:
268 		case 0x26:
269 		case 0x27:	sprintf(buffer, "madd.%s  %s,%s,%s,%s", fmt3, cpreg[1][fd], cpreg[1][fr], cpreg[1][fs], cpreg[1][ft]); break;
270 		case 0x28:
271 		case 0x29:
272 		case 0x2a:
273 		case 0x2b:
274 		case 0x2c:
275 		case 0x2d:
276 		case 0x2e:
277 		case 0x2f:	sprintf(buffer, "msub.%s  %s,%s,%s,%s", fmt3, cpreg[1][fd], cpreg[1][fr], cpreg[1][fs], cpreg[1][ft]); break;
278 		case 0x30:
279 		case 0x31:
280 		case 0x32:
281 		case 0x33:
282 		case 0x34:
283 		case 0x35:
284 		case 0x36:
285 		case 0x37:	sprintf(buffer, "nmadd.%s %s,%s,%s,%s", fmt3, cpreg[1][fd], cpreg[1][fr], cpreg[1][fs], cpreg[1][ft]); break;
286 		case 0x38:
287 		case 0x39:
288 		case 0x3a:
289 		case 0x3b:
290 		case 0x3c:
291 		case 0x3d:
292 		case 0x3e:
293 		case 0x3f:	sprintf(buffer, "nmsub.%s %s,%s,%s,%s", fmt3, cpreg[1][fd], cpreg[1][fr], cpreg[1][fs], cpreg[1][ft]); break;
294 		default:	sprintf(buffer, "cop1   $%07x", op & 0x01ffffff);									break;
295 	}
296 }
297 
dasm_cop2(UINT32 pc,UINT32 op,char * buffer)298 static void dasm_cop2(UINT32 pc, UINT32 op, char *buffer)
299 {
300 	int rt = (op >> 16) & 31;
301 	int rd = (op >> 11) & 31;
302 
303 	switch ((op >> 21) & 31)
304 	{
305 		case 0x00:	sprintf(buffer, "mfc2   %s,%s", reg[rt], cpreg[2][rd]);					break;
306 		case 0x01:	sprintf(buffer, "dmfc2  %s,%s", reg[rt], cpreg[2][rd]);					break;
307 		case 0x02:	sprintf(buffer, "cfc2   %s,%s", reg[rt], ccreg[2][rd]);					break;
308 		case 0x04:	sprintf(buffer, "mtc2   %s,%s", reg[rt], cpreg[2][rd]);					break;
309 		case 0x05:	sprintf(buffer, "dmtc2  %s,%s", reg[rt], cpreg[2][rd]);					break;
310 		case 0x06:	sprintf(buffer, "ctc2   %s,%s", reg[rt], ccreg[2][rd]);					break;
311 		case 0x08:	/* BC */
312 			switch (rt)
313 			{
314 				case 0x00:	sprintf(buffer, "bc2f   $%08x", pc + 4 + ((INT16)op << 2));		break;
315 				case 0x01:	sprintf(buffer, "bc2t   $%08x", pc + 4 + ((INT16)op << 2));		break;
316 				case 0x02:	sprintf(buffer, "bc2fl [invalid]");								break;
317 				case 0x03:	sprintf(buffer, "bc2tl [invalid]");								break;
318 				default:	sprintf(buffer, "dc.l   $%08x [invalid]", op);					break;
319 			}
320 			break;
321 		case 0x10:
322 		case 0x11:
323 		case 0x12:
324 		case 0x13:
325 		case 0x14:
326 		case 0x15:
327 		case 0x16:
328 		case 0x17:
329 		case 0x18:
330 		case 0x19:
331 		case 0x1a:
332 		case 0x1b:
333 		case 0x1c:
334 		case 0x1d:
335 		case 0x1e:
336 		case 0x1f:	/* COP */
337 			sprintf(buffer, "cop2   $%07x", op & 0x01ffffff);
338 			break;
339 		default:	sprintf(buffer, "dc.l   $%08x [invalid]", op);									break;
340 	}
341 }
342 
dasmmips3(char * buffer,unsigned pc)343 unsigned dasmmips3(char *buffer, unsigned pc)
344 {
345 	UINT32 op = ROPCODE(pc);
346 	int rs = (op >> 21) & 31;
347 	int rt = (op >> 16) & 31;
348 	int rd = (op >> 11) & 31;
349 	int shift = (op >> 6) & 31;
350 
351 	switch (op >> 26)
352 	{
353 		case 0x00:	/* SPECIAL */
354 			switch (op & 63)
355 			{
356 				case 0x00:	if (op == 0)
357 							sprintf(buffer, "nop");
358 							else
359 							sprintf(buffer, "sll    %s,%s,%d", reg[rd], reg[rt], shift);			break;
360 				case 0x01:	sprintf(buffer, "mov%c   %s,%s,%d", ((op >> 16) & 1) ? 't' : 'f', reg[rd], reg[rt], (op >> 18) & 7); break;
361 				case 0x02:	sprintf(buffer, "srl    %s,%s,%d", reg[rd], reg[rt], shift);			break;
362 				case 0x03:	sprintf(buffer, "sra    %s,%s,%d", reg[rd], reg[rt], shift);			break;
363 				case 0x04:	sprintf(buffer, "sllv   %s,%s,%s", reg[rd], reg[rt], reg[rs]);			break;
364 				case 0x06:	sprintf(buffer, "srlv   %s,%s,%s", reg[rd], reg[rt], reg[rs]);			break;
365 				case 0x07:	sprintf(buffer, "srav   %s,%s,%s", reg[rd], reg[rt], reg[rs]);			break;
366 				case 0x08:	sprintf(buffer, "jr     %s", reg[rs]);									break;
367 				case 0x09:	if (rd == 31)
368 							sprintf(buffer, "jalr   %s", reg[rs]);
369 							else
370 							sprintf(buffer, "jalr   %s,%s", reg[rs], reg[rd]);						break;
371 				case 0x0a:	sprintf(buffer, "movz   %s,%s,%s", reg[rd], reg[rs], reg[rt]);			break;
372 				case 0x0b:	sprintf(buffer, "movn   %s,%s,%s", reg[rd], reg[rs], reg[rt]);			break;
373 				case 0x0c:	sprintf(buffer, "syscall");												break;
374 				case 0x0d:	sprintf(buffer, "break");												break;
375 				case 0x0f:	sprintf(buffer, "sync");												break;
376 				case 0x10:	sprintf(buffer, "mfhi   %s", reg[rd]);									break;
377 				case 0x11:	sprintf(buffer, "mthi   %s", reg[rs]);									break;
378 				case 0x12:	sprintf(buffer, "mflo   %s", reg[rd]);									break;
379 				case 0x13:	sprintf(buffer, "mtlo   %s", reg[rs]);									break;
380 				case 0x14:	sprintf(buffer, "dsllv  %s,%s,%s", reg[rd], reg[rt], reg[rs]);			break;
381 				case 0x16:	sprintf(buffer, "dsrlv  %s,%s,%s", reg[rd], reg[rt], reg[rs]);			break;
382 				case 0x17:	sprintf(buffer, "dsrav  %s,%s,%s", reg[rd], reg[rt], reg[rs]);			break;
383 				case 0x18:	sprintf(buffer, "mult   %s,%s", reg[rs], reg[rt]);						break;
384 				case 0x19:	sprintf(buffer, "multu  %s,%s", reg[rs], reg[rt]);						break;
385 				case 0x1a:	sprintf(buffer, "div    %s,%s", reg[rs], reg[rt]);						break;
386 				case 0x1b:	sprintf(buffer, "divu   %s,%s", reg[rs], reg[rt]);						break;
387 				case 0x1c:	sprintf(buffer, "dmult  %s,%s", reg[rs], reg[rt]);						break;
388 				case 0x1d:	sprintf(buffer, "dmultu %s,%s", reg[rs], reg[rt]);						break;
389 				case 0x1e:	sprintf(buffer, "ddiv   %s,%s", reg[rs], reg[rt]);						break;
390 				case 0x1f:	sprintf(buffer, "ddivu  %s,%s", reg[rs], reg[rt]);						break;
391 				case 0x20:	sprintf(buffer, "add    %s,%s,%s", reg[rd], reg[rs], reg[rt]);			break;
392 				case 0x21:	sprintf(buffer, "addu   %s,%s,%s", reg[rd], reg[rs], reg[rt]);			break;
393 				case 0x22:	sprintf(buffer, "sub    %s,%s,%s", reg[rd], reg[rs], reg[rt]);			break;
394 				case 0x23:	sprintf(buffer, "subu   %s,%s,%s", reg[rd], reg[rs], reg[rt]);			break;
395 				case 0x24:	sprintf(buffer, "and    %s,%s,%s", reg[rd], reg[rs], reg[rt]);			break;
396 				case 0x25:	sprintf(buffer, "or     %s,%s,%s", reg[rd], reg[rs], reg[rt]);			break;
397 				case 0x26:	sprintf(buffer, "xor    %s,%s,%s", reg[rd], reg[rs], reg[rt]);			break;
398 				case 0x27:	sprintf(buffer, "nor    %s,%s,%s", reg[rd], reg[rs], reg[rt]);			break;
399 				case 0x2a:	sprintf(buffer, "slt    %s,%s,%s", reg[rd], reg[rs], reg[rt]);			break;
400 				case 0x2b:	sprintf(buffer, "sltu   %s,%s,%s", reg[rd], reg[rs], reg[rt]);			break;
401 				case 0x2c:	sprintf(buffer, "dadd   %s,%s,%s", reg[rd], reg[rs], reg[rt]);			break;
402 				case 0x2d:	sprintf(buffer, "daddu  %s,%s,%s", reg[rd], reg[rs], reg[rt]);			break;
403 				case 0x2e:	sprintf(buffer, "dsub   %s,%s,%s", reg[rd], reg[rs], reg[rt]);			break;
404 				case 0x2f:	sprintf(buffer, "dsubu  %s,%s,%s", reg[rd], reg[rs], reg[rt]);			break;
405 				case 0x30:	sprintf(buffer, "tge    %s,%s", reg[rs], reg[rt]);						break;
406 				case 0x31:	sprintf(buffer, "tgeu   %s,%s", reg[rs], reg[rt]);						break;
407 				case 0x32:	sprintf(buffer, "tlt    %s,%s", reg[rs], reg[rt]);						break;
408 				case 0x33:	sprintf(buffer, "tltu   %s,%s", reg[rs], reg[rt]);						break;
409 				case 0x34:	sprintf(buffer, "teq    %s,%s", reg[rs], reg[rt]);						break;
410 				case 0x36:	sprintf(buffer, "tne    %s,%s", reg[rs], reg[rt]);						break;
411 				case 0x38:	sprintf(buffer, "dsll   %s,%s,%d", reg[rd], reg[rt], shift);			break;
412 				case 0x3a:	sprintf(buffer, "dsrl   %s,%s,%d", reg[rd], reg[rt], shift);			break;
413 				case 0x3b:	sprintf(buffer, "dsra   %s,%s,%d", reg[rd], reg[rt], shift);			break;
414 				case 0x3c:	sprintf(buffer, "dsll   %s,%s,%d", reg[rd], reg[rt], shift+32);			break;
415 				case 0x3e:	sprintf(buffer, "dsrl   %s,%s,%d", reg[rd], reg[rt], shift+32);			break;
416 				case 0x3f:	sprintf(buffer, "dsra   %s,%s,%d", reg[rd], reg[rt], shift+32);			break;
417 				default:	sprintf(buffer, "dc.l   $%08x [invalid]", op);							break;
418 			}
419 			break;
420 
421 		case 0x01:	/* REGIMM */
422 			switch ((op >> 16) & 31)
423 			{
424 				case 0x00:	sprintf(buffer, "bltz   %s,$%08x", reg[rs], pc + 4 + ((INT16)op << 2));	break;
425 				case 0x01:	sprintf(buffer, "bgez   %s,$%08x", reg[rs], pc + 4 + ((INT16)op << 2));	break;
426 				case 0x02:	sprintf(buffer, "bltzl  %s,$%08x", reg[rs], pc + 4 + ((INT16)op << 2));	break;
427 				case 0x03:	sprintf(buffer, "bgezl  %s,$%08x", reg[rs], pc + 4 + ((INT16)op << 2));	break;
428 				case 0x08:	sprintf(buffer, "tgei   %s,%s", reg[rs], signed_16bit(op));				break;
429 				case 0x09:	sprintf(buffer, "tgeiu  %s,%s", reg[rs], signed_16bit(op));				break;
430 				case 0x0a:	sprintf(buffer, "tlti   %s,%s", reg[rs], signed_16bit(op));				break;
431 				case 0x0b:	sprintf(buffer, "tltiu  %s,%s", reg[rs], signed_16bit(op));				break;
432 				case 0x0c:	sprintf(buffer, "teqi   %s,%s", reg[rs], signed_16bit(op));				break;
433 				case 0x0e:	sprintf(buffer, "tnei   %s,%s", reg[rs], signed_16bit(op));				break;
434 				case 0x10:	sprintf(buffer, "bltzal %s,$%08x", reg[rs], pc + 4 + ((INT16)op << 2));	break;
435 				case 0x11:	sprintf(buffer, "bgezal %s,$%08x", reg[rs], pc + 4 + ((INT16)op << 2));	break;
436 				case 0x12:	sprintf(buffer, "bltzall %s,$%08x", reg[rs], pc + 4 + ((INT16)op << 2));break;
437 				case 0x13:	sprintf(buffer, "bgezall %s,$%08x", reg[rs], pc + 4 + ((INT16)op << 2));break;
438 				default:	sprintf(buffer, "dc.l   $%08x [invalid]", op);							break;
439 			}
440 			break;
441 
442 		case 0x02:	sprintf(buffer, "j      $%08x", (pc & 0xf0000000) | ((op & 0x0fffffff) << 2));	break;
443 		case 0x03:	sprintf(buffer, "jal    $%08x", (pc & 0xf0000000) | ((op & 0x0fffffff) << 2));	break;
444 		case 0x04:	if (rs == 0 && rt == 0)
445 					sprintf(buffer, "b      $%08x", pc + 4 + ((INT16)op << 2));
446 					else
447 					sprintf(buffer, "beq    %s,%s,$%08x", reg[rs], reg[rt], pc + 4 + ((INT16)op << 2));break;
448 		case 0x05:	sprintf(buffer, "bne    %s,%s,$%08x", reg[rs], reg[rt], pc + 4 + ((INT16)op << 2));break;
449 		case 0x06:	sprintf(buffer, "blez   %s,$%08x", reg[rs], pc + 4 + ((INT16)op << 2));			break;
450 		case 0x07:	sprintf(buffer, "bgtz   %s,$%08x", reg[rs], pc + 4 + ((INT16)op << 2));			break;
451 		case 0x08:	sprintf(buffer, "addi   %s,%s,%s", reg[rt], reg[rs], signed_16bit(op));			break;
452 		case 0x09:	sprintf(buffer, "addiu  %s,%s,%s", reg[rt], reg[rs], signed_16bit(op));			break;
453 		case 0x0a:	sprintf(buffer, "slti   %s,%s,%s", reg[rt], reg[rs], signed_16bit(op));			break;
454 		case 0x0b:	sprintf(buffer, "sltiu  %s,%s,%s", reg[rt], reg[rs], signed_16bit(op));			break;
455 		case 0x0c:	sprintf(buffer, "andi   %s,%s,$%04x", reg[rt], reg[rs], (UINT16)op);			break;
456 		case 0x0d:	sprintf(buffer, "ori    %s,%s,$%04x", reg[rt], reg[rs], (UINT16)op);			break;
457 		case 0x0e:	sprintf(buffer, "xori   %s,%s,$%04x", reg[rt], reg[rs], (UINT16)op);			break;
458 		case 0x0f:	sprintf(buffer, "lui    %s,$%04x", reg[rt], (UINT16)op);						break;
459 		case 0x10:	dasm_cop0(pc, op, buffer);														break;
460 		case 0x11:	dasm_cop1(pc, op, buffer);														break;
461 		case 0x12:	dasm_cop2(pc, op, buffer);														break;
462 		case 0x13:	dasm_cop1x(pc, op, buffer);														break;
463 		case 0x14:	sprintf(buffer, "beql   %s,%s,$%08x", reg[rs], reg[rt], pc + 4 + ((INT16)op << 2));break;
464 		case 0x15:	sprintf(buffer, "bnel   %s,%s,$%08x", reg[rs], reg[rt], pc + 4 + ((INT16)op << 2));break;
465 		case 0x16:	sprintf(buffer, "blezl  %s,%s,$%08x", reg[rs], reg[rt], pc + 4 + ((INT16)op << 2));break;
466 		case 0x17:	sprintf(buffer, "bgtzl  %s,%s,$%08x", reg[rs], reg[rt], pc + 4 + ((INT16)op << 2));break;
467 		case 0x18:	sprintf(buffer, "daddi  %s,%s,%s", reg[rt], reg[rs], signed_16bit(op));			break;
468 		case 0x19:	sprintf(buffer, "daddiu %s,%s,%s", reg[rt], reg[rs], signed_16bit(op));			break;
469 		case 0x1a:	sprintf(buffer, "ldl    %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]);		break;
470 		case 0x1b:	sprintf(buffer, "ldr    %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]);		break;
471 		case 0x20:	sprintf(buffer, "lb     %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]);		break;
472 		case 0x21:	sprintf(buffer, "lh     %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]);		break;
473 		case 0x22:	sprintf(buffer, "lwl    %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]);		break;
474 		case 0x23:	sprintf(buffer, "lw     %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]);		break;
475 		case 0x24:	sprintf(buffer, "lbu    %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]);		break;
476 		case 0x25:	sprintf(buffer, "lhu    %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]);		break;
477 		case 0x26:	sprintf(buffer, "lwr    %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]);		break;
478 		case 0x27:	sprintf(buffer, "lwu    %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]);		break;
479 		case 0x28:	sprintf(buffer, "sb     %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]);		break;
480 		case 0x29:	sprintf(buffer, "sh     %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]);		break;
481 		case 0x2a:	sprintf(buffer, "swl    %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]);		break;
482 		case 0x2b:	sprintf(buffer, "sw     %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]);		break;
483 		case 0x2c:	sprintf(buffer, "sdl    %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]);		break;
484 		case 0x2d:	sprintf(buffer, "sdr    %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]);		break;
485 		case 0x2e:	sprintf(buffer, "swr    %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]);		break;
486 		case 0x2f:	sprintf(buffer, "cache  %s(%s)", reg[rs], signed_16bit(op));					break;
487 		case 0x30:	sprintf(buffer, "ll     %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]);		break;
488 		case 0x31:	sprintf(buffer, "lwc1   %s,%s(%s)", cpreg[1][rt], signed_16bit(op), reg[rs]);	break;
489 		case 0x32:	sprintf(buffer, "lwc2   %s,%s(%s)", cpreg[2][rt], signed_16bit(op), reg[rs]);	break;
490 		case 0x33:	sprintf(buffer, "pref   $%x,%s(%s)", rt, signed_16bit(op), reg[rs]);			break;
491 		case 0x34:	sprintf(buffer, "lld    %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]);		break;
492 		case 0x35:	sprintf(buffer, "ldc1   %s,%s(%s)", cpreg[1][rt], signed_16bit(op), reg[rs]);	break;
493 		case 0x36:	sprintf(buffer, "ldc2   %s,%s(%s)", cpreg[2][rt], signed_16bit(op), reg[rs]);	break;
494 		case 0x37:	sprintf(buffer, "ld     %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]);		break;
495 		case 0x38:	sprintf(buffer, "sc     %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]);		break;
496 		case 0x39:	sprintf(buffer, "swc1   %s,%s(%s)", cpreg[1][rt], signed_16bit(op), reg[rs]);	break;
497 		case 0x3a:	sprintf(buffer, "swc2   %s,%s(%s)", cpreg[2][rt], signed_16bit(op), reg[rs]);	break;
498 		case 0x3c:	sprintf(buffer, "scd    %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]);		break;
499 		case 0x3d:	sprintf(buffer, "sdc1   %s,%s(%s)", cpreg[1][rt], signed_16bit(op), reg[rs]);	break;
500 		case 0x3e:	sprintf(buffer, "sdc2   %s,%s(%s)", cpreg[2][rt], signed_16bit(op), reg[rs]);	break;
501 		case 0x3f:	sprintf(buffer, "sd     %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]);		break;
502 		default:	sprintf(buffer, "dc.l   $%08x [invalid]", op);									break;
503 	}
504 	return 4;
505 }
506