1 /* tc-z80.c -- Assemble code for the Zilog Z80 and ASCII R800
2 Copyright 2005 Free Software Foundation, Inc.
5 This file is part of GAS, the GNU Assembler.
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
9 the Free Software Foundation; either version 2, or (at your option)
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.
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
25 #include "safe-ctype.h"
28 #include "libiberty.h"
30 /* Exported constants. */
31 const char comment_chars[] = ";\0";
32 const char line_comment_chars[] = "#;\0";
33 const char line_separator_chars[] = "\0";
34 const char EXP_CHARS[] = "eE\0";
35 const char FLT_CHARS[] = "RrFf\0";
37 /* For machine specific options. */
38 const char * md_shortopts = ""; /* None yet. */
42 OPTION_MACH_Z80 = OPTION_MD_BASE,
57 struct option md_longopts[] =
59 { "z80", no_argument, NULL, OPTION_MACH_Z80},
60 { "r800", no_argument, NULL, OPTION_MACH_R800},
61 { "ignore-undocumented-instructions", no_argument, NULL, OPTION_MACH_IUD },
62 { "Wnud", no_argument, NULL, OPTION_MACH_IUD },
63 { "warn-undocumented-instructions", no_argument, NULL, OPTION_MACH_WUD },
64 { "Wud", no_argument, NULL, OPTION_MACH_WUD },
65 { "forbid-undocumented-instructions", no_argument, NULL, OPTION_MACH_FUD },
66 { "Fud", no_argument, NULL, OPTION_MACH_FUD },
67 { "ignore-unportable-instructions", no_argument, NULL, OPTION_MACH_IUP },
68 { "Wnup", no_argument, NULL, OPTION_MACH_IUP },
69 { "warn-unportable-instructions", no_argument, NULL, OPTION_MACH_WUP },
70 { "Wup", no_argument, NULL, OPTION_MACH_WUP },
71 { "forbid-unportable-instructions", no_argument, NULL, OPTION_MACH_FUP },
72 { "Fup", no_argument, NULL, OPTION_MACH_FUP },
74 { NULL, no_argument, NULL, 0 }
77 size_t md_longopts_size = sizeof (md_longopts);
79 extern int coff_flags;
80 /* Instruction classes that silently assembled. */
81 static int ins_ok = INS_Z80 | INS_UNDOC;
82 /* Instruction classes that generate errors. */
83 static int ins_err = INS_R800;
84 /* Instruction classes actually used, determines machine type. */
85 static int ins_used = INS_Z80;
88 md_parse_option (int c, char* arg ATTRIBUTE_UNUSED)
98 case OPTION_MACH_R800:
99 ins_ok = INS_Z80 | INS_UNDOC | INS_R800;
100 ins_err = INS_UNPORT;
102 case OPTION_MACH_IUD:
104 ins_err &= ~INS_UNDOC;
106 case OPTION_MACH_IUP:
107 ins_ok |= INS_UNDOC | INS_UNPORT;
108 ins_err &= ~(INS_UNDOC | INS_UNPORT);
110 case OPTION_MACH_WUD:
111 if ((ins_ok & INS_R800) == 0)
113 ins_ok &= ~(INS_UNDOC|INS_UNPORT);
114 ins_err &= ~INS_UNDOC;
117 case OPTION_MACH_WUP:
118 ins_ok &= ~INS_UNPORT;
119 ins_err &= ~(INS_UNDOC|INS_UNPORT);
121 case OPTION_MACH_FUD:
122 if ((ins_ok & INS_R800) == 0)
124 ins_ok &= (INS_UNDOC | INS_UNPORT);
125 ins_err |= INS_UNDOC | INS_UNPORT;
128 case OPTION_MACH_FUP:
129 ins_ok &= ~INS_UNPORT;
130 ins_err |= INS_UNPORT;
138 md_show_usage (FILE * f)
141 CPU model/instruction set options:\n\
143 -z80\t\t assemble for Z80\n\
144 -ignore-undocumented-instructions\n\
146 \tsilently assemble undocumented Z80-instructions that work on R800\n\
147 -ignore-unportable-instructions\n\
149 \tsilently assemble all undocumented Z80-instructions\n\
150 -warn-undocumented-instructions\n\
152 \tissue warnings for undocumented Z80-instructions that work on R800\n\
153 -warn-unportable-instructions\n\
155 \tissue warnings for other undocumented Z80-instructions\n\
156 -forbid-undocumented-instructions\n\
158 \ttreat all undocumented z80-instructions as errors\n\
159 -forbid-unportable-instructions\n\
161 \ttreat undocumented z80-instructions that do not work on R800 as errors\n\
162 -r800\t assemble for R800\n\n\
163 Default: -z80 -ignore-undocument-instructions -warn-unportable-instructions.\n");
166 static symbolS * zero;
174 p = input_line_pointer;
175 input_line_pointer = "0";
178 input_line_pointer = p;
179 zero = make_expr_symbol (& nul);
180 /* We do not use relaxation (yet). */
189 if (ins_used & (INS_UNPORT | INS_R800))
190 ins_used |= INS_UNDOC;
195 mach_type = bfd_mach_z80strict;
197 case INS_Z80|INS_UNDOC:
198 mach_type = bfd_mach_z80;
200 case INS_Z80|INS_UNDOC|INS_UNPORT:
201 mach_type = bfd_mach_z80full;
203 case INS_Z80|INS_UNDOC|INS_R800:
204 mach_type = bfd_mach_r800;
210 bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach_type);
213 /* Port specific features. */
214 const pseudo_typeS md_pseudo_table[] =
216 { "defs", s_space, 1}, /* Synonym for ds on some assemblers. */
217 { "ds", s_space, 1}, /* Fill with bytes rather than words. */
218 { "psect", obj_coff_section, 0}, /* TODO: Translate attributes. */
219 { "set", 0, 0}, /* Real instruction on z80. */
224 skip_space (const char *s)
226 while (*s == ' ' || *s == '\t')
231 /* A non-zero return-value causes a continue in the
232 function read_a_source_file () in ../read.c. */
234 z80_start_line_hook (void)
239 /* Convert one character constants. */
240 for (p = input_line_pointer; *p && *p != '\n'; ++p)
245 if (p[1] != 0 && p[1] != '\'' && p[2] == '\'')
247 snprintf (buf, 4, "%3d", (unsigned char)p[1]);
254 for (quote = *p++; quote != *p && '\n' != *p; ++p)
258 as_bad (_("-- unterminated string"));
259 ignore_rest_of_line ();
265 /* Check for <label>[:] (EQU|DEFL) <value>. */
266 if (is_name_beginner (*input_line_pointer))
268 char c, *rest, *line_start;
271 line_start = input_line_pointer;
276 c = get_symbol_end ();
277 rest = input_line_pointer + 1;
281 if (*rest == ' ' || *rest == '\t')
283 if (strncasecmp (rest, "EQU", 3) == 0)
285 else if (strncasecmp (rest, "DEFL", 4) == 0)
289 if (len && (rest[len] == ' ' || rest[len] == '\t'))
291 /* Handle assignment here. */
292 input_line_pointer = rest + len;
293 if (line_start[-1] == '\n')
294 bump_line_counters ();
295 /* Most Z80 assemblers require the first definition of a
296 label to use "EQU" and redefinitions to have "DEFL".
297 That does not fit the way GNU as deals with labels, so
298 GNU as is more permissive. */
299 equals (line_start, TRUE);
304 /* Restore line and pointer. */
305 *input_line_pointer = c;
306 input_line_pointer = line_start;
313 md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
319 md_atof (int type ATTRIBUTE_UNUSED, char *litP ATTRIBUTE_UNUSED,
320 int *sizeP ATTRIBUTE_UNUSED)
322 return _("floating point numbers are not implemented");
326 md_section_align (segT seg ATTRIBUTE_UNUSED, valueT size)
332 md_pcrel_from (fixS * fixp)
334 return fixp->fx_where +
335 fixp->fx_frag->fr_address + 1;
338 typedef const char * (asfunc)(char, char, const char*);
340 typedef struct _table_t
348 /* Compares the key for structs that start with a char * to the key. */
350 key_cmp (const void * a, const void * b)
352 const char *str_a, *str_b;
354 str_a = *((const char**)a);
355 str_b = *((const char**)b);
356 return strcmp (str_a, str_b);
359 #define BUFLEN 8 /* Large enough for any keyword. */
362 const char *key = buf;
364 #define R_STACKABLE (0x80)
365 #define R_ARITH (0x40)
368 #define R_INDEX (R_IX | R_IY)
377 #define REG_F (6 | 8)
381 #define REG_AF (3 | R_STACKABLE)
382 #define REG_BC (0 | R_STACKABLE | R_ARITH)
383 #define REG_DE (1 | R_STACKABLE | R_ARITH)
384 #define REG_HL (2 | R_STACKABLE | R_ARITH)
385 #define REG_SP (3 | R_ARITH)
387 static const struct reg_entry
405 {"ix", REG_HL | R_IX },
406 {"ixh",REG_H | R_IX },
407 {"ixl",REG_L | R_IX },
408 {"iy", REG_HL | R_IY },
409 {"iyh",REG_H | R_IY },
410 {"iyl",REG_L | R_IY },
416 /* Prevent an error on a line from also generating
417 a "junk at end of line" error message. */
418 static char err_flag;
421 error (const char * message)
430 error (_("illegal operand"));
434 wrong_mach (int ins_type)
441 p = "undocumented instruction";
444 p = "instruction does not work on R800";
447 p = "instruction only works R800";
450 p = 0; /* Not reachables. */
453 if (ins_type & ins_err)
460 check_mach (int ins_type)
462 if ((ins_type & ins_ok) == 0)
463 wrong_mach (ins_type);
464 ins_used |= ins_type;
467 /* This function tries to subtract two symbols, the generic code does
468 that too, but this function tries harder.
469 The behaviour of this function is not altered by extra
470 fragmentations caused by the code to produce listings. */
472 z80_optimize_expr (expressionS *resultP, operatorT left_op,
476 fragS *lfrag, *rfrag, *cur;
479 if (left_op == O_subtract
480 && right->X_op == O_symbol
481 && resultP->X_op == O_symbol)
483 lfrag = symbol_get_frag (resultP->X_add_symbol);
484 rfrag = symbol_get_frag (right->X_add_symbol);
486 if (S_GET_SEGMENT (right->X_add_symbol) != undefined_section
487 && (S_GET_SEGMENT (right->X_add_symbol)
488 == S_GET_SEGMENT (resultP->X_add_symbol)))
490 for (swap = 0; (res == 0) && (swap < 2); ++swap)
501 /* Now som == cur->fr_address - rfrag->address, except
502 the latter may not have been computed yet. */
503 for (som = 0; cur && cur != lfrag; cur = cur->fr_next)
505 if (cur->fr_type == rs_fill) /* Is the size fized? */
506 som += cur->fr_fix+cur->fr_offset*cur->fr_var;
513 resultP->X_add_number -= right->X_add_number;
514 resultP->X_add_number
515 += (S_GET_VALUE (resultP->X_add_symbol)
516 - S_GET_VALUE (right->X_add_symbol));
517 som -= lfrag->fr_address - rfrag->fr_address;
518 /* Correct the result if the fr_address
519 fields are not computed yet. */
520 resultP->X_add_number += (swap ? -som : som);
521 resultP->X_op = O_constant;
522 resultP->X_add_symbol = 0;
531 /* Check whether an expression is indirect. */
533 is_indir (const char *s)
539 /* Indirection is indicated with parentheses. */
542 for (p = s, depth = 0; *p && *p != ','; ++p)
548 for (quote = *p++; quote != *p && *p != '\n'; ++p)
549 if (*p == '\\' && p[1])
559 p = skip_space (p + 1);
565 error (_("mismatched parentheses"));
571 error (_("mismatched parentheses"));
576 /* Parse general expression. */
578 parse_exp2 (const char *s, expressionS *op, segT *pseg)
583 const struct reg_entry * regp;
587 op->X_md = indir = is_indir (p);
589 p = skip_space (p + 1);
591 for (i = 0; i < BUFLEN; ++i)
593 if (!ISALPHA (p[i])) /* Register names consist of letters only. */
595 buf[i] = TOLOWER (p[i]);
598 if ((i < BUFLEN) && ((p[i] == 0) || (strchr (")+-, \t", p[i]))))
601 regp = bsearch (& key, regtable, ARRAY_SIZE (regtable),
602 sizeof (regtable[0]), key_cmp);
606 op->X_add_symbol = op->X_op_symbol = 0;
607 op->X_add_number = regp->number;
608 op->X_op = O_register;
609 p += strlen (regp->name);
615 if ((regp->number & R_INDEX) && (regp->number & R_ARITH))
619 if ((*p == '+') || (*p == '-'))
621 input_line_pointer = (char*) p;
622 expression (& offset);
623 p = skip_space (input_line_pointer);
625 error (_("bad offset expression syntax"));
628 op->X_add_symbol = make_expr_symbol (& offset);
632 /* We treat (i[xy]) as (i[xy]+0), which is how it will
633 end up anyway, unless we're processing jp (i[xy]). */
634 op->X_add_symbol = zero;
639 if ((*p == 0) || (*p == ','))
643 /* Not an argument involving a register; use the generic parser. */
644 input_line_pointer = (char*) s ;
645 *pseg = expression (op);
646 if (op->X_op == O_absent)
647 error (_("missing operand"));
648 if (op->X_op == O_illegal)
649 error (_("bad expression syntax"));
650 return input_line_pointer;
654 parse_exp (const char *s, expressionS *op)
657 return parse_exp2 (s, op, & dummy);
660 /* Condition codes, including some synonyms provided by HiTech zas. */
661 static const struct reg_entry cc_tab[] =
679 /* Parse condition code. */
681 parse_cc (const char *s, char * op)
685 struct reg_entry * cc_p;
687 for (i = 0; i < BUFLEN; ++i)
689 if (!ISALPHA (s[i])) /* Condition codes consist of letters only. */
691 buf[i] = TOLOWER (s[i]);
695 && ((s[i] == 0) || (s[i] == ',')))
698 cc_p = bsearch (&key, cc_tab, ARRAY_SIZE (cc_tab),
699 sizeof (cc_tab[0]), key_cmp);
716 emit_insn (char prefix, char opcode, const char * args)
732 emit_byte (expressionS * val, bfd_reloc_code_real_type r_type)
739 *p = val->X_add_number;
740 if ((r_type != BFD_RELOC_8_PCREL) && (val->X_op == O_constant))
743 hi = (BFD_RELOC_8 == r_type) ? 255 : 127;
745 if ((val->X_add_number < lo) || (val->X_add_number > hi))
747 if (r_type == BFD_RELOC_Z80_DISP8)
748 as_bad (_("offset too large"));
750 as_warn (_("overflow"));
755 fixp = fix_new_exp (frag_now, p - frag_now->fr_literal, 1, val,
756 (r_type == BFD_RELOC_8_PCREL) ? TRUE : FALSE, r_type);
757 /* FIXME : Process constant offsets immediately. */
762 emit_word (expressionS * val)
767 if ( (val->X_op == O_register)
768 || (val->X_op == O_md1))
772 *p = val->X_add_number;
773 p[1] = (val->X_add_number>>8);
774 if (val->X_op != O_constant)
775 fix_new_exp (frag_now, p - frag_now->fr_literal, 2,
776 val, FALSE, BFD_RELOC_16);
781 emit_mx (char prefix, char opcode, int shift, expressionS * arg)
782 /* The operand m may be r, (hl), (ix+d), (iy+d),
783 if 0 == prefix m may also be ixl, ixh, iyl, iyh. */
788 rnum = arg->X_add_number;
804 if ((prefix == 0) && (rnum & R_INDEX))
806 prefix = (rnum & R_IX) ? 0xDD : 0xFD;
807 check_mach (INS_UNDOC);
816 q = frag_more (prefix ? 2 : 1);
819 * q ++ = opcode + (rnum << shift);
823 *q++ = (rnum & R_IX) ? 0xDD : 0xFD;
824 *q = (prefix) ? prefix : (opcode + (6 << shift));
825 emit_byte (symbol_get_value_expression (arg->X_add_symbol),
826 BFD_RELOC_Z80_DISP8);
830 *q = opcode+(6<<shift);
838 /* The operand m may be r, (hl), (ix+d), (iy+d),
839 if 0 = prefix m may also be ixl, ixh, iyl, iyh. */
841 emit_m (char prefix, char opcode, const char *args)
846 p = parse_exp (args, &arg_m);
851 emit_mx (prefix, opcode, 0, &arg_m);
859 /* The operand m may be as above or one of the undocumented
860 combinations (ix+d),r and (iy+d),r (if unportable instructions
863 emit_mr (char prefix, char opcode, const char *args)
865 expressionS arg_m, arg_r;
868 p = parse_exp (args, & arg_m);
875 p = parse_exp (p + 1, & arg_r);
877 if ((arg_r.X_md == 0)
878 && (arg_r.X_op == O_register)
879 && (arg_r.X_add_number < 8))
880 opcode += arg_r.X_add_number-6; /* Emit_mx () will add 6. */
886 check_mach (INS_UNPORT);
889 emit_mx (prefix, opcode, 0, & arg_m);
898 emit_sx (char prefix, char opcode, expressionS * arg_p)
906 emit_mx (prefix, opcode, 0, arg_p);
913 q = frag_more (prefix ? 2 : 1);
917 emit_byte (arg_p, BFD_RELOC_8);
922 /* The operand s may be r, (hl), (ix+d), (iy+d), n. */
924 emit_s (char prefix, char opcode, const char *args)
929 p = parse_exp (args, & arg_s);
930 emit_sx (prefix, opcode, & arg_s);
935 emit_call (char prefix ATTRIBUTE_UNUSED, char opcode, const char * args)
938 const char *p; char *q;
940 p = parse_exp (args, &addr);
952 /* Operand may be rr, r, (hl), (ix+d), (iy+d). */
954 emit_incdec (char prefix, char opcode, const char * args)
958 const char *p; char *q;
960 p = parse_exp (args, &operand);
961 rnum = operand.X_add_number;
963 && (operand.X_op == O_register)
966 q = frag_more ((rnum & R_INDEX) ? 2 : 1);
968 *q++ = (rnum & R_IX) ? 0xDD : 0xFD;
969 *q = prefix + ((rnum & 3) << 4);
973 if ((operand.X_op == O_md1) || (operand.X_op == O_register))
974 emit_mx (0, opcode, 3, & operand);
982 emit_jr (char prefix ATTRIBUTE_UNUSED, char opcode, const char * args)
988 p = parse_exp (args, &addr);
995 emit_byte (&addr, BFD_RELOC_8_PCREL);
1001 emit_jp (char prefix, char opcode, const char * args)
1008 p = parse_exp (args, & addr);
1011 rnum = addr.X_add_number;
1012 if ((addr.X_op == O_register && (rnum & ~R_INDEX) == REG_HL)
1013 /* An operand (i[xy]) would have been rewritten to (i[xy]+0)
1015 || (addr.X_op == O_md1 && addr.X_add_symbol == zero))
1017 q = frag_more ((rnum & R_INDEX) ? 2 : 1);
1019 *q++ = (rnum & R_IX) ? 0xDD : 0xFD;
1035 emit_im (char prefix, char opcode, const char * args)
1041 p = parse_exp (args, & mode);
1042 if (mode.X_md || (mode.X_op != O_constant))
1045 switch (mode.X_add_number)
1049 ++mode.X_add_number;
1054 *q = opcode + 8*mode.X_add_number;
1063 emit_pop (char prefix ATTRIBUTE_UNUSED, char opcode, const char * args)
1069 p = parse_exp (args, & regp);
1071 && (regp.X_op == O_register)
1072 && (regp.X_add_number & R_STACKABLE))
1076 rnum = regp.X_add_number;
1080 *q++ = (rnum&R_IX)?0xDD:0xFD;
1084 *q = opcode + ((rnum & 3) << 4);
1093 emit_retcc (char prefix ATTRIBUTE_UNUSED, char opcode, const char * args)
1098 p = parse_cc (args, &cc);
1104 return p ? p : args;
1108 emit_adc (char prefix, char opcode, const char * args)
1115 p = parse_exp (args, &term);
1118 error (_("bad intruction syntax"));
1122 if ((term.X_md) || (term.X_op != O_register))
1125 switch (term.X_add_number)
1128 p = emit_s (0, prefix, p);
1131 p = parse_exp (p, &term);
1132 if ((!term.X_md) && (term.X_op == O_register))
1134 rnum = term.X_add_number;
1135 if (R_ARITH == (rnum & (R_ARITH | R_INDEX)))
1139 *q = opcode + ((rnum & 3) << 4);
1151 emit_add (char prefix, char opcode, const char * args)
1158 p = parse_exp (args, &term);
1161 error (_("bad intruction syntax"));
1165 if ((term.X_md) || (term.X_op != O_register))
1168 switch (term.X_add_number & ~R_INDEX)
1171 p = emit_s (0, prefix, p);
1174 lhs = term.X_add_number;
1175 p = parse_exp (p, &term);
1176 if ((!term.X_md) && (term.X_op == O_register))
1178 rhs = term.X_add_number;
1180 && ((rhs == lhs) || ((rhs & ~R_INDEX) != REG_HL)))
1182 q = frag_more ((lhs & R_INDEX) ? 2 : 1);
1184 *q++ = (lhs & R_IX) ? 0xDD : 0xFD;
1185 *q = opcode + ((rhs & 3) << 4);
1197 emit_bit (char prefix, char opcode, const char * args)
1203 p = parse_exp (args, &b);
1205 error (_("bad intruction syntax"));
1207 bn = b.X_add_number;
1209 && (b.X_op == O_constant)
1214 /* Bit : no optional third operand. */
1215 p = emit_m (prefix, opcode + (bn << 3), p);
1217 /* Set, res : resulting byte can be copied to register. */
1218 p = emit_mr (prefix, opcode + (bn << 3), p);
1226 emit_jpcc (char prefix, char opcode, const char * args)
1231 p = parse_cc (args, & cc);
1232 if (p && *p++ == ',')
1233 p = emit_call (0, opcode + cc, p);
1235 p = (prefix == (char)0xC3)
1236 ? emit_jp (0xE9, prefix, args)
1237 : emit_call (0, prefix, args);
1242 emit_jrcc (char prefix, char opcode, const char * args)
1247 p = parse_cc (args, &cc);
1248 if (p && *p++ == ',')
1251 error (_("condition code invalid for jr"));
1253 p = emit_jr (0, opcode + cc, p);
1256 p = emit_jr (0, prefix, args);
1262 emit_ex (char prefix_in ATTRIBUTE_UNUSED,
1263 char opcode_in ATTRIBUTE_UNUSED, const char * args)
1267 char prefix, opcode;
1269 p = parse_exp (args, &op);
1273 error (_("bad instruction syntax"));
1277 prefix = opcode = 0;
1278 if (op.X_op == O_register)
1279 switch (op.X_add_number | (op.X_md ? 0x8000 : 0))
1282 if (TOLOWER (*p++) == 'a' && TOLOWER (*p++) == 'f')
1284 /* The scrubber changes '\'' to '`' in this context. */
1291 if (TOLOWER (*p++) == 'h' && TOLOWER (*p++) == 'l')
1295 p = parse_exp (p, & op);
1296 if (op.X_op == O_register
1298 && (op.X_add_number & ~R_INDEX) == REG_HL)
1301 if (R_INDEX & op.X_add_number)
1302 prefix = (R_IX & op.X_add_number) ? 0xDD : 0xFD;
1307 emit_insn (prefix, opcode, p);
1315 emit_in (char prefix ATTRIBUTE_UNUSED, char opcode ATTRIBUTE_UNUSED,
1318 expressionS reg, port;
1322 p = parse_exp (args, ®);
1325 error (_("bad intruction syntax"));
1329 p = parse_exp (p, &port);
1331 && reg.X_op == O_register
1332 && (reg.X_add_number <= 7 || reg.X_add_number == REG_F)
1335 if (port.X_op != O_md1 && port.X_op != O_register)
1337 if (REG_A == reg.X_add_number)
1341 emit_byte (&port, BFD_RELOC_8);
1348 if (port.X_add_number == REG_C)
1350 if (reg.X_add_number == REG_F)
1351 check_mach (INS_UNDOC);
1356 *q = 0x40|((reg.X_add_number&7)<<3);
1369 emit_out (char prefix ATTRIBUTE_UNUSED, char opcode ATTRIBUTE_UNUSED,
1372 expressionS reg, port;
1376 p = parse_exp (args, & port);
1379 error (_("bad intruction syntax"));
1382 p = parse_exp (p, ®);
1384 { ill_op (); return p; }
1385 /* Allow "out (c), 0" as unportable instruction. */
1386 if (reg.X_op == O_constant && reg.X_add_number == 0)
1388 check_mach (INS_UNPORT);
1389 reg.X_op = O_register;
1390 reg.X_add_number = 6;
1393 || reg.X_op != O_register
1394 || reg.X_add_number > 7)
1397 if (port.X_op != O_register && port.X_op != O_md1)
1399 if (REG_A == reg.X_add_number)
1403 emit_byte (&port, BFD_RELOC_8);
1410 if (REG_C == port.X_add_number)
1414 *q = 0x41 | (reg.X_add_number << 3);
1423 emit_rst (char prefix ATTRIBUTE_UNUSED, char opcode, const char * args)
1429 p = parse_exp (args, &addr);
1430 if (addr.X_op != O_constant)
1432 error ("rst needs constant address");
1436 if (addr.X_add_number & ~(7 << 3))
1441 *q = opcode + (addr.X_add_number & (7 << 3));
1447 emit_ldxhl (char prefix, char opcode, expressionS *src, expressionS *d)
1455 if (src->X_op == O_register)
1457 if (src->X_add_number>7)
1466 *q = opcode + src->X_add_number;
1468 emit_byte (d, BFD_RELOC_Z80_DISP8);
1481 emit_byte (d, BFD_RELOC_Z80_DISP8);
1482 emit_byte (src, BFD_RELOC_8);
1488 emit_ldreg (int dest, expressionS * src)
1495 /* 8 Bit ld group: */
1498 if (src->X_md == 0 && src->X_op == O_register && src->X_add_number == REG_A)
1502 *q = (dest == REG_I) ? 0x47 : 0x4F;
1509 if ((src->X_md) && src->X_op != O_register && src->X_op != O_md1)
1518 && src->X_op == O_register
1519 && (src->X_add_number == REG_BC || src->X_add_number == REG_DE))
1522 *q = 0x0A + ((dest & 1) << 4);
1527 && src->X_op == O_register
1528 && (src->X_add_number == REG_R || src->X_add_number == REG_I))
1532 *q = (src->X_add_number == REG_I) ? 0x57 : 0x5F;
1540 emit_sx (0, 0x40 + (dest << 3), src);
1545 if ((src->X_md == 0)
1546 && (src->X_op == O_register)
1547 && (src->X_add_number & R_INDEX))
1550 emit_sx (0, 0x40 + (dest << 3), src);
1562 check_mach (INS_UNDOC);
1563 if (src-> X_op == O_register)
1565 rnum = src->X_add_number;
1566 if ((rnum & ~R_INDEX) < 8
1567 && ((rnum & R_INDEX) == (dest & R_INDEX)
1568 || ( (rnum & ~R_INDEX) != REG_H
1569 && (rnum & ~R_INDEX) != REG_L)))
1572 *q++ = (dest & R_IX) ? 0xDD : 0xFD;
1573 *q = 0x40 + ((dest & 0x07) << 3) + (rnum & 7);
1581 *q++ = (dest & R_IX) ? 0xDD : 0xFD;
1582 *q = 0x06 + ((dest & 0x07) << 3);
1583 emit_byte (src, BFD_RELOC_8);
1587 /* 16 Bit ld group: */
1590 && src->X_op == O_register
1591 && REG_HL == (src->X_add_number &~ R_INDEX))
1593 q = frag_more ((src->X_add_number & R_INDEX) ? 2 : 1);
1594 if (src->X_add_number & R_INDEX)
1595 *q++ = (src->X_add_number & R_IX) ? 0xDD : 0xFD;
1602 if (src->X_op == O_register || src->X_op != O_md1)
1604 q = frag_more (src->X_md ? 2 : 1);
1608 *q = 0x4B + ((dest & 3) << 4);
1611 *q = 0x01 + ((dest & 3) << 4);
1618 if (src->X_op == O_register || src->X_op == O_md1)
1620 q = frag_more ((dest & R_INDEX) ? 2 : 1);
1622 * q ++ = (dest & R_IX) ? 0xDD : 0xFD;
1623 *q = (src->X_md) ? 0x2A : 0x21;
1638 emit_ld (char prefix_in ATTRIBUTE_UNUSED, char opcode_in ATTRIBUTE_UNUSED,
1641 expressionS dst, src;
1644 char prefix, opcode;
1646 p = parse_exp (args, &dst);
1648 error (_("bad intruction syntax"));
1649 p = parse_exp (p, &src);
1654 emit_ldxhl ((dst.X_add_number & R_IX) ? 0xDD : 0xFD, 0x70,
1655 &src, symbol_get_value_expression (dst.X_add_symbol));
1661 switch (dst.X_add_number)
1665 if (src.X_md == 0 && src.X_op == O_register && src.X_add_number == REG_A)
1668 *q = 0x02 + ( (dst.X_add_number & 1) << 4);
1674 emit_ldxhl (0, 0x70, &src, NULL);
1681 emit_ldreg (dst.X_add_number, &src);
1685 if (src.X_md != 0 || src.X_op != O_register)
1687 prefix = opcode = 0;
1688 switch (src.X_add_number)
1691 opcode = 0x32; break;
1692 case REG_BC: case REG_DE: case REG_SP:
1693 prefix = 0xED; opcode = 0x43 + ((src.X_add_number&3)<<4); break;
1695 opcode = 0x22; break;
1697 prefix = 0xDD; opcode = 0x22; break;
1699 prefix = 0xFD; opcode = 0x22; break;
1703 q = frag_more (prefix?2:1);
1716 emit_data (char prefix ATTRIBUTE_UNUSED, char opcode, const char * args)
1723 p = skip_space (args);
1725 error (_("missing operand"));
1729 if (*p == '\"' || *p == '\'')
1733 for (quote = *p, q = ++p, cnt = 0; *p && quote != *p; ++p, ++cnt)
1735 u = frag_more (cnt);
1738 as_warn (_("unterminated string"));
1740 p = skip_space (p+1);
1750 p = parse_exp (p, &exp);
1751 if (exp.X_op == O_md1 || exp.X_op == O_register)
1757 as_warn (_("parentheses ignored"));
1759 emit_byte (&exp, BFD_RELOC_8);
1767 as_warn (_("missing ','"));
1776 emit_mulub (char prefix ATTRIBUTE_UNUSED, char opcode, const char * args)
1780 p = skip_space (args);
1781 if (TOLOWER (*p++) != 'a' || *p++ != ',')
1787 reg = TOLOWER (*p++);
1794 check_mach (INS_R800);
1795 if (!*skip_space (p))
1799 *q = opcode + ((reg - 'b') << 3);
1810 emit_muluw (char prefix ATTRIBUTE_UNUSED, char opcode, const char * args)
1814 p = skip_space (args);
1815 if (TOLOWER (*p++) != 'h' || TOLOWER (*p++) != 'l' || *p++ != ',')
1822 p = parse_exp (p, & reg);
1824 if ((!reg.X_md) && reg.X_op == O_register)
1825 switch (reg.X_add_number)
1829 check_mach (INS_R800);
1832 *q = opcode + ((reg.X_add_number & 3) << 4);
1841 static table_t instab[] =
1843 { "adc", 0x88, 0x4A, emit_adc },
1844 { "add", 0x80, 0x09, emit_add },
1845 { "and", 0x00, 0xA0, emit_s },
1846 { "bit", 0xCB, 0x40, emit_bit },
1847 { "call", 0xCD, 0xC4, emit_jpcc },
1848 { "ccf", 0x00, 0x3F, emit_insn },
1849 { "cp", 0x00, 0xB8, emit_s },
1850 { "cpd", 0xED, 0xA9, emit_insn },
1851 { "cpdr", 0xED, 0xB9, emit_insn },
1852 { "cpi", 0xED, 0xA1, emit_insn },
1853 { "cpir", 0xED, 0xB1, emit_insn },
1854 { "cpl", 0x00, 0x2F, emit_insn },
1855 { "daa", 0x00, 0x27, emit_insn },
1856 { "db", 0x00, 0x01, emit_data },
1857 { "dec", 0x0B, 0x05, emit_incdec },
1858 { "defb", 0x00, 0x01, emit_data },
1859 { "defw", 0x00, 0x02, emit_data },
1860 { "di", 0x00, 0xF3, emit_insn },
1861 { "djnz", 0x00, 0x10, emit_jr },
1862 { "dw", 0x00, 0x02, emit_data },
1863 { "ei", 0x00, 0xFB, emit_insn },
1864 { "ex", 0x00, 0x00, emit_ex},
1865 { "exx", 0x00, 0xD9, emit_insn },
1866 { "halt", 0x00, 0x76, emit_insn },
1867 { "im", 0xED, 0x46, emit_im },
1868 { "in", 0x00, 0x00, emit_in },
1869 { "inc", 0x03, 0x04, emit_incdec },
1870 { "ind", 0xED, 0xAA, emit_insn },
1871 { "indr", 0xED, 0xBA, emit_insn },
1872 { "ini", 0xED, 0xA2, emit_insn },
1873 { "inir", 0xED, 0xB2, emit_insn },
1874 { "jp", 0xC3, 0xC2, emit_jpcc },
1875 { "jr", 0x18, 0x20, emit_jrcc },
1876 { "ld", 0x00, 0x00, emit_ld },
1877 { "ldd", 0xED, 0xA8, emit_insn },
1878 { "lddr", 0xED, 0xB8, emit_insn },
1879 { "ldi", 0xED, 0xA0, emit_insn },
1880 { "ldir", 0xED, 0xB0, emit_insn },
1881 { "mulub", 0xED, 0xC5, emit_mulub }, /* R800 only. */
1882 { "muluw", 0xED, 0xC3, emit_muluw }, /* R800 only. */
1883 { "neg", 0xed, 0x44, emit_insn },
1884 { "nop", 0x00, 0x00, emit_insn },
1885 { "or", 0x00, 0xB0, emit_s },
1886 { "otdr", 0xED, 0xBB, emit_insn },
1887 { "otir", 0xED, 0xB3, emit_insn },
1888 { "out", 0x00, 0x00, emit_out },
1889 { "outd", 0xED, 0xAB, emit_insn },
1890 { "outi", 0xED, 0xA3, emit_insn },
1891 { "pop", 0x00, 0xC1, emit_pop },
1892 { "push", 0x00, 0xC5, emit_pop },
1893 { "res", 0xCB, 0x80, emit_bit },
1894 { "ret", 0xC9, 0xC0, emit_retcc },
1895 { "reti", 0xED, 0x4D, emit_insn },
1896 { "retn", 0xED, 0x45, emit_insn },
1897 { "rl", 0xCB, 0x10, emit_mr },
1898 { "rla", 0x00, 0x17, emit_insn },
1899 { "rlc", 0xCB, 0x00, emit_mr },
1900 { "rlca", 0x00, 0x07, emit_insn },
1901 { "rld", 0xED, 0x6F, emit_insn },
1902 { "rr", 0xCB, 0x18, emit_mr },
1903 { "rra", 0x00, 0x1F, emit_insn },
1904 { "rrc", 0xCB, 0x08, emit_mr },
1905 { "rrca", 0x00, 0x0F, emit_insn },
1906 { "rrd", 0xED, 0x67, emit_insn },
1907 { "rst", 0x00, 0xC7, emit_rst},
1908 { "sbc", 0x98, 0x42, emit_adc },
1909 { "scf", 0x00, 0x37, emit_insn },
1910 { "set", 0xCB, 0xC0, emit_bit },
1911 { "sla", 0xCB, 0x20, emit_mr },
1912 { "sli", 0xCB, 0x30, emit_mr },
1913 { "sll", 0xCB, 0x30, emit_mr },
1914 { "sra", 0xCB, 0x28, emit_mr },
1915 { "srl", 0xCB, 0x38, emit_mr },
1916 { "sub", 0x00, 0x90, emit_s },
1917 { "xor", 0x00, 0xA8, emit_s },
1921 md_assemble (char* str)
1929 old_ptr = input_line_pointer;
1930 p = skip_space (str);
1931 for (i = 0; (i < BUFLEN) && (ISALPHA (*p));)
1932 buf[i++] = TOLOWER (*p++);
1935 || ((*p) && (!ISSPACE (*p))))
1936 as_bad (_("illegal instruction '%s'"), buf);
1942 insp = bsearch (&key, instab, ARRAY_SIZE (instab),
1943 sizeof (instab[0]), key_cmp);
1945 as_bad (_("illegal instruction '%s'"), buf);
1948 p = insp->fp (insp->prefix, insp->opcode, p);
1950 if ((!err_flag) && *p)
1951 as_bad (_("junk at end of line, first unrecognized character is `%c'"),
1954 input_line_pointer = old_ptr;
1958 md_apply_fix (fixS * fixP, valueT* valP, segT seg ATTRIBUTE_UNUSED)
1960 long val = * (long *) valP;
1961 char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
1963 switch (fixP->fx_r_type)
1965 case BFD_RELOC_8_PCREL:
1968 fixP->fx_no_overflow = 1;
1973 fixP->fx_no_overflow = (-128 <= val && val < 128);
1974 if (!fixP->fx_no_overflow)
1975 as_bad_where (fixP->fx_file, fixP->fx_line,
1976 _("relative jump out of range"));
1982 case BFD_RELOC_Z80_DISP8:
1985 fixP->fx_no_overflow = 1;
1990 fixP->fx_no_overflow = (-128 <= val && val < 128);
1991 if (!fixP->fx_no_overflow)
1992 as_bad_where (fixP->fx_file, fixP->fx_line,
1993 _("index offset out of range"));
2000 if (val > 255 || val < -128)
2001 as_warn_where (fixP->fx_file, fixP->fx_line, _("overflow"));
2003 if (fixP->fx_addsy == NULL)
2009 *buf++ = (val >> 8);
2010 if (fixP->fx_addsy == NULL)
2014 case BFD_RELOC_32: /* .Long may produce this. */
2016 *buf++ = (val >> 8);
2017 *buf++ = (val >> 16);
2018 *buf++ = (val >> 24);
2019 if (fixP->fx_addsy == NULL)
2024 printf (_("md_apply_fix: unknown r_type 0x%x\n"), fixP->fx_r_type);
2029 /* GAS will call this to generate a reloc. GAS will pass the
2030 resulting reloc to `bfd_install_relocation'. This currently works
2031 poorly, as `bfd_install_relocation' often does the wrong thing, and
2032 instances of `tc_gen_reloc' have been written to work around the
2033 problems, which in turns makes it difficult to fix
2034 `bfd_install_relocation'. */
2036 /* If while processing a fixup, a reloc really
2037 needs to be created then it is done here. */
2040 tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED , fixS *fixp)
2044 if (! bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type))
2046 as_bad_where (fixp->fx_file, fixp->fx_line,
2047 _("reloc %d not supported by object file format"),
2048 (int) fixp->fx_r_type);
2052 reloc = xmalloc (sizeof (arelent));
2053 reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
2054 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
2055 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
2056 reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
2057 reloc->addend = fixp->fx_offset;