1 // license:BSD-3-Clause
2 // copyright-holders:Aaron Giles
3 /***************************************************************************
4 
5     r3kdasm.c
6     Disassembler for the portable R3000 emulator.
7     Written by Aaron Giles
8 
9 ***************************************************************************/
10 
11 #include "emu.h"
12 #include "mips1dsm.h"
13 
14 const char *const mips1_disassembler::reg[32] =
15 {
16 	"0",    "r1",   "r2",   "r3",   "r4",   "r5",   "r6",   "r7",
17 	"r8",   "r9",   "r10",  "r11",  "r12",  "r13",  "r14",  "r15",
18 	"r16",  "r17",  "r18",  "r19",  "r20",  "r21",  "r22",  "r23",
19 	"r24",  "r25",  "r26",  "r27",  "r28",  "r29",  "r30",  "r31"
20 };
21 
22 
23 const char *const mips1_disassembler::cpreg[4][32] =
24 {
25 	{
26 		"Index","Random","EntryLo","cpr3",  "Context",  "cpr5", "cpr6", "cpr7",
27 		"BadVAddr", "cpr9", "EntryHi","cpr11","SR","Cause","EPC","PRId",
28 		"cpr16","cpr17","cpr18","cpr19","cpr20","cpr21","cpr22","cpr23",
29 		"cpr24","cpr25","cpr26","cpr27","cpr28","cpr29","cpr30","cpr31"
30 	},
31 	{
32 		"f0",   "f1",   "f2",   "f3",   "f4",   "f5",   "f6",   "f7",
33 		"f8",   "f9",   "f10",  "f11",  "f12",  "f13",  "f14",  "f15",
34 		"f16",  "f17",  "f18",  "f19",  "f20",  "f21",  "f22",  "f23",
35 		"f24",  "f25",  "f26",  "f27",  "f28",  "f29",  "f30",  "f31"
36 	},
37 	{
38 		"cpr0", "cpr1", "cpr2", "cpr3", "cpr4", "cpr5", "cpr6", "cpr7",
39 		"cpr8", "cpr9", "cpr10","cpr11","cpr12","cpr13","cpr14","cpr15",
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 
51 
52 const char *const mips1_disassembler::ccreg[4][32] =
53 {
54 	{
55 		"ccr0", "ccr1", "ccr2", "ccr3", "ccr4", "ccr5", "ccr6", "ccr7",
56 		"ccr8", "ccr9", "ccr10","ccr11","ccr12","ccr13","ccr14","ccr15",
57 		"ccr16","ccr17","ccr18","ccr19","ccr20","ccr21","ccr22","ccr23",
58 		"ccr24","ccr25","ccr26","ccr27","ccr28","ccr29","ccr30","ccr31"
59 	},
60 	{
61 		"ccr0", "ccr1", "ccr2", "ccr3", "ccr4", "ccr5", "ccr6", "ccr7",
62 		"ccr8", "ccr9", "ccr10","ccr11","ccr12","ccr13","ccr14","ccr15",
63 		"ccr16","ccr17","ccr18","ccr19","ccr20","ccr21","ccr22","ccr23",
64 		"ccr24","ccr25","ccr26","ccr27","ccr28","ccr29","ccr30","ccr31"
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 
80 
81 /***************************************************************************
82     CODE CODE
83 ***************************************************************************/
84 
signed_16bit(int16_t val)85 std::string mips1_disassembler::signed_16bit(int16_t val)
86 {
87 	if (val < 0)
88 		return util::string_format("-$%x", -val);
89 	else
90 		return util::string_format("$%x", val);
91 }
92 
dasm_cop(uint32_t pc,int cop,uint32_t op,std::ostream & stream)93 uint32_t mips1_disassembler::dasm_cop(uint32_t pc, int cop, uint32_t op, std::ostream &stream)
94 {
95 	int rt = (op >> 16) & 31;
96 	int rd = (op >> 11) & 31;
97 	uint32_t flags = 0;
98 
99 	switch ((op >> 21) & 31)
100 	{
101 		case 0x00:  util::stream_format(stream, "mfc%d   %s,%s", cop, reg[rt], cpreg[cop][rd]);                 break;
102 		case 0x02:  util::stream_format(stream, "cfc%d   %s,%s", cop, reg[rt], ccreg[cop][rd]);                 break;
103 		case 0x04:  util::stream_format(stream, "mtc%d   %s,%s", cop, reg[rt], cpreg[cop][rd]);                 break;
104 		case 0x06:  util::stream_format(stream, "ctc%d   %s,%s", cop, reg[rt], ccreg[cop][rd]);                 break;
105 		case 0x08:  /* BC */
106 			switch (rt)
107 			{
108 				case 0x00:  util::stream_format(stream, "bc%df   $%08x", cop, pc + 4 + ((int16_t)op << 2));       break;
109 				case 0x01:  util::stream_format(stream, "bc%dt   $%08x", cop, pc + 4 + ((int16_t)op << 2));       break;
110 				case 0x02:  util::stream_format(stream, "bc%dfl [invalid]", cop);                               break;
111 				case 0x03:  util::stream_format(stream, "bc%dtl [invalid]", cop);                               break;
112 				default:    util::stream_format(stream, "dc.l    $%08x [invalid]", op);                         break;
113 			}
114 			break;
115 		case 0x10:
116 		case 0x11:
117 		case 0x12:
118 		case 0x13:
119 		case 0x14:
120 		case 0x15:
121 		case 0x16:
122 		case 0x17:
123 		case 0x18:
124 		case 0x19:
125 		case 0x1a:
126 		case 0x1b:
127 		case 0x1c:
128 		case 0x1d:
129 		case 0x1e:
130 		case 0x1f:  /* COP */
131 			if (cop == 0)
132 			{
133 				switch (op & 0x01ffffff)
134 				{
135 					case 0x01:  util::stream_format(stream, "tlbr");                                            break;
136 					case 0x02:  util::stream_format(stream, "tlbwi");                                           break;
137 					case 0x06:  util::stream_format(stream, "tlbwr");                                           break;
138 					case 0x08:  util::stream_format(stream, "tlbp");                                            break;
139 					case 0x10:  util::stream_format(stream, "rfe");                                             break;
140 					case 0x18:  util::stream_format(stream, "eret [invalid]");                                  break;
141 					default:    util::stream_format(stream, "cop%d  $%07x", cop, op & 0x01ffffff);              break;
142 				}
143 			}
144 			else
145 				util::stream_format(stream, "cop%d  $%07x", cop, op & 0x01ffffff);
146 			break;
147 		default:    util::stream_format(stream, "dc.l  $%08x [invalid]", op);                                   break;
148 	}
149 
150 	return flags;
151 }
152 
dasm_cop1(uint32_t pc,uint32_t op,std::ostream & stream)153 uint32_t mips1_disassembler::dasm_cop1(uint32_t pc, uint32_t op, std::ostream &stream)
154 {
155 	static const char *const format_table[] =
156 	{
157 		"?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?",
158 		"s","d","?","?","w","l","?","?","?","?","?","?","?","?","?","?"
159 	};
160 	const char *fmt = format_table[(op >> 21) & 31];
161 	int ft = (op >> 16) & 31;
162 	int fs = (op >> 11) & 31;
163 	int fd = (op >> 6) & 31;
164 	int rt = (op >> 16) & 31;
165 	int rd = (op >> 11) & 31;
166 	uint32_t flags = 0;
167 
168 	switch ((op >> 21) & 31)
169 	{
170 		case 0x00:  util::stream_format(stream, "mfc1   %s,%s", reg[rt], cpreg[1][rd]);                     break;
171 		case 0x01:  util::stream_format(stream, "dmfc1  %s,%s", reg[rt], cpreg[1][rd]);                     break;
172 		case 0x02:  util::stream_format(stream, "cfc1   %s,%s", reg[rt], ccreg[1][rd]);                     break;
173 		case 0x04:  util::stream_format(stream, "mtc1   %s,%s", reg[rt], cpreg[1][rd]);                     break;
174 		case 0x05:  util::stream_format(stream, "dmtc1  %s,%s", reg[rt], cpreg[1][rd]);                     break;
175 		case 0x06:  util::stream_format(stream, "ctc1   %s,%s", reg[rt], ccreg[1][rd]);                     break;
176 		case 0x08:  /* BC */
177 			switch (rt & 3)
178 			{
179 				case 0x00:  util::stream_format(stream, "bc1f   $%08x,%d", pc + 4 + ((int16_t)op << 2), (op >> 18) & 7);      break;
180 				case 0x01:  util::stream_format(stream, "bc1t   $%08x,%d", pc + 4 + ((int16_t)op << 2), (op >> 18) & 7);      break;
181 				case 0x02:  util::stream_format(stream, "bc1fl  $%08x,%d", pc + 4 + ((int16_t)op << 2), (op >> 18) & 7); flags = STEP_OVER | step_over_extra(1); break;
182 				case 0x03:  util::stream_format(stream, "bc1tl  $%08x,%d", pc + 4 + ((int16_t)op << 2), (op >> 18) & 7); flags = STEP_OVER | step_over_extra(1); break;
183 			}
184 			break;
185 		default:    /* COP */
186 			switch (op & 0x3f)
187 			{
188 				case 0x00:  util::stream_format(stream, "add.%s  %s,%s,%s", fmt, cpreg[1][fd], cpreg[1][fs], cpreg[1][ft]); break;
189 				case 0x01:  util::stream_format(stream, "sub.%s  %s,%s,%s", fmt, cpreg[1][fd], cpreg[1][fs], cpreg[1][ft]); break;
190 				case 0x02:  util::stream_format(stream, "mul.%s  %s,%s,%s", fmt, cpreg[1][fd], cpreg[1][fs], cpreg[1][ft]); break;
191 				case 0x03:  util::stream_format(stream, "div.%s  %s,%s,%s", fmt, cpreg[1][fd], cpreg[1][fs], cpreg[1][ft]); break;
192 				case 0x04:  util::stream_format(stream, "sqrt.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]);                  break;
193 				case 0x05:  util::stream_format(stream, "abs.%s  %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]);                  break;
194 				case 0x06:  util::stream_format(stream, "mov.%s  %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]);                  break;
195 				case 0x07:  util::stream_format(stream, "neg.%s  %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]);                  break;
196 				case 0x08:  util::stream_format(stream, "round.l.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]);               break;
197 				case 0x09:  util::stream_format(stream, "trunc.l.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]);               break;
198 				case 0x0a:  util::stream_format(stream, "ceil.l.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]);                break;
199 				case 0x0b:  util::stream_format(stream, "floor.l.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]);               break;
200 				case 0x0c:  util::stream_format(stream, "round.w.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]);               break;
201 				case 0x0d:  util::stream_format(stream, "trunc.w.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]);               break;
202 				case 0x0e:  util::stream_format(stream, "ceil.w.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]);                break;
203 				case 0x0f:  util::stream_format(stream, "floor.w.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]);               break;
204 				case 0x11:  util::stream_format(stream, "mov%c.%s  %s,%s,%d", ((op >> 16) & 1) ? 't' : 'f', fmt, cpreg[1][fd], cpreg[1][fs], (op >> 18) & 7);   break;
205 				case 0x12:  util::stream_format(stream, "movz.%s  %s,%s,%s", fmt, cpreg[1][fd], cpreg[1][fs], reg[rt]);     break;
206 				case 0x13:  util::stream_format(stream, "movn.%s  %s,%s,%s", fmt, cpreg[1][fd], cpreg[1][fs], reg[rt]);     break;
207 				case 0x15:  util::stream_format(stream, "recip.%s  %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]);                break;
208 				case 0x16:  util::stream_format(stream, "rsqrt.%s  %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]);                break;
209 				case 0x20:  util::stream_format(stream, "cvt.s.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]);                 break;
210 				case 0x21:  util::stream_format(stream, "cvt.d.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]);                 break;
211 				case 0x24:  util::stream_format(stream, "cvt.w.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]);                 break;
212 				case 0x25:  util::stream_format(stream, "cvt.l.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]);                 break;
213 				case 0x30:  util::stream_format(stream, "c.f.%s  %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7);    break;
214 				case 0x31:  util::stream_format(stream, "c.un.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7);    break;
215 				case 0x32:  util::stream_format(stream, "c.eq.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7);    break;
216 				case 0x33:  util::stream_format(stream, "c.ueq.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7);   break;
217 				case 0x34:  util::stream_format(stream, "c.olt.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7);   break;
218 				case 0x35:  util::stream_format(stream, "c.ult.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7);   break;
219 				case 0x36:  util::stream_format(stream, "c.ole.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7);   break;
220 				case 0x37:  util::stream_format(stream, "c.ule.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7);   break;
221 				case 0x38:  util::stream_format(stream, "c.sf.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7);    break;
222 				case 0x39:  util::stream_format(stream, "c.ngle.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7);break;
223 				case 0x3a:  util::stream_format(stream, "c.seq.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7);   break;
224 				case 0x3b:  util::stream_format(stream, "c.ngl.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7);   break;
225 				case 0x3c:  util::stream_format(stream, "c.lt.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7);    break;
226 				case 0x3d:  util::stream_format(stream, "c.nge.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7);   break;
227 				case 0x3e:  util::stream_format(stream, "c.le.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7);    break;
228 				case 0x3f:  util::stream_format(stream, "c.ngt.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7);   break;
229 				default:    util::stream_format(stream, "cop1   $%07x", op & 0x01ffffff);                                   break;
230 			}
231 			break;
232 	}
233 	return flags;
234 }
235 
disassemble(std::ostream & stream,offs_t pc,const data_buffer & opcodes,const data_buffer & params)236 offs_t mips1_disassembler::disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer &params)
237 {
238 	uint32_t op = opcodes.r32(pc);
239 	int rs = (op >> 21) & 31;
240 	int rt = (op >> 16) & 31;
241 	int rd = (op >> 11) & 31;
242 	int shift = (op >> 6) & 31;
243 	uint32_t flags = 0;
244 
245 	switch (op >> 26)
246 	{
247 		case 0x00:  /* SPECIAL */
248 			switch (op & 63)
249 			{
250 				case 0x00:  if (op == 0)
251 							util::stream_format(stream, "nop");
252 							else
253 							util::stream_format(stream, "sll    %s,%s,%d", reg[rd], reg[rt], shift);
254 					break;
255 				case 0x02:  util::stream_format(stream, "srl    %s,%s,%d", reg[rd], reg[rt], shift);            break;
256 				case 0x03:  util::stream_format(stream, "sra    %s,%s,%d", reg[rd], reg[rt], shift);            break;
257 				case 0x04:  util::stream_format(stream, "sllv   %s,%s,%s", reg[rd], reg[rt], reg[rs]);          break;
258 				case 0x06:  util::stream_format(stream, "srlv   %s,%s,%s", reg[rd], reg[rt], reg[rs]);          break;
259 				case 0x07:  util::stream_format(stream, "srav   %s,%s,%s", reg[rd], reg[rt], reg[rs]);          break;
260 				case 0x08:  util::stream_format(stream, "jr     %s", reg[rs]); if (rs == 31) flags = STEP_OUT; break;
261 				case 0x09:  if (rd == 31)
262 							util::stream_format(stream, "jalr   %s", reg[rs]);
263 							else
264 							util::stream_format(stream, "jalr   %s,%s", reg[rs], reg[rd]);
265 					flags = STEP_OVER | step_over_extra(1);
266 					break;
267 				case 0x0c:  util::stream_format(stream, "syscall"); flags = STEP_OVER;                 break;
268 				case 0x0d:  util::stream_format(stream, "break"); flags = STEP_OVER;                   break;
269 				case 0x0f:  util::stream_format(stream, "sync [invalid]");                                      break;
270 				case 0x10:  util::stream_format(stream, "mfhi   %s", reg[rd]);                                  break;
271 				case 0x11:  util::stream_format(stream, "mthi   %s", reg[rs]);                                  break;
272 				case 0x12:  util::stream_format(stream, "mflo   %s", reg[rd]);                                  break;
273 				case 0x13:  util::stream_format(stream, "mtlo   %s", reg[rs]);                                  break;
274 				case 0x18:  util::stream_format(stream, "mult   %s,%s", reg[rs], reg[rt]);                      break;
275 				case 0x19:  util::stream_format(stream, "multu  %s,%s", reg[rs], reg[rt]);                      break;
276 				case 0x1a:  util::stream_format(stream, "div    %s,%s", reg[rs], reg[rt]);                      break;
277 				case 0x1b:  util::stream_format(stream, "divu   %s,%s", reg[rs], reg[rt]);                      break;
278 				case 0x20:  util::stream_format(stream, "add    %s,%s,%s", reg[rd], reg[rs], reg[rt]);          break;
279 				case 0x21:  util::stream_format(stream, "addu   %s,%s,%s", reg[rd], reg[rs], reg[rt]);          break;
280 				case 0x22:  util::stream_format(stream, "sub    %s,%s,%s", reg[rd], reg[rs], reg[rt]);          break;
281 				case 0x23:  util::stream_format(stream, "subu   %s,%s,%s", reg[rd], reg[rs], reg[rt]);          break;
282 				case 0x24:  util::stream_format(stream, "and    %s,%s,%s", reg[rd], reg[rs], reg[rt]);          break;
283 				case 0x25:  util::stream_format(stream, "or     %s,%s,%s", reg[rd], reg[rs], reg[rt]);          break;
284 				case 0x26:  util::stream_format(stream, "xor    %s,%s,%s", reg[rd], reg[rs], reg[rt]);          break;
285 				case 0x27:  util::stream_format(stream, "nor    %s,%s,%s", reg[rd], reg[rs], reg[rt]);          break;
286 				case 0x2a:  util::stream_format(stream, "slt    %s,%s,%s", reg[rd], reg[rs], reg[rt]);          break;
287 				case 0x2b:  util::stream_format(stream, "sltu   %s,%s,%s", reg[rd], reg[rs], reg[rt]);          break;
288 				case 0x30:  util::stream_format(stream, "teq [invalid]");                                       break;
289 				case 0x31:  util::stream_format(stream, "tgeu [invalid]");                                      break;
290 				case 0x32:  util::stream_format(stream, "tlt [invalid]");                                       break;
291 				case 0x33:  util::stream_format(stream, "tltu [invalid]");                                      break;
292 				case 0x34:  util::stream_format(stream, "tge [invalid]");                                       break;
293 				case 0x36:  util::stream_format(stream, "tne [invalid]");                                       break;
294 				default:    util::stream_format(stream, "dc.l   $%08x [invalid]", op);                          break;
295 			}
296 			break;
297 
298 		case 0x01:  /* REGIMM */
299 			switch ((op >> 16) & 31)
300 			{
301 				case 0x00:  util::stream_format(stream, "bltz   %s,$%08x", reg[rs], pc + 4 + ((int16_t)op << 2)); break;
302 				case 0x01:  util::stream_format(stream, "bgez   %s,$%08x", reg[rs], pc + 4 + ((int16_t)op << 2)); break;
303 				case 0x02:  util::stream_format(stream, "bltzl [invalid]");                                     break;
304 				case 0x03:  util::stream_format(stream, "bgezl [invalid]");                                     break;
305 				case 0x08:  util::stream_format(stream, "tgei [invalid]");                                      break;
306 				case 0x09:  util::stream_format(stream, "tgeiu [invalid]");                                     break;
307 				case 0x0a:  util::stream_format(stream, "tlti [invalid]");                                      break;
308 				case 0x0b:  util::stream_format(stream, "tltiu [invalid]");                                     break;
309 				case 0x0c:  util::stream_format(stream, "teqi [invalid]");                                      break;
310 				case 0x0e:  util::stream_format(stream, "tnei [invalid]");                                      break;
311 				case 0x10:  util::stream_format(stream, "bltzal %s,$%08x", reg[rs], pc + 4 + ((int16_t)op << 2)); flags = STEP_OVER | step_over_extra(1); break;
312 				case 0x11:  util::stream_format(stream, "bgezal %s,$%08x", reg[rs], pc + 4 + ((int16_t)op << 2)); flags = STEP_OVER | step_over_extra(1); break;
313 				case 0x12:  util::stream_format(stream, "bltzall [invalid]");                                   break;
314 				case 0x13:  util::stream_format(stream, "bgezall [invalid]");                                   break;
315 				default:    util::stream_format(stream, "dc.l   $%08x [invalid]", op);                          break;
316 			}
317 			break;
318 
319 		case 0x02:  util::stream_format(stream, "j      $%08x", (pc & 0xf0000000) | ((op & 0x03ffffff) << 2));  break;
320 		case 0x03:  util::stream_format(stream, "jal    $%08x", (pc & 0xf0000000) | ((op & 0x03ffffff) << 2)); flags = STEP_OVER | step_over_extra(1); break;
321 		case 0x04:  if (rs == 0 && rt == 0)
322 					util::stream_format(stream, "b      $%08x", pc + 4 + ((int16_t)op << 2));
323 					else
324 					util::stream_format(stream, "beq    %s,%s,$%08x", reg[rs], reg[rt], pc + 4 + ((int16_t)op << 2));
325 			break;
326 		case 0x05:  util::stream_format(stream, "bne    %s,%s,$%08x", reg[rs], reg[rt], pc + 4 + ((int16_t)op << 2));break;
327 		case 0x06:  util::stream_format(stream, "blez   %s,$%08x", reg[rs], pc + 4 + ((int16_t)op << 2));         break;
328 		case 0x07:  util::stream_format(stream, "bgtz   %s,$%08x", reg[rs], pc + 4 + ((int16_t)op << 2));         break;
329 		case 0x08:  util::stream_format(stream, "addi   %s,%s,%s", reg[rt], reg[rs], signed_16bit(op));         break;
330 		case 0x09:  util::stream_format(stream, "addiu  %s,%s,%s", reg[rt], reg[rs], signed_16bit(op));         break;
331 		case 0x0a:  util::stream_format(stream, "slti   %s,%s,%s", reg[rt], reg[rs], signed_16bit(op));         break;
332 		case 0x0b:  util::stream_format(stream, "sltiu  %s,%s,%s", reg[rt], reg[rs], signed_16bit(op));         break;
333 		case 0x0c:  util::stream_format(stream, "andi   %s,%s,$%04x", reg[rt], reg[rs], (uint16_t)op);            break;
334 		case 0x0d:  util::stream_format(stream, "ori    %s,%s,$%04x", reg[rt], reg[rs], (uint16_t)op);            break;
335 		case 0x0e:  util::stream_format(stream, "xori   %s,%s,$%04x", reg[rt], reg[rs], (uint16_t)op);            break;
336 		case 0x0f:  util::stream_format(stream, "lui    %s,$%04x", reg[rt], (uint16_t)op);                        break;
337 		case 0x10:  flags = dasm_cop(pc, 0, op, stream);                                            break;
338 		case 0x11:  flags = dasm_cop1(pc, op, stream);                                          break;
339 		case 0x12:  flags = dasm_cop(pc, 2, op, stream);                                            break;
340 		case 0x13:  flags = dasm_cop(pc, 3, op, stream);                                            break;
341 		case 0x14:  util::stream_format(stream, "beql [invalid]");                                              break;
342 		case 0x15:  util::stream_format(stream, "bnel [invalid]");                                              break;
343 		case 0x16:  util::stream_format(stream, "blezl [invalid]");                                             break;
344 		case 0x17:  util::stream_format(stream, "bgtzl [invalid]");                                             break;
345 		case 0x20:  util::stream_format(stream, "lb     %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]);        break;
346 		case 0x21:  util::stream_format(stream, "lh     %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]);        break;
347 		case 0x22:  util::stream_format(stream, "lwl    %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]);        break;
348 		case 0x23:  util::stream_format(stream, "lw     %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]);        break;
349 		case 0x24:  util::stream_format(stream, "lbu    %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]);        break;
350 		case 0x25:  util::stream_format(stream, "lhu    %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]);        break;
351 		case 0x26:  util::stream_format(stream, "lwr    %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]);        break;
352 		case 0x28:  util::stream_format(stream, "sb     %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]);        break;
353 		case 0x29:  util::stream_format(stream, "sh     %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]);        break;
354 		case 0x2a:  util::stream_format(stream, "swl    %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]);        break;
355 		case 0x2b:  util::stream_format(stream, "sw     %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]);        break;
356 		case 0x2e:  util::stream_format(stream, "swr    %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]);        break;
357 		case 0x2f:  util::stream_format(stream, "cache [invalid]");                                             break;
358 		case 0x30:  util::stream_format(stream, "ll [invalid]");                                                break;
359 		case 0x31:  util::stream_format(stream, "lwc1   %s,%s(%s)", cpreg[1][rt], signed_16bit(op), reg[rs]);   break;
360 		case 0x32:  util::stream_format(stream, "lwc2   %s,%s(%s)", cpreg[2][rt], signed_16bit(op), reg[rs]);   break;
361 		case 0x33:  util::stream_format(stream, "lwc3   %s,%s(%s)", cpreg[3][rt], signed_16bit(op), reg[rs]);   break;
362 		case 0x34:  util::stream_format(stream, "ldc0 [invalid]");                                              break;
363 		case 0x35:  util::stream_format(stream, "ldc1 [invalid]");                                              break;
364 		case 0x36:  util::stream_format(stream, "ldc2 [invalid]");                                              break;
365 		case 0x37:  util::stream_format(stream, "ldc3 [invalid]");                                              break;
366 		case 0x38:  util::stream_format(stream, "sc [invalid]");                                                break;
367 		case 0x39:  util::stream_format(stream, "swc1   %s,%s(%s)", cpreg[1][rt], signed_16bit(op), reg[rs]);   break;
368 		case 0x3a:  util::stream_format(stream, "swc2   %s,%s(%s)", cpreg[2][rt], signed_16bit(op), reg[rs]);   break;
369 		case 0x3b:  util::stream_format(stream, "swc3   %s,%s(%s)", cpreg[3][rt], signed_16bit(op), reg[rs]);   break;
370 		case 0x3c:  util::stream_format(stream, "sdc0 [invalid]");                                              break;
371 		case 0x3d:  util::stream_format(stream, "sdc1 [invalid]");                                              break;
372 		case 0x3e:  util::stream_format(stream, "sdc2 [invalid]");                                              break;
373 		case 0x3f:  util::stream_format(stream, "sdc3 [invalid]");                                              break;
374 		default:    util::stream_format(stream, "dc.l   $%08x [invalid]", op);                                  break;
375 	}
376 	return 4 | flags | SUPPORTED;
377 }
378 
opcode_alignment() const379 uint32_t mips1_disassembler::opcode_alignment() const
380 {
381 	return 4;
382 }
383