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