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