1 /*****************************************************************************
2  *
3  *	 8000dasm.c
4  *	 Portable Z8000(2) emulator
5  *	 Z8000 disassembler; requires the z8000_exec table to be initialized
6  *
7  *	 Copyright (c) 1998 Juergen Buchmueller, all rights reserved.
8  *	 Bug fixes and MSB_FIRST compliance Ernesto Corvi.
9  *
10  *	 - This source code is released as freeware for non-commercial purposes.
11  *	 - You are free to use and redistribute this code in modified or
12  *	   unmodified form, provided you list me in the credits.
13  *	 - If you modify this source code, you must add a notice to each modified
14  *	   source file that it has been changed.  If you're a nice person, you
15  *	   will clearly mark each change too.  :)
16  *	 - If you wish to use this for commercial purposes, please contact me at
17  *	   pullmoll@t-online.de
18  *	 - The author of this copywritten work reserves the right to change the
19  *     terms of its usage and license at any time, including retroactively
20  *   - This entire notice must remain in the source code.
21  *
22  *****************************************************************************/
23 
24 #include <stdio.h>
25 #include "z8000.h"
26 #include "z8000cpu.h"
27 #include "memory.h"
28 
29 static int n[12];	/* opcode nibbles */
30 static int b[6];	/* opcode bytes */
31 static int w[3];	/* opcode words */
32 
GET_OP(int i,unsigned pc)33 void GET_OP(int i, unsigned pc)
34 {
35 	UINT16 opcode = cpu_readop16(pc);
36 	w[i] = opcode;
37 	b[i*2+0] = opcode >> 8;
38 	b[i*2+1] = opcode & 0xff;
39 	n[i*4+0] = (opcode >> 12) & 0x0f;
40 	n[i*4+1] = (opcode >> 8) & 0x0f;
41 	n[i*4+2] = (opcode >> 4) & 0x0f;
42 	n[i*4+3] = opcode & 0x0f;
43 }
44 
45 static const char *cc[16] = {
46 	"n",   "lt",  "le",  "ule",  "pe/ov",   "mi",  "eq/z",   "c/ult",
47 	"a",   "ge",  "gt",  "ugt",  "po/nov",  "pl",  "ne/nz",  "nc/uge"
48 };
49 
50 static const char *flg[16] = {
51 	"",    "p/v",  "s",   "p/v,s",   "z",   "p/v,z",  "s,z",  "p/v,s,z",
52 	"c",   "p/v,c","s,c", "p/v,s,c", "z,c", "p/v,z,c","s,z,c","p/v,s,z,c"
53 };
54 
55 static const char *ints[4] = {
56 	"",    "vi",  "nvi",   "vi,nvi"
57 };
58 
DasmZ8000(char * buff,int pc)59 int DasmZ8000(char *buff, int pc)
60 {
61 	int new_pc = pc, i, tmp;
62 	char *dst = buff;
63 	const char *src;
64 	Z8000_exec *o;
65 
66     GET_OP(0, new_pc);
67 	new_pc += 2;
68 	switch (pc)
69 	{
70 		case 0x0000:
71 			dst += sprintf(dst, ".word   #$%04x ;RST", w[0]);
72 			break;
73 		case 0x0002:
74 			dst += sprintf(dst, ".word   #$%04x ;RST FCW", w[0]);
75             break;
76 		case 0x0004:
77 			dst += sprintf(dst, ".word   #$%04x ;RST PC", w[0]);
78             break;
79 		default:
80 			o = &z8000_exec[w[0]];
81 			if (o->size > 1) { GET_OP(1, new_pc); new_pc += 2; }
82 			if (o->size > 2) { GET_OP(2, new_pc); new_pc += 2; }
83 			src = o->dasm;
84 
85 			while (*src)
86 			{
87 				if (*src == '%')
88 				{
89 					src++;
90 					switch (*src) {
91 					case '0': case '1': case '2': case '3':
92 					case '4': case '5': case '6': case '7':
93 						/* nibble number */
94 						i = *src++ - '0';
95 						dst += sprintf(dst, "%d", n[i]);
96 						break;
97 					case '#':
98 						/* immediate */
99 						src++;
100 						switch (*src++) {
101 							case 'b': /* imm8 (byte) */
102 								i = *src++ - '0';
103 								dst += sprintf(dst, "#$%02x", b[i]);
104 								break;
105 							case 'w': /* imm16 (word) */
106 								i = *src++ - '0';
107 								dst += sprintf(dst, "#$%04x", w[i]);
108 								break;
109 							case 'l': /* imm32 (long) */
110 								i = *src++ - '0';
111 								dst += sprintf(dst, "#$%04x%04x", w[i], w[i+1]);
112 								break;
113 						}
114 						break;
115 					case '$':
116 						/* absolute immediate 8bit (rl/rr) */
117 						src++;
118 						i = *src++ - '0';
119 						dst += sprintf(dst, "#%d", ((INT8)b[i]<0) ? -(INT8)b[i] : b[i]);
120 						break;
121 					case '+':
122 						/* imm4m1 (inc/dec value) */
123 						src++;
124 						i = *src++ - '0';
125 						dst += sprintf(dst, "%i", n[i] + 1);
126 						break;
127 					case '*':
128 						/* left/right (rotate/shift) */
129 						src++;
130 						dst += sprintf(dst, "%c", b[2] ? 'r' : 'l');
131 						break;
132 					case '?':
133 						/* imm1or2 (shift/rotate once or twice) */
134 						src++;
135 						i = *src++ - '0';
136 						dst += sprintf(dst, "%c", (n[i] & 2) ? '2' : '1');
137 						break;
138 					case 'R':
139 						src++;
140 						tmp = ((n[1] & 0x01) << 16) + (n[3] << 8) + (n[7] & 0x08);
141 						switch (tmp)
142 						{
143 							case 0x000: dst += sprintf(dst, "inirb "); break;
144 							case 0x008: dst += sprintf(dst, "inib  "); break;
145 							case 0x010: dst += sprintf(dst, "sinirb"); break;
146 							case 0x018: dst += sprintf(dst, "sinib "); break;
147 							case 0x020: dst += sprintf(dst, "otirb "); break;
148 							case 0x028: dst += sprintf(dst, "outib "); break;
149 							case 0x030: dst += sprintf(dst, "soutib"); break;
150 							case 0x038: dst += sprintf(dst, "sotirb"); break;
151 							case 0x040: dst += sprintf(dst, "inb   "); break;
152 							case 0x048: dst += sprintf(dst, "inb   "); break;
153 							case 0x050: dst += sprintf(dst, "sinb  "); break;
154 							case 0x058: dst += sprintf(dst, "sinb  "); break;
155 							case 0x060: dst += sprintf(dst, "outb  "); break;
156 							case 0x068: dst += sprintf(dst, "outb  "); break;
157 							case 0x070: dst += sprintf(dst, "soutb "); break;
158 							case 0x078: dst += sprintf(dst, "soutb "); break;
159 							case 0x080: dst += sprintf(dst, "indrb "); break;
160 							case 0x088: dst += sprintf(dst, "indb  "); break;
161 							case 0x090: dst += sprintf(dst, "sindrb"); break;
162 							case 0x098: dst += sprintf(dst, "sindb "); break;
163 							case 0x0a0: dst += sprintf(dst, "otdrb "); break;
164 							case 0x0a8: dst += sprintf(dst, "outdb "); break;
165 							case 0x0b0: dst += sprintf(dst, "soutdb"); break;
166 							case 0x0b8: dst += sprintf(dst, "sotdrb"); break;
167 							case 0x100: dst += sprintf(dst, "inir  "); break;
168 							case 0x108: dst += sprintf(dst, "ini   "); break;
169 							case 0x110: dst += sprintf(dst, "sinir "); break;
170 							case 0x118: dst += sprintf(dst, "sini  "); break;
171 							case 0x120: dst += sprintf(dst, "otir  "); break;
172 							case 0x128: dst += sprintf(dst, "outi  "); break;
173 							case 0x130: dst += sprintf(dst, "souti "); break;
174 							case 0x138: dst += sprintf(dst, "sotir "); break;
175 							case 0x140: dst += sprintf(dst, "in    "); break;
176 							case 0x148: dst += sprintf(dst, "in    "); break;
177 							case 0x150: dst += sprintf(dst, "sin   "); break;
178 							case 0x158: dst += sprintf(dst, "sin   "); break;
179 							case 0x160: dst += sprintf(dst, "out   "); break;
180 							case 0x168: dst += sprintf(dst, "out   "); break;
181 							case 0x170: dst += sprintf(dst, "sout  "); break;
182 							case 0x178: dst += sprintf(dst, "sout  "); break;
183 							case 0x180: dst += sprintf(dst, "indr  "); break;
184 							case 0x188: dst += sprintf(dst, "ind   "); break;
185 							case 0x190: dst += sprintf(dst, "sindr "); break;
186 							case 0x198: dst += sprintf(dst, "sind  "); break;
187 							case 0x1a0: dst += sprintf(dst, "otdr  "); break;
188 							case 0x1a8: dst += sprintf(dst, "outd  "); break;
189 							case 0x1b0: dst += sprintf(dst, "soutd "); break;
190 							case 0x1b8: dst += sprintf(dst, "sotdr "); break;
191                             default:
192 								dst += sprintf(dst, "??????");
193 						}
194                         break;
195                     case 'a':
196 						/* address */
197 						src++;
198 						i = *src++ - '0';
199 						dst += sprintf(dst, "$%04x", w[i]);
200 						break;
201 					case 'c':
202 						/* condition code */
203 						src++;
204 						i = *src++ - '0';
205 						if (n[i] == 8) {	/* always? */
206 							/* skip following comma */
207 							if (*src == ',')
208 								src++;
209 						}
210 						else dst += sprintf(dst, "%s", cc[n[i]]);
211 						break;
212 					case 'd':
213 						/* displacement */
214 						src++;
215 						i = *src++ - '0';
216 						switch (i) {
217 							case 0: /* disp7 */
218 								tmp = new_pc - 2 * (w[0] & 0x7f);
219 								dst += sprintf(dst, "#$%04x", tmp);
220 								break;
221 							case 1: /* disp8 */
222 								tmp = new_pc + 2 * (INT8)(w[0] & 0xff);
223 								dst += sprintf(dst, "#$%04x", tmp);
224 								break;
225 							case 2: /* disp12 */
226 								tmp = w[0] & 0x7ff;
227 								if (w[0] & 0x800)
228 									tmp = new_pc + 0x1000 -2 * tmp;
229 								else
230 									tmp = new_pc + -2 * tmp;
231 								dst += sprintf(dst, "#$%04x", tmp);
232 								break;
233 						}
234 						break;
235 					case 'f':
236 						/* flag (setflg/resflg/comflg) */
237 						src++;
238 						i = *src++ - '0';
239 						dst += sprintf(dst, "%s", flg[n[i]]);
240 						break;
241 					case 'i':
242 						/* interrupts */
243 						src++;
244 						i = *src++ - '0';
245 						dst += sprintf(dst, "%s", ints[n[i] & 3]);
246 						break;
247 					case 'p':
248 						/* disp16 (pc relative) */
249 						src++;
250 						i = *src++ - '0';
251 						dst += sprintf(dst, "$%04x", new_pc + w[i]);
252 						break;
253 					case 'r':
254 						/* register */
255 						src++;
256 						switch (*src++) {
257 							case 'b':
258 								/* byte */
259 								i = *src++ - '0';
260 								if (n[i] & 8)
261 									dst += sprintf(dst, "rl%d", n[i] & 7);
262 								else
263 									dst += sprintf(dst, "rh%d", n[i]);
264 								break;
265 							case 'w':
266 								/* word */
267 								i = *src++ - '0';
268 								dst += sprintf(dst, "r%d", n[i]);
269 								break;
270 							case 'l':
271 								/* long */
272 								i = *src++ - '0';
273 								dst += sprintf(dst, "rr%d", n[i]);
274 								break;
275 							case 'q':
276 								/* quad word (long long) */
277 								i = *src++ - '0';
278 								dst += sprintf(dst, "rq%d", n[i]);
279 								break;
280 						}
281 						break;
282 					default:
283 						*dst++ = '%';
284 						*dst++ = *src++;
285 						break;
286 					}
287 				} else *dst++ = *src++;
288 			}
289 			*dst = '\0';
290 			break;
291 	}
292 	return new_pc - pc;
293 }
294