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
295