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