1 /* 2012 - pancake@nopcode.org - radare2 integration */
2 /* Z80 assembler by shevek
3
4 Copyright (C) 2002-2009 Bas Wijnen <wijnen@debian.org>
5 Copyright (C) 2005 Jan Wilmans <jw@dds.nl>
6
7 This file is part of z80asm.
8
9 Z80asm is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
13
14 Z80asm is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 #ifndef R_API_I
24 #define R_API_I
25 #endif
26 #include "z80asm.h"
27 #include <r_util.h>
28
29 /* hack */
30 // must remove: equ, include, incbin, macro
31 // static void wrt_ref (int val, int type, int count);
32 static unsigned char *obuf;
33 static int obuflen = 0;
34 #define write_one_byte(x, y) obuf[obuflen++] = x
35 #define wrtb(x) obuf[obuflen++] = x
36
37 /* global variables */
38 /* mnemonics, used as argument to indx() in assemble */
39 static const char *mnemonics[] = {
40 "call", "cpdr", "cpir", "djnz", "halt", "indr", "inir", "lddr", "ldir",
41 "otdr", "otir", "outd", "outi", "push", "reti", "retn", "rlca", "rrca",
42 "defb", "defw", "defs", "defm",
43 "adc", "add", "and", "bit", "ccf", "cpd", "cpi", "cpl", "daa", "dec", "equ",
44 "exx", "inc", "ind", "ini", "ldd", "ldi", "neg", "nop", "out", "pop",
45 "res", "ret", "rla", "rlc", "rld", "rra", "rrc", "rrd", "rst", "sbc",
46 "scf", "set", "sla", "sll", "sli", "sra", "srl", "sub", "xor", "org",
47 "cp", "di", "ei", "ex", "im", "in", "jp", "jr", "ld", "or", "rl", "rr",
48 "db", "dw", "ds", "dm",
49 "include", "incbin", "if", "else", "endif", "end", "macro", "endm",
50 "seek", NULL
51 };
52
53 /* current line, address and file */
54 static int addr = 0, file;
55 /* current number of characters in list file, for indentation */
56 // static int listdepth;
57
58 /* use readbyte instead of (hl) if writebyte is true */
59 static int writebyte;
60 static const char *readbyte;
61 /* variables which are filled by rd_* functions and used later,
62 * like readbyte */
63 static const char *readword, *indexjmp, *bitsetres;
64
65 /* 0, 0xdd or 0xfd depening on which index prefix should be given */
66 static int indexed;
67
68 /* increased for every -v option on the command line */
69 static int verbose = 0;
70
71 /* read commas after indx() if comma > 1. increase for every call */
72 static int comma;
73
74 /* address at start of line (for references) */
75 static int baseaddr;
76
77 /* set by readword and readbyte, used for new_reference */
78 static char mem_delimiter;
79
80 /* line currently being parsed */
81 static char *z80buffer = NULL;
82
83 /* if a macro is currently being defined */
84 static int define_macro = 0;
85
86 /* file (and macro) stack */
87 static int sp;
88 static struct stack stack[MAX_INCLUDE]; /* maximum level of includes */
89
90 /* hack */
91 #include "expressions.c"
92
93 /* print an error message, including current line and file */
printerr(int error,const char * fmt,...)94 static void printerr(int error, const char *fmt, ...) {
95 #if 0
96 va_list l;
97 va_start (l, fmt);
98 if ((sp < 0) || (stack[sp].name == 0)) {
99 fprintf (stderr, "internal assembler error, sp == %i\n", sp);
100 vfprintf (stderr, fmt, l);
101 }
102 fprintf (stderr, "%s%s:%d: %s: ", stack[sp].dir? stack[sp].dir->name: "",
103 stack[sp].name, stack[sp].line, error? "error": "warning");
104 vfprintf (stderr, fmt, l);
105 va_end (l);
106 if (error) {
107 errors++;
108 }
109 #endif
110 }
111
112 /* skip over spaces in string */
delspc(const char * ptr)113 static const char *delspc(const char *ptr) {
114 while (*ptr && isspace ((const unsigned char) *ptr))
115 ptr++;
116 if (*ptr == ';') {
117 ptr = "";
118 }
119 return ptr;
120 }
121
122 /* read away a comma, error if there is none */
rd_comma(const char ** p)123 static void rd_comma(const char **p) {
124 *p = delspc (*p);
125 if (**p != ',') {
126 eprintf ("`,' expected. Remainder of line: %s\n", *p);
127 return;
128 }
129 *p = delspc ((*p) + 1);
130 }
131
132 /* look ahead for a comma, no error if not found */
has_argument(const char ** p)133 static int has_argument(const char **p) {
134 const char *q = delspc (*p);
135 return *q == ',';
136 }
137
138 /* During assembly, many literals are not parsed. Instead, they are saved
139 * until all labels are read. After that, they are parsed. This function
140 * is used during assembly, to find the place where the command continues. */
skipword(const char ** pos,char delimiter)141 static void skipword(const char **pos, char delimiter) {
142 /* rd_expr will happily read the expression, and possibly return
143 * an invalid result. It will update pos, which is what we need. */
144 /* Pass valid to allow using undefined labels without errors. */
145 int valid;
146 rd_expr (pos, delimiter, &valid, sp, 0);
147 }
148
149 /* find any of the list[] entries as the start of ptr and return index */
indx(const char ** ptr,const char ** list,int error,const char ** expr)150 static int indx(const char **ptr, const char **list, int error, const char **expr) {
151 int i;
152 *ptr = delspc (*ptr);
153 if (!**ptr) {
154 if (error) {
155 eprintf ("unexpected end of line\n");
156 return 0;
157 } else {
158 return 0;
159 }
160 }
161 if (comma > 1) {
162 rd_comma (ptr);
163 }
164 for (i = 0; list[i]; i++) {
165 const char *input = *ptr;
166 const char *check = list[i];
167 int had_expr = 0;
168 if (!list[i][0]) {
169 continue;
170 }
171 while (*check) {
172 if (*check == ' ') {
173 input = delspc (input);
174 } else if (*check == '*') {
175 *expr = input;
176 mem_delimiter = check[1];
177 rd_expr (&input, mem_delimiter, NULL, sp, 0);
178 had_expr = 1;
179 } else if (*check == '+') {
180 if (*input == '+' || *input == '-') {
181 *expr = input;
182 mem_delimiter = check[1];
183 rd_expr (&input, mem_delimiter, NULL, sp, 0);
184 }
185 } else if (*check == *input || (*check >= 'a' && *check <= 'z'
186 && *check - 'a' + 'A' == *input)) {
187 ++input;
188 } else {
189 break;
190 }
191
192 ++check;
193 }
194 if (*check || (isalnum ((const unsigned char) check[-1]) && isalnum ((const unsigned char) input[0]))) {
195 continue;
196 }
197 if (had_expr) {
198 input = delspc (input);
199 if (*input && *input != ',') {
200 continue;
201 }
202 }
203 *ptr = input;
204 comma++;
205 return i + 1;
206 }
207 // if (error) eprintf ("parse error. Remainder of line=%s\n", *ptr);
208 return 0;
209 }
210
211 /* read a mnemonic */
readcommand(const char ** p)212 static int readcommand(const char **p) {
213 return indx (p, mnemonics, 0, NULL);
214 }
215
216 /* try to read a label and optionally store it in the list */
readlabel(const char ** p,int store)217 static void readlabel(const char **p, int store) {
218 const char *c, *d, *pos, *dummy;
219 int i, j;
220 struct label *previous;
221 for (d = *p; *d && *d != ';'; d++) {
222 ;
223 }
224 for (c = *p; !strchr (" \r\n\t", *c) && c < d; c++) {
225 ;
226 }
227 pos = strchr (*p, ':');
228 if (!pos || pos >= c) {
229 return;
230 }
231 if (pos == *p) {
232 eprintf ("`:' found without a label");
233 return;
234 }
235 if (!store) {
236 *p = pos + 1;
237 return;
238 }
239 c = pos + 1;
240 dummy = *p;
241 j = rd_label (&dummy, &i, &previous, sp, 0);
242 if (i || j) {
243 eprintf ("duplicate definition of label %s\n", *p);
244 *p = c;
245 return;
246 }
247
248 *p = c;
249 }
250
compute_ref(struct reference * ref,int allow_invalid)251 static int compute_ref(struct reference *ref, int allow_invalid) {
252 const char *ptr;
253 int valid = 0;
254 int backup_addr = addr;
255 int backup_baseaddr = baseaddr;
256 int backup_comma = comma;
257 int backup_file = file;
258 int backup_sp = sp;
259 sp = ref->level;
260 addr = ref->addr;
261 baseaddr = ref->baseaddr;
262 comma = ref->comma;
263 file = ref->infile;
264 ptr = ref->input;
265 if (!ref->done) {
266 ref->computed_value = rd_expr (&ptr, ref->delimiter,
267 allow_invalid? &valid: NULL,
268 ref->level, 1);
269 if (valid) {
270 ref->done = 1;
271 }
272 }
273 sp = backup_sp;
274 addr = backup_addr;
275 baseaddr = backup_baseaddr;
276 comma = backup_comma;
277 file = backup_file;
278 return ref->computed_value;
279 }
280
281 /* read a word from input and store it in readword. return 1 on success */
rd_word(const char ** p,char delimiter)282 static int rd_word(const char **p, char delimiter) {
283 *p = delspc (*p);
284 if (**p == 0) {
285 return 0;
286 }
287 readword = *p;
288 mem_delimiter = delimiter;
289 skipword (p, delimiter);
290 return 1;
291 }
292
293 /* read a byte from input and store it in readbyte. return 1 on success */
rd_byte(const char ** p,char delimiter)294 static int rd_byte(const char **p, char delimiter) {
295 *p = delspc (*p);
296 if (**p == 0) {
297 return 0;
298 }
299 readbyte = *p;
300 writebyte = 1;
301 mem_delimiter = delimiter;
302 skipword (p, delimiter);
303 return 1;
304 }
305
306 /* read (SP), DE, or AF */
rd_ex1(const char ** p)307 static int rd_ex1(const char **p) {
308 #define DE 2
309 #define AF 3
310 const char *list[] = {
311 "( sp )", "de", "af", NULL
312 };
313 return indx (p, list, 1, NULL);
314 }
315
316 /* read first argument of IN */
rd_in(const char ** p)317 static int rd_in(const char **p) {
318 #define A 8
319 const char *list[] = {
320 "b", "c", "d", "e", "h", "l", "f", "a", NULL
321 };
322 return indx (p, list, 1, NULL);
323 }
324
325 /* read second argument of out (c),x */
rd_out(const char ** p)326 static int rd_out(const char **p) {
327 const char *list[] = {
328 "b", "c", "d", "e", "h", "l", "0", "a", NULL
329 };
330 return indx (p, list, 1, NULL);
331 }
332
333 /* read (c) or (nn) */
rd_nnc(const char ** p)334 static int rd_nnc(const char **p) {
335 #define C 1
336 int i;
337 const char *list[] = {
338 "( c )", "(*)", "a , (*)", NULL
339 };
340 i = indx (p, list, 1, &readbyte);
341 if (i < 2) {
342 return i;
343 }
344 return 2;
345 }
346
347 /* read (C) */
rd_c(const char ** p)348 static int rd_c(const char **p) {
349 const char *list[] = {
350 "( c )", "( bc )", NULL
351 };
352 return indx (p, list, 1, NULL);
353 }
354
355 /* read a or hl */
rd_a_hl(const char ** p)356 static int rd_a_hl(const char **p) {
357 #define HL 2
358 const char *list[] = {
359 "a", "hl", NULL
360 };
361 return indx (p, list, 1, NULL);
362 }
363
364 /* read first argument of ld */
rd_ld(const char ** p)365 static int rd_ld(const char **p) {
366 #define ldBC 1
367 #define ldDE 2
368 #define ldHL 3
369 #define ldSP 4
370 #define ldIX 5
371 #define ldIY 6
372 #define ldB 7
373 #define ldC 8
374 #define ldD 9
375 #define ldE 10
376 #define ldH 11
377 #define ldL 12
378 #define ld_HL 13
379 #define ldA 14
380 #define ldI 15
381 #define ldR 16
382 #define ld_BC 17
383 #define ld_DE 18
384 #define ld_IX 19
385 #define ld_IY 20
386 #define ld_NN 21
387 int i;
388 const char *list[] = {
389 "ixh", "ixl", "iyh", "iyl", "bc", "de", "hl", "sp", "ix",
390 "iy", "b", "c", "d", "e", "h", "l", "( hl )", "a", "i",
391 "r", "( bc )", "( de )", "( ix +)", "(iy +)", "(*)", NULL
392 };
393 const char *nn;
394 i = indx (p, list, 1, &nn);
395 if (!i) {
396 return 0;
397 }
398 if (i <= 2) {
399 indexed = 0xdd;
400 return ldH + (i == 2);
401 }
402 if (i <= 4) {
403 indexed = 0xfd;
404 return ldH + (i == 4);
405 }
406 i -= 4;
407 if (i == ldIX || i == ldIY) {
408 indexed = i == ldIX? 0xDD: 0xFD;
409 return ldHL;
410 }
411 if (i == ld_IX || i == ld_IY) {
412 indexjmp = nn;
413 indexed = i == ld_IX? 0xDD: 0xFD;
414 return ld_HL;
415 }
416 if (i == ld_NN) {
417 readword = nn;
418 }
419 return i;
420 }
421
422 /* read first argument of JP */
rd_jp(const char ** p)423 static int rd_jp(const char **p) {
424 int i;
425 const char *list[] = {
426 "nz", "z", "nc", "c", "po", "pe", "p", "m", "( ix )", "( iy )",
427 "(hl)", NULL
428 };
429 i = indx (p, list, 0, NULL);
430 if (i < 9) {
431 return i;
432 }
433 if (i == 11) {
434 return -1;
435 }
436 indexed = 0xDD + 0x20 * (i - 9);
437 return -1;
438 }
439
440 /* read first argument of JR */
rd_jr(const char ** p)441 static int rd_jr(const char **p) {
442 const char *list[] = {
443 "nz", "z", "nc", "c", NULL
444 };
445 return indx (p, list, 0, NULL);
446 }
447
448 /* read A */
rd_a(const char ** p)449 static int rd_a(const char **p) {
450 const char *list[] = {
451 "a", NULL
452 };
453 return indx (p, list, 1, NULL);
454 }
455
456 /* read bc,de,hl,af */
rd_stack(const char ** p)457 static int rd_stack(const char **p) {
458 int i;
459 const char *list[] = {
460 "bc", "de", "hl", "af", "ix", "iy", NULL
461 };
462 i = indx (p, list, 1, NULL);
463 if (i < 5) {
464 return i;
465 }
466 indexed = 0xDD + 0x20 * (i - 5);
467 return 3;
468 }
469
470 /* read b,c,d,e,h,l,(hl),a,(ix+nn),(iy+nn),nn
471 * but now with extra hl or i[xy](15) for add-instruction
472 * and set variables accordingly */
rd_r_add(const char ** p)473 static int rd_r_add(const char **p) {
474 #define addHL 15
475 int i;
476 const char *list[] = {
477 "ixl", "ixh", "iyl", "iyh", "b", "c", "d", "e", "h", "l",
478 "( hl )", "a", "( ix +)", "( iy +)", "hl", "ix", "iy", "*", NULL
479 };
480 const char *nn;
481 i = indx (p, list, 0, &nn);
482 if (i == 18) { /* expression */
483 readbyte = nn;
484 writebyte = 1;
485 return 7;
486 }
487 if (i > 14) { /* hl, ix, iy */
488 if (i > 15) {
489 indexed = 0xDD + 0x20 * (i - 16);
490 }
491 return addHL;
492 }
493 if (i <= 4) { /* i[xy][hl] */
494 indexed = 0xdd + 0x20 * (i > 2);
495 return 6 - (i & 1);
496 }
497 i -= 4;
498 if (i < 9) {
499 return i;
500 }
501 indexed = 0xDD + 0x20 * (i - 9); /* (i[xy] +) */
502 indexjmp = nn;
503 return 7;
504 }
505
506 /* read bc,de,hl, or sp */
rd_rr_(const char ** p)507 static int rd_rr_(const char **p) {
508 const char *list[] = {
509 "bc", "de", "hl", "sp", NULL
510 };
511 return indx (p, list, 1, NULL);
512 }
513
514 /* read bc,de,hl|ix|iy,sp. hl|ix|iy only if it is already indexed the same. */
rd_rrxx(const char ** p)515 static int rd_rrxx(const char **p) {
516 const char *listx[] = {
517 "bc", "de", "ix", "sp", NULL
518 };
519 const char *listy[] = {
520 "bc", "de", "iy", "sp", NULL
521 };
522 const char *list[] = {
523 "bc", "de", "hl", "sp", NULL
524 };
525 if (indexed == 0xdd) {
526 return indx (p, listx, 1, NULL);
527 }
528 if (indexed == 0xfd) {
529 return indx (p, listy, 1, NULL);
530 }
531 return indx (p, list, 1, NULL);
532 }
533
534 /* read b,c,d,e,h,l,(hl),a,(ix+nn),(iy+nn),nn
535 * and set variables accordingly */
rd_r(const char ** p)536 static int rd_r(const char **p) {
537 int i;
538 const char *nn;
539 const char *list[] = {
540 "ixl", "ixh", "iyl", "iyh", "b", "c", "d", "e", "h", "l", "( hl )",
541 "a", "( ix +)", "( iy +)", "*", NULL
542 };
543 i = indx (p, list, 0, &nn);
544 if (i == 15) { /* expression */
545 readbyte = nn;
546 writebyte = 1;
547 return 7;
548 }
549 if (i <= 4) {
550 indexed = 0xdd + 0x20 * (i > 2);
551 return 6 - (i & 1);
552 }
553 i -= 4;
554 if (i < 9) {
555 return i;
556 }
557 indexed = 0xDD + 0x20 * (i - 9);
558 indexjmp = nn;
559 return 7;
560 }
561
562 /* like rd_r(), but without nn */
rd_r_(const char ** p)563 static int rd_r_(const char **p) {
564 int i;
565 const char *list[] = {
566 "b", "c", "d", "e", "h", "l", "( hl )", "a", "( ix +)", "( iy +)", NULL
567 };
568 i = indx (p, list, 1, &indexjmp);
569 if (i < 9) {
570 return i;
571 }
572 indexed = 0xDD + 0x20 * (i - 9);
573 return 7;
574 }
575
576 /* read a number from 0 to 7, for bit, set or res */
rd_0_7(const char ** p)577 static int rd_0_7(const char **p) {
578 *p = delspc (*p);
579 if (**p == 0) {
580 return 0;
581 }
582 bitsetres = *p;
583 skipword (p, ',');
584 return 1;
585 }
586
587 /* read long condition. do not error if not found. */
rd_cc(const char ** p)588 static int rd_cc(const char **p) {
589 const char *list[] = {
590 "nz", "z", "nc", "c", "po", "pe", "p", "m", NULL
591 };
592 return indx (p, list, 0, NULL);
593 }
594
595 /* read long or short register, */
rd_r_rr(const char ** p)596 static int rd_r_rr(const char **p) {
597 int i;
598 const char *list[] = {
599 "iy", "ix", "sp", "hl", "de", "bc", "", "b", "c", "d", "e", "h",
600 "l", "( hl )", "a", "( ix +)", "( iy +)", NULL
601 };
602 i = indx (p, list, 1, &indexjmp);
603 if (!i) {
604 return 0;
605 }
606 if (i < 16 && i > 2) {
607 return 7 - i;
608 }
609 if (i > 15) {
610 indexed = 0xDD + (i - 16) * 0x20;
611 return -7;
612 }
613 indexed = 0xDD + (2 - i) * 0x20;
614 return 3;
615 }
616
617 /* read hl */
rd_hl(const char ** p)618 static int rd_hl(const char **p) {
619 const char *list[] = {
620 "hl", NULL
621 };
622 return indx (p, list, 1, NULL);
623 }
624
625 /* read hl, ix, or iy */
rd_hlx(const char ** p)626 static int rd_hlx(const char **p) {
627 int i;
628 const char *list[] = {
629 "hl", "ix", "iy", NULL
630 };
631 i = indx (p, list, 1, NULL);
632 if (i < 2) {
633 return i;
634 }
635 indexed = 0xDD + 0x20 * (i - 2);
636 return 1;
637 }
638
639 /* read af' */
rd_af_(const char ** p)640 static int rd_af_(const char **p) {
641 const char *list[] = {
642 "af'", NULL
643 };
644 return indx (p, list, 1, NULL);
645 }
646
647 /* read 0(1), 1(3), or 2(4) */
rd_0_2(const char ** p)648 static int rd_0_2(const char **p) {
649 const char *list[] = {
650 "0", "", "1", "2", NULL
651 };
652 return indx (p, list, 1, NULL);
653 }
654
655 /* read argument of ld (hl), */
rd_ld_hl(const char ** p)656 static int rd_ld_hl(const char **p) {
657 int i;
658 const char *list[] = {
659 "b", "c", "d", "e", "h", "l", "", "a", "*", NULL
660 };
661 i = indx (p, list, 0, &readbyte);
662 if (i < 9) {
663 return i;
664 }
665 writebyte = 1;
666 return 7;
667 }
668
669 /* read argument of ld (nnnn), */
rd_ld_nn(const char ** p)670 static int rd_ld_nn(const char **p) {
671 #define ld_nnHL 5
672 #define ld_nnA 6
673 int i;
674 const char *list[] = {
675 "bc", "de", "", "sp", "hl", "a", "ix", "iy", NULL
676 };
677 i = indx (p, list, 1, NULL);
678 if (i < 7) {
679 return i;
680 }
681 indexed = 0xdd + 0x20 * (i == 8);
682 return ld_nnHL;
683 }
684
685 /* read argument of ld a, */
rd_lda(const char ** p)686 static int rd_lda(const char **p) {
687 #define A_N 7
688 #define A_I 9
689 #define A_R 10
690 #define A_NN 11
691 int i;
692 const char *list[] = {
693 "( sp )", "( iy +)", "( de )", "( bc )", "( ix +)", "b", "c", "d", "e", "h",
694 "l", "( hl )", "a", "i", "r", "(*)", "*", NULL
695 };
696 const char *nn;
697 i = indx (p, list, 0, &nn);
698 if (i == 2 || i == 5) {
699 indexed = (i == 2)? 0xFD: 0xDD;
700 indexjmp = nn;
701 return 7;
702 }
703 if (i == 17) {
704 readbyte = nn;
705 writebyte = 1;
706 return 7;
707 }
708 if (i == 16) {
709 readword = nn;
710 }
711 return i - 5;
712 }
713
714 /* read argument of ld b|c|d|e|h|l */
rd_ldbcdehla(const char ** p)715 static int rd_ldbcdehla(const char **p) {
716 int i;
717 const char *list[] = {
718 "b", "c", "d", "e", "h", "l", "( hl )", "a", "( ix +)", "( iy +)", "ixh",
719 "ixl", "iyh", "iyl", "*", NULL
720 };
721 const char *nn;
722 i = indx (p, list, 0, &nn);
723 if (i == 15) {
724 readbyte = nn;
725 writebyte = 1;
726 return 7;
727 }
728 if (i > 10) {
729 int x;
730 x = 0xdd + 0x20 * (i > 12);
731 if (indexed && indexed != x) {
732 eprintf ("illegal use of index registers\n");
733 return 0;
734 }
735 indexed = x;
736 return 6 - (i & 1);
737 }
738 if (i > 8) {
739 if (indexed) {
740 eprintf ("illegal use of index registers\n");
741 return 0;
742 }
743 indexed = 0xDD + 0x20 * (i == 10);
744 indexjmp = nn;
745 return 7;
746 }
747 return i;
748 }
749
750 /* read nnnn, or (nnnn) */
rd_nn_nn(const char ** p)751 static int rd_nn_nn(const char **p) {
752 #define _NN 1
753 const char *list[] = {
754 "(*)", "*", NULL
755 };
756 return 2 - indx (p, list, 0, &readword);
757 }
758
759 /* read {HL|IX|IY},nnnn, or (nnnn) */
rd_sp(const char ** p)760 static int rd_sp(const char **p) {
761 #define SPNN 0
762 #define SPHL 1
763 int i;
764 const char *list[] = {
765 "hl", "ix", "iy", "(*)", "*", NULL
766 };
767 const char *nn;
768 i = indx (p, list, 0, &nn);
769 if (i > 3) {
770 readword = nn;
771 return i == 4? 2: 0;
772 }
773 if (i != 1) {
774 indexed = 0xDD + 0x20 * (i - 2);
775 }
776 return 1;
777 }
778
779 /* do the actual work */
assemble(const char * str,unsigned char * _obuf)780 static int assemble(const char *str, unsigned char *_obuf) {
781 const char *ptr;
782 char *bufptr;
783 int r, s; /* registers */
784
785 obuflen = 0;
786 obuf = _obuf;
787 int cmd, cont = 1;
788 // XXX: must free
789 z80buffer = strdup (str);
790 if (!cont) {
791 return obuflen;
792 }
793 // if (havelist)
794 // fprintf (listfile, "%04x", addr);
795 for (bufptr = z80buffer; (bufptr = strchr (bufptr, '\n'));) {
796 *bufptr = ' ';
797 }
798 for (bufptr = z80buffer; (bufptr = strchr (bufptr, '\r'));) {
799 *bufptr = ' ';
800 }
801 ptr = z80buffer;
802 // lastlabel = NULL;
803 baseaddr = addr;
804 ++stack[sp].line;
805 ptr = delspc (ptr);
806 if (!*ptr) {
807 return obuflen;
808 }
809 if (!define_macro) {
810 readlabel (&ptr, 1);
811 } else {
812 readlabel (&ptr, 0);
813 }
814 ptr = delspc (ptr);
815 if (!*ptr) {
816 return obuflen;
817 }
818 comma = 0;
819 indexed = 0;
820 indexjmp = 0;
821 writebyte = 0;
822 readbyte = 0;
823 readword = 0;
824 cmd = readcommand (&ptr) - 1;
825 int i, have_quote;
826 switch (cmd) {
827 case Z80_ADC:
828 if (!(r = rd_a_hl (&ptr))) {
829 break;
830 }
831 if (r == HL) {
832 if (!(r = rd_rr_(&ptr))) {
833 break;
834 }
835 wrtb (0xED);
836 r--;
837 wrtb (0x4A + 0x10 * r);
838 break;
839 }
840 if (!(r = rd_r (&ptr))) {
841 break;
842 }
843 r--;
844 wrtb (0x88 + r);
845 break;
846 case Z80_ADD:
847 if (!(r = rd_r_add (&ptr))) {
848 break;
849 }
850 if (r == addHL) {
851 if (!(r = rd_rrxx (&ptr))) {
852 break;
853 }
854 r--;
855 wrtb (0x09 + 0x10 * r); /* ADD HL/IX/IY, qq */
856 break;
857 }
858 if (has_argument (&ptr)) {
859 if (r != A) {
860 eprintf ("parse error before: %s\n", ptr);
861 break;
862 }
863 if (!(r = rd_r (&ptr))) {
864 break;
865 }
866 r--;
867 wrtb (0x80 + r); /* ADD A,r */
868 break;
869 }
870 r--;
871 wrtb (0x80 + r); /* ADD r */
872 break;
873 case Z80_AND:
874 if (!(r = rd_r (&ptr))) {
875 break;
876 }
877 r--;
878 wrtb (0xA0 + r);
879 break;
880 case Z80_BIT:
881 if (!rd_0_7 (&ptr)) {
882 break;
883 }
884 rd_comma (&ptr);
885 if (!(r = rd_r_(&ptr))) {
886 break;
887 }
888 wrtb (0xCB);
889 wrtb (0x40 + (r - 1));
890 break;
891 case Z80_CALL:
892 if ((r = rd_cc (&ptr))) {
893 r--;
894 wrtb (0xC4 + 8 * r);
895 rd_comma (&ptr);
896 } else {
897 wrtb (0xCD);
898 }
899 break;
900 case Z80_CCF:
901 wrtb (0x3F);
902 break;
903 case Z80_CP:
904 if (!(r = rd_r (&ptr))) {
905 break;
906 }
907 r--;
908 wrtb (0xB8 + r);
909 break;
910 case Z80_CPD:
911 wrtb (0xED);
912 wrtb (0xA9);
913 break;
914 case Z80_CPDR:
915 wrtb (0xED);
916 wrtb (0xB9);
917 break;
918 case Z80_CPI:
919 wrtb (0xED);
920 wrtb (0xA1);
921 break;
922 case Z80_CPIR:
923 wrtb (0xED);
924 wrtb (0xB1);
925 break;
926 case Z80_CPL:
927 wrtb (0x2F);
928 break;
929 case Z80_DAA:
930 wrtb (0x27);
931 break;
932 case Z80_DEC:
933 if (!(r = rd_r_rr (&ptr))) {
934 break;
935 }
936 if (r < 0) {
937 r--;
938 wrtb (0x05 - 8 * r);
939 break;
940 }
941 r--;
942 wrtb (0x0B + 0x10 * r);
943 break;
944 case Z80_DI:
945 wrtb (0xF3);
946 break;
947 case Z80_DJNZ:
948 wrtb (0x10);
949 // rd_wrt_jr (&ptr, '\0');
950 break;
951 case Z80_EI:
952 wrtb (0xFB);
953 break;
954 case Z80_EX:
955 if (!(r = rd_ex1 (&ptr))) {
956 break;
957 }
958 switch (r) {
959 case DE:
960 if (!rd_hl (&ptr)) {
961 break;
962 }
963 wrtb (0xEB);
964 break;
965 case AF:
966 if (!rd_af_(&ptr)) {
967 break;
968 }
969 wrtb (0x08);
970 break;
971 default:
972 if (!rd_hlx (&ptr)) {
973 break;
974 }
975 wrtb (0xE3);
976 }
977 break;
978 case Z80_EXX:
979 wrtb (0xD9);
980 break;
981 case Z80_HALT:
982 wrtb (0x76);
983 break;
984 case Z80_IM:
985 if (!(r = rd_0_2 (&ptr))) {
986 break;
987 }
988 wrtb (0xED);
989 r--;
990 wrtb (0x46 + 8 * r);
991 break;
992 case Z80_IN:
993 if (!(r = rd_in (&ptr))) {
994 break;
995 }
996 if (r == A) {
997 if (!(r = rd_nnc (&ptr))) {
998 break;
999 }
1000 if (r == C) {
1001 wrtb (0xED);
1002 wrtb (0x40 + 8 * (A - 1));
1003 break;
1004 }
1005 wrtb (0xDB);
1006 break;
1007 }
1008 if (!rd_c (&ptr)) {
1009 break;
1010 }
1011 wrtb (0xED);
1012 r--;
1013 wrtb (0x40 + 8 * r);
1014 break;
1015 case Z80_INC:
1016 if (!(r = rd_r_rr (&ptr))) {
1017 break;
1018 }
1019 if (r < 0) {
1020 r++;
1021 wrtb (0x04 - 8 * r);
1022 break;
1023 }
1024 r--;
1025 wrtb (0x03 + 0x10 * r);
1026 break;
1027 case Z80_IND:
1028 wrtb (0xED);
1029 wrtb (0xAA);
1030 break;
1031 case Z80_INDR:
1032 wrtb (0xED);
1033 wrtb (0xBA);
1034 break;
1035 case Z80_INI:
1036 wrtb (0xED);
1037 wrtb (0xA2);
1038 break;
1039 case Z80_INIR:
1040 wrtb (0xED);
1041 wrtb (0xB2);
1042 break;
1043 case Z80_JP:
1044 r = rd_jp (&ptr);
1045 if (r < 0) {
1046 wrtb (0xE9);
1047 break;
1048 }
1049 if (r) {
1050 r--;
1051 wrtb (0xC2 + 8 * r);
1052 rd_comma (&ptr);
1053 } else {
1054 wrtb (0xC3);
1055 }
1056 break;
1057 case Z80_JR:
1058 r = rd_jr (&ptr);
1059 if (r) {
1060 rd_comma (&ptr);
1061 }
1062 wrtb (0x18 + 8 * r);
1063 break;
1064 case Z80_LD:
1065 if (!(r = rd_ld (&ptr))) {
1066 break;
1067 }
1068 switch (r) {
1069 case ld_BC:
1070 case ld_DE:
1071 if (!rd_a (&ptr)) {
1072 break;
1073 }
1074 wrtb (0x02 + 0x10 * (r == ld_DE ? 1 : 0));
1075 break;
1076 case ld_HL:
1077 r = rd_ld_hl (&ptr) - 1;
1078 wrtb (0x70 + r);
1079 break;
1080 case ld_NN:
1081 if (!(r = rd_ld_nn (&ptr))) {
1082 break;
1083 }
1084 if (r == ld_nnA || r == ld_nnHL) {
1085 wrtb (0x22 + 0x10 * (r == ld_nnA ? 1 : 0));
1086 break;
1087 }
1088 wrtb (0xED);
1089 wrtb (0x43 + 0x10 * --r);
1090 break;
1091 case ldA:
1092 if (!(r = rd_lda (&ptr))) {
1093 break;
1094 }
1095 if (r == A_NN) {
1096 wrtb (0x3A);
1097 break;
1098 }
1099 if (r == A_I || r == A_R) {
1100 wrtb (0xED);
1101 wrtb (0x57 + 8 * (r == A_R ? 1 : 0));
1102 break;
1103 }
1104 if (r == A_N) {
1105 char n = r_num_math (NULL, readbyte);
1106 wrtb (0x3E);
1107 wrtb (n);
1108 break;
1109 }
1110 if (r < 0) {
1111 r++;
1112 wrtb (0x0A - 0x10 * r);
1113 break;
1114 }
1115 wrtb (0x78 + --r);
1116 break;
1117 case ldB:
1118 case ldC:
1119 case ldD:
1120 case ldE:
1121 case ldH:
1122 case ldL:
1123 if (!(s = rd_ldbcdehla (&ptr))) {
1124 break;
1125 }
1126 if (s == 7) {
1127 char n = r_num_math (NULL, readbyte);
1128 wrtb (0x08 * (r - 7) + 0x6);
1129 wrtb (n);
1130 } else {
1131 wrtb (0x40 + 0x08 * (r -7) + (s - 1));
1132 }
1133 break;
1134 case ldBC:
1135 case ldDE:
1136 s = rd_nn_nn (&ptr);
1137 if (s == _NN) {
1138 wrtb (0xED);
1139 wrtb (0x4B + 0x10 * (r == ldDE ? 1 : 0));
1140 break;
1141 }
1142 wrtb (0x01 + (r == ldDE ? 1 : 0) * 0x10);
1143 break;
1144 case ldHL:
1145 r = rd_nn_nn (&ptr);
1146 wrtb (0x21 + (r == _NN ? 1 : 0) * 9);
1147 break;
1148 case ldI:
1149 case ldR:
1150 if (!rd_a (&ptr)) {
1151 break;
1152 }
1153 wrtb (0xED);
1154 wrtb (0x47 + 0x08 * (r == ldR ? 1 : 0));
1155 break;
1156 case ldSP:
1157 r = rd_sp (&ptr);
1158 if (r == SPHL) {
1159 wrtb (0xF9);
1160 break;
1161 }
1162 if (r == SPNN) {
1163 wrtb (0x31);
1164 break;
1165 }
1166 wrtb (0xED);
1167 wrtb (0x7B);
1168 break;
1169 }
1170 break;
1171 case Z80_LDD:
1172 wrtb (0xED);
1173 wrtb (0xA8);
1174 break;
1175 case Z80_LDDR:
1176 wrtb (0xED);
1177 wrtb (0xB8);
1178 break;
1179 case Z80_LDI:
1180 wrtb (0xED);
1181 wrtb (0xA0);
1182 break;
1183 case Z80_LDIR:
1184 wrtb (0xED);
1185 wrtb (0xB0);
1186 break;
1187 case Z80_NEG:
1188 wrtb (0xED);
1189 wrtb (0x44);
1190 break;
1191 case Z80_NOP:
1192 wrtb (0x00);
1193 break;
1194 case Z80_OR:
1195 if (!(r = rd_r (&ptr))) {
1196 break;
1197 }
1198 r--;
1199 wrtb (0xB0 + r);
1200 break;
1201 case Z80_OTDR:
1202 wrtb (0xED);
1203 wrtb (0xBB);
1204 break;
1205 case Z80_OTIR:
1206 wrtb (0xED);
1207 wrtb (0xB3);
1208 break;
1209 case Z80_OUT:
1210 if (!(r = rd_nnc (&ptr))) {
1211 break;
1212 }
1213 if (r == C) {
1214 if (!(r = rd_out (&ptr))) {
1215 break;
1216 }
1217 wrtb (0xED);
1218 r--;
1219 wrtb (0x41 + 8 * r);
1220 break;
1221 }
1222 if (!rd_a (&ptr)) {
1223 break;
1224 }
1225 wrtb (0xD3);
1226 break;
1227 case Z80_OUTD:
1228 wrtb (0xED);
1229 wrtb (0xAB);
1230 break;
1231 case Z80_OUTI:
1232 wrtb (0xED);
1233 wrtb (0xA3);
1234 break;
1235 case Z80_POP:
1236 if (!(r = rd_stack (&ptr))) {
1237 break;
1238 }
1239 r--;
1240 wrtb (0xC1 + 0x10 * r);
1241 break;
1242 case Z80_PUSH:
1243 if (!(r = rd_stack (&ptr))) {
1244 break;
1245 }
1246 r--;
1247 wrtb (0xC5 + 0x10 * r);
1248 break;
1249 case Z80_RES:
1250 if (!rd_0_7 (&ptr)) {
1251 break;
1252 }
1253 rd_comma (&ptr);
1254 if (!(r = rd_r_(&ptr))) {
1255 break;
1256 }
1257 wrtb (0xCB);
1258 r--;
1259 wrtb (0x80 + r);
1260 break;
1261 case Z80_RET:
1262 if (!(r = rd_cc (&ptr))) {
1263 wrtb (0xC9);
1264 break;
1265 }
1266 r--;
1267 wrtb (0xC0 + 8 * r);
1268 break;
1269 case Z80_RETI:
1270 wrtb (0xED);
1271 wrtb (0x4D);
1272 break;
1273 case Z80_RETN:
1274 wrtb (0xED);
1275 wrtb (0x45);
1276 break;
1277 case Z80_RL:
1278 if (!(r = rd_r_(&ptr))) {
1279 break;
1280 }
1281 wrtb (0xCB);
1282 r--;
1283 wrtb (0x10 + r);
1284 break;
1285 case Z80_RLA:
1286 wrtb (0x17);
1287 break;
1288 case Z80_RLC:
1289 if (!(r = rd_r_(&ptr))) {
1290 break;
1291 }
1292 wrtb (0xCB);
1293 r--;
1294 wrtb (0x00 + r);
1295 break;
1296 case Z80_RLCA:
1297 wrtb (0x07);
1298 break;
1299 case Z80_RLD:
1300 wrtb (0xED);
1301 wrtb (0x6F);
1302 break;
1303 case Z80_RR:
1304 if (!(r = rd_r_(&ptr))) {
1305 break;
1306 }
1307 wrtb (0xCB);
1308 r--;
1309 wrtb (0x18 + r);
1310 break;
1311 case Z80_RRA:
1312 wrtb (0x1F);
1313 break;
1314 case Z80_RRC:
1315 if (!(r = rd_r_(&ptr))) {
1316 break;
1317 }
1318 wrtb (0xCB);
1319 r--;
1320 wrtb (0x08 + r);
1321 break;
1322 case Z80_RRCA:
1323 wrtb (0x0F);
1324 break;
1325 case Z80_RRD:
1326 wrtb (0xED);
1327 wrtb (0x67);
1328 break;
1329 case Z80_RST:
1330 ptr = "";
1331 break;
1332 case Z80_SBC:
1333 if (!(r = rd_a_hl (&ptr))) {
1334 break;
1335 }
1336 if (r == HL) {
1337 if (!(r = rd_rr_(&ptr))) {
1338 break;
1339 }
1340 wrtb (0xED);
1341 r--;
1342 wrtb (0x42 + 0x10 * r);
1343 break;
1344 }
1345 if (!(r = rd_r (&ptr))) {
1346 break;
1347 }
1348 r--;
1349 wrtb (0x98 + r);
1350 break;
1351 case Z80_SCF:
1352 wrtb (0x37);
1353 break;
1354 case Z80_SET:
1355 if (!rd_0_7 (&ptr)) {
1356 break;
1357 }
1358 rd_comma (&ptr);
1359 if (!(r = rd_r_(&ptr))) {
1360 break;
1361 }
1362 wrtb (0xCB);
1363 r--;
1364 wrtb (0xC0 + r);
1365 break;
1366 case Z80_SLA:
1367 if (!(r = rd_r_(&ptr))) {
1368 break;
1369 }
1370 wrtb (0xCB);
1371 r--;
1372 wrtb (0x20 + r);
1373 break;
1374 case Z80_SLI:
1375 if (!(r = rd_r_(&ptr))) {
1376 break;
1377 }
1378 wrtb (0xCB);
1379 r--;
1380 wrtb (0x30 + r);
1381 break;
1382 case Z80_SRA:
1383 if (!(r = rd_r_(&ptr))) {
1384 break;
1385 }
1386 wrtb (0xCB);
1387 r--;
1388 wrtb (0x28 + r);
1389 break;
1390 case Z80_SRL:
1391 if (!(r = rd_r_(&ptr))) {
1392 break;
1393 }
1394 wrtb (0xCB);
1395 r--;
1396 wrtb (0x38 + r);
1397 break;
1398 case Z80_SUB:
1399 if (!(r = rd_r (&ptr))) {
1400 break;
1401 }
1402 if (has_argument (&ptr)) { /* SUB A,r ? */
1403 if (r != A) {
1404 eprintf ("parse error before: %s\n", ptr);
1405 break;
1406 }
1407 if (!(r = rd_r (&ptr))) {
1408 break;
1409 }
1410 }
1411 r--;
1412 wrtb (0x90 + r);
1413 break;
1414 case Z80_XOR:
1415 if (!(r = rd_r (&ptr))) {
1416 break;
1417 }
1418 r--;
1419 wrtb (0xA8 + r);
1420 break;
1421 case Z80_DEFB:
1422 case Z80_DB:
1423 case Z80_DEFM:
1424 case Z80_DM:
1425 ptr = delspc (ptr);
1426 while (1) {
1427 have_quote = (*ptr == '"' || *ptr == '\'');
1428 if (have_quote) {
1429 /* Read string. */
1430 int quote = *ptr;
1431 ++ptr;
1432 while (*ptr != quote) {
1433 write_one_byte (rd_character (&ptr, NULL, 1), 0);
1434 if (*ptr == 0) {
1435 eprintf ("end of line in quoted string\n");
1436 break;
1437 }
1438 }
1439 ++ptr;
1440 } else {
1441 /* Read expression. */
1442 skipword (&ptr, ',');
1443 }
1444 ptr = delspc (ptr);
1445 if (*ptr == ',') {
1446 ++ptr;
1447 continue;
1448 }
1449 if (*ptr != 0) {
1450 eprintf ("junk in byte definition: %s\n", ptr);
1451 }
1452 break;
1453 }
1454 break;
1455 case Z80_DEFW:
1456 case Z80_DW:
1457 if (!rd_word (&ptr, ',')) {
1458 eprintf ("No data for word definition\n");
1459 break;
1460 }
1461 while (1) {
1462 ptr = delspc (ptr);
1463 if (*ptr != ',') {
1464 break;
1465 }
1466 ++ptr;
1467 if (!rd_word (&ptr, ',')) {
1468 eprintf ("Missing expression in defw\n");
1469 }
1470 }
1471 break;
1472 case Z80_DEFS:
1473 case Z80_DS:
1474 r = rd_expr (&ptr, ',', NULL, sp, 1);
1475 if (r < 0) {
1476 eprintf ("ds should have its first argument >=0"
1477 " (not -0x%x)\n", -r);
1478 break;
1479 }
1480 ptr = delspc (ptr);
1481 if (*ptr) {
1482 rd_comma (&ptr);
1483 readbyte = 0;
1484 rd_byte (&ptr, '\0');
1485 writebyte = 0;
1486 break;
1487 }
1488 for (i = 0; i < r; i++) {
1489 write_one_byte (0, 0);
1490 }
1491 break;
1492 case Z80_END:
1493 break;
1494 case Z80_ORG:
1495 addr = rd_expr (&ptr, '\0', NULL, sp, 1) & 0xffff;
1496 break;
1497 case Z80_IF:
1498 break;
1499 case Z80_ELSE:
1500 eprintf ("else without if\n");
1501 break;
1502 case Z80_ENDIF:
1503 eprintf ("endif without if\n");
1504 break;
1505 case Z80_ENDM:
1506 if (stack[sp].file) {
1507 eprintf ("endm outside macro definition\n");
1508 }
1509 break;
1510 case Z80_SEEK:
1511 eprintf ("seek error\n");
1512 break;
1513 default:
1514 // eprintf ("command or comment expected (was %s)\n", ptr);
1515 return 0;
1516 }
1517
1518 return obuflen;
1519 }
1520
1521 // XXX
z80asm(unsigned char * outbuf,const char * s)1522 R_API_I int z80asm(unsigned char *outbuf, const char *s) {
1523 return assemble (s, outbuf);
1524 }
1525
1526 #ifdef MAIN_ASM
main(int argc,char ** argv)1527 int main(int argc, char **argv) {
1528 int len;
1529 unsigned char buf[4];
1530
1531 buf[0] = buf[1] = buf[2] = 0;
1532 len = z80asm (buf, "nop");
1533 printf ("%d %02x%02x%02x\n", len, buf[0], buf[1], buf[2]);
1534
1535 len = z80asm (buf, "cp b");
1536 printf ("%d %02x%02x%02x\n", len, buf[0], buf[1], buf[2]);
1537
1538 len = z80asm (buf, "call 0x123");
1539 printf ("%d %02x%02x%02x\n", len, buf[0], buf[1], buf[2]);
1540
1541 len = z80asm (buf, "call bla");
1542 printf ("%d %02x%02x%02x\n", len, buf[0], buf[1], buf[2]);
1543
1544 return 0;
1545 }
1546 #endif
1547