[ARC] Add SYNTAX_NOP and SYNTAX_1OP for extension instructions
[deliverable/binutils-gdb.git] / gas / config / tc-z8k.c
index bde058ab652b8fbbd045370d25f2876e82eb1b14..265adc6ac24f8304b74c4ca296c518d91641425d 100644 (file)
@@ -1,12 +1,11 @@
 /* tc-z8k.c -- Assemble code for the Zilog Z800n
 /* tc-z8k.c -- Assemble code for the Zilog Z800n
-   Copyright 1992, 1993, 1994, 1995, 1996, 1998, 2000, 2001, 2002
-   Free Software Foundation, Inc.
+   Copyright (C) 1992-2016 Free Software Foundation, Inc.
 
    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
 
    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,
 
    You should have received a copy of the GNU General Public License
    along with GAS; see the file COPYING.  If not, write to the Free
 
    You should have received a copy of the GNU General Public License
    along with GAS; see the file COPYING.  If not, write to the Free
-   Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-   02111-1307, USA.  */
+   Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
+   02110-1301, USA.  */
 
 /* Written By Steve Chamberlain <sac@cygnus.com>.  */
 
 
 /* Written By Steve Chamberlain <sac@cygnus.com>.  */
 
-#define DEFINE_TABLE
-#include <stdio.h>
-
 #include "as.h"
 #include "as.h"
-#include "bfd.h"
 #include "safe-ctype.h"
 #include "safe-ctype.h"
+#define DEFINE_TABLE
 #include "opcodes/z8k-opc.h"
 
 const char comment_chars[] = "!";
 #include "opcodes/z8k-opc.h"
 
 const char comment_chars[] = "!";
@@ -36,38 +32,35 @@ const char line_separator_chars[] = ";";
 extern int machine;
 extern int coff_flags;
 int segmented_mode;
 extern int machine;
 extern int coff_flags;
 int segmented_mode;
-const int md_reloc_size;
 
 
-void cons ();
-
-void
-s_segm ()
-{
-  segmented_mode = 1;
-  machine = bfd_mach_z8001;
-  coff_flags = F_Z8001;
-}
+/* This is non-zero if target was set from the command line.
+   If non-zero, 1 means Z8002 (non-segmented), 2 means Z8001 (segmented).  */
+static int z8k_target_from_cmdline;
 
 
-void
-s_unseg ()
+static void
+s_segm (int segm)
 {
 {
-  segmented_mode = 0;
-  machine = bfd_mach_z8002;
-  coff_flags = F_Z8002;
+  if (segm)
+    {
+      segmented_mode = 1;
+      bfd_set_arch_mach (stdoutput, TARGET_ARCH, bfd_mach_z8001);
+    }
+  else
+    {
+      segmented_mode = 0;
+      bfd_set_arch_mach (stdoutput, TARGET_ARCH, bfd_mach_z8002);
+    }
 }
 
 static void
 }
 
 static void
-even ()
+even (int ignore ATTRIBUTE_UNUSED)
 {
   frag_align (1, 0, 0);
   record_alignment (now_seg, 1);
 }
 
 {
   frag_align (1, 0, 0);
   record_alignment (now_seg, 1);
 }
 
-void obj_coff_section ();
-
-int
-tohex (c)
-     int c;
+static int
+tohex (int c)
 {
   if (ISDIGIT (c))
     return c - '0';
 {
   if (ISDIGIT (c))
     return c - '0';
@@ -76,8 +69,8 @@ tohex (c)
   return c - 'A' + 10;
 }
 
   return c - 'A' + 10;
 }
 
-void
-sval ()
+static void
+sval (int ignore ATTRIBUTE_UNUSED)
 {
   SKIP_WHITESPACE ();
   if (*input_line_pointer == '\'')
 {
   SKIP_WHITESPACE ();
   if (*input_line_pointer == '\'')
@@ -117,12 +110,12 @@ const pseudo_typeS md_pseudo_table[] = {
   {"import" , s_ignore        , 0},
   {"page"   , listing_eject   , 0},
   {"program", s_ignore        , 0},
   {"import" , s_ignore        , 0},
   {"page"   , listing_eject   , 0},
   {"program", s_ignore        , 0},
-  {"z8001"  , s_segm          , 0},
-  {"z8002"  , s_unseg         , 0},
+  {"z8001"  , s_segm          , 1},
+  {"z8002"  , s_segm          , 0},
 
 
-  {"segm"   , s_segm          , 0},
-  {"unsegm" , s_unseg         , 0},
-  {"unseg"  , s_unseg         , 0},
+  {"segm"   , s_segm          , 1},
+  {"unsegm" , s_segm          , 0},
+  {"unseg"  , s_segm          , 0},
   {"name"   , s_app_file      , 0},
   {"global" , s_globl         , 0},
   {"wval"   , cons            , 2},
   {"name"   , s_app_file      , 0},
   {"global" , s_globl         , 0},
   {"wval"   , cons            , 2},
@@ -147,52 +140,39 @@ const char FLT_CHARS[] = "rRsSfFdDxXpP";
 static struct hash_control *opcode_hash_control;
 
 void
 static struct hash_control *opcode_hash_control;
 
 void
-md_begin ()
+md_begin (void)
 {
 {
-  opcode_entry_type *opcode;
-  char *prev_name = "";
-  int idx = 0;
+  const opcode_entry_type *opcode;
+  int idx = -1;
 
   opcode_hash_control = hash_new ();
 
   for (opcode = z8k_table; opcode->name; opcode++)
     {
       /* Only enter unique codes into the table.  */
 
   opcode_hash_control = hash_new ();
 
   for (opcode = z8k_table; opcode->name; opcode++)
     {
       /* Only enter unique codes into the table.  */
-      if (strcmp (opcode->name, prev_name))
-       {
-         hash_insert (opcode_hash_control, opcode->name, (char *) opcode);
-         idx++;
-       }
-      opcode->idx = idx;
-      prev_name = opcode->name;
+      if (idx != opcode->idx)
+       hash_insert (opcode_hash_control, opcode->name, (char *) opcode);
+      idx = opcode->idx;
     }
 
   /* Default to z8002.  */
     }
 
   /* Default to z8002.  */
-  s_unseg ();
+  s_segm (z8k_target_from_cmdline ? z8k_target_from_cmdline - 1 : 0);
 
   /* Insert the pseudo ops, too.  */
   for (idx = 0; md_pseudo_table[idx].poc_name; idx++)
     {
       opcode_entry_type *fake_opcode;
 
   /* Insert the pseudo ops, too.  */
   for (idx = 0; md_pseudo_table[idx].poc_name; idx++)
     {
       opcode_entry_type *fake_opcode;
-      fake_opcode = (opcode_entry_type *) malloc (sizeof (opcode_entry_type));
+      fake_opcode = XNEW (opcode_entry_type);
       fake_opcode->name = md_pseudo_table[idx].poc_name;
       fake_opcode->func = (void *) (md_pseudo_table + idx);
       fake_opcode->opcode = 250;
       hash_insert (opcode_hash_control, fake_opcode->name, fake_opcode);
     }
       fake_opcode->name = md_pseudo_table[idx].poc_name;
       fake_opcode->func = (void *) (md_pseudo_table + idx);
       fake_opcode->opcode = 250;
       hash_insert (opcode_hash_control, fake_opcode->name, fake_opcode);
     }
-
-  linkrelax = 1;
 }
 
 }
 
-struct z8k_exp {
-  char *e_beg;
-  char *e_end;
-  expressionS e_exp;
-};
-
 typedef struct z8k_op {
 typedef struct z8k_op {
-  /* 'b','w','r','q'.  */
-  char regsize;
+  /* CLASS_REG_xxx.  */
+  int regsize;
 
   /* 0 .. 15.  */
   unsigned int reg;
 
   /* 0 .. 15.  */
   unsigned int reg;
@@ -209,27 +189,40 @@ typedef struct z8k_op {
 static expressionS *da_operand;
 static expressionS *imm_operand;
 
 static expressionS *da_operand;
 static expressionS *imm_operand;
 
-int reg[16];
-int the_cc;
-int the_ctrl;
-int the_flags;
-int the_interrupt;
+static int reg[16];
+static int the_cc;
+static int the_ctrl;
+static int the_flags;
+static int the_interrupt;
 
 
-char *
-whatreg (reg, src)
-     int *reg;
-     char *src;
+/* Determine register number.  src points to the ascii number
+   (after "rl", "rh", "r", "rr", or "rq").  If a character
+   outside the set of {0,',',')','('} follows the number,
+   return NULL to indicate that it's not a valid register
+   number.  */
+
+static char *
+whatreg (unsigned int *preg, char *src)
 {
 {
+  unsigned int new_reg;
+
+  /* src[0] is already known to be a digit.  */
   if (ISDIGIT (src[1]))
     {
   if (ISDIGIT (src[1]))
     {
-      *reg = (src[0] - '0') * 10 + src[1] - '0';
-      return src + 2;
+      new_reg = (src[0] - '0') * 10 + src[1] - '0';
+      src += 2;
     }
   else
     {
     }
   else
     {
-      *reg = (src[0] - '0');
-      return src + 1;
+      new_reg = (src[0] - '0');
+      src += 1;
     }
     }
+
+  if (src[0] != 0 && src[0] != ',' && src[0] != '(' && src[0] != ')')
+    return NULL;
+
+  *preg = new_reg;
+  return src;
 }
 
 /* Parse operands
 }
 
 /* Parse operands
@@ -249,101 +242,114 @@ whatreg (reg, src)
 /* Try to parse a reg name.  Return a pointer to the first character
    in SRC after the reg name.  */
 
 /* Try to parse a reg name.  Return a pointer to the first character
    in SRC after the reg name.  */
 
-char *
-parse_reg (src, mode, reg)
-     char *src;
-     int *mode;
-     unsigned int *reg;
+static char *
+parse_reg (char *src, int *mode, unsigned int *preg)
 {
 {
-  char *res = 0;
+  char *res = NULL;
   char regno;
 
   char regno;
 
-  if (src[0] == 's' && src[1] == 'p' && (src[2] == 0 || src[2] == ','))
+  /* Check for stack pointer "sp" alias.  */
+  if ((src[0] == 's' || src[0] == 'S')
+      && (src[1] == 'p' || src[1] == 'P')
+      && (src[2] == 0 || src[2] == ','))
     {
       if (segmented_mode)
        {
          *mode = CLASS_REG_LONG;
     {
       if (segmented_mode)
        {
          *mode = CLASS_REG_LONG;
-         *reg = 14;
+         *preg = 14;
        }
       else
        {
          *mode = CLASS_REG_WORD;
        }
       else
        {
          *mode = CLASS_REG_WORD;
-         *reg = 15;
+         *preg = 15;
        }
       return src + 2;
     }
        }
       return src + 2;
     }
-  if (src[0] == 'r')
+
+  if (src[0] == 'r' || src[0] == 'R')
     {
     {
-      if (src[1] == 'r')
+      if (src[1] == 'r' || src[1] == 'R')
        {
          if (src[2] < '0' || src[2] > '9')
        {
          if (src[2] < '0' || src[2] > '9')
-           return res;  /* Assume no register name but a label starting with 'rr'.  */
+           return NULL;        /* Assume no register name but a label starting with 'rr'.  */
          *mode = CLASS_REG_LONG;
          *mode = CLASS_REG_LONG;
-         res = whatreg (reg, src + 2);
-         regno = *reg;
+         res = whatreg (preg, src + 2);
+         if (res == NULL)
+           return NULL;        /* Not a valid register name.  */
+         regno = *preg;
          if (regno > 14)
          if (regno > 14)
-           as_warn (_("register rr%d, out of range."), regno);
+           as_bad (_("register rr%d out of range"), regno);
+         if (regno & 1)
+           as_bad (_("register rr%d does not exist"), regno);
        }
        }
-      else if (src[1] == 'h')
+      else if (src[1] == 'h' || src[1] == 'H')
        {
          if (src[2] < '0' || src[2] > '9')
        {
          if (src[2] < '0' || src[2] > '9')
-           return res;  /* Assume no register name but a label starting with 'rh'.  */
+           return NULL;        /* Assume no register name but a label starting with 'rh'.  */
          *mode = CLASS_REG_BYTE;
          *mode = CLASS_REG_BYTE;
-         res = whatreg (reg, src + 2);
-         regno = *reg;
+         res = whatreg (preg, src + 2);
+         if (res == NULL)
+           return NULL;        /* Not a valid register name.  */
+         regno = *preg;
          if (regno > 7)
          if (regno > 7)
-           as_warn (_("register rh%d, out of range."), regno);
+           as_bad (_("register rh%d out of range"), regno);
        }
        }
-      else if (src[1] == 'l')
+      else if (src[1] == 'l' || src[1] == 'L')
        {
          if (src[2] < '0' || src[2] > '9')
        {
          if (src[2] < '0' || src[2] > '9')
-           return res;  /* Assume no register name but a label starting with 'rl'.  */
+           return NULL;        /* Assume no register name but a label starting with 'rl'.  */
          *mode = CLASS_REG_BYTE;
          *mode = CLASS_REG_BYTE;
-         res = whatreg (reg, src + 2);
-         regno = *reg;
+         res = whatreg (preg, src + 2);
+         if (res == NULL)
+           return NULL;        /* Not a valid register name.  */
+         regno = *preg;
          if (regno > 7)
          if (regno > 7)
-           as_warn (_("register rl%d, out of range."), regno);
-         *reg += 8;
+           as_bad (_("register rl%d out of range"), regno);
+         *preg += 8;
        }
        }
-      else if (src[1] == 'q')
+      else if (src[1] == 'q' || src[1] == 'Q')
        {
          if (src[2] < '0' || src[2] > '9')
        {
          if (src[2] < '0' || src[2] > '9')
-           return res;  /* Assume no register name but a label starting with 'rq'.  */
+           return NULL;        /* Assume no register name but a label starting with 'rq'.  */
          *mode = CLASS_REG_QUAD;
          *mode = CLASS_REG_QUAD;
-         res = whatreg (reg, src + 2);
-         regno = *reg;
+         res = whatreg (preg, src + 2);
+         if (res == NULL)
+           return NULL;        /* Not a valid register name.  */
+         regno = *preg;
          if (regno > 12)
          if (regno > 12)
-           as_warn (_("register rq%d, out of range."), regno);
+           as_bad (_("register rq%d out of range"), regno);
+         if (regno & 3)
+           as_bad (_("register rq%d does not exist"), regno);
        }
       else
        {
          if (src[1] < '0' || src[1] > '9')
        }
       else
        {
          if (src[1] < '0' || src[1] > '9')
-           return res;  /* Assume no register name but a label starting with 'r'.  */
+           return NULL;        /* Assume no register name but a label starting with 'r'.  */
          *mode = CLASS_REG_WORD;
          *mode = CLASS_REG_WORD;
-         res = whatreg (reg, src + 1);
-         regno = *reg;
+         res = whatreg (preg, src + 1);
+         if (res == NULL)
+           return NULL;        /* Not a valid register name.  */
+         regno = *preg;
          if (regno > 15)
          if (regno > 15)
-           as_warn (_("register r%d, out of range."), regno);
+           as_bad (_("register r%d out of range"), regno);
        }
     }
   return res;
 }
 
        }
     }
   return res;
 }
 
-char *
-parse_exp (s, op)
-     char *s;
-     expressionS *op;
+static char *
+parse_exp (char *s, expressionS *op)
 {
   char *save = input_line_pointer;
 {
   char *save = input_line_pointer;
-  char *new;
+  char *new_pointer;
 
   input_line_pointer = s;
   expression (op);
   if (op->X_op == O_absent)
     as_bad (_("missing operand"));
 
   input_line_pointer = s;
   expression (op);
   if (op->X_op == O_absent)
     as_bad (_("missing operand"));
-  new = input_line_pointer;
+  new_pointer = input_line_pointer;
   input_line_pointer = save;
   input_line_pointer = save;
-  return new;
+  return new_pointer;
 }
 
 /* The many forms of operand:
 }
 
 /* The many forms of operand:
@@ -361,9 +367,7 @@ parse_exp (s, op)
    */
 
 static char *
    */
 
 static char *
-checkfor (ptr, what)
-     char *ptr;
-     char what;
+checkfor (char *ptr, char what)
 {
   if (*ptr == what)
     ptr++;
 {
   if (*ptr == what)
     ptr++;
@@ -376,9 +380,7 @@ checkfor (ptr, what)
 /* Make sure the mode supplied is the size of a word.  */
 
 static void
 /* Make sure the mode supplied is the size of a word.  */
 
 static void
-regword (mode, string)
-     int mode;
-     char *string;
+regword (int mode, const char *string)
 {
   int ok;
 
 {
   int ok;
 
@@ -392,9 +394,7 @@ regword (mode, string)
 /* Make sure the mode supplied is the size of an address.  */
 
 static void
 /* Make sure the mode supplied is the size of an address.  */
 
 static void
-regaddr (mode, string)
-     int mode;
-     char *string;
+regaddr (int mode, const char *string)
 {
   int ok;
 
 {
   int ok;
 
@@ -407,11 +407,12 @@ regaddr (mode, string)
 
 struct ctrl_names {
   int value;
 
 struct ctrl_names {
   int value;
-  char *name;
+  const char *name;
 };
 
 };
 
-struct ctrl_names ctrl_table[] = {
-  { 0x2, "fcw" },
+static struct ctrl_names ctrl_table[] = {
+  { 0x1, "flags" },   /* ldctlb only.  */
+  { 0x2, "fcw" },     /* ldctl only.  Applies to all remaining control registers.  */
   { 0x3, "refresh" },
   { 0x4, "psapseg" },
   { 0x5, "psapoff" },
   { 0x3, "refresh" },
   { 0x4, "psapseg" },
   { 0x5, "psapoff" },
@@ -423,13 +424,10 @@ struct ctrl_names ctrl_table[] = {
 };
 
 static void
 };
 
 static void
-get_ctrl_operand (ptr, mode, dst)
-     char **ptr;
-     struct z8k_op *mode;
-     unsigned int dst ATTRIBUTE_UNUSED;
+get_ctrl_operand (char **ptr, struct z8k_op *mode, unsigned int dst ATTRIBUTE_UNUSED)
 {
   char *src = *ptr;
 {
   char *src = *ptr;
-  int i;
+  int i, l;
 
   while (*src == ' ')
     src++;
 
   while (*src == ' ')
     src++;
@@ -437,46 +435,40 @@ get_ctrl_operand (ptr, mode, dst)
   mode->mode = CLASS_CTRL;
   for (i = 0; ctrl_table[i].name; i++)
     {
   mode->mode = CLASS_CTRL;
   for (i = 0; ctrl_table[i].name; i++)
     {
-      int j;
-
-      for (j = 0; ctrl_table[i].name[j]; j++)
-       {
-         if (ctrl_table[i].name[j] != src[j])
-           goto fail;
-       }
-      the_ctrl = ctrl_table[i].value;
-      *ptr = src + j;
-      return;
-    fail:
-      ;
+      l = strlen (ctrl_table[i].name);
+      if (! strncasecmp (ctrl_table[i].name, src, l))
+        {
+          the_ctrl = ctrl_table[i].value;
+          if (*(src + l) && *(src + l) != ',')
+            break;
+          *ptr = src + l;  /* Valid control name found: "consume" it.  */
+          return;
+        }
     }
   the_ctrl = 0;
     }
   the_ctrl = 0;
-  return;
 }
 
 struct flag_names {
   int value;
 }
 
 struct flag_names {
   int value;
-  char *name;
-
+  const char *name;
 };
 
 };
 
-struct flag_names flag_table[] = {
-  { 0x1, "p" },
-  { 0x1, "v" },
-  { 0x2, "s" },
-  { 0x4, "z" },
-  { 0x8, "c" },
+static struct flag_names flag_table[] = {
+  { 0x1, "P" },
+  { 0x1, "V" },
+  { 0x2, "S" },
+  { 0x4, "Z" },
+  { 0x8, "C" },
   { 0x0, "+" },
   { 0x0, "+" },
+  { 0x0, "," },
   { 0, 0 }
 };
 
 static void
   { 0, 0 }
 };
 
 static void
-get_flags_operand (ptr, mode, dst)
-     char **ptr;
-     struct z8k_op *mode;
-     unsigned int dst ATTRIBUTE_UNUSED;
+get_flags_operand (char **ptr, struct z8k_op *mode, unsigned int dst ATTRIBUTE_UNUSED)
 {
   char *src = *ptr;
 {
   char *src = *ptr;
+  char c;
   int i;
   int j;
 
   int i;
   int j;
 
@@ -489,9 +481,10 @@ get_flags_operand (ptr, mode, dst)
     {
       if (!src[j])
        goto done;
     {
       if (!src[j])
        goto done;
+      c = TOUPPER(src[j]);
       for (i = 0; flag_table[i].name; i++)
        {
       for (i = 0; flag_table[i].name; i++)
        {
-         if (flag_table[i].name[0] == src[j])
+         if (flag_table[i].name[0] == c)
            {
              the_flags = the_flags | flag_table[i].value;
              goto match;
            {
              the_flags = the_flags | flag_table[i].value;
              goto match;
@@ -503,16 +496,14 @@ get_flags_operand (ptr, mode, dst)
     }
  done:
   *ptr = src + j;
     }
  done:
   *ptr = src + j;
-  return;
 }
 
 struct interrupt_names {
   int value;
 }
 
 struct interrupt_names {
   int value;
-  char *name;
-
+  const char *name;
 };
 
 };
 
-struct interrupt_names intr_table[] = {
+static struct interrupt_names intr_table[] = {
   { 0x1, "nvi" },
   { 0x2, "vi" },
   { 0x3, "both" },
   { 0x1, "nvi" },
   { 0x2, "vi" },
   { 0x3, "both" },
@@ -521,77 +512,100 @@ struct interrupt_names intr_table[] = {
 };
 
 static void
 };
 
 static void
-get_interrupt_operand (ptr, mode, dst)
-     char **ptr;
-     struct z8k_op *mode;
-     unsigned int dst ATTRIBUTE_UNUSED;
+get_interrupt_operand (char **ptr, struct z8k_op *mode, unsigned int dst ATTRIBUTE_UNUSED)
 {
   char *src = *ptr;
 {
   char *src = *ptr;
-  int i;
+  int i, l;
 
   while (*src == ' ')
     src++;
 
   mode->mode = CLASS_IMM;
 
   while (*src == ' ')
     src++;
 
   mode->mode = CLASS_IMM;
-  for (i = 0; intr_table[i].name; i++)
-    {
-      int j;
+  the_interrupt = 0;
 
 
-      for (j = 0; intr_table[i].name[j]; j++)
+  while (*src)
+    {
+      for (i = 0; intr_table[i].name; i++)
+       {
+         l = strlen (intr_table[i].name);
+         if (! strncasecmp (intr_table[i].name, src, l))
+           {
+             the_interrupt |= intr_table[i].value;
+             if (*(src + l) && *(src + l) != ',')
+               {
+                 *ptr = src + l;
+               invalid:
+                 as_bad (_("unknown interrupt %s"), src);
+                 while (**ptr && ! is_end_of_line[(unsigned char) **ptr])
+                   (*ptr)++;    /* Consume rest of line.  */
+                 return;
+               }
+             src += l;
+             if (! *src)
+               {
+                 *ptr = src;
+                 return;
+               }
+           }
+       }
+      if (*src == ',')
+       src++;
+      else
        {
        {
-         if (intr_table[i].name[j] != src[j])
-           goto fail;
+         *ptr = src;
+         goto invalid;
        }
        }
-      the_interrupt = intr_table[i].value;
-      *ptr = src + j;
-      return;
-    fail:
-      ;
     }
     }
+
+  /* No interrupt type specified, opcode won't do anything.  */
+  as_warn (_("opcode has no effect"));
   the_interrupt = 0x0;
   the_interrupt = 0x0;
-  return;
 }
 
 struct cc_names {
   int value;
 }
 
 struct cc_names {
   int value;
-  char *name;
-
+  const char *name;
 };
 
 };
 
-struct cc_names table[] = {
+static struct cc_names table[] = {
   { 0x0, "f" },
   { 0x1, "lt" },
   { 0x2, "le" },
   { 0x3, "ule" },
   { 0x0, "f" },
   { 0x1, "lt" },
   { 0x2, "le" },
   { 0x3, "ule" },
+  { 0x4, "ov/pe" },
   { 0x4, "ov" },
   { 0x4, "ov" },
+  { 0x4, "pe/ov" },
   { 0x4, "pe" },
   { 0x5, "mi" },
   { 0x6, "eq" },
   { 0x6, "z" },
   { 0x4, "pe" },
   { 0x5, "mi" },
   { 0x6, "eq" },
   { 0x6, "z" },
+  { 0x7, "c/ult" },
   { 0x7, "c" },
   { 0x7, "c" },
+  { 0x7, "ult/c" },
   { 0x7, "ult" },
   { 0x8, "t" },
   { 0x9, "ge" },
   { 0xa, "gt" },
   { 0xb, "ugt" },
   { 0x7, "ult" },
   { 0x8, "t" },
   { 0x9, "ge" },
   { 0xa, "gt" },
   { 0xb, "ugt" },
+  { 0xc, "nov/po" },
   { 0xc, "nov" },
   { 0xc, "nov" },
+  { 0xc, "po/nov" },
   { 0xc, "po" },
   { 0xd, "pl" },
   { 0xe, "ne" },
   { 0xe, "nz" },
   { 0xc, "po" },
   { 0xd, "pl" },
   { 0xe, "ne" },
   { 0xe, "nz" },
+  { 0xf, "nc/uge" },
   { 0xf, "nc" },
   { 0xf, "nc" },
+  { 0xf, "uge/nc" },
   { 0xf, "uge" },
   { 0  ,  0 }
 };
 
 static void
   { 0xf, "uge" },
   { 0  ,  0 }
 };
 
 static void
-get_cc_operand (ptr, mode, dst)
-     char **ptr;
-     struct z8k_op *mode;
-     unsigned int dst ATTRIBUTE_UNUSED;
+get_cc_operand (char **ptr, struct z8k_op *mode, unsigned int dst ATTRIBUTE_UNUSED)
 {
   char *src = *ptr;
 {
   char *src = *ptr;
-  int i;
+  int i, l;
 
   while (*src == ' ')
     src++;
 
   while (*src == ' ')
     src++;
@@ -599,27 +613,21 @@ get_cc_operand (ptr, mode, dst)
   mode->mode = CLASS_CC;
   for (i = 0; table[i].name; i++)
     {
   mode->mode = CLASS_CC;
   for (i = 0; table[i].name; i++)
     {
-      int j;
-
-      for (j = 0; table[i].name[j]; j++)
-       {
-         if (table[i].name[j] != src[j])
-           goto fail;
-       }
-      the_cc = table[i].value;
-      *ptr = src + j;
-      return;
-    fail:
-      ;
+      l = strlen (table[i].name);
+      if (! strncasecmp (table[i].name, src, l))
+        {
+          the_cc = table[i].value;
+          if (*(src + l) && *(src + l) != ',')
+            break;
+          *ptr = src + l;  /* Valid cc found: "consume" it.  */
+          return;
+        }
     }
     }
-  the_cc = 0x8;
+  the_cc = 0x8;  /* Not recognizing the cc defaults to t.  (Assuming no cc present.)  */
 }
 
 static void
 }
 
 static void
-get_operand (ptr, mode, dst)
-     char **ptr;
-     struct z8k_op *mode;
-     unsigned int dst ATTRIBUTE_UNUSED;
+get_operand (char **ptr, struct z8k_op *mode, unsigned int dst ATTRIBUTE_UNUSED)
 {
   char *src = *ptr;
   char *end;
 {
   char *src = *ptr;
   char *end;
@@ -636,20 +644,19 @@ get_operand (ptr, mode, dst)
     }
   else if (*src == '@')
     {
     }
   else if (*src == '@')
     {
-      int d;
-
       mode->mode = CLASS_IR;
       mode->mode = CLASS_IR;
-      src = parse_reg (src + 1, &d, &mode->reg);
+      src = parse_reg (src + 1, &mode->regsize, &mode->reg);
     }
   else
     {
     }
   else
     {
-      int regn;
+      unsigned int regn;
 
       end = parse_reg (src, &mode->mode, &regn);
 
       if (end)
        {
 
       end = parse_reg (src, &mode->mode, &regn);
 
       if (end)
        {
-         int nw, nr;
+         int nw;
+         unsigned int nr;
 
          src = end;
          if (*src == '(')
 
          src = end;
          if (*src == '(')
@@ -667,9 +674,6 @@ get_operand (ptr, mode, dst)
                    src++;
 
                  regaddr (mode->mode, "ra(rb) ra");
                    src++;
 
                  regaddr (mode->mode, "ra(rb) ra");
-#if 0
-                 regword (mode->mode, "ra(rb) rb");
-#endif
                  mode->mode = CLASS_BX;
                  mode->reg = regn;
                  mode->x_reg = nr;
                  mode->mode = CLASS_BX;
                  mode->reg = regn;
                  mode->x_reg = nr;
@@ -723,32 +727,47 @@ get_operand (ptr, mode, dst)
 }
 
 static char *
 }
 
 static char *
-get_operands (opcode, op_end, operand)
-     opcode_entry_type *opcode;
-     char *op_end;
-     op_type *operand;
+get_operands (const opcode_entry_type *opcode, char *op_end, op_type *operand)
 {
   char *ptr = op_end;
   char *savptr;
 
 {
   char *ptr = op_end;
   char *savptr;
 
-  ptr++;
   switch (opcode->noperands)
     {
     case 0:
       operand[0].mode = 0;
       operand[1].mode = 0;
   switch (opcode->noperands)
     {
     case 0:
       operand[0].mode = 0;
       operand[1].mode = 0;
+      while (*ptr == ' ')
+        ptr++;
       break;
 
     case 1:
       if (opcode->arg_info[0] == CLASS_CC)
       break;
 
     case 1:
       if (opcode->arg_info[0] == CLASS_CC)
-       get_cc_operand (&ptr, operand + 0, 0);
-
+        {
+          get_cc_operand (&ptr, operand + 0, 0);
+          while (*ptr == ' ')
+            ptr++;
+          if (*ptr && ! is_end_of_line[(unsigned char) *ptr])
+            {
+              as_bad (_("invalid condition code '%s'"), ptr);
+              while (*ptr && ! is_end_of_line[(unsigned char) *ptr])
+                ptr++;   /* Consume rest of line.  */
+            }
+        }
       else if (opcode->arg_info[0] == CLASS_FLAGS)
       else if (opcode->arg_info[0] == CLASS_FLAGS)
-       get_flags_operand (&ptr, operand + 0, 0);
-
+       {
+         get_flags_operand (&ptr, operand + 0, 0);
+         while (*ptr == ' ')
+           ptr++;
+         if (*ptr && ! is_end_of_line[(unsigned char) *ptr])
+           {
+             as_bad (_("invalid flag '%s'"), ptr);
+             while (*ptr && ! is_end_of_line[(unsigned char) *ptr])
+               ptr++;   /* Consume rest of line.  */
+           }
+       }
       else if (opcode->arg_info[0] == (CLASS_IMM + (ARG_IMM2)))
        get_interrupt_operand (&ptr, operand + 0, 0);
       else if (opcode->arg_info[0] == (CLASS_IMM + (ARG_IMM2)))
        get_interrupt_operand (&ptr, operand + 0, 0);
-
       else
        get_operand (&ptr, operand + 0, 0);
 
       else
        get_operand (&ptr, operand + 0, 0);
 
@@ -758,8 +777,20 @@ get_operands (opcode, op_end, operand)
     case 2:
       savptr = ptr;
       if (opcode->arg_info[0] == CLASS_CC)
     case 2:
       savptr = ptr;
       if (opcode->arg_info[0] == CLASS_CC)
-       get_cc_operand (&ptr, operand + 0, 0);
-
+        {
+          get_cc_operand (&ptr, operand + 0, 0);
+          while (*ptr == ' ')
+            ptr++;
+          if (*ptr != ',' && strchr (ptr + 1, ','))
+            {
+              savptr = ptr;
+              while (*ptr != ',')
+                ptr++;
+              *ptr = 0;
+              ptr++;
+              as_bad (_("invalid condition code '%s'"), savptr);
+            }
+        }
       else if (opcode->arg_info[0] == CLASS_CTRL)
        {
          get_ctrl_operand (&ptr, operand + 0, 0);
       else if (opcode->arg_info[0] == CLASS_CTRL)
        {
          get_ctrl_operand (&ptr, operand + 0, 0);
@@ -774,6 +805,8 @@ get_operands (opcode, op_end, operand)
              if (*ptr == ',')
                ptr++;
              get_ctrl_operand (&ptr, operand + 1, 1);
              if (*ptr == ',')
                ptr++;
              get_ctrl_operand (&ptr, operand + 1, 1);
+             if (the_ctrl == 0)
+               return NULL;
              return ptr;
            }
        }
              return ptr;
            }
        }
@@ -822,10 +855,7 @@ get_operands (opcode, op_end, operand)
    provided.  */
 
 static opcode_entry_type *
    provided.  */
 
 static opcode_entry_type *
-get_specific (opcode, operands)
-     opcode_entry_type *opcode;
-     op_type *operands;
-
+get_specific (opcode_entry_type *opcode, op_type *operands)
 {
   opcode_entry_type *this_try = opcode;
   int found = 0;
 {
   opcode_entry_type *this_try = opcode;
   int found = 0;
@@ -842,9 +872,14 @@ get_specific (opcode, operands)
        {
          unsigned int mode = operands[i].mode;
 
        {
          unsigned int mode = operands[i].mode;
 
+          if (((mode & CLASS_MASK) == CLASS_IR) && ((this_try->arg_info[i] & CLASS_MASK) == CLASS_IRO))
+            {
+              mode = operands[i].mode = (operands[i].mode & ~CLASS_MASK) | CLASS_IRO;
+            }
+
          if ((mode & CLASS_MASK) != (this_try->arg_info[i] & CLASS_MASK))
            {
          if ((mode & CLASS_MASK) != (this_try->arg_info[i] & CLASS_MASK))
            {
-             /* It could be an pc rel operand, if this is a da mode
+             /* It could be a pc rel operand, if this is a da mode
                 and we like disps, then insert it.  */
 
              if (mode == CLASS_DA && this_try->arg_info[i] == CLASS_DISP)
                 and we like disps, then insert it.  */
 
              if (mode == CLASS_DA && this_try->arg_info[i] == CLASS_DISP)
@@ -878,8 +913,18 @@ get_specific (opcode, operands)
            {
            default:
              break;
            {
            default:
              break;
-           case CLASS_X:
+           case CLASS_IRO:
+             if (operands[i].regsize != CLASS_REG_WORD)
+               as_bad (_("invalid indirect register size"));
+             reg[this_try->arg_info[i] & ARG_MASK] = operands[i].reg;
+             break;
            case CLASS_IR:
            case CLASS_IR:
+             if ((segmented_mode && operands[i].regsize != CLASS_REG_LONG)
+                 || (!segmented_mode && operands[i].regsize != CLASS_REG_WORD))
+               as_bad (_("invalid indirect register size"));
+             reg[this_try->arg_info[i] & ARG_MASK] = operands[i].reg;
+             break;
+           case CLASS_X:
            case CLASS_BA:
            case CLASS_BX:
            case CLASS_DISP:
            case CLASS_BA:
            case CLASS_BX:
            case CLASS_DISP:
@@ -891,6 +936,10 @@ get_specific (opcode, operands)
            case CLASS_REGN0:
              reg[this_try->arg_info[i] & ARG_MASK] = operands[i].reg;
              break;
            case CLASS_REGN0:
              reg[this_try->arg_info[i] & ARG_MASK] = operands[i].reg;
              break;
+           case CLASS_CTRL:
+             if (this_try->opcode == OPC_ldctlb && the_ctrl != 1)
+               as_bad (_("invalid control register name"));
+             break;
            }
        }
 
            }
        }
 
@@ -904,63 +953,41 @@ get_specific (opcode, operands)
     return 0;
 }
 
     return 0;
 }
 
-#if 0 /* Not used.  */
-static void
-check_operand (operand, width, string)
-     struct z8k_op *operand;
-     unsigned int width;
-     char *string;
-{
-  if (operand->exp.X_add_symbol == 0
-      && operand->exp.X_op_symbol == 0)
-    {
-
-      /* No symbol involved, let's look at offset, it's dangerous if
-        any of the high bits are not 0 or ff's, find out by oring or
-        anding with the width and seeing if the answer is 0 or all
-        fs.  */
-      if ((operand->exp.X_add_number & ~width) != 0 &&
-         (operand->exp.X_add_number | width) != (~0))
-       {
-         as_warn (_("operand %s0x%x out of range."),
-                  string, operand->exp.X_add_number);
-       }
-    }
-
-}
-#endif
-
 static char buffer[20];
 
 static void
 static char buffer[20];
 
 static void
-newfix (ptr, type, operand)
-     int ptr;
-     int type;
-     expressionS *operand;
+newfix (int ptr, int type, int size, expressionS *operand)
 {
 {
+  int is_pcrel = 0;
+  fixS *fixP;
+
+  /* Size is in nibbles.  */
   if (operand->X_add_symbol
       || operand->X_op_symbol
       || operand->X_add_number)
     {
   if (operand->X_add_symbol
       || operand->X_op_symbol
       || operand->X_add_number)
     {
-      fix_new_exp (frag_now,
-                  ptr,
-                  1,
-                  operand,
-                  0,
-                  type);
+      switch(type)
+        {
+        case BFD_RELOC_8_PCREL:
+        case BFD_RELOC_Z8K_CALLR:
+        case BFD_RELOC_Z8K_DISP7:
+          is_pcrel = 1;
+        }
+      fixP = fix_new_exp (frag_now, ptr, size / 2,
+                          operand, is_pcrel, type);
+      if (is_pcrel)
+       fixP->fx_no_overflow = 1;
     }
 }
 
 static char *
     }
 }
 
 static char *
-apply_fix (ptr, type, operand, size)
-     char *ptr;
-     int type;
-     expressionS *operand;
-     int size;
+apply_fix (char *ptr, int type, expressionS *operand, int size)
 {
 {
-  int n = operand->X_add_number;
+  long n = operand->X_add_number;
 
 
-  newfix ((ptr - buffer) / 2, type, operand);
+  /* size is in nibbles.  */
+
+  newfix ((ptr - buffer) / 2, type, size + 1, operand);
   switch (size)
     {
     case 8:                    /* 8 nibbles == 32 bits.  */
   switch (size)
     {
     case 8:                    /* 8 nibbles == 32 bits.  */
@@ -982,22 +1009,20 @@ apply_fix (ptr, type, operand, size)
 
 /* Now we know what sort of opcodes it is.  Let's build the bytes.  */
 
 
 /* Now we know what sort of opcodes it is.  Let's build the bytes.  */
 
-#define INSERT(x,y) *x++ = y>>24; *x++ = y>> 16; *x++=y>>8; *x++ =y;
-
 static void
 static void
-build_bytes (this_try, operand)
-     opcode_entry_type *this_try;
-     struct z8k_op *operand ATTRIBUTE_UNUSED;
+build_bytes (opcode_entry_type *this_try, struct z8k_op *operand ATTRIBUTE_UNUSED)
 {
   char *output_ptr = buffer;
   int c;
 {
   char *output_ptr = buffer;
   int c;
-  int nib;
   int nibble;
   unsigned int *class_ptr;
 
   frag_wane (frag_now);
   frag_new (0);
 
   int nibble;
   unsigned int *class_ptr;
 
   frag_wane (frag_now);
   frag_new (0);
 
+  if (frag_room () < 8)
+    frag_grow (8);  /* Make room for maximum instruction size.  */
+
   memset (buffer, 0, sizeof (buffer));
   class_ptr = this_try->byte_info;
 
   memset (buffer, 0, sizeof (buffer));
   class_ptr = this_try->byte_info;
 
@@ -1014,31 +1039,31 @@ build_bytes (this_try, operand)
          if (segmented_mode)
            {
              /* da_operand->X_add_number |= 0x80000000;  --  Now set at relocation time.  */
          if (segmented_mode)
            {
              /* da_operand->X_add_number |= 0x80000000;  --  Now set at relocation time.  */
-             output_ptr = apply_fix (output_ptr, R_IMM32, da_operand, 8);
+             output_ptr = apply_fix (output_ptr, BFD_RELOC_32, da_operand, 8);
            }
          else
            {
            }
          else
            {
-             output_ptr = apply_fix (output_ptr, R_IMM16, da_operand, 4);
+             output_ptr = apply_fix (output_ptr, BFD_RELOC_16, da_operand, 4);
            }
          da_operand = 0;
          break;
        case CLASS_DISP8:
          /* pc rel 8 bit  */
            }
          da_operand = 0;
          break;
        case CLASS_DISP8:
          /* pc rel 8 bit  */
-         output_ptr = apply_fix (output_ptr, R_JR, da_operand, 2);
+         output_ptr = apply_fix (output_ptr, BFD_RELOC_8_PCREL, da_operand, 2);
          da_operand = 0;
          break;
 
        case CLASS_0DISP7:
          /* pc rel 7 bit  */
          *output_ptr = 0;
          da_operand = 0;
          break;
 
        case CLASS_0DISP7:
          /* pc rel 7 bit  */
          *output_ptr = 0;
-         output_ptr = apply_fix (output_ptr, R_DISP7, da_operand, 2);
+         output_ptr = apply_fix (output_ptr, BFD_RELOC_Z8K_DISP7, da_operand, 2);
          da_operand = 0;
          break;
 
        case CLASS_1DISP7:
          /* pc rel 7 bit  */
          *output_ptr = 0x80;
          da_operand = 0;
          break;
 
        case CLASS_1DISP7:
          /* pc rel 7 bit  */
          *output_ptr = 0x80;
-         output_ptr = apply_fix (output_ptr, R_DISP7, da_operand, 2);
+         output_ptr = apply_fix (output_ptr, BFD_RELOC_Z8K_DISP7, da_operand, 2);
          output_ptr[-2] = 0x8;
          da_operand = 0;
          break;
          output_ptr[-2] = 0x8;
          da_operand = 0;
          break;
@@ -1060,9 +1085,13 @@ build_bytes (this_try, operand)
          *output_ptr++ = the_cc;
          break;
        case CLASS_0CCC:
          *output_ptr++ = the_cc;
          break;
        case CLASS_0CCC:
+         if (the_ctrl < 2 || the_ctrl > 7)
+           as_bad (_("invalid control register name"));
          *output_ptr++ = the_ctrl;
          break;
        case CLASS_1CCC:
          *output_ptr++ = the_ctrl;
          break;
        case CLASS_1CCC:
+         if (the_ctrl < 2 || the_ctrl > 7)
+           as_bad (_("invalid control register name"));
          *output_ptr++ = the_ctrl | 0x8;
          break;
        case CLASS_00II:
          *output_ptr++ = the_ctrl | 0x8;
          break;
        case CLASS_00II:
@@ -1094,49 +1123,48 @@ build_bytes (this_try, operand)
           switch (c & ARG_MASK)
             {
             case ARG_DISP12:
           switch (c & ARG_MASK)
             {
             case ARG_DISP12:
-              output_ptr = apply_fix (output_ptr, R_CALLR, da_operand, 4);
+              output_ptr = apply_fix (output_ptr, BFD_RELOC_Z8K_CALLR, da_operand, 4);
               break;
             case ARG_DISP16:
               break;
             case ARG_DISP16:
-             output_ptr = apply_fix (output_ptr, R_REL16, da_operand, 4);
+             output_ptr = apply_fix (output_ptr, BFD_RELOC_16_PCREL, da_operand, 4);
              break;
            default:
              break;
            default:
-             output_ptr = apply_fix (output_ptr, R_IMM16, da_operand, 4);
+             output_ptr = apply_fix (output_ptr, BFD_RELOC_16, da_operand, 4);
            }
          da_operand = 0;
          break;
 
        case CLASS_IMM:
          {
            }
          da_operand = 0;
          break;
 
        case CLASS_IMM:
          {
-           nib = 0;
            switch (c & ARG_MASK)
              {
              case ARG_NIM4:
            switch (c & ARG_MASK)
              {
              case ARG_NIM4:
+                if (imm_operand->X_add_number > 15)
+                 as_bad (_("immediate value out of range"));
                imm_operand->X_add_number = -imm_operand->X_add_number;
                imm_operand->X_add_number = -imm_operand->X_add_number;
-               /* Drop through.  */
-             case ARG_IMM4:
-               output_ptr = apply_fix (output_ptr, R_IMM4L, imm_operand, 1);
+               output_ptr = apply_fix (output_ptr, BFD_RELOC_Z8K_IMM4L, imm_operand, 1);
                break;
                break;
+              /*case ARG_IMMNMINUS1: not used.  */
              case ARG_IMM4M1:
                imm_operand->X_add_number--;
              case ARG_IMM4M1:
                imm_operand->X_add_number--;
-               output_ptr = apply_fix (output_ptr, R_IMM4L, imm_operand, 1);
-               break;
-             case ARG_IMMNMINUS1:
-               imm_operand->X_add_number--;
-               output_ptr = apply_fix (output_ptr, R_IMM4L, imm_operand, 1);
+                /* Drop through.  */
+             case ARG_IMM4:
+                if (imm_operand->X_add_number > 15)
+                 as_bad (_("immediate value out of range"));
+               output_ptr = apply_fix (output_ptr, BFD_RELOC_Z8K_IMM4L, imm_operand, 1);
                break;
              case ARG_NIM8:
                imm_operand->X_add_number = -imm_operand->X_add_number;
                break;
              case ARG_NIM8:
                imm_operand->X_add_number = -imm_operand->X_add_number;
+                /* Drop through.  */
              case ARG_IMM8:
              case ARG_IMM8:
-               output_ptr = apply_fix (output_ptr, R_IMM8, imm_operand, 2);
+               output_ptr = apply_fix (output_ptr, BFD_RELOC_8, imm_operand, 2);
                break;
              case ARG_IMM16:
                break;
              case ARG_IMM16:
-               output_ptr = apply_fix (output_ptr, R_IMM16, imm_operand, 4);
+               output_ptr = apply_fix (output_ptr, BFD_RELOC_16, imm_operand, 4);
                break;
                break;
-
              case ARG_IMM32:
              case ARG_IMM32:
-               output_ptr = apply_fix (output_ptr, R_IMM32, imm_operand, 8);
+               output_ptr = apply_fix (output_ptr, BFD_RELOC_32, imm_operand, 8);
                break;
                break;
-
              default:
                abort ();
              }
              default:
                abort ();
              }
@@ -1164,15 +1192,13 @@ build_bytes (this_try, operand)
    the frags/bytes it assembles to.  */
 
 void
    the frags/bytes it assembles to.  */
 
 void
-md_assemble (str)
-     char *str;
+md_assemble (char *str)
 {
   char c;
   char *op_start;
   char *op_end;
 {
   char c;
   char *op_start;
   char *op_end;
-  struct z8k_op operand[3];
+  struct z8k_op operand[4];
   opcode_entry_type *opcode;
   opcode_entry_type *opcode;
-  opcode_entry_type *prev_opcode;
 
   /* Drop leading whitespace.  */
   while (*str == ' ')
 
   /* Drop leading whitespace.  */
   while (*str == ' ')
@@ -1180,7 +1206,7 @@ md_assemble (str)
 
   /* Find the op code end.  */
   for (op_start = op_end = str;
 
   /* Find the op code end.  */
   for (op_start = op_end = str;
-       *op_end != 0 && *op_end != ' ';
+       *op_end != 0 && *op_end != ' ' && ! is_end_of_line[(unsigned char) *op_end];
        op_end++)
     ;
 
        op_end++)
     ;
 
@@ -1190,7 +1216,7 @@ md_assemble (str)
     }
   c = *op_end;
 
     }
   c = *op_end;
 
-  *op_end = 0;
+  *op_end = 0;  /* Zero-terminate op code string for hash_find() call.  */
 
   opcode = (opcode_entry_type *) hash_find (opcode_hash_control, op_start);
 
 
   opcode = (opcode_entry_type *) hash_find (opcode_hash_control, op_start);
 
@@ -1200,12 +1226,13 @@ md_assemble (str)
       return;
     }
 
       return;
     }
 
+  *op_end = c;  /* Restore original string.  */
+
   if (opcode->opcode == 250)
     {
       pseudo_typeS *p;
       char oc;
       char *old = input_line_pointer;
   if (opcode->opcode == 250)
     {
       pseudo_typeS *p;
       char oc;
       char *old = input_line_pointer;
-      *op_end = c;
 
       /* Was really a pseudo op.  */
 
 
       /* Was really a pseudo op.  */
 
@@ -1227,12 +1254,12 @@ md_assemble (str)
 
       new_input_line_pointer = get_operands (opcode, op_end, operand);
       if (new_input_line_pointer)
 
       new_input_line_pointer = get_operands (opcode, op_end, operand);
       if (new_input_line_pointer)
-        input_line_pointer = new_input_line_pointer;
-      prev_opcode = opcode;
-
-      opcode = get_specific (opcode, operand);
+        {
+          input_line_pointer = new_input_line_pointer;
+          opcode = get_specific (opcode, operand);
+        }
 
 
-      if (opcode == 0)
+      if (new_input_line_pointer == NULL || opcode == NULL)
        {
          /* Couldn't find an opcode which matched the operands.  */
          char *where = frag_more (2);
        {
          /* Couldn't find an opcode which matched the operands.  */
          char *where = frag_more (2);
@@ -1248,112 +1275,43 @@ md_assemble (str)
     }
 }
 
     }
 }
 
-void
-tc_crawl_symbol_chain (headers)
-     object_headers *headers ATTRIBUTE_UNUSED;
-{
-  printf (_("call to tc_crawl_symbol_chain \n"));
-}
+/* We have no need to default values of symbols.  */
 
 symbolS *
 
 symbolS *
-md_undefined_symbol (name)
-     char *name ATTRIBUTE_UNUSED;
+md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
 {
   return 0;
 }
 
 {
   return 0;
 }
 
-void
-tc_headers_hook (headers)
-     object_headers *headers ATTRIBUTE_UNUSED;
-{
-  printf (_("call to tc_headers_hook \n"));
-}
-
 /* Various routines to kill one day.  */
 /* Various routines to kill one day.  */
-/* Equal to MAX_PRECISION in atof-ieee.c.  */
-#define MAX_LITTLENUMS 6
-
-/* Turn a string in input_line_pointer into a floating point constant
-   of type TYPE, and store the appropriate bytes in *LITP.  The number
-   of LITTLENUMS emitted is stored in *SIZEP.  An error message is
-   returned, or NULL on OK.  */
-
-char *
-md_atof (type, litP, sizeP)
-     char type;
-     char *litP;
-     int *sizeP;
-{
-  int prec;
-  LITTLENUM_TYPE words[MAX_LITTLENUMS];
-  LITTLENUM_TYPE *wordP;
-  char *t;
-  char *atof_ieee ();
-
-  switch (type)
-    {
-    case 'f':
-    case 'F':
-    case 's':
-    case 'S':
-      prec = 2;
-      break;
-
-    case 'd':
-    case 'D':
-    case 'r':
-    case 'R':
-      prec = 4;
-      break;
 
 
-    case 'x':
-    case 'X':
-      prec = 6;
-      break;
-
-    case 'p':
-    case 'P':
-      prec = 6;
-      break;
-
-    default:
-      *sizeP = 0;
-      return _("Bad call to MD_ATOF()");
-    }
-  t = atof_ieee (input_line_pointer, type, words);
-  if (t)
-    input_line_pointer = t;
-
-  *sizeP = prec * sizeof (LITTLENUM_TYPE);
-  for (wordP = words; prec--;)
-    {
-      md_number_to_chars (litP, (long) (*wordP++), sizeof (LITTLENUM_TYPE));
-      litP += sizeof (LITTLENUM_TYPE);
-    }
-  return 0;
+const char *
+md_atof (int type, char *litP, int *sizeP)
+{
+  return ieee_md_atof (type, litP, sizeP, TRUE);
 }
 \f
 const char *md_shortopts = "z:";
 
 struct option md_longopts[] =
   {
 }
 \f
 const char *md_shortopts = "z:";
 
 struct option md_longopts[] =
   {
+#define OPTION_RELAX  (OPTION_MD_BASE)
+    {"linkrelax", no_argument, NULL, OPTION_RELAX},
     {NULL, no_argument, NULL, 0}
   };
 
 size_t md_longopts_size = sizeof (md_longopts);
 
 int
     {NULL, no_argument, NULL, 0}
   };
 
 size_t md_longopts_size = sizeof (md_longopts);
 
 int
-md_parse_option (c, arg)
-     int c;
-     char *arg;
+md_parse_option (int c, const char *arg)
 {
   switch (c)
     {
     case 'z':
       if (!strcmp (arg, "8001"))
 {
   switch (c)
     {
     case 'z':
       if (!strcmp (arg, "8001"))
-       s_segm ();
+       z8k_target_from_cmdline = 2;
       else if (!strcmp (arg, "8002"))
       else if (!strcmp (arg, "8002"))
-       s_unseg ();
+       z8k_target_from_cmdline = 1;
       else
        {
          as_bad (_("invalid architecture -z%s"), arg);
       else
        {
          as_bad (_("invalid architecture -z%s"), arg);
@@ -1361,6 +1319,10 @@ md_parse_option (c, arg)
        }
       break;
 
        }
       break;
 
+    case OPTION_RELAX:
+      linkrelax = 1;
+      break;
+
     default:
       return 0;
     }
     default:
       return 0;
     }
@@ -1369,101 +1331,203 @@ md_parse_option (c, arg)
 }
 
 void
 }
 
 void
-md_show_usage (stream)
-     FILE *stream;
+md_show_usage (FILE *stream)
 {
   fprintf (stream, _("\
 {
   fprintf (stream, _("\
-Z8K options:\n\
--z8001                 generate segmented code\n\
--z8002                 generate unsegmented code\n"));
+ Z8K options:\n\
+  -z8001                  generate segmented code\n\
+  -z8002                  generate unsegmented code\n\
+  -linkrelax              create linker relaxable code\n"));
 }
 \f
 void
 }
 \f
 void
-tc_aout_fix_to_chars ()
+md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED,
+                 segT sec ATTRIBUTE_UNUSED,
+                 fragS *fragP ATTRIBUTE_UNUSED)
 {
 {
-  printf (_("call to tc_aout_fix_to_chars \n"));
+  printf (_("call to md_convert_frag\n"));
   abort ();
 }
 
   abort ();
 }
 
-void
-md_convert_frag (headers, seg, fragP)
-     object_headers *headers ATTRIBUTE_UNUSED;
-     segT seg ATTRIBUTE_UNUSED;
-     fragS *fragP ATTRIBUTE_UNUSED;
+/* Generate a machine dependent reloc from a fixup.  */
+
+arelent*
+tc_gen_reloc (asection *section ATTRIBUTE_UNUSED,
+             fixS *fixp      ATTRIBUTE_UNUSED)
 {
 {
-  printf (_("call to md_convert_frag \n"));
-  abort ();
+  arelent *reloc;
+
+  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->addend = fixp->fx_offset;
+  reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
+
+  if (! reloc->howto)
+    {
+      as_bad_where (fixp->fx_file, fixp->fx_line,
+                    _("Cannot represent %s relocation in object file"),
+                    bfd_get_reloc_code_name (fixp->fx_r_type));
+      abort ();
+    }
+  return reloc;
 }
 
 valueT
 }
 
 valueT
-md_section_align (seg, size)
-     segT seg;
-     valueT size;
+md_section_align (segT seg, valueT size)
 {
 {
-  return ((size + (1 << section_alignment[(int) seg]) - 1)
-         & (-1 << section_alignment[(int) seg]));
+  int align = bfd_get_section_alignment (stdoutput, seg);
+  valueT mask = ((valueT) 1 << align) - 1;
+
+  return (size + mask) & ~mask;
 }
 
 }
 
+/* Attempt to simplify or eliminate a fixup. To indicate that a fixup
+   has been eliminated, set fix->fx_done. If fix->fx_addsy is non-NULL,
+   we will have to generate a reloc entry.  */
 void
 void
-md_apply_fix3 (fixP, valP, segment)
-     fixS * fixP;
-     valueT * valP;
-     segT segment ATTRIBUTE_UNUSED;
+md_apply_fix (fixS *fixP, valueT *valP, segT segment ATTRIBUTE_UNUSED)
 {
   long val = * (long *) valP;
   char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
 
   switch (fixP->fx_r_type)
     {
 {
   long val = * (long *) valP;
   char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
 
   switch (fixP->fx_r_type)
     {
-    case R_IMM4L:
-      buf[0] = (buf[0] & 0xf0) | ((buf[0] + val) & 0xf);
+    case BFD_RELOC_Z8K_IMM4L:
+      if (fixP->fx_addsy)
+        {
+          fixP->fx_no_overflow = 1;
+          fixP->fx_done = 0;
+        }
+      else
+       buf[0] = (buf[0] & 0xf0) | (val & 0xf);
       break;
 
       break;
 
-    case R_JR:
-
-      *buf++ = val;
-#if 0
-      if (val != 0)
-       abort ();
-#endif
+    case BFD_RELOC_8:
+      if (fixP->fx_addsy)
+        {
+          fixP->fx_no_overflow = 1;
+          fixP->fx_done = 0;
+        }
+      else
+       *buf++ = val;
       break;
 
       break;
 
-    case R_DISP7:
-
-      *buf++ += val;
-#if 0
-      if (val != 0)
-       abort ();
-#endif
+    case BFD_RELOC_16:
+      if (fixP->fx_addsy)
+        {
+          fixP->fx_no_overflow = 1;
+          fixP->fx_done = 0;
+        }
+      else
+        {
+          *buf++ = (val >> 8);
+          *buf++ = val;
+        }
       break;
 
       break;
 
-    case R_IMM8:
-      buf[0] += val;
+    case BFD_RELOC_32:
+      if (fixP->fx_addsy)
+        {
+          fixP->fx_no_overflow = 1;
+          fixP->fx_done = 0;
+        }
+      else
+        {
+          *buf++ = (val >> 24);
+          *buf++ = (val >> 16);
+          *buf++ = (val >> 8);
+          *buf++ = val;
+        }
       break;
       break;
-    case R_IMM16:
-      *buf++ = (val >> 8);
-      *buf++ = val;
+
+    case BFD_RELOC_8_PCREL:
+      if (fixP->fx_addsy)
+        {
+          fixP->fx_no_overflow = 1;
+          fixP->fx_done = 0;
+        }
+      else
+        {
+          if (val & 1)
+            as_bad_where (fixP->fx_file, fixP->fx_line,
+                          _("cannot branch to odd address"));
+          val /= 2;
+          if (val > 127 || val < -128)
+            as_bad_where (fixP->fx_file, fixP->fx_line,
+                          _("relative jump out of range"));
+          *buf++ = val;
+          fixP->fx_no_overflow = 1;
+          fixP->fx_done = 1;
+        }
       break;
       break;
-    case R_IMM32:
-      *buf++ = (val >> 24);
-      *buf++ = (val >> 16);
-      *buf++ = (val >> 8);
-      *buf++ = val;
+
+    case BFD_RELOC_16_PCREL:
+      if (fixP->fx_addsy)
+        {
+          fixP->fx_no_overflow = 1;
+          fixP->fx_done = 0;
+        }
+      else
+        {
+          val = val - fixP->fx_frag->fr_address + fixP->fx_where - fixP->fx_size;
+          if (val > 32767 || val < -32768)
+            as_bad_where (fixP->fx_file, fixP->fx_line,
+                          _("relative address out of range"));
+          *buf++ = (val >> 8);
+          *buf++ = val;
+          fixP->fx_no_overflow = 1;
+          fixP->fx_done = 1;
+        }
       break;
       break;
-#if 0
-    case R_DA | R_SEG:
-      *buf++ = (val >> 16);
-      *buf++ = 0x00;
-      *buf++ = (val >> 8);
-      *buf++ = val;
+
+    case BFD_RELOC_Z8K_CALLR:
+      if (fixP->fx_addsy)
+        {
+          fixP->fx_no_overflow = 1;
+          fixP->fx_done = 0;
+        }
+      else
+        {
+          if (val & 1)
+            as_bad_where (fixP->fx_file, fixP->fx_line,
+                          _("cannot branch to odd address"));
+          if (val > 4096 || val < -4095)
+            as_bad_where (fixP->fx_file, fixP->fx_line,
+                          _("relative call out of range"));
+          val = -val / 2;
+          *buf = (*buf & 0xf0) | ((val >> 8) & 0xf);
+          buf++;
+          *buf++ = val & 0xff;
+          fixP->fx_no_overflow = 1;
+          fixP->fx_done = 1;
+        }
       break;
       break;
-#endif
 
 
-    case 0:
-      md_number_to_chars (buf, val, fixP->fx_size);
+    case BFD_RELOC_Z8K_DISP7:
+      if (fixP->fx_addsy)
+        {
+          fixP->fx_no_overflow = 1;
+          fixP->fx_done = 0;
+        }
+      else
+        {
+          if (val & 1)
+            as_bad_where (fixP->fx_file, fixP->fx_line,
+                          _("cannot branch to odd address"));
+          val /= 2;
+          if (val > 0 || val < -127)
+            as_bad_where (fixP->fx_file, fixP->fx_line,
+                          _("relative jump out of range"));
+          *buf = (*buf & 0x80) | (-val & 0x7f);
+          fixP->fx_no_overflow = 1;
+          fixP->fx_done = 1;
+        }
       break;
 
     default:
       break;
 
     default:
+      printf(_("md_apply_fix: unknown r_type 0x%x\n"), fixP->fx_r_type);
       abort ();
     }
 
       abort ();
     }
 
@@ -1472,95 +1536,30 @@ md_apply_fix3 (fixP, valP, segment)
 }
 
 int
 }
 
 int
-md_estimate_size_before_relax (fragP, segment_type)
-     register fragS *fragP ATTRIBUTE_UNUSED;
-     register segT segment_type ATTRIBUTE_UNUSED;
+md_estimate_size_before_relax (fragS *fragP ATTRIBUTE_UNUSED,
+                               segT segment_type ATTRIBUTE_UNUSED)
 {
 {
-  printf (_("call tomd_estimate_size_before_relax\n"));
+  printf (_("call to md_estimate_size_before_relax\n"));
   abort ();
 }
 
 /* Put number into target byte order.  */
 
 void
   abort ();
 }
 
 /* Put number into target byte order.  */
 
 void
-md_number_to_chars (ptr, use, nbytes)
-     char *ptr;
-     valueT use;
-     int nbytes;
+md_number_to_chars (char *ptr, valueT use, int nbytes)
 {
   number_to_chars_bigendian (ptr, use, nbytes);
 }
 
 {
   number_to_chars_bigendian (ptr, use, nbytes);
 }
 
+/* On the Z8000, a PC-relative offset is relative to the address of the
+   instruction plus its size.  */
 long
 long
-md_pcrel_from (fixP)
-     fixS *fixP ATTRIBUTE_UNUSED;
+md_pcrel_from (fixS *fixP)
 {
 {
-  abort ();
+  return fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address;
 }
 
 void
 }
 
 void
-tc_coff_symbol_emit_hook (s)
-     symbolS *s ATTRIBUTE_UNUSED;
+tc_coff_symbol_emit_hook (symbolS *s ATTRIBUTE_UNUSED)
 {
 }
 {
 }
-
-void
-tc_reloc_mangle (fix_ptr, intr, base)
-     fixS *fix_ptr;
-     struct internal_reloc *intr;
-     bfd_vma base;
-
-{
-  symbolS *symbol_ptr;
-
-  if (fix_ptr->fx_addsy
-      && fix_ptr->fx_subsy)
-    {
-      symbolS *add = fix_ptr->fx_addsy;
-      symbolS *sub = fix_ptr->fx_subsy;
-
-      if (S_GET_SEGMENT (add) != S_GET_SEGMENT (sub))
-       as_bad (_("Can't subtract symbols in different sections %s %s"),
-               S_GET_NAME (add), S_GET_NAME (sub));
-      else
-       {
-         int diff = S_GET_VALUE (add) - S_GET_VALUE (sub);
-
-         fix_ptr->fx_addsy = 0;
-         fix_ptr->fx_subsy = 0;
-         fix_ptr->fx_offset += diff;
-       }
-    }
-  symbol_ptr = fix_ptr->fx_addsy;
-
-  /* If this relocation is attached to a symbol then it's ok
-     to output it.  */
-  if (fix_ptr->fx_r_type == 0)
-    {
-      /* cons likes to create reloc32's whatever the size of the reloc.  */
-      switch (fix_ptr->fx_size)
-       {
-       case 2:
-         intr->r_type = R_IMM16;
-         break;
-       case 1:
-         intr->r_type = R_IMM8;
-         break;
-       case 4:
-         intr->r_type = R_IMM32;
-         break;
-       default:
-         abort ();
-       }
-    }
-  else
-    intr->r_type = fix_ptr->fx_r_type;
-
-  intr->r_vaddr = fix_ptr->fx_frag->fr_address + fix_ptr->fx_where + base;
-  intr->r_offset = fix_ptr->fx_offset;
-
-  if (symbol_ptr)
-    intr->r_symndx = symbol_ptr->sy_number;
-  else
-    intr->r_symndx = -1;
-}
This page took 0.068436 seconds and 4 git commands to generate.