Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
716 | lvd | 1 | #include "std.h" |
2 | |||
3 | #include "emul.h" |
||
4 | #include "vars.h" |
||
5 | #include "memory.h" |
||
6 | #include "dbglabls.h" |
||
7 | |||
8 | #include "util.h" |
||
9 | |||
10 | char asmbuf[0x40]; |
||
11 | |||
12 | #define _iw 9 |
||
13 | #define _ib 10 |
||
14 | #define _shrt 27 |
||
15 | #define _ld 0x89 |
||
16 | #define _zr16 0x8A |
||
17 | #define _zr8 0x8B |
||
18 | #define _cb 0x8C |
||
19 | #define _zjr 0x8D |
||
20 | #define _hl 0x8E |
||
21 | #define _zr81 0x8F |
||
22 | #define _zop 0x90 |
||
23 | #define _zf 0x91 |
||
24 | #define _zr16a 0x92 |
||
25 | #define _zr8_ 0x9D |
||
26 | #define _zr81_ 0x9E |
||
27 | |||
28 | unsigned char asm_tab_z80[] = |
||
29 | { |
||
30 | #if 0 |
||
31 | 2,0xED,0xFF,0xFF,0xFF, // call unreal api |
||
32 | 'u','a','p','i',0, |
||
33 | #endif |
||
34 | |||
35 | // fix bug out (c),a => out (0C),a |
||
36 | 2, 0xED, 0x70, 0xFF, 0xFF, // in (c) |
||
37 | 'i','n',' ','(','c',')',0, |
||
38 | 2, 0xED, 0x71, 0xFF, 0xFF, // out (c),0 |
||
39 | 'o','u','t',' ','(','c',')',',','0',0, |
||
40 | 2, 0xED, 0x40, 0xFF, 0xC7, // in r8,(c) |
||
41 | 'i','n',' ',_zr8,',','(','c',')',0, |
||
42 | 2, 0xED, 0x41, 0xFF, 0xC7, // out (c),r8 |
||
43 | 'o','u','t',' ','(','c',')',',',_zr8,0, |
||
44 | |||
45 | |||
46 | 1,0xCB,0xFF, // all cb-opcodes |
||
47 | _cb,0, |
||
48 | 1, 0x00, 0xFF, // nop |
||
49 | 'n','o','p',0, |
||
50 | 1, 0x08, 0xFF, // ex af,af' |
||
51 | 'e','x',' ','a','f',',','a','f','\'',0, |
||
52 | 1,0x02, 0xFF, // ld (bc),a |
||
53 | _ld, '(','b','c',')',',','a',0, |
||
54 | 1,0x12, 0xFF, // ld (de),a |
||
55 | _ld, '(','d','e',')',',','a',0, |
||
56 | 1,0x0A, 0xFF, // ld a,(bc) |
||
57 | _ld, 'a',',','(','b','c',')',0, |
||
58 | 1,0x1A, 0xFF, // ld a,(de) |
||
59 | _ld, 'a',',','(','d','e',')',0, |
||
60 | 1,0x03,0xCF, // inc r16 |
||
61 | 'i','n','c',' ',_zr16,0, |
||
62 | 1,0x0B,0xCF, // dec r16 |
||
63 | 'd','e','c',' ',_zr16,0, |
||
64 | 1,0x04,0xC7, // inc r8 |
||
65 | 'i','n','c',' ', _zr8,0, |
||
66 | 1, 0x05, 0xC7, // dec r8 |
||
67 | 'd','e','c',' ', _zr8,0, |
||
68 | 1, 0x07, 0xFF, // rlca |
||
69 | 'r','l','c','a',0, |
||
70 | 1, 0x17, 0xFF, // rla |
||
71 | 'r','l','a',0, |
||
72 | 1, 0x27, 0xFF, // daa |
||
73 | 'd','a','a',0, |
||
74 | 1, 0x37, 0xFF, // scf |
||
75 | 's','c','f',0, |
||
76 | 1, 0x0F, 0xFF, // rrca |
||
77 | 'r','r','c','a',0, |
||
78 | 1, 0x1F, 0xFF, // rra |
||
79 | 'r','r','a',0, |
||
80 | 1, 0x2F, 0xFF, // cpl |
||
81 | 'c','p','l',0, |
||
82 | 1, 0x3F, 0xFF, // ccf |
||
83 | 'c','c','f',0, |
||
84 | 1, 0x00, 0xC7, // relative jumps |
||
85 | _zjr, _shrt, 0, |
||
86 | 1, 0x09, 0xCF, // add hl, r16 |
||
87 | 'a','d','d',' ',_hl,',',_zr16,0, |
||
88 | 1, 0x32, 0xFF, // ld (nnnn),a |
||
89 | _ld,'(',_iw,')',',','a',0, |
||
90 | 1, 0x3A, 0xFF, // ld a,(nnnn) |
||
91 | _ld,'a',',','(',_iw,')',0, |
||
92 | 1, 0x22, 0xFF, // ld (nnnn),hl |
||
93 | _ld,'(',_iw,')',',',_hl,0, |
||
94 | 1, 0x2A, 0xFF, // ld hl,(nnnn) |
||
95 | _ld,_hl,',','(',_iw,')',0, |
||
96 | 1, 0x76, 0xFF, // halt |
||
97 | 'h','a','l','t',0, |
||
98 | 1, 0x40, 0xC0, // ld r8,r8 |
||
99 | _ld, _zr8_, ',', _zr81_, 0, |
||
100 | 1, 0x80, 0xC0, // op r8 |
||
101 | _zop/*, ' '*/, _zr81, 0, |
||
102 | 1, 0xC0, 0xC7, // ret cc |
||
103 | 'r','e','t',' ',_zf,0, |
||
104 | 1, 0xC2, 0xC7, // jp cc, nnnn |
||
105 | 'j','p',' ',_zf,',',_iw,0, |
||
106 | 1, 0xC4, 0xC7, // call cc, nnnn |
||
107 | 'c','a','l','l',' ',_zf,',',_iw,0, |
||
108 | 1, 0xC6, 0xC7, // op immb |
||
109 | _zop/*, ' '*/, _ib, 0, |
||
110 | 1, 0xC1, 0xCF, // pop r16a |
||
111 | 'p','o','p',' ',_zr16a,0, |
||
112 | 1, 0xC5, 0xCF, // push r16a |
||
113 | 'p','u','s','h',' ',_zr16a,0, |
||
114 | 1, 0xC3, 0xFF, // jp nnnn |
||
115 | 'j','p', ' ', _iw,0, |
||
116 | 1, 0xD3, 0xFF, // out (nn),a |
||
117 | 'o','u','t',' ','(',_ib,')',',','a',0, |
||
118 | 1, 0xE3, 0xFF, // ex (sp),hl |
||
119 | 'e','x',' ','(','s','p',')',',',_hl,0, |
||
120 | 1, 0xF3, 0xFF, // di |
||
121 | 'd','i',0, |
||
122 | 1, 0xC9, 0xFF, // ret |
||
123 | 'r','e','t',0, |
||
124 | 1, 0xD9, 0xFF, // exx |
||
125 | 'e','x','x',0, |
||
126 | 1, 0xE9, 0xFF, // jp (hl) |
||
127 | 'j','p',' ','(',_hl,')',0, |
||
128 | 1, 0xF9, 0xFF, // ld sp, hl |
||
129 | _ld, 's','p',',',_hl,0, |
||
130 | 1, 0xDB, 0xFF, // in a,(nn) |
||
131 | 'i','n',' ','a',',','(',_ib,')',0, |
||
132 | 1, 0xEB, 0xFF, // ex de,hl - no 'ex de,ix' ! |
||
133 | 'e','x',' ','d','e',',','h','l',0, |
||
134 | 1, 0xFB, 0xFF, // ei |
||
135 | 'e','i',0, |
||
136 | 1, 0xCD, 0xFF, // call nnnn |
||
137 | 'c','a','l','l',' ',_iw,0, |
||
138 | 1, 0xC7, 0xFF, // rst 0 |
||
139 | 'r','s','t',' ','0',0, |
||
140 | 1, 0xCF, 0xFF, // rst 8 |
||
141 | 'r','s','t',' ','8',0, |
||
142 | 1, 0xD7, 0xFF, // rst 10 |
||
143 | 'r','s','t',' ','1','0',0, |
||
144 | 1, 0xDF, 0xFF, // rst 18 |
||
145 | 'r','s','t',' ','1','8',0, |
||
146 | 1, 0xE7, 0xFF, // rst 20 |
||
147 | 'r','s','t',' ','2','0',0, |
||
148 | 1, 0xEF, 0xFF, // rst 28 |
||
149 | 'r','s','t',' ','2','8',0, |
||
150 | 1, 0xF7, 0xFF, // rst 30 |
||
151 | 'r','s','t',' ','3','0',0, |
||
152 | 1, 0xFF, 0xFF, // rst 38 |
||
153 | 'r','s','t',' ','3','8',0, |
||
154 | |||
155 | |||
156 | // ED opcodes |
||
157 | #if 0 // moved above |
||
158 | 2, 0xED, 0x70, 0xFF, 0xFF, // in (c) |
||
159 | 'i','n',' ','(','c',')',0, |
||
160 | 2, 0xED, 0x71, 0xFF, 0xFF, // out (c),0 |
||
161 | 'o','u','t',' ','(','c',')',',','0',0, |
||
162 | 2, 0xED, 0x40, 0xFF, 0xC7, // in r8,(c) |
||
163 | 'i','n',' ',_zr8,',','(','c',')',0, |
||
164 | 2, 0xED, 0x41, 0xFF, 0xC7, // out (c),r8 |
||
165 | 'o','u','t',' ','(','c',')',',',_zr8,0, |
||
166 | #endif |
||
167 | 2, 0xED, 0x42, 0xFF, 0xCF, // sbc hl,r16 |
||
168 | 's','b','c',' ','h','l',',',_zr16,0, |
||
169 | 2, 0xED, 0x4A, 0xFF, 0xCF, // adc hl,r16 |
||
170 | 'a','d','c',' ','h','l',',',_zr16,0, |
||
171 | 2, 0xED, 0x43, 0xFF, 0xCF, // ld (nnnn), r16 |
||
172 | _ld, '(',_iw,')',',',_zr16, 0, |
||
173 | 2, 0xED, 0x4B, 0xFF, 0xCF, // ld r16, (nnnn) |
||
174 | _ld, _zr16, ',', '(',_iw,')', 0, |
||
175 | 2, 0xED, 0x44, 0xFF, 0xC7, // neg |
||
176 | 'n','e','g',0, |
||
177 | 2, 0xED, 0x45, 0xFF, 0xCF, // retn |
||
178 | 'r','e','t','n',0, |
||
179 | 2, 0xED, 0x4D, 0xFF, 0xCF, // reti |
||
180 | 'r','e','t','i',0, |
||
181 | 2, 0xED, 0x46, 0xFF, 0xDF, // im 0 |
||
182 | 'i','m',' ','0',0, |
||
183 | 2, 0xED, 0x56, 0xFF, 0xDF, // im 1 |
||
184 | 'i','m',' ','1',0, |
||
185 | 2, 0xED, 0x5E, 0xFF, 0xDF, // im 2 |
||
186 | 'i','m',' ','2',0, |
||
187 | 2, 0xED, 0x4E, 0xFF, 0xDF, // im 0/1 |
||
188 | 'i','m',' ','0','/','1',0, |
||
189 | 2, 0xED, 0x47, 0xFF, 0xFF, // ld i,a |
||
190 | _ld, 'i',',','a',0, |
||
191 | 2, 0xED, 0x57, 0xFF, 0xFF, // ld a,i |
||
192 | _ld, 'a',',','i',0, |
||
193 | 2, 0xED, 0x67, 0xFF, 0xFF, // rrd |
||
194 | 'r','r','d',0, |
||
195 | 2, 0xED, 0x4F, 0xFF, 0xFF, // ld r,a |
||
196 | _ld, 'r',',','a',0, |
||
197 | 2, 0xED, 0x5F, 0xFF, 0xFF, // ld a,r |
||
198 | _ld, 'a',',','r',0, |
||
199 | 2, 0xED, 0x6F, 0xFF, 0xFF, // rld |
||
200 | 'r','l','d',0, |
||
201 | |||
202 | 2, 0xED, 0xA0, 0xFF, 0xFF, // ldi |
||
203 | 'l','d','i',0, |
||
204 | 2, 0xED, 0xA1, 0xFF, 0xFF, // cpi |
||
205 | 'c','p','i',0, |
||
206 | 2, 0xED, 0xA2, 0xFF, 0xFF, // ini |
||
207 | 'i','n','i',0, |
||
208 | 2, 0xED, 0xA3, 0xFF, 0xFF, // outi |
||
209 | 'o','u','t','i',0, |
||
210 | 2, 0xED, 0xA8, 0xFF, 0xFF, // ldd |
||
211 | 'l','d','d',0, |
||
212 | 2, 0xED, 0xA9, 0xFF, 0xFF, // cpd |
||
213 | 'c','p','d',0, |
||
214 | 2, 0xED, 0xAA, 0xFF, 0xFF, // ind |
||
215 | 'i','n','d',0, |
||
216 | 2, 0xED, 0xAB, 0xFF, 0xFF, // outd |
||
217 | 'o','u','t','d',0, |
||
218 | |||
219 | 2, 0xED, 0xB0, 0xFF, 0xFF, // ldir |
||
220 | 'l','d','i','r',0, |
||
221 | 2, 0xED, 0xB1, 0xFF, 0xFF, // cpir |
||
222 | 'c','p','i','r',0, |
||
223 | 2, 0xED, 0xB2, 0xFF, 0xFF, // inir |
||
224 | 'i','n','i','r',0, |
||
225 | 2, 0xED, 0xB3, 0xFF, 0xFF, // otir |
||
226 | 'o','t','i','r',0, |
||
227 | 2, 0xED, 0xB8, 0xFF, 0xFF, // lddr |
||
228 | 'l','d','d','r',0, |
||
229 | 2, 0xED, 0xB9, 0xFF, 0xFF, // cpdr |
||
230 | 'c','p','d','r',0, |
||
231 | 2, 0xED, 0xBA, 0xFF, 0xFF, // indr |
||
232 | 'i','n','d','r',0, |
||
233 | 2, 0xED, 0xBB, 0xFF, 0xFF, // otdr |
||
234 | 'o','t','d','r',0, |
||
235 | |||
236 | 2, 0xED, 0x00, 0xFF, 0x00, // all others 'ED' |
||
237 | 'n','o','p','*',0, |
||
238 | |||
239 | // place immediates after all - 'ld a,b' is not 'ld a,0B' |
||
240 | 1, 0x01, 0xCF, // ld r16,imm16 |
||
241 | _ld, _zr16, ',', _iw, 0, |
||
242 | 1, 0x06, 0xC7, // ld r8, imm8 |
||
243 | _ld, _zr8, ',', _ib, 0, |
||
244 | |||
245 | |||
246 | }; |
||
247 | |||
248 | |||
249 | #define abs(x) ((x)>0? (x):(-(x))) |
||
250 | |||
251 | // ======================================================================= |
||
252 | char z80r16_1[] = "bc\0de\0hl\0sp"; |
||
253 | char z80r16_2[] = "bc\0de\0ix\0sp"; |
||
254 | char z80r16_3[] = "bc\0de\0iy\0sp"; |
||
255 | char z80r8_1[] = "b\0\0\0\0c\0\0\0\0d\0\0\0\0e\0\0\0\0h\0\0\0\0l\0\0\0\0(hl)\0a"; |
||
256 | char z80r8_2[] = "b\0\0\0\0c\0\0\0\0d\0\0\0\0e\0\0\0\0xh\0\0\0xl\0\0\0(1x)\0a"; |
||
257 | char z80r8_3[] = "b\0\0\0\0c\0\0\0\0d\0\0\0\0e\0\0\0\0yh\0\0\0yl\0\0\0(1y)\0a"; |
||
258 | char cbtab[] = "rlc \0\0\0rrc \0\0\0rl \0\0\0\0rr \0\0\0\0sla \0\0\0sra \0\0\0sli \0\0\0srl \0\0\0" |
||
259 | "bit 0,\0bit 1,\0bit 2,\0bit 3,\0bit 4,\0bit 5,\0bit 6,\0bit 7,\0" |
||
260 | "res 0,\0res 1,\0res 2,\0res 3,\0res 4,\0res 5,\0res 6,\0res 7,\0" |
||
261 | "set 0,\0set 1,\0set 2,\0set 3,\0set 4,\0set 5,\0set 6,\0set 7,\0"; |
||
262 | char zjr[] = "xxxxxx\0xxxxxx\0djnz \0\0jr \0\0\0\0jr nz,\0jr z,\0\0jr nc,\0jr c,\0"; |
||
263 | //char zop[] = "add\0adc\0sub\0sbc\0and\0xor\0or\0\0cp"; lvd |
||
264 | char zop[] = "add a,\0\0adc a,\0\0sub \0\0\0\0sbc a,\0\0and \0\0\0\0xor \0\0\0\0or \0\0\0\0\0cp \0\0\0\0\0"; |
||
265 | char zf[] = "nz\0z\0\0nc\0c\0\0po\0pe\0p\0\0m"; |
||
266 | // ======================================================================= |
||
267 | |||
268 | void disasm_address(char *line, unsigned addr, char labels) |
||
269 | { |
||
270 | char *label = 0; |
||
271 | if (labels&&addr) label = mon_labels.find(am_r(addr)); |
||
272 | if (label) { |
||
273 | //strcpy(line, label); |
||
274 | int i; |
||
275 | for (i=0;(i<20)&&label[i];i++)line[i]=label[i]; |
||
276 | line[i]=label[i]; |
||
277 | } //Alone Coder 0.36.6 |
||
278 | else sprintf(line, "%04X", addr & 0xFFFF); |
||
279 | } |
||
280 | |||
281 | unsigned char *disasm(unsigned char *cmd, unsigned current, char labels) |
||
282 | { |
||
283 | unsigned char *st = cmd, z80p; |
||
284 | char *z80r16, *z80r8; |
||
285 | |||
286 | z80r16 = z80r16_1, z80r8 = z80r8_1, z80p = 0; |
||
287 | for (;;) { // z80 prefixes |
||
288 | if (*cmd == 0xDD) z80r16 = z80r16_2, z80r8 = z80r8_2, z80p = 0xDD; |
||
289 | else if (*cmd == 0xFD) z80r16 = z80r16_3, z80r8 = z80r8_3, z80p = 0xFD; |
||
290 | else break; |
||
291 | cmd++; |
||
292 | } |
||
293 | |||
294 | for (unsigned char *ptr = asm_tab_z80; *ptr; ) { |
||
295 | // cmd - start of command, c1 - mod/rm, cm - current pointer |
||
296 | unsigned char *rcmd = cmd; |
||
297 | if (*cmd == 0xED) rcmd++, z80r16 = z80r16_1, z80r8 = z80r8_1, z80p = 0; |
||
298 | unsigned char *cm = rcmd+1; |
||
299 | |||
300 | for (int j = 0; j < *ptr; j++) // match mask |
||
301 | if ((cmd[j] & ptr[j+*ptr+1]) != ptr[j+1]) goto nextcmd; |
||
302 | *asmbuf = 0; |
||
303 | unsigned char *pt; |
||
304 | for (pt = ptr + (2 * *ptr) + 1; *pt; pt++) { // scan all commands |
||
305 | char ln[/*32*/64]; |
||
306 | const char *l1 = ln; |
||
307 | ln[0] = 0; //Alone Coder 0.36.6 |
||
308 | switch (*pt) { |
||
309 | case _zr16: // in rcmd & 0x30 |
||
310 | l1 = z80r16+3*((*rcmd>>4) & 3); |
||
311 | break; |
||
312 | case _zr16a: // in rcmd & 0x30 |
||
313 | if (((*rcmd>>4)&3) == 3) l1 = "af"; |
||
314 | else l1 = z80r16+3*((*rcmd>>4) & 3); |
||
315 | break; |
||
316 | case _hl: // hl/ix/iy |
||
317 | l1 = z80r16+3*2; |
||
318 | break; |
||
319 | case _zjr: // relative jumps |
||
320 | l1 = zjr+7*((*rcmd>>3)&7); |
||
321 | break; |
||
322 | case _zop: // z80 operations at rcmd & 0x38 |
||
323 | //l1 = zop+4*((*rcmd>>3)&7); lvd |
||
324 | l1 = zop+8*((*rcmd>>3)&7); |
||
325 | break; |
||
326 | case _zf: // z80 flags at rcmd & 0x38 |
||
327 | l1 = zf+3*((*rcmd>>3)&7); |
||
328 | break; |
||
329 | case _cb: // all CB-opcodes |
||
330 | { |
||
331 | if (!z80p) { |
||
332 | sprintf(ln, "%s%s", cbtab+(*cm>>3)*7, z80r8_1+(*cm&7)*5); |
||
333 | cm++; |
||
334 | } else { |
||
335 | if ((cm[1] & 7) != 6 && ((cm[1] & 0xC0) != 0x40)) // operand is reg,(ix+nn) |
||
336 | sprintf(ln, "%s%s,(i%c%c%02X)", cbtab+(cm[1]>>3)*7, z80r8_1+(cm[1]&7)*5, z80p==0xDD ? 'x':'y', *(char*)cm>=0?'+':'-',abs(*(char*)cm)); |
||
337 | else // only (ix+nn) |
||
338 | sprintf(ln, "%s(i%c%c%02X)", cbtab+(cm[1]>>3)*7, z80p==0xDD ? 'x':'y', *(char*)cm>=0?'+':'-',abs(*(char*)cm)); |
||
339 | cm += 2; |
||
340 | } |
||
341 | break; |
||
342 | } |
||
343 | case _zr8: // in rcmd & 0x38 |
||
344 | if (z80p && ((*rcmd & 0x38) == 0x30)) { |
||
345 | sprintf(ln, "(i%c%c%02X)", z80p==0xDD ? 'x':'y', *(char*)cm>=0?'+':'-',abs(*(char*)cm)); |
||
346 | cm++; |
||
347 | } else l1 = z80r8+5*((*rcmd>>3) & 7); |
||
348 | break; |
||
349 | case _zr8_: // in rcmd & 0x38, in ld r8,r8 |
||
350 | if (!z80p || (*rcmd & 7)==6) { l1 = z80r8_1+5*((*rcmd>>3) & 7); break; } |
||
351 | if ((*rcmd & 0x38) == 0x30) { |
||
352 | sprintf(ln, "(i%c%c%02X)", z80p==0xDD ? 'x':'y', *(char*)cm>=0?'+':'-',abs(*(char*)cm)); |
||
353 | cm++; |
||
354 | } else l1 = z80r8+5*((*rcmd>>3) & 7); |
||
355 | break; |
||
356 | case _zr81: // in rcmd & 7 |
||
357 | if (z80p && (*rcmd & 7)==6) { |
||
358 | sprintf(ln, "(i%c%c%02X)", z80p==0xDD ? 'x':'y', *(char*)cm>=0?'+':'-',abs(*(char*)cm)); |
||
359 | cm++; |
||
360 | } else l1 = z80r8+5*(*rcmd & 7); |
||
361 | break; |
||
362 | case _zr81_: // in rcmd & 7, in ld r8,r8 |
||
363 | if (!z80p || ((*rcmd & 0x38) == 0x30)) { l1 = z80r8_1+5*(*rcmd & 7); break; } |
||
364 | if ((*rcmd & 7)==6) { |
||
365 | sprintf(ln, "(i%c%c%02X)", z80p==0xDD ? 'x':'y', *(char*)cm>=0?'+':'-',abs(*(char*)cm)); |
||
366 | cm++; |
||
367 | } else l1 = z80r8+5*(*rcmd & 7); |
||
368 | break; |
||
369 | case _ld: |
||
370 | l1 = "ld "; break; |
||
371 | case _shrt: // short jump |
||
372 | disasm_address(ln, current+cm-st + *(signed char*)cm + 1, labels); |
||
373 | cm++; |
||
374 | break; |
||
375 | case _ib: // immediate byte at cm |
||
376 | sprintf(ln, "%02X", *cm++); |
||
377 | break; |
||
378 | case _iw: // immediate word at cm |
||
379 | disasm_address(ln, *(unsigned short*)cm, labels); cm += 2; |
||
380 | break; |
||
381 | default: |
||
382 | *(short*)ln = *pt; |
||
383 | } |
||
384 | strcat(asmbuf, l1); |
||
385 | } |
||
386 | // make tabulation between instruction and operands |
||
387 | { |
||
388 | // if( !cpu.logena ) //LVD |
||
389 | { |
||
390 | char b1[0x40], *p = asmbuf, *q = b1; |
||
391 | while (*p != ' ' && *p) *q++ = *p++; |
||
392 | *q++ = *p; |
||
393 | if (*p) { |
||
394 | while (q < b1+5) *q++ = ' '; // +5 - tab size=5, was 4 |
||
395 | while (*++p) *q++ = *p; |
||
396 | } |
||
397 | *q = 0; |
||
398 | strcpy(asmbuf, b1); |
||
399 | } |
||
400 | return max(cm, cmd+*ptr); |
||
401 | } |
||
402 | nextcmd: |
||
403 | ptr += (2 * *ptr) + 1; while (*ptr++); // skip mask,code and instruction |
||
404 | } |
||
405 | strcpy(asmbuf, "???"); return cmd+1; |
||
406 | } |
||
407 | |||
408 | int getindex(unsigned char **ptr, char *table, unsigned width, int size) { |
||
409 | int max = 0, imax; // find max match - fdiv and fdivr must be found as fdivr |
||
410 | for (int i = 0; i < size; i++) { |
||
411 | int ln = strlen(table + i*width); |
||
412 | if (!strncmp((char*)*ptr, table + i*width, ln)) |
||
413 | if (ln > max) max = ln, imax = i; |
||
414 | } |
||
415 | if (max) { |
||
416 | (*ptr) += strlen(table + imax*width); |
||
417 | return imax; |
||
418 | } |
||
419 | return -1; |
||
420 | } |
||
421 | int scanhex(unsigned char **ptr) { |
||
422 | int r = 0, s = 1; |
||
423 | if (**ptr == '-') (*ptr)++, s = -1; |
||
424 | if (**ptr == '+') (*ptr)++; |
||
425 | while (isdigit(**ptr) || (**ptr >= 'a' && **ptr <= 'f')) |
||
426 | r = 16*r + hexdigit(**ptr), (*ptr)++; |
||
427 | return r*s; |
||
428 | } |
||
429 | unsigned char cmdb[16]; |
||
430 | unsigned char asmresult[24]; |
||
431 | unsigned char z80p; |
||
432 | unsigned char a_command[0x40]; |
||
433 | |||
434 | int z80scanr8(unsigned char **ptr, unsigned char **cm) { |
||
435 | int in = getindex(ptr, z80r8_1, 5, 8); |
||
436 | if (in >= 0) return in; |
||
437 | char *r8 = z80r8_1; |
||
438 | if (z80p == 0xDD) r8 = z80r8_2; |
||
439 | if (z80p == 0xFD) r8 = z80r8_3; |
||
440 | in = getindex(ptr, r8, 5, 8); |
||
441 | if (!z80p) return in; |
||
442 | if (*(unsigned short*)(*ptr) != WORD2('(','i')) return in; |
||
443 | (*ptr) += 3; |
||
444 | char c = *(*ptr - 1); |
||
445 | if ((z80p == 0xDD && c != 'x') || (z80p == 0xFD && c != 'y')) return -1; |
||
446 | int ofs = (**ptr == ')') ? 0 : scanhex(ptr); |
||
447 | if (ofs > 127 || ofs < -128) return -1; |
||
448 | if (*((*ptr)++) != ')') return -1; |
||
449 | *(signed char*)(*cm)++ = (signed char)ofs; |
||
450 | return 6; |
||
451 | } |
||
452 | |||
453 | int assemble(unsigned addr) |
||
454 | { |
||
455 | char *z80r16 = z80r16_1; |
||
456 | if (z80p == 0xDD) z80r16 = z80r16_2; |
||
457 | if (z80p == 0xFD) z80r16 = z80r16_3; |
||
458 | |||
459 | for (unsigned char *p1 = asm_tab_z80; *p1; ) { |
||
460 | memset(cmdb, 0, sizeof(cmdb)); |
||
461 | unsigned char *cc = a_command; memcpy(cmdb, p1+1, *p1); |
||
462 | unsigned char *cmd = cmdb; |
||
463 | unsigned char *rcmd = cmd; |
||
464 | unsigned char *cm; |
||
465 | if (*cmd == 0xED) { rcmd++; if (z80p) goto nextcmd; } |
||
466 | cm = rcmd+1; |
||
467 | |||
468 | int in; |
||
469 | unsigned char *ptr; //Alone Coder |
||
470 | for (/*unsigned char * */ptr = p1+2 * *p1+1; *ptr; ptr++) { |
||
471 | switch (*ptr) { |
||
472 | case _zr16: // in rcmd & 0x30 |
||
473 | if ((in = getindex(&cc, z80r16, 3, 4)) < 0) goto nextcmd; |
||
474 | *rcmd |= (in << 4); |
||
475 | break; |
||
476 | case _zr16a: // in rcmd & 0x30 |
||
477 | if (*(unsigned short*)cc == WORD2('a','f')) { |
||
478 | cc += 2; |
||
479 | in = 3; |
||
480 | } else { |
||
481 | if ((in = getindex(&cc, z80r16, 3, 4)) < 0) goto nextcmd; |
||
482 | } |
||
483 | *rcmd |= (in << 4); |
||
484 | break; |
||
485 | case _zjr: // relative jumps |
||
486 | if ((in = getindex(&cc, zjr, 7, 8)) < 0) goto nextcmd; |
||
487 | *rcmd |= (in << 3); |
||
488 | break; |
||
489 | case _zop: // z80 ops |
||
490 | if ((in = getindex(&cc, zop, 8, 8)) < 0) goto nextcmd; |
||
491 | *rcmd |= (in << 3); |
||
492 | break; |
||
493 | case _zf: // z80 flags |
||
494 | if ((in = getindex(&cc, zf, 3, 8)) < 0) goto nextcmd; |
||
495 | *rcmd |= (in << 3); |
||
496 | break; |
||
497 | case _hl: // hl/ix/iy |
||
498 | if ((in = getindex(&cc, z80r16, 3, 4)) != 2) goto nextcmd; |
||
499 | break; |
||
500 | case _cb: // all CB-opcodes |
||
501 | { |
||
502 | if ((in = getindex(&cc, cbtab, 7, 32)) < 0) goto nextcmd; |
||
503 | int in1 = getindex(&cc, z80r8_1, 5, 8); |
||
504 | if (!z80p) { |
||
505 | if (in1 < 0) goto nextcmd; |
||
506 | } else { |
||
507 | if (in1 < 0) { |
||
508 | in1 = z80scanr8(&cc, &cm); |
||
509 | if (in1 < 0) goto nextcmd; |
||
510 | } else { |
||
511 | if (*cc++ != ',' || z80scanr8(&cc, &cm) != 6) goto nextcmd; |
||
512 | } |
||
513 | } |
||
514 | *cm++ = in*8+in1; |
||
515 | break; |
||
516 | } |
||
517 | case _zr8: // r8 in *rcmd & 0x38 |
||
518 | case _zr8_: // r8 in *rcmd & 0x38, in ld r8,r8 |
||
519 | if ((in = z80scanr8(&cc, &cm)) < 0) goto nextcmd; |
||
520 | *rcmd |= in<<3; |
||
521 | break; |
||
522 | case _zr81: // r8 in *rcmd & 7 |
||
523 | case _zr81_: // r8 in *rcmd & 7, in ld r8,r8 |
||
524 | if ((in = z80scanr8(&cc, &cm)) < 0) goto nextcmd; |
||
525 | *rcmd |= in; |
||
526 | break; |
||
527 | case _ld: |
||
528 | if ((*(unsigned*)cc & 0xFFFFFF) != WORD4('l','d',' ',0)) goto nextcmd; |
||
529 | cc += 3; break; |
||
530 | case _shrt: // short jump |
||
531 | { |
||
532 | if (!ishex(*cc)) goto nextcmd; |
||
533 | in = scanhex(&cc); |
||
534 | int x = i16(in-(int)addr+cmdb-cm-1); |
||
535 | if (x > 0x7F || x < -0x80) goto nextcmd; |
||
536 | *(char*)cm = x; cm++; |
||
537 | break; |
||
538 | } |
||
539 | case _ib: // immediate byte at cm |
||
540 | if (*cc == '\'' && cc[2] == '\'') { in = cc[1]; cc+=3; goto imm; } |
||
541 | if (!ishex(*cc)) goto nextcmd; |
||
542 | in = scanhex(&cc); |
||
543 | if ((unsigned)in > 0xFF) goto nextcmd; |
||
544 | imm: |
||
545 | *(char*)cm++ = (char)in; |
||
546 | break; |
||
547 | case _iw: // immediate word at cm |
||
548 | if (!ishex(*cc)) goto nextcmd; |
||
549 | in = scanhex(&cc); |
||
550 | if ((unsigned)in > 0xFFFF) goto nextcmd; |
||
551 | *(unsigned short*)cm = (unsigned short)in; cm += 2; |
||
552 | break; |
||
553 | default: |
||
554 | if (*ptr != *cc++) goto nextcmd; |
||
555 | } |
||
556 | } |
||
557 | if (!*cc) return max(unsigned(cm-cmdb), unsigned(*p1)); |
||
558 | nextcmd: |
||
559 | p1 += (2 * *p1) + 1; while (*p1++); |
||
560 | } |
||
561 | return 0; |
||
562 | } |
||
563 | |||
564 | int assemble_cmd(unsigned char *cmd, unsigned addr) |
||
565 | { |
||
566 | unsigned char *res = a_command; |
||
567 | unsigned char bf[0x40]; strcpy((char*)bf, (char*)cmd); |
||
568 | for (res = bf; *res; res++) { // don't allow to kill space befor (# - place 0x01 |
||
569 | if (*(short*)res == WORD2(' ','(')) *(short*)res = WORD2(1,'('); |
||
570 | if (*(short*)res == WORD2(' ','#')) *(short*)res = WORD2(1,'#'); |
||
571 | } |
||
572 | res = a_command; cmd = bf; |
||
573 | while (*cmd == ' ') cmd++; |
||
574 | while (*cmd && *cmd != ' ') *res++ = tolower(*cmd++); |
||
575 | while (*cmd) { |
||
576 | while (*cmd == ' ' && (!isalnum(cmd[1]) || !isalnum(res[-1]))) cmd++; |
||
577 | *res++ = (cmd[-1] == '\'') ? *cmd : tolower(*cmd); |
||
578 | cmd++; |
||
579 | } |
||
580 | if (res[-1] == ' ') res[-1] = 0; |
||
581 | *res = 0; |
||
582 | // replace 0x01 to space again |
||
583 | for (res = a_command; *res; res++) if (!(*res-1)) *res = ' '; |
||
584 | |||
585 | unsigned r; |
||
586 | z80p = 0; if ((r = assemble(addr))) goto inspref1; |
||
587 | z80p = 0xDD; if ((r = assemble(addr))) goto inspref1; |
||
588 | z80p = 0xFD; if ((r = assemble(addr))) goto inspref1; |
||
589 | return 0; |
||
590 | inspref1: |
||
591 | unsigned char *p = asmresult; |
||
592 | if (z80p) *p++ = z80p; |
||
593 | for (unsigned i=0; i < r; i++) *p++ = cmdb[i]; |
||
594 | return r + (z80p ? 1 : 0); |
||
595 | } |