]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gas/config/tc-z80.c
Copyright update for binutils
[thirdparty/binutils-gdb.git] / gas / config / tc-z80.c
CommitLineData
3c9b82ba 1/* tc-z80.c -- Assemble code for the Zilog Z80 and ASCII R800
6f2750fe 2 Copyright (C) 2005-2016 Free Software Foundation, Inc.
3c9b82ba
NC
3 Contributed by Arnold Metselaar <arnold_m@operamail.com>
4
5 This file is part of GAS, the GNU Assembler.
6
7 GAS is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
ec2655a6 9 the Free Software Foundation; either version 3, or (at your option)
3c9b82ba
NC
10 any later version.
11
12 GAS is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GAS; see the file COPYING. If not, write to the Free
19 Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
20 02110-1301, USA. */
21
22#include "as.h"
3c9b82ba
NC
23#include "safe-ctype.h"
24#include "subsegs.h"
3c9b82ba
NC
25
26/* Exported constants. */
27const char comment_chars[] = ";\0";
28const char line_comment_chars[] = "#;\0";
29const char line_separator_chars[] = "\0";
30const char EXP_CHARS[] = "eE\0";
31const char FLT_CHARS[] = "RrFf\0";
32
33/* For machine specific options. */
34const char * md_shortopts = ""; /* None yet. */
35
36enum options
37{
38 OPTION_MACH_Z80 = OPTION_MD_BASE,
39 OPTION_MACH_R800,
40 OPTION_MACH_IUD,
41 OPTION_MACH_WUD,
42 OPTION_MACH_FUD,
43 OPTION_MACH_IUP,
44 OPTION_MACH_WUP,
45 OPTION_MACH_FUP
46};
47
48#define INS_Z80 1
49#define INS_UNDOC 2
50#define INS_UNPORT 4
51#define INS_R800 8
52
53struct option md_longopts[] =
54{
55 { "z80", no_argument, NULL, OPTION_MACH_Z80},
56 { "r800", no_argument, NULL, OPTION_MACH_R800},
57 { "ignore-undocumented-instructions", no_argument, NULL, OPTION_MACH_IUD },
58 { "Wnud", no_argument, NULL, OPTION_MACH_IUD },
59 { "warn-undocumented-instructions", no_argument, NULL, OPTION_MACH_WUD },
60 { "Wud", no_argument, NULL, OPTION_MACH_WUD },
61 { "forbid-undocumented-instructions", no_argument, NULL, OPTION_MACH_FUD },
62 { "Fud", no_argument, NULL, OPTION_MACH_FUD },
63 { "ignore-unportable-instructions", no_argument, NULL, OPTION_MACH_IUP },
64 { "Wnup", no_argument, NULL, OPTION_MACH_IUP },
65 { "warn-unportable-instructions", no_argument, NULL, OPTION_MACH_WUP },
66 { "Wup", no_argument, NULL, OPTION_MACH_WUP },
67 { "forbid-unportable-instructions", no_argument, NULL, OPTION_MACH_FUP },
68 { "Fup", no_argument, NULL, OPTION_MACH_FUP },
69
70 { NULL, no_argument, NULL, 0 }
71} ;
72
73size_t md_longopts_size = sizeof (md_longopts);
74
75extern int coff_flags;
76/* Instruction classes that silently assembled. */
77static int ins_ok = INS_Z80 | INS_UNDOC;
78/* Instruction classes that generate errors. */
79static int ins_err = INS_R800;
80/* Instruction classes actually used, determines machine type. */
81static int ins_used = INS_Z80;
82
83int
84md_parse_option (int c, char* arg ATTRIBUTE_UNUSED)
85{
86 switch (c)
87 {
88 default:
89 return 0;
90 case OPTION_MACH_Z80:
91 ins_ok &= ~INS_R800;
92 ins_err |= INS_R800;
93 break;
94 case OPTION_MACH_R800:
95 ins_ok = INS_Z80 | INS_UNDOC | INS_R800;
96 ins_err = INS_UNPORT;
97 break;
98 case OPTION_MACH_IUD:
99 ins_ok |= INS_UNDOC;
100 ins_err &= ~INS_UNDOC;
101 break;
102 case OPTION_MACH_IUP:
103 ins_ok |= INS_UNDOC | INS_UNPORT;
104 ins_err &= ~(INS_UNDOC | INS_UNPORT);
105 break;
106 case OPTION_MACH_WUD:
107 if ((ins_ok & INS_R800) == 0)
108 {
109 ins_ok &= ~(INS_UNDOC|INS_UNPORT);
110 ins_err &= ~INS_UNDOC;
111 }
112 break;
113 case OPTION_MACH_WUP:
114 ins_ok &= ~INS_UNPORT;
115 ins_err &= ~(INS_UNDOC|INS_UNPORT);
116 break;
117 case OPTION_MACH_FUD:
118 if ((ins_ok & INS_R800) == 0)
119 {
120 ins_ok &= (INS_UNDOC | INS_UNPORT);
121 ins_err |= INS_UNDOC | INS_UNPORT;
122 }
123 break;
124 case OPTION_MACH_FUP:
125 ins_ok &= ~INS_UNPORT;
126 ins_err |= INS_UNPORT;
127 break;
128 }
129
130 return 1;
131}
132
133void
134md_show_usage (FILE * f)
135{
136 fprintf (f, "\n\
137CPU model/instruction set options:\n\
138\n\
139 -z80\t\t assemble for Z80\n\
140 -ignore-undocumented-instructions\n\
141 -Wnud\n\
142\tsilently assemble undocumented Z80-instructions that work on R800\n\
143 -ignore-unportable-instructions\n\
144 -Wnup\n\
145\tsilently assemble all undocumented Z80-instructions\n\
146 -warn-undocumented-instructions\n\
147 -Wud\n\
148\tissue warnings for undocumented Z80-instructions that work on R800\n\
149 -warn-unportable-instructions\n\
150 -Wup\n\
151\tissue warnings for other undocumented Z80-instructions\n\
152 -forbid-undocumented-instructions\n\
153 -Fud\n\
154\ttreat all undocumented z80-instructions as errors\n\
155 -forbid-unportable-instructions\n\
156 -Fup\n\
157\ttreat undocumented z80-instructions that do not work on R800 as errors\n\
158 -r800\t assemble for R800\n\n\
159Default: -z80 -ignore-undocument-instructions -warn-unportable-instructions.\n");
160}
161
162static symbolS * zero;
163
25045f79
AM
164struct reg_entry
165{
166 char* name;
167 int number;
168};
169#define R_STACKABLE (0x80)
170#define R_ARITH (0x40)
171#define R_IX (0x20)
172#define R_IY (0x10)
173#define R_INDEX (R_IX | R_IY)
174
175#define REG_A (7)
176#define REG_B (0)
177#define REG_C (1)
178#define REG_D (2)
179#define REG_E (3)
180#define REG_H (4)
181#define REG_L (5)
182#define REG_F (6 | 8)
183#define REG_I (9)
184#define REG_R (10)
185
186#define REG_AF (3 | R_STACKABLE)
187#define REG_BC (0 | R_STACKABLE | R_ARITH)
188#define REG_DE (1 | R_STACKABLE | R_ARITH)
189#define REG_HL (2 | R_STACKABLE | R_ARITH)
190#define REG_IX (REG_HL | R_IX)
191#define REG_IY (REG_HL | R_IY)
192#define REG_SP (3 | R_ARITH)
193
194static const struct reg_entry regtable[] =
195{
196 {"a", REG_A },
197 {"af", REG_AF },
198 {"b", REG_B },
199 {"bc", REG_BC },
200 {"c", REG_C },
201 {"d", REG_D },
202 {"de", REG_DE },
203 {"e", REG_E },
204 {"f", REG_F },
205 {"h", REG_H },
206 {"hl", REG_HL },
207 {"i", REG_I },
208 {"ix", REG_IX },
209 {"ixh",REG_H | R_IX },
210 {"ixl",REG_L | R_IX },
211 {"iy", REG_IY },
212 {"iyh",REG_H | R_IY },
213 {"iyl",REG_L | R_IY },
214 {"l", REG_L },
215 {"r", REG_R },
216 {"sp", REG_SP },
217} ;
218
219#define BUFLEN 8 /* Large enough for any keyword. */
220
3c9b82ba
NC
221void
222md_begin (void)
223{
25045f79 224 expressionS nul, reg;
3c9b82ba 225 char * p;
25045f79
AM
226 unsigned int i, j, k;
227 char buf[BUFLEN];
3c9b82ba 228
25045f79
AM
229 reg.X_op = O_register;
230 reg.X_md = 0;
231 reg.X_add_symbol = reg.X_op_symbol = 0;
232 for ( i = 0 ; i < ARRAY_SIZE ( regtable ) ; ++i )
233 {
234 reg.X_add_number = regtable[i].number;
235 k = strlen ( regtable[i].name );
236 buf[k] = 0;
237 if ( k+1 < BUFLEN )
238 {
239 for ( j = ( 1<<k ) ; j ; --j )
240 {
241 for ( k = 0 ; regtable[i].name[k] ; ++k )
242 {
243 buf[k] = ( j & ( 1<<k ) ) ? TOUPPER ( regtable[i].name[k] ) : regtable[i].name[k];
244 }
245 symbolS * psym = symbol_find_or_make(buf);
246 S_SET_SEGMENT(psym, reg_section);
247 symbol_set_value_expression(psym, &reg);
248 }
249 }
250 }
3c9b82ba
NC
251 p = input_line_pointer;
252 input_line_pointer = "0";
253 nul.X_md=0;
254 expression (& nul);
255 input_line_pointer = p;
256 zero = make_expr_symbol (& nul);
257 /* We do not use relaxation (yet). */
258 linkrelax = 0;
259}
260
261void
262z80_md_end (void)
263{
264 int mach_type;
265
266 if (ins_used & (INS_UNPORT | INS_R800))
267 ins_used |= INS_UNDOC;
268
269 switch (ins_used)
270 {
271 case INS_Z80:
272 mach_type = bfd_mach_z80strict;
273 break;
274 case INS_Z80|INS_UNDOC:
275 mach_type = bfd_mach_z80;
276 break;
277 case INS_Z80|INS_UNDOC|INS_UNPORT:
278 mach_type = bfd_mach_z80full;
279 break;
280 case INS_Z80|INS_UNDOC|INS_R800:
281 mach_type = bfd_mach_r800;
282 break;
283 default:
284 mach_type = 0;
285 }
286
287 bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach_type);
288}
289
3c9b82ba
NC
290static const char *
291skip_space (const char *s)
292{
293 while (*s == ' ' || *s == '\t')
294 ++s;
295 return s;
296}
297
298/* A non-zero return-value causes a continue in the
299 function read_a_source_file () in ../read.c. */
300int
301z80_start_line_hook (void)
302{
303 char *p, quote;
304 char buf[4];
305
306 /* Convert one character constants. */
307 for (p = input_line_pointer; *p && *p != '\n'; ++p)
308 {
309 switch (*p)
310 {
311 case '\'':
312 if (p[1] != 0 && p[1] != '\'' && p[2] == '\'')
313 {
314 snprintf (buf, 4, "%3d", (unsigned char)p[1]);
315 *p++ = buf[0];
316 *p++ = buf[1];
317 *p++ = buf[2];
318 break;
319 }
320 case '"':
321 for (quote = *p++; quote != *p && '\n' != *p; ++p)
322 /* No escapes. */ ;
323 if (quote != *p)
324 {
325 as_bad (_("-- unterminated string"));
326 ignore_rest_of_line ();
327 return 1;
328 }
329 break;
330 }
331 }
134dcee5 332 /* Check for <label>[:] [.](EQU|DEFL) <value>. */
3c9b82ba
NC
333 if (is_name_beginner (*input_line_pointer))
334 {
d02603dc 335 char *name;
3c9b82ba
NC
336 char c, *rest, *line_start;
337 int len;
338
339 line_start = input_line_pointer;
3c9b82ba
NC
340 if (ignore_input ())
341 return 0;
342
d02603dc 343 c = get_symbol_name (&name);
3c9b82ba
NC
344 rest = input_line_pointer + 1;
345
346 if (*rest == ':')
347 ++rest;
348 if (*rest == ' ' || *rest == '\t')
349 ++rest;
134dcee5
AM
350 if (*rest == '.')
351 ++rest;
3c9b82ba
NC
352 if (strncasecmp (rest, "EQU", 3) == 0)
353 len = 3;
354 else if (strncasecmp (rest, "DEFL", 4) == 0)
355 len = 4;
356 else
357 len = 0;
3c45a255 358 if (len && (!ISALPHA(rest[len]) ) )
3c9b82ba
NC
359 {
360 /* Handle assignment here. */
3c9b82ba 361 if (line_start[-1] == '\n')
f9eb6721 362 {
3c45a255
AM
363 bump_line_counters ();
364 LISTING_NEWLINE ();
f9eb6721 365 }
3c45a255
AM
366 input_line_pointer = rest + len - 1;
367 /* Allow redefining with "DEFL" (len == 4), but not with "EQU". */
d02603dc 368 equals (name, len == 4);
3c9b82ba
NC
369 return 1;
370 }
371 else
372 {
373 /* Restore line and pointer. */
d02603dc 374 (void) restore_line_pointer (c);
3c9b82ba
NC
375 input_line_pointer = line_start;
376 }
377 }
378 return 0;
379}
380
381symbolS *
382md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
383{
384 return NULL;
385}
386
387char *
388md_atof (int type ATTRIBUTE_UNUSED, char *litP ATTRIBUTE_UNUSED,
389 int *sizeP ATTRIBUTE_UNUSED)
390{
391 return _("floating point numbers are not implemented");
392}
393
394valueT
395md_section_align (segT seg ATTRIBUTE_UNUSED, valueT size)
396{
397 return size;
398}
399
400long
401md_pcrel_from (fixS * fixp)
402{
403 return fixp->fx_where +
404 fixp->fx_frag->fr_address + 1;
405}
406
407typedef const char * (asfunc)(char, char, const char*);
408
409typedef struct _table_t
410{
411 char* name;
412 char prefix;
413 char opcode;
414 asfunc * fp;
415} table_t;
416
417/* Compares the key for structs that start with a char * to the key. */
418static int
419key_cmp (const void * a, const void * b)
420{
421 const char *str_a, *str_b;
422
423 str_a = *((const char**)a);
424 str_b = *((const char**)b);
425 return strcmp (str_a, str_b);
426}
427
3c9b82ba
NC
428char buf[BUFLEN];
429const char *key = buf;
430
3c9b82ba
NC
431/* Prevent an error on a line from also generating
432 a "junk at end of line" error message. */
433static char err_flag;
434
435static void
436error (const char * message)
437{
20203fb9 438 as_bad ("%s", message);
3c9b82ba
NC
439 err_flag = 1;
440}
441
442static void
443ill_op (void)
444{
445 error (_("illegal operand"));
446}
447
448static void
449wrong_mach (int ins_type)
450{
451 const char *p;
452
453 switch (ins_type)
454 {
455 case INS_UNDOC:
456 p = "undocumented instruction";
457 break;
458 case INS_UNPORT:
459 p = "instruction does not work on R800";
460 break;
461 case INS_R800:
462 p = "instruction only works R800";
463 break;
464 default:
134dcee5 465 p = 0; /* Not reachable. */
3c9b82ba
NC
466 }
467
468 if (ins_type & ins_err)
469 error (_(p));
470 else
73812f59 471 as_warn ("%s", _(p));
3c9b82ba
NC
472}
473
474static void
475check_mach (int ins_type)
476{
477 if ((ins_type & ins_ok) == 0)
478 wrong_mach (ins_type);
479 ins_used |= ins_type;
480}
481
3c9b82ba
NC
482/* Check whether an expression is indirect. */
483static int
484is_indir (const char *s)
485{
486 char quote;
487 const char *p;
488 int indir, depth;
489
490 /* Indirection is indicated with parentheses. */
491 indir = (*s == '(');
492
493 for (p = s, depth = 0; *p && *p != ','; ++p)
494 {
495 switch (*p)
496 {
497 case '"':
498 case '\'':
499 for (quote = *p++; quote != *p && *p != '\n'; ++p)
500 if (*p == '\\' && p[1])
501 ++p;
502 break;
503 case '(':
504 ++ depth;
505 break;
506 case ')':
507 -- depth;
508 if (depth == 0)
509 {
510 p = skip_space (p + 1);
511 if (*p && *p != ',')
512 indir = 0;
513 --p;
514 }
515 if (depth < 0)
516 error (_("mismatched parentheses"));
517 break;
518 }
519 }
520
521 if (depth != 0)
522 error (_("mismatched parentheses"));
523
524 return indir;
525}
526
25045f79 527/* Check whether a symbol involves a register. */
3739860c 528static int
25045f79
AM
529contains_register(symbolS *sym)
530{
531 if (sym)
532 {
533 expressionS * ex = symbol_get_value_expression(sym);
3739860c
L
534 return (O_register == ex->X_op)
535 || (ex->X_add_symbol && contains_register(ex->X_add_symbol))
25045f79
AM
536 || (ex->X_op_symbol && contains_register(ex->X_op_symbol));
537 }
538 else
539 return 0;
540}
541
542/* Parse general expression, not loooking for indexed adressing. */
3c9b82ba 543static const char *
25045f79 544parse_exp_not_indexed (const char *s, expressionS *op)
3c9b82ba
NC
545{
546 const char *p;
547 int indir;
3c9b82ba
NC
548
549 p = skip_space (s);
550 op->X_md = indir = is_indir (p);
25045f79 551 input_line_pointer = (char*) s ;
73812f59 552 expression (op);
25045f79 553 switch (op->X_op)
3c9b82ba 554 {
25045f79
AM
555 case O_absent:
556 error (_("missing operand"));
557 break;
558 case O_illegal:
559 error (_("bad expression syntax"));
560 break;
abd58633
AM
561 default:
562 break;
3c9b82ba 563 }
3c9b82ba
NC
564 return input_line_pointer;
565}
566
25045f79 567/* Parse expression, change operator to O_md1 for indexed addressing*/
3c9b82ba
NC
568static const char *
569parse_exp (const char *s, expressionS *op)
570{
25045f79
AM
571 const char* res = parse_exp_not_indexed (s, op);
572 switch (op->X_op)
573 {
574 case O_add:
575 case O_subtract:
576 if (op->X_md && (O_register == symbol_get_value_expression(op->X_add_symbol)->X_op))
577 {
578 int rnum = symbol_get_value_expression(op->X_add_symbol)->X_add_number;
579 if ( ((REG_IX != rnum) && (REG_IY != rnum)) || contains_register(op->X_op_symbol) )
580 {
581 ill_op();
582 }
583 else
584 {
585 if (O_subtract == op->X_op)
586 {
587 expressionS minus;
588 minus.X_op = O_uminus;
589 minus.X_add_number = 0;
590 minus.X_add_symbol = op->X_op_symbol;
591 minus.X_op_symbol = 0;
592 op->X_op_symbol = make_expr_symbol(&minus);
593 op->X_op = O_add;
594 }
595 symbol_get_value_expression(op->X_op_symbol)->X_add_number += op->X_add_number;
596 op->X_add_number = rnum;
597 op->X_add_symbol = op->X_op_symbol;
598 op->X_op_symbol = 0;
599 op->X_op = O_md1;
600 }
601 }
602 break;
603 case O_register:
604 if ( op->X_md && ((REG_IX == op->X_add_number)||(REG_IY == op->X_add_number)) )
605 {
606 op->X_add_symbol = zero;
607 op->X_op = O_md1;
608 }
609 break;
abd58633
AM
610 default:
611 break;
25045f79
AM
612 }
613 return res;
3c9b82ba
NC
614}
615
616/* Condition codes, including some synonyms provided by HiTech zas. */
617static const struct reg_entry cc_tab[] =
618{
619 { "age", 6 << 3 },
620 { "alt", 7 << 3 },
621 { "c", 3 << 3 },
622 { "di", 4 << 3 },
623 { "ei", 5 << 3 },
624 { "lge", 2 << 3 },
625 { "llt", 3 << 3 },
626 { "m", 7 << 3 },
627 { "nc", 2 << 3 },
628 { "nz", 0 << 3 },
629 { "p", 6 << 3 },
630 { "pe", 5 << 3 },
631 { "po", 4 << 3 },
632 { "z", 1 << 3 },
633} ;
634
635/* Parse condition code. */
636static const char *
637parse_cc (const char *s, char * op)
638{
639 const char *p;
640 int i;
641 struct reg_entry * cc_p;
642
643 for (i = 0; i < BUFLEN; ++i)
644 {
645 if (!ISALPHA (s[i])) /* Condition codes consist of letters only. */
646 break;
647 buf[i] = TOLOWER (s[i]);
648 }
649
650 if ((i < BUFLEN)
651 && ((s[i] == 0) || (s[i] == ',')))
652 {
653 buf[i] = 0;
654 cc_p = bsearch (&key, cc_tab, ARRAY_SIZE (cc_tab),
655 sizeof (cc_tab[0]), key_cmp);
656 }
657 else
658 cc_p = NULL;
659
660 if (cc_p)
661 {
662 *op = cc_p->number;
663 p = s + i;
664 }
665 else
666 p = NULL;
667
668 return p;
669}
670
671static const char *
672emit_insn (char prefix, char opcode, const char * args)
673{
674 char *p;
675
676 if (prefix)
677 {
678 p = frag_more (2);
679 *p++ = prefix;
680 }
681 else
682 p = frag_more (1);
683 *p = opcode;
684 return args;
685}
686
134dcee5
AM
687void z80_cons_fix_new (fragS *frag_p, int offset, int nbytes, expressionS *exp)
688{
689 bfd_reloc_code_real_type r[4] =
690 {
691 BFD_RELOC_8,
692 BFD_RELOC_16,
693 BFD_RELOC_24,
694 BFD_RELOC_32
695 };
696
3739860c 697 if (nbytes < 1 || nbytes > 4)
134dcee5
AM
698 {
699 as_bad (_("unsupported BFD relocation size %u"), nbytes);
700 }
701 else
702 {
703 fix_new_exp (frag_p, offset, nbytes, exp, 0, r[nbytes-1]);
704 }
705}
706
3c9b82ba
NC
707static void
708emit_byte (expressionS * val, bfd_reloc_code_real_type r_type)
709{
710 char *p;
711 int lo, hi;
3c9b82ba
NC
712
713 p = frag_more (1);
714 *p = val->X_add_number;
25045f79
AM
715 if ( contains_register(val->X_add_symbol) || contains_register(val->X_op_symbol) )
716 {
717 ill_op();
718 }
719 else if ((r_type == BFD_RELOC_8_PCREL) && (val->X_op == O_constant))
134dcee5 720 {
20203fb9 721 as_bad (_("cannot make a relative jump to an absolute location"));
134dcee5
AM
722 }
723 else if (val->X_op == O_constant)
3c9b82ba
NC
724 {
725 lo = -128;
726 hi = (BFD_RELOC_8 == r_type) ? 255 : 127;
727
728 if ((val->X_add_number < lo) || (val->X_add_number > hi))
729 {
730 if (r_type == BFD_RELOC_Z80_DISP8)
731 as_bad (_("offset too large"));
732 else
733 as_warn (_("overflow"));
734 }
735 }
736 else
737 {
73812f59
NC
738 fix_new_exp (frag_now, p - frag_now->fr_literal, 1, val,
739 (r_type == BFD_RELOC_8_PCREL) ? TRUE : FALSE, r_type);
3c9b82ba
NC
740 /* FIXME : Process constant offsets immediately. */
741 }
742}
743
744static void
745emit_word (expressionS * val)
746{
747 char *p;
748
749 p = frag_more (2);
750 if ( (val->X_op == O_register)
25045f79
AM
751 || (val->X_op == O_md1)
752 || contains_register(val->X_add_symbol)
753 || contains_register(val->X_op_symbol) )
3c9b82ba
NC
754 ill_op ();
755 else
756 {
757 *p = val->X_add_number;
758 p[1] = (val->X_add_number>>8);
759 if (val->X_op != O_constant)
760 fix_new_exp (frag_now, p - frag_now->fr_literal, 2,
761 val, FALSE, BFD_RELOC_16);
762 }
763}
764
765static void
766emit_mx (char prefix, char opcode, int shift, expressionS * arg)
767 /* The operand m may be r, (hl), (ix+d), (iy+d),
768 if 0 == prefix m may also be ixl, ixh, iyl, iyh. */
769{
770 char *q;
771 int rnum;
772
773 rnum = arg->X_add_number;
774 switch (arg->X_op)
775 {
776 case O_register:
777 if (arg->X_md)
778 {
779 if (rnum != REG_HL)
780 {
781 ill_op ();
782 break;
783 }
784 else
785 rnum = 6;
786 }
787 else
788 {
789 if ((prefix == 0) && (rnum & R_INDEX))
790 {
791 prefix = (rnum & R_IX) ? 0xDD : 0xFD;
792 check_mach (INS_UNDOC);
793 rnum &= ~R_INDEX;
794 }
795 if (rnum > 7)
796 {
797 ill_op ();
798 break;
799 }
800 }
801 q = frag_more (prefix ? 2 : 1);
802 if (prefix)
803 * q ++ = prefix;
804 * q ++ = opcode + (rnum << shift);
805 break;
806 case O_md1:
807 q = frag_more (2);
808 *q++ = (rnum & R_IX) ? 0xDD : 0xFD;
809 *q = (prefix) ? prefix : (opcode + (6 << shift));
761025be
AM
810 {
811 expressionS offset = *arg;
812 offset.X_op = O_symbol;
813 offset.X_add_number = 0;
814 emit_byte (&offset, BFD_RELOC_Z80_DISP8);
815 }
3c9b82ba
NC
816 if (prefix)
817 {
818 q = frag_more (1);
819 *q = opcode+(6<<shift);
820 }
821 break;
822 default:
823 abort ();
824 }
825}
826
827/* The operand m may be r, (hl), (ix+d), (iy+d),
828 if 0 = prefix m may also be ixl, ixh, iyl, iyh. */
829static const char *
830emit_m (char prefix, char opcode, const char *args)
831{
832 expressionS arg_m;
833 const char *p;
834
835 p = parse_exp (args, &arg_m);
836 switch (arg_m.X_op)
837 {
838 case O_md1:
839 case O_register:
840 emit_mx (prefix, opcode, 0, &arg_m);
841 break;
842 default:
843 ill_op ();
844 }
845 return p;
846}
847
848/* The operand m may be as above or one of the undocumented
849 combinations (ix+d),r and (iy+d),r (if unportable instructions
850 are allowed). */
851static const char *
852emit_mr (char prefix, char opcode, const char *args)
853{
854 expressionS arg_m, arg_r;
855 const char *p;
856
857 p = parse_exp (args, & arg_m);
858
859 switch (arg_m.X_op)
860 {
861 case O_md1:
862 if (*p == ',')
863 {
864 p = parse_exp (p + 1, & arg_r);
865
866 if ((arg_r.X_md == 0)
867 && (arg_r.X_op == O_register)
868 && (arg_r.X_add_number < 8))
869 opcode += arg_r.X_add_number-6; /* Emit_mx () will add 6. */
870 else
871 {
872 ill_op ();
873 break;
874 }
875 check_mach (INS_UNPORT);
876 }
877 case O_register:
878 emit_mx (prefix, opcode, 0, & arg_m);
879 break;
880 default:
881 ill_op ();
882 }
883 return p;
884}
885
886static void
887emit_sx (char prefix, char opcode, expressionS * arg_p)
888{
889 char *q;
890
891 switch (arg_p->X_op)
892 {
893 case O_register:
894 case O_md1:
895 emit_mx (prefix, opcode, 0, arg_p);
896 break;
897 default:
898 if (arg_p->X_md)
899 ill_op ();
900 else
901 {
902 q = frag_more (prefix ? 2 : 1);
903 if (prefix)
904 *q++ = prefix;
905 *q = opcode ^ 0x46;
906 emit_byte (arg_p, BFD_RELOC_8);
907 }
908 }
909}
910
911/* The operand s may be r, (hl), (ix+d), (iy+d), n. */
912static const char *
913emit_s (char prefix, char opcode, const char *args)
914{
915 expressionS arg_s;
916 const char *p;
917
918 p = parse_exp (args, & arg_s);
919 emit_sx (prefix, opcode, & arg_s);
920 return p;
921}
922
923static const char *
924emit_call (char prefix ATTRIBUTE_UNUSED, char opcode, const char * args)
925{
926 expressionS addr;
927 const char *p; char *q;
928
25045f79 929 p = parse_exp_not_indexed (args, &addr);
3c9b82ba
NC
930 if (addr.X_md)
931 ill_op ();
932 else
933 {
934 q = frag_more (1);
935 *q = opcode;
936 emit_word (& addr);
937 }
938 return p;
939}
940
941/* Operand may be rr, r, (hl), (ix+d), (iy+d). */
942static const char *
943emit_incdec (char prefix, char opcode, const char * args)
944{
945 expressionS operand;
946 int rnum;
947 const char *p; char *q;
948
949 p = parse_exp (args, &operand);
950 rnum = operand.X_add_number;
951 if ((! operand.X_md)
952 && (operand.X_op == O_register)
953 && (R_ARITH&rnum))
954 {
955 q = frag_more ((rnum & R_INDEX) ? 2 : 1);
956 if (rnum & R_INDEX)
957 *q++ = (rnum & R_IX) ? 0xDD : 0xFD;
958 *q = prefix + ((rnum & 3) << 4);
959 }
960 else
961 {
962 if ((operand.X_op == O_md1) || (operand.X_op == O_register))
963 emit_mx (0, opcode, 3, & operand);
964 else
965 ill_op ();
966 }
967 return p;
968}
969
970static const char *
971emit_jr (char prefix ATTRIBUTE_UNUSED, char opcode, const char * args)
972{
973 expressionS addr;
974 const char *p;
975 char *q;
976
25045f79 977 p = parse_exp_not_indexed (args, &addr);
3c9b82ba
NC
978 if (addr.X_md)
979 ill_op ();
980 else
981 {
982 q = frag_more (1);
983 *q = opcode;
984 emit_byte (&addr, BFD_RELOC_8_PCREL);
985 }
986 return p;
987}
988
989static const char *
990emit_jp (char prefix, char opcode, const char * args)
991{
992 expressionS addr;
993 const char *p;
994 char *q;
995 int rnum;
996
25045f79 997 p = parse_exp_not_indexed (args, & addr);
3c9b82ba
NC
998 if (addr.X_md)
999 {
1000 rnum = addr.X_add_number;
25045f79 1001 if ((O_register == addr.X_op) && (REG_HL == (rnum & ~R_INDEX)))
3c9b82ba
NC
1002 {
1003 q = frag_more ((rnum & R_INDEX) ? 2 : 1);
1004 if (rnum & R_INDEX)
1005 *q++ = (rnum & R_IX) ? 0xDD : 0xFD;
1006 *q = prefix;
1007 }
1008 else
1009 ill_op ();
1010 }
1011 else
1012 {
1013 q = frag_more (1);
1014 *q = opcode;
1015 emit_word (& addr);
1016 }
1017 return p;
1018}
1019
1020static const char *
1021emit_im (char prefix, char opcode, const char * args)
1022{
1023 expressionS mode;
1024 const char *p;
1025 char *q;
1026
1027 p = parse_exp (args, & mode);
1028 if (mode.X_md || (mode.X_op != O_constant))
1029 ill_op ();
1030 else
1031 switch (mode.X_add_number)
1032 {
1033 case 1:
1034 case 2:
1035 ++mode.X_add_number;
1036 /* Fall through. */
1037 case 0:
1038 q = frag_more (2);
1039 *q++ = prefix;
1040 *q = opcode + 8*mode.X_add_number;
1041 break;
1042 default:
1043 ill_op ();
1044 }
1045 return p;
1046}
1047
1048static const char *
1049emit_pop (char prefix ATTRIBUTE_UNUSED, char opcode, const char * args)
1050{
1051 expressionS regp;
1052 const char *p;
1053 char *q;
1054
1055 p = parse_exp (args, & regp);
1056 if ((!regp.X_md)
1057 && (regp.X_op == O_register)
1058 && (regp.X_add_number & R_STACKABLE))
1059 {
1060 int rnum;
1061
1062 rnum = regp.X_add_number;
1063 if (rnum&R_INDEX)
1064 {
1065 q = frag_more (2);
1066 *q++ = (rnum&R_IX)?0xDD:0xFD;
1067 }
1068 else
1069 q = frag_more (1);
1070 *q = opcode + ((rnum & 3) << 4);
1071 }
1072 else
1073 ill_op ();
1074
1075 return p;
1076}
1077
1078static const char *
1079emit_retcc (char prefix ATTRIBUTE_UNUSED, char opcode, const char * args)
1080{
1081 char cc, *q;
1082 const char *p;
1083
1084 p = parse_cc (args, &cc);
1085 q = frag_more (1);
1086 if (p)
1087 *q = opcode + cc;
1088 else
1089 *q = prefix;
1090 return p ? p : args;
1091}
1092
1093static const char *
1094emit_adc (char prefix, char opcode, const char * args)
1095{
1096 expressionS term;
1097 int rnum;
1098 const char *p;
1099 char *q;
1100
1101 p = parse_exp (args, &term);
1102 if (*p++ != ',')
1103 {
9aff4b7a 1104 error (_("bad instruction syntax"));
3c9b82ba
NC
1105 return p;
1106 }
1107
1108 if ((term.X_md) || (term.X_op != O_register))
1109 ill_op ();
1110 else
1111 switch (term.X_add_number)
1112 {
1113 case REG_A:
1114 p = emit_s (0, prefix, p);
1115 break;
1116 case REG_HL:
1117 p = parse_exp (p, &term);
1118 if ((!term.X_md) && (term.X_op == O_register))
1119 {
1120 rnum = term.X_add_number;
1121 if (R_ARITH == (rnum & (R_ARITH | R_INDEX)))
1122 {
1123 q = frag_more (2);
1124 *q++ = 0xED;
1125 *q = opcode + ((rnum & 3) << 4);
1126 break;
1127 }
1128 }
1129 /* Fall through. */
1130 default:
1131 ill_op ();
1132 }
1133 return p;
1134}
1135
1136static const char *
1137emit_add (char prefix, char opcode, const char * args)
1138{
1139 expressionS term;
1140 int lhs, rhs;
1141 const char *p;
1142 char *q;
1143
1144 p = parse_exp (args, &term);
1145 if (*p++ != ',')
1146 {
9aff4b7a 1147 error (_("bad instruction syntax"));
3c9b82ba
NC
1148 return p;
1149 }
1150
1151 if ((term.X_md) || (term.X_op != O_register))
1152 ill_op ();
1153 else
1154 switch (term.X_add_number & ~R_INDEX)
1155 {
1156 case REG_A:
1157 p = emit_s (0, prefix, p);
1158 break;
1159 case REG_HL:
1160 lhs = term.X_add_number;
1161 p = parse_exp (p, &term);
1162 if ((!term.X_md) && (term.X_op == O_register))
1163 {
1164 rhs = term.X_add_number;
1165 if ((rhs & R_ARITH)
1166 && ((rhs == lhs) || ((rhs & ~R_INDEX) != REG_HL)))
1167 {
1168 q = frag_more ((lhs & R_INDEX) ? 2 : 1);
1169 if (lhs & R_INDEX)
1170 *q++ = (lhs & R_IX) ? 0xDD : 0xFD;
1171 *q = opcode + ((rhs & 3) << 4);
1172 break;
1173 }
1174 }
1175 /* Fall through. */
1176 default:
1177 ill_op ();
1178 }
1179 return p;
1180}
1181
1182static const char *
1183emit_bit (char prefix, char opcode, const char * args)
1184{
1185 expressionS b;
1186 int bn;
1187 const char *p;
1188
1189 p = parse_exp (args, &b);
1190 if (*p++ != ',')
9aff4b7a 1191 error (_("bad instruction syntax"));
3c9b82ba
NC
1192
1193 bn = b.X_add_number;
1194 if ((!b.X_md)
1195 && (b.X_op == O_constant)
1196 && (0 <= bn)
1197 && (bn < 8))
1198 {
1199 if (opcode == 0x40)
1200 /* Bit : no optional third operand. */
1201 p = emit_m (prefix, opcode + (bn << 3), p);
1202 else
1203 /* Set, res : resulting byte can be copied to register. */
1204 p = emit_mr (prefix, opcode + (bn << 3), p);
1205 }
1206 else
1207 ill_op ();
1208 return p;
1209}
1210
1211static const char *
1212emit_jpcc (char prefix, char opcode, const char * args)
1213{
1214 char cc;
1215 const char *p;
1216
1217 p = parse_cc (args, & cc);
1218 if (p && *p++ == ',')
1219 p = emit_call (0, opcode + cc, p);
1220 else
1221 p = (prefix == (char)0xC3)
1222 ? emit_jp (0xE9, prefix, args)
1223 : emit_call (0, prefix, args);
1224 return p;
1225}
1226
1227static const char *
1228emit_jrcc (char prefix, char opcode, const char * args)
1229{
1230 char cc;
1231 const char *p;
1232
1233 p = parse_cc (args, &cc);
1234 if (p && *p++ == ',')
1235 {
1236 if (cc > (3 << 3))
1237 error (_("condition code invalid for jr"));
1238 else
1239 p = emit_jr (0, opcode + cc, p);
1240 }
1241 else
1242 p = emit_jr (0, prefix, args);
1243
1244 return p;
1245}
1246
1247static const char *
1248emit_ex (char prefix_in ATTRIBUTE_UNUSED,
1249 char opcode_in ATTRIBUTE_UNUSED, const char * args)
1250{
1251 expressionS op;
1252 const char * p;
1253 char prefix, opcode;
1254
25045f79 1255 p = parse_exp_not_indexed (args, &op);
3c9b82ba
NC
1256 p = skip_space (p);
1257 if (*p++ != ',')
1258 {
1259 error (_("bad instruction syntax"));
1260 return p;
1261 }
1262
1263 prefix = opcode = 0;
1264 if (op.X_op == O_register)
1265 switch (op.X_add_number | (op.X_md ? 0x8000 : 0))
1266 {
1267 case REG_AF:
1268 if (TOLOWER (*p++) == 'a' && TOLOWER (*p++) == 'f')
1269 {
1270 /* The scrubber changes '\'' to '`' in this context. */
1271 if (*p == '`')
1272 ++p;
1273 opcode = 0x08;
1274 }
1275 break;
1276 case REG_DE:
1277 if (TOLOWER (*p++) == 'h' && TOLOWER (*p++) == 'l')
1278 opcode = 0xEB;
1279 break;
1280 case REG_SP|0x8000:
1281 p = parse_exp (p, & op);
1282 if (op.X_op == O_register
1283 && op.X_md == 0
1284 && (op.X_add_number & ~R_INDEX) == REG_HL)
1285 {
1286 opcode = 0xE3;
1287 if (R_INDEX & op.X_add_number)
1288 prefix = (R_IX & op.X_add_number) ? 0xDD : 0xFD;
1289 }
1290 break;
1291 }
1292 if (opcode)
1293 emit_insn (prefix, opcode, p);
1294 else
1295 ill_op ();
1296
1297 return p;
1298}
1299
1300static const char *
1301emit_in (char prefix ATTRIBUTE_UNUSED, char opcode ATTRIBUTE_UNUSED,
1302 const char * args)
1303{
1304 expressionS reg, port;
1305 const char *p;
1306 char *q;
1307
1308 p = parse_exp (args, &reg);
1309 if (*p++ != ',')
1310 {
9aff4b7a 1311 error (_("bad instruction syntax"));
3c9b82ba
NC
1312 return p;
1313 }
1314
1315 p = parse_exp (p, &port);
1316 if (reg.X_md == 0
1317 && reg.X_op == O_register
1318 && (reg.X_add_number <= 7 || reg.X_add_number == REG_F)
1319 && (port.X_md))
1320 {
1321 if (port.X_op != O_md1 && port.X_op != O_register)
1322 {
1323 if (REG_A == reg.X_add_number)
1324 {
1325 q = frag_more (1);
1326 *q = 0xDB;
1327 emit_byte (&port, BFD_RELOC_8);
1328 }
1329 else
1330 ill_op ();
1331 }
1332 else
1333 {
1334 if (port.X_add_number == REG_C)
1335 {
1336 if (reg.X_add_number == REG_F)
1337 check_mach (INS_UNDOC);
1338 else
1339 {
1340 q = frag_more (2);
1341 *q++ = 0xED;
1342 *q = 0x40|((reg.X_add_number&7)<<3);
1343 }
1344 }
1345 else
1346 ill_op ();
1347 }
1348 }
1349 else
1350 ill_op ();
1351 return p;
1352}
1353
1354static const char *
1355emit_out (char prefix ATTRIBUTE_UNUSED, char opcode ATTRIBUTE_UNUSED,
1356 const char * args)
1357{
1358 expressionS reg, port;
1359 const char *p;
1360 char *q;
1361
1362 p = parse_exp (args, & port);
1363 if (*p++ != ',')
1364 {
9aff4b7a 1365 error (_("bad instruction syntax"));
3c9b82ba
NC
1366 return p;
1367 }
1368 p = parse_exp (p, &reg);
1369 if (!port.X_md)
1370 { ill_op (); return p; }
1371 /* Allow "out (c), 0" as unportable instruction. */
1372 if (reg.X_op == O_constant && reg.X_add_number == 0)
1373 {
1374 check_mach (INS_UNPORT);
1375 reg.X_op = O_register;
1376 reg.X_add_number = 6;
1377 }
1378 if (reg.X_md
1379 || reg.X_op != O_register
1380 || reg.X_add_number > 7)
1381 ill_op ();
1382 else
1383 if (port.X_op != O_register && port.X_op != O_md1)
1384 {
1385 if (REG_A == reg.X_add_number)
1386 {
1387 q = frag_more (1);
1388 *q = 0xD3;
1389 emit_byte (&port, BFD_RELOC_8);
1390 }
1391 else
1392 ill_op ();
1393 }
1394 else
1395 {
1396 if (REG_C == port.X_add_number)
1397 {
1398 q = frag_more (2);
1399 *q++ = 0xED;
1400 *q = 0x41 | (reg.X_add_number << 3);
1401 }
1402 else
1403 ill_op ();
1404 }
1405 return p;
1406}
1407
1408static const char *
1409emit_rst (char prefix ATTRIBUTE_UNUSED, char opcode, const char * args)
1410{
1411 expressionS addr;
1412 const char *p;
1413 char *q;
1414
25045f79 1415 p = parse_exp_not_indexed (args, &addr);
3c9b82ba
NC
1416 if (addr.X_op != O_constant)
1417 {
1418 error ("rst needs constant address");
1419 return p;
1420 }
1421
1422 if (addr.X_add_number & ~(7 << 3))
1423 ill_op ();
1424 else
1425 {
1426 q = frag_more (1);
1427 *q = opcode + (addr.X_add_number & (7 << 3));
1428 }
1429 return p;
1430}
1431
1432static void
1433emit_ldxhl (char prefix, char opcode, expressionS *src, expressionS *d)
1434{
1435 char *q;
1436
1437 if (src->X_md)
1438 ill_op ();
1439 else
1440 {
1441 if (src->X_op == O_register)
1442 {
1443 if (src->X_add_number>7)
1444 ill_op ();
1445 if (prefix)
1446 {
1447 q = frag_more (2);
1448 *q++ = prefix;
1449 }
1450 else
1451 q = frag_more (1);
1452 *q = opcode + src->X_add_number;
1453 if (d)
1454 emit_byte (d, BFD_RELOC_Z80_DISP8);
1455 }
1456 else
1457 {
1458 if (prefix)
1459 {
1460 q = frag_more (2);
1461 *q++ = prefix;
1462 }
1463 else
1464 q = frag_more (1);
1465 *q = opcode^0x46;
1466 if (d)
1467 emit_byte (d, BFD_RELOC_Z80_DISP8);
1468 emit_byte (src, BFD_RELOC_8);
1469 }
1470 }
1471}
1472
1473static void
1474emit_ldreg (int dest, expressionS * src)
1475{
1476 char *q;
1477 int rnum;
1478
1479 switch (dest)
1480 {
1481 /* 8 Bit ld group: */
1482 case REG_I:
1483 case REG_R:
1484 if (src->X_md == 0 && src->X_op == O_register && src->X_add_number == REG_A)
1485 {
1486 q = frag_more (2);
1487 *q++ = 0xED;
1488 *q = (dest == REG_I) ? 0x47 : 0x4F;
1489 }
1490 else
1491 ill_op ();
1492 break;
1493
1494 case REG_A:
1495 if ((src->X_md) && src->X_op != O_register && src->X_op != O_md1)
1496 {
1497 q = frag_more (1);
1498 *q = 0x3A;
1499 emit_word (src);
1500 break;
1501 }
1502
1503 if ((src->X_md)
1504 && src->X_op == O_register
1505 && (src->X_add_number == REG_BC || src->X_add_number == REG_DE))
1506 {
1507 q = frag_more (1);
2cf402d6 1508 *q = 0x0A + ((src->X_add_number & 1) << 4);
3c9b82ba
NC
1509 break;
1510 }
1511
1512 if ((!src->X_md)
1513 && src->X_op == O_register
1514 && (src->X_add_number == REG_R || src->X_add_number == REG_I))
1515 {
1516 q = frag_more (2);
1517 *q++ = 0xED;
1518 *q = (src->X_add_number == REG_I) ? 0x57 : 0x5F;
1519 break;
1520 }
1521 /* Fall through. */
1522 case REG_B:
1523 case REG_C:
1524 case REG_D:
1525 case REG_E:
1526 emit_sx (0, 0x40 + (dest << 3), src);
1527 break;
1528
1529 case REG_H:
1530 case REG_L:
1531 if ((src->X_md == 0)
1532 && (src->X_op == O_register)
1533 && (src->X_add_number & R_INDEX))
1534 ill_op ();
1535 else
1536 emit_sx (0, 0x40 + (dest << 3), src);
1537 break;
1538
1539 case R_IX | REG_H:
1540 case R_IX | REG_L:
1541 case R_IY | REG_H:
1542 case R_IY | REG_L:
1543 if (src->X_md)
1544 {
1545 ill_op ();
1546 break;
1547 }
1548 check_mach (INS_UNDOC);
1549 if (src-> X_op == O_register)
1550 {
1551 rnum = src->X_add_number;
1552 if ((rnum & ~R_INDEX) < 8
1553 && ((rnum & R_INDEX) == (dest & R_INDEX)
1554 || ( (rnum & ~R_INDEX) != REG_H
1555 && (rnum & ~R_INDEX) != REG_L)))
1556 {
1557 q = frag_more (2);
1558 *q++ = (dest & R_IX) ? 0xDD : 0xFD;
1559 *q = 0x40 + ((dest & 0x07) << 3) + (rnum & 7);
1560 }
1561 else
1562 ill_op ();
1563 }
1564 else
1565 {
1566 q = frag_more (2);
1567 *q++ = (dest & R_IX) ? 0xDD : 0xFD;
1568 *q = 0x06 + ((dest & 0x07) << 3);
1569 emit_byte (src, BFD_RELOC_8);
1570 }
1571 break;
1572
1573 /* 16 Bit ld group: */
1574 case REG_SP:
1575 if (src->X_md == 0
1576 && src->X_op == O_register
1577 && REG_HL == (src->X_add_number &~ R_INDEX))
1578 {
1579 q = frag_more ((src->X_add_number & R_INDEX) ? 2 : 1);
1580 if (src->X_add_number & R_INDEX)
1581 *q++ = (src->X_add_number & R_IX) ? 0xDD : 0xFD;
1582 *q = 0xF9;
1583 break;
1584 }
1585 /* Fall through. */
1586 case REG_BC:
1587 case REG_DE:
7fbe7b46 1588 if (src->X_op == O_register || src->X_op == O_md1)
3c9b82ba
NC
1589 ill_op ();
1590 q = frag_more (src->X_md ? 2 : 1);
1591 if (src->X_md)
1592 {
1593 *q++ = 0xED;
1594 *q = 0x4B + ((dest & 3) << 4);
1595 }
1596 else
1597 *q = 0x01 + ((dest & 3) << 4);
1598 emit_word (src);
1599 break;
1600
1601 case REG_HL:
1602 case REG_HL | R_IX:
1603 case REG_HL | R_IY:
1604 if (src->X_op == O_register || src->X_op == O_md1)
1605 ill_op ();
1606 q = frag_more ((dest & R_INDEX) ? 2 : 1);
1607 if (dest & R_INDEX)
1608 * q ++ = (dest & R_IX) ? 0xDD : 0xFD;
1609 *q = (src->X_md) ? 0x2A : 0x21;
1610 emit_word (src);
1611 break;
1612
1613 case REG_AF:
1614 case REG_F:
1615 ill_op ();
1616 break;
1617
1618 default:
1619 abort ();
1620 }
1621}
1622
1623static const char *
1624emit_ld (char prefix_in ATTRIBUTE_UNUSED, char opcode_in ATTRIBUTE_UNUSED,
1625 const char * args)
1626{
1627 expressionS dst, src;
1628 const char *p;
1629 char *q;
1630 char prefix, opcode;
1631
1632 p = parse_exp (args, &dst);
1633 if (*p++ != ',')
9aff4b7a 1634 error (_("bad instruction syntax"));
3c9b82ba
NC
1635 p = parse_exp (p, &src);
1636
1637 switch (dst.X_op)
1638 {
1639 case O_md1:
761025be
AM
1640 {
1641 expressionS dst_offset = dst;
1642 dst_offset.X_op = O_symbol;
1643 dst_offset.X_add_number = 0;
1644 emit_ldxhl ((dst.X_add_number & R_IX) ? 0xDD : 0xFD, 0x70,
1645 &src, &dst_offset);
1646 }
3c9b82ba
NC
1647 break;
1648
1649 case O_register:
1650 if (dst.X_md)
1651 {
1652 switch (dst.X_add_number)
1653 {
1654 case REG_BC:
1655 case REG_DE:
1656 if (src.X_md == 0 && src.X_op == O_register && src.X_add_number == REG_A)
1657 {
1658 q = frag_more (1);
1659 *q = 0x02 + ( (dst.X_add_number & 1) << 4);
1660 }
1661 else
1662 ill_op ();
1663 break;
1664 case REG_HL:
1665 emit_ldxhl (0, 0x70, &src, NULL);
1666 break;
1667 default:
1668 ill_op ();
1669 }
1670 }
1671 else
1672 emit_ldreg (dst.X_add_number, &src);
1673 break;
1674
1675 default:
1676 if (src.X_md != 0 || src.X_op != O_register)
1677 ill_op ();
1678 prefix = opcode = 0;
1679 switch (src.X_add_number)
1680 {
1681 case REG_A:
1682 opcode = 0x32; break;
1683 case REG_BC: case REG_DE: case REG_SP:
1684 prefix = 0xED; opcode = 0x43 + ((src.X_add_number&3)<<4); break;
1685 case REG_HL:
1686 opcode = 0x22; break;
1687 case REG_HL|R_IX:
1688 prefix = 0xDD; opcode = 0x22; break;
1689 case REG_HL|R_IY:
1690 prefix = 0xFD; opcode = 0x22; break;
1691 }
1692 if (opcode)
1693 {
1694 q = frag_more (prefix?2:1);
1695 if (prefix)
1696 *q++ = prefix;
1697 *q = opcode;
1698 emit_word (&dst);
1699 }
1700 else
1701 ill_op ();
1702 }
1703 return p;
1704}
1705
134dcee5
AM
1706static void
1707emit_data (int size ATTRIBUTE_UNUSED)
3c9b82ba
NC
1708{
1709 const char *p, *q;
1710 char *u, quote;
1711 int cnt;
1712 expressionS exp;
1713
134dcee5
AM
1714 if (is_it_end_of_statement ())
1715 {
1716 demand_empty_rest_of_line ();
1717 return;
1718 }
1719 p = skip_space (input_line_pointer);
3c9b82ba 1720
134dcee5 1721 do
3c9b82ba
NC
1722 {
1723 if (*p == '\"' || *p == '\'')
1724 {
134dcee5
AM
1725 for (quote = *p, q = ++p, cnt = 0; *p && quote != *p; ++p, ++cnt)
1726 ;
1727 u = frag_more (cnt);
1728 memcpy (u, q, cnt);
1729 if (!*p)
1730 as_warn (_("unterminated string"));
1731 else
1732 p = skip_space (p+1);
3c9b82ba
NC
1733 }
1734 else
1735 {
1736 p = parse_exp (p, &exp);
1737 if (exp.X_op == O_md1 || exp.X_op == O_register)
1738 {
1739 ill_op ();
1740 break;
1741 }
1742 if (exp.X_md)
1743 as_warn (_("parentheses ignored"));
134dcee5 1744 emit_byte (&exp, BFD_RELOC_8);
3c9b82ba
NC
1745 p = skip_space (p);
1746 }
3c9b82ba 1747 }
134dcee5
AM
1748 while (*p++ == ',') ;
1749 input_line_pointer = (char *)(p-1);
3c9b82ba
NC
1750}
1751
1752static const char *
1753emit_mulub (char prefix ATTRIBUTE_UNUSED, char opcode, const char * args)
1754{
1755 const char *p;
1756
1757 p = skip_space (args);
1758 if (TOLOWER (*p++) != 'a' || *p++ != ',')
1759 ill_op ();
1760 else
1761 {
1762 char *q, reg;
1763
1764 reg = TOLOWER (*p++);
1765 switch (reg)
1766 {
1767 case 'b':
1768 case 'c':
1769 case 'd':
1770 case 'e':
1771 check_mach (INS_R800);
1772 if (!*skip_space (p))
1773 {
1774 q = frag_more (2);
1775 *q++ = prefix;
1776 *q = opcode + ((reg - 'b') << 3);
1777 break;
1778 }
1779 default:
1780 ill_op ();
1781 }
1782 }
1783 return p;
1784}
1785
1786static const char *
1787emit_muluw (char prefix ATTRIBUTE_UNUSED, char opcode, const char * args)
1788{
1789 const char *p;
1790
1791 p = skip_space (args);
1792 if (TOLOWER (*p++) != 'h' || TOLOWER (*p++) != 'l' || *p++ != ',')
1793 ill_op ();
1794 else
1795 {
1796 expressionS reg;
1797 char *q;
1798
1799 p = parse_exp (p, & reg);
1800
1801 if ((!reg.X_md) && reg.X_op == O_register)
1802 switch (reg.X_add_number)
1803 {
1804 case REG_BC:
1805 case REG_SP:
1806 check_mach (INS_R800);
1807 q = frag_more (2);
1808 *q++ = prefix;
1809 *q = opcode + ((reg.X_add_number & 3) << 4);
1810 break;
1811 default:
1812 ill_op ();
1813 }
1814 }
1815 return p;
1816}
1817
134dcee5
AM
1818/* Port specific pseudo ops. */
1819const pseudo_typeS md_pseudo_table[] =
1820{
1821 { "db" , emit_data, 1},
1822 { "d24", cons, 3},
1823 { "d32", cons, 4},
1824 { "def24", cons, 3},
1825 { "def32", cons, 4},
3739860c 1826 { "defb", emit_data, 1},
134dcee5
AM
1827 { "defs", s_space, 1}, /* Synonym for ds on some assemblers. */
1828 { "defw", cons, 2},
1829 { "ds", s_space, 1}, /* Fill with bytes rather than words. */
1830 { "dw", cons, 2},
1831 { "psect", obj_coff_section, 0}, /* TODO: Translate attributes. */
1832 { "set", 0, 0}, /* Real instruction on z80. */
1833 { NULL, 0, 0 }
1834} ;
1835
3c9b82ba
NC
1836static table_t instab[] =
1837{
1838 { "adc", 0x88, 0x4A, emit_adc },
1839 { "add", 0x80, 0x09, emit_add },
1840 { "and", 0x00, 0xA0, emit_s },
1841 { "bit", 0xCB, 0x40, emit_bit },
1842 { "call", 0xCD, 0xC4, emit_jpcc },
1843 { "ccf", 0x00, 0x3F, emit_insn },
1844 { "cp", 0x00, 0xB8, emit_s },
1845 { "cpd", 0xED, 0xA9, emit_insn },
1846 { "cpdr", 0xED, 0xB9, emit_insn },
1847 { "cpi", 0xED, 0xA1, emit_insn },
1848 { "cpir", 0xED, 0xB1, emit_insn },
1849 { "cpl", 0x00, 0x2F, emit_insn },
1850 { "daa", 0x00, 0x27, emit_insn },
3c9b82ba 1851 { "dec", 0x0B, 0x05, emit_incdec },
3c9b82ba
NC
1852 { "di", 0x00, 0xF3, emit_insn },
1853 { "djnz", 0x00, 0x10, emit_jr },
3c9b82ba
NC
1854 { "ei", 0x00, 0xFB, emit_insn },
1855 { "ex", 0x00, 0x00, emit_ex},
1856 { "exx", 0x00, 0xD9, emit_insn },
1857 { "halt", 0x00, 0x76, emit_insn },
1858 { "im", 0xED, 0x46, emit_im },
1859 { "in", 0x00, 0x00, emit_in },
1860 { "inc", 0x03, 0x04, emit_incdec },
1861 { "ind", 0xED, 0xAA, emit_insn },
1862 { "indr", 0xED, 0xBA, emit_insn },
1863 { "ini", 0xED, 0xA2, emit_insn },
1864 { "inir", 0xED, 0xB2, emit_insn },
1865 { "jp", 0xC3, 0xC2, emit_jpcc },
1866 { "jr", 0x18, 0x20, emit_jrcc },
1867 { "ld", 0x00, 0x00, emit_ld },
1868 { "ldd", 0xED, 0xA8, emit_insn },
1869 { "lddr", 0xED, 0xB8, emit_insn },
1870 { "ldi", 0xED, 0xA0, emit_insn },
1871 { "ldir", 0xED, 0xB0, emit_insn },
1872 { "mulub", 0xED, 0xC5, emit_mulub }, /* R800 only. */
1873 { "muluw", 0xED, 0xC3, emit_muluw }, /* R800 only. */
1874 { "neg", 0xed, 0x44, emit_insn },
1875 { "nop", 0x00, 0x00, emit_insn },
1876 { "or", 0x00, 0xB0, emit_s },
1877 { "otdr", 0xED, 0xBB, emit_insn },
1878 { "otir", 0xED, 0xB3, emit_insn },
1879 { "out", 0x00, 0x00, emit_out },
1880 { "outd", 0xED, 0xAB, emit_insn },
1881 { "outi", 0xED, 0xA3, emit_insn },
1882 { "pop", 0x00, 0xC1, emit_pop },
1883 { "push", 0x00, 0xC5, emit_pop },
1884 { "res", 0xCB, 0x80, emit_bit },
1885 { "ret", 0xC9, 0xC0, emit_retcc },
1886 { "reti", 0xED, 0x4D, emit_insn },
1887 { "retn", 0xED, 0x45, emit_insn },
1888 { "rl", 0xCB, 0x10, emit_mr },
1889 { "rla", 0x00, 0x17, emit_insn },
1890 { "rlc", 0xCB, 0x00, emit_mr },
1891 { "rlca", 0x00, 0x07, emit_insn },
1892 { "rld", 0xED, 0x6F, emit_insn },
1893 { "rr", 0xCB, 0x18, emit_mr },
1894 { "rra", 0x00, 0x1F, emit_insn },
1895 { "rrc", 0xCB, 0x08, emit_mr },
1896 { "rrca", 0x00, 0x0F, emit_insn },
1897 { "rrd", 0xED, 0x67, emit_insn },
1898 { "rst", 0x00, 0xC7, emit_rst},
1899 { "sbc", 0x98, 0x42, emit_adc },
1900 { "scf", 0x00, 0x37, emit_insn },
1901 { "set", 0xCB, 0xC0, emit_bit },
1902 { "sla", 0xCB, 0x20, emit_mr },
1903 { "sli", 0xCB, 0x30, emit_mr },
1904 { "sll", 0xCB, 0x30, emit_mr },
1905 { "sra", 0xCB, 0x28, emit_mr },
1906 { "srl", 0xCB, 0x38, emit_mr },
1907 { "sub", 0x00, 0x90, emit_s },
1908 { "xor", 0x00, 0xA8, emit_s },
1909} ;
1910
1911void
1912md_assemble (char* str)
1913{
1914 const char *p;
1915 char * old_ptr;
1916 int i;
1917 table_t *insp;
1918
1919 err_flag = 0;
1920 old_ptr = input_line_pointer;
1921 p = skip_space (str);
1922 for (i = 0; (i < BUFLEN) && (ISALPHA (*p));)
1923 buf[i++] = TOLOWER (*p++);
1924
134dcee5
AM
1925 if (i == BUFLEN)
1926 {
1927 buf[BUFLEN-3] = buf[BUFLEN-2] = '.'; /* Mark opcode as abbreviated. */
1928 buf[BUFLEN-1] = 0;
1929 as_bad (_("Unknown instruction '%s'"), buf);
1930 }
1931 else if ((*p) && (!ISSPACE (*p)))
1932 as_bad (_("syntax error"));
3739860c 1933 else
3c9b82ba 1934 {
134dcee5 1935 buf[i] = 0;
3c9b82ba 1936 p = skip_space (p);
134dcee5 1937 key = buf;
3739860c 1938
134dcee5
AM
1939 insp = bsearch (&key, instab, ARRAY_SIZE (instab),
1940 sizeof (instab[0]), key_cmp);
1941 if (!insp)
1942 as_bad (_("Unknown instruction '%s'"), buf);
1943 else
1944 {
1945 p = insp->fp (insp->prefix, insp->opcode, p);
1946 p = skip_space (p);
1947 if ((!err_flag) && *p)
1948 as_bad (_("junk at end of line, first unrecognized character is `%c'"),
1949 *p);
1950 }
3c9b82ba
NC
1951 }
1952 input_line_pointer = old_ptr;
1953}
1954
1955void
1956md_apply_fix (fixS * fixP, valueT* valP, segT seg ATTRIBUTE_UNUSED)
1957{
1958 long val = * (long *) valP;
de6d4f05 1959 char *p_lit = fixP->fx_where + fixP->fx_frag->fr_literal;
3c9b82ba
NC
1960
1961 switch (fixP->fx_r_type)
1962 {
1963 case BFD_RELOC_8_PCREL:
1964 if (fixP->fx_addsy)
1965 {
1966 fixP->fx_no_overflow = 1;
1967 fixP->fx_done = 0;
1968 }
1969 else
1970 {
1971 fixP->fx_no_overflow = (-128 <= val && val < 128);
1972 if (!fixP->fx_no_overflow)
1973 as_bad_where (fixP->fx_file, fixP->fx_line,
1974 _("relative jump out of range"));
de6d4f05 1975 *p_lit++ = val;
3c9b82ba
NC
1976 fixP->fx_done = 1;
1977 }
1978 break;
1979
1980 case BFD_RELOC_Z80_DISP8:
1981 if (fixP->fx_addsy)
1982 {
1983 fixP->fx_no_overflow = 1;
1984 fixP->fx_done = 0;
1985 }
1986 else
1987 {
1988 fixP->fx_no_overflow = (-128 <= val && val < 128);
1989 if (!fixP->fx_no_overflow)
1990 as_bad_where (fixP->fx_file, fixP->fx_line,
1991 _("index offset out of range"));
de6d4f05 1992 *p_lit++ = val;
3c9b82ba
NC
1993 fixP->fx_done = 1;
1994 }
1995 break;
1996
1997 case BFD_RELOC_8:
1998 if (val > 255 || val < -128)
1999 as_warn_where (fixP->fx_file, fixP->fx_line, _("overflow"));
de6d4f05 2000 *p_lit++ = val;
3739860c 2001 fixP->fx_no_overflow = 1;
3c9b82ba
NC
2002 if (fixP->fx_addsy == NULL)
2003 fixP->fx_done = 1;
2004 break;
2005
2006 case BFD_RELOC_16:
de6d4f05
AM
2007 *p_lit++ = val;
2008 *p_lit++ = (val >> 8);
3739860c 2009 fixP->fx_no_overflow = 1;
134dcee5
AM
2010 if (fixP->fx_addsy == NULL)
2011 fixP->fx_done = 1;
2012 break;
2013
2014 case BFD_RELOC_24: /* Def24 may produce this. */
de6d4f05
AM
2015 *p_lit++ = val;
2016 *p_lit++ = (val >> 8);
2017 *p_lit++ = (val >> 16);
3739860c 2018 fixP->fx_no_overflow = 1;
3c9b82ba
NC
2019 if (fixP->fx_addsy == NULL)
2020 fixP->fx_done = 1;
2021 break;
2022
134dcee5 2023 case BFD_RELOC_32: /* Def32 and .long may produce this. */
de6d4f05
AM
2024 *p_lit++ = val;
2025 *p_lit++ = (val >> 8);
2026 *p_lit++ = (val >> 16);
2027 *p_lit++ = (val >> 24);
3c9b82ba
NC
2028 if (fixP->fx_addsy == NULL)
2029 fixP->fx_done = 1;
2030 break;
2031
2032 default:
2033 printf (_("md_apply_fix: unknown r_type 0x%x\n"), fixP->fx_r_type);
2034 abort ();
2035 }
2036}
2037
2038/* GAS will call this to generate a reloc. GAS will pass the
2039 resulting reloc to `bfd_install_relocation'. This currently works
2040 poorly, as `bfd_install_relocation' often does the wrong thing, and
2041 instances of `tc_gen_reloc' have been written to work around the
2042 problems, which in turns makes it difficult to fix
2043 `bfd_install_relocation'. */
2044
2045/* If while processing a fixup, a reloc really
2046 needs to be created then it is done here. */
2047
2048arelent *
2049tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED , fixS *fixp)
2050{
2051 arelent *reloc;
2052
2053 if (! bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type))
2054 {
2055 as_bad_where (fixp->fx_file, fixp->fx_line,
2056 _("reloc %d not supported by object file format"),
2057 (int) fixp->fx_r_type);
2058 return NULL;
2059 }
2060
2061 reloc = xmalloc (sizeof (arelent));
2062 reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
2063 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
2064 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
2065 reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
2066 reloc->addend = fixp->fx_offset;
2067
2068 return reloc;
2069}