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