1 // license:BSD-3-Clause
2 // copyright-holders:Wilbert Pol
3 /*******************************************************************
4 
5 sm8500d.c
6 Sharp sm8500 CPU disassembly
7 
8 
9 
10 *******************************************************************/
11 
12 #include "emu.h"
13 #include "sm8500d.h"
14 
15 const char *const sm8500_disassembler::s_mnemonic[] =
16 {
17 	"adc",  "adcw", "add",  "addw", "and",  "andw",  "band", "bbc",  "bbs",
18 	"bclr", "bcmp", "bmov", "bor",  "br",   "btst", "bset",  "bxor", "call", "cals", "clr",
19 	"clrc", "cmp",  "cmpw", "com",  "comc",  "da",   "dbnz", "dec",
20 	"decw", "di",   "div",  "ei",   "exts",  "halt", "inc",  "incw",
21 	"iret", "jmp",  "mov",  "movm", "movw",  "mult", "neg",  "nop",  "or",
22 	"orw",  "pop",  "popw", "push", "pushw", "ret",  "rl",   "rlc",
23 	"rr",   "rrc",  "sbc",  "sbcw", "setc", "sll",   "sra",  "srl",  "stop",
24 	"sub",  "subw", "swap", "xor",  "xorw", "mov  PS0,", "invalid", "dm?",
25 /* unknowns */
26 "unk5A", "unk5B",
27 
28 /* more complicated instructions */
29 "comp1A", "comp1B", "comp4F",
30 };
31 
32 const uint32_t sm8500_disassembler::s_flags[] = {
33 	0, 0, 0, 0, 0, 0, 0, 0, 0,
34 	0, 0, 0, 0, 0, 0, 0, 0, STEP_OVER, STEP_OVER, 0,
35 	0, 0, 0, 0, 0, 0, STEP_OVER, 0,
36 	0, 0, 0, 0, 0, STEP_OVER, 0, 0,
37 	STEP_OUT, 0, 0, 0, 0, 0, 0, 0, 0,
38 	0, 0, 0, 0, 0, STEP_OUT, 0, 0,
39 	0, 0, 0, 0, 0, 0, 0, 0, 0,
40 	0, 0, 0, 0, 0, 0, 0, 0,
41 	0, 0,
42 	0, 0, 0
43 };
44 
45 const char *const sm8500_disassembler::sm8500_cond[16] = {
46 	"F", "LT", "LE", "ULE", "OV",  "MI", "Z",  "C",
47 	"T", "GE", "GT", "UGT", "NOV", "PL", "NZ", "NC"
48 };
49 
50 const uint8_t sm8500_disassembler::sm8500_b2w[8] = {
51 	0, 8, 2, 10, 4, 12, 6, 14
52 };
53 
54 const sm8500_disassembler::sm8500dasm sm8500_disassembler::mnemonic[256] = {
55 	/* 00 - 0F */
56 		{zCLR, AM_R},  {zNEG,AM_R},   {zCOM,AM_R},   {zRR,AM_R},
57 		{zRL, AM_R},   {zRRC,AM_R},  {zRLC,AM_R},   {zSRL,AM_R},
58 		{zINC, AM_R},  {zDEC,AM_R},  {zSRA,AM_R},    {zSLL,AM_R},
59 		{zDA, AM_R},   {zSWAP,AM_R}, {zPUSH,AM_R},  {zPOP,AM_R},
60 	/* 10 - 1F */
61 		{zCMP,AM_rr},  {zADD,AM_rr},  {zSUB,AM_rr},   {zADC,AM_rr},
62 		{zSBC,AM_rr},  {zAND,AM_rr},  {zOR,AM_rr},    {zXOR,AM_rr},
63 		{zINCW,AM_S}, {zDECW,AM_S}, {z1A,AM_1A},    {z1B,AM_1B},
64 		{zBCLR,AM_riB}, {zBSET,AM_riB},   {zPUSHW,AM_S}, {zPOPW,AM_S},
65 	/* 20 - 2F */
66 		{zCMP,AM_rmb},   {zADD,AM_rmb},  {zSUB,AM_rmb},    {zADC,AM_rmb},
67 		{zSBC,AM_rmb},   {zAND,AM_rmb},   {zOR,AM_rmb},    {zXOR,AM_rmb},
68 		{zMOV,AM_rmb},  {zMOV,AM_mbr},  {zBBC,AM_bid},    {zBBS,AM_bid},
69 		{zEXTS,AM_R}, {zDM,AM_i},   {zMOVPS0,AM_i},    {zBTST,AM_Ri},
70 	/* 30 - 3F */
71 		{zCMP,AM_rmw},  {zADD,AM_rmw},  {zSUB,AM_rmw},   {zADC,AM_rmw},
72 		{zSBC,AM_rmw},  {zAND,AM_rmw},   {zOR,AM_rmw},    {zXOR,AM_rmw},
73 		{zMOV,AM_rmw},  {zMOV,AM_mwr},  {zMOVW,AM_smw},  {zMOVW,AM_mws},
74 		{zMOVW,AM_ss}, {zDM,AM_R},   {zJMP,AM_2},   {zCALL,AM_2},
75 	/* 40 - 4F */
76 		{zCMP,AM_RR},  {zADD,AM_RR},  {zSUB,AM_RR},   {zADC,AM_RR},
77 		{zSBC,AM_RR},  {zAND,AM_RR},  {zOR,AM_RR},    {zXOR,AM_RR},
78 		{zMOV,AM_RR},  {zCALL,AM_ii}, {zMOVW,AM_SS},  {zMOVW,AM_Sw},
79 		{zMULT,AM_RR}, {zMULT,AM_iR}, {zBMOV,AM_bR},  {z4F,AM_4F},
80 	/* 50 - 5F */
81 		{zCMP,AM_iR},  {zADD,AM_iR},  {zSUB,AM_iR},   {zADC,AM_iR},
82 		{zSBC,AM_iR},  {zAND,AM_iR},  {zOR,AM_iR},    {zXOR,AM_iR},
83 		{zMOV, AM_iR}, {zINVLD,0},   {z5A,AM_5A},    {z5B,AM_5B},
84 		{zDIV,AM_SS},  {zDIV,AM_iS},   {zMOVM,AM_RiR},  {zMOVM,AM_Rii},
85 	/* 60 - 6F */
86 		{zCMPW,AM_SS}, {zADDW,AM_SS}, {zSUBW,AM_SS},  {zADCW,AM_SS},
87 		{zSBCW,AM_SS}, {zANDW,AM_SS}, {zORW,AM_SS},   {zXORW,AM_SS},
88 		{zCMPW,AM_Sw}, {zADDW,AM_Sw}, {zSUBW,AM_Sw},  {zADCW,AM_Sw},
89 		{zSBCW,AM_Sw}, {zANDW,AM_Sw}, {zORW,AM_Sw},   {zXORW,AM_Sw},
90 	/* 70 - 7F */
91 		{zDBNZ,AM_rbr}, {zDBNZ,AM_rbr}, {zDBNZ,AM_rbr},  {zDBNZ,AM_rbr},
92 		{zDBNZ,AM_rbr}, {zDBNZ,AM_rbr}, {zDBNZ,AM_rbr},  {zDBNZ,AM_rbr},
93 		{zMOVW,AM_riw}, {zMOVW,AM_riw}, {zMOVW,AM_riw},  {zMOVW,AM_riw},
94 		{zMOVW,AM_riw}, {zMOVW,AM_riw}, {zMOVW,AM_riw},  {zMOVW,AM_riw},
95 	/* 80 - 8F */
96 		{zBBC,AM_Rbr},  {zBBC,AM_Rbr},  {zBBC,AM_Rbr},   {zBBC,AM_Rbr},
97 		{zBBC,AM_Rbr},  {zBBC,AM_Rbr},  {zBBC,AM_Rbr},   {zBBC,AM_Rbr},
98 		{zBBS,AM_Rbr},  {zBBS,AM_Rbr},  {zBBS,AM_Rbr},   {zBBS,AM_Rbr},
99 		{zBBS,AM_Rbr},  {zBBS,AM_Rbr},  {zBBS,AM_Rbr},   {zBBS,AM_Rbr},
100 	/* 90 - 9F */
101 		{zJMP,AM_cjp},  {zJMP,AM_cjp},  {zJMP,AM_cjp},   {zJMP,AM_cjp},
102 		{zJMP,AM_cjp},  {zJMP,AM_cjp},  {zJMP,AM_cjp},   {zJMP,AM_cjp},
103 		{zJMP,AM_cjp},  {zJMP,AM_cjp},  {zJMP,AM_cjp},   {zJMP,AM_cjp},
104 		{zJMP,AM_cjp},  {zJMP,AM_cjp},  {zJMP,AM_cjp},   {zJMP,AM_cjp},
105 	/* A0 - AF */
106 		{zBCLR,AM_Rb}, {zBCLR,AM_Rb}, {zBCLR,AM_Rb},  {zBCLR,AM_Rb},
107 		{zBCLR,AM_Rb}, {zBCLR,AM_Rb}, {zBCLR,AM_Rb},  {zBCLR,AM_Rb},
108 		{zBSET,AM_Rb}, {zBSET,AM_Rb}, {zBSET,AM_Rb},  {zBSET,AM_Rb},
109 		{zBSET,AM_Rb}, {zBSET,AM_Rb}, {zBSET,AM_Rb},  {zBSET,AM_Rb},
110 	/* B0 - BF */
111 		{zMOV,AM_rR},  {zMOV,AM_rR},  {zMOV,AM_rR},   {zMOV,AM_rR},
112 		{zMOV,AM_rR},  {zMOV,AM_rR},  {zMOV,AM_rR},   {zMOV,AM_rR},
113 		{zMOV,AM_Rr},  {zMOV,AM_Rr},  {zMOV,AM_Rr},   {zMOV,AM_Rr},
114 		{zMOV,AM_Rr},  {zMOV,AM_Rr},  {zMOV,AM_Rr},   {zMOV,AM_Rr},
115 	/* C0 - CF */
116 		{zMOV,AM_rib},  {zMOV,AM_rib},  {zMOV,AM_rib},   {zMOV,AM_rib},
117 		{zMOV,AM_rib},  {zMOV,AM_rib},  {zMOV,AM_rib},   {zMOV,AM_rib},
118 		{zMOV,AM_pi},  {zMOV,AM_pi},  {zMOV,AM_pi},   {zMOV,AM_pi},
119 		{zMOV,AM_pi},  {zMOV,AM_pi},  {zMOV,AM_pi},   {zMOV,AM_pi},
120 	/* D0 - DF */
121 		{zBR,AM_cbr},   {zBR,AM_cbr},   {zBR,AM_cbr},    {zBR,AM_cbr},
122 		{zBR,AM_cbr},   {zBR,AM_cbr},   {zBR,AM_cbr},    {zBR,AM_cbr},
123 		{zBR,AM_cbr},   {zBR,AM_cbr},   {zBR,AM_cbr},    {zBR,AM_cbr},
124 		{zBR,AM_cbr},   {zBR,AM_cbr},   {zBR,AM_cbr},    {zBR,AM_cbr},
125 	/* E0 - EF */
126 		{zCALS,AM_CALS},   {zCALS,AM_CALS},   {zCALS,AM_CALS},    {zCALS,AM_CALS},
127 		{zCALS,AM_CALS},   {zCALS,AM_CALS},   {zCALS,AM_CALS},    {zCALS,AM_CALS},
128 		{zCALS,AM_CALS},   {zCALS,AM_CALS},   {zCALS,AM_CALS},    {zCALS,AM_CALS},
129 		{zCALS,AM_CALS},   {zCALS,AM_CALS},   {zCALS,AM_CALS},    {zCALS,AM_CALS},
130 	/* F0 - FF */
131 		{zSTOP,0}, {zHALT,0}, {zINVLD,0},    {zINVLD,0},
132 		{zINVLD,0},   {zINVLD,0},   {zINVLD,0},    {zINVLD,0},
133 		{zRET,0},  {zIRET,0}, {zCLRC,0},  {zCOMC,0},
134 		{zSETC,0}, {zEI,0},   {zDI,0},    {zNOP,0},
135 
136 };
137 
opcode_alignment() const138 u32 sm8500_disassembler::opcode_alignment() const
139 {
140 	return 1;
141 }
142 
disassemble(std::ostream & stream,offs_t pc,const data_buffer & opcodes,const data_buffer & params)143 offs_t sm8500_disassembler::disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer &params)
144 {
145 	const sm8500dasm *instr;
146 	uint8_t op;
147 	int8_t offset;
148 	uint16_t ea;
149 	uint16_t ea2;
150 	uint16_t ea3;
151 	offs_t pos = pc;
152 
153 	op = opcodes.r8(pos++);
154 
155 	instr = &mnemonic[op];
156 
157 	if ( instr->arguments )
158 	{
159 		if ( instr->arguments != AM_1A && instr->arguments != AM_1B && instr->arguments != AM_4F ) {
160 			util::stream_format(stream, "%-4s ", s_mnemonic[ instr->mnemonic ]);
161 		}
162 		switch( instr->arguments ) {
163 		case AM_R:
164 			ea = opcodes.r8(pos++);
165 			util::stream_format(stream, "R%02Xh", ea);
166 			break;
167 		case AM_iR:
168 			util::stream_format(stream, "R%02Xh, $%02X", opcodes.r8(pos+1), opcodes.r8(pos));
169 			pos += 2;
170 			break;
171 		case AM_iS:
172 			util::stream_format(stream, "RR%02Xh, $%02X", opcodes.r8(pos+1), opcodes.r8(pos));
173 			pos += 2;
174 			break;
175 		case AM_Sw:
176 			ea2 = opcodes.r8(pos++);
177 			ea = opcodes.r8(pos++) << 8;
178 			ea += opcodes.r8(pos++);
179 			util::stream_format(stream, "RR%02Xh, $%04X", ea2, ea);
180 			break;
181 		case AM_rib:
182 			ea = opcodes.r8(pos++);
183 			util::stream_format(stream, "r%02Xh, $%02X", op & 0x07, ea);
184 			break;
185 		case AM_riw:
186 			ea = opcodes.r8(pos++) << 8;
187 			ea += opcodes.r8(pos++);
188 			util::stream_format(stream, "rr%02Xh, $%04X", sm8500_b2w[op & 0x07], ea);
189 			break;
190 		case AM_rmb:
191 			ea = opcodes.r8(pos++);
192 			util::stream_format(stream, "r%02Xh,", ( ea >> 3 ) & 0x07);
193 			switch( ea & 0xC0 ) {
194 			case 0x00:
195 				util::stream_format(stream, "@r%02Xh", ea & 0x07); break;
196 			case 0x40:
197 				util::stream_format(stream, "(r%02Xh)+", ea & 0x07); break;
198 			case 0x80:
199 				ea2 = opcodes.r8(pos++);
200 				if ( ea & 0x07 ) {
201 					util::stream_format(stream, "$%02X(r%02Xh)", ea2, ea & 0x07);
202 				} else {
203 					util::stream_format(stream, "@$%02X", ea2);
204 				}
205 				break;
206 			case 0xC0:
207 				util::stream_format(stream, "-(r%02Xh)", ea & 0x07); break;
208 			}
209 			break;
210 		case AM_mbr:
211 			ea = opcodes.r8(pos++);
212 			switch( ea & 0xC0 ) {
213 			case 0x00:
214 				util::stream_format(stream, "@r%02Xh", ea & 0x07); break;
215 			case 0x40:
216 				util::stream_format(stream, "(r%02Xh)+", ea & 0x07); break;
217 			case 0x80:
218 				ea2 = opcodes.r8(pos++);
219 				if ( ea & 0x07 ) {
220 					util::stream_format(stream, "$%02X(r%02Xh)", ea2, ea & 0x07);
221 				} else {
222 					util::stream_format(stream, "@$%02X", ea2);
223 				}
224 				break;
225 			case 0xC0:
226 				util::stream_format(stream, "-(r%02Xh)", ea & 0x07); break;
227 			}
228 			util::stream_format(stream, ",r%02Xh", ( ea >> 3 ) & 0x07);
229 			break;
230 		case AM_rmw:
231 			ea = opcodes.r8(pos++);
232 			util::stream_format(stream, "r%02Xh,", ( ea >> 3 ) & 0x07);
233 			switch( ea & 0xC0 ) {
234 			case 0x00:
235 				util::stream_format(stream, "@rr%02Xh", sm8500_b2w[ea & 0x07]); break;
236 			case 0x40:
237 				util::stream_format(stream, "(rr%02Xh)+", sm8500_b2w[ea & 0x07]); break;
238 			case 0x80:
239 				ea2 = opcodes.r8(pos++) << 8;
240 				ea2 += opcodes.r8(pos++);
241 				if ( ea & 0x07 ) {
242 					util::stream_format(stream, "$%04X(rr%02Xh)", ea2, sm8500_b2w[ea & 0x07]);
243 				} else {
244 					util::stream_format(stream, "@$%04X", ea2);
245 				}
246 				break;
247 			case 0xC0:
248 				util::stream_format(stream, "-(rr%02Xh)", sm8500_b2w[ea & 0x07]); break;
249 			}
250 			break;
251 		case AM_mwr:
252 			ea = opcodes.r8(pos++);
253 			switch( ea & 0xC0 ) {
254 			case 0x00:
255 				util::stream_format(stream, "@rr%02Xh", sm8500_b2w[ea & 0x07]); break;
256 			case 0x40:
257 				util::stream_format(stream, "(rr%02Xh)+", sm8500_b2w[ea & 0x07]); break;
258 			case 0x80:
259 				ea2 = opcodes.r8(pos++) << 8;
260 				ea2 += opcodes.r8(pos++);
261 				if ( ea & 0x07 ) {
262 					util::stream_format(stream, "$%04X(rr%02Xh)", ea2, sm8500_b2w[ea & 0x07]);
263 				} else {
264 					util::stream_format(stream, "@$%04X", ea2);
265 				}
266 				break;
267 			case 0xC0:
268 				util::stream_format(stream, "-(rr%02Xh)", sm8500_b2w[ea & 0x07]); break;
269 			}
270 			util::stream_format(stream, ",r%02Xh", ( ea >> 3 ) & 0x07);
271 			break;
272 		case AM_smw:
273 			ea = opcodes.r8(pos++);
274 			util::stream_format(stream, "rr%02Xh,", sm8500_b2w[( ea >> 3 ) & 0x07]);
275 			switch( ea & 0xC0 ) {
276 			case 0x00:
277 				util::stream_format(stream, "@rr%02Xh", sm8500_b2w[ea & 0x07]); break;
278 			case 0x40:
279 				util::stream_format(stream, "(rr%02Xh)+", sm8500_b2w[ea & 0x07]); break;
280 			case 0x80:
281 				ea2 = opcodes.r8(pos++) << 8;
282 				ea2 += opcodes.r8(pos++);
283 				if ( ea & 0x07 ) {
284 					util::stream_format(stream, "$%04X(rr%02Xh)", ea2, sm8500_b2w[ea & 0x07]);
285 				} else {
286 					util::stream_format(stream, "@$%04X", ea2);
287 				}
288 				break;
289 			case 0xC0:
290 				util::stream_format(stream, "-(rr%02Xh)", sm8500_b2w[ea & 0x07]); break;
291 			}
292 			break;
293 		case AM_mws:
294 			ea = opcodes.r8(pos++);
295 			switch( ea & 0xC0 ) {
296 			case 0x00:
297 				util::stream_format(stream, "@rr%02Xh", sm8500_b2w[ea & 0x07]); break;
298 			case 0x40:
299 				util::stream_format(stream, "(rr%02Xh)+", sm8500_b2w[ea & 0x07]); break;
300 			case 0x80:
301 				ea2 = opcodes.r8(pos++) << 8;
302 				ea2 += opcodes.r8(pos++);
303 				if ( ea & 0x07 ) {
304 					util::stream_format(stream, "$%04X(rr%02Xh)", ea2, sm8500_b2w[ea & 0x07]);
305 				} else {
306 					util::stream_format(stream, "@$%04X", ea2);
307 				}
308 				break;
309 			case 0xC0:
310 				util::stream_format(stream, "-(rr%02Xh)", sm8500_b2w[ea & 0x07]); break;
311 			}
312 			util::stream_format(stream, ",rr%02Xh", sm8500_b2w[( ea >> 3 ) & 0x07]);
313 			break;
314 		case AM_cbr:
315 			offset = (int8_t) opcodes.r8(pos++);
316 			util::stream_format(stream, "%s,$%04X", sm8500_cond[ op & 0x0F ], pos + offset);
317 			break;
318 		case AM_rbr:
319 			offset = (int8_t) opcodes.r8(pos++);
320 			util::stream_format(stream, "r%02Xh,$%04X", op & 0x07, pos + offset);
321 			break;
322 		case AM_cjp:
323 			ea = opcodes.r8(pos++) << 8;
324 			ea += opcodes.r8(pos++);
325 			util::stream_format(stream, "%s,$%04X", sm8500_cond[ op & 0x0F], ea);
326 			break;
327 		case AM_rr:
328 			ea = opcodes.r8(pos++);
329 			switch( ea & 0xc0 ) {
330 			case 0x00:
331 				util::stream_format(stream, "r%02Xh,r%02Xh", (ea >> 3 ) & 0x07, ea & 0x07);
332 				break;
333 			case 0x40:
334 			case 0x80:
335 			case 0xC0:
336 				util::stream_format(stream, "undef");
337 				break;
338 			}
339 			break;
340 		case AM_r1:
341 			ea = opcodes.r8(pos++);
342 			switch( ea & 0xC0 ) {
343 			case 0x00:
344 				util::stream_format(stream, "@r%02Xh", (ea >> 3 ) & 0x07);
345 				break;
346 			case 0x40:
347 			case 0x80:
348 			case 0xC0:
349 				util::stream_format(stream, "undef");
350 				break;
351 			}
352 			break;
353 		case AM_S:
354 			ea = opcodes.r8(pos++);
355 			util::stream_format(stream, "RR%02Xh", ea);
356 			break;
357 		case AM_pi:
358 			ea = opcodes.r8(pos++);
359 			util::stream_format(stream, "r%02Xh, $%02X", 0x10 + (op & 0x07), ea);
360 			break;
361 		case AM_Ri:
362 			ea = opcodes.r8(pos++);
363 			ea2 = opcodes.r8(pos++);
364 			util::stream_format(stream, "R%02Xh,$%02X", ea, ea2);
365 			break;
366 		case AM_i:
367 			ea = opcodes.r8(pos++);
368 			util::stream_format(stream, "$%02X", ea);
369 			break;
370 		case AM_ii:
371 			ea = opcodes.r8(pos++) << 8;
372 			ea += opcodes.r8(pos++);
373 			util::stream_format(stream, "$%04X", ea);
374 			break;
375 		case AM_5A:
376 			ea = opcodes.r8(pos++);
377 			ea2 = opcodes.r8(pos++);
378 			switch( ea & 0xC0 ) {
379 			case 0x00:
380 				util::stream_format(stream, "CMP (rr%02Xh),$%02Xh", ea & 7, ea2); break;
381 			case 0x40:
382 				util::stream_format(stream, "undef $%04X", ea); break;
383 			case 0x80:
384 				ea3 = opcodes.r8(pos++);
385 				util::stream_format(stream, "CMP (rr%02Xh+%02Xh),$%02Xh", ea & 7, ea2, ea3); break;
386 			case 0xC0:
387 				util::stream_format(stream, "undef $%04X", ea); break;
388 			}
389 			break;
390 		case AM_5B:
391 			ea = opcodes.r8(pos++);
392 			ea2 = opcodes.r8(pos++);
393 			ea3 = (ea << 8) | ea2;
394 			switch( ea & 0xC0 ) {
395 			case 0x40:
396 				util::stream_format(stream, "MOV (rr%02Xh)+,$%02Xh", ea & 7, ea2); break; // could be AND instead of MOV
397 			default:
398 				util::stream_format(stream, "undef $%04X", ea3); break;
399 			}
400 			break;
401 		case AM_ss:
402 			ea = opcodes.r8(pos++);
403 			switch( ea & 0xC0 ) {
404 			case 0x00:
405 				util::stream_format(stream, "rr%02Xh,rr%02Xh", sm8500_b2w[( ea >> 3 ) & 0x07], sm8500_b2w[ea & 0x07]); break;
406 			case 0x40:
407 				util::stream_format(stream, "undef"); break;
408 			case 0x80:
409 				util::stream_format(stream, "undef"); break;
410 			case 0xC0:
411 				util::stream_format(stream, "undef"); break;
412 			}
413 			break;
414 		case AM_RR:
415 			ea = opcodes.r8(pos++);
416 			ea2 = opcodes.r8(pos++);
417 			util::stream_format(stream, "R%02Xh,R%02Xh", ea2, ea);
418 			break;
419 		case AM_2:
420 			ea = opcodes.r8(pos++);
421 			switch( ea & 0xC0 ) {
422 			case 0x00:
423 				util::stream_format(stream, "rr%02Xh", sm8500_b2w[ea & 0x07]); break;
424 			case 0x40:
425 				ea2 = opcodes.r8(pos++) << 8;
426 				ea2 += opcodes.r8(pos++);
427 				if ( ea & 0x38 ) {
428 					util::stream_format(stream, "@$%04X(r%02Xh)", ea2, ( ea >> 3 ) & 0x07);
429 				} else {
430 					util::stream_format(stream, "@$%04X", ea2);
431 				}
432 				break;
433 			case 0x80:
434 				util::stream_format(stream, "undef"); break;
435 			case 0xC0:
436 				util::stream_format(stream, "undef"); break;
437 			}
438 			break;
439 		case AM_SS:
440 			ea = opcodes.r8(pos++);
441 			ea2 = opcodes.r8(pos++);
442 			util::stream_format(stream, "RR%02Xh,RR%02Xh", ea2, ea);
443 			break;
444 		case AM_bR:
445 			ea = opcodes.r8(pos++);
446 			ea2 = opcodes.r8(pos++);
447 			switch( ea & 0xC0 ) {
448 			case 0x00:
449 				util::stream_format(stream, "BF,R%02Xh,#%d", ea2, ea & 0x07); break;
450 			case 0x40:
451 				util::stream_format(stream, "R%02Xh,#%d,BF", ea2, ea & 0x07); break;
452 			case 0x80:
453 				util::stream_format(stream, "undef"); break;
454 			case 0xC0:
455 				util::stream_format(stream, "undef"); break;
456 			}
457 			break;
458 		case AM_Rbr:
459 			ea = opcodes.r8(pos++);
460 			offset = (int8_t) opcodes.r8(pos++);
461 			util::stream_format(stream, "R%02Xh,#%d,$%04X", ea, op & 0x07, pos + offset);
462 			break;
463 		case AM_Rb:
464 			ea = opcodes.r8(pos++);
465 			util::stream_format(stream, "R%02Xh,#%d", ea, op&0x07);
466 			break;
467 		case AM_rR:
468 			ea = opcodes.r8(pos++);
469 			util::stream_format(stream, "r%02Xh,R%02Xh", op & 0x07, ea);
470 			break;
471 		case AM_Rr:
472 			ea = opcodes.r8(pos++);
473 			util::stream_format(stream, "R%02Xh,r%02Xh", ea, op & 0x07);
474 			break;
475 		case AM_Rii:
476 			ea = opcodes.r8(pos++);
477 			util::stream_format(stream, "R%02Xh,", ea);
478 			ea = opcodes.r8(pos++);
479 			util::stream_format(stream, "$%02X,", ea);
480 			ea = opcodes.r8(pos++);
481 			util::stream_format(stream, "$%02X", ea);
482 			break;
483 		case AM_RiR:
484 			ea = opcodes.r8(pos++);
485 			util::stream_format(stream, "R%02Xh,", ea);
486 			ea = opcodes.r8(pos++);
487 			util::stream_format(stream, "$%02X,", ea);
488 			ea = opcodes.r8(pos++);
489 			util::stream_format(stream, "R%02Xh", ea);
490 			break;
491 		case AM_riB:
492 			ea = opcodes.r8(pos++);
493 			ea2 = opcodes.r8(pos++);
494 			switch( ea & 0xC0 ) {
495 			case 0x00:
496 				util::stream_format(stream, "#%2x(r%02Xh),#%d", ea2, ea >> 3, ea & 0x07);
497 				break;
498 			case 0x40:
499 				util::stream_format(stream, "undef"); break;
500 			case 0x80:
501 				util::stream_format(stream, "undef"); break;
502 			case 0xC0:
503 				util::stream_format(stream, "undef"); break;
504 			}
505 			break;
506 		case AM_CALS:
507 			ea = opcodes.r8(pos++);
508 			util::stream_format(stream, "$%04X", 0x1000 | ( ( op & 0x0f ) << 8 ) | ea);
509 			break;
510 		case AM_bid:
511 			ea = opcodes.r8(pos++);
512 			ea2 = opcodes.r8(pos++);
513 			if ( ea & 0x38 ) {
514 				util::stream_format(stream, "$%02X(r%02Xh)", ea2, ( ea >> 3 ) & 0x07);
515 			} else {
516 				util::stream_format(stream, "$%04X", 0xFF00 + ea2);
517 			}
518 			util::stream_format(stream, ",#%d,", ea & 0x07);
519 			offset = (int8_t) opcodes.r8(pos++);
520 			util::stream_format(stream, "$%04X", pos + offset);
521 			break;
522 		case AM_1A:
523 			ea = opcodes.r8(pos++);
524 			switch( ea & 0x07 ) {
525 			case 0x00: util::stream_format(stream, "%-4s ", s_mnemonic[ zCLR ]); break;
526 			case 0x01: util::stream_format(stream, "%-4s ", s_mnemonic[ zNEG ]); break;
527 			case 0x02: util::stream_format(stream, "%-4s ", s_mnemonic[ zCOM ]); break;
528 			case 0x03: util::stream_format(stream, "%-4s ", s_mnemonic[ zRR ]); break;
529 			case 0x04: util::stream_format(stream, "%-4s ", s_mnemonic[ zRL ]); break;
530 			case 0x05: util::stream_format(stream, "%-4s ", s_mnemonic[ zRRC ]); break;
531 			case 0x06: util::stream_format(stream, "%-4s ", s_mnemonic[ zRLC ]); break;
532 			case 0x07: util::stream_format(stream, "%-4s ", s_mnemonic[ zSRL ]); break;
533 			}
534 			util::stream_format(stream, "@r%02Xh", ( ea >> 3 ) & 0x07);
535 			break;
536 		case AM_1B:
537 			ea = opcodes.r8(pos++);
538 			switch( ea & 0x07 ) {
539 			case 0x00: util::stream_format(stream, "%-4s ", s_mnemonic[ zINC ]); break;
540 			case 0x01: util::stream_format(stream, "%-4s ", s_mnemonic[ zDEC ]); break;
541 			case 0x02: util::stream_format(stream, "%-4s ", s_mnemonic[ zSRA ]); break;
542 			case 0x03: util::stream_format(stream, "%-4s ", s_mnemonic[ zSLL ]); break;
543 			case 0x04: util::stream_format(stream, "%-4s ", s_mnemonic[ zDA ]); break;
544 			case 0x05: util::stream_format(stream, "%-4s ", s_mnemonic[ zSWAP ]); break;
545 			case 0x06: util::stream_format(stream, "%-4s ", s_mnemonic[ zPUSH ]); break;
546 			case 0x07: util::stream_format(stream, "%-4s ", s_mnemonic[ zPOP ]); break;
547 			}
548 			util::stream_format(stream, "@r%02Xh", ( ea >> 3 ) & 0x07);
549 			break;
550 		case AM_4F:
551 			ea = opcodes.r8(pos++);
552 			ea2 = opcodes.r8(pos++);
553 			switch( ea & 0xc0 ) {
554 			case 0x00: util::stream_format(stream, "%-4s ", s_mnemonic[ zBCMP ]); break;
555 			case 0x40: util::stream_format(stream, "%-4s ", s_mnemonic[ zBAND ]); break;
556 			case 0x80: util::stream_format(stream, "%-4s ", s_mnemonic[ zBOR ]); break;
557 			case 0xC0: util::stream_format(stream, "%-4s ", s_mnemonic[ zBXOR ]); break;
558 			}
559 			if ( ! ( ea & 0x80 ) ) {
560 				util::stream_format(stream, "BF,");
561 			}
562 			util::stream_format(stream, "R%02Xh,$%02X", ea2, ea & 0x07);
563 			if ( ea & 0x80 ) {
564 				util::stream_format(stream, ",BF");
565 			}
566 			break;
567 		}
568 	}
569 	else
570 	{
571 		util::stream_format(stream, "%s", s_mnemonic[ instr->mnemonic ]);
572 	}
573 
574 	return (pos - pc) | s_flags[instr->mnemonic] | SUPPORTED;
575 }
576