x86-64: accept 64-bit LFS/LGS/LSS forms with suffix or operand size specifier
[deliverable/binutils-gdb.git] / gas / config / tc-h8300.c
index f383e79d232230175ded87bf944e15ad7b31dcda..c79c6d42255dcb320125a9a827ab0443f69e31e4 100644 (file)
@@ -1,12 +1,11 @@
 /* tc-h8300.c -- Assemble code for the Renesas H8/300
 /* tc-h8300.c -- Assemble code for the Renesas H8/300
-   Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2000,
-   2001, 2002, 2003 Free Software Foundation, Inc.
+   Copyright (C) 1991-2019 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>.  */
 
-#include <stdio.h>
 #include "as.h"
 #include "subsegs.h"
 #include "as.h"
 #include "subsegs.h"
-#include "bfd.h"
-
-#ifdef BFD_ASSEMBLER
 #include "dwarf2dbg.h"
 #include "dwarf2dbg.h"
-#endif
 
 #define DEFINE_TABLE
 #define h8_opcodes ops
 #include "opcode/h8300.h"
 #include "safe-ctype.h"
 
 #define DEFINE_TABLE
 #define h8_opcodes ops
 #include "opcode/h8300.h"
 #include "safe-ctype.h"
-
-#ifdef OBJ_ELF
 #include "elf/h8.h"
 #include "elf/h8.h"
-#endif
 
 const char comment_chars[] = ";";
 const char line_comment_chars[] = "#";
 
 const char comment_chars[] = ";";
 const char line_comment_chars[] = "#";
+#ifdef TE_LINUX
+const char line_separator_chars[] = "!";
+#else
 const char line_separator_chars[] = "";
 const char line_separator_chars[] = "";
+#endif
 
 
-void cons         PARAMS ((int));
-void sbranch      PARAMS ((int));
-void h8300hmode   PARAMS ((int));
-void h8300smode   PARAMS ((int));
-void h8300hnmode  PARAMS ((int));
-void h8300snmode  PARAMS ((int));
-void h8300sxmode  PARAMS ((int));
-void h8300sxnmode PARAMS ((int));
-static void pint  PARAMS ((int));
+static void sbranch (int);
+static void h8300hmode (int);
+static void h8300smode (int);
+static void h8300hnmode (int);
+static void h8300snmode (int);
+static void h8300sxmode (int);
+static void h8300sxnmode (int);
+static void pint (int);
 
 int Hmode;
 int Smode;
 int Nmode;
 int SXmode;
 
 
 int Hmode;
 int Smode;
 int Nmode;
 int SXmode;
 
-#define PSIZE (Hmode ? L_32 : L_16)
+static int default_mach = bfd_mach_h8300;
+
+#define PSIZE (Hmode && !Nmode ? L_32 : L_16)
 
 
-int bsize = L_8;               /* Default branch displacement.  */
+static int bsize = L_8;                /* Default branch displacement.  */
 
 struct h8_instruction
 {
 
 struct h8_instruction
 {
@@ -71,99 +67,121 @@ struct h8_instruction
   const struct h8_opcode *opcode;
 };
 
   const struct h8_opcode *opcode;
 };
 
-struct h8_instruction *h8_instructions;
+static struct h8_instruction *h8_instructions;
 
 
-void
-h8300hmode (arg)
-     int arg ATTRIBUTE_UNUSED;
+static void
+h8300hmode (int arg ATTRIBUTE_UNUSED)
 {
   Hmode = 1;
   Smode = 0;
 {
   Hmode = 1;
   Smode = 0;
-#ifdef BFD_ASSEMBLER
   if (!bfd_set_arch_mach (stdoutput, bfd_arch_h8300, bfd_mach_h8300h))
     as_warn (_("could not set architecture and machine"));
   if (!bfd_set_arch_mach (stdoutput, bfd_arch_h8300, bfd_mach_h8300h))
     as_warn (_("could not set architecture and machine"));
-#endif
 }
 
 }
 
-void
-h8300smode (arg)
-     int arg ATTRIBUTE_UNUSED;
+static void
+h8300smode (int arg ATTRIBUTE_UNUSED)
 {
   Smode = 1;
   Hmode = 1;
 {
   Smode = 1;
   Hmode = 1;
-#ifdef BFD_ASSEMBLER
   if (!bfd_set_arch_mach (stdoutput, bfd_arch_h8300, bfd_mach_h8300s))
     as_warn (_("could not set architecture and machine"));
   if (!bfd_set_arch_mach (stdoutput, bfd_arch_h8300, bfd_mach_h8300s))
     as_warn (_("could not set architecture and machine"));
-#endif
 }
 
 }
 
-void
-h8300hnmode (arg)
-     int arg ATTRIBUTE_UNUSED;
+static void
+h8300hnmode (int arg ATTRIBUTE_UNUSED)
 {
   Hmode = 1;
   Smode = 0;
   Nmode = 1;
 {
   Hmode = 1;
   Smode = 0;
   Nmode = 1;
-#ifdef BFD_ASSEMBLER
   if (!bfd_set_arch_mach (stdoutput, bfd_arch_h8300, bfd_mach_h8300hn))
     as_warn (_("could not set architecture and machine"));
   if (!bfd_set_arch_mach (stdoutput, bfd_arch_h8300, bfd_mach_h8300hn))
     as_warn (_("could not set architecture and machine"));
-#endif
 }
 
 }
 
-void
-h8300snmode (arg)
-     int arg ATTRIBUTE_UNUSED;
+static void
+h8300snmode (int arg ATTRIBUTE_UNUSED)
 {
   Smode = 1;
   Hmode = 1;
   Nmode = 1;
 {
   Smode = 1;
   Hmode = 1;
   Nmode = 1;
-#ifdef BFD_ASSEMBLER
   if (!bfd_set_arch_mach (stdoutput, bfd_arch_h8300, bfd_mach_h8300sn))
     as_warn (_("could not set architecture and machine"));
   if (!bfd_set_arch_mach (stdoutput, bfd_arch_h8300, bfd_mach_h8300sn))
     as_warn (_("could not set architecture and machine"));
-#endif
 }
 
 }
 
-void
-h8300sxmode (arg)
-     int arg ATTRIBUTE_UNUSED;
+static void
+h8300sxmode (int arg ATTRIBUTE_UNUSED)
 {
   Smode = 1;
   Hmode = 1;
   SXmode = 1;
 {
   Smode = 1;
   Hmode = 1;
   SXmode = 1;
-#ifdef BFD_ASSEMBLER
   if (!bfd_set_arch_mach (stdoutput, bfd_arch_h8300, bfd_mach_h8300sx))
     as_warn (_("could not set architecture and machine"));
   if (!bfd_set_arch_mach (stdoutput, bfd_arch_h8300, bfd_mach_h8300sx))
     as_warn (_("could not set architecture and machine"));
-#endif
 }
 
 }
 
-void
-h8300sxnmode (arg)
-     int arg ATTRIBUTE_UNUSED;
+static void
+h8300sxnmode (int arg ATTRIBUTE_UNUSED)
 {
   Smode = 1;
   Hmode = 1;
   SXmode = 1;
   Nmode = 1;
 {
   Smode = 1;
   Hmode = 1;
   SXmode = 1;
   Nmode = 1;
-#ifdef BFD_ASSEMBLER
   if (!bfd_set_arch_mach (stdoutput, bfd_arch_h8300, bfd_mach_h8300sxn))
     as_warn (_("could not set architecture and machine"));
   if (!bfd_set_arch_mach (stdoutput, bfd_arch_h8300, bfd_mach_h8300sxn))
     as_warn (_("could not set architecture and machine"));
-#endif
 }
 
 }
 
-void
-sbranch (size)
-     int size;
+static void
+sbranch (int size)
 {
   bsize = size;
 }
 
 static void
 {
   bsize = size;
 }
 
 static void
-pint (arg)
-     int arg ATTRIBUTE_UNUSED;
+pint (int arg ATTRIBUTE_UNUSED)
 {
   cons (Hmode ? 4 : 2);
 }
 
 {
   cons (Hmode ? 4 : 2);
 }
 
+/* Like obj_elf_section, but issues a warning for new
+   sections which do not have an attribute specification.  */
+
+static void
+h8300_elf_section (int push)
+{
+  static const char * known_data_sections [] = { ".rodata", ".tdata", ".tbss" };
+  static const char * known_data_prefixes [] = { ".debug", ".zdebug", ".gnu.warning" };
+  char * saved_ilp = input_line_pointer;
+  const char * name;
+
+  name = obj_elf_section_name ();
+  if (name == NULL)
+    return;
+
+  if (* input_line_pointer != ','
+      && bfd_get_section_by_name (stdoutput, name) == NULL)
+    {
+      signed int i;
+
+      /* Ignore this warning for well known data sections.  */
+      for (i = ARRAY_SIZE (known_data_sections); i--;)
+       if (strcmp (name, known_data_sections[i]) == 0)
+         break;
+
+      if (i < 0)
+       for (i = ARRAY_SIZE (known_data_prefixes); i--;)
+         if (strncmp (name, known_data_prefixes[i],
+                      strlen (known_data_prefixes[i])) == 0)
+           break;
+
+      if (i < 0)
+       as_warn (_("new section '%s' defined without attributes - this might cause problems"), name);
+    }
+
+  /* FIXME: We ought to free the memory allocated by obj_elf_section_name()
+     for 'name', but we do not know if it was taken from the obstack, via
+     demand_copy_C_string(), or xmalloc()ed.  */
+  input_line_pointer = saved_ilp;
+  obj_elf_section (push);
+}
+
 /* This table describes all the machine specific pseudo-ops the assembler
    has to support.  The fields are:
    pseudo-op name without dot
 /* This table describes all the machine specific pseudo-ops the assembler
    has to support.  The fields are:
    pseudo-op name without dot
@@ -190,11 +208,15 @@ 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},
+
+  {"section",   h8300_elf_section, 0},
+  {"section.s", h8300_elf_section, 0},
+  {"sect",      h8300_elf_section, 0},
+  {"sect.s",    h8300_elf_section, 0},
+
   {0, 0, 0}
 };
 
   {0, 0, 0}
 };
 
-const int md_reloc_size;
-
 const char EXP_CHARS[] = "eE";
 
 /* Chars that mean this number is a floating point constant
 const char EXP_CHARS[] = "eE";
 
 /* Chars that mean this number is a floating point constant
@@ -209,7 +231,7 @@ static struct hash_control *opcode_hash_control;    /* Opcode mnemonics.  */
    needs.  */
 
 void
    needs.  */
 
 void
-md_begin ()
+md_begin (void)
 {
   unsigned int nopcodes;
   struct h8_opcode *p, *p1;
 {
   unsigned int nopcodes;
   struct h8_opcode *p, *p1;
@@ -217,18 +239,15 @@ md_begin ()
   char prev_buffer[100];
   int idx = 0;
 
   char prev_buffer[100];
   int idx = 0;
 
-#ifdef BFD_ASSEMBLER
-  if (!bfd_set_arch_mach (stdoutput, bfd_arch_h8300, bfd_mach_h8300))
+  if (!bfd_set_arch_mach (stdoutput, bfd_arch_h8300, default_mach))
     as_warn (_("could not set architecture and machine"));
     as_warn (_("could not set architecture and machine"));
-#endif
 
   opcode_hash_control = hash_new ();
   prev_buffer[0] = 0;
 
   nopcodes = sizeof (h8_opcodes) / sizeof (struct h8_opcode);
 
   opcode_hash_control = hash_new ();
   prev_buffer[0] = 0;
 
   nopcodes = sizeof (h8_opcodes) / sizeof (struct h8_opcode);
-  
-  h8_instructions = (struct h8_instruction *)
-    xmalloc (nopcodes * sizeof (struct h8_instruction));
+
+  h8_instructions = XNEWVEC (struct h8_instruction, nopcodes);
 
   pi = h8_instructions;
   p1 = h8_opcodes;
 
   pi = h8_instructions;
   p1 = h8_opcodes;
@@ -241,14 +260,14 @@ md_begin ()
     {
       struct h8_opcode *first_skipped = 0;
       int len, cmplen = 0;
     {
       struct h8_opcode *first_skipped = 0;
       int len, cmplen = 0;
-      char *src = p1->name;
+      const char *src = p1->name;
       char *dst, *buffer;
 
       if (p1->name == 0)
        break;
       /* Strip off any . part when inserting the opcode and only enter
         unique codes into the hash table.  */
       char *dst, *buffer;
 
       if (p1->name == 0)
        break;
       /* Strip off any . part when inserting the opcode and only enter
         unique codes into the hash table.  */
-      dst = buffer = malloc (strlen (src) + 1);
+      dst = buffer = XNEWVEC (char, strlen (src) + 1);
       while (*src)
        {
          if (*src == '.')
       while (*src)
        {
          if (*src == '.')
@@ -319,13 +338,6 @@ md_begin ()
   linkrelax = 1;
 }
 
   linkrelax = 1;
 }
 
-struct h8_exp
-{
-  char *e_beg;
-  char *e_end;
-  expressionS e_exp;
-};
-
 struct h8_op
 {
   op_type mode;
 struct h8_op
 {
   op_type mode;
@@ -333,20 +345,19 @@ struct h8_op
   expressionS exp;
 };
 
   expressionS exp;
 };
 
-static void clever_message PARAMS ((const struct h8_instruction *, struct h8_op *));
-static void fix_operand_size PARAMS ((struct h8_op *, int));
-static void build_bytes    PARAMS ((const struct h8_instruction *, struct h8_op *));
-static void do_a_fix_imm   PARAMS ((int, int, struct h8_op *, int));
-static void check_operand  PARAMS ((struct h8_op *, unsigned int, char *));
-static const struct h8_instruction * get_specific PARAMS ((const struct h8_instruction *, struct h8_op *, int));
-static char *get_operands PARAMS ((unsigned, char *, struct h8_op *));
-static void get_operand PARAMS ((char **, struct h8_op *, int));
-static int parse_reg PARAMS ((char *, op_type *, unsigned *, int));
-static char *skip_colonthing PARAMS ((char *, int *));
-static char *parse_exp PARAMS ((char *, struct h8_op *));
-
-static int constant_fits_width_p PARAMS ((struct h8_op *, unsigned int));
-static int constant_fits_size_p PARAMS ((struct h8_op *, int, int));
+static void clever_message (const struct h8_instruction *, struct h8_op *);
+static void fix_operand_size (struct h8_op *, int);
+static void build_bytes (const struct h8_instruction *, struct h8_op *);
+static void do_a_fix_imm (int, int, struct h8_op *, int, const struct h8_instruction *);
+static void check_operand (struct h8_op *, unsigned int, const char *);
+static const struct h8_instruction * get_specific (const struct h8_instruction *, struct h8_op *, int) ;
+static char *get_operands (unsigned, char *, struct h8_op *);
+static void get_operand (char **, struct h8_op *, int);
+static int parse_reg (char *, op_type *, unsigned *, int);
+static char *skip_colonthing (char *, int *);
+static char *parse_exp (char *, struct h8_op *);
+
+static int constant_fits_size_p (struct h8_op *, int, int);
 
 /*
   parse operands
 
 /*
   parse operands
@@ -362,16 +373,12 @@ static int constant_fits_size_p PARAMS ((struct h8_op *, int, int));
 /* Try to parse a reg name.  Return the number of chars consumed.  */
 
 static int
 /* Try to parse a reg name.  Return the number of chars consumed.  */
 
 static int
-parse_reg (src, mode, reg, direction)
-     char *src;
-     op_type *mode;
-     unsigned int *reg;
-     int direction;
+parse_reg (char *src, op_type *mode, unsigned int *reg, int direction)
 {
   char *end;
   int len;
 
 {
   char *end;
   int len;
 
-  /* Cribbed from get_symbol_end.  */
+  /* Cribbed from get_symbol_name.  */
   if (!is_name_beginner (*src) || *src == '\001')
     return 0;
   end = src + 1;
   if (!is_name_beginner (*src) || *src == '\001')
     return 0;
   end = src + 1;
@@ -385,36 +392,36 @@ parse_reg (src, mode, reg, direction)
       *reg = 7;
       return len;
     }
       *reg = 7;
       return len;
     }
-  if (len == 3 && 
-      TOLOWER (src[0]) == 'c' && 
-      TOLOWER (src[1]) == 'c' && 
+  if (len == 3 &&
+      TOLOWER (src[0]) == 'c' &&
+      TOLOWER (src[1]) == 'c' &&
       TOLOWER (src[2]) == 'r')
     {
       *mode = CCR;
       *reg = 0;
       return len;
     }
       TOLOWER (src[2]) == 'r')
     {
       *mode = CCR;
       *reg = 0;
       return len;
     }
-  if (len == 3 && 
-      TOLOWER (src[0]) == 'e' && 
-      TOLOWER (src[1]) == 'x' && 
+  if (len == 3 &&
+      TOLOWER (src[0]) == 'e' &&
+      TOLOWER (src[1]) == 'x' &&
       TOLOWER (src[2]) == 'r')
     {
       *mode = EXR;
       *reg = 1;
       return len;
     }
       TOLOWER (src[2]) == 'r')
     {
       *mode = EXR;
       *reg = 1;
       return len;
     }
-  if (len == 3 && 
-      TOLOWER (src[0]) == 'v' && 
-      TOLOWER (src[1]) == 'b' && 
+  if (len == 3 &&
+      TOLOWER (src[0]) == 'v' &&
+      TOLOWER (src[1]) == 'b' &&
       TOLOWER (src[2]) == 'r')
     {
       *mode = VBR;
       *reg = 6;
       return len;
     }
       TOLOWER (src[2]) == 'r')
     {
       *mode = VBR;
       *reg = 6;
       return len;
     }
-  if (len == 3 && 
-      TOLOWER (src[0]) == 's' && 
-      TOLOWER (src[1]) == 'b' && 
+  if (len == 3 &&
+      TOLOWER (src[0]) == 's' &&
+      TOLOWER (src[1]) == 'b' &&
       TOLOWER (src[2]) == 'r')
     {
       *mode = SBR;
       TOLOWER (src[2]) == 'r')
     {
       *mode = SBR;
@@ -479,9 +486,7 @@ parse_reg (src, mode, reg, direction)
    in OP->MODE, otherwise leave it for later code to decide.  */
 
 static char *
    in OP->MODE, otherwise leave it for later code to decide.  */
 
 static char *
-parse_exp (src, op)
-     char *src;
-     struct h8_op *op;
+parse_exp (char *src, struct h8_op *op)
 {
   char *save;
 
 {
   char *save;
 
@@ -501,9 +506,7 @@ parse_exp (src, op)
    in *MODE.  Leave *MODE unchanged otherwise.  */
 
 static char *
    in *MODE.  Leave *MODE unchanged otherwise.  */
 
 static char *
-skip_colonthing (src, mode)
-     char *src;
-     int *mode;
+skip_colonthing (char *src, int *mode)
 {
   if (*src == ':')
     {
 {
   if (*src == ':')
     {
@@ -550,23 +553,23 @@ skip_colonthing (src, mode)
    @@aa[:8]            memory indirect.  */
 
 static int
    @@aa[:8]            memory indirect.  */
 
 static int
-constant_fits_width_p (operand, width)
-     struct h8_op *operand;
-     unsigned int width;
+constant_fits_width_p (struct h8_op *operand, offsetT width)
 {
 {
-  return ((operand->exp.X_add_number & ~width) == 0
-         || (operand->exp.X_add_number | width) == (unsigned)(~0));
+  offsetT num;
+
+  num = ((operand->exp.X_add_number & 0xffffffff) ^ 0x80000000) - 0x80000000;
+  return (num & ~width) == 0 || (num | width) == ~0;
 }
 
 static int
 }
 
 static int
-constant_fits_size_p (operand, size, no_symbols)
-     struct h8_op *operand;
-     int size, no_symbols;
+constant_fits_size_p (struct h8_op *operand, int size, int no_symbols)
 {
 {
-  offsetT num = operand->exp.X_add_number;
+  offsetT num;
+
   if (no_symbols
       && (operand->exp.X_add_symbol != 0 || operand->exp.X_op_symbol != 0))
     return 0;
   if (no_symbols
       && (operand->exp.X_add_symbol != 0 || operand->exp.X_op_symbol != 0))
     return 0;
+  num = operand->exp.X_add_number & 0xffffffff;
   switch (size)
     {
     case L_2:
   switch (size)
     {
     case L_2:
@@ -580,11 +583,13 @@ constant_fits_size_p (operand, size, no_symbols)
     case L_5:
       return num >= 1 && num < 32;
     case L_8:
     case L_5:
       return num >= 1 && num < 32;
     case L_8:
-      return (num & ~0xFF) == 0 || ((unsigned)num | 0x7F) == ~0u;
+      num = (num ^ 0x80000000) - 0x80000000;
+      return (num & ~0xFF) == 0 || (num | 0x7F) == ~0;
     case L_8U:
       return (num & ~0xFF) == 0;
     case L_16:
     case L_8U:
       return (num & ~0xFF) == 0;
     case L_16:
-      return (num & ~0xFFFF) == 0 || ((unsigned)num | 0x7FFF) == ~0u;
+      num = (num ^ 0x80000000) - 0x80000000;
+      return (num & ~0xFFFF) == 0 || (num | 0x7FFF) == ~0;
     case L_16U:
       return (num & ~0xFFFF) == 0;
     case L_32:
     case L_16U:
       return (num & ~0xFFFF) == 0;
     case L_32:
@@ -595,10 +600,7 @@ constant_fits_size_p (operand, size, no_symbols)
 }
 
 static void
 }
 
 static void
-get_operand (ptr, op, direction)
-     char **ptr;
-     struct h8_op *op;
-     int direction;
+get_operand (char **ptr, struct h8_op *op, int direction)
 {
   char *src = *ptr;
   op_type mode;
 {
   char *src = *ptr;
   op_type mode;
@@ -613,7 +615,7 @@ get_operand (ptr, op, direction)
 
   /* Gross.  Gross.  ldm and stm have a format not easily handled
      by get_operand.  We deal with it explicitly here.  */
 
   /* Gross.  Gross.  ldm and stm have a format not easily handled
      by get_operand.  We deal with it explicitly here.  */
-  if (TOLOWER (src[0]) == 'e' && TOLOWER (src[1]) == 'r' && 
+  if (TOLOWER (src[0]) == 'e' && TOLOWER (src[1]) == 'r' &&
       ISDIGIT (src[2]) && src[3] == '-' &&
       TOLOWER (src[4]) == 'e' && TOLOWER (src[5]) == 'r' && ISDIGIT (src[6]))
     {
       ISDIGIT (src[2]) && src[3] == '-' &&
       TOLOWER (src[4]) == 'e' && TOLOWER (src[5]) == 'r' && ISDIGIT (src[6]))
     {
@@ -622,15 +624,18 @@ get_operand (ptr, op, direction)
       low = src[2] - '0';
       high = src[6] - '0';
 
       low = src[2] - '0';
       high = src[6] - '0';
 
-      if (high == low)
+       /* Check register pair's validity as per tech note TN-H8*-193A/E
+         from Renesas for H8S and H8SX hardware manual.  */
+      if (   !(low == 0 && (high == 1 || high == 2 || high == 3))
+          && !(low == 1 && (high == 2 || high == 3 || high == 4) && SXmode)
+          && !(low == 2 && (high == 3 || ((high == 4 || high == 5) && SXmode)))
+          && !(low == 3 && (high == 4 || high == 5 || high == 6) && SXmode)
+          && !(low == 4 && (high == 5 || high == 6))
+          && !(low == 4 && high == 7 && SXmode)
+          && !(low == 5 && (high == 6 || high == 7) && SXmode)
+          && !(low == 6 && high == 7 && SXmode))
        as_bad (_("Invalid register list for ldm/stm\n"));
 
        as_bad (_("Invalid register list for ldm/stm\n"));
 
-      if (high < low)
-       as_bad (_("Invalid register list for ldm/stm\n"));
-
-      if (high - low > 3)
-       as_bad (_("Invalid register list for ldm/stm)\n"));
-
       /* Even sicker.  We encode two registers into op->reg.  One
         for the low register to save, the other for the high
         register to save;  we also set the high bit in op->reg
       /* Even sicker.  We encode two registers into op->reg.  One
         for the low register to save, the other for the high
         register to save;  we also set the high bit in op->reg
@@ -672,7 +677,7 @@ get_operand (ptr, op, direction)
              op->mode = (op->mode & ~SIZE) | L_8;
              break;
            default:
              op->mode = (op->mode & ~SIZE) | L_8;
              break;
            default:
-             as_warn ("invalid suffix after register.");
+             as_warn (_("invalid suffix after register."));
              break;
            }
          src += 2;
              break;
            }
          src += 2;
@@ -689,7 +694,7 @@ get_operand (ptr, op, direction)
          *ptr = parse_exp (src + 1, op);
          if (op->exp.X_add_number >= 0x100)
            {
          *ptr = parse_exp (src + 1, op);
          if (op->exp.X_add_number >= 0x100)
            {
-             int divisor;
+             int divisor = 1;
 
              op->mode = VECIND;
              /* FIXME : 2?  or 4?  */
 
              op->mode = VECIND;
              /* FIXME : 2?  or 4?  */
@@ -718,7 +723,9 @@ get_operand (ptr, op, direction)
              return;
            }
 
              return;
            }
 
-         if ((mode & SIZE) != PSIZE)
+         if (((mode & SIZE) != PSIZE)
+             /* For Normal mode accept 16 bit and 32 bit pointer registers.  */
+             && (!Nmode || ((mode & SIZE) != L_32)))
            as_bad (_("Wrong size pointer register for architecture."));
 
          op->mode = src[0] == '-' ? RDPREDEC : RDPREINC;
            as_bad (_("Wrong size pointer register for architecture."));
 
          op->mode = src[0] == '-' ? RDPREDEC : RDPREINC;
@@ -751,7 +758,7 @@ get_operand (ptr, op, direction)
                }
              if (mode
                  && src[len + 2] == ','
                }
              if (mode
                  && src[len + 2] == ','
-                 && TOLOWER (src[len + 3]) != 'p' 
+                 && TOLOWER (src[len + 3]) != 'p'
                  && TOLOWER (src[len + 4]) != 'c'
                  && src[len + 5] != ')')
                {
                  && TOLOWER (src[len + 4]) != 'c'
                  && src[len + 5] != ')')
                {
@@ -813,7 +820,7 @@ get_operand (ptr, op, direction)
            op->mode |= DISP | direction;
          src = skip_colonthing (src, &op->mode);
 
            op->mode |= DISP | direction;
          src = skip_colonthing (src, &op->mode);
 
-         if (*src != ')' && '(')
+         if (*src != ')')
            {
              as_bad (_("expected @(exp, reg16)"));
              return;
            {
              as_bad (_("expected @(exp, reg16)"));
              return;
@@ -828,7 +835,9 @@ get_operand (ptr, op, direction)
          src += len;
          if (*src == '+' || *src == '-')
            {
          src += len;
          if (*src == '+' || *src == '-')
            {
-             if ((mode & SIZE) != PSIZE)
+             if (((mode & SIZE) != PSIZE)
+                 /* For Normal mode accept 16 bit and 32 bit pointer registers.  */
+                 && (!Nmode || ((mode & SIZE) != L_32)))
                as_bad (_("Wrong size pointer register for architecture."));
              op->mode = *src == '+' ? RSPOSTINC : RSPOSTDEC;
              op->reg = num;
                as_bad (_("Wrong size pointer register for architecture."));
              op->mode = *src == '+' ? RSPOSTINC : RSPOSTDEC;
              op->reg = num;
@@ -836,7 +845,9 @@ get_operand (ptr, op, direction)
              *ptr = src;
              return;
            }
              *ptr = src;
              return;
            }
-         if ((mode & SIZE) != PSIZE)
+         if (((mode & SIZE) != PSIZE)
+             /* For Normal mode accept 16 bit and 32 bit pointer registers.  */
+             && (!Nmode || ((mode & SIZE) != L_32)))
            as_bad (_("Wrong size pointer register for architecture."));
 
          op->mode = direction | IND | PSIZE;
            as_bad (_("Wrong size pointer register for architecture."));
 
          op->mode = direction | IND | PSIZE;
@@ -861,9 +872,9 @@ get_operand (ptr, op, direction)
       *ptr = parse_exp (src + 1, op);
       return;
     }
       *ptr = parse_exp (src + 1, op);
       return;
     }
-  else if (strncmp (src, "mach", 4) == 0 || 
+  else if (strncmp (src, "mach", 4) == 0 ||
           strncmp (src, "macl", 4) == 0 ||
           strncmp (src, "macl", 4) == 0 ||
-          strncmp (src, "MACH", 4) == 0 || 
+          strncmp (src, "MACH", 4) == 0 ||
           strncmp (src, "MACL", 4) == 0)
     {
       op->reg = TOLOWER (src[3]) == 'l';
           strncmp (src, "MACL", 4) == 0)
     {
       op->reg = TOLOWER (src[3]) == 'l';
@@ -879,10 +890,7 @@ get_operand (ptr, op, direction)
 }
 
 static char *
 }
 
 static char *
-get_operands (noperands, op_end, operand)
-     unsigned int noperands;
-     char *op_end;
-     struct h8_op *operand;
+get_operands (unsigned int noperands, char *op_end, struct h8_op *operand)
 {
   char *ptr = op_end;
 
 {
   char *ptr = op_end;
 
@@ -965,7 +973,7 @@ get_mova_operands (char *op_end, struct h8_op *operand)
     }
   else if ((operand[1].mode & MODE) == LOWREG)
     {
     }
   else if ((operand[1].mode & MODE) == LOWREG)
     {
-      switch (operand[1].mode & SIZE) 
+      switch (operand[1].mode & SIZE)
        {
        case L_8:
          operand[0].mode = (operand[0].mode & ~MODE) | INDEXB;
        {
        case L_8:
          operand[0].mode = (operand[0].mode & ~MODE) | INDEXB;
@@ -998,13 +1006,13 @@ get_mova_operands (char *op_end, struct h8_op *operand)
 
  error:
   as_bad (_("expected valid addressing mode for mova: \"@(disp, ea.sz),ERn\""));
 
  error:
   as_bad (_("expected valid addressing mode for mova: \"@(disp, ea.sz),ERn\""));
-  return;
 }
 
 static void
 get_rtsl_operands (char *ptr, struct h8_op *operand)
 {
 }
 
 static void
 get_rtsl_operands (char *ptr, struct h8_op *operand)
 {
-  int mode, num, num2, len, type = 0;
+  int mode, len, type = 0;
+  unsigned int num, num2;
 
   ptr++;
   if (*ptr == '(')
 
   ptr++;
   if (*ptr == '(')
@@ -1030,7 +1038,7 @@ get_rtsl_operands (char *ptr, struct h8_op *operand)
       ptr += len;
       /* CONST_xxx are used as placeholders in the opcode table.  */
       num = num2 - num;
       ptr += len;
       /* CONST_xxx are used as placeholders in the opcode table.  */
       num = num2 - num;
-      if (num < 0 || num > 3)
+      if (num > 3)
        {
          as_bad (_("invalid register list"));
          return;
        {
          as_bad (_("invalid register list"));
          return;
@@ -1054,10 +1062,8 @@ get_rtsl_operands (char *ptr, struct h8_op *operand)
    provided.  */
 
 static const struct h8_instruction *
    provided.  */
 
 static const struct h8_instruction *
-get_specific (instruction, operands, size)
-     const struct h8_instruction *instruction;
-     struct h8_op *operands;
-     int size;
+get_specific (const struct h8_instruction *instruction,
+             struct h8_op *operands, int size)
 {
   const struct h8_instruction *this_try = instruction;
   const struct h8_instruction *found_other = 0, *found_mismatched = 0;
 {
   const struct h8_instruction *this_try = instruction;
   const struct h8_instruction *found_other = 0, *found_mismatched = 0;
@@ -1181,7 +1187,7 @@ get_specific (instruction, operands, size)
                }
              else if (x_mode == IMM && op_mode != IMM)
                {
                }
              else if (x_mode == IMM && op_mode != IMM)
                {
-                 offsetT num = operands[i].exp.X_add_number;
+                 offsetT num = operands[i].exp.X_add_number & 0xffffffff;
                  if (op_mode == KBIT || op_mode == DBIT)
                    /* This is ok if the immediate value is sensible.  */;
                  else if (op_mode == CONST_2)
                  if (op_mode == KBIT || op_mode == DBIT)
                    /* This is ok if the immediate value is sensible.  */;
                  else if (op_mode == CONST_2)
@@ -1221,15 +1227,6 @@ get_specific (instruction, operands, size)
                      x |= x_size = L_32;
                    }
 
                      x |= x_size = L_32;
                    }
 
-#if 0 /* ??? */
-                 /* Promote an L8 to L_16 if it makes us match.  */
-                 if ((op_mode == ABS || op_mode == DISP) && x_size == L_8)
-                   {
-                     if (op_size == L_16)
-                       x_size = L_16;
-                   }
-#endif
-
                  if (((x_size == L_16 && op_size == L_16U)
                       || (x_size == L_8 && op_size == L_8U)
                       || (x_size == L_3 && op_size == L_3NZ))
                  if (((x_size == L_16 && op_size == L_16U)
                       || (x_size == L_8 && op_size == L_8U)
                       || (x_size == L_3 && op_size == L_3NZ))
@@ -1283,10 +1280,7 @@ get_specific (instruction, operands, size)
 }
 
 static void
 }
 
 static void
-check_operand (operand, width, string)
-     struct h8_op *operand;
-     unsigned int width;
-     char *string;
+check_operand (struct h8_op *operand, unsigned int width, const char *string)
 {
   if (operand->exp.X_add_symbol == 0
       && operand->exp.X_op_symbol == 0)
 {
   if (operand->exp.X_add_symbol == 0
       && operand->exp.X_op_symbol == 0)
@@ -1333,17 +1327,14 @@ check_operand (operand, width, string)
      (may relax into an 8bit absolute address).  */
 
 static void
      (may relax into an 8bit absolute address).  */
 
 static void
-do_a_fix_imm (offset, nibble, operand, relaxmode)
-     int offset, nibble;
-     struct h8_op *operand;
-     int relaxmode;
+do_a_fix_imm (int offset, int nibble, struct h8_op *operand, int relaxmode, const struct h8_instruction *this_try)
 {
   int idx;
   int size;
   int where;
   char *bytes = frag_now->fr_literal + offset;
 
 {
   int idx;
   int size;
   int where;
   char *bytes = frag_now->fr_literal + offset;
 
-  char *t = ((operand->mode & MODE) == IMM) ? "#" : "@";
+  const char *t = ((operand->mode & MODE) == IMM) ? "#" : "@";
 
   if (operand->exp.X_add_symbol == 0)
     {
 
   if (operand->exp.X_add_symbol == 0)
     {
@@ -1376,6 +1367,15 @@ do_a_fix_imm (offset, nibble, operand, relaxmode)
          check_operand (operand, 0xffff, t);
          bytes[0] |= operand->exp.X_add_number >> 8;
          bytes[1] |= operand->exp.X_add_number >> 0;
          check_operand (operand, 0xffff, t);
          bytes[0] |= operand->exp.X_add_number >> 8;
          bytes[1] |= operand->exp.X_add_number >> 0;
+         /* MOVA needs both relocs to relax the second operand properly.  */
+         if (relaxmode != 0
+             && (OP_KIND(this_try->opcode->how) == O_MOVAB
+                 || OP_KIND(this_try->opcode->how) == O_MOVAW
+                 || OP_KIND(this_try->opcode->how) == O_MOVAL))
+           {
+             idx = BFD_RELOC_16;
+             fix_new_exp (frag_now, offset, 2, &operand->exp, 0, idx);
+           }
          break;
        case L_24:
          check_operand (operand, 0xffffff, t);
          break;
        case L_24:
          check_operand (operand, 0xffffff, t);
@@ -1392,7 +1392,10 @@ do_a_fix_imm (offset, nibble, operand, relaxmode)
          bytes[3] |= operand->exp.X_add_number >> 0;
          if (relaxmode != 0)
            {
          bytes[3] |= operand->exp.X_add_number >> 0;
          if (relaxmode != 0)
            {
-             idx = (relaxmode == 2) ? R_MOV24B1 : R_MOVL1;
+             if ((operand->mode & MODE) == DISP && relaxmode == 1)
+               idx = BFD_RELOC_H8_DISP32A16;
+             else
+               idx = (relaxmode == 2) ? R_MOV24B1 : R_MOVL1;
              fix_new_exp (frag_now, offset, 4, &operand->exp, 0, idx);
            }
          break;
              fix_new_exp (frag_now, offset, 4, &operand->exp, 0, idx);
            }
          break;
@@ -1406,7 +1409,9 @@ do_a_fix_imm (offset, nibble, operand, relaxmode)
        case L_32:
          size = 4;
          where = (operand->mode & SIZE) == L_24 ? -1 : 0;
        case L_32:
          size = 4;
          where = (operand->mode & SIZE) == L_24 ? -1 : 0;
-         if (relaxmode == 2)
+         if ((operand->mode & MODE) == DISP && relaxmode == 1)
+           idx = BFD_RELOC_H8_DISP32A16;
+         else if (relaxmode == 2)
            idx = R_MOV24B1;
          else if (relaxmode == 1)
            idx = R_MOVL1;
            idx = R_MOV24B1;
          else if (relaxmode == 1)
            idx = R_MOVL1;
@@ -1415,6 +1420,7 @@ do_a_fix_imm (offset, nibble, operand, relaxmode)
          break;
        default:
          as_bad (_("Can't work out size of operand.\n"));
          break;
        default:
          as_bad (_("Can't work out size of operand.\n"));
+         /* Fall through.  */
        case L_16:
        case L_16U:
          size = 2;
        case L_16:
        case L_16U:
          size = 2;
@@ -1448,13 +1454,11 @@ do_a_fix_imm (offset, nibble, operand, relaxmode)
 /* Now we know what sort of opcodes it is, let's build the bytes.  */
 
 static void
 /* Now we know what sort of opcodes it is, let's build the bytes.  */
 
 static void
-build_bytes (this_try, operand)
-     const struct h8_instruction *this_try;
-     struct h8_op *operand;
+build_bytes (const struct h8_instruction *this_try, struct h8_op *operand)
 {
   int i;
   char *output = frag_more (this_try->length);
 {
   int i;
   char *output = frag_more (this_try->length);
-  op_type *nibble_ptr = this_try->opcode->data.nib;
+  const op_type *nibble_ptr = this_try->opcode->data.nib;
   op_type c;
   unsigned int nibble_count = 0;
   int op_at[3];
   op_type c;
   unsigned int nibble_count = 0;
   int op_at[3];
@@ -1467,12 +1471,12 @@ build_bytes (this_try, operand)
   if (!Hmode && this_try->opcode->available != AV_H8)
     as_warn (_("Opcode `%s' with these operand types not available in H8/300 mode"),
             this_try->opcode->name);
   if (!Hmode && this_try->opcode->available != AV_H8)
     as_warn (_("Opcode `%s' with these operand types not available in H8/300 mode"),
             this_try->opcode->name);
-  else if (!Smode 
-          && this_try->opcode->available != AV_H8 
+  else if (!Smode
+          && this_try->opcode->available != AV_H8
           && this_try->opcode->available != AV_H8H)
     as_warn (_("Opcode `%s' with these operand types not available in H8/300H mode"),
             this_try->opcode->name);
           && this_try->opcode->available != AV_H8H)
     as_warn (_("Opcode `%s' with these operand types not available in H8/300H mode"),
             this_try->opcode->name);
-  else if (!SXmode 
+  else if (!SXmode
           && this_try->opcode->available != AV_H8
           && this_try->opcode->available != AV_H8H
           && this_try->opcode->available != AV_H8S)
           && this_try->opcode->available != AV_H8
           && this_try->opcode->available != AV_H8H
           && this_try->opcode->available != AV_H8S)
@@ -1614,9 +1618,23 @@ build_bytes (this_try, operand)
   for (i = 0; i < this_try->length; i++)
     output[i] = (asnibbles[i * 2] << 4) | asnibbles[i * 2 + 1];
 
   for (i = 0; i < this_try->length; i++)
     output[i] = (asnibbles[i * 2] << 4) | asnibbles[i * 2 + 1];
 
-  /* Note if this is a movb instruction -- there's a special relaxation
-     which only applies to them.  */
-  if (this_try->opcode->how == O (O_MOV, SB))
+  /* Note if this is a mov.b or a bit manipulation instruction
+     there is a special relaxation which only applies.  */
+  if (   this_try->opcode->how == O (O_MOV,   SB)
+      || this_try->opcode->how == O (O_BCLR,  SB)
+      || this_try->opcode->how == O (O_BAND,  SB)
+      || this_try->opcode->how == O (O_BIAND, SB)
+      || this_try->opcode->how == O (O_BILD,  SB)
+      || this_try->opcode->how == O (O_BIOR,  SB)
+      || this_try->opcode->how == O (O_BIST,  SB)
+      || this_try->opcode->how == O (O_BIXOR, SB)
+      || this_try->opcode->how == O (O_BLD,   SB)
+      || this_try->opcode->how == O (O_BNOT,  SB)
+      || this_try->opcode->how == O (O_BOR,   SB)
+      || this_try->opcode->how == O (O_BSET,  SB)
+      || this_try->opcode->how == O (O_BST,   SB)
+      || this_try->opcode->how == O (O_BTST,  SB)
+      || this_try->opcode->how == O (O_BXOR,  SB))
     movb = 1;
 
   /* Output any fixes.  */
     movb = 1;
 
   /* Output any fixes.  */
@@ -1627,12 +1645,13 @@ build_bytes (this_try, operand)
 
       if (x_mode == IMM || x_mode == DISP)
        do_a_fix_imm (output - frag_now->fr_literal + op_at[i] / 2,
 
       if (x_mode == IMM || x_mode == DISP)
        do_a_fix_imm (output - frag_now->fr_literal + op_at[i] / 2,
-                     op_at[i] & 1, operand + i, (x & MEMRELAX) != 0);
-
+                     op_at[i] & 1, operand + i, (x & MEMRELAX) != 0,
+                     this_try);
       else if (x_mode == ABS)
        do_a_fix_imm (output - frag_now->fr_literal + op_at[i] / 2,
                      op_at[i] & 1, operand + i,
       else if (x_mode == ABS)
        do_a_fix_imm (output - frag_now->fr_literal + op_at[i] / 2,
                      op_at[i] & 1, operand + i,
-                     (x & MEMRELAX) ? movb + 1 : 0);
+                     (x & MEMRELAX) ? movb + 1 : 0,
+                     this_try);
 
       else if (x_mode == PCREL)
        {
 
       else if (x_mode == PCREL)
        {
@@ -1646,14 +1665,6 @@ build_bytes (this_try, operand)
          if (operand[i].exp.X_add_number & 1)
            as_warn (_("branch operand has odd offset (%lx)\n"),
                     (unsigned long) operand->exp.X_add_number);
          if (operand[i].exp.X_add_number & 1)
            as_warn (_("branch operand has odd offset (%lx)\n"),
                     (unsigned long) operand->exp.X_add_number);
-#ifndef OBJ_ELF
-         /* The COFF port has always been off by one, changing it
-            now would be an incompatible change, so we leave it as-is.
-
-            We don't want to do this for ELF as we want to be
-            compatible with the proposed ELF format from Hitachi.  */
-         operand[i].exp.X_add_number -= 1;
-#endif
          if (size16)
            {
              operand[i].exp.X_add_number =
          if (size16)
            {
              operand[i].exp.X_add_number =
@@ -1705,11 +1716,10 @@ build_bytes (this_try, operand)
          int where = 0;
          bfd_reloc_code_real_type reloc_type = R_JMPL1;
 
          int where = 0;
          bfd_reloc_code_real_type reloc_type = R_JMPL1;
 
-#ifdef OBJ_ELF
          /* To be compatible with the proposed H8 ELF format, we
             want the relocation's offset to point to the first byte
             that will be modified, not to the start of the instruction.  */
          /* To be compatible with the proposed H8 ELF format, we
             want the relocation's offset to point to the first byte
             that will be modified, not to the start of the instruction.  */
-         
+
          if ((operand->mode & SIZE) == L_32)
            {
              where = 2;
          if ((operand->mode & SIZE) == L_32)
            {
              where = 2;
@@ -1717,12 +1727,11 @@ build_bytes (this_try, operand)
            }
          else
            where = 1;
            }
          else
            where = 1;
-#endif
 
          /* This jmp may be a jump or a branch.  */
 
 
          /* This jmp may be a jump or a branch.  */
 
-         check_operand (operand + i, 
-                        SXmode ? 0xffffffff : Hmode ? 0xffffff : 0xffff, 
+         check_operand (operand + i,
+                        SXmode ? 0xffffffff : Hmode ? 0xffffff : 0xffff,
                         "@");
 
          if (operand[i].exp.X_add_number & 1)
                         "@");
 
          if (operand[i].exp.X_add_number & 1)
@@ -1746,9 +1755,8 @@ build_bytes (this_try, operand)
    detect errors.  */
 
 static void
    detect errors.  */
 
 static void
-clever_message (instruction, operand)
-     const struct h8_instruction *instruction;
-     struct h8_op *operand;
+clever_message (const struct h8_instruction *instruction,
+               struct h8_op *operand)
 {
   /* Find out if there was more than one possible opcode.  */
 
 {
   /* Find out if there was more than one possible opcode.  */
 
@@ -1817,9 +1825,7 @@ clever_message (instruction, operand)
    displacement in an @(d:2,ERn) operand.  */
 
 static void
    displacement in an @(d:2,ERn) operand.  */
 
 static void
-fix_operand_size (operand, size)
-     struct h8_op *operand;
-     int size;
+fix_operand_size (struct h8_op *operand, int size)
 {
   if (SXmode && (operand->mode & MODE) == DISP)
     {
 {
   if (SXmode && (operand->mode & MODE) == DISP)
     {
@@ -1855,8 +1861,9 @@ fix_operand_size (operand, size)
           is safe.  get_specific() will relax L_24 into L_32 where
           necessary.  */
        if (Hmode
           is safe.  get_specific() will relax L_24 into L_32 where
           necessary.  */
        if (Hmode
-           && (operand->exp.X_add_number < -32768
-               || operand->exp.X_add_number > 32767
+           && !Nmode
+           && ((((addressT) operand->exp.X_add_number + 0x8000)
+                & 0xffffffff) > 0xffff
                || operand->exp.X_add_symbol != 0
                || operand->exp.X_op_symbol != 0))
          operand->mode |= L_24;
                || operand->exp.X_add_symbol != 0
                || operand->exp.X_op_symbol != 0))
          operand->mode |= L_24;
@@ -1865,10 +1872,14 @@ fix_operand_size (operand, size)
        break;
 
       case PCREL:
        break;
 
       case PCREL:
-       /* This condition is long standing, though somewhat suspect.  */
-       if (operand->exp.X_add_number > -128
-           && operand->exp.X_add_number < 127)
-         operand->mode |= L_8;
+       if ((((addressT) operand->exp.X_add_number + 0x80)
+            & 0xffffffff) <= 0xff)
+         {
+           if (operand->exp.X_add_symbol != NULL)
+             operand->mode |= bsize;
+           else
+             operand->mode |= L_8;
+         }
        else
          operand->mode |= L_16;
        break;
        else
          operand->mode |= L_16;
        break;
@@ -1881,8 +1892,7 @@ fix_operand_size (operand, size)
    the frags/bytes it assembles.  */
 
 void
    the frags/bytes it assembles.  */
 
 void
-md_assemble (str)
-     char *str;
+md_assemble (char *str)
 {
   char *op_start;
   char *op_end;
 {
   char *op_start;
   char *op_end;
@@ -1958,6 +1968,27 @@ md_assemble (str)
   *op_end = c;
   prev_instruction = instruction;
 
   *op_end = c;
   prev_instruction = instruction;
 
+  /* Now we have operands from instruction.
+     Let's check them out for ldm and stm.  */
+  if (OP_KIND (instruction->opcode->how) == O_LDM)
+    {
+      /* The first operand must be @er7+, and the
+        second operand must be a register pair.  */
+      if ((operand[0].mode != RSINC)
+           || (operand[0].reg != 7)
+           || ((operand[1].reg & 0x80000000) == 0))
+       as_bad (_("invalid operand in ldm"));
+    }
+  else if (OP_KIND (instruction->opcode->how) == O_STM)
+    {
+      /* The first operand must be a register pair,
+        and the second operand must be @-er7.  */
+      if (((operand[0].reg & 0x80000000) == 0)
+            || (operand[1].mode != RDDEC)
+            || (operand[1].reg != 7))
+       as_bad (_("invalid operand in stm"));
+    }
+
   size = SN;
   if (dot)
     {
   size = SN;
   if (dot)
     {
@@ -2029,169 +2060,177 @@ md_assemble (str)
 
   build_bytes (instruction, operand);
 
 
   build_bytes (instruction, operand);
 
-#ifdef BFD_ASSEMBLER
   dwarf2_emit_insn (instruction->length);
   dwarf2_emit_insn (instruction->length);
-#endif
-}
-
-#ifndef BFD_ASSEMBLER
-void
-tc_crawl_symbol_chain (headers)
-     object_headers *headers ATTRIBUTE_UNUSED;
-{
-  printf (_("call to tc_crawl_symbol_chain \n"));
 }
 }
-#endif
 
 symbolS *
 
 symbolS *
-md_undefined_symbol (name)
-     char *name ATTRIBUTE_UNUSED;
+md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
 {
   return 0;
 }
 
 {
   return 0;
 }
 
-#ifndef BFD_ASSEMBLER
-void
-tc_headers_hook (headers)
-     object_headers *headers ATTRIBUTE_UNUSED;
+/* Various routines to kill one day.  */
+
+const char *
+md_atof (int type, char *litP, int *sizeP)
 {
 {
-  printf (_("call to tc_headers_hook \n"));
+  return ieee_md_atof (type, litP, sizeP, TRUE);
 }
 }
-#endif
+\f
+#define OPTION_H_TICK_HEX      (OPTION_MD_BASE)
+#define OPTION_MACH            (OPTION_MD_BASE+1)
 
 
-/* Various routines to kill one day */
-/* Equal to MAX_PRECISION in atof-ieee.c */
-#define MAX_LITTLENUMS 6
+const char *md_shortopts = "";
+struct option md_longopts[] =
+{
+  { "h-tick-hex", no_argument,       NULL, OPTION_H_TICK_HEX  },
+  { "mach", required_argument, NULL, OPTION_MACH },
+  {NULL, no_argument, NULL, 0}
+};
 
 
-/* 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.  */
+size_t md_longopts_size = sizeof (md_longopts);
 
 
-char *
-md_atof (type, litP, sizeP)
-     char type;
-     char *litP;
-     int *sizeP;
+struct mach_func
 {
 {
-  int prec;
-  LITTLENUM_TYPE words[MAX_LITTLENUMS];
-  LITTLENUM_TYPE *wordP;
-  char *t;
+  const char *name;
+  void (*func) (void);
+};
 
 
-  switch (type)
-    {
-    case 'f':
-    case 'F':
-    case 's':
-    case 'S':
-      prec = 2;
-      break;
+static void
+mach_h8300h (void)
+{
+  Hmode = 1;
+  Smode = 0;
+  Nmode = 0;
+  SXmode = 0;
+  default_mach = bfd_mach_h8300h;
+}
 
 
-    case 'd':
-    case 'D':
-    case 'r':
-    case 'R':
-      prec = 4;
-      break;
+static void
+mach_h8300hn (void)
+{
+  Hmode = 1;
+  Smode = 0;
+  Nmode = 1;
+  SXmode = 0;
+  default_mach = bfd_mach_h8300hn;
+}
 
 
-    case 'x':
-    case 'X':
-      prec = 6;
-      break;
+static void
+mach_h8300s (void)
+{
+  Hmode = 1;
+  Smode = 1;
+  Nmode = 0;
+  SXmode = 0;
+  default_mach = bfd_mach_h8300s;
+}
 
 
-    case 'p':
-    case 'P':
-      prec = 6;
-      break;
+static void
+mach_h8300sn (void)
+{
+  Hmode = 1;
+  Smode = 1;
+  Nmode = 1;
+  SXmode = 0;
+  default_mach = bfd_mach_h8300sn;
+}
 
 
-    default:
-      *sizeP = 0;
-      return _("Bad call to MD_ATOF()");
-    }
-  t = atof_ieee (input_line_pointer, type, words);
-  if (t)
-    input_line_pointer = t;
+static void
+mach_h8300sx (void)
+{
+  Hmode = 1;
+  Smode = 1;
+  Nmode = 0;
+  SXmode = 1;
+  default_mach = bfd_mach_h8300sx;
+}
 
 
-  *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;
+static void
+mach_h8300sxn (void)
+{
+  Hmode = 1;
+  Smode = 1;
+  Nmode = 1;
+  SXmode = 1;
+  default_mach = bfd_mach_h8300sxn;
 }
 }
-\f
-const char *md_shortopts = "";
-struct option md_longopts[] = {
-  {NULL, no_argument, NULL, 0}
-};
 
 
-size_t md_longopts_size = sizeof (md_longopts);
+const struct mach_func mach_table[] =
+{
+  {"h8300h",  mach_h8300h},
+  {"h8300hn", mach_h8300hn},
+  {"h8300s",  mach_h8300s},
+  {"h8300sn", mach_h8300sn},
+  {"h8300sx", mach_h8300sx},
+  {"h8300sxn", mach_h8300sxn}
+};
 
 int
 
 int
-md_parse_option (c, arg)
-     int c ATTRIBUTE_UNUSED;
-     char *arg ATTRIBUTE_UNUSED;
+md_parse_option (int c ATTRIBUTE_UNUSED, const char *arg ATTRIBUTE_UNUSED)
 {
 {
-  return 0;
+  unsigned int i;
+  switch (c)
+    {
+    case OPTION_H_TICK_HEX:
+      enable_h_tick_hex = 1;
+      break;
+    case OPTION_MACH:
+      for (i = 0; i < sizeof(mach_table) / sizeof(struct mach_func); i++)
+       {
+         if (strcasecmp (arg, mach_table[i].name) == 0)
+           {
+             mach_table[i].func();
+             break;
+           }
+       }
+      if (i >= sizeof(mach_table) / sizeof(struct mach_func))
+       as_bad (_("Invalid argument to --mach option: %s"), arg);
+      break;
+    default:
+      return 0;
+    }
+  return 1;
 }
 
 void
 }
 
 void
-md_show_usage (stream)
-     FILE *stream ATTRIBUTE_UNUSED;
+md_show_usage (FILE *stream)
 {
 {
+  fprintf (stream, _(" H8300-specific assembler options:\n"));
+  fprintf (stream, _("\
+  -mach=<name>             Set the H8300 machine type to one of:\n\
+                           h8300h, h8300hn, h8300s, h8300sn, h8300sx, h8300sxn\n"));
+  fprintf (stream, _("\
+  -h-tick-hex              Support H'00 style hex constants\n"));
 }
 \f
 }
 \f
-void tc_aout_fix_to_chars PARAMS ((void));
+void tc_aout_fix_to_chars (void);
 
 void
 
 void
-tc_aout_fix_to_chars ()
+tc_aout_fix_to_chars (void)
 {
   printf (_("call to tc_aout_fix_to_chars \n"));
   abort ();
 }
 
 void
 {
   printf (_("call to tc_aout_fix_to_chars \n"));
   abort ();
 }
 
 void
-md_convert_frag (headers, seg, fragP)
-#ifdef BFD_ASSEMBLER
-     bfd *headers ATTRIBUTE_UNUSED;
-#else
-     object_headers *headers ATTRIBUTE_UNUSED;
-#endif
-     segT seg ATTRIBUTE_UNUSED;
-     fragS *fragP ATTRIBUTE_UNUSED;
+md_convert_frag (bfd *headers ATTRIBUTE_UNUSED,
+                segT seg ATTRIBUTE_UNUSED,
+                fragS *fragP ATTRIBUTE_UNUSED)
 {
   printf (_("call to md_convert_frag \n"));
   abort ();
 }
 
 {
   printf (_("call to md_convert_frag \n"));
   abort ();
 }
 
-#ifdef BFD_ASSEMBLER
 valueT
 valueT
-md_section_align (segment, size)
-     segT segment;
-     valueT size;
+md_section_align (segT segment, valueT size)
 {
 {
-  int align = bfd_get_section_alignment (stdoutput, segment);
-  return ((size + (1 << align) - 1) & (-1 << align));
+  int align = bfd_section_alignment (segment);
+  return ((size + (1 << align) - 1) & (-1U << align));
 }
 }
-#else
-valueT
-md_section_align (seg, size)
-     segT seg;
-     valueT size;
-{
-  return ((size + (1 << section_alignment[(int) seg]) - 1)
-         & (-1 << section_alignment[(int) seg]));
-}
-#endif
-
 
 void
 
 void
-md_apply_fix3 (fixP, valP, seg)
-     fixS *fixP;
-     valueT *valP;
-     segT seg ATTRIBUTE_UNUSED;
+md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
 {
   char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
   long val = *valP;
 {
   char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
   long val = *valP;
@@ -2211,6 +2250,13 @@ md_apply_fix3 (fixP, valP, seg)
       *buf++ = (val >> 8);
       *buf++ = val;
       break;
       *buf++ = (val >> 8);
       *buf++ = val;
       break;
+    case 8:
+      /* This can arise when the .quad or .8byte pseudo-ops are used.
+        Returning here (without setting fx_done) will cause the code
+        to attempt to generate a reloc which will then fail with the
+        slightly more helpful error message: "Cannot represent
+        relocation type BFD_RELOC_64".  */
+      return;
     default:
       abort ();
     }
     default:
       abort ();
     }
@@ -2220,99 +2266,30 @@ md_apply_fix3 (fixP, valP, seg)
 }
 
 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);
 }
 
 long
 {
   number_to_chars_bigendian (ptr, use, nbytes);
 }
 
 long
-md_pcrel_from (fixP)
-     fixS *fixP ATTRIBUTE_UNUSED;
+md_pcrel_from (fixS *fixp)
 {
 {
-  abort ();
+  as_bad_where (fixp->fx_file, fixp->fx_line,
+               _("Unexpected reference to a symbol in a non-code section"));
+  return 0;
 }
 
 }
 
-#ifndef BFD_ASSEMBLER
-void
-tc_reloc_mangle (fix_ptr, intr, base)
-     fixS *fix_ptr;
-     struct internal_reloc *intr;
-     bfd_vma base;
-
-{
-  symbolS *symbol_ptr;
-
-  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 == TC_CONS_RELOC)
-    {
-      /* cons likes to create reloc32's whatever the size of the reloc..
-       */
-      switch (fix_ptr->fx_size)
-       {
-       case 4:
-         intr->r_type = R_RELLONG;
-         break;
-       case 2:
-         intr->r_type = R_RELWORD;
-         break;
-       case 1:
-         intr->r_type = R_RELBYTE;
-         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)
-    {
-      if (symbol_ptr->sy_number != -1)
-       intr->r_symndx = symbol_ptr->sy_number;
-      else
-       {
-         symbolS *segsym;
-
-         /* This case arises when a reference is made to `.'.  */
-         segsym = seg_info (S_GET_SEGMENT (symbol_ptr))->dot;
-         if (segsym == NULL)
-           intr->r_symndx = -1;
-         else
-           {
-             intr->r_symndx = segsym->sy_number;
-             intr->r_offset += S_GET_VALUE (symbol_ptr);
-           }
-       }
-    }
-  else
-    intr->r_symndx = -1;
-}
-#else /* BFD_ASSEMBLER */
 arelent *
 arelent *
-tc_gen_reloc (section, fixp)
-     asection *section ATTRIBUTE_UNUSED;
-     fixS *fixp;
+tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
 {
   arelent *rel;
   bfd_reloc_code_real_type r_type;
 {
   arelent *rel;
   bfd_reloc_code_real_type r_type;
@@ -2323,13 +2300,13 @@ tc_gen_reloc (section, fixp)
          || S_GET_SEGMENT (fixp->fx_addsy) == undefined_section)
        {
          as_bad_where (fixp->fx_file, fixp->fx_line,
          || S_GET_SEGMENT (fixp->fx_addsy) == undefined_section)
        {
          as_bad_where (fixp->fx_file, fixp->fx_line,
-                       "Difference of symbols in different sections is not supported");
+                       _("Difference of symbols in different sections is not supported"));
          return NULL;
        }
     }
 
          return NULL;
        }
     }
 
-  rel = (arelent *) xmalloc (sizeof (arelent));
-  rel->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
+  rel = XNEW (arelent);
+  rel->sym_ptr_ptr = XNEW (asymbol *);
   *rel->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
   rel->address = fixp->fx_frag->fr_address + fixp->fx_where;
   rel->addend = fixp->fx_offset;
   *rel->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
   rel->address = fixp->fx_frag->fr_address + fixp->fx_where;
   rel->addend = fixp->fx_offset;
@@ -2339,7 +2316,7 @@ tc_gen_reloc (section, fixp)
 #define DEBUG 0
 #if DEBUG
   fprintf (stderr, "%s\n", bfd_get_reloc_code_name (r_type));
 #define DEBUG 0
 #if DEBUG
   fprintf (stderr, "%s\n", bfd_get_reloc_code_name (r_type));
-  fflush(stderr);
+  fflush (stderr);
 #endif
   rel->howto = bfd_reloc_type_lookup (stdoutput, r_type);
   if (rel->howto == NULL)
 #endif
   rel->howto = bfd_reloc_type_lookup (stdoutput, r_type);
   if (rel->howto == NULL)
@@ -2352,4 +2329,3 @@ tc_gen_reloc (section, fixp)
 
   return rel;
 }
 
   return rel;
 }
-#endif
This page took 0.040007 seconds and 4 git commands to generate.