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