Back to index

cell-binutils  2.17cvs20070401
tc-z80.c
Go to the documentation of this file.
00001 /* tc-z80.c -- Assemble code for the Zilog Z80 and ASCII R800
00002    Copyright 2005, 2006 Free Software Foundation, Inc.
00003    Contributed by Arnold Metselaar <arnold_m@operamail.com>
00004 
00005    This file is part of GAS, the GNU Assembler.
00006 
00007    GAS is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 2, or (at your option)
00010    any later version.
00011 
00012    GAS is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015    GNU General Public License for more details.
00016 
00017    You should have received a copy of the GNU General Public License
00018    along with GAS; see the file COPYING.  If not, write to the Free
00019    Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
00020    02110-1301, USA.  */
00021 
00022 #include "as.h"
00023 #include "safe-ctype.h"
00024 #include "subsegs.h"
00025 
00026 /* Exported constants.  */
00027 const char comment_chars[] = ";\0";
00028 const char line_comment_chars[] = "#;\0";
00029 const char line_separator_chars[] = "\0";
00030 const char EXP_CHARS[] = "eE\0";
00031 const char FLT_CHARS[] = "RrFf\0";
00032 
00033 /* For machine specific options.  */
00034 const char * md_shortopts = ""; /* None yet.  */
00035 
00036 enum options
00037 {
00038   OPTION_MACH_Z80 = OPTION_MD_BASE,
00039   OPTION_MACH_R800,
00040   OPTION_MACH_IUD,
00041   OPTION_MACH_WUD,
00042   OPTION_MACH_FUD,
00043   OPTION_MACH_IUP,
00044   OPTION_MACH_WUP,
00045   OPTION_MACH_FUP
00046 };
00047 
00048 #define INS_Z80    1
00049 #define INS_UNDOC  2
00050 #define INS_UNPORT 4
00051 #define INS_R800   8
00052 
00053 struct option md_longopts[] =
00054 {
00055   { "z80",       no_argument, NULL, OPTION_MACH_Z80},
00056   { "r800",      no_argument, NULL, OPTION_MACH_R800},
00057   { "ignore-undocumented-instructions", no_argument, NULL, OPTION_MACH_IUD },
00058   { "Wnud",  no_argument, NULL, OPTION_MACH_IUD },
00059   { "warn-undocumented-instructions",  no_argument, NULL, OPTION_MACH_WUD },
00060   { "Wud",  no_argument, NULL, OPTION_MACH_WUD },
00061   { "forbid-undocumented-instructions", no_argument, NULL, OPTION_MACH_FUD },
00062   { "Fud",  no_argument, NULL, OPTION_MACH_FUD },
00063   { "ignore-unportable-instructions", no_argument, NULL, OPTION_MACH_IUP },
00064   { "Wnup",  no_argument, NULL, OPTION_MACH_IUP },
00065   { "warn-unportable-instructions",  no_argument, NULL, OPTION_MACH_WUP },
00066   { "Wup",  no_argument, NULL, OPTION_MACH_WUP },
00067   { "forbid-unportable-instructions", no_argument, NULL, OPTION_MACH_FUP },
00068   { "Fup",  no_argument, NULL, OPTION_MACH_FUP },
00069 
00070   { NULL, no_argument, NULL, 0 }
00071 } ;
00072 
00073 size_t md_longopts_size = sizeof (md_longopts);
00074 
00075 extern int coff_flags;
00076 /* Instruction classes that silently assembled.  */
00077 static int ins_ok = INS_Z80 | INS_UNDOC;
00078 /* Instruction classes that generate errors.  */
00079 static int ins_err = INS_R800;
00080 /* Instruction classes actually used, determines machine type.  */
00081 static int ins_used = INS_Z80;
00082 
00083 int
00084 md_parse_option (int c, char* arg ATTRIBUTE_UNUSED)
00085 {
00086   switch (c)
00087     {
00088     default:
00089       return 0;
00090     case OPTION_MACH_Z80:
00091       ins_ok &= ~INS_R800;
00092       ins_err |= INS_R800;
00093       break;
00094     case OPTION_MACH_R800:
00095       ins_ok = INS_Z80 | INS_UNDOC | INS_R800;
00096       ins_err = INS_UNPORT;
00097       break;
00098     case OPTION_MACH_IUD:
00099       ins_ok |= INS_UNDOC;
00100       ins_err &= ~INS_UNDOC;
00101       break;
00102     case OPTION_MACH_IUP:
00103       ins_ok |= INS_UNDOC | INS_UNPORT;
00104       ins_err &= ~(INS_UNDOC | INS_UNPORT);
00105       break;
00106     case OPTION_MACH_WUD:
00107       if ((ins_ok & INS_R800) == 0)
00108        {
00109          ins_ok &= ~(INS_UNDOC|INS_UNPORT);
00110          ins_err &= ~INS_UNDOC;
00111        }
00112       break;
00113     case OPTION_MACH_WUP:
00114       ins_ok &= ~INS_UNPORT;
00115       ins_err &= ~(INS_UNDOC|INS_UNPORT);
00116       break;
00117     case OPTION_MACH_FUD:
00118       if ((ins_ok & INS_R800) == 0)
00119        {
00120          ins_ok &= (INS_UNDOC | INS_UNPORT);
00121          ins_err |= INS_UNDOC | INS_UNPORT;
00122        }
00123       break;
00124     case OPTION_MACH_FUP:
00125       ins_ok &= ~INS_UNPORT;
00126       ins_err |= INS_UNPORT;
00127       break;
00128     }
00129 
00130   return 1;
00131 }
00132 
00133 void
00134 md_show_usage (FILE * f)
00135 {
00136   fprintf (f, "\n\
00137 CPU model/instruction set options:\n\
00138 \n\
00139   -z80\t\t  assemble for Z80\n\
00140   -ignore-undocumented-instructions\n\
00141   -Wnud\n\
00142 \tsilently assemble undocumented Z80-instructions that work on R800\n\
00143   -ignore-unportable-instructions\n\
00144   -Wnup\n\
00145 \tsilently assemble all undocumented Z80-instructions\n\
00146   -warn-undocumented-instructions\n\
00147   -Wud\n\
00148 \tissue warnings for undocumented Z80-instructions that work on R800\n\
00149   -warn-unportable-instructions\n\
00150   -Wup\n\
00151 \tissue warnings for other undocumented Z80-instructions\n\
00152   -forbid-undocumented-instructions\n\
00153   -Fud\n\
00154 \ttreat all undocumented z80-instructions as errors\n\
00155   -forbid-unportable-instructions\n\
00156   -Fup\n\
00157 \ttreat undocumented z80-instructions that do not work on R800 as errors\n\
00158   -r800\t  assemble for R800\n\n\
00159 Default: -z80 -ignore-undocument-instructions -warn-unportable-instructions.\n");
00160 }
00161 
00162 static symbolS * zero;
00163 
00164 void
00165 md_begin (void)
00166 {
00167   expressionS nul;
00168   char * p;
00169 
00170   p = input_line_pointer;
00171   input_line_pointer = "0";
00172   nul.X_md=0;
00173   expression (& nul);
00174   input_line_pointer = p;
00175   zero = make_expr_symbol (& nul);
00176   /* We do not use relaxation (yet).  */
00177   linkrelax = 0;
00178 }
00179 
00180 void
00181 z80_md_end (void)
00182 {
00183   int mach_type;
00184 
00185   if (ins_used & (INS_UNPORT | INS_R800))
00186     ins_used |= INS_UNDOC;
00187 
00188   switch (ins_used)
00189     {
00190     case INS_Z80:
00191       mach_type = bfd_mach_z80strict;
00192       break;
00193     case INS_Z80|INS_UNDOC:
00194       mach_type = bfd_mach_z80;
00195       break;
00196     case INS_Z80|INS_UNDOC|INS_UNPORT:
00197       mach_type = bfd_mach_z80full;
00198       break;
00199     case INS_Z80|INS_UNDOC|INS_R800:
00200       mach_type = bfd_mach_r800;
00201       break;
00202     default:
00203       mach_type = 0;
00204     }
00205 
00206   bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach_type);
00207 }
00208 
00209 static const char *
00210 skip_space (const char *s)
00211 {
00212   while (*s == ' ' || *s == '\t')
00213     ++s;
00214   return s;
00215 }
00216 
00217 /* A non-zero return-value causes a continue in the
00218    function read_a_source_file () in ../read.c.  */
00219 int
00220 z80_start_line_hook (void)
00221 {
00222   char *p, quote;
00223   char buf[4];
00224 
00225   /* Convert one character constants.  */
00226   for (p = input_line_pointer; *p && *p != '\n'; ++p)
00227     {
00228       switch (*p)
00229        {
00230        case '\'':
00231          if (p[1] != 0 && p[1] != '\'' && p[2] == '\'')
00232            {
00233              snprintf (buf, 4, "%3d", (unsigned char)p[1]);
00234              *p++ = buf[0];
00235              *p++ = buf[1];
00236              *p++ = buf[2];
00237              break;
00238            }
00239        case '"':
00240          for (quote = *p++; quote != *p && '\n' != *p; ++p)
00241            /* No escapes.  */ ;
00242          if (quote != *p)
00243            {
00244              as_bad (_("-- unterminated string"));
00245              ignore_rest_of_line ();
00246              return 1;
00247            }
00248          break;
00249        }
00250     }
00251   /* Check for <label>[:] [.](EQU|DEFL) <value>.  */
00252   if (is_name_beginner (*input_line_pointer))
00253     {
00254       char c, *rest, *line_start;
00255       int len;
00256       symbolS * symbolP;
00257 
00258       line_start = input_line_pointer;
00259       LISTING_NEWLINE ();
00260       if (ignore_input ())
00261        return 0;
00262 
00263       c = get_symbol_end ();
00264       rest = input_line_pointer + 1;
00265 
00266       if (*rest == ':')
00267        ++rest;
00268       if (*rest == ' ' || *rest == '\t')
00269        ++rest;
00270       if (*rest == '.')
00271        ++rest;
00272       if (strncasecmp (rest, "EQU", 3) == 0)
00273        len = 3;
00274       else if (strncasecmp (rest, "DEFL", 4) == 0)
00275        len = 4;
00276       else
00277        len = 0;
00278       if (len && (rest[len] == ' ' || rest[len] == '\t'))
00279        {
00280          /* Handle assignment here.  */
00281          input_line_pointer = rest + len;
00282          if (line_start[-1] == '\n')
00283            bump_line_counters ();
00284          /* Most Z80 assemblers require the first definition of a
00285              label to use "EQU" and redefinitions to have "DEFL".  */
00286          if (len == 3 && (symbolP = symbol_find (line_start)) != NULL) 
00287            {
00288              if (S_IS_DEFINED (symbolP) || symbol_equated_p (symbolP))
00289               as_bad (_("symbol `%s' is already defined"), line_start);
00290            }
00291          equals (line_start, 1);
00292          return 1;
00293        }
00294       else
00295        {
00296          /* Restore line and pointer.  */
00297          *input_line_pointer = c;
00298          input_line_pointer = line_start;
00299        }
00300     }
00301   return 0;
00302 }
00303 
00304 symbolS *
00305 md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
00306 {
00307   return NULL;
00308 }
00309 
00310 char *
00311 md_atof (int type ATTRIBUTE_UNUSED, char *litP ATTRIBUTE_UNUSED,
00312         int *sizeP ATTRIBUTE_UNUSED)
00313 {
00314   return _("floating point numbers are not implemented");
00315 }
00316 
00317 valueT
00318 md_section_align (segT seg ATTRIBUTE_UNUSED, valueT size)
00319 {
00320   return size;
00321 }
00322 
00323 long
00324 md_pcrel_from (fixS * fixp)
00325 {
00326   return fixp->fx_where +
00327     fixp->fx_frag->fr_address + 1;
00328 }
00329 
00330 typedef const char * (asfunc)(char, char, const char*);
00331 
00332 typedef struct _table_t
00333 {
00334   char* name;
00335   char prefix;
00336   char opcode;
00337   asfunc * fp;
00338 } table_t;
00339 
00340 /* Compares the key for structs that start with a char * to the key.  */
00341 static int
00342 key_cmp (const void * a, const void * b)
00343 {
00344   const char *str_a, *str_b;
00345 
00346   str_a = *((const char**)a);
00347   str_b = *((const char**)b);
00348   return strcmp (str_a, str_b);
00349 }
00350 
00351 #define BUFLEN 8 /* Large enough for any keyword.  */
00352 
00353 char buf[BUFLEN];
00354 const char *key = buf;
00355 
00356 #define R_STACKABLE (0x80)
00357 #define R_ARITH     (0x40)
00358 #define R_IX        (0x20)
00359 #define R_IY        (0x10)
00360 #define R_INDEX     (R_IX | R_IY)
00361 
00362 #define REG_A (7)
00363 #define REG_B (0)
00364 #define REG_C (1)
00365 #define REG_D (2)
00366 #define REG_E (3)
00367 #define REG_H (4)
00368 #define REG_L (5)
00369 #define REG_F (6 | 8)
00370 #define REG_I (9)
00371 #define REG_R (10)
00372 
00373 #define REG_AF (3 | R_STACKABLE)
00374 #define REG_BC (0 | R_STACKABLE | R_ARITH)
00375 #define REG_DE (1 | R_STACKABLE | R_ARITH)
00376 #define REG_HL (2 | R_STACKABLE | R_ARITH)
00377 #define REG_SP (3 | R_ARITH)
00378 
00379 static const struct reg_entry
00380 {
00381   char* name;
00382   int number;
00383 } regtable[] =
00384 {
00385   {"a",  REG_A },
00386   {"af", REG_AF },
00387   {"b",  REG_B },
00388   {"bc", REG_BC },
00389   {"c",  REG_C },
00390   {"d",  REG_D },
00391   {"de", REG_DE },
00392   {"e",  REG_E },
00393   {"f",  REG_F },
00394   {"h",  REG_H },
00395   {"hl", REG_HL },
00396   {"i",  REG_I },
00397   {"ix", REG_HL | R_IX },
00398   {"ixh",REG_H | R_IX },
00399   {"ixl",REG_L | R_IX },
00400   {"iy", REG_HL | R_IY },
00401   {"iyh",REG_H | R_IY },
00402   {"iyl",REG_L | R_IY },
00403   {"l",  REG_L },
00404   {"r",  REG_R },
00405   {"sp", REG_SP },
00406 } ;
00407 
00408 /* Prevent an error on a line from also generating
00409    a "junk at end of line" error message.  */
00410 static char err_flag;
00411 
00412 static void
00413 error (const char * message)
00414 {
00415   as_bad (message);
00416   err_flag = 1;
00417 }
00418 
00419 static void
00420 ill_op (void)
00421 {
00422   error (_("illegal operand"));
00423 }
00424 
00425 static void
00426 wrong_mach (int ins_type)
00427 {
00428   const char *p;
00429 
00430   switch (ins_type)
00431     {
00432     case INS_UNDOC:
00433       p = "undocumented instruction";
00434       break;
00435     case INS_UNPORT:
00436       p = "instruction does not work on R800";
00437       break;
00438     case INS_R800:
00439       p = "instruction only works R800";
00440       break;
00441     default:
00442       p = 0; /* Not reachable.  */
00443     }
00444 
00445   if (ins_type & ins_err)
00446     error (_(p));
00447   else
00448     as_warn (_(p));
00449 }
00450 
00451 static void
00452 check_mach (int ins_type)
00453 {
00454   if ((ins_type & ins_ok) == 0)
00455     wrong_mach (ins_type);
00456   ins_used |= ins_type;
00457 }
00458 
00459 /* Check whether an expression is indirect.  */
00460 static int
00461 is_indir (const char *s)
00462 {
00463   char quote;
00464   const char *p;
00465   int indir, depth;
00466 
00467   /* Indirection is indicated with parentheses.  */
00468   indir = (*s == '(');
00469 
00470   for (p = s, depth = 0; *p && *p != ','; ++p)
00471     {
00472       switch (*p)
00473        {
00474        case '"':
00475        case '\'':
00476          for (quote = *p++; quote != *p && *p != '\n'; ++p)
00477            if (*p == '\\' && p[1])
00478              ++p;
00479          break;
00480        case '(':
00481          ++ depth;
00482          break;
00483        case ')':
00484          -- depth;
00485          if (depth == 0)
00486            {
00487              p = skip_space (p + 1);
00488              if (*p && *p != ',')
00489               indir = 0;
00490              --p;
00491            }
00492          if (depth < 0)
00493            error (_("mismatched parentheses"));
00494          break;
00495        }
00496     }
00497 
00498   if (depth != 0)
00499     error (_("mismatched parentheses"));
00500 
00501   return indir;
00502 }
00503 
00504 /* Parse general expression.  */
00505 static const char *
00506 parse_exp2 (const char *s, expressionS *op, segT *pseg)
00507 {
00508   const char *p;
00509   int indir;
00510   int i;
00511   const struct reg_entry * regp;
00512   expressionS offset;
00513 
00514   p = skip_space (s);
00515   op->X_md = indir = is_indir (p);
00516   if (indir)
00517     p = skip_space (p + 1);
00518 
00519   for (i = 0; i < BUFLEN; ++i)
00520     {
00521       if (!ISALPHA (p[i])) /* Register names consist of letters only.  */
00522        break;
00523       buf[i] = TOLOWER (p[i]);
00524     }
00525 
00526   if ((i < BUFLEN) && ((p[i] == 0) || (strchr (")+-, \t", p[i]))))
00527     {
00528       buf[i] = 0;
00529       regp = bsearch (& key, regtable, ARRAY_SIZE (regtable),
00530                     sizeof (regtable[0]), key_cmp);
00531       if (regp)
00532        {
00533          *pseg = reg_section;
00534          op->X_add_symbol = op->X_op_symbol = 0;
00535          op->X_add_number = regp->number;
00536          op->X_op = O_register;
00537          p += strlen (regp->name);
00538          p = skip_space (p);
00539          if (indir)
00540            {
00541              if (*p == ')')
00542               ++p;
00543              if ((regp->number & R_INDEX) && (regp->number & R_ARITH))
00544               {
00545                 op->X_op = O_md1;
00546 
00547                 if  ((*p == '+') || (*p == '-'))
00548                   {
00549                     input_line_pointer = (char*) p;
00550                     expression (& offset);
00551                     p = skip_space (input_line_pointer);
00552                     if (*p != ')')
00553                      error (_("bad offset expression syntax"));
00554                     else
00555                      ++ p;
00556                     op->X_add_symbol = make_expr_symbol (& offset);
00557                     return p;
00558                   }
00559 
00560                 /* We treat (i[xy]) as (i[xy]+0), which is how it will
00561                    end up anyway, unless we're processing jp (i[xy]).  */
00562                 op->X_add_symbol = zero;
00563               }
00564            }
00565          p = skip_space (p);
00566 
00567          if ((*p == 0) || (*p == ','))
00568            return p;
00569        }
00570     }
00571   /* Not an argument involving a register; use the generic parser.  */
00572   input_line_pointer = (char*) s ;
00573   *pseg = expression (op);
00574   if (op->X_op == O_absent)
00575     error (_("missing operand"));
00576   if (op->X_op == O_illegal)
00577     error (_("bad expression syntax"));
00578   return input_line_pointer;
00579 }
00580 
00581 static const char *
00582 parse_exp (const char *s, expressionS *op)
00583 {
00584   segT dummy;
00585   return parse_exp2 (s, op, & dummy);
00586 }
00587 
00588 /* Condition codes, including some synonyms provided by HiTech zas.  */
00589 static const struct reg_entry cc_tab[] =
00590 {
00591   { "age", 6 << 3 },
00592   { "alt", 7 << 3 },
00593   { "c",   3 << 3 },
00594   { "di",  4 << 3 },
00595   { "ei",  5 << 3 },
00596   { "lge", 2 << 3 },
00597   { "llt", 3 << 3 },
00598   { "m",   7 << 3 },
00599   { "nc",  2 << 3 },
00600   { "nz",  0 << 3 },
00601   { "p",   6 << 3 },
00602   { "pe",  5 << 3 },
00603   { "po",  4 << 3 },
00604   { "z",   1 << 3 },
00605 } ;
00606 
00607 /* Parse condition code.  */
00608 static const char *
00609 parse_cc (const char *s, char * op)
00610 {
00611   const char *p;
00612   int i;
00613   struct reg_entry * cc_p;
00614 
00615   for (i = 0; i < BUFLEN; ++i)
00616     {
00617       if (!ISALPHA (s[i])) /* Condition codes consist of letters only.  */
00618        break;
00619       buf[i] = TOLOWER (s[i]);
00620     }
00621 
00622   if ((i < BUFLEN)
00623       && ((s[i] == 0) || (s[i] == ',')))
00624     {
00625       buf[i] = 0;
00626       cc_p = bsearch (&key, cc_tab, ARRAY_SIZE (cc_tab),
00627                     sizeof (cc_tab[0]), key_cmp);
00628     }
00629   else
00630     cc_p = NULL;
00631 
00632   if (cc_p)
00633     {
00634       *op = cc_p->number;
00635       p = s + i;
00636     }
00637   else
00638     p = NULL;
00639 
00640   return p;
00641 }
00642 
00643 static const char *
00644 emit_insn (char prefix, char opcode, const char * args)
00645 {
00646   char *p;
00647 
00648   if (prefix)
00649     {
00650       p = frag_more (2);
00651       *p++ = prefix;
00652     }
00653   else
00654     p = frag_more (1);
00655   *p = opcode;
00656   return args;
00657 }
00658 
00659 void z80_cons_fix_new (fragS *frag_p, int offset, int nbytes, expressionS *exp)
00660 {
00661   bfd_reloc_code_real_type r[4] =
00662     {
00663       BFD_RELOC_8,
00664       BFD_RELOC_16,
00665       BFD_RELOC_24,
00666       BFD_RELOC_32
00667     };
00668 
00669   if (nbytes < 1 || nbytes > 4) 
00670     {
00671       as_bad (_("unsupported BFD relocation size %u"), nbytes);
00672     }
00673   else
00674     {
00675       fix_new_exp (frag_p, offset, nbytes, exp, 0, r[nbytes-1]);
00676     }
00677 }
00678 
00679 static void
00680 emit_byte (expressionS * val, bfd_reloc_code_real_type r_type)
00681 {
00682   char *p;
00683   int lo, hi;
00684   fixS * fixp;
00685 
00686   p = frag_more (1);
00687   *p = val->X_add_number;
00688   if ((r_type == BFD_RELOC_8_PCREL) && (val->X_op == O_constant))
00689     {
00690       as_bad(_("cannot make a relative jump to an absolute location"));
00691     }
00692   else if (val->X_op == O_constant)
00693     {
00694       lo = -128;
00695       hi = (BFD_RELOC_8 == r_type) ? 255 : 127;
00696 
00697       if ((val->X_add_number < lo) || (val->X_add_number > hi))
00698        {
00699          if (r_type == BFD_RELOC_Z80_DISP8)
00700            as_bad (_("offset too large"));
00701          else
00702            as_warn (_("overflow"));
00703        }
00704     }
00705   else
00706     {
00707       fixp = fix_new_exp (frag_now, p - frag_now->fr_literal, 1, val,
00708                        (r_type == BFD_RELOC_8_PCREL) ? TRUE : FALSE, r_type);
00709       /* FIXME : Process constant offsets immediately.  */
00710     }
00711 }
00712 
00713 static void
00714 emit_word (expressionS * val)
00715 {
00716   char *p;
00717 
00718   p = frag_more (2);
00719   if (   (val->X_op == O_register)
00720       || (val->X_op == O_md1))
00721     ill_op ();
00722   else
00723     {
00724       *p = val->X_add_number;
00725       p[1] = (val->X_add_number>>8);
00726       if (val->X_op != O_constant)
00727        fix_new_exp (frag_now, p - frag_now->fr_literal, 2,
00728                    val, FALSE, BFD_RELOC_16);
00729     }
00730 }
00731 
00732 static void
00733 emit_mx (char prefix, char opcode, int shift, expressionS * arg)
00734      /* The operand m may be r, (hl), (ix+d), (iy+d),
00735        if 0 == prefix m may also be ixl, ixh, iyl, iyh.  */
00736 {
00737   char *q;
00738   int rnum;
00739 
00740   rnum = arg->X_add_number;
00741   switch (arg->X_op)
00742     {
00743     case O_register:
00744       if (arg->X_md)
00745        {
00746          if (rnum != REG_HL)
00747            {
00748              ill_op ();
00749              break;
00750            }
00751          else
00752            rnum = 6;
00753        }
00754       else
00755        {
00756          if ((prefix == 0) && (rnum & R_INDEX))
00757            {
00758              prefix = (rnum & R_IX) ? 0xDD : 0xFD;
00759              check_mach (INS_UNDOC);
00760              rnum &= ~R_INDEX;
00761            }
00762          if (rnum > 7)
00763            {
00764              ill_op ();
00765              break;
00766            }
00767        }
00768       q = frag_more (prefix ? 2 : 1);
00769       if (prefix)
00770        * q ++ = prefix;
00771       * q ++ = opcode + (rnum << shift);
00772       break;
00773     case O_md1:
00774       q = frag_more (2);
00775       *q++ = (rnum & R_IX) ? 0xDD : 0xFD;
00776       *q = (prefix) ? prefix : (opcode + (6 << shift));
00777       emit_byte (symbol_get_value_expression (arg->X_add_symbol),
00778                BFD_RELOC_Z80_DISP8);
00779       if (prefix)
00780        {
00781          q = frag_more (1);
00782          *q = opcode+(6<<shift);
00783        }
00784       break;
00785     default:
00786       abort ();
00787     }
00788 }
00789 
00790 /* The operand m may be r, (hl), (ix+d), (iy+d),
00791    if 0 = prefix m may also be ixl, ixh, iyl, iyh.  */
00792 static const char *
00793 emit_m (char prefix, char opcode, const char *args)
00794 {
00795   expressionS arg_m;
00796   const char *p;
00797 
00798   p = parse_exp (args, &arg_m);
00799   switch (arg_m.X_op)
00800     {
00801     case O_md1:
00802     case O_register:
00803       emit_mx (prefix, opcode, 0, &arg_m);
00804       break;
00805     default:
00806       ill_op ();
00807     }
00808   return p;
00809 }
00810 
00811 /* The operand m may be as above or one of the undocumented
00812    combinations (ix+d),r and (iy+d),r (if unportable instructions
00813    are allowed).  */
00814 static const char *
00815 emit_mr (char prefix, char opcode, const char *args)
00816 {
00817   expressionS arg_m, arg_r;
00818   const char *p;
00819 
00820   p = parse_exp (args, & arg_m);
00821 
00822   switch (arg_m.X_op)
00823     {
00824     case O_md1:
00825       if (*p == ',')
00826        {
00827          p = parse_exp (p + 1, & arg_r);
00828 
00829          if ((arg_r.X_md == 0)
00830              && (arg_r.X_op == O_register)
00831              && (arg_r.X_add_number < 8))
00832            opcode += arg_r.X_add_number-6; /* Emit_mx () will add 6.  */
00833          else
00834            {
00835              ill_op ();
00836              break;
00837            }
00838          check_mach (INS_UNPORT);
00839        }
00840     case O_register:
00841       emit_mx (prefix, opcode, 0, & arg_m);
00842       break;
00843     default:
00844       ill_op ();
00845     }
00846   return p;
00847 }
00848 
00849 static void
00850 emit_sx (char prefix, char opcode, expressionS * arg_p)
00851 {
00852   char *q;
00853 
00854   switch (arg_p->X_op)
00855     {
00856     case O_register:
00857     case O_md1:
00858       emit_mx (prefix, opcode, 0, arg_p);
00859       break;
00860     default:
00861       if (arg_p->X_md)
00862        ill_op ();
00863       else
00864        {
00865          q = frag_more (prefix ? 2 : 1);
00866          if (prefix)
00867            *q++ = prefix;
00868          *q = opcode ^ 0x46;
00869          emit_byte (arg_p, BFD_RELOC_8);
00870        }
00871     }
00872 }
00873 
00874 /* The operand s may be r, (hl), (ix+d), (iy+d), n.  */
00875 static const char *
00876 emit_s (char prefix, char opcode, const char *args)
00877 {
00878   expressionS arg_s;
00879   const char *p;
00880 
00881   p = parse_exp (args, & arg_s);
00882   emit_sx (prefix, opcode, & arg_s);
00883   return p;
00884 }
00885 
00886 static const char *
00887 emit_call (char prefix ATTRIBUTE_UNUSED, char opcode, const char * args)
00888 {
00889   expressionS addr;
00890   const char *p;  char *q;
00891 
00892   p = parse_exp (args, &addr);
00893   if (addr.X_md)
00894     ill_op ();
00895   else
00896     {
00897       q = frag_more (1);
00898       *q = opcode;
00899       emit_word (& addr);
00900     }
00901   return p;
00902 }
00903 
00904 /* Operand may be rr, r, (hl), (ix+d), (iy+d).  */
00905 static const char *
00906 emit_incdec (char prefix, char opcode, const char * args)
00907 {
00908   expressionS operand;
00909   int rnum;
00910   const char *p;  char *q;
00911 
00912   p = parse_exp (args, &operand);
00913   rnum = operand.X_add_number;
00914   if ((! operand.X_md)
00915       && (operand.X_op == O_register)
00916       && (R_ARITH&rnum))
00917     {
00918       q = frag_more ((rnum & R_INDEX) ? 2 : 1);
00919       if (rnum & R_INDEX)
00920        *q++ = (rnum & R_IX) ? 0xDD : 0xFD;
00921       *q = prefix + ((rnum & 3) << 4);
00922     }
00923   else
00924     {
00925       if ((operand.X_op == O_md1) || (operand.X_op == O_register))
00926        emit_mx (0, opcode, 3, & operand);
00927       else
00928        ill_op ();
00929     }
00930   return p;
00931 }
00932 
00933 static const char *
00934 emit_jr (char prefix ATTRIBUTE_UNUSED, char opcode, const char * args)
00935 {
00936   expressionS addr;
00937   const char *p;
00938   char *q;
00939 
00940   p = parse_exp (args, &addr);
00941   if (addr.X_md)
00942     ill_op ();
00943   else
00944     {
00945       q = frag_more (1);
00946       *q = opcode;
00947       emit_byte (&addr, BFD_RELOC_8_PCREL);
00948     }
00949   return p;
00950 }
00951 
00952 static const char *
00953 emit_jp (char prefix, char opcode, const char * args)
00954 {
00955   expressionS addr;
00956   const char *p;
00957   char *q;
00958   int rnum;
00959 
00960   p = parse_exp (args, & addr);
00961   if (addr.X_md)
00962     {
00963       rnum = addr.X_add_number;
00964       if ((addr.X_op == O_register && (rnum & ~R_INDEX) == REG_HL)
00965         /* An operand (i[xy]) would have been rewritten to (i[xy]+0)
00966             in parse_exp ().  */
00967          || (addr.X_op == O_md1 && addr.X_add_symbol == zero))
00968        {
00969          q = frag_more ((rnum & R_INDEX) ? 2 : 1);
00970          if (rnum & R_INDEX)
00971            *q++ = (rnum & R_IX) ? 0xDD : 0xFD;
00972          *q = prefix;
00973        }
00974       else
00975        ill_op ();
00976     }
00977   else
00978     {
00979       q = frag_more (1);
00980       *q = opcode;
00981       emit_word (& addr);
00982     }
00983   return p;
00984 }
00985 
00986 static const char *
00987 emit_im (char prefix, char opcode, const char * args)
00988 {
00989   expressionS mode;
00990   const char *p;
00991   char *q;
00992 
00993   p = parse_exp (args, & mode);
00994   if (mode.X_md || (mode.X_op != O_constant))
00995     ill_op ();
00996   else
00997     switch (mode.X_add_number)
00998       {
00999       case 1:
01000       case 2:
01001        ++mode.X_add_number;
01002        /* Fall through.  */
01003       case 0:
01004        q = frag_more (2);
01005        *q++ = prefix;
01006        *q = opcode + 8*mode.X_add_number;
01007        break;
01008       default:
01009        ill_op ();
01010       }
01011   return p;
01012 }
01013 
01014 static const char *
01015 emit_pop (char prefix ATTRIBUTE_UNUSED, char opcode, const char * args)
01016 {
01017   expressionS regp;
01018   const char *p;
01019   char *q;
01020 
01021   p = parse_exp (args, & regp);
01022   if ((!regp.X_md)
01023       && (regp.X_op == O_register)
01024       && (regp.X_add_number & R_STACKABLE))
01025     {
01026       int rnum;
01027 
01028       rnum = regp.X_add_number;
01029       if (rnum&R_INDEX)
01030        {
01031          q = frag_more (2);
01032          *q++ = (rnum&R_IX)?0xDD:0xFD;
01033        }
01034       else
01035        q = frag_more (1);
01036       *q = opcode + ((rnum & 3) << 4);
01037     }
01038   else
01039     ill_op ();
01040 
01041   return p;
01042 }
01043 
01044 static const char *
01045 emit_retcc (char prefix ATTRIBUTE_UNUSED, char opcode, const char * args)
01046 {
01047   char cc, *q;
01048   const char *p;
01049 
01050   p = parse_cc (args, &cc);
01051   q = frag_more (1);
01052   if (p)
01053     *q = opcode + cc;
01054   else
01055     *q = prefix;
01056   return p ? p : args;
01057 }
01058 
01059 static const char *
01060 emit_adc (char prefix, char opcode, const char * args)
01061 {
01062   expressionS term;
01063   int rnum;
01064   const char *p;
01065   char *q;
01066 
01067   p = parse_exp (args, &term);
01068   if (*p++ != ',')
01069     {
01070       error (_("bad intruction syntax"));
01071       return p;
01072     }
01073 
01074   if ((term.X_md) || (term.X_op != O_register))
01075     ill_op ();
01076   else
01077     switch (term.X_add_number)
01078       {
01079       case REG_A:
01080        p = emit_s (0, prefix, p);
01081        break;
01082       case REG_HL:
01083        p = parse_exp (p, &term);
01084        if ((!term.X_md) && (term.X_op == O_register))
01085          {
01086            rnum = term.X_add_number;
01087            if (R_ARITH == (rnum & (R_ARITH | R_INDEX)))
01088              {
01089               q = frag_more (2);
01090               *q++ = 0xED;
01091               *q = opcode + ((rnum & 3) << 4);
01092               break;
01093              }
01094          }
01095        /* Fall through.  */
01096       default:
01097        ill_op ();
01098       }
01099   return p;
01100 }
01101 
01102 static const char *
01103 emit_add (char prefix, char opcode, const char * args)
01104 {
01105   expressionS term;
01106   int lhs, rhs;
01107   const char *p;
01108   char *q;
01109 
01110   p = parse_exp (args, &term);
01111   if (*p++ != ',')
01112     {
01113       error (_("bad intruction syntax"));
01114       return p;
01115     }
01116 
01117   if ((term.X_md) || (term.X_op != O_register))
01118     ill_op ();
01119   else
01120     switch (term.X_add_number & ~R_INDEX)
01121       {
01122       case REG_A:
01123        p = emit_s (0, prefix, p);
01124        break;
01125       case REG_HL:
01126        lhs = term.X_add_number;
01127        p = parse_exp (p, &term);
01128        if ((!term.X_md) && (term.X_op == O_register))
01129          {
01130            rhs = term.X_add_number;
01131            if ((rhs & R_ARITH)
01132               && ((rhs == lhs) || ((rhs & ~R_INDEX) != REG_HL)))
01133              {
01134               q = frag_more ((lhs & R_INDEX) ? 2 : 1);
01135               if (lhs & R_INDEX)
01136                 *q++ = (lhs & R_IX) ? 0xDD : 0xFD;
01137               *q = opcode + ((rhs & 3) << 4);
01138               break;
01139              }
01140          }
01141        /* Fall through.  */
01142       default:
01143        ill_op ();
01144       }
01145   return p;
01146 }
01147 
01148 static const char *
01149 emit_bit (char prefix, char opcode, const char * args)
01150 {
01151   expressionS b;
01152   int bn;
01153   const char *p;
01154 
01155   p = parse_exp (args, &b);
01156   if (*p++ != ',')
01157     error (_("bad intruction syntax"));
01158 
01159   bn = b.X_add_number;
01160   if ((!b.X_md)
01161       && (b.X_op == O_constant)
01162       && (0 <= bn)
01163       && (bn < 8))
01164     {
01165       if (opcode == 0x40)
01166        /* Bit : no optional third operand.  */
01167        p = emit_m (prefix, opcode + (bn << 3), p);
01168       else
01169        /* Set, res : resulting byte can be copied to register.  */
01170        p = emit_mr (prefix, opcode + (bn << 3), p);
01171     }
01172   else
01173     ill_op ();
01174   return p;
01175 }
01176 
01177 static const char *
01178 emit_jpcc (char prefix, char opcode, const char * args)
01179 {
01180   char cc;
01181   const char *p;
01182 
01183   p = parse_cc (args, & cc);
01184   if (p && *p++ == ',')
01185     p = emit_call (0, opcode + cc, p);
01186   else
01187     p = (prefix == (char)0xC3)
01188       ? emit_jp (0xE9, prefix, args)
01189       : emit_call (0, prefix, args);
01190   return p;
01191 }
01192 
01193 static const char *
01194 emit_jrcc (char prefix, char opcode, const char * args)
01195 {
01196   char cc;
01197   const char *p;
01198 
01199   p = parse_cc (args, &cc);
01200   if (p && *p++ == ',')
01201     {
01202       if (cc > (3 << 3))
01203        error (_("condition code invalid for jr"));
01204       else
01205        p = emit_jr (0, opcode + cc, p);
01206     }
01207   else
01208     p = emit_jr (0, prefix, args);
01209 
01210   return p;
01211 }
01212 
01213 static const char *
01214 emit_ex (char prefix_in ATTRIBUTE_UNUSED,
01215         char opcode_in ATTRIBUTE_UNUSED, const char * args)
01216 {
01217   expressionS op;
01218   const char * p;
01219   char prefix, opcode;
01220 
01221   p = parse_exp (args, &op);
01222   p = skip_space (p);
01223   if (*p++ != ',')
01224     {
01225       error (_("bad instruction syntax"));
01226       return p;
01227     }
01228 
01229   prefix = opcode = 0;
01230   if (op.X_op == O_register)
01231     switch (op.X_add_number | (op.X_md ? 0x8000 : 0))
01232       {
01233       case REG_AF:
01234        if (TOLOWER (*p++) == 'a' && TOLOWER (*p++) == 'f')
01235          {
01236            /* The scrubber changes '\'' to '`' in this context.  */
01237            if (*p == '`')
01238              ++p;
01239            opcode = 0x08;
01240          }
01241        break;
01242       case REG_DE:
01243        if (TOLOWER (*p++) == 'h' && TOLOWER (*p++) == 'l')
01244          opcode = 0xEB;
01245        break;
01246       case REG_SP|0x8000:
01247        p = parse_exp (p, & op);
01248        if (op.X_op == O_register
01249            && op.X_md == 0
01250            && (op.X_add_number & ~R_INDEX) == REG_HL)
01251          {
01252            opcode = 0xE3;
01253            if (R_INDEX & op.X_add_number)
01254              prefix = (R_IX & op.X_add_number) ? 0xDD : 0xFD;
01255          }
01256        break;
01257       }
01258   if (opcode)
01259     emit_insn (prefix, opcode, p);
01260   else
01261     ill_op ();
01262 
01263   return p;
01264 }
01265 
01266 static const char *
01267 emit_in (char prefix ATTRIBUTE_UNUSED, char opcode ATTRIBUTE_UNUSED,
01268        const char * args)
01269 {
01270   expressionS reg, port;
01271   const char *p;
01272   char *q;
01273 
01274   p = parse_exp (args, &reg);
01275   if (*p++ != ',')
01276     {
01277       error (_("bad intruction syntax"));
01278       return p;
01279     }
01280 
01281   p = parse_exp (p, &port);
01282   if (reg.X_md == 0
01283       && reg.X_op == O_register
01284       && (reg.X_add_number <= 7 || reg.X_add_number == REG_F)
01285       && (port.X_md))
01286     {
01287       if (port.X_op != O_md1 && port.X_op != O_register)
01288        {
01289          if (REG_A == reg.X_add_number)
01290            {
01291              q = frag_more (1);
01292              *q = 0xDB;
01293              emit_byte (&port, BFD_RELOC_8);
01294            }
01295          else
01296            ill_op ();
01297        }
01298       else
01299        {
01300          if (port.X_add_number == REG_C)
01301            {
01302              if (reg.X_add_number == REG_F)
01303               check_mach (INS_UNDOC);
01304              else
01305               {
01306                 q = frag_more (2);
01307                 *q++ = 0xED;
01308                 *q = 0x40|((reg.X_add_number&7)<<3);
01309               }
01310            }
01311          else
01312            ill_op ();
01313        }
01314     }
01315   else
01316     ill_op ();
01317   return p;
01318 }
01319 
01320 static const char *
01321 emit_out (char prefix ATTRIBUTE_UNUSED, char opcode ATTRIBUTE_UNUSED,
01322         const char * args)
01323 {
01324   expressionS reg, port;
01325   const char *p;
01326   char *q;
01327 
01328   p = parse_exp (args, & port);
01329   if (*p++ != ',')
01330     {
01331       error (_("bad intruction syntax"));
01332       return p;
01333     }
01334   p = parse_exp (p, &reg);
01335   if (!port.X_md)
01336     { ill_op (); return p; }
01337   /* Allow "out (c), 0" as unportable instruction.  */
01338   if (reg.X_op == O_constant && reg.X_add_number == 0)
01339     {
01340       check_mach (INS_UNPORT);
01341       reg.X_op = O_register;
01342       reg.X_add_number = 6;
01343     }
01344   if (reg.X_md
01345       || reg.X_op != O_register
01346       || reg.X_add_number > 7)
01347     ill_op ();
01348   else
01349     if (port.X_op != O_register && port.X_op != O_md1)
01350       {
01351        if (REG_A == reg.X_add_number)
01352          {
01353            q = frag_more (1);
01354            *q = 0xD3;
01355            emit_byte (&port, BFD_RELOC_8);
01356          }
01357        else
01358          ill_op ();
01359       }
01360     else
01361       {
01362        if (REG_C == port.X_add_number)
01363          {
01364            q = frag_more (2);
01365            *q++ = 0xED;
01366            *q = 0x41 | (reg.X_add_number << 3);
01367          }
01368        else
01369          ill_op ();
01370       }
01371   return p;
01372 }
01373 
01374 static const char *
01375 emit_rst (char prefix ATTRIBUTE_UNUSED, char opcode, const char * args)
01376 {
01377   expressionS addr;
01378   const char *p;
01379   char *q;
01380 
01381   p = parse_exp (args, &addr);
01382   if (addr.X_op != O_constant)
01383     {
01384       error ("rst needs constant address");
01385       return p;
01386     }
01387 
01388   if (addr.X_add_number & ~(7 << 3))
01389     ill_op ();
01390   else
01391     {
01392       q = frag_more (1);
01393       *q = opcode + (addr.X_add_number & (7 << 3));
01394     }
01395   return p;
01396 }
01397 
01398 static void
01399 emit_ldxhl (char prefix, char opcode, expressionS *src, expressionS *d)
01400 {
01401   char *q;
01402 
01403   if (src->X_md)
01404     ill_op ();
01405   else
01406     {
01407       if (src->X_op == O_register)
01408        {
01409          if (src->X_add_number>7)
01410            ill_op ();
01411          if (prefix)
01412            {
01413              q = frag_more (2);
01414              *q++ = prefix;
01415            }
01416          else
01417        q = frag_more (1);
01418          *q = opcode + src->X_add_number;
01419          if (d)
01420            emit_byte (d, BFD_RELOC_Z80_DISP8);
01421        }
01422       else
01423        {
01424          if (prefix)
01425            {
01426              q = frag_more (2);
01427              *q++ = prefix;
01428            }
01429          else
01430            q = frag_more (1);
01431          *q = opcode^0x46;
01432          if (d)
01433            emit_byte (d, BFD_RELOC_Z80_DISP8);
01434          emit_byte (src, BFD_RELOC_8);
01435        }
01436     }
01437 }
01438 
01439 static void
01440 emit_ldreg (int dest, expressionS * src)
01441 {
01442   char *q;
01443   int rnum;
01444 
01445   switch (dest)
01446     {
01447       /* 8 Bit ld group:  */
01448     case REG_I:
01449     case REG_R:
01450       if (src->X_md == 0 && src->X_op == O_register && src->X_add_number == REG_A)
01451        {
01452          q = frag_more (2);
01453          *q++ = 0xED;
01454          *q = (dest == REG_I) ? 0x47 : 0x4F;
01455        }
01456       else
01457        ill_op ();
01458       break;
01459 
01460     case REG_A:
01461       if ((src->X_md) && src->X_op != O_register && src->X_op != O_md1)
01462        {
01463          q = frag_more (1);
01464          *q = 0x3A;
01465          emit_word (src);
01466          break;
01467        }
01468 
01469       if ((src->X_md)
01470          && src->X_op == O_register
01471          && (src->X_add_number == REG_BC || src->X_add_number == REG_DE))
01472        {
01473          q = frag_more (1);
01474          *q = 0x0A + ((dest & 1) << 4);
01475          break;
01476        }
01477 
01478       if ((!src->X_md)
01479          && src->X_op == O_register
01480          && (src->X_add_number == REG_R || src->X_add_number == REG_I))
01481        {
01482          q = frag_more (2);
01483          *q++ = 0xED;
01484          *q = (src->X_add_number == REG_I) ? 0x57 : 0x5F;
01485          break;
01486        }
01487       /* Fall through.  */
01488     case REG_B:
01489     case REG_C:
01490     case REG_D:
01491     case REG_E:
01492       emit_sx (0, 0x40 + (dest << 3), src);
01493       break;
01494 
01495     case REG_H:
01496     case REG_L:
01497       if ((src->X_md == 0)
01498          && (src->X_op == O_register)
01499          && (src->X_add_number & R_INDEX))
01500        ill_op ();
01501       else
01502        emit_sx (0, 0x40 + (dest << 3), src);
01503       break;
01504 
01505     case R_IX | REG_H:
01506     case R_IX | REG_L:
01507     case R_IY | REG_H:
01508     case R_IY | REG_L:
01509       if (src->X_md)
01510        {
01511          ill_op ();
01512          break;
01513        }
01514       check_mach (INS_UNDOC);
01515       if (src-> X_op == O_register)
01516        {
01517          rnum = src->X_add_number;
01518          if ((rnum & ~R_INDEX) < 8
01519              && ((rnum & R_INDEX) == (dest & R_INDEX)
01520                  || (   (rnum & ~R_INDEX) != REG_H
01521                      && (rnum & ~R_INDEX) != REG_L)))
01522            {
01523              q = frag_more (2);
01524              *q++ = (dest & R_IX) ? 0xDD : 0xFD;
01525              *q = 0x40 + ((dest & 0x07) << 3) + (rnum & 7);
01526            }
01527          else
01528            ill_op ();
01529        }
01530       else
01531        {
01532          q = frag_more (2);
01533          *q++ = (dest & R_IX) ? 0xDD : 0xFD;
01534          *q = 0x06 + ((dest & 0x07) << 3);
01535          emit_byte (src, BFD_RELOC_8);
01536        }
01537       break;
01538 
01539       /* 16 Bit ld group:  */
01540     case REG_SP:
01541       if (src->X_md == 0
01542          && src->X_op == O_register
01543          && REG_HL == (src->X_add_number &~ R_INDEX))
01544        {
01545          q = frag_more ((src->X_add_number & R_INDEX) ? 2 : 1);
01546          if (src->X_add_number & R_INDEX)
01547            *q++ = (src->X_add_number & R_IX) ? 0xDD : 0xFD;
01548          *q = 0xF9;
01549          break;
01550        }
01551       /* Fall through.  */
01552     case REG_BC:
01553     case REG_DE:
01554       if (src->X_op == O_register || src->X_op == O_md1)
01555        ill_op ();
01556       q = frag_more (src->X_md ? 2 : 1);
01557       if (src->X_md)
01558        {
01559          *q++ = 0xED;
01560          *q = 0x4B + ((dest & 3) << 4);
01561        }
01562       else
01563        *q = 0x01 + ((dest & 3) << 4);
01564       emit_word (src);
01565       break;
01566 
01567     case REG_HL:
01568     case REG_HL | R_IX:
01569     case REG_HL | R_IY:
01570       if (src->X_op == O_register || src->X_op == O_md1)
01571        ill_op ();
01572       q = frag_more ((dest & R_INDEX) ? 2 : 1);
01573       if (dest & R_INDEX)
01574        * q ++ = (dest & R_IX) ? 0xDD : 0xFD;
01575       *q = (src->X_md) ? 0x2A : 0x21;
01576       emit_word (src);
01577       break;
01578 
01579     case REG_AF:
01580     case REG_F:
01581       ill_op ();
01582       break;
01583 
01584     default:
01585       abort ();
01586     }
01587 }
01588 
01589 static const char *
01590 emit_ld (char prefix_in ATTRIBUTE_UNUSED, char opcode_in ATTRIBUTE_UNUSED,
01591        const char * args)
01592 {
01593   expressionS dst, src;
01594   const char *p;
01595   char *q;
01596   char prefix, opcode;
01597 
01598   p = parse_exp (args, &dst);
01599   if (*p++ != ',')
01600     error (_("bad intruction syntax"));
01601   p = parse_exp (p, &src);
01602 
01603   switch (dst.X_op)
01604     {
01605     case O_md1:
01606       emit_ldxhl ((dst.X_add_number & R_IX) ? 0xDD : 0xFD, 0x70,
01607                 &src, symbol_get_value_expression (dst.X_add_symbol));
01608       break;
01609 
01610     case O_register:
01611       if (dst.X_md)
01612        {
01613          switch (dst.X_add_number)
01614            {
01615            case REG_BC:
01616            case REG_DE:
01617              if (src.X_md == 0 && src.X_op == O_register && src.X_add_number == REG_A)
01618               {
01619                 q = frag_more (1);
01620                 *q = 0x02 + ( (dst.X_add_number & 1) << 4);
01621               }
01622              else
01623               ill_op ();
01624              break;
01625            case REG_HL:
01626              emit_ldxhl (0, 0x70, &src, NULL);
01627              break;
01628            default:
01629              ill_op ();
01630            }
01631        }
01632       else
01633        emit_ldreg (dst.X_add_number, &src);
01634       break;
01635 
01636     default:
01637       if (src.X_md != 0 || src.X_op != O_register)
01638        ill_op ();
01639       prefix = opcode = 0;
01640       switch (src.X_add_number)
01641        {
01642        case REG_A:
01643          opcode = 0x32; break;
01644        case REG_BC: case REG_DE: case REG_SP:
01645          prefix = 0xED; opcode = 0x43 + ((src.X_add_number&3)<<4); break;
01646        case REG_HL:
01647          opcode = 0x22; break;
01648        case REG_HL|R_IX:
01649          prefix = 0xDD; opcode = 0x22; break;
01650        case REG_HL|R_IY:
01651          prefix = 0xFD; opcode = 0x22; break;
01652        }
01653       if (opcode)
01654        {
01655          q = frag_more (prefix?2:1);
01656          if (prefix)
01657            *q++ = prefix;
01658          *q = opcode;
01659          emit_word (&dst);
01660        }
01661       else
01662        ill_op ();
01663     }
01664   return p;
01665 }
01666 
01667 static void
01668 emit_data (int size ATTRIBUTE_UNUSED)
01669 {
01670   const char *p, *q;
01671   char *u, quote;
01672   int cnt;
01673   expressionS exp;
01674 
01675   if (is_it_end_of_statement ())
01676     {
01677       demand_empty_rest_of_line ();
01678       return;
01679     }
01680   p = skip_space (input_line_pointer);
01681 
01682   do
01683     {
01684       if (*p == '\"' || *p == '\'')
01685        {
01686            for (quote = *p, q = ++p, cnt = 0; *p && quote != *p; ++p, ++cnt)
01687              ;
01688            u = frag_more (cnt);
01689            memcpy (u, q, cnt);
01690            if (!*p)
01691              as_warn (_("unterminated string"));
01692            else
01693              p = skip_space (p+1);
01694        }
01695       else
01696        {
01697          p = parse_exp (p, &exp);
01698          if (exp.X_op == O_md1 || exp.X_op == O_register)
01699            {
01700              ill_op ();
01701              break;
01702            }
01703          if (exp.X_md)
01704            as_warn (_("parentheses ignored"));
01705          emit_byte (&exp, BFD_RELOC_8);
01706          p = skip_space (p);
01707        }
01708     }
01709   while (*p++ == ',') ;
01710   input_line_pointer = (char *)(p-1);
01711 }
01712 
01713 static const char *
01714 emit_mulub (char prefix ATTRIBUTE_UNUSED, char opcode, const char * args)
01715 {
01716   const char *p;
01717 
01718   p = skip_space (args);
01719   if (TOLOWER (*p++) != 'a' || *p++ != ',')
01720     ill_op ();
01721   else
01722     {
01723       char *q, reg;
01724 
01725       reg = TOLOWER (*p++);
01726       switch (reg)
01727        {
01728        case 'b':
01729        case 'c':
01730        case 'd':
01731        case 'e':
01732          check_mach (INS_R800);
01733          if (!*skip_space (p))
01734            {
01735              q = frag_more (2);
01736              *q++ = prefix;
01737              *q = opcode + ((reg - 'b') << 3);
01738              break;
01739            }
01740        default:
01741          ill_op ();
01742        }
01743     }
01744   return p;
01745 }
01746 
01747 static const char *
01748 emit_muluw (char prefix ATTRIBUTE_UNUSED, char opcode, const char * args)
01749 {
01750   const char *p;
01751 
01752   p = skip_space (args);
01753   if (TOLOWER (*p++) != 'h' || TOLOWER (*p++) != 'l' || *p++ != ',')
01754     ill_op ();
01755   else
01756     {
01757       expressionS reg;
01758       char *q;
01759 
01760       p = parse_exp (p, & reg);
01761 
01762       if ((!reg.X_md) && reg.X_op == O_register)
01763        switch (reg.X_add_number)
01764          {
01765          case REG_BC:
01766          case REG_SP:
01767            check_mach (INS_R800);
01768            q = frag_more (2);
01769            *q++ = prefix;
01770            *q = opcode + ((reg.X_add_number & 3) << 4);
01771            break;
01772          default:
01773            ill_op ();
01774          }
01775     }
01776   return p;
01777 }
01778 
01779 /* Port specific pseudo ops.  */
01780 const pseudo_typeS md_pseudo_table[] =
01781 {
01782   { "db" , emit_data, 1},
01783   { "d24", cons, 3},
01784   { "d32", cons, 4},
01785   { "def24", cons, 3},
01786   { "def32", cons, 4},
01787   { "defb", emit_data, 1},  
01788   { "defs", s_space, 1}, /* Synonym for ds on some assemblers.  */
01789   { "defw", cons, 2},
01790   { "ds",   s_space, 1}, /* Fill with bytes rather than words.  */
01791   { "dw", cons, 2},
01792   { "psect", obj_coff_section, 0}, /* TODO: Translate attributes.  */
01793   { "set", 0, 0},           /* Real instruction on z80.  */
01794   { NULL, 0, 0 }
01795 } ;
01796 
01797 static table_t instab[] =
01798 {
01799   { "adc",  0x88, 0x4A, emit_adc },
01800   { "add",  0x80, 0x09, emit_add },
01801   { "and",  0x00, 0xA0, emit_s },
01802   { "bit",  0xCB, 0x40, emit_bit },
01803   { "call", 0xCD, 0xC4, emit_jpcc },
01804   { "ccf",  0x00, 0x3F, emit_insn },
01805   { "cp",   0x00, 0xB8, emit_s },
01806   { "cpd",  0xED, 0xA9, emit_insn },
01807   { "cpdr", 0xED, 0xB9, emit_insn },
01808   { "cpi",  0xED, 0xA1, emit_insn },
01809   { "cpir", 0xED, 0xB1, emit_insn },
01810   { "cpl",  0x00, 0x2F, emit_insn },
01811   { "daa",  0x00, 0x27, emit_insn },
01812   { "dec",  0x0B, 0x05, emit_incdec },
01813   { "di",   0x00, 0xF3, emit_insn },
01814   { "djnz", 0x00, 0x10, emit_jr },
01815   { "ei",   0x00, 0xFB, emit_insn },
01816   { "ex",   0x00, 0x00, emit_ex},
01817   { "exx",  0x00, 0xD9, emit_insn },
01818   { "halt", 0x00, 0x76, emit_insn },
01819   { "im",   0xED, 0x46, emit_im },
01820   { "in",   0x00, 0x00, emit_in },
01821   { "inc",  0x03, 0x04, emit_incdec },
01822   { "ind",  0xED, 0xAA, emit_insn },
01823   { "indr", 0xED, 0xBA, emit_insn },
01824   { "ini",  0xED, 0xA2, emit_insn },
01825   { "inir", 0xED, 0xB2, emit_insn },
01826   { "jp",   0xC3, 0xC2, emit_jpcc },
01827   { "jr",   0x18, 0x20, emit_jrcc },
01828   { "ld",   0x00, 0x00, emit_ld },
01829   { "ldd",  0xED, 0xA8, emit_insn },
01830   { "lddr", 0xED, 0xB8, emit_insn },
01831   { "ldi",  0xED, 0xA0, emit_insn },
01832   { "ldir", 0xED, 0xB0, emit_insn },
01833   { "mulub", 0xED, 0xC5, emit_mulub }, /* R800 only.  */
01834   { "muluw", 0xED, 0xC3, emit_muluw }, /* R800 only.  */
01835   { "neg",  0xed, 0x44, emit_insn },
01836   { "nop",  0x00, 0x00, emit_insn },
01837   { "or",   0x00, 0xB0, emit_s },
01838   { "otdr", 0xED, 0xBB, emit_insn },
01839   { "otir", 0xED, 0xB3, emit_insn },
01840   { "out",  0x00, 0x00, emit_out },
01841   { "outd", 0xED, 0xAB, emit_insn },
01842   { "outi", 0xED, 0xA3, emit_insn },
01843   { "pop",  0x00, 0xC1, emit_pop },
01844   { "push", 0x00, 0xC5, emit_pop },
01845   { "res",  0xCB, 0x80, emit_bit },
01846   { "ret",  0xC9, 0xC0, emit_retcc },
01847   { "reti", 0xED, 0x4D, emit_insn },
01848   { "retn", 0xED, 0x45, emit_insn },
01849   { "rl",   0xCB, 0x10, emit_mr },
01850   { "rla",  0x00, 0x17, emit_insn },
01851   { "rlc",  0xCB, 0x00, emit_mr },
01852   { "rlca", 0x00, 0x07, emit_insn },
01853   { "rld",  0xED, 0x6F, emit_insn },
01854   { "rr",   0xCB, 0x18, emit_mr },
01855   { "rra",  0x00, 0x1F, emit_insn },
01856   { "rrc",  0xCB, 0x08, emit_mr },
01857   { "rrca", 0x00, 0x0F, emit_insn },
01858   { "rrd",  0xED, 0x67, emit_insn },
01859   { "rst",  0x00, 0xC7, emit_rst},
01860   { "sbc",  0x98, 0x42, emit_adc },
01861   { "scf",  0x00, 0x37, emit_insn },
01862   { "set",  0xCB, 0xC0, emit_bit },
01863   { "sla",  0xCB, 0x20, emit_mr },
01864   { "sli",  0xCB, 0x30, emit_mr },
01865   { "sll",  0xCB, 0x30, emit_mr },
01866   { "sra",  0xCB, 0x28, emit_mr },
01867   { "srl",  0xCB, 0x38, emit_mr },
01868   { "sub",  0x00, 0x90, emit_s },
01869   { "xor",  0x00, 0xA8, emit_s },
01870 } ;
01871 
01872 void
01873 md_assemble (char* str)
01874 {
01875   const char *p;
01876   char * old_ptr;
01877   int i;
01878   table_t *insp;
01879 
01880   err_flag = 0;
01881   old_ptr = input_line_pointer;
01882   p = skip_space (str);
01883   for (i = 0; (i < BUFLEN) && (ISALPHA (*p));)
01884     buf[i++] = TOLOWER (*p++);
01885 
01886   if (i == BUFLEN)
01887     {
01888       buf[BUFLEN-3] = buf[BUFLEN-2] = '.'; /* Mark opcode as abbreviated.  */
01889       buf[BUFLEN-1] = 0;
01890       as_bad (_("Unknown instruction '%s'"), buf);
01891     }
01892   else if ((*p) && (!ISSPACE (*p)))
01893     as_bad (_("syntax error"));
01894   else 
01895     {
01896       buf[i] = 0;
01897       p = skip_space (p);
01898       key = buf;
01899       
01900       insp = bsearch (&key, instab, ARRAY_SIZE (instab),
01901                   sizeof (instab[0]), key_cmp);
01902       if (!insp)
01903        as_bad (_("Unknown instruction '%s'"), buf);
01904       else
01905        {
01906          p = insp->fp (insp->prefix, insp->opcode, p);
01907          p = skip_space (p);
01908        if ((!err_flag) && *p)
01909          as_bad (_("junk at end of line, first unrecognized character is `%c'"),
01910                 *p);
01911        }
01912     }
01913   input_line_pointer = old_ptr;
01914 }
01915 
01916 void
01917 md_apply_fix (fixS * fixP, valueT* valP, segT seg ATTRIBUTE_UNUSED)
01918 {
01919   long val = * (long *) valP;
01920   char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
01921 
01922   switch (fixP->fx_r_type)
01923     {
01924     case BFD_RELOC_8_PCREL:
01925       if (fixP->fx_addsy)
01926         {
01927           fixP->fx_no_overflow = 1;
01928           fixP->fx_done = 0;
01929         }
01930       else
01931         {
01932          fixP->fx_no_overflow = (-128 <= val && val < 128);
01933          if (!fixP->fx_no_overflow)
01934             as_bad_where (fixP->fx_file, fixP->fx_line,
01935                        _("relative jump out of range"));
01936          *buf++ = val;
01937           fixP->fx_done = 1;
01938         }
01939       break;
01940 
01941     case BFD_RELOC_Z80_DISP8:
01942       if (fixP->fx_addsy)
01943         {
01944           fixP->fx_no_overflow = 1;
01945           fixP->fx_done = 0;
01946         }
01947       else
01948         {
01949          fixP->fx_no_overflow = (-128 <= val && val < 128);
01950          if (!fixP->fx_no_overflow)
01951             as_bad_where (fixP->fx_file, fixP->fx_line,
01952                        _("index offset  out of range"));
01953          *buf++ = val;
01954           fixP->fx_done = 1;
01955         }
01956       break;
01957 
01958     case BFD_RELOC_8:
01959       if (val > 255 || val < -128)
01960        as_warn_where (fixP->fx_file, fixP->fx_line, _("overflow"));
01961       *buf++ = val;
01962       fixP->fx_no_overflow = 1; 
01963       if (fixP->fx_addsy == NULL)
01964        fixP->fx_done = 1;
01965       break;
01966 
01967     case BFD_RELOC_16:
01968       *buf++ = val;
01969       *buf++ = (val >> 8);
01970       fixP->fx_no_overflow = 1; 
01971       if (fixP->fx_addsy == NULL)
01972        fixP->fx_done = 1;
01973       break;
01974 
01975     case BFD_RELOC_24: /* Def24 may produce this.  */
01976       *buf++ = val;
01977       *buf++ = (val >> 8);
01978       *buf++ = (val >> 16);
01979       fixP->fx_no_overflow = 1; 
01980       if (fixP->fx_addsy == NULL)
01981        fixP->fx_done = 1;
01982       break;
01983 
01984     case BFD_RELOC_32: /* Def32 and .long may produce this.  */
01985       *buf++ = val;
01986       *buf++ = (val >> 8);
01987       *buf++ = (val >> 16);
01988       *buf++ = (val >> 24);
01989       if (fixP->fx_addsy == NULL)
01990        fixP->fx_done = 1;
01991       break;
01992 
01993     default:
01994       printf (_("md_apply_fix: unknown r_type 0x%x\n"), fixP->fx_r_type);
01995       abort ();
01996     }
01997 }
01998 
01999 /* GAS will call this to generate a reloc.  GAS will pass the
02000    resulting reloc to `bfd_install_relocation'.  This currently works
02001    poorly, as `bfd_install_relocation' often does the wrong thing, and
02002    instances of `tc_gen_reloc' have been written to work around the
02003    problems, which in turns makes it difficult to fix
02004    `bfd_install_relocation'.  */
02005 
02006 /* If while processing a fixup, a reloc really
02007    needs to be created then it is done here.  */
02008 
02009 arelent *
02010 tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED , fixS *fixp)
02011 {
02012   arelent *reloc;
02013 
02014   if (! bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type))
02015     {
02016       as_bad_where (fixp->fx_file, fixp->fx_line,
02017                   _("reloc %d not supported by object file format"),
02018                   (int) fixp->fx_r_type);
02019       return NULL;
02020     }
02021 
02022   reloc               = xmalloc (sizeof (arelent));
02023   reloc->sym_ptr_ptr  = xmalloc (sizeof (asymbol *));
02024   *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
02025   reloc->address      = fixp->fx_frag->fr_address + fixp->fx_where;
02026   reloc->howto        = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
02027   reloc->addend       = fixp->fx_offset;
02028 
02029   return reloc;
02030 }
02031