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