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