change the type of some fields to bfd_reloc_code_real_type
[deliverable/binutils-gdb.git] / gas / config / tc-z80.c
index 28f69b1d54bac6fc6a2c938b3024e2aaae755800..dcc74f6ed58a60c310551ebd27926fe143fe87bc 100644 (file)
@@ -1,12 +1,12 @@
 /* tc-z80.c -- Assemble code for the Zilog Z80 and ASCII R800
 /* tc-z80.c -- Assemble code for the Zilog Z80 and ASCII R800
-   Copyright 2005 Free Software Foundation, Inc.
+   Copyright (C) 2005-2016 Free Software Foundation, Inc.
    Contributed by Arnold Metselaar <arnold_m@operamail.com>
 
    This file is part of GAS, the GNU Assembler.
 
    GAS is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    Contributed by Arnold Metselaar <arnold_m@operamail.com>
 
    This file is part of GAS, the GNU Assembler.
 
    GAS is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
+   the Free Software Foundation; either version 3, or (at your option)
    any later version.
 
    GAS is distributed in the hope that it will be useful,
    any later version.
 
    GAS is distributed in the hope that it will be useful,
    02110-1301, USA.  */
 
 #include "as.h"
    02110-1301, USA.  */
 
 #include "as.h"
-#include "listing.h"
-#include "bfd.h"
 #include "safe-ctype.h"
 #include "subsegs.h"
 #include "safe-ctype.h"
 #include "subsegs.h"
-#include "symbols.h"
-#include "libiberty.h"
 
 /* Exported constants.  */
 const char comment_chars[] = ";\0";
 
 /* Exported constants.  */
 const char comment_chars[] = ";\0";
@@ -85,7 +81,7 @@ static int ins_err = INS_R800;
 static int ins_used = INS_Z80;
 
 int
 static int ins_used = INS_Z80;
 
 int
-md_parse_option (int c, char* arg ATTRIBUTE_UNUSED)
+md_parse_option (int c, const char* arg ATTRIBUTE_UNUSED)
 {
   switch (c)
     {
 {
   switch (c)
     {
@@ -165,14 +161,95 @@ Default: -z80 -ignore-undocument-instructions -warn-unportable-instructions.\n")
 
 static symbolS * zero;
 
 
 static symbolS * zero;
 
+struct reg_entry
+{
+  const char* name;
+  int number;
+};
+#define R_STACKABLE (0x80)
+#define R_ARITH     (0x40)
+#define R_IX        (0x20)
+#define R_IY        (0x10)
+#define R_INDEX     (R_IX | R_IY)
+
+#define REG_A (7)
+#define REG_B (0)
+#define REG_C (1)
+#define REG_D (2)
+#define REG_E (3)
+#define REG_H (4)
+#define REG_L (5)
+#define REG_F (6 | 8)
+#define REG_I (9)
+#define REG_R (10)
+
+#define REG_AF (3 | R_STACKABLE)
+#define REG_BC (0 | R_STACKABLE | R_ARITH)
+#define REG_DE (1 | R_STACKABLE | R_ARITH)
+#define REG_HL (2 | R_STACKABLE | R_ARITH)
+#define REG_IX (REG_HL | R_IX)
+#define REG_IY (REG_HL | R_IY)
+#define REG_SP (3 | R_ARITH)
+
+static const struct reg_entry regtable[] =
+{
+  {"a",  REG_A },
+  {"af", REG_AF },
+  {"b",  REG_B },
+  {"bc", REG_BC },
+  {"c",  REG_C },
+  {"d",  REG_D },
+  {"de", REG_DE },
+  {"e",  REG_E },
+  {"f",  REG_F },
+  {"h",  REG_H },
+  {"hl", REG_HL },
+  {"i",  REG_I },
+  {"ix", REG_IX },
+  {"ixh",REG_H | R_IX },
+  {"ixl",REG_L | R_IX },
+  {"iy", REG_IY },
+  {"iyh",REG_H | R_IY },
+  {"iyl",REG_L | R_IY },
+  {"l",  REG_L },
+  {"r",  REG_R },
+  {"sp", REG_SP },
+} ;
+
+#define BUFLEN 8 /* Large enough for any keyword.  */
+
 void
 md_begin (void)
 {
 void
 md_begin (void)
 {
-  expressionS nul;
+  expressionS nul, reg;
   char * p;
   char * p;
+  unsigned int i, j, k;
+  char buf[BUFLEN];
 
 
+  reg.X_op = O_register;
+  reg.X_md = 0;
+  reg.X_add_symbol = reg.X_op_symbol = 0;
+  for ( i = 0 ; i < ARRAY_SIZE ( regtable ) ; ++i )
+    {
+      reg.X_add_number = regtable[i].number;
+      k = strlen ( regtable[i].name );
+      buf[k] = 0;
+      if ( k+1 < BUFLEN )
+        {
+          for ( j = ( 1<<k ) ; j ; --j )
+            {
+              for ( k = 0 ; regtable[i].name[k] ; ++k )
+                {
+                  buf[k] = ( j & ( 1<<k ) ) ? TOUPPER ( regtable[i].name[k] ) : regtable[i].name[k];
+                }
+              symbolS * psym = symbol_find_or_make(buf);
+             S_SET_SEGMENT(psym, reg_section);
+             symbol_set_value_expression(psym, &reg);
+            }
+        }
+    }
   p = input_line_pointer;
   p = input_line_pointer;
-  input_line_pointer = "0";
+  input_line_pointer = (char *) "0";
   nul.X_md=0;
   expression (& nul);
   input_line_pointer = p;
   nul.X_md=0;
   expression (& nul);
   input_line_pointer = p;
@@ -210,16 +287,6 @@ z80_md_end (void)
   bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach_type);
 }
 
   bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach_type);
 }
 
-/* Port specific features.  */
-const pseudo_typeS md_pseudo_table[] =
-{
-  { "defs",  s_space, 1}, /* Synonym for ds on some assemblers.  */
-  { "ds",    s_space, 1}, /* Fill with bytes rather than words.  */
-  { "psect", obj_coff_section, 0}, /* TODO: Translate attributes.  */
-  { "set", 0, 0},              /* Real instruction on z80.  */
-  { NULL, 0, 0 }
-} ;
-
 static const char *
 skip_space (const char *s)
 {
 static const char *
 skip_space (const char *s)
 {
@@ -262,47 +329,49 @@ z80_start_line_hook (void)
          break;
        }
     }
          break;
        }
     }
-  /* Check for <label>[:] (EQU|DEFL) <value>.  */
+  /* Check for <label>[:] [.](EQU|DEFL) <value>.  */
   if (is_name_beginner (*input_line_pointer))
     {
   if (is_name_beginner (*input_line_pointer))
     {
+      char *name;
       char c, *rest, *line_start;
       int len;
 
       line_start = input_line_pointer;
       char c, *rest, *line_start;
       int len;
 
       line_start = input_line_pointer;
-      LISTING_NEWLINE ();
       if (ignore_input ())
        return 0;
 
       if (ignore_input ())
        return 0;
 
-      c = get_symbol_end ();
+      c = get_symbol_name (&name);
       rest = input_line_pointer + 1;
 
       if (*rest == ':')
        ++rest;
       if (*rest == ' ' || *rest == '\t')
        ++rest;
       rest = input_line_pointer + 1;
 
       if (*rest == ':')
        ++rest;
       if (*rest == ' ' || *rest == '\t')
        ++rest;
+      if (*rest == '.')
+       ++rest;
       if (strncasecmp (rest, "EQU", 3) == 0)
        len = 3;
       else if (strncasecmp (rest, "DEFL", 4) == 0)
        len = 4;
       else
        len = 0;
       if (strncasecmp (rest, "EQU", 3) == 0)
        len = 3;
       else if (strncasecmp (rest, "DEFL", 4) == 0)
        len = 4;
       else
        len = 0;
-      if (len && (rest[len] == ' ' || rest[len] == '\t'))
+      if (len && (!ISALPHA(rest[len]) ) )
        {
          /* Handle assignment here.  */
        {
          /* Handle assignment here.  */
-         input_line_pointer = rest + len;
          if (line_start[-1] == '\n')
          if (line_start[-1] == '\n')
-           bump_line_counters ();
-         /* Most Z80 assemblers require the first definition of a
-             label to use "EQU" and redefinitions to have "DEFL".
-             That does not fit the way GNU as deals with labels, so
-             GNU as is more permissive.  */
-         equals (line_start, TRUE);
+           {
+             bump_line_counters ();
+             LISTING_NEWLINE ();
+           }
+         input_line_pointer = rest + len - 1;
+         /* Allow redefining with "DEFL" (len == 4), but not with "EQU".  */
+         equals (name, len == 4);
          return 1;
        }
       else
        {
          /* Restore line and pointer.  */
          return 1;
        }
       else
        {
          /* Restore line and pointer.  */
-         *input_line_pointer = c;
+         (void) restore_line_pointer (c);
          input_line_pointer = line_start;
        }
     }
          input_line_pointer = line_start;
        }
     }
@@ -315,7 +384,7 @@ md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
   return NULL;
 }
 
   return NULL;
 }
 
-char *
+const char *
 md_atof (int type ATTRIBUTE_UNUSED, char *litP ATTRIBUTE_UNUSED,
         int *sizeP ATTRIBUTE_UNUSED)
 {
 md_atof (int type ATTRIBUTE_UNUSED, char *litP ATTRIBUTE_UNUSED,
         int *sizeP ATTRIBUTE_UNUSED)
 {
@@ -339,9 +408,9 @@ typedef const char * (asfunc)(char, char, const char*);
 
 typedef struct _table_t
 {
 
 typedef struct _table_t
 {
-  char* name;
-  char prefix;
-  char opcode;
+  const char* name;
+  unsigned char prefix;
+  unsigned char opcode;
   asfunc * fp;
 } table_t;
 
   asfunc * fp;
 } table_t;
 
@@ -356,63 +425,9 @@ key_cmp (const void * a, const void * b)
   return strcmp (str_a, str_b);
 }
 
   return strcmp (str_a, str_b);
 }
 
-#define BUFLEN 8 /* Large enough for any keyword.  */
-
 char buf[BUFLEN];
 const char *key = buf;
 
 char buf[BUFLEN];
 const char *key = buf;
 
-#define R_STACKABLE (0x80)
-#define R_ARITH     (0x40)
-#define R_IX        (0x20)
-#define R_IY        (0x10)
-#define R_INDEX     (R_IX | R_IY)
-
-#define REG_A (7)
-#define REG_B (0)
-#define REG_C (1)
-#define REG_D (2)
-#define REG_E (3)
-#define REG_H (4)
-#define REG_L (5)
-#define REG_F (6 | 8)
-#define REG_I (9)
-#define REG_R (10)
-
-#define REG_AF (3 | R_STACKABLE)
-#define REG_BC (0 | R_STACKABLE | R_ARITH)
-#define REG_DE (1 | R_STACKABLE | R_ARITH)
-#define REG_HL (2 | R_STACKABLE | R_ARITH)
-#define REG_SP (3 | R_ARITH)
-
-static const struct reg_entry
-{
-  char* name;
-  int number;
-} regtable[] =
-{
-  {"a",  REG_A },
-  {"af", REG_AF },
-  {"b",  REG_B },
-  {"bc", REG_BC },
-  {"c",  REG_C },
-  {"d",  REG_D },
-  {"de", REG_DE },
-  {"e",  REG_E },
-  {"f",  REG_F },
-  {"h",  REG_H },
-  {"hl", REG_HL },
-  {"i",  REG_I },
-  {"ix", REG_HL | R_IX },
-  {"ixh",REG_H | R_IX },
-  {"ixl",REG_L | R_IX },
-  {"iy", REG_HL | R_IY },
-  {"iyh",REG_H | R_IY },
-  {"iyl",REG_L | R_IY },
-  {"l",  REG_L },
-  {"r",  REG_R },
-  {"sp", REG_SP },
-} ;
-
 /* Prevent an error on a line from also generating
    a "junk at end of line" error message.  */
 static char err_flag;
 /* Prevent an error on a line from also generating
    a "junk at end of line" error message.  */
 static char err_flag;
@@ -420,7 +435,7 @@ static char err_flag;
 static void
 error (const char * message)
 {
 static void
 error (const char * message)
 {
-  as_bad (message);
+  as_bad ("%s", message);
   err_flag = 1;
 }
 
   err_flag = 1;
 }
 
@@ -447,13 +462,13 @@ wrong_mach (int ins_type)
       p = "instruction only works R800";
       break;
     default:
       p = "instruction only works R800";
       break;
     default:
-      p = 0; /* Not reachables.  */
+      p = 0; /* Not reachable.  */
     }
 
   if (ins_type & ins_err)
     error (_(p));
   else
     }
 
   if (ins_type & ins_err)
     error (_(p));
   else
-    as_warn (_(p));
+    as_warn ("%s", _(p));
 }
 
 static void
 }
 
 static void
@@ -464,70 +479,6 @@ check_mach (int ins_type)
   ins_used |= ins_type;
 }
 
   ins_used |= ins_type;
 }
 
-/* This function tries to subtract two symbols, the generic code does
-   that too, but this function tries harder.
-   The behaviour of this function is not altered by extra
-   fragmentations caused by the code to produce listings.  */
-int
-z80_optimize_expr (expressionS *resultP, operatorT left_op,
-                  expressionS *right)
-{
-  int res, swap, som;
-  fragS *lfrag, *rfrag, *cur;
-
-  res = 0;
-  if (left_op == O_subtract
-      && right->X_op == O_symbol
-      && resultP->X_op == O_symbol)
-    {
-      lfrag = symbol_get_frag (resultP->X_add_symbol);
-      rfrag = symbol_get_frag (right->X_add_symbol);
-
-      if (S_GET_SEGMENT (right->X_add_symbol) !=  undefined_section
-         && (S_GET_SEGMENT (right->X_add_symbol)
-             == S_GET_SEGMENT (resultP->X_add_symbol)))
-       {
-         for (swap = 0; (res == 0) && (swap < 2); ++swap)
-           {
-             if (swap)
-               {
-                 cur = lfrag;
-                 lfrag = rfrag;
-                 rfrag = cur;
-               }
-             else
-               cur = rfrag;
-
-             /* Now som == cur->fr_address - rfrag->address, except
-                the latter may not have been computed yet.  */
-             for (som = 0; cur && cur != lfrag; cur = cur->fr_next)
-               {
-                 if (cur->fr_type == rs_fill) /* Is the size fized?  */
-                   som += cur->fr_fix+cur->fr_offset*cur->fr_var;
-                 else
-                   break;
-               }
-
-             if  (cur == lfrag)
-               {
-                 resultP->X_add_number -= right->X_add_number;
-                 resultP->X_add_number
-                   += (S_GET_VALUE (resultP->X_add_symbol)
-                       - S_GET_VALUE (right->X_add_symbol));
-                 som -= lfrag->fr_address - rfrag->fr_address;
-                 /* Correct the result if the fr_address
-                    fields are not computed yet.  */
-                 resultP->X_add_number += (swap ? -som : som);
-                 resultP->X_op = O_constant;
-                 resultP->X_add_symbol = 0;
-                 res = 1;
-               }
-           }
-       }
-    }
-  return res;
-}
-
 /* Check whether an expression is indirect.  */
 static int
 is_indir (const char *s)
 /* Check whether an expression is indirect.  */
 static int
 is_indir (const char *s)
@@ -573,88 +524,93 @@ is_indir (const char *s)
   return indir;
 }
 
   return indir;
 }
 
-/* Parse general expression.  */
+/* Check whether a symbol involves a register.  */
+static int
+contains_register(symbolS *sym)
+{
+  if (sym)
+  {
+    expressionS * ex = symbol_get_value_expression(sym);
+    return (O_register == ex->X_op)
+      || (ex->X_add_symbol && contains_register(ex->X_add_symbol))
+      || (ex->X_op_symbol && contains_register(ex->X_op_symbol));
+  }
+  else
+    return 0;
+}
+
+/* Parse general expression, not loooking for indexed adressing.  */
 static const char *
 static const char *
-parse_exp2 (const char *s, expressionS *op, segT *pseg)
+parse_exp_not_indexed (const char *s, expressionS *op)
 {
   const char *p;
   int indir;
 {
   const char *p;
   int indir;
-  int i;
-  const struct reg_entry * regp;
-  expressionS offset;
 
   p = skip_space (s);
   op->X_md = indir = is_indir (p);
 
   p = skip_space (s);
   op->X_md = indir = is_indir (p);
-  if (indir)
-    p = skip_space (p + 1);
-
-  for (i = 0; i < BUFLEN; ++i)
-    {
-      if (!ISALPHA (p[i])) /* Register names consist of letters only.  */
-       break;
-      buf[i] = TOLOWER (p[i]);
-    }
-
-  if ((i < BUFLEN) && ((p[i] == 0) || (strchr (")+-, \t", p[i]))))
+  input_line_pointer = (char*) s ;
+  expression (op);
+  switch (op->X_op)
     {
     {
-      buf[i] = 0;
-      regp = bsearch (& key, regtable, ARRAY_SIZE (regtable),
-                     sizeof (regtable[0]), key_cmp);
-      if (regp)
-       {
-         *pseg = reg_section;
-         op->X_add_symbol = op->X_op_symbol = 0;
-         op->X_add_number = regp->number;
-         op->X_op = O_register;
-         p += strlen (regp->name);
-         p = skip_space (p);
-         if (indir)
-           {
-             if (*p == ')')
-               ++p;
-             if ((regp->number & R_INDEX) && (regp->number & R_ARITH))
-               {
-                 op->X_op = O_md1;
-
-                 if  ((*p == '+') || (*p == '-'))
-                   {
-                     input_line_pointer = (char*) p;
-                     expression (& offset);
-                     p = skip_space (input_line_pointer);
-                     if (*p != ')')
-                       error (_("bad offset expression syntax"));
-                     else
-                       ++ p;
-                     op->X_add_symbol = make_expr_symbol (& offset);
-                     return p;
-                   }
-
-                 /* We treat (i[xy]) as (i[xy]+0), which is how it will
-                    end up anyway, unless we're processing jp (i[xy]).  */
-                 op->X_add_symbol = zero;
-               }
-           }
-         p = skip_space (p);
-
-         if ((*p == 0) || (*p == ','))
-           return p;
-       }
+    case O_absent:
+      error (_("missing operand"));
+      break;
+    case O_illegal:
+      error (_("bad expression syntax"));
+      break;
+    default:
+      break;
     }
     }
-  /* Not an argument involving a register; use the generic parser.  */
-  input_line_pointer = (char*) s ;
-  *pseg = expression (op);
-  if (op->X_op == O_absent)
-    error (_("missing operand"));
-  if (op->X_op == O_illegal)
-    error (_("bad expression syntax"));
   return input_line_pointer;
 }
 
   return input_line_pointer;
 }
 
+/* Parse expression, change operator to O_md1 for indexed addressing*/
 static const char *
 parse_exp (const char *s, expressionS *op)
 {
 static const char *
 parse_exp (const char *s, expressionS *op)
 {
-  segT dummy;
-  return parse_exp2 (s, op, & dummy);
+  const char* res = parse_exp_not_indexed (s, op);
+  switch (op->X_op)
+    {
+    case O_add:
+    case O_subtract:
+      if (op->X_md && (O_register == symbol_get_value_expression(op->X_add_symbol)->X_op))
+        {
+         int rnum = symbol_get_value_expression(op->X_add_symbol)->X_add_number;
+         if ( ((REG_IX != rnum) && (REG_IY != rnum)) || contains_register(op->X_op_symbol) )
+           {
+             ill_op();
+           }
+         else
+           {
+             if (O_subtract == op->X_op)
+               {
+                 expressionS minus;
+                 minus.X_op = O_uminus;
+                 minus.X_add_number = 0;
+                 minus.X_add_symbol = op->X_op_symbol;
+                 minus.X_op_symbol = 0;
+                 op->X_op_symbol = make_expr_symbol(&minus);
+                 op->X_op = O_add;
+               }
+             symbol_get_value_expression(op->X_op_symbol)->X_add_number += op->X_add_number;
+             op->X_add_number = rnum;
+             op->X_add_symbol = op->X_op_symbol;
+             op->X_op_symbol = 0;
+             op->X_op = O_md1;
+           }
+       }
+      break;
+    case O_register:
+      if ( op->X_md && ((REG_IX == op->X_add_number)||(REG_IY == op->X_add_number)) )
+        {
+         op->X_add_symbol = zero;
+         op->X_op = O_md1;
+       }
+       break;
+    default:
+      break;
+    }
+  return res;
 }
 
 /* Condition codes, including some synonyms provided by HiTech zas.  */
 }
 
 /* Condition codes, including some synonyms provided by HiTech zas.  */
@@ -728,16 +684,43 @@ emit_insn (char prefix, char opcode, const char * args)
   return args;
 }
 
   return args;
 }
 
+void z80_cons_fix_new (fragS *frag_p, int offset, int nbytes, expressionS *exp)
+{
+  bfd_reloc_code_real_type r[4] =
+    {
+      BFD_RELOC_8,
+      BFD_RELOC_16,
+      BFD_RELOC_24,
+      BFD_RELOC_32
+    };
+
+  if (nbytes < 1 || nbytes > 4)
+    {
+      as_bad (_("unsupported BFD relocation size %u"), nbytes);
+    }
+  else
+    {
+      fix_new_exp (frag_p, offset, nbytes, exp, 0, r[nbytes-1]);
+    }
+}
+
 static void
 emit_byte (expressionS * val, bfd_reloc_code_real_type r_type)
 {
   char *p;
   int lo, hi;
 static void
 emit_byte (expressionS * val, bfd_reloc_code_real_type r_type)
 {
   char *p;
   int lo, hi;
-  fixS * fixp;
 
   p = frag_more (1);
   *p = val->X_add_number;
 
   p = frag_more (1);
   *p = val->X_add_number;
-  if ((r_type != BFD_RELOC_8_PCREL) && (val->X_op == O_constant))
+  if ( contains_register(val->X_add_symbol) || contains_register(val->X_op_symbol) )
+    {
+      ill_op();
+    }
+  else if ((r_type == BFD_RELOC_8_PCREL) && (val->X_op == O_constant))
+    {
+      as_bad (_("cannot make a relative jump to an absolute location"));
+    }
+  else if (val->X_op == O_constant)
     {
       lo = -128;
       hi = (BFD_RELOC_8 == r_type) ? 255 : 127;
     {
       lo = -128;
       hi = (BFD_RELOC_8 == r_type) ? 255 : 127;
@@ -752,8 +735,8 @@ emit_byte (expressionS * val, bfd_reloc_code_real_type r_type)
     }
   else
     {
     }
   else
     {
-      fixp = fix_new_exp (frag_now, p - frag_now->fr_literal, 1, val,
-                         (r_type == BFD_RELOC_8_PCREL) ? TRUE : FALSE, r_type);
+      fix_new_exp (frag_now, p - frag_now->fr_literal, 1, val,
+                  (r_type == BFD_RELOC_8_PCREL) ? TRUE : FALSE, r_type);
       /* FIXME : Process constant offsets immediately.  */
     }
 }
       /* FIXME : Process constant offsets immediately.  */
     }
 }
@@ -765,7 +748,9 @@ emit_word (expressionS * val)
 
   p = frag_more (2);
   if (   (val->X_op == O_register)
 
   p = frag_more (2);
   if (   (val->X_op == O_register)
-      || (val->X_op == O_md1))
+      || (val->X_op == O_md1)
+      || contains_register(val->X_add_symbol)
+      || contains_register(val->X_op_symbol) )
     ill_op ();
   else
     {
     ill_op ();
   else
     {
@@ -822,8 +807,12 @@ emit_mx (char prefix, char opcode, int shift, expressionS * arg)
       q = frag_more (2);
       *q++ = (rnum & R_IX) ? 0xDD : 0xFD;
       *q = (prefix) ? prefix : (opcode + (6 << shift));
       q = frag_more (2);
       *q++ = (rnum & R_IX) ? 0xDD : 0xFD;
       *q = (prefix) ? prefix : (opcode + (6 << shift));
-      emit_byte (symbol_get_value_expression (arg->X_add_symbol),
-                BFD_RELOC_Z80_DISP8);
+      {
+       expressionS offset = *arg;
+       offset.X_op = O_symbol;
+       offset.X_add_number = 0;
+       emit_byte (&offset, BFD_RELOC_Z80_DISP8);
+      }
       if (prefix)
        {
          q = frag_more (1);
       if (prefix)
        {
          q = frag_more (1);
@@ -937,7 +926,7 @@ emit_call (char prefix ATTRIBUTE_UNUSED, char opcode, const char * args)
   expressionS addr;
   const char *p;  char *q;
 
   expressionS addr;
   const char *p;  char *q;
 
-  p = parse_exp (args, &addr);
+  p = parse_exp_not_indexed (args, &addr);
   if (addr.X_md)
     ill_op ();
   else
   if (addr.X_md)
     ill_op ();
   else
@@ -985,7 +974,7 @@ emit_jr (char prefix ATTRIBUTE_UNUSED, char opcode, const char * args)
   const char *p;
   char *q;
 
   const char *p;
   char *q;
 
-  p = parse_exp (args, &addr);
+  p = parse_exp_not_indexed (args, &addr);
   if (addr.X_md)
     ill_op ();
   else
   if (addr.X_md)
     ill_op ();
   else
@@ -1005,14 +994,11 @@ emit_jp (char prefix, char opcode, const char * args)
   char *q;
   int rnum;
 
   char *q;
   int rnum;
 
-  p = parse_exp (args, & addr);
+  p = parse_exp_not_indexed (args, & addr);
   if (addr.X_md)
     {
       rnum = addr.X_add_number;
   if (addr.X_md)
     {
       rnum = addr.X_add_number;
-      if ((addr.X_op == O_register && (rnum & ~R_INDEX) == REG_HL)
-        /* An operand (i[xy]) would have been rewritten to (i[xy]+0)
-            in parse_exp ().  */
-         || (addr.X_op == O_md1 && addr.X_add_symbol == zero))
+      if ((O_register == addr.X_op) && (REG_HL == (rnum & ~R_INDEX)))
        {
          q = frag_more ((rnum & R_INDEX) ? 2 : 1);
          if (rnum & R_INDEX)
        {
          q = frag_more ((rnum & R_INDEX) ? 2 : 1);
          if (rnum & R_INDEX)
@@ -1115,7 +1101,7 @@ emit_adc (char prefix, char opcode, const char * args)
   p = parse_exp (args, &term);
   if (*p++ != ',')
     {
   p = parse_exp (args, &term);
   if (*p++ != ',')
     {
-      error (_("bad intruction syntax"));
+      error (_("bad instruction syntax"));
       return p;
     }
 
       return p;
     }
 
@@ -1158,7 +1144,7 @@ emit_add (char prefix, char opcode, const char * args)
   p = parse_exp (args, &term);
   if (*p++ != ',')
     {
   p = parse_exp (args, &term);
   if (*p++ != ',')
     {
-      error (_("bad intruction syntax"));
+      error (_("bad instruction syntax"));
       return p;
     }
 
       return p;
     }
 
@@ -1202,7 +1188,7 @@ emit_bit (char prefix, char opcode, const char * args)
 
   p = parse_exp (args, &b);
   if (*p++ != ',')
 
   p = parse_exp (args, &b);
   if (*p++ != ',')
-    error (_("bad intruction syntax"));
+    error (_("bad instruction syntax"));
 
   bn = b.X_add_number;
   if ((!b.X_md)
 
   bn = b.X_add_number;
   if ((!b.X_md)
@@ -1266,7 +1252,7 @@ emit_ex (char prefix_in ATTRIBUTE_UNUSED,
   const char * p;
   char prefix, opcode;
 
   const char * p;
   char prefix, opcode;
 
-  p = parse_exp (args, &op);
+  p = parse_exp_not_indexed (args, &op);
   p = skip_space (p);
   if (*p++ != ',')
     {
   p = skip_space (p);
   if (*p++ != ',')
     {
@@ -1322,7 +1308,7 @@ emit_in (char prefix ATTRIBUTE_UNUSED, char opcode ATTRIBUTE_UNUSED,
   p = parse_exp (args, &reg);
   if (*p++ != ',')
     {
   p = parse_exp (args, &reg);
   if (*p++ != ',')
     {
-      error (_("bad intruction syntax"));
+      error (_("bad instruction syntax"));
       return p;
     }
 
       return p;
     }
 
@@ -1376,7 +1362,7 @@ emit_out (char prefix ATTRIBUTE_UNUSED, char opcode ATTRIBUTE_UNUSED,
   p = parse_exp (args, & port);
   if (*p++ != ',')
     {
   p = parse_exp (args, & port);
   if (*p++ != ',')
     {
-      error (_("bad intruction syntax"));
+      error (_("bad instruction syntax"));
       return p;
     }
   p = parse_exp (p, &reg);
       return p;
     }
   p = parse_exp (p, &reg);
@@ -1426,7 +1412,7 @@ emit_rst (char prefix ATTRIBUTE_UNUSED, char opcode, const char * args)
   const char *p;
   char *q;
 
   const char *p;
   char *q;
 
-  p = parse_exp (args, &addr);
+  p = parse_exp_not_indexed (args, &addr);
   if (addr.X_op != O_constant)
     {
       error ("rst needs constant address");
   if (addr.X_op != O_constant)
     {
       error ("rst needs constant address");
@@ -1519,7 +1505,7 @@ emit_ldreg (int dest, expressionS * src)
          && (src->X_add_number == REG_BC || src->X_add_number == REG_DE))
        {
          q = frag_more (1);
          && (src->X_add_number == REG_BC || src->X_add_number == REG_DE))
        {
          q = frag_more (1);
-         *q = 0x0A + ((dest & 1) << 4);
+         *q = 0x0A + ((src->X_add_number & 1) << 4);
          break;
        }
 
          break;
        }
 
@@ -1599,7 +1585,7 @@ emit_ldreg (int dest, expressionS * src)
       /* Fall through.  */
     case REG_BC:
     case REG_DE:
       /* Fall through.  */
     case REG_BC:
     case REG_DE:
-      if (src->X_op == O_register || src->X_op != O_md1)
+      if (src->X_op == O_register || src->X_op == O_md1)
        ill_op ();
       q = frag_more (src->X_md ? 2 : 1);
       if (src->X_md)
        ill_op ();
       q = frag_more (src->X_md ? 2 : 1);
       if (src->X_md)
@@ -1645,14 +1631,19 @@ emit_ld (char prefix_in ATTRIBUTE_UNUSED, char opcode_in ATTRIBUTE_UNUSED,
 
   p = parse_exp (args, &dst);
   if (*p++ != ',')
 
   p = parse_exp (args, &dst);
   if (*p++ != ',')
-    error (_("bad intruction syntax"));
+    error (_("bad instruction syntax"));
   p = parse_exp (p, &src);
 
   switch (dst.X_op)
     {
     case O_md1:
   p = parse_exp (p, &src);
 
   switch (dst.X_op)
     {
     case O_md1:
-      emit_ldxhl ((dst.X_add_number & R_IX) ? 0xDD : 0xFD, 0x70,
-                 &src, symbol_get_value_expression (dst.X_add_symbol));
+      {
+        expressionS dst_offset = dst;
+       dst_offset.X_op = O_symbol;
+       dst_offset.X_add_number = 0;
+       emit_ldxhl ((dst.X_add_number & R_IX) ? 0xDD : 0xFD, 0x70,
+                   &src, &dst_offset);
+      }
       break;
 
     case O_register:
       break;
 
     case O_register:
@@ -1712,38 +1703,33 @@ emit_ld (char prefix_in ATTRIBUTE_UNUSED, char opcode_in ATTRIBUTE_UNUSED,
   return p;
 }
 
   return p;
 }
 
-static const char *
-emit_data (char prefix ATTRIBUTE_UNUSED, char opcode, const char * args)
+static void
+emit_data (int size ATTRIBUTE_UNUSED)
 {
   const char *p, *q;
   char *u, quote;
   int cnt;
   expressionS exp;
 
 {
   const char *p, *q;
   char *u, quote;
   int cnt;
   expressionS exp;
 
-  p = skip_space (args);
-  if (!*p)
-    error (_("missing operand"));
+  if (is_it_end_of_statement ())
+    {
+      demand_empty_rest_of_line ();
+      return;
+    }
+  p = skip_space (input_line_pointer);
 
 
-  while (*p)
+  do
     {
       if (*p == '\"' || *p == '\'')
        {
     {
       if (*p == '\"' || *p == '\'')
        {
-         if (opcode == 1)
-           {
-             for (quote = *p, q = ++p, cnt = 0; *p && quote != *p; ++p, ++cnt)
-               ;
-             u = frag_more (cnt);
-             memcpy (u, q, cnt);
-             if (!*p)
-               as_warn (_("unterminated string"));
-             else
-               p = skip_space (p+1);
-           }
-         else
-           {
-             ill_op ();
-             break;
-           }
+           for (quote = *p, q = ++p, cnt = 0; *p && quote != *p; ++p, ++cnt)
+             ;
+           u = frag_more (cnt);
+           memcpy (u, q, cnt);
+           if (!*p)
+             as_warn (_("unterminated string"));
+           else
+             p = skip_space (p+1);
        }
       else
        {
        }
       else
        {
@@ -1755,21 +1741,12 @@ emit_data (char prefix ATTRIBUTE_UNUSED, char opcode, const char * args)
            }
          if (exp.X_md)
            as_warn (_("parentheses ignored"));
            }
          if (exp.X_md)
            as_warn (_("parentheses ignored"));
-         if (opcode == 1)
-           emit_byte (&exp, BFD_RELOC_8);
-         else
-           emit_word (&exp);
+         emit_byte (&exp, BFD_RELOC_8);
          p = skip_space (p);
        }
          p = skip_space (p);
        }
-      if (*p)
-       {
-         if (*p != ',')
-           as_warn (_("missing ','"));
-         else
-           ++p;
-       }
     }
     }
-  return p;
+  while (*p++ == ',') ;
+  input_line_pointer = (char *)(p-1);
 }
 
 static const char *
 }
 
 static const char *
@@ -1838,6 +1815,24 @@ emit_muluw (char prefix ATTRIBUTE_UNUSED, char opcode, const char * args)
   return p;
 }
 
   return p;
 }
 
+/* Port specific pseudo ops.  */
+const pseudo_typeS md_pseudo_table[] =
+{
+  { "db" , emit_data, 1},
+  { "d24", cons, 3},
+  { "d32", cons, 4},
+  { "def24", cons, 3},
+  { "def32", cons, 4},
+  { "defb", emit_data, 1},
+  { "defs", s_space, 1}, /* Synonym for ds on some assemblers.  */
+  { "defw", cons, 2},
+  { "ds",   s_space, 1}, /* Fill with bytes rather than words.  */
+  { "dw", cons, 2},
+  { "psect", obj_coff_section, 0}, /* TODO: Translate attributes.  */
+  { "set", 0, 0},              /* Real instruction on z80.  */
+  { NULL, 0, 0 }
+} ;
+
 static table_t instab[] =
 {
   { "adc",  0x88, 0x4A, emit_adc },
 static table_t instab[] =
 {
   { "adc",  0x88, 0x4A, emit_adc },
@@ -1853,13 +1848,9 @@ static table_t instab[] =
   { "cpir", 0xED, 0xB1, emit_insn },
   { "cpl",  0x00, 0x2F, emit_insn },
   { "daa",  0x00, 0x27, emit_insn },
   { "cpir", 0xED, 0xB1, emit_insn },
   { "cpl",  0x00, 0x2F, emit_insn },
   { "daa",  0x00, 0x27, emit_insn },
-  { "db",   0x00, 0x01, emit_data },
   { "dec",  0x0B, 0x05, emit_incdec },
   { "dec",  0x0B, 0x05, emit_incdec },
-  { "defb", 0x00, 0x01, emit_data },
-  { "defw", 0x00, 0x02, emit_data },
   { "di",   0x00, 0xF3, emit_insn },
   { "djnz", 0x00, 0x10, emit_jr },
   { "di",   0x00, 0xF3, emit_insn },
   { "djnz", 0x00, 0x10, emit_jr },
-  { "dw",   0x00, 0x02, emit_data },
   { "ei",   0x00, 0xFB, emit_insn },
   { "ex",   0x00, 0x00, emit_ex},
   { "exx",  0x00, 0xD9, emit_insn },
   { "ei",   0x00, 0xFB, emit_insn },
   { "ex",   0x00, 0x00, emit_ex},
   { "exx",  0x00, 0xD9, emit_insn },
@@ -1931,25 +1922,32 @@ md_assemble (char* str)
   for (i = 0; (i < BUFLEN) && (ISALPHA (*p));)
     buf[i++] = TOLOWER (*p++);
 
   for (i = 0; (i < BUFLEN) && (ISALPHA (*p));)
     buf[i++] = TOLOWER (*p++);
 
-  if ((i == BUFLEN)
-      || ((*p) && (!ISSPACE (*p))))
-    as_bad (_("illegal instruction '%s'"), buf);
-
-  buf[i] = 0;
-  p = skip_space (p);
-  key = buf;
-
-  insp = bsearch (&key, instab, ARRAY_SIZE (instab),
-                 sizeof (instab[0]), key_cmp);
-  if (!insp)
-    as_bad (_("illegal instruction '%s'"), buf);
+  if (i == BUFLEN)
+    {
+      buf[BUFLEN-3] = buf[BUFLEN-2] = '.'; /* Mark opcode as abbreviated.  */
+      buf[BUFLEN-1] = 0;
+      as_bad (_("Unknown instruction '%s'"), buf);
+    }
+  else if ((*p) && (!ISSPACE (*p)))
+    as_bad (_("syntax error"));
   else
     {
   else
     {
-      p = insp->fp (insp->prefix, insp->opcode, p);
+      buf[i] = 0;
       p = skip_space (p);
       p = skip_space (p);
-      if ((!err_flag) && *p)
-       as_bad (_("junk at end of line, first unrecognized character is `%c'"),
-               *p);
+      key = buf;
+
+      insp = bsearch (&key, instab, ARRAY_SIZE (instab),
+                   sizeof (instab[0]), key_cmp);
+      if (!insp)
+       as_bad (_("Unknown instruction '%s'"), buf);
+      else
+       {
+         p = insp->fp (insp->prefix, insp->opcode, p);
+         p = skip_space (p);
+       if ((!err_flag) && *p)
+         as_bad (_("junk at end of line, first unrecognized character is `%c'"),
+                 *p);
+       }
     }
   input_line_pointer = old_ptr;
 }
     }
   input_line_pointer = old_ptr;
 }
@@ -1958,7 +1956,7 @@ void
 md_apply_fix (fixS * fixP, valueT* valP, segT seg ATTRIBUTE_UNUSED)
 {
   long val = * (long *) valP;
 md_apply_fix (fixS * fixP, valueT* valP, segT seg ATTRIBUTE_UNUSED)
 {
   long val = * (long *) valP;
-  char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
+  char *p_lit = fixP->fx_where + fixP->fx_frag->fr_literal;
 
   switch (fixP->fx_r_type)
     {
 
   switch (fixP->fx_r_type)
     {
@@ -1974,7 +1972,7 @@ md_apply_fix (fixS * fixP, valueT* valP, segT seg ATTRIBUTE_UNUSED)
          if (!fixP->fx_no_overflow)
             as_bad_where (fixP->fx_file, fixP->fx_line,
                          _("relative jump out of range"));
          if (!fixP->fx_no_overflow)
             as_bad_where (fixP->fx_file, fixP->fx_line,
                          _("relative jump out of range"));
-         *buf++ = val;
+         *p_lit++ = val;
           fixP->fx_done = 1;
         }
       break;
           fixP->fx_done = 1;
         }
       break;
@@ -1991,7 +1989,7 @@ md_apply_fix (fixS * fixP, valueT* valP, segT seg ATTRIBUTE_UNUSED)
          if (!fixP->fx_no_overflow)
             as_bad_where (fixP->fx_file, fixP->fx_line,
                          _("index offset  out of range"));
          if (!fixP->fx_no_overflow)
             as_bad_where (fixP->fx_file, fixP->fx_line,
                          _("index offset  out of range"));
-         *buf++ = val;
+         *p_lit++ = val;
           fixP->fx_done = 1;
         }
       break;
           fixP->fx_done = 1;
         }
       break;
@@ -1999,23 +1997,34 @@ md_apply_fix (fixS * fixP, valueT* valP, segT seg ATTRIBUTE_UNUSED)
     case BFD_RELOC_8:
       if (val > 255 || val < -128)
        as_warn_where (fixP->fx_file, fixP->fx_line, _("overflow"));
     case BFD_RELOC_8:
       if (val > 255 || val < -128)
        as_warn_where (fixP->fx_file, fixP->fx_line, _("overflow"));
-      *buf++ = val;
+      *p_lit++ = val;
+      fixP->fx_no_overflow = 1;
       if (fixP->fx_addsy == NULL)
        fixP->fx_done = 1;
       break;
 
     case BFD_RELOC_16:
       if (fixP->fx_addsy == NULL)
        fixP->fx_done = 1;
       break;
 
     case BFD_RELOC_16:
-      *buf++ = val;
-      *buf++ = (val >> 8);
+      *p_lit++ = val;
+      *p_lit++ = (val >> 8);
+      fixP->fx_no_overflow = 1;
       if (fixP->fx_addsy == NULL)
        fixP->fx_done = 1;
       break;
 
       if (fixP->fx_addsy == NULL)
        fixP->fx_done = 1;
       break;
 
-    case BFD_RELOC_32: /* .Long may produce this.  */
-      *buf++ = val;
-      *buf++ = (val >> 8);
-      *buf++ = (val >> 16);
-      *buf++ = (val >> 24);
+    case BFD_RELOC_24: /* Def24 may produce this.  */
+      *p_lit++ = val;
+      *p_lit++ = (val >> 8);
+      *p_lit++ = (val >> 16);
+      fixP->fx_no_overflow = 1;
+      if (fixP->fx_addsy == NULL)
+       fixP->fx_done = 1;
+      break;
+
+    case BFD_RELOC_32: /* Def32 and .long may produce this.  */
+      *p_lit++ = val;
+      *p_lit++ = (val >> 8);
+      *p_lit++ = (val >> 16);
+      *p_lit++ = (val >> 24);
       if (fixP->fx_addsy == NULL)
        fixP->fx_done = 1;
       break;
       if (fixP->fx_addsy == NULL)
        fixP->fx_done = 1;
       break;
@@ -2049,8 +2058,8 @@ tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED , fixS *fixp)
       return NULL;
     }
 
       return NULL;
     }
 
-  reloc               = xmalloc (sizeof (arelent));
-  reloc->sym_ptr_ptr  = xmalloc (sizeof (asymbol *));
+  reloc               = XNEW (arelent);
+  reloc->sym_ptr_ptr  = XNEW (asymbol *);
   *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
   reloc->address      = fixp->fx_frag->fr_address + fixp->fx_where;
   reloc->howto        = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
   *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
   reloc->address      = fixp->fx_frag->fr_address + fixp->fx_where;
   reloc->howto        = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
@@ -2058,4 +2067,3 @@ tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED , fixS *fixp)
 
   return reloc;
 }
 
   return reloc;
 }
-
This page took 0.035659 seconds and 4 git commands to generate.