]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - gas/config/tc-tic54x.c
Update year range in copyright notice of binutils files
[thirdparty/binutils-gdb.git] / gas / config / tc-tic54x.c
index f549d48cffa88335ab4e8704c1ccea6161e4dfd5..5a6bc8aa7dc67b1b02afe0f400223dc97088d794 100644 (file)
@@ -1,12 +1,12 @@
 /* tc-tic54x.c -- Assembly code for the Texas Instruments TMS320C54X
-   Copyright (C) 1999, 2000 Free Software Foundation.
+   Copyright (C) 1999-2021 Free Software Foundation, Inc.
    Contributed by Timothy Wall (twall@cygnus.com)
 
    This file is part of GAS, the GNU Assembler.
 
    GAS is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
+   the Free Software Foundation; either version 3, or (at your option)
    any later version.
 
    GAS is distributed in the hope that it will be useful,
@@ -16,8 +16,8 @@
 
    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.  */
 
 /* Texas Instruments TMS320C54X machine specific gas.
    Written by Timothy Wall (twall@alum.mit.edu).
    We don't convert '' to '\0'
    We don't allow strings with .byte/.half/.short/.long
    Probably details of the subsym stuff are different
-   TI sets labels to be data type 4 (T_INT); GAS uses T_NULL.  */
+   TI sets labels to be data type 4 (T_INT); GAS uses T_NULL.
+
+   COFF1 limits section names to 8 characters.
+   Some of the default behavior changed from COFF1 to COFF2.  */
 
-#include <stdlib.h>
-#include <limits.h>
-#include <errno.h>
 #include "as.h"
+#include <limits.h>
+#include "safe-ctype.h"
 #include "sb.h"
 #include "macro.h"
 #include "subsegs.h"
-#include "struc-symbol.h"
 #include "opcode/tic54x.h"
 #include "obj-coff.h"
 #include <math.h>
 
-#define MAX_LINE 256 /* Lines longer than this are truncated by TI's asm.  */
 
-const char comment_chars[] = ";";
-const char line_comment_chars[] = ";*#"; /* At column zero only.  */
-const char line_separator_chars[] = ""; /* Not permitted.  */
+static struct stag
+{
+  symbolS *sym;                        /* Symbol for this stag; value is offset.  */
+  const char *name;            /* Shortcut to symbol name.  */
+  bfd_vma size;                        /* Size of struct/union.  */
+  int current_bitfield_offset;  /* Temporary for tracking fields.  */
+  int is_union;
+  struct stag_field            /* List of fields.  */
+  {
+    const char *name;
+    bfd_vma offset;            /* Of start of this field.  */
+    int bitfield_offset;       /* Of start of this field.  */
+    struct stag *stag;         /* If field is struct/union.  */
+    struct stag_field *next;
+  } *field;
+  /* For nesting; used only in stag construction.  */
+  struct stag *inner;          /* Enclosed .struct.  */
+  struct stag *outer;          /* Enclosing .struct.  */
+} *current_stag = NULL;
 
-/* Characters which indicate that this is a floating point constant.  */
-const char FLT_CHARS[] = "fF";
+#define MAX_LINE 256 /* Lines longer than this are truncated by TI's asm.  */
 
-/* Characters that can be used to separate mantissa from exp in FP
-   nums.  */
-const char EXP_CHARS[] = "eE";
+typedef struct _tic54x_insn
+{
+  const insn_template *tm;     /* Opcode template.  */
 
-/* Only word (et al.), align, or conditionals are allowed within
-   .struct/.union.  */
-#define ILLEGAL_WITHIN_STRUCT()                                        \
-  do                                                           \
-    if (current_stag != NULL)                                  \
-      {                                                        \
-       as_bad (_("pseudo-op illegal within .struct/.union"));  \
-       return;                                                 \
-      }                                                                \
-  while (0)
+  char mnemonic[MAX_LINE];     /* Opcode name/mnemonic.  */
+  char parmnemonic[MAX_LINE];   /* 2nd mnemonic of parallel insn.  */
 
-void
-md_show_usage (stream)
-     FILE *stream;
-{
-  fprintf (stream, _("C54x-specific command line  options:\n"));
-  fprintf (stream, _("-mfar-mode | -mf          Use extended addressing\n"));
-  fprintf (stream, _("-mcpu=<CPU version>       Specify the CPU version\n"));
-#if 0
-  fprintf (stream, _("-mcoff-version={0|1|2}    Select COFF version\n"));
-#endif
-  fprintf (stream, _("-merrors-to-file <filename>\n"));
-  fprintf (stream, _("-me <filename>            Redirect errors to a file\n"));
-}
+  int opcount;
+  struct opstruct
+  {
+    char buf[MAX_LINE];
+    enum optype type;
+    expressionS exp;
+  } operands[MAX_OPERANDS];
 
-const char *md_shortopts = "";
+  int paropcount;
+  struct opstruct paroperands[MAX_OPERANDS];
+
+  int is_lkaddr;
+  int lkoperand;
+  int words;                   /* Size of insn in 16-bit words.  */
+  int using_default_dst;       /* Do we need to explicitly set an
+                                  omitted OP_DST operand?  */
+  struct
+  {
+    unsigned short word;            /* Final encoded opcode data.  */
+    int unresolved;
+    int r_nchars;                   /* Relocation size.  */
+    bfd_reloc_code_real_type r_type; /* Relocation type.  */
+    expressionS addr_expr;          /* Storage for unresolved expressions.  */
+  } opcode[3];
+} tic54x_insn;
 
 enum cpu_version
 {
@@ -105,6 +122,24 @@ enum address_mode
   far_mode  /* >16-bit addresses.  */
 };
 
+static segT stag_saved_seg;
+static subsegT stag_saved_subseg;
+
+const char comment_chars[] = ";";
+const char line_comment_chars[] = ";*#"; /* At column zero only.  */
+const char line_separator_chars[] = ""; /* Not permitted.  */
+
+int emitting_long = 0;
+
+/* Characters which indicate that this is a floating point constant.  */
+const char FLT_CHARS[] = "fF";
+
+/* Characters that can be used to separate mantissa from exp in FP
+   nums.  */
+const char EXP_CHARS[] = "eE";
+
+const char *md_shortopts = "";
+
 #define OPTION_ADDRESS_MODE     (OPTION_MD_BASE)
 #define OPTION_CPU_VERSION      (OPTION_ADDRESS_MODE + 1)
 #define OPTION_COFF_VERSION     (OPTION_CPU_VERSION + 1)
@@ -112,15 +147,12 @@ enum address_mode
 
 struct option md_longopts[] =
 {
-  { "mfar-mode",       no_argument,     NULL, OPTION_ADDRESS_MODE },
-  { "mf",            no_argument,       NULL, OPTION_ADDRESS_MODE },
-  { "mcpu",        required_argument,   NULL, OPTION_CPU_VERSION },
-#if 0
-  { "mcoff-version",   required_argument,   NULL, OPTION_COFF_VERSION },
-#endif
+  { "mfar-mode",       no_argument,        NULL, OPTION_ADDRESS_MODE },
+  { "mf",             no_argument,         NULL, OPTION_ADDRESS_MODE },
+  { "mcpu",           required_argument,   NULL, OPTION_CPU_VERSION },
   { "merrors-to-file", required_argument,   NULL, OPTION_STDERR_TO_FILE },
-  { "me",            required_argument,   NULL, OPTION_STDERR_TO_FILE },
-  { NULL, no_argument, NULL, 0},
+  { "me",             required_argument,   NULL, OPTION_STDERR_TO_FILE },
+  { NULL,              no_argument,         NULL, 0},
 };
 
 size_t md_longopts_size = sizeof (md_longopts);
@@ -128,7 +160,7 @@ size_t md_longopts_size = sizeof (md_longopts);
 static int assembly_begun = 0;
 /* Addressing mode is not entirely implemented; the latest rev of the Other
    assembler doesn't seem to make any distinction whatsoever; all relocations
-   are stored as extended relocatiosn.  Older versions used REL16 vs RELEXT16,
+   are stored as extended relocations.  Older versions used REL16 vs RELEXT16,
    but now it seems all relocations are RELEXT16.  We use all RELEXT16.
 
    The cpu version is kind of a waste of time as well.  There is one
@@ -149,11 +181,12 @@ static symbolS *last_label_seen = NULL;
 /* This ensures that all new labels are unique.  */
 static int local_label_id;
 
-static struct hash_control *subsym_recurse_hash; /* Prevent infinite recurse.  */
-static struct hash_control *math_hash; /* Built-in math functions.  */
+static htab_t subsym_recurse_hash; /* Prevent infinite recurse.  */
+static htab_t math_hash; /* Built-in math functions.  */
 /* Allow maximum levels of macro nesting; level 0 is the main substitution
    symbol table.  The other assembler only does 32 levels, so there!  */
-static struct hash_control *subsym_hash[100];
+#define MAX_SUBSYM_HASH 100
+static htab_t subsym_hash[MAX_SUBSYM_HASH];
 
 /* Keep track of local labels so we can substitute them before GAS sees them
    since macros use their own 'namespace' for local labels, use a separate hash
@@ -164,92 +197,62 @@ static struct hash_control *subsym_hash[100];
    We use our own macro nesting counter, since GAS overloads it when expanding
    other things (like conditionals and repeat loops).  */
 static int macro_level = 0;
-static struct hash_control *local_label_hash[100];
+static htab_t local_label_hash[100];
 /* Keep track of struct/union tags.  */
-static struct hash_control *stag_hash;
-static struct hash_control *op_hash;
-static struct hash_control *parop_hash;
-static struct hash_control *reg_hash;
-static struct hash_control *mmreg_hash;
-static struct hash_control *cc_hash;
-static struct hash_control *cc2_hash;
-static struct hash_control *cc3_hash;
-static struct hash_control *sbit_hash;
-static struct hash_control *misc_symbol_hash;
-
-static char *subsym_substitute PARAMS ((char *line, int forced));
-static char *subsym_lookup PARAMS ((char *name, int nest_level));
-static void subsym_create_or_replace PARAMS ((char *name, char *value));
-static float math_ceil PARAMS ((float, float));
-static float math_cvi PARAMS ((float, float));
-static float math_floor PARAMS ((float, float));
-static float math_fmod PARAMS ((float, float));
-static float math_int PARAMS ((float, float));
-static float math_round PARAMS ((float, float));
-static float math_sgn PARAMS ((float, float));
-static float math_trunc PARAMS ((float, float));
-static float math_acos PARAMS ((float, float));
-static float math_asin PARAMS ((float, float));
-static float math_atan PARAMS ((float, float));
-static float math_atan2 PARAMS ((float, float));
-static float math_cosh PARAMS ((float, float));
-static float math_cos PARAMS ((float, float));
-static float math_cvf PARAMS ((float, float));
-static float math_exp PARAMS ((float, float));
-static float math_fabs PARAMS ((float, float));
-static float math_ldexp PARAMS ((float, float));
-static float math_log10 PARAMS ((float, float));
-static float math_log PARAMS ((float, float));
-static float math_max PARAMS ((float, float));
-static float math_pow PARAMS ((float, float));
-static float math_sin PARAMS ((float, float));
-static float math_sinh PARAMS ((float, float));
-static float math_sqrt PARAMS ((float, float));
-static float math_tan PARAMS ((float, float));
-static float math_tanh PARAMS ((float, float));
+static htab_t stag_hash;
+static htab_t op_hash;
+static htab_t parop_hash;
+static htab_t reg_hash;
+static htab_t mmreg_hash;
+static htab_t cc_hash;
+static htab_t cc2_hash;
+static htab_t cc3_hash;
+static htab_t sbit_hash;
+static htab_t misc_symbol_hash;
 
-static struct stag
-{
-  symbolS *sym;                     /* Symbol for this stag; value is offset.  */
-  const char *name;             /* Shortcut to symbol name.  */
-  bfd_vma size;                     /* Size of struct/union.  */
-  int current_bitfield_offset;      /* Temporary for tracking fields.  */
-  int is_union;
-  struct stag_field             /* List of fields.  */
-  {
-    const char *name;
-    bfd_vma offset;             /* Of start of this field.  */
-    int bitfield_offset;           /* Of start of this field.  */
-    struct stag *stag;       /* If field is struct/union.  */
-    struct stag_field *next;
-  } *field;
-  /* For nesting; used only in stag construction.  */
-  struct stag *inner;         /* Enclosed .struct.  */
-  struct stag *outer;         /* Enclosing .struct.  */
-} *current_stag = NULL;
+/* Only word (et al.), align, or conditionals are allowed within
+   .struct/.union.  */
+#define ILLEGAL_WITHIN_STRUCT()                                        \
+  do                                                           \
+    if (current_stag != NULL)                                  \
+      {                                                        \
+       as_bad (_("pseudo-op illegal within .struct/.union"));  \
+       return;                                                 \
+      }                                                                \
+  while (0)
 
-static segT stag_saved_seg;
-static subsegT stag_saved_subseg;
 
-/* Output a single character (upper octect is zero).  */
+static void subsym_create_or_replace (char *, char *);
+static char *subsym_lookup (char *, int);
+static char *subsym_substitute (char *, int);
+
+
+void
+md_show_usage (FILE *stream)
+{
+  fprintf (stream, _("C54x-specific command line options:\n"));
+  fprintf (stream, _("-mfar-mode | -mf          Use extended addressing\n"));
+  fprintf (stream, _("-mcpu=<CPU version>       Specify the CPU version\n"));
+  fprintf (stream, _("-merrors-to-file <filename>\n"));
+  fprintf (stream, _("-me <filename>            Redirect errors to a file\n"));
+}
+
+/* Output a single character (upper octet is zero).  */
 
 static void
-tic54x_emit_char (c)
-     char c;
+tic54x_emit_char (char c)
 {
-  expressionS exp;
+  expressionS expn;
 
-  exp.X_op = O_constant;
-  exp.X_add_number = c;
-  emit_expr (&exp, 2);
+  expn.X_op = O_constant;
+  expn.X_add_number = c;
+  emit_expr (&expn, 2);
 }
 
 /* Walk backwards in the frag chain.  */
 
 static fragS *
-frag_prev (frag, seg)
-     fragS *frag;
-     segT seg;
+frag_prev (fragS *frag, segT seg)
 {
   segment_info_type *seginfo = seg_info (seg);
   fragS *fragp;
@@ -262,9 +265,7 @@ frag_prev (frag, seg)
 }
 
 static fragS *
-bit_offset_frag (frag, seg)
-     fragS *frag;
-     segT seg;
+bit_offset_frag (fragS *frag, segT seg)
 {
   while (frag != NULL)
     {
@@ -282,9 +283,7 @@ bit_offset_frag (frag, seg)
    none. .field/.space/.bes may leave words partially allocated.  */
 
 static int
-frag_bit_offset (frag, seg)
-     fragS *frag;
-     segT seg;
+frag_bit_offset (fragS *frag, segT seg)
 {
   frag = bit_offset_frag (frag, seg);
 
@@ -298,14 +297,14 @@ frag_bit_offset (frag, seg)
    expression.  */
 
 static char *
-parse_expression (char *str, expressionS * exp)
+parse_expression (char *str, expressionS *expn)
 {
   char *s;
   char *tmp;
 
   tmp = input_line_pointer;    /* Save line pointer.  */
   input_line_pointer = str;
-  expression (exp);
+  expression (expn);
   s = input_line_pointer;
   input_line_pointer = tmp;    /* Restore line pointer.  */
   return s;                    /* Return pointer to where parsing stopped.  */
@@ -318,13 +317,11 @@ parse_expression (char *str, expressionS * exp)
    unsupported.  */
 
 static void
-tic54x_asg (x)
-     int x ATTRIBUTE_UNUSED;
+tic54x_asg (int x ATTRIBUTE_UNUSED)
 {
   int c;
   char *name;
   char *str;
-  char *tmp;
   int quoted = *input_line_pointer == '"';
 
   ILLEGAL_WITHIN_STRUCT ();
@@ -340,7 +337,7 @@ tic54x_asg (x)
       str = input_line_pointer;
       while ((c = *input_line_pointer) != ',')
        {
-         if (is_end_of_line[(int) *input_line_pointer])
+         if (is_end_of_line[(unsigned char) c])
            break;
          ++input_line_pointer;
        }
@@ -353,23 +350,19 @@ tic54x_asg (x)
       return;
     }
 
-  name = ++input_line_pointer;
-  c = get_symbol_end ();       /* Get terminator.  */
-  if (!isalpha (*name))
+  ++input_line_pointer;
+  c = get_symbol_name (&name); /* Get terminator.  */
+  if (!ISALPHA (*name))
     {
-      as_bad ("symbols assigned with .asg must begin with a letter");
+      as_bad (_("symbols assigned with .asg must begin with a letter"));
       ignore_rest_of_line ();
       return;
     }
 
-  tmp = xmalloc (strlen (str) + 1);
-  strcpy (tmp, str);
-  str = tmp;
-  tmp = xmalloc (strlen (name) + 1);
-  strcpy (tmp, name);
-  name = tmp;
+  str = xstrdup (str);
+  name = xstrdup (name);
   subsym_create_or_replace (name, str);
-  *input_line_pointer = c;
+  (void) restore_line_pointer (c);
   demand_empty_rest_of_line ();
 }
 
@@ -380,8 +373,7 @@ tic54x_asg (x)
    table, since that's what works best.  */
 
 static void
-tic54x_eval (x)
-     int x ATTRIBUTE_UNUSED;
+tic54x_eval (int x ATTRIBUTE_UNUSED)
 {
   char c;
   int value;
@@ -414,20 +406,17 @@ tic54x_eval (x)
       ignore_rest_of_line ();
       return;
     }
-  name = input_line_pointer;
-  c = get_symbol_end ();       /* Get terminator.  */
-  tmp = xmalloc (strlen (name) + 1);
-  name = strcpy (tmp, name);
-  *input_line_pointer = c;
+  c = get_symbol_name (&name); /* Get terminator.  */
+  name = xstrdup (name);
+  (void) restore_line_pointer (c);
 
-  if (!isalpha (*name))
+  if (!ISALPHA (*name))
     {
       as_bad (_("symbols assigned with .eval must begin with a letter"));
       ignore_rest_of_line ();
       return;
     }
-  symbolP = symbol_new (name, absolute_section,
-                       (valueT) value, &zero_address_frag);
+  symbolP = symbol_new (name, absolute_section, &zero_address_frag, value);
   SF_SET_LOCAL (symbolP);
   symbol_table_insert (symbolP);
 
@@ -435,8 +424,7 @@ tic54x_eval (x)
      But since there's not written rule as to when, don't even bother trying
      to match their behavior.  */
   sprintf (valuestr, "%d", value);
-  tmp = xmalloc (strlen (valuestr) + 1);
-  strcpy (tmp, valuestr);
+  tmp = xstrdup (valuestr);
   subsym_create_or_replace (name, tmp);
 
   demand_empty_rest_of_line ();
@@ -457,8 +445,7 @@ tic54x_eval (x)
       (not yet implemented).  */
 
 static void
-tic54x_bss (x)
-     int x ATTRIBUTE_UNUSED;
+tic54x_bss (int x ATTRIBUTE_UNUSED)
 {
   char c;
   char *name;
@@ -475,11 +462,12 @@ tic54x_bss (x)
   current_seg = now_seg;       /* Save current seg.  */
   current_subseg = now_subseg; /* Save current subseg.  */
 
-  name = input_line_pointer;
-  c = get_symbol_end ();       /* Get terminator.  */
+  c = get_symbol_name (&name); /* Get terminator.  */
+  if (c == '"')
+    c = * ++ input_line_pointer;
   if (c != ',')
     {
-      as_bad (".bss size argument missing\n");
+      as_bad (_(".bss size argument missing\n"));
       ignore_rest_of_line ();
       return;
     }
@@ -488,7 +476,7 @@ tic54x_bss (x)
   words = get_absolute_expression ();
   if (words < 0)
     {
-      as_bad (".bss size %d < 0!", words);
+      as_bad (_(".bss size %d < 0!"), words);
       ignore_rest_of_line ();
       return;
     }
@@ -517,11 +505,11 @@ tic54x_bss (x)
   symbolP = symbol_find_or_make (name);
 
   if (S_GET_SEGMENT (symbolP) == bss_section)
-    symbolP->sy_frag->fr_symbol = (symbolS *) NULL;
+    symbol_get_frag (symbolP)->fr_symbol = (symbolS *) NULL;
 
   symbol_set_frag (symbolP, frag_now);
   p = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP,
-               (offsetT) (words << 1), (char *) 0);
+               (offsetT) (words * OCTETS_PER_BYTE), (char *) 0);
   *p = 0;                      /* Fill char.  */
 
   S_SET_SEGMENT (symbolP, bss_section);
@@ -540,55 +528,48 @@ tic54x_bss (x)
     }
 
   if (block)
-    bss_section->flags |= SEC_BLOCK;
+    bss_section->flags |= SEC_TIC54X_BLOCK;
 
   subseg_set (current_seg, current_subseg);    /* Restore current seg.  */
   demand_empty_rest_of_line ();
 }
 
 static void
-stag_add_field_symbols (stag, path, base_offset, rootsym, root_stag_name)
-     struct stag *stag;
-     const char *path;
-     bfd_vma base_offset;
-     symbolS *rootsym;
-     const char *root_stag_name;
-{
-  char prefix[strlen (path) + 2];
+stag_add_field_symbols (struct stag *stag,
+                       const char *path,
+                       bfd_vma base_offset,
+                       symbolS *rootsym,
+                       const char *root_stag_name)
+{
+  char * prefix;
   struct stag_field *field = stag->field;
 
   /* Construct a symbol for every field contained within this structure
      including fields within structure fields.  */
-  strcpy (prefix, path);
-  if (*path)
-    strcat (prefix, ".");
+  prefix = concat (path, *path ? "." : "", NULL);
 
   while (field != NULL)
     {
-      int len = strlen (prefix) + strlen (field->name) + 2;
-      char *name = xmalloc (len);
-      strcpy (name, prefix);
-      strcat (name, field->name);
+      char *name = concat (prefix, field->name, NULL);
+      char *freename = name;
 
       if (rootsym == NULL)
        {
          symbolS *sym;
-         sym = symbol_new (name, absolute_section,
-                           (field->stag ? field->offset :
-                            (valueT) (base_offset + field->offset)),
-                           &zero_address_frag);
+         sym = symbol_new (name, absolute_section, &zero_address_frag,
+                           (field->stag ? field->offset
+                            : base_offset + field->offset));
          SF_SET_LOCAL (sym);
          symbol_table_insert (sym);
        }
       else
        {
-         char *replacement = xmalloc (strlen (name)
-                                      + strlen (stag->name) + 2);
-         strcpy (replacement, S_GET_NAME (rootsym));
-         strcat (replacement, "+");
-         strcat (replacement, root_stag_name);
-         strcat (replacement, name + strlen (S_GET_NAME (rootsym)));
-         hash_insert (subsym_hash[0], name, replacement);
+         char *replacement;
+
+         replacement = concat (S_GET_NAME (rootsym), "+", root_stag_name,
+                               name + strlen (S_GET_NAME (rootsym)), NULL);
+         str_hash_insert (subsym_hash[0], name, replacement, 0);
+         freename = NULL;
        }
 
       /* Recurse if the field is a structure.
@@ -598,23 +579,23 @@ stag_add_field_symbols (stag, path, base_offset, rootsym, root_stag_name)
                                field->offset,
                                rootsym, root_stag_name);
       field = field->next;
+      free (freename);
     }
+  free (prefix);
 }
 
 /* Keep track of stag fields so that when structures are nested we can add the
    complete dereferencing symbols to the symbol table.  */
 
 static void
-stag_add_field (parent, name, offset, stag)
-     struct stag *parent;
-     const char *name;
-     bfd_vma offset;
-     struct stag *stag;
+stag_add_field (struct stag *parent,
+               const char *name,
+               bfd_vma offset,
+               struct stag *stag)
 {
-  struct stag_field *sfield = xmalloc (sizeof (struct stag_field));
+  struct stag_field *sfield = XCNEW (struct stag_field);
 
-  memset (sfield, 0, sizeof (*sfield));
-  sfield->name = strcpy (xmalloc (strlen (name) + 1), name);
+  sfield->name = xstrdup (name);
   sfield->offset = offset;
   sfield->bitfield_offset = parent->current_bitfield_offset;
   sfield->stag = stag;
@@ -630,8 +611,8 @@ stag_add_field (parent, name, offset, stag)
   /* Only create a symbol for this field if the parent has no name.  */
   if (!strncmp (".fake", parent->name, 5))
     {
-      symbolS *sym = symbol_new (name, absolute_section,
-                                (valueT) offset, &zero_address_frag);
+      symbolS *sym = symbol_new (name, absolute_section, &zero_address_frag,
+                                offset);
       SF_SET_LOCAL (sym);
       symbol_table_insert (sym);
     }
@@ -665,7 +646,7 @@ tic54x_struct (int arg)
     {
       /* Offset is ignored in inner structs.  */
       SKIP_WHITESPACE ();
-      if (!is_end_of_line[(int) *input_line_pointer])
+      if (!is_end_of_line[(unsigned char) *input_line_pointer])
        start_offset = get_absolute_expression ();
       else
        start_offset = 0;
@@ -674,8 +655,7 @@ tic54x_struct (int arg)
   if (current_stag)
     {
       /* Nesting, link to outer one.  */
-      current_stag->inner = (struct stag *) xmalloc (sizeof (struct stag));
-      memset (current_stag->inner, 0, sizeof (struct stag));
+      current_stag->inner = XCNEW (struct stag);
       current_stag->inner->outer = current_stag;
       current_stag = current_stag->inner;
       if (start_offset)
@@ -684,8 +664,7 @@ tic54x_struct (int arg)
     }
   else
     {
-      current_stag = (struct stag *) xmalloc (sizeof (struct stag));
-      memset (current_stag, 0, sizeof (struct stag));
+      current_stag = XCNEW (struct stag);
       abs_section_offset = start_offset;
     }
   current_stag->is_union = is_union;
@@ -696,16 +675,17 @@ tic54x_struct (int arg)
       char fake[] = ".fake_stagNNNNNNN";
       sprintf (fake, ".fake_stag%d", struct_count++);
       current_stag->sym = symbol_new (fake, absolute_section,
-                                     (valueT) abs_section_offset,
-                                     &zero_address_frag);
+                                     &zero_address_frag,
+                                     abs_section_offset);
     }
   else
     {
-      char label[strlen (S_GET_NAME (line_label)) + 1];
-      strcpy (label, S_GET_NAME (line_label));
-      current_stag->sym = symbol_new (label, absolute_section,
-                                     (valueT) abs_section_offset,
-                                     &zero_address_frag);
+      char * label = xstrdup (S_GET_NAME (line_label));
+      current_stag->sym = symbol_new (label,
+                                     absolute_section,
+                                     &zero_address_frag,
+                                     abs_section_offset);
+      free (label);
     }
   current_stag->name = S_GET_NAME (current_stag->sym);
   SF_SET_LOCAL (current_stag->sym);
@@ -760,7 +740,7 @@ tic54x_endstruct (int is_union)
   /* Nested .structs don't get put in the stag table.  */
   if (current_stag->outer == NULL)
     {
-      hash_insert (stag_hash, current_stag->name, current_stag);
+      str_hash_insert (stag_hash, current_stag->name, current_stag, 0);
       stag_add_field_symbols (current_stag, path,
                              S_GET_VALUE (current_stag->sym),
                              NULL, NULL);
@@ -786,12 +766,11 @@ tic54x_endstruct (int is_union)
    format on the existing allocated space.  */
 
 static void
-tic54x_tag (ignore)
-     int ignore ATTRIBUTE_UNUSED;
+tic54x_tag (int ignore ATTRIBUTE_UNUSED)
 {
-  char *name = input_line_pointer;
-  int c = get_symbol_end ();
-  struct stag *stag = (struct stag *) hash_find (stag_hash, name);
+  char *name;
+  int c = get_symbol_name (&name);
+  struct stag *stag = (struct stag *) str_hash_find (stag_hash, name);
 
   if (!stag)
     {
@@ -810,9 +789,9 @@ tic54x_tag (ignore)
     }
   else
     {
-      char label[strlen (S_GET_NAME (line_label)) + 1];
+      char * label;
 
-      strcpy (label, S_GET_NAME (line_label));
+      label = xstrdup (S_GET_NAME (line_label));
       if (current_stag != NULL)
        stag_add_field (current_stag, label,
                        abs_section_offset - S_GET_VALUE (current_stag->sym),
@@ -820,22 +799,25 @@ tic54x_tag (ignore)
       else
        {
          symbolS *sym = symbol_find (label);
+
          if (!sym)
            {
              as_bad (_(".tag target '%s' undefined"), label);
              ignore_rest_of_line ();
+             free (label);
              return;
            }
          stag_add_field_symbols (stag, S_GET_NAME (sym),
                                  S_GET_VALUE (stag->sym), sym, stag->name);
        }
+      free (label);
     }
 
   /* Bump by the struct size, but only if we're within a .struct section.  */
   if (current_stag != NULL && !current_stag->is_union)
     abs_section_offset += stag->size;
 
-  *input_line_pointer = c;
+  (void) restore_line_pointer (c);
   demand_empty_rest_of_line ();
   line_label = NULL;
 }
@@ -854,7 +836,7 @@ tic54x_struct_field (int type)
   int longword_align = 0;
 
   SKIP_WHITESPACE ();
-  if (!is_end_of_line[(int) *input_line_pointer])
+  if (!is_end_of_line[(unsigned char) *input_line_pointer])
     count = get_absolute_expression ();
 
   switch (type)
@@ -903,9 +885,7 @@ tic54x_struct_field (int type)
              new_bitfield_offset = count - 16;
            }
          else
-           {
-             new_bitfield_offset = count;
-           }
+           new_bitfield_offset = count;
        }
       else
        {
@@ -933,6 +913,7 @@ tic54x_struct_field (int type)
     {
       static int fieldno = 0;
       char fake[] = ".fake_fieldNNNNN";
+
       sprintf (fake, ".fake_field%d", fieldno++);
       stag_add_field (current_stag, fake,
                      abs_section_offset - S_GET_VALUE (current_stag->sym),
@@ -940,11 +921,13 @@ tic54x_struct_field (int type)
     }
   else
     {
-      char label[strlen (S_GET_NAME (line_label) + 1)];
-      strcpy (label, S_GET_NAME (line_label));
+      char * label;
+
+      label = xstrdup (S_GET_NAME (line_label));
       stag_add_field (current_stag, label,
                      abs_section_offset - S_GET_VALUE (current_stag->sym),
                      NULL);
+      free (label);
     }
 
   if (current_stag->is_union)
@@ -963,11 +946,10 @@ tic54x_struct_field (int type)
 
 /* Handle .byte, .word. .int, .long and all variants.  */
 
-int emitting_long = 0;
 static void
 tic54x_cons (int type)
 {
-  register unsigned int c;
+  unsigned int c;
   int octets;
 
   /* If we're within a .struct construct, don't actually allocate space.  */
@@ -1024,28 +1006,28 @@ tic54x_cons (int type)
        }
       else
        {
-         expressionS exp;
+         expressionS expn;
 
-         input_line_pointer = parse_expression (input_line_pointer, &exp);
-         if (exp.X_op == O_constant)
+         input_line_pointer = parse_expression (input_line_pointer, &expn);
+         if (expn.X_op == O_constant)
            {
-             offsetT value = exp.X_add_number;
+             offsetT value = expn.X_add_number;
              /* Truncate overflows.  */
              switch (octets)
                {
                case 1:
                  if ((value > 0 && value > 0xFF)
                      || (value < 0 && value < - 0x100))
-                   as_warn ("Overflow in expression, truncated to 8 bits");
+                   as_warn (_("Overflow in expression, truncated to 8 bits"));
                  break;
                case 2:
                  if ((value > 0 && value > 0xFFFF)
                      || (value < 0 && value < - 0x10000))
-                   as_warn ("Overflow in expression, truncated to 16 bits");
+                   as_warn (_("Overflow in expression, truncated to 16 bits"));
                  break;
                }
            }
-         if (exp.X_op != O_constant && octets < 2)
+         if (expn.X_op != O_constant && octets < 2)
            {
              /* Disallow .byte with a non constant expression that will
                 require relocation.  */
@@ -1054,25 +1036,25 @@ tic54x_cons (int type)
              return;
            }
 
-         if (exp.X_op != O_constant
+         if (expn.X_op != O_constant
              && amode == c_mode
              && octets == 4)
            {
              /* FIXME -- at one point TI tools used to output REL16
                 relocations, but I don't think the latest tools do at all
                 The current tools output extended relocations regardless of
-                the addresing mode (I actually think that ".c_mode" is
+                the addressing mode (I actually think that ".c_mode" is
                 totally ignored in the latest tools).  */
              amode = far_mode;
              emitting_long = 1;
-             emit_expr (&exp, 4);
+             emit_expr (&expn, 4);
              emitting_long = 0;
              amode = c_mode;
            }
          else
            {
              emitting_long = octets == 4;
-             emit_expr (&exp, (octets == 1) ? 2 : octets);
+             emit_expr (&expn, (octets == 1) ? 2 : octets);
              emitting_long = 0;
            }
        }
@@ -1103,8 +1085,7 @@ tic54x_cons (int type)
    these, so we ignore the type here.  */
 
 void
-tic54x_global (type)
-     int type;
+tic54x_global (int type)
 {
   char *name;
   int c;
@@ -1117,16 +1098,15 @@ tic54x_global (type)
 
   do
     {
-      name = input_line_pointer;
-      c = get_symbol_end ();
+      c = get_symbol_name (&name);
       symbolP = symbol_find_or_make (name);
+      c = restore_line_pointer (c);
 
-      *input_line_pointer = c;
       S_SET_STORAGE_CLASS (symbolP, C_EXT);
       if (c == ',')
        {
          input_line_pointer++;
-         if (is_end_of_line[(int) *input_line_pointer])
+         if (is_end_of_line[(unsigned char) *input_line_pointer])
            c = *input_line_pointer;
        }
     }
@@ -1137,22 +1117,22 @@ tic54x_global (type)
 
 /* Remove the symbol from the local label hash lookup.  */
 
-static void
-tic54x_remove_local_label (key, value)
-     const char *key;
-     PTR value ATTRIBUTE_UNUSED;
+static int
+tic54x_remove_local_label (void **slot, void *arg ATTRIBUTE_UNUSED)
 {
-  PTR *elem = hash_delete (local_label_hash[macro_level], key);
+  string_tuple_t *tuple = *((string_tuple_t **) slot);
+  void *elem = str_hash_find (local_label_hash[macro_level], tuple->key);
+  str_hash_delete (local_label_hash[macro_level], tuple->key);
   free (elem);
+  return 0;
 }
 
 /* Reset all local labels.  */
 
 static void
-tic54x_clear_local_labels (ignored)
-     int ignored ATTRIBUTE_UNUSED;
+tic54x_clear_local_labels (int ignored ATTRIBUTE_UNUSED)
 {
-  hash_traverse (local_label_hash[macro_level], tic54x_remove_local_label);
+  htab_traverse (local_label_hash[macro_level], tic54x_remove_local_label, NULL);
 }
 
 /* .text
@@ -1164,7 +1144,9 @@ tic54x_clear_local_labels (ignored)
 
    ARG is 't' for text, 'd' for data, or '*' for a named section
 
-   For compatibility, '*' sections have SEC_DATA set instead of SEC_CODE.  */
+   For compatibility, '*' sections are SEC_CODE if instructions are
+   encountered, or SEC_DATA if not.
+*/
 
 static void
 tic54x_sect (int arg)
@@ -1182,24 +1164,27 @@ tic54x_sect (int arg)
     {
       char *name = NULL;
       int len;
+      /* Make sure all named initialized sections flagged properly.  If we
+         encounter instructions, we'll flag it with SEC_CODE as well.  */
+      const char *flags = ",\"w\"\n";
+
       /* If there are quotes, remove them.  */
       if (*input_line_pointer == '"')
        {
          name = demand_copy_C_string (&len);
          demand_empty_rest_of_line ();
-         name = strcpy (xmalloc (len + 10), name);
+         name = concat (name, flags, (char *) NULL);
        }
       else
        {
          int c;
-         name = input_line_pointer;
-         c = get_symbol_end ();
-         name = strcpy (xmalloc (len + 10), name);
-         *input_line_pointer = c;
+
+         c = get_symbol_name (&name);
+         name = concat (name, flags, (char *) NULL);
+         (void) restore_line_pointer (c);
          demand_empty_rest_of_line ();
        }
-      /* Make sure all named initialized sections are SEC_DATA.  */
-      strcat (name, ",\"w\"\n");
+
       input_scrub_insert_line (name);
       obj_coff_section (0);
 
@@ -1227,7 +1212,7 @@ tic54x_sect (int arg)
 static void
 tic54x_space (int arg)
 {
-  expressionS exp;
+  expressionS expn;
   char *p = 0;
   int octets = 0;
   long words;
@@ -1243,22 +1228,21 @@ tic54x_space (int arg)
 #endif
 
   /* Read the bit count.  */
-  expression (&exp);
+  expression (&expn);
 
   /* Some expressions are unresolvable until later in the assembly pass;
      postpone until relaxation/fixup.  we also have to postpone if a previous
      partial allocation has not been completed yet.  */
-  if (exp.X_op != O_constant || frag_bit_offset (frag_now, now_seg) == -1)
+  if (expn.X_op != O_constant || frag_bit_offset (frag_now, now_seg) == -1)
     {
-      struct bit_info *bi = xmalloc (sizeof (struct bit_info));
-      char *p;
+      struct bit_info *bi = XNEW (struct bit_info);
 
       bi->seg = now_seg;
       bi->type = bes;
       bi->sym = label;
       p = frag_var (rs_machine_dependent,
                    65536 * 2, 1, (relax_substateT) 0,
-                   make_expr_symbol (&exp), (offsetT) 0,
+                   make_expr_symbol (&expn), (offsetT) 0,
                    (char *) bi);
       if (p)
        *p = 0;
@@ -1272,7 +1256,8 @@ tic54x_space (int arg)
   if (bit_offset != 0 && bit_offset < 16)
     {
       int spare_bits = bits_per_byte - bit_offset;
-      if (spare_bits >= exp.X_add_number)
+
+      if (spare_bits >= expn.X_add_number)
        {
          /* Don't have to do anything; sufficient bits have already been
             allocated; just point the label to the right place.  */
@@ -1282,10 +1267,10 @@ tic54x_space (int arg)
              S_SET_VALUE (label, frag_now_fix () - 1);
              label = NULL;
            }
-         frag_now->tc_frag_data += exp.X_add_number;
+         frag_now->tc_frag_data += expn.X_add_number;
          goto getout;
        }
-      exp.X_add_number -= spare_bits;
+      expn.X_add_number -= spare_bits;
       /* Set the label to point to the first word allocated, which in this
         case is the previous word, which was only partially filled.  */
       if (!bes && label != NULL)
@@ -1296,9 +1281,9 @@ tic54x_space (int arg)
        }
     }
   /* Convert bits to bytes/words and octets, rounding up.  */
-  words = ((exp.X_add_number + bits_per_byte - 1) / bits_per_byte);
+  words = ((expn.X_add_number + bits_per_byte - 1) / bits_per_byte);
   /* How many do we have left over?  */
-  bit_offset = exp.X_add_number % bits_per_byte;
+  bit_offset = expn.X_add_number % bits_per_byte;
   octets = words * OCTETS_PER_BYTE;
   if (octets < 0)
     {
@@ -1347,7 +1332,7 @@ tic54x_space (int arg)
 /* [symbol] .usect "section-name", size-in-words
                   [, [blocking-flag] [, alignment-flag]]
 
-   Unitialized section.
+   Uninitialized section.
    Non-zero blocking means that if the section would cross a page (128-word)
    boundary, it will be page-aligned.
    Non-zero alignment aligns on a longword boundary.
@@ -1355,8 +1340,7 @@ tic54x_space (int arg)
    Has no effect on the current section.  */
 
 static void
-tic54x_usect (x)
-     int x ATTRIBUTE_UNUSED;
+tic54x_usect (int x ATTRIBUTE_UNUSED)
 {
   char c;
   char *name;
@@ -1373,17 +1357,13 @@ tic54x_usect (x)
   current_seg = now_seg;       /* Save current seg.  */
   current_subseg = now_subseg; /* Save current subseg.  */
 
-  if (*input_line_pointer == '"')
-    input_line_pointer++;
-  section_name = input_line_pointer;
-  c = get_symbol_end ();       /* Get terminator.  */
-  input_line_pointer++;                /* Skip null symbol terminator.  */
-  name = xmalloc (input_line_pointer - section_name + 1);
-  strcpy (name, section_name);
-
-  if (*input_line_pointer == ',')
+  c = get_symbol_name (&section_name); /* Get terminator.  */
+  name = xstrdup (section_name);
+  c = restore_line_pointer (c);
+  
+  if (c == ',')
     ++input_line_pointer;
-  else if (c != ',')
+  else
     {
       as_bad (_("Missing size argument"));
       ignore_rest_of_line ();
@@ -1414,7 +1394,7 @@ tic54x_usect (x)
     blocking_flag = alignment_flag = 0;
 
   seg = subseg_new (name, 0);
-  flags = bfd_get_section_flags (stdoutput, seg) | SEC_ALLOC;
+  flags = bfd_section_flags (seg) | SEC_ALLOC;
 
   if (alignment_flag)
     {
@@ -1441,10 +1421,10 @@ tic54x_usect (x)
   *p = 0;
 
   if (blocking_flag)
-    flags |= SEC_BLOCK;
+    flags |= SEC_TIC54X_BLOCK;
 
-  if (!bfd_set_section_flags (stdoutput, seg, flags))
-    as_warn ("Error setting flags for \"%s\": %s", name,
+  if (!bfd_set_section_flags (seg, flags))
+    as_warn (_("Error setting flags for \"%s\": %s"), name,
             bfd_errmsg (bfd_get_error ()));
 
   subseg_set (current_seg, current_subseg);    /* Restore current seg.  */
@@ -1452,8 +1432,7 @@ tic54x_usect (x)
 }
 
 static enum cpu_version
-lookup_version (ver)
-     const char *ver;
+lookup_version (const char *ver)
 {
   enum cpu_version version = VNONE;
 
@@ -1464,8 +1443,8 @@ lookup_version (ver)
              || ver[2] == '5' || ver[2] == '8' || ver[2] == '9'))
        version = ver[2] - '0';
       else if (strlen (ver) == 5
-              && toupper (ver[3]) == 'L'
-              && toupper (ver[4]) == 'P'
+              && TOUPPER (ver[3]) == 'L'
+              && TOUPPER (ver[4]) == 'P'
               && (ver[2] == '5' || ver[2] == '6'))
        version = ver[2] - '0' + 10;
     }
@@ -1474,14 +1453,13 @@ lookup_version (ver)
 }
 
 static void
-set_cpu (version)
-     enum cpu_version version;
+set_cpu (enum cpu_version version)
 {
   cpu = version;
   if (version == V545LP || version == V546LP)
     {
       symbolS *symbolP = symbol_new ("__allow_lp", absolute_section,
-                                    (valueT) 1, &zero_address_frag);
+                                    &zero_address_frag, 1);
       SF_SET_LOCAL (symbolP);
       symbol_table_insert (symbolP);
     }
@@ -1502,8 +1480,7 @@ set_cpu (version)
 static int cpu_needs_set = 1;
 
 static void
-tic54x_version (x)
-     int x ATTRIBUTE_UNUSED;
+tic54x_version (int x ATTRIBUTE_UNUSED)
 {
   enum cpu_version version = VNONE;
   enum cpu_version old_version = cpu;
@@ -1514,7 +1491,7 @@ tic54x_version (x)
 
   SKIP_WHITESPACE ();
   ver = input_line_pointer;
-  while (!is_end_of_line[(int) *input_line_pointer])
+  while (!is_end_of_line[(unsigned char) *input_line_pointer])
     ++input_line_pointer;
   c = *input_line_pointer;
   *input_line_pointer = 0;
@@ -1572,15 +1549,13 @@ tic54x_float_cons (int type)
 
 /* The argument is capitalized if it should be zero-terminated
    's' is normal string with upper 8-bits zero-filled, 'p' is packed.
-   Code copied from read.c, and slightly modified so that strings are packed
+   Code copied from stringer, and slightly modified so that strings are packed
    and encoded into the correct octets.  */
 
 static void
-tic54x_stringer (type)
-     int type;
+tic54x_stringer (int type)
 {
-  register unsigned int c;
-  char *start;
+  unsigned int c;
   int append_zero = type == 'S' || type == 'P';
   int packed = type == 'p' || type == 'P';
   int last_char = -1; /* Packed strings need two bytes at a time to encode.  */
@@ -1610,7 +1585,6 @@ tic54x_stringer (type)
          }
        case '\"':
          ++input_line_pointer; /* -> 1st char of string.  */
-         start = input_line_pointer;
          while (is_a_char (c = next_char_of_string ()))
            {
              if (!packed)
@@ -1664,20 +1638,18 @@ tic54x_stringer (type)
 }
 
 static void
-tic54x_p2align (arg)
-     int arg ATTRIBUTE_UNUSED;
+tic54x_p2align (int arg ATTRIBUTE_UNUSED)
 {
   as_bad (_("p2align not supported on this target"));
 }
 
 static void
-tic54x_align_words (arg)
-     int arg;
+tic54x_align_words (int arg)
 {
   /* Only ".align" with no argument is allowed within .struct/.union.  */
   int count = arg;
 
-  if (!is_end_of_line[(int) *input_line_pointer])
+  if (!is_end_of_line[(unsigned char) *input_line_pointer])
     {
       if (arg == 2)
        as_warn (_("Argument to .even ignored"));
@@ -1701,13 +1673,12 @@ tic54x_align_words (arg)
   s_align_bytes (count << 1);
 }
 
-/* Initialize multiple-bit fields withing a single word of memory.  */
+/* Initialize multiple-bit fields within a single word of memory.  */
 
 static void
-tic54x_field (ignore)
-     int ignore ATTRIBUTE_UNUSED;
+tic54x_field (int ignore ATTRIBUTE_UNUSED)
 {
-  expressionS exp;
+  expressionS expn;
   int size = 16;
   char *p;
   valueT value;
@@ -1719,7 +1690,7 @@ tic54x_field (ignore)
       return;
     }
 
-  input_line_pointer = parse_expression (input_line_pointer, &exp);
+  input_line_pointer = parse_expression (input_line_pointer, &expn);
 
   if (*input_line_pointer == ',')
     {
@@ -1734,7 +1705,7 @@ tic54x_field (ignore)
     }
 
   /* Truncate values to the field width.  */
-  if (exp.X_op != O_constant)
+  if (expn.X_op != O_constant)
     {
       /* If the expression value is relocatable, the field size *must*
          be 16.  */
@@ -1746,16 +1717,17 @@ tic54x_field (ignore)
        }
 
       frag_now->tc_frag_data = 0;
-      emit_expr (&exp, 2);
+      emit_expr (&expn, 2);
     }
   else
     {
       unsigned long fmask = (size == 32) ? 0xFFFFFFFF : (1ul << size) - 1;
-      value = exp.X_add_number;
-      exp.X_add_number &= fmask;
-      if (value != (valueT) exp.X_add_number)
+
+      value = expn.X_add_number;
+      expn.X_add_number &= fmask;
+      if (value != (valueT) expn.X_add_number)
        as_warn (_("field value truncated"));
-      value = exp.X_add_number;
+      value = expn.X_add_number;
       /* Bits are stored MS first.  */
       while (size >= 16)
        {
@@ -1767,13 +1739,15 @@ tic54x_field (ignore)
       if (size > 0)
        {
          int bit_offset = frag_bit_offset (frag_now, now_seg);
+
          fragS *alloc_frag = bit_offset_frag (frag_now, now_seg);
          if (bit_offset == -1)
            {
-             struct bit_info *bi = xmalloc (sizeof (struct bit_info));
+             struct bit_info *bi = XNEW (struct bit_info);
              /* We don't know the previous offset at this time, so store the
                 info we need and figure it out later.  */
              expressionS size_exp;
+
              size_exp.X_op = O_constant;
              size_exp.X_add_number = size;
              bi->seg = now_seg;
@@ -1825,8 +1799,7 @@ tic54x_field (ignore)
    available yet.  seg_info ()->bss is the next best thing.  */
 
 static int
-tic54x_initialized_section (seg)
-     segT seg;
+tic54x_initialized_section (segT seg)
 {
   return !seg_info (seg)->bss;
 }
@@ -1839,8 +1812,7 @@ tic54x_initialized_section (seg)
    Name is required for uninitialized sections.  */
 
 static void
-tic54x_clink (ignored)
-     int ignored ATTRIBUTE_UNUSED;
+tic54x_clink (int ignored ATTRIBUTE_UNUSED)
 {
   segT seg = now_seg;
 
@@ -1850,12 +1822,12 @@ tic54x_clink (ignored)
     {
       char *section_name = ++input_line_pointer;
       char *name;
+
       while (is_a_char (next_char_of_string ()))
        ;
       know (input_line_pointer[-1] == '\"');
       input_line_pointer[-1] = 0;
-      name = xmalloc (input_line_pointer - section_name + 1);
-      strcpy (name, section_name);
+      name = xstrdup (section_name);
 
       seg = bfd_get_section_by_name (stdoutput, name);
       if (seg == NULL)
@@ -1869,14 +1841,14 @@ tic54x_clink (ignored)
     {
       if (!tic54x_initialized_section (seg))
        {
-         as_bad (_("Current section is unitialized, "
+         as_bad (_("Current section is uninitialized, "
                    "section name required for .clink"));
          ignore_rest_of_line ();
          return;
        }
     }
 
-  seg->flags |= SEC_CLINK;
+  seg->flags |= SEC_TIC54X_CLINK;
 
   demand_empty_rest_of_line ();
 }
@@ -1886,29 +1858,24 @@ tic54x_clink (ignored)
    set to "." instead.  */
 
 static void
-tic54x_set_default_include (dot)
-     int dot;
+tic54x_set_default_include (void)
 {
-  char *dir = ".";
-  char *tmp = NULL;
+  char *dir, *tmp = NULL;
+  const char *curfile;
+  unsigned lineno;
 
-  if (!dot)
-    {
-      char *curfile;
-      unsigned lineno;
-
-      as_where (&curfile, &lineno);
-      dir = strcpy (xmalloc (strlen (curfile) + 1), curfile);
-      tmp = strrchr (dir, '/');
-    }
+  curfile = as_where (&lineno);
+  dir = xstrdup (curfile);
+  tmp = strrchr (dir, '/');
   if (tmp != NULL)
     {
       int len;
+
       *tmp = '\0';
       len = strlen (dir);
       if (include_dir_count == 0)
        {
-         include_dirs = (char **) xmalloc (sizeof (*include_dirs));
+         include_dirs = XNEWVEC (const char *, 1);
          include_dir_count = 1;
        }
       include_dirs[0] = dir;
@@ -1931,8 +1898,7 @@ tic54x_set_default_include (dot)
    Entering/exiting included/copied file clears all local labels.  */
 
 static void
-tic54x_include (ignored)
-     int ignored ATTRIBUTE_UNUSED;
+tic54x_include (int ignored ATTRIBUTE_UNUSED)
 {
   char newblock[] = " .newblock\n";
   char *filename;
@@ -1951,11 +1917,11 @@ tic54x_include (ignored)
   else
     {
       filename = input_line_pointer;
-      while (!is_end_of_line[(int) *input_line_pointer])
+      while (!is_end_of_line[(unsigned char) *input_line_pointer])
        ++input_line_pointer;
       c = *input_line_pointer;
       *input_line_pointer = '\0';
-      filename = strcpy (xmalloc (strlen (filename) + 1), filename);
+      filename = xstrdup (filename);
       *input_line_pointer = c;
       demand_empty_rest_of_line ();
     }
@@ -1963,20 +1929,18 @@ tic54x_include (ignored)
      and a .newblock.
      The included file will be inserted before the newblock, so that the
      newblock is executed after the included file is processed.  */
-  input = xmalloc (sizeof (newblock) + strlen (filename) + 4);
-  sprintf (input, "\"%s\"\n%s", filename, newblock);
+  input = concat ("\"", filename, "\"\n", newblock, (char *) NULL);
   input_scrub_insert_line (input);
 
   tic54x_clear_local_labels (0);
 
-  tic54x_set_default_include (0);
+  tic54x_set_default_include ();
 
   s_include (0);
 }
 
 static void
-tic54x_message (type)
-     int type;
+tic54x_message (int type)
 {
   char *msg;
   char c;
@@ -1989,11 +1953,11 @@ tic54x_message (type)
   else
     {
       msg = input_line_pointer;
-      while (!is_end_of_line[(int) *input_line_pointer])
+      while (!is_end_of_line[(unsigned char) *input_line_pointer])
        ++input_line_pointer;
       c = *input_line_pointer;
       *input_line_pointer = 0;
-      msg = strcpy (xmalloc (strlen (msg) + 1), msg);
+      msg = xstrdup (msg);
       *input_line_pointer = c;
     }
 
@@ -2022,20 +1986,19 @@ tic54x_message (type)
    run address (vma).  */
 
 static void
-tic54x_label (ignored)
-     int ignored ATTRIBUTE_UNUSED;
+tic54x_label (int ignored ATTRIBUTE_UNUSED)
 {
-  char *name = input_line_pointer;
+  char *name;
   symbolS *symbolP;
   int c;
 
   ILLEGAL_WITHIN_STRUCT ();
 
-  c = get_symbol_end ();
+  c = get_symbol_name (&name);
   symbolP = colon (name);
   S_SET_STORAGE_CLASS (symbolP, C_STATLAB);
 
-  *input_line_pointer = c;
+  (void) restore_line_pointer (c);
   demand_empty_rest_of_line ();
 }
 
@@ -2044,17 +2007,16 @@ tic54x_label (ignored)
    absolute local symbols.  */
 
 static void
-tic54x_mmregs (ignored)
-     int ignored ATTRIBUTE_UNUSED;
+tic54x_mmregs (int ignored ATTRIBUTE_UNUSED)
 {
-  symbol *sym;
+  tic54x_symbol *sym;
 
   ILLEGAL_WITHIN_STRUCT ();
 
-  for (sym = (symbol *) mmregs; sym->name; sym++)
+  for (sym = (tic54x_symbol *) mmregs; sym->name; sym++)
     {
       symbolS *symbolP = symbol_new (sym->name, absolute_section,
-                                    (valueT) sym->value, &zero_address_frag);
+                                    &zero_address_frag, sym->value);
       SF_SET_LOCAL (symbolP);
       symbol_table_insert (symbolP);
     }
@@ -2069,17 +2031,16 @@ tic54x_loop (int count)
   ILLEGAL_WITHIN_STRUCT ();
 
   SKIP_WHITESPACE ();
-  if (!is_end_of_line[(int) *input_line_pointer])
+  if (!is_end_of_line[(unsigned char) *input_line_pointer])
     count = get_absolute_expression ();
 
-  do_repeat (count, "LOOP", "ENDLOOP");
+  do_repeat ((size_t) count, "LOOP", "ENDLOOP");
 }
 
 /* Normally, endloop gets eaten by the preceding loop.  */
 
 static void
-tic54x_endloop (ignore)
-     int ignore ATTRIBUTE_UNUSED;
+tic54x_endloop (int ignore ATTRIBUTE_UNUSED)
 {
   as_bad (_("ENDLOOP without corresponding LOOP"));
   ignore_rest_of_line ();
@@ -2088,15 +2049,14 @@ tic54x_endloop (ignore)
 /* .break [condition].  */
 
 static void
-tic54x_break (ignore)
-     int ignore ATTRIBUTE_UNUSED;
+tic54x_break (int ignore ATTRIBUTE_UNUSED)
 {
   int cond = 1;
 
   ILLEGAL_WITHIN_STRUCT ();
 
   SKIP_WHITESPACE ();
-  if (!is_end_of_line[(int) *input_line_pointer])
+  if (!is_end_of_line[(unsigned char) *input_line_pointer])
     cond = get_absolute_expression ();
 
   if (cond)
@@ -2104,23 +2064,22 @@ tic54x_break (ignore)
 }
 
 static void
-set_address_mode (mode)
-     int mode;
+set_address_mode (int mode)
 {
   amode = mode;
   if (mode == far_mode)
     {
       symbolS *symbolP = symbol_new ("__allow_far", absolute_section,
-                                    (valueT) 1, &zero_address_frag);
+                                    &zero_address_frag, 1);
       SF_SET_LOCAL (symbolP);
       symbol_table_insert (symbolP);
     }
 }
 
 static int address_mode_needs_set = 1;
+
 static void
-tic54x_address_mode (mode)
-     int mode;
+tic54x_address_mode (int mode)
 {
   if (assembly_begun && amode != (unsigned) mode)
     {
@@ -2143,8 +2102,7 @@ tic54x_address_mode (mode)
    Designate initialized sections for blocking.  */
 
 static void
-tic54x_sblock (ignore)
-     int ignore ATTRIBUTE_UNUSED;
+tic54x_sblock (int ignore ATTRIBUTE_UNUSED)
 {
   int c = ',';
 
@@ -2158,15 +2116,16 @@ tic54x_sblock (ignore)
       if (*input_line_pointer == '"')
        {
          int len;
+
          name = demand_copy_C_string (&len);
        }
       else
        {
-         char *section_name = input_line_pointer;
-         c = get_symbol_end ();
-         name = xmalloc (strlen (section_name) + 1);
-         strcpy (name, section_name);
-         *input_line_pointer = c;
+         char *section_name;
+
+         c = get_symbol_name (&section_name);
+         name = xstrdup (section_name);
+         (void) restore_line_pointer (c);
        }
 
       seg = bfd_get_section_by_name (stdoutput, name);
@@ -2182,10 +2141,10 @@ tic54x_sblock (ignore)
          ignore_rest_of_line ();
          return;
        }
-      seg->flags |= SEC_BLOCK;
+      seg->flags |= SEC_TIC54X_BLOCK;
 
       c = *input_line_pointer;
-      if (!is_end_of_line[(int) c])
+      if (!is_end_of_line[(unsigned char) c])
        ++input_line_pointer;
     }
 
@@ -2199,8 +2158,7 @@ tic54x_sblock (ignore)
    symbols assigned with .set/.equ may not be redefined.  */
 
 static void
-tic54x_set (ignore)
-     int ignore ATTRIBUTE_UNUSED;
+tic54x_set (int ignore ATTRIBUTE_UNUSED)
 {
   symbolS *symbolP;
   char *name;
@@ -2218,7 +2176,7 @@ tic54x_set (ignore)
   if ((symbolP = symbol_find (name)) == NULL
       && (symbolP = md_undefined_symbol (name)) == NULL)
     {
-      symbolP = symbol_new (name, absolute_section, 0, &zero_address_frag);
+      symbolP = symbol_new (name, absolute_section, &zero_address_frag, 0);
       S_SET_STORAGE_CLASS (symbolP, C_STAT);
     }
   free (name);
@@ -2255,8 +2213,7 @@ tic54x_sslist (int show)
    Define a substitution string to be local to a macro.  */
 
 static void
-tic54x_var (ignore)
-     int ignore ATTRIBUTE_UNUSED;
+tic54x_var (int ignore ATTRIBUTE_UNUSED)
 {
   static char empty[] = "";
   char *name;
@@ -2272,22 +2229,21 @@ tic54x_var (ignore)
     }
   do
     {
-      if (!isalpha (*input_line_pointer))
+      if (!ISALPHA (*input_line_pointer))
        {
          as_bad (_("Substitution symbols must begin with a letter"));
          ignore_rest_of_line ();
          return;
        }
-      name = input_line_pointer;
-      c = get_symbol_end ();
+      c = get_symbol_name (&name);
       /* .var symbols start out with a null string.  */
-      name = strcpy (xmalloc (strlen (name) + 1), name);
-      hash_insert (subsym_hash[macro_level], name, empty);
-      *input_line_pointer = c;
+      name = xstrdup (name);
+      str_hash_insert (subsym_hash[macro_level], name, empty, 0);
+      c = restore_line_pointer (c);
       if (c == ',')
        {
          ++input_line_pointer;
-         if (is_end_of_line[(int) *input_line_pointer])
+         if (is_end_of_line[(unsigned char) *input_line_pointer])
            c = *input_line_pointer;
        }
     }
@@ -2304,8 +2260,7 @@ tic54x_var (ignore)
    FIXME need to try the source file directory as well.  */
 
 static void
-tic54x_mlib (ignore)
-     int ignore ATTRIBUTE_UNUSED;
+tic54x_mlib (int ignore ATTRIBUTE_UNUSED)
 {
   char *filename;
   char *path;
@@ -2324,8 +2279,8 @@ tic54x_mlib (ignore)
     {
       SKIP_WHITESPACE ();
       len = 0;
-      while (!is_end_of_line[(int) *input_line_pointer]
-            && !isspace (*input_line_pointer))
+      while (!is_end_of_line[(unsigned char) *input_line_pointer]
+            && !ISSPACE (*input_line_pointer))
        {
          obstack_1grow (&notes, *input_line_pointer);
          ++input_line_pointer;
@@ -2336,11 +2291,13 @@ tic54x_mlib (ignore)
     }
   demand_empty_rest_of_line ();
 
-  tic54x_set_default_include (0);
-  path = xmalloc ((unsigned long) len + include_dir_maxlen + 5);
+  tic54x_set_default_include ();
+  path = XNEWVEC (char, (unsigned long) len + include_dir_maxlen + 5);
+
   for (i = 0; i < include_dir_count; i++)
     {
       FILE *try;
+
       strcpy (path, include_dirs[i]);
       strcat (path, "/");
       strcat (path, filename);
@@ -2350,6 +2307,7 @@ tic54x_mlib (ignore)
          break;
        }
     }
+
   if (i >= include_dir_count)
     {
       free (path);
@@ -2365,8 +2323,8 @@ tic54x_mlib (ignore)
   abfd = bfd_openr (path, NULL);
   if (!abfd)
     {
-      as_bad (_("Can't open macro library file '%s' for reading."), path);
-      as_perror ("%s", path);
+      as_bad (_("can't open macro library file '%s' for reading: %s"),
+             path, bfd_errmsg (bfd_get_error ()));
       ignore_rest_of_line ();
       return;
     }
@@ -2383,18 +2341,18 @@ tic54x_mlib (ignore)
     {
       /* Get a size at least as big as the archive member.  */
       bfd_size_type size = bfd_get_size (mbfd);
-      char *buf = xmalloc (size);
+      char *buf = XNEWVEC (char, size);
       char *fname = tmpnam (NULL);
       FILE *ftmp;
 
       /* We're not sure how big it is, but it will be smaller than "size".  */
-      bfd_read (buf, size, 1, mbfd);
+      size = bfd_bread (buf, size, mbfd);
 
       /* Write to a temporary file, then use s_include to include it
         a bit of a hack.  */
       ftmp = fopen (fname, "w+b");
       fwrite ((void *) buf, size, 1, ftmp);
-      if (buf[size - 1] != '\n')
+      if (size == 0 || buf[size - 1] != '\n')
        fwrite ("\n", 1, 1, ftmp);
       fclose (ftmp);
       free (buf);
@@ -2407,6 +2365,8 @@ const pseudo_typeS md_pseudo_table[] =
 {
   { "algebraic", s_ignore                 ,          0 },
   { "align"    , tic54x_align_words       ,        128 },
+  { "ascii"    , tic54x_stringer          ,        'p' },
+  { "asciz"    , tic54x_stringer          ,        'P' },
   { "even"     , tic54x_align_words       ,          2 },
   { "asg"      , tic54x_asg               ,          0 },
   { "eval"     , tic54x_eval              ,          0 },
@@ -2427,9 +2387,6 @@ const pseudo_typeS md_pseudo_table[] =
   { "emsg"     , tic54x_message           ,        'e' },
   { "mmsg"     , tic54x_message           ,        'm' },
   { "wmsg"     , tic54x_message           ,        'w' },
-#if 0
-  { "end"      , s_end                    ,          0 },
-#endif
   { "far_mode" , tic54x_address_mode      ,   far_mode },
   { "fclist"   , tic54x_fclist            ,          1 },
   { "fcnolist" , tic54x_fclist            ,          0 },
@@ -2455,10 +2412,6 @@ const pseudo_typeS md_pseudo_table[] =
                                                              address.  */
   { "length"   , s_ignore                 ,          0 },
   { "width"    , s_ignore                 ,          0 },
-#if 0
-  { "list"     , listing_list             ,          1 },
-  { "nolist"   , listing_list             ,          0 },
-#endif
   { "long"     , tic54x_cons              ,        'l' },
   { "ulong"    , tic54x_cons              ,        'L' },
   { "xlong"    , tic54x_cons              ,        'x' },
@@ -2472,9 +2425,6 @@ const pseudo_typeS md_pseudo_table[] =
   { "newblock" , tic54x_clear_local_labels,          0 },
   { "option"   , s_ignore                 ,          0 },
   { "p2align"  , tic54x_p2align           ,          0 },
-#if 0
-  { "page"     , listing_eject            ,          0 },
-#endif
   { "sblock"   , tic54x_sblock            ,          0 },
   { "sect"     , tic54x_sect              ,        '*' },
   { "set"      , tic54x_set               ,          0 },
@@ -2490,9 +2440,6 @@ const pseudo_typeS md_pseudo_table[] =
   { "endstruct", tic54x_endstruct         ,          0 },
   { "tab"      , s_ignore                 ,          0 },
   { "text"     , tic54x_sect              ,        't' },
-#if 0
-  { "title"    , listing_title            ,          0 },
-#endif
   { "union"    , tic54x_struct            ,          1 },
   { "endunion" , tic54x_endstruct         ,          1 },
   { "usect"    , tic54x_usect             ,          0 },
@@ -2501,25 +2448,8 @@ const pseudo_typeS md_pseudo_table[] =
   {0           , 0                        ,          0 }
 };
 
-#if 0
-/* For debugging, strings for each operand type.  */
-static const char *optypes[] =
-{
-  "none", "Xmem", "Ymem", "pmad", "dmad", "Smem", "Lmem", "MMR", "PA",
-  "Sind", "xpmad", "xpmad+", "MMRX", "MMRY",
-  "SRC1", "SRC", "RND", "DST",
-  "ARX",
-  "SHIFT", "SHFT",
-  "B", "A", "lk", "TS", "k8", "16", "BITC", "CC", "CC2", "CC3", "123", "031",
-  "k5", "k8u", "ASM", "T", "DP", "ARP", "k3", "lku", "N", "SBIT", "12",
-  "k9", "TRN",
-};
-#endif
-
 int
-md_parse_option (c, arg)
-     int c;
-     char *arg;
+md_parse_option (int c, const char *arg)
 {
   switch (c)
     {
@@ -2528,6 +2458,7 @@ md_parse_option (c, arg)
     case OPTION_COFF_VERSION:
       {
        int version = atoi (arg);
+
        if (version != 0 && version != 1 && version != 2)
          as_fatal (_("Bad COFF version '%s'"), arg);
        /* FIXME -- not yet implemented.  */
@@ -2547,8 +2478,9 @@ md_parse_option (c, arg)
       break;
     case OPTION_STDERR_TO_FILE:
       {
-       char *filename = arg;
+       const char *filename = arg;
        FILE *fp = fopen (filename, "w+");
+
        if (fp == NULL)
          as_fatal (_("Can't redirect stderr to the file '%s'"), filename);
        fclose (fp);
@@ -2567,67 +2499,48 @@ md_parse_option (c, arg)
    deleting the local label hash between macro invocations.  */
 
 void
-tic54x_macro_start ()
+tic54x_macro_start (void)
 {
-  ++macro_level;
-  subsym_hash[macro_level] = hash_new ();
-  local_label_hash[macro_level] = hash_new ();
+  if (++macro_level >= MAX_SUBSYM_HASH)
+    {
+      as_fatal (_("Macro nesting is too deep"));
+      return;
+    }
+  subsym_hash[macro_level] = str_htab_create ();
+  local_label_hash[macro_level] = str_htab_create ();
 }
 
 void
-tic54x_macro_info (info)
-     void *info;
+tic54x_macro_info (const macro_entry *macro)
 {
-  struct formal_struct
-  {
-    struct formal_struct *next;        /* Next formal in list  */
-    sb name;                   /* Name of the formal  */
-    sb def;                    /* The default value  */
-    sb actual;                 /* The actual argument (changed on
-                                   each expansion) */
-    int index;                 /* The index of the formal
-                                   0 .. formal_count - 1 */
-  } *entry;
-  struct macro_struct
-  {
-    sb sub;                    /* Substitution text.  */
-    int formal_count;          /* Number of formal args.  */
-    struct formal_struct *formals;     /* Pointer to list of
-                                           formal_structs.  */
-    struct hash_control *formal_hash; /* Hash table of formals.  */
-  } *macro;
-
-  macro = (struct macro_struct *) info;
+  const formal_entry *entry;
 
   /* Put the formal args into the substitution symbol table.  */
   for (entry = macro->formals; entry; entry = entry->next)
     {
-      char *name = strncpy (xmalloc (entry->name.len + 1),
-                           entry->name.ptr, entry->name.len);
-      char *value = strncpy (xmalloc (entry->actual.len + 1),
-                            entry->actual.ptr, entry->actual.len);
+      char *name = xstrndup (entry->name.ptr, entry->name.len);
+      char *value = xstrndup (entry->actual.ptr, entry->actual.len);
+
       name[entry->name.len] = '\0';
       value[entry->actual.len] = '\0';
-      hash_insert (subsym_hash[macro_level], name, value);
+      str_hash_insert (subsym_hash[macro_level], name, value, 0);
     }
 }
 
 /* Get rid of this macro's .var's, arguments, and local labels.  */
 
 void
-tic54x_macro_end ()
+tic54x_macro_end (void)
 {
-  hash_die (subsym_hash[macro_level]);
+  htab_delete (subsym_hash[macro_level]);
   subsym_hash[macro_level] = NULL;
-  hash_die (local_label_hash[macro_level]);
+  htab_delete (local_label_hash[macro_level]);
   local_label_hash[macro_level] = NULL;
   --macro_level;
 }
 
 static int
-subsym_symlen (a, ignore)
-     char *a;
-     char *ignore ATTRIBUTE_UNUSED;
+subsym_symlen (char *a, char *ignore ATTRIBUTE_UNUSED)
 {
   return strlen (a);
 }
@@ -2635,20 +2548,16 @@ subsym_symlen (a, ignore)
 /* Compare symbol A to string B.  */
 
 static int
-subsym_symcmp (a, b)
-     char *a;
-     char *b;
+subsym_symcmp (char *a, char *b)
 {
   return strcmp (a, b);
 }
 
-/* Return the index of the first occurence of B in A, or zero if none
+/* Return the index of the first occurrence of B in A, or zero if none
    assumes b is an integer char value as a string.  Index is one-based.  */
 
 static int
-subsym_firstch (a, b)
-     char *a;
-     char *b;
+subsym_firstch (char *a, char *b)
 {
   int val = atoi (b);
   char *tmp = strchr (a, val);
@@ -2659,9 +2568,7 @@ subsym_firstch (a, b)
 /* Similar to firstch, but returns index of last occurrence of B in A.  */
 
 static int
-subsym_lastch (a, b)
-     char *a;
-     char *b;
+subsym_lastch (char *a, char *b)
 {
   int val = atoi (b);
   char *tmp = strrchr (a, val);
@@ -2673,9 +2580,7 @@ subsym_lastch (a, b)
    symbol table).  */
 
 static int
-subsym_isdefed (a, ignore)
-     char *a;
-     char *ignore ATTRIBUTE_UNUSED;
+subsym_isdefed (char *a, char *ignore ATTRIBUTE_UNUSED)
 {
   symbolS *symbolP = symbol_find (a);
 
@@ -2687,9 +2592,7 @@ subsym_isdefed (a, ignore)
    symbols, unsubstituted.  */
 
 static int
-subsym_ismember (sym, list)
-     char *sym;
-     char *list;
+subsym_ismember (char *sym, char *list)
 {
   char *elem, *ptr, *listv;
 
@@ -2704,8 +2607,7 @@ subsym_ismember (sym, list)
       return 0;
     }
 
-  ptr = elem = xmalloc (strlen (listv) + 1);
-  strcpy (elem, listv);
+  ptr = elem = xstrdup (listv);
   while (*ptr && *ptr != ',')
     ++ptr;
   *ptr++ = 0;
@@ -2727,19 +2629,17 @@ subsym_ismember (sym, list)
    5 if decimal.  */
 
 static int
-subsym_iscons (a, ignore)
-     char *a;
-     char *ignore ATTRIBUTE_UNUSED;
+subsym_iscons (char *a, char *ignore ATTRIBUTE_UNUSED)
 {
-  expressionS exp;
+  expressionS expn;
 
-  parse_expression (a, &exp);
+  parse_expression (a, &expn);
 
-  if (exp.X_op == O_constant)
+  if (expn.X_op == O_constant)
     {
       int len = strlen (a);
 
-      switch (toupper (a[len - 1]))
+      switch (TOUPPER (a[len - 1]))
        {
        case 'B':
          return 1;
@@ -2755,7 +2655,7 @@ subsym_iscons (a, ignore)
       /* No suffix; either octal, hex, or decimal.  */
       if (*a == '0' && len > 1)
        {
-         if (toupper (a[1]) == 'X')
+         if (TOUPPER (a[1]) == 'X')
            return 3;
          return 2;
        }
@@ -2768,9 +2668,7 @@ subsym_iscons (a, ignore)
 /* Return 1 if A is a valid symbol name.  Expects string input.   */
 
 static int
-subsym_isname (a, ignore)
-     char *a;
-     char *ignore ATTRIBUTE_UNUSED;
+subsym_isname (char *a, char *ignore ATTRIBUTE_UNUSED)
 {
   if (!is_name_beginner (*a))
     return 0;
@@ -2788,25 +2686,22 @@ subsym_isname (a, ignore)
    Note this does not recognize "A" or "B" accumulators.  */
 
 static int
-subsym_isreg (a, ignore)
-     char *a;
-     char *ignore ATTRIBUTE_UNUSED;
+subsym_isreg (char *a, char *ignore ATTRIBUTE_UNUSED)
 {
-  if (hash_find (reg_hash, a))
+  if (str_hash_find (reg_hash, a))
     return 1;
-  if (hash_find (mmreg_hash, a))
+  if (str_hash_find (mmreg_hash, a))
     return 1;
   return 0;
 }
 
-/* Return the structrure size, given the stag.  */
+/* Return the structure size, given the stag.  */
 
 static int
-subsym_structsz (name, ignore)
-     char *name;
-     char *ignore ATTRIBUTE_UNUSED;
+subsym_structsz (char *name, char *ignore ATTRIBUTE_UNUSED)
 {
-  struct stag *stag = (struct stag *) hash_find (stag_hash, name);
+  struct stag *stag = (struct stag *) str_hash_find (stag_hash, name);
+
   if (stag)
     return stag->size;
 
@@ -2821,33 +2716,26 @@ subsym_structsz (name, ignore)
    return zero, we punt and return zero.  */
 
 static int
-subsym_structacc (stag_name, ignore)
-     char *stag_name ATTRIBUTE_UNUSED;
-     char *ignore ATTRIBUTE_UNUSED;
+subsym_structacc (char *stag_name ATTRIBUTE_UNUSED,
+                 char *ignore ATTRIBUTE_UNUSED)
 {
   return 0;
 }
 
 static float
-math_ceil (arg1, ignore)
-     float arg1;
-     float ignore ATTRIBUTE_UNUSED;
+math_ceil (float arg1, float ignore ATTRIBUTE_UNUSED)
 {
   return (float) ceil (arg1);
 }
 
 static float
-math_cvi (arg1, ignore)
-     float arg1;
-     float ignore ATTRIBUTE_UNUSED;
+math_cvi (float arg1, float ignore ATTRIBUTE_UNUSED)
 {
   return (int) arg1;
 }
 
 static float
-math_floor (arg1, ignore)
-     float arg1;
-     float ignore ATTRIBUTE_UNUSED;
+math_floor (float arg1, float ignore ATTRIBUTE_UNUSED)
 {
   return (float) floor (arg1);
 }
@@ -2859,57 +2747,43 @@ math_fmod (float arg1, float arg2)
 }
 
 static float
-math_int (arg1, ignore)
-     float arg1;
-     float ignore ATTRIBUTE_UNUSED;
+math_int (float arg1, float ignore ATTRIBUTE_UNUSED)
 {
   return ((float) ((int) arg1)) == arg1;
 }
 
 static float
-math_round (arg1, ignore)
-     float arg1;
-     float ignore ATTRIBUTE_UNUSED;
+math_round (float arg1, float ignore ATTRIBUTE_UNUSED)
 {
   return arg1 > 0 ? (int) (arg1 + 0.5) : (int) (arg1 - 0.5);
 }
 
 static float
-math_sgn (arg1, ignore)
-     float arg1;
-     float ignore ATTRIBUTE_UNUSED;
+math_sgn (float arg1, float ignore ATTRIBUTE_UNUSED)
 {
   return (arg1 < 0) ? -1 : (arg1 ? 1 : 0);
 }
 
 static float
-math_trunc (arg1, ignore)
-     float arg1;
-     float ignore ATTRIBUTE_UNUSED;
+math_trunc (float arg1, float ignore ATTRIBUTE_UNUSED)
 {
   return (int) arg1;
 }
 
 static float
-math_acos (arg1, ignore)
-     float arg1;
-     float ignore ATTRIBUTE_UNUSED;
+math_acos (float arg1, float ignore ATTRIBUTE_UNUSED)
 {
   return (float) acos (arg1);
 }
 
 static float
-math_asin (arg1, ignore)
-     float arg1;
-     float ignore ATTRIBUTE_UNUSED;
+math_asin (float arg1, float ignore ATTRIBUTE_UNUSED)
 {
   return (float) asin (arg1);
 }
 
 static float
-math_atan (arg1, ignore)
-     float arg1;
-     float ignore ATTRIBUTE_UNUSED;
+math_atan (float arg1, float ignore ATTRIBUTE_UNUSED)
 {
   return (float) atan (arg1);
 }
@@ -2921,41 +2795,31 @@ math_atan2 (float arg1, float arg2)
 }
 
 static float
-math_cosh (arg1, ignore)
-     float arg1;
-     float ignore ATTRIBUTE_UNUSED;
+math_cosh (float arg1, float ignore ATTRIBUTE_UNUSED)
 {
   return (float) cosh (arg1);
 }
 
 static float
-math_cos (arg1, ignore)
-     float arg1;
-     float ignore ATTRIBUTE_UNUSED;
+math_cos (float arg1, float ignore ATTRIBUTE_UNUSED)
 {
   return (float) cos (arg1);
 }
 
 static float
-math_cvf (arg1, ignore)
-     float arg1;
-     float ignore ATTRIBUTE_UNUSED;
+math_cvf (float arg1, float ignore ATTRIBUTE_UNUSED)
 {
   return (float) arg1;
 }
 
 static float
-math_exp (arg1, ignore)
-     float arg1;
-     float ignore ATTRIBUTE_UNUSED;
+math_exp (float arg1, float ignore ATTRIBUTE_UNUSED)
 {
   return (float) exp (arg1);
 }
 
 static float
-math_fabs (arg1, ignore)
-     float arg1;
-     float ignore ATTRIBUTE_UNUSED;
+math_fabs (float arg1, float ignore ATTRIBUTE_UNUSED)
 {
   return (float) fabs (arg1);
 }
@@ -2969,17 +2833,13 @@ math_ldexp (float arg1, float arg2)
 }
 
 static float
-math_log10 (arg1, ignore)
-     float arg1;
-     float ignore ATTRIBUTE_UNUSED;
+math_log10 (float arg1, float ignore ATTRIBUTE_UNUSED)
 {
   return (float) log10 (arg1);
 }
 
 static float
-math_log (arg1, ignore)
-     float arg1;
-     float ignore ATTRIBUTE_UNUSED;
+math_log (float arg1, float ignore ATTRIBUTE_UNUSED)
 {
   return (float) log (arg1);
 }
@@ -3003,41 +2863,31 @@ math_pow (float arg1, float arg2)
 }
 
 static float
-math_sin (arg1, ignore)
-     float arg1;
-     float ignore ATTRIBUTE_UNUSED;
+math_sin (float arg1, float ignore ATTRIBUTE_UNUSED)
 {
   return (float) sin (arg1);
 }
 
 static float
-math_sinh (arg1, ignore)
-     float arg1;
-     float ignore ATTRIBUTE_UNUSED;
+math_sinh (float arg1, float ignore ATTRIBUTE_UNUSED)
 {
   return (float) sinh (arg1);
 }
 
 static float
-math_sqrt (arg1, ignore)
-     float arg1;
-     float ignore ATTRIBUTE_UNUSED;
+math_sqrt (float arg1, float ignore ATTRIBUTE_UNUSED)
 {
   return (float) sqrt (arg1);
 }
 
 static float
-math_tan (arg1, ignore)
-     float arg1;
-     float ignore ATTRIBUTE_UNUSED;
+math_tan (float arg1, float ignore ATTRIBUTE_UNUSED)
 {
   return (float) tan (arg1);
 }
 
 static float
-math_tanh (arg1, ignore)
-     float arg1;
-     float ignore ATTRIBUTE_UNUSED;
+math_tanh (float arg1, float ignore ATTRIBUTE_UNUSED)
 {
   return (float) tanh (arg1);
 }
@@ -3045,7 +2895,7 @@ math_tanh (arg1, ignore)
 /* Built-in substitution symbol functions and math functions.  */
 typedef struct
 {
-  char *name;
+  const char *name;
   int (*proc) (char *, char *);
   int nargs;
 } subsym_proc_entry;
@@ -3069,7 +2919,7 @@ static const subsym_proc_entry subsym_procs[] =
 
 typedef struct
 {
-  char *name;
+  const char *name;
   float (*proc) (float, float);
   int nargs;
   int int_return;
@@ -3112,27 +2962,27 @@ static const math_proc_entry math_procs[] =
 };
 
 void
-md_begin ()
+md_begin (void)
 {
-  template *opcode;
-  partemplate *paropcode;
-  symbol *sym;
+  insn_template *tm;
+  tic54x_symbol *sym;
   const subsym_proc_entry *subsym_proc;
   const math_proc_entry *math_proc;
-  const char *hash_err;
   char **symname;
   char *TIC54X_DIR = getenv ("TIC54X_DIR");
   char *A_DIR = TIC54X_DIR ? TIC54X_DIR : getenv ("A_DIR");
 
   local_label_id = 0;
 
-  /* Look for A_DIR and add it to the include list.  */
+  /* Look for A_DIR and add it to the include list.  */
   if (A_DIR != NULL)
     {
       char *tmp = xstrdup (A_DIR);
+
       do
        {
          char *next = strchr (tmp, ';');
+
          if (next)
            *next++ = '\0';
          add_include_dir (tmp);
@@ -3141,136 +2991,71 @@ md_begin ()
       while (tmp != NULL);
     }
 
-  op_hash = hash_new ();
-  for (opcode = (template *) tic54x_optab; opcode->name; opcode++)
-    {
-      if (hash_find (op_hash, opcode->name))
-       continue;
-      hash_err = hash_insert (op_hash, opcode->name, (char *) opcode);
-      if (hash_err)
-       as_fatal ("Internal Error: Can't hash %s: %s",
-                 opcode->name, hash_err);
-    }
-  parop_hash = hash_new ();
-  for (paropcode = (partemplate *) tic54x_paroptab;
-       paropcode->name;
-       paropcode++)
-    {
-      if (hash_find (parop_hash, paropcode->name))
-       continue;
-      hash_err = hash_insert (parop_hash, paropcode->name, (char *) paropcode);
-      if (hash_err)
-       as_fatal ("Internal Error: Can't hash %s: %s",
-                 paropcode->name, hash_err);
-    }
-  reg_hash = hash_new ();
-  for (sym = (symbol *) regs; sym->name; sym++)
+  op_hash = str_htab_create ();
+  for (tm = (insn_template *) tic54x_optab; tm->name; tm++)
+    str_hash_insert (op_hash, tm->name, tm, 0);
+
+  parop_hash = str_htab_create ();
+  for (tm = (insn_template *) tic54x_paroptab; tm->name; tm++)
+    str_hash_insert (parop_hash, tm->name, tm, 0);
+
+  reg_hash = str_htab_create ();
+  for (sym = (tic54x_symbol *) regs; sym->name; sym++)
     {
       /* Add basic registers to the symbol table.  */
       symbolS *symbolP = symbol_new (sym->name, absolute_section,
-                                    (valueT) sym->value, &zero_address_frag);
+                                    &zero_address_frag, sym->value);
       SF_SET_LOCAL (symbolP);
       symbol_table_insert (symbolP);
-      hash_err = hash_insert (reg_hash, sym->name, (char *) sym);
-    }
-  for (sym = (symbol *) mmregs; sym->name; sym++)
-    hash_err = hash_insert (reg_hash, sym->name, (char *) sym);
-  mmreg_hash = hash_new ();
-  for (sym = (symbol *) mmregs; sym->name; sym++)
-    {
-      hash_err = hash_insert (mmreg_hash, sym->name, (char *) sym);
-    }
-  cc_hash = hash_new ();
-  for (sym = (symbol *) condition_codes; sym->name; sym++)
-    {
-      hash_err = hash_insert (cc_hash, sym->name, (char *) sym);
-    }
-  cc2_hash = hash_new ();
-  for (sym = (symbol *) cc2_codes; sym->name; sym++)
-    {
-      hash_err = hash_insert (cc2_hash, sym->name, (char *) sym);
-    }
-  cc3_hash = hash_new ();
-  for (sym = (symbol *) cc3_codes; sym->name; sym++)
-    {
-      hash_err = hash_insert (cc3_hash, sym->name, (char *) sym);
+      str_hash_insert (reg_hash, sym->name, sym, 0);
     }
-  sbit_hash = hash_new ();
-  for (sym = (symbol *) status_bits; sym->name; sym++)
-    {
-      hash_err = hash_insert (sbit_hash, sym->name, (char *) sym);
-    }
-  misc_symbol_hash = hash_new ();
+  for (sym = (tic54x_symbol *) mmregs; sym->name; sym++)
+    str_hash_insert (reg_hash, sym->name, sym, 0);
+  mmreg_hash = str_htab_create ();
+  for (sym = (tic54x_symbol *) mmregs; sym->name; sym++)
+    str_hash_insert (mmreg_hash, sym->name, sym, 0);
+
+  cc_hash = str_htab_create ();
+  for (sym = (tic54x_symbol *) condition_codes; sym->name; sym++)
+    str_hash_insert (cc_hash, sym->name, sym, 0);
+
+  cc2_hash = str_htab_create ();
+  for (sym = (tic54x_symbol *) cc2_codes; sym->name; sym++)
+    str_hash_insert (cc2_hash, sym->name, sym, 0);
+
+  cc3_hash = str_htab_create ();
+  for (sym = (tic54x_symbol *) cc3_codes; sym->name; sym++)
+    str_hash_insert (cc3_hash, sym->name, sym, 0);
+
+  sbit_hash = str_htab_create ();
+  for (sym = (tic54x_symbol *) status_bits; sym->name; sym++)
+    str_hash_insert (sbit_hash, sym->name, sym, 0);
+
+  misc_symbol_hash = str_htab_create ();
   for (symname = (char **) misc_symbols; *symname; symname++)
-    {
-      hash_err = hash_insert (misc_symbol_hash, *symname, *symname);
-    }
+    str_hash_insert (misc_symbol_hash, *symname, *symname, 0);
+
   /* Only the base substitution table and local label table are initialized;
      the others (for local macro substitution) get instantiated as needed.  */
-  local_label_hash[0] = hash_new ();
-  subsym_hash[0] = hash_new ();
+  local_label_hash[0] = str_htab_create ();
+  subsym_hash[0] = str_htab_create ();
   for (subsym_proc = subsym_procs; subsym_proc->name; subsym_proc++)
-    {
-      hash_err = hash_insert (subsym_hash[0], subsym_proc->name,
-                             (char *) subsym_proc);
-    }
-  math_hash = hash_new ();
+    str_hash_insert (subsym_hash[0], subsym_proc->name, subsym_proc, 0);
+
+  math_hash = str_htab_create ();
   for (math_proc = math_procs; math_proc->name; math_proc++)
     {
       /* Insert into the main subsym hash for recognition; insert into
         the math hash to actually store information.  */
-      hash_err = hash_insert (subsym_hash[0], math_proc->name,
-                             (char *) math_proc);
-      hash_err = hash_insert (math_hash, math_proc->name,
-                             (char *) math_proc);
+      str_hash_insert (subsym_hash[0], math_proc->name, math_proc, 0);
+      str_hash_insert (math_hash, math_proc->name, math_proc, 0);
     }
-  subsym_recurse_hash = hash_new ();
-  stag_hash = hash_new ();
+  subsym_recurse_hash = str_htab_create ();
+  stag_hash = str_htab_create ();
 }
 
-typedef struct _tic54x_insn
-{
-  const template *tm;         /* Opcode template.  */
-  const partemplate *ptm;         /* Parallel opcode template.  */
-
-  char mnemonic[MAX_LINE];       /* Opcode name/mnemonic.  */
-  char parmnemonic[MAX_LINE];       /* 2nd mnemonic of parallel insn.  */
-
-  int opcount;
-  struct opstruct
-  {
-    char buf[MAX_LINE];
-    enum optype type;
-    expressionS exp;
-  } operands[MAX_OPERANDS];
-
-  int paropcount;
-  struct opstruct paroperands[MAX_OPERANDS];
-
-  int is_lkaddr;
-  int lkoperand;
-  int words;                   /* Size of insn in 16-bit words.  */
-  int using_default_dst;           /* Do we need to explicitly set an
-                                      omitted OP_DST operand?  */
-  struct
-  {
-    unsigned short word;           /* Final encoded opcode data.  */
-    int unresolved;
-    int r_nchars;                   /* Relocation size.  */
-    bfd_reloc_code_real_type r_type; /* Relocation type.  */
-    expressionS addr_expr;       /* Storage for unresolved expressions.  */
-  } opcode[3];
-} tic54x_insn;
-
-static int encode_operand (tic54x_insn *, enum optype, struct opstruct *);
-static int encode_dmad (tic54x_insn *, struct opstruct *, int);
-static int operands_match (tic54x_insn *, struct opstruct *, int,
-                          const enum optype *, int, int);
-static int encode_address (tic54x_insn *, struct opstruct *);
-
 static int
-is_accumulator (operand)
-     struct opstruct *operand;
+is_accumulator (struct opstruct *operand)
 {
   return strcasecmp (operand->buf, "a") == 0
     || strcasecmp (operand->buf, "b") == 0;
@@ -3281,20 +3066,19 @@ is_accumulator (operand)
    the next array.  */
 
 static int
-get_operands (operands, line)
-     struct opstruct operands[];
-     char *line;
+get_operands (struct opstruct operands[], char *line)
 {
   char *lptr = line;
   int numexp = 0;
   int expecting_operand = 0;
   int i;
 
-  while (numexp < MAX_OPERANDS && !is_end_of_line[(int) *lptr])
+  while (numexp < MAX_OPERANDS && !is_end_of_line[(unsigned char) *lptr])
     {
       int paren_not_balanced = 0;
       char *op_start, *op_end;
-      while (*lptr && isspace (*lptr))
+
+      while (*lptr && ISSPACE (*lptr))
        ++lptr;
       op_start = lptr;
       while (paren_not_balanced || *lptr != ',')
@@ -3303,7 +3087,7 @@ get_operands (operands, line)
            {
              if (paren_not_balanced)
                {
-                 as_bad ("Unbalanced parenthesis in operand %d", numexp);
+                 as_bad (_("Unbalanced parenthesis in operand %d"), numexp);
                  return -1;
                }
              else
@@ -3319,12 +3103,13 @@ get_operands (operands, line)
       if (op_end != op_start)
        {
          int len = op_end - op_start;
+
          strncpy (operands[numexp].buf, op_start, len);
          operands[numexp].buf[len] = 0;
          /* Trim trailing spaces; while the preprocessor gets rid of most,
             there are weird usage patterns that can introduce them
             (i.e. using strings for macro args).  */
-         while (len > 0 && isspace (operands[numexp].buf[len - 1]))
+         while (len > 0 && ISSPACE (operands[numexp].buf[len - 1]))
            operands[numexp].buf[--len] = 0;
          lptr = op_end;
          ++numexp;
@@ -3333,7 +3118,7 @@ get_operands (operands, line)
        {
          if (expecting_operand || *lptr == ',')
            {
-             as_bad ("Expecting operand after ','");
+             as_bad (_("Expecting operand after ','"));
              return -1;
            }
        }
@@ -3341,18 +3126,18 @@ get_operands (operands, line)
        {
          if (*++lptr == '\0')
            {
-             as_bad ("Expecting operand after ','");
+             as_bad (_("Expecting operand after ','"));
              return -1;
            }
          expecting_operand = 1;
        }
     }
 
-  while (*lptr && isspace (*lptr++))
+  while (*lptr && ISSPACE (*lptr++))
     ;
-  if (!is_end_of_line[(int) *lptr])
+  if (!is_end_of_line[(unsigned char) *lptr])
     {
-      as_bad ("Extra junk on line");
+      as_bad (_("Extra junk on line"));
       return -1;
     }
 
@@ -3374,6 +3159,7 @@ get_operands (operands, line)
        {
          /* Indirect.  */
          char *paren = strchr (operands[i].buf, '(');
+
          /* Allow immediate syntax in the inner expression.  */
          if (paren && paren[1] == '#')
            *++paren = '(';
@@ -3384,6 +3170,7 @@ get_operands (operands, line)
              int len = strlen (paren);
              char *end = paren + len;
              int c;
+
              while (end[-1] != ')')
                if (--end <= paren)
                  {
@@ -3408,8 +3195,7 @@ get_operands (operands, line)
 /* Predicates for different operand types.  */
 
 static int
-is_immediate (operand)
-     struct opstruct *operand;
+is_immediate (struct opstruct *operand)
 {
   return *operand->buf == '#';
 }
@@ -3418,8 +3204,7 @@ is_immediate (operand)
    and must *not* have the '#' prefix.  */
 
 static int
-is_absolute (operand)
-     struct opstruct *operand;
+is_absolute (struct opstruct *operand)
 {
   return operand->exp.X_op == O_constant && !is_immediate (operand);
 }
@@ -3427,8 +3212,7 @@ is_absolute (operand)
 /* Is this an indirect operand?  */
 
 static int
-is_indirect (operand)
-     struct opstruct *operand;
+is_indirect (struct opstruct *operand)
 {
   return operand->buf[0] == '*';
 }
@@ -3436,8 +3220,7 @@ is_indirect (operand)
 /* Is this a valid dual-memory operand?  */
 
 static int
-is_dual (operand)
-     struct opstruct *operand;
+is_dual (struct opstruct *operand)
 {
   if (is_indirect (operand) && strncasecmp (operand->buf, "*ar", 3) == 0)
     {
@@ -3457,18 +3240,15 @@ is_dual (operand)
 }
 
 static int
-is_mmreg (operand)
-     struct opstruct *operand;
+is_mmreg (struct opstruct *operand)
 {
   return (is_absolute (operand)
          || is_immediate (operand)
-         || hash_find (mmreg_hash, operand->buf) != 0);
+         || str_hash_find (mmreg_hash, operand->buf) != 0);
 }
 
 static int
-is_type (operand, type)
-     struct opstruct *operand;
-     enum optype type;
+is_type (struct opstruct *operand, enum optype type)
 {
   switch (type)
     {
@@ -3501,20 +3281,20 @@ is_type (operand, type)
     case OP_DST:
       return is_accumulator (operand);
     case OP_B:
-      return is_accumulator (operand) && toupper (operand->buf[0]) == 'B';
+      return is_accumulator (operand) && TOUPPER (operand->buf[0]) == 'B';
     case OP_A:
-      return is_accumulator (operand) && toupper (operand->buf[0]) == 'A';
+      return is_accumulator (operand) && TOUPPER (operand->buf[0]) == 'A';
     case OP_ARX:
       return strncasecmp ("ar", operand->buf, 2) == 0
-       && isdigit (operand->buf[2]);
+       && ISDIGIT (operand->buf[2]);
     case OP_SBIT:
-      return hash_find (sbit_hash, operand->buf) != 0 || is_absolute (operand);
+      return str_hash_find (sbit_hash, operand->buf) != 0 || is_absolute (operand);
     case OP_CC:
-      return hash_find (cc_hash, operand->buf) != 0;
+      return str_hash_find (cc_hash, operand->buf) != 0;
     case OP_CC2:
-      return hash_find (cc2_hash, operand->buf) != 0;
+      return str_hash_find (cc2_hash, operand->buf) != 0;
     case OP_CC3:
-      return hash_find (cc3_hash, operand->buf) != 0
+      return str_hash_find (cc3_hash, operand->buf) != 0
        || is_immediate (operand) || is_absolute (operand);
     case OP_16:
       return (is_immediate (operand) || is_absolute (operand))
@@ -3572,19 +3352,17 @@ is_type (operand, type)
 }
 
 static int
-operands_match (insn, operands, opcount, refoptype, minops, maxops)
-     tic54x_insn *insn;
-     struct opstruct *operands;
-     int opcount;
-     const enum optype *refoptype;
-     int minops, maxops;
+operands_match (tic54x_insn *insn,
+               struct opstruct *operands,
+               int opcount,
+               const enum optype *refoptype,
+               int minops,
+               int maxops)
 {
   int op = 0, refop = 0;
 
   if (opcount == 0 && minops == 0)
-    {
-      return 1;
-    }
+    return 1;
 
   while (op <= maxops && refop <= maxops)
     {
@@ -3642,10 +3420,7 @@ operands_match (insn, operands, opcount, refoptype, minops, maxops)
    2 for the upper 7 bits of a 23-bit address (LDX).  */
 
 static int
-encode_dmad (insn, operand, xpc_code)
-     tic54x_insn *insn;
-     struct opstruct *operand;
-     int xpc_code;
+encode_dmad (tic54x_insn *insn, struct opstruct *operand, int xpc_code)
 {
   int op = 1 + insn->is_lkaddr;
 
@@ -3661,6 +3436,7 @@ encode_dmad (insn, operand, xpc_code)
   if (insn->opcode[op].addr_expr.X_op == O_constant)
     {
       valueT value = insn->opcode[op].addr_expr.X_add_number;
+
       if (xpc_code == 1)
        {
          insn->opcode[0].word &= 0xFF80;
@@ -3705,9 +3481,7 @@ encode_dmad (insn, operand, xpc_code)
 /* 7-bit direct address encoding.  */
 
 static int
-encode_address (insn, operand)
-     tic54x_insn *insn;
-     struct opstruct *operand;
+encode_address (tic54x_insn *insn, struct opstruct *operand)
 {
   /* Assumes that dma addresses are *always* in word 0 of the opcode.  */
   insn->opcode[0].addr_expr = operand->exp;
@@ -3716,6 +3490,8 @@ encode_address (insn, operand)
     insn->opcode[0].word |= (operand->exp.X_add_number & 0x7F);
   else
     {
+      if (operand->exp.X_op == O_register)
+        as_bad (_("Use the .mmregs directive to use memory-mapped register names such as '%s'"), operand->buf);
       /* Do the fixup later; just store the expression.  */
       insn->opcode[0].r_nchars = 1;
       insn->opcode[0].r_type = BFD_RELOC_TIC54X_PARTLS7;
@@ -3726,9 +3502,7 @@ encode_address (insn, operand)
 }
 
 static int
-encode_indirect (insn, operand)
-     tic54x_insn *insn;
-     struct opstruct *operand;
+encode_indirect (tic54x_insn *insn, struct opstruct *operand)
 {
   int arf;
   int mod;
@@ -3736,7 +3510,7 @@ encode_indirect (insn, operand)
   if (insn->is_lkaddr)
     {
       /* lk addresses always go in the second insn word.  */
-      mod = ((toupper (operand->buf[1]) == 'A') ? 12 :
+      mod = ((TOUPPER (operand->buf[1]) == 'A') ? 12 :
             (operand->buf[1] == '(') ? 15 :
             (strchr (operand->buf, '%') != NULL) ? 14 : 13);
       arf = ((mod == 12) ? operand->buf[3] - '0' :
@@ -3761,7 +3535,7 @@ encode_indirect (insn, operand)
     }
   else
     {
-      arf = (toupper (operand->buf[1]) == 'A' ?
+      arf = (TOUPPER (operand->buf[1]) == 'A' ?
             operand->buf[3] : operand->buf[4]) - '0';
 
       if (operand->buf[1] == '+')
@@ -3782,9 +3556,9 @@ encode_indirect (insn, operand)
          else
            mod = (operand->buf[4] == '-' ? 8 : 10);/* *ARx+% / *ARx-%  */
        }
-      else if (toupper (operand->buf[6]) == 'B')
+      else if (TOUPPER (operand->buf[6]) == 'B')
        mod = (operand->buf[4] == '-' ? 4 : 7); /* ARx+0B / *ARx-0B  */
-      else if (toupper (operand->buf[6]) == '%')
+      else if (TOUPPER (operand->buf[6]) == '%')
        mod = (operand->buf[4] == '-' ? 9 : 11); /* ARx+0% / *ARx - 0%  */
       else
        {
@@ -3800,11 +3574,12 @@ encode_indirect (insn, operand)
 }
 
 static int
-encode_integer (insn, operand, which, min, max, mask)
-     tic54x_insn *insn;
-     struct opstruct *operand;
-     int which, min, max;
-     unsigned short mask;
+encode_integer (tic54x_insn *insn,
+               struct opstruct *operand,
+               int which,
+               int min,
+               int max,
+               unsigned short mask)
 {
   long parse, integer;
 
@@ -3859,11 +3634,9 @@ encode_integer (insn, operand, which, min, max, mask)
 }
 
 static int
-encode_condition (insn, operand)
-     tic54x_insn *insn;
-     struct opstruct *operand;
+encode_condition (tic54x_insn *insn, struct opstruct *operand)
 {
-  symbol *cc = (symbol *) hash_find (cc_hash, operand->buf);
+  tic54x_symbol *cc = (tic54x_symbol *) str_hash_find (cc_hash, operand->buf);
   if (!cc)
     {
       as_bad (_("Unrecognized condition code \"%s\""), operand->buf);
@@ -3907,9 +3680,9 @@ encode_condition (insn, operand)
              return 0;
            }
        }
-      else if (((insn->opcode[0].word & CATG_A2) && (cc->value & CATG_A2)) ||
-              ((insn->opcode[0].word & CATG_B2) && (cc->value & CATG_B2)) ||
-              ((insn->opcode[0].word & CATG_C2) && (cc->value & CATG_C2)))
+      else if (   ((insn->opcode[0].word & CATG_A2) && (cc->value & CATG_A2))
+              || ((insn->opcode[0].word & CATG_B2) && (cc->value & CATG_B2))
+              || ((insn->opcode[0].word & CATG_C2) && (cc->value & CATG_C2)))
        {
          as_bad (_("Duplicate %s conditional"), operand->buf);
          return 0;
@@ -3921,11 +3694,9 @@ encode_condition (insn, operand)
 }
 
 static int
-encode_cc3 (insn, operand)
-     tic54x_insn *insn;
-     struct opstruct *operand;
+encode_cc3 (tic54x_insn *insn, struct opstruct *operand)
 {
-  symbol *cc3 = (symbol *) hash_find (cc3_hash, operand->buf);
+  tic54x_symbol *cc3 = (tic54x_symbol *) str_hash_find (cc3_hash, operand->buf);
   int value = cc3 ? cc3->value : operand->exp.X_add_number << 8;
 
   if ((value & 0x0300) != value)
@@ -3938,11 +3709,10 @@ encode_cc3 (insn, operand)
 }
 
 static int
-encode_arx (insn, operand)
-     tic54x_insn *insn;
-     struct opstruct *operand;
+encode_arx (tic54x_insn *insn, struct opstruct *operand)
 {
   int arf = strlen (operand->buf) >= 3 ? operand->buf[2] - '0' : -1;
+
   if (strncasecmp ("ar", operand->buf, 2) || arf < 0 || arf > 7)
     {
       as_bad (_("Invalid auxiliary register (use AR0-AR7)"));
@@ -3953,11 +3723,10 @@ encode_arx (insn, operand)
 }
 
 static int
-encode_cc2 (insn, operand)
-     tic54x_insn *insn;
-     struct opstruct *operand;
+encode_cc2 (tic54x_insn *insn, struct opstruct *operand)
 {
-  symbol *cc2 = (symbol *) hash_find (cc2_hash, operand->buf);
+  tic54x_symbol *cc2 = (tic54x_symbol *) str_hash_find (cc2_hash, operand->buf);
+
   if (!cc2)
     {
       as_bad (_("Unrecognized condition code \"%s\""), operand->buf);
@@ -3968,12 +3737,9 @@ encode_cc2 (insn, operand)
 }
 
 static int
-encode_operand (insn, type, operand)
-     tic54x_insn *insn;
-     enum optype type;
-     struct opstruct *operand;
+encode_operand (tic54x_insn *insn, enum optype type, struct opstruct *operand)
 {
-  int ext = insn->tm && ((insn->tm->flags & FL_EXT) != 0);
+  int ext = (insn->tm->flags & FL_EXT) != 0;
 
   if (type == OP_MMR && operand->exp.X_op != O_constant)
     {
@@ -4002,7 +3768,7 @@ encode_operand (insn, type, operand)
       /* 16-bit immediate value.  */
       return encode_dmad (insn, operand, 0);
     case OP_SRC:
-      if (toupper (*operand->buf) == 'B')
+      if (TOUPPER (*operand->buf) == 'B')
        {
          insn->opcode[ext ? (1 + insn->is_lkaddr) : 0].word |= (1 << 9);
          if (insn->using_default_dst)
@@ -4010,8 +3776,8 @@ encode_operand (insn, type, operand)
        }
       return 1;
     case OP_RND:
-      /* Make sure this agrees with with the OP_DST operand.  */
-      if (!((toupper (operand->buf[0]) == 'B') ^
+      /* Make sure this agrees with the OP_DST operand.  */
+      if (!((TOUPPER (operand->buf[0]) == 'B') ^
            ((insn->opcode[0].word & (1 << 8)) != 0)))
        {
          as_bad (_("Destination accumulator for each part of this parallel "
@@ -4021,7 +3787,7 @@ encode_operand (insn, type, operand)
       return 1;
     case OP_SRC1:
     case OP_DST:
-      if (toupper (operand->buf[0]) == 'B')
+      if (TOUPPER (operand->buf[0]) == 'B')
        insn->opcode[ext ? (1 + insn->is_lkaddr) : 0].word |= (1 << 8);
       return 1;
     case OP_Xmem:
@@ -4118,7 +3884,8 @@ encode_operand (insn, type, operand)
                             0, 65535, 0xFFFF);
     case OP_SBIT:
       {
-       symbol *sbit = (symbol *) hash_find (sbit_hash, operand->buf);
+       tic54x_symbol *sbit = (tic54x_symbol *)
+         str_hash_find (sbit_hash, operand->buf);
        int value = is_absolute (operand) ?
          operand->exp.X_add_number : (sbit ? sbit->value : -1);
        int reg = 0;
@@ -4132,7 +3899,7 @@ encode_operand (insn, type, operand)
              }
            /* Guess the register based on the status bit; "ovb" is the last
               status bit defined for st0.  */
-           if (sbit > (symbol *) hash_find (sbit_hash, "ovb"))
+           if (sbit > (tic54x_symbol *) str_hash_find (sbit_hash, "ovb"))
              reg = 1;
          }
        if (value == -1)
@@ -4194,10 +3961,16 @@ encode_operand (insn, type, operand)
 }
 
 static void
-emit_insn (insn)
-     tic54x_insn *insn;
+emit_insn (tic54x_insn *insn)
 {
   int i;
+  flagword oldflags = bfd_section_flags (now_seg);
+  flagword flags = oldflags | SEC_CODE;
+
+  if (!bfd_set_section_flags (now_seg, flags))
+        as_warn (_("error setting flags for \"%s\": %s"),
+                 bfd_section_name (now_seg),
+                 bfd_errmsg (bfd_get_error ()));
 
   for (i = 0; i < insn->words; i++)
     {
@@ -4213,7 +3986,7 @@ emit_insn (insn)
       if (insn->opcode[i].unresolved)
        fix_new_exp (frag_now, p - frag_now->fr_literal,
                     insn->opcode[i].r_nchars, &insn->opcode[i].addr_expr,
-                    false, insn->opcode[i].r_type);
+                    FALSE, insn->opcode[i].r_type);
     }
 }
 
@@ -4221,13 +3994,12 @@ emit_insn (insn)
    return the total number of words used by the instruction.  */
 
 static int
-build_insn (insn)
-     tic54x_insn *insn;
+build_insn (tic54x_insn *insn)
 {
   int i;
 
   /* Only non-parallel instructions support lk addressing.  */
-  if (insn->tm)
+  if (!(insn->tm->flags & FL_PAR))
     {
       for (i = 0; i < insn->opcount; i++)
        {
@@ -4244,23 +4016,24 @@ build_insn (insn)
            }
        }
     }
-  insn->words =
-    (insn->tm ? insn->tm->words : insn->ptm->words) + insn->is_lkaddr;
+  insn->words = insn->tm->words + insn->is_lkaddr;
 
-  insn->opcode[0].word = insn->tm ? insn->tm->opcode : insn->ptm->opcode;
-  if (insn->tm && (insn->tm->flags & FL_EXT))
+  insn->opcode[0].word = insn->tm->opcode;
+  if (insn->tm->flags & FL_EXT)
     insn->opcode[1 + insn->is_lkaddr].word = insn->tm->opcode2;
 
   for (i = 0; i < insn->opcount; i++)
     {
       enum optype type = insn->operands[i].type;
+
       if (!encode_operand (insn, type, &insn->operands[i]))
        return 0;
     }
-  if (insn->ptm)
+  if (insn->tm->flags & FL_PAR)
     for (i = 0; i < insn->paropcount; i++)
       {
        enum optype partype = insn->paroperands[i].type;
+
        if (!encode_operand (insn, partype, &insn->paroperands[i]))
          return 0;
       }
@@ -4271,8 +4044,7 @@ build_insn (insn)
 }
 
 static int
-optimize_insn (insn)
-     tic54x_insn *insn;
+optimize_insn (tic54x_insn *insn)
 {
   /* Optimize some instructions, helping out the brain-dead programmer.  */
 #define is_zero(op) ((op).exp.X_op == O_constant && (op).exp.X_add_number == 0)
@@ -4347,10 +4119,10 @@ optimize_insn (insn)
          return 1;
        }
 
-      if (((OPTYPE (insn->tm->operand_types[0]) == OP_Smem
+      if (   ((OPTYPE (insn->tm->operand_types[0]) == OP_Smem
            && OPTYPE (insn->tm->operand_types[1]) == OP_SHIFT)
           || (OPTYPE (insn->tm->operand_types[0]) == OP_Xmem
-              && OPTYPE (insn->tm->operand_types[1]) == OP_SHFT))
+           && OPTYPE (insn->tm->operand_types[1]) == OP_SHFT))
          && is_zero (insn->operands[1])
          && insn->opcount == 3)
        {
@@ -4365,11 +4137,9 @@ optimize_insn (insn)
 /* Find a matching template if possible, and get the operand strings.  */
 
 static int
-tic54x_parse_insn (insn, line)
-     tic54x_insn *insn;
-     char *line;
+tic54x_parse_insn (tic54x_insn *insn, char *line)
 {
-  insn->tm = (template *) hash_find (op_hash, insn->mnemonic);
+  insn->tm = (insn_template *) str_hash_find (op_hash, insn->mnemonic);
   if (!insn->tm)
     {
       as_bad (_("Unrecognized instruction \"%s\""), insn->mnemonic);
@@ -4392,8 +4162,8 @@ tic54x_parse_insn (insn, line)
          /* SUCCESS! now try some optimizations.  */
          if (optimize_insn (insn))
            {
-             insn->tm = (template *) hash_find (op_hash,
-                                                insn->mnemonic);
+             insn->tm = (insn_template *) str_hash_find (op_hash,
+                                                         insn->mnemonic);
              continue;
            }
 
@@ -4414,11 +4184,10 @@ static int parallel_on_next_line_hint = 0;
    Look for a subsequent line starting with "||".  */
 
 static int
-next_line_shows_parallel (next_line)
-     char *next_line;
+next_line_shows_parallel (char *next_line)
 {
   /* Look for the second half.  */
-  while (isspace (*next_line))
+  while (*next_line != 0 && ISSPACE (*next_line))
     ++next_line;
 
   return (next_line[0] == PARALLEL_SEPARATOR
@@ -4426,31 +4195,29 @@ next_line_shows_parallel (next_line)
 }
 
 static int
-tic54x_parse_parallel_insn_firstline (insn, line)
-     tic54x_insn *insn;
-     char *line;
+tic54x_parse_parallel_insn_firstline (tic54x_insn *insn, char *line)
 {
-  insn->ptm = (partemplate *) hash_find (parop_hash, insn->mnemonic);
-  if (!insn->ptm)
+  insn->tm = (insn_template *) str_hash_find (parop_hash, insn->mnemonic);
+  if (!insn->tm)
     {
       as_bad (_("Unrecognized parallel instruction \"%s\""),
              insn->mnemonic);
       return 0;
     }
 
-  while (insn->ptm->name && strcasecmp (insn->ptm->name,
-                                       insn->mnemonic) == 0)
+  while (insn->tm->name && strcasecmp (insn->tm->name,
+                                       insn->mnemonic) == 0)
     {
       insn->opcount = get_operands (insn->operands, line);
       if (insn->opcount < 0)
        return 0;
       if (insn->opcount == 2
          && operands_match (insn, &insn->operands[0], insn->opcount,
-                            insn->ptm->operand_types, 2, 2))
+                            insn->tm->operand_types, 2, 2))
        {
          return 1;
        }
-      ++(insn->ptm);
+      ++(insn->tm);
     }
   /* Didn't find a matching parallel; try for a normal insn.  */
   return 0;
@@ -4459,30 +4226,27 @@ tic54x_parse_parallel_insn_firstline (insn, line)
 /* Parse the second line of a two-line parallel instruction.  */
 
 static int
-tic54x_parse_parallel_insn_lastline (insn, line)
-     tic54x_insn *insn;
-     char *line;
+tic54x_parse_parallel_insn_lastline (tic54x_insn *insn, char *line)
 {
   int valid_mnemonic = 0;
 
   insn->paropcount = get_operands (insn->paroperands, line);
-  while (insn->ptm->name && strcasecmp (insn->ptm->name,
+  while (insn->tm->name && strcasecmp (insn->tm->name,
                                       insn->mnemonic) == 0)
     {
-      if (strcasecmp (insn->ptm->parname, insn->parmnemonic) == 0)
+      if (strcasecmp (insn->tm->parname, insn->parmnemonic) == 0)
        {
          valid_mnemonic = 1;
-         if (insn->paropcount >= insn->ptm->minops
-             && insn->paropcount <= insn->ptm->maxops
+
+         if (insn->paropcount >= insn->tm->minops
+             && insn->paropcount <= insn->tm->maxops
              && operands_match (insn, insn->paroperands,
                                 insn->paropcount,
-                                insn->ptm->paroperand_types,
-                                insn->ptm->minops, insn->ptm->maxops))
-           {
-             return 1;
-           }
+                                insn->tm->paroperand_types,
+                                insn->tm->minops, insn->tm->maxops))
+           return 1;
        }
-      ++(insn->ptm);
+      ++(insn->tm);
     }
   if (valid_mnemonic)
     as_bad (_("Invalid operand (s) for parallel instruction \"%s\""),
@@ -4500,26 +4264,25 @@ tic54x_parse_parallel_insn_lastline (insn, line)
    replacement on the value.  */
 
 static char *
-subsym_get_arg (char *line, char *terminators, char **str, int nosub)
+subsym_get_arg (char *line, const char *terminators, char **str, int nosub)
 {
   char *ptr = line;
   char *endp;
   int is_string = *line == '"';
-  int is_char = isdigit (*line);
+  int is_char = ISDIGIT (*line);
 
   if (is_char)
     {
-      while (isdigit (*ptr))
+      while (ISDIGIT (*ptr))
        ++ptr;
       endp = ptr;
-      *str = xmalloc (ptr - line + 1);
-      strncpy (*str, line, ptr - line);
-      (*str)[ptr - line] = 0;
+      *str = xmemdup0 (line, ptr - line);
     }
   else if (is_string)
     {
       char *savedp = input_line_pointer;
       int len;
+
       input_line_pointer = ptr;
       *str = demand_copy_C_string (&len);
       endp = input_line_pointer;
@@ -4531,7 +4294,7 @@ subsym_get_arg (char *line, char *terminators, char **str, int nosub)
     }
   else
     {
-      char *term = terminators;
+      const char *term = terminators;
       char *value = NULL;
 
       while (*ptr && *ptr != *term)
@@ -4545,9 +4308,7 @@ subsym_get_arg (char *line, char *terminators, char **str, int nosub)
            ++term;
        }
       endp = ptr;
-      *str = xmalloc (ptr - line + 1);
-      strncpy (*str, line, ptr - line);
-      (*str)[ptr - line] = 0;
+      *str = xmemdup0 (line, ptr - line);
       /* Do simple substitution, if available.  */
       if (!nosub && (value = subsym_lookup (*str, macro_level)) != NULL)
        *str = value;
@@ -4562,36 +4323,27 @@ subsym_get_arg (char *line, char *terminators, char **str, int nosub)
    that's compatible w/TI's assembler.  */
 
 static void
-subsym_create_or_replace (name, value)
-     char *name;
-     char *value;
+subsym_create_or_replace (char *name, char *value)
 {
   int i;
 
   for (i = macro_level; i > 0; i--)
-    {
-      if (hash_find (subsym_hash[i], name))
-       {
-         hash_replace (subsym_hash[i], name, value);
-         return;
-       }
-    }
-  if (hash_find (subsym_hash[0], name))
-    hash_replace (subsym_hash[0], name, value);
-  else
-    hash_insert (subsym_hash[0], name, value);
+    if (str_hash_find (subsym_hash[i], name))
+      {
+       str_hash_insert (subsym_hash[i], name, value, 1);
+       return;
+      }
+  str_hash_insert (subsym_hash[0], name, value, 1);
 }
 
 /* Look up the substitution string replacement for the given symbol.
-   Start with the innermost macro substituion table given and work
+   Start with the innermost macro substitution table given and work
    outwards.  */
 
 static char *
-subsym_lookup (name, nest_level)
-     char *name;
-     int nest_level;
+subsym_lookup (char *name, int nest_level)
 {
-  char *value = hash_find (subsym_hash[nest_level], name);
+  char *value = str_hash_find (subsym_hash[nest_level], name);
 
   if (value || nest_level == 0)
     return value;
@@ -4624,8 +4376,7 @@ subsym_substitute (char *line, int forced)
   char *tmp;
 
   /* Work with a copy of the input line.  */
-  replacement = xmalloc (strlen (line) + 1);
-  strcpy (replacement, line);
+  replacement = xstrdup (line);
 
   ptr = head = replacement;
 
@@ -4635,9 +4386,7 @@ subsym_substitute (char *line, int forced)
   if (strstr (line, ".if")
       || strstr (line, ".elseif")
       || strstr (line, ".break"))
-    {
-      line_conditional = 1;
-    }
+    line_conditional = 1;
 
   /* Watch out for .eval, so that we avoid doing substitution on the
      symbol being assigned a value.  */
@@ -4649,10 +4398,9 @@ subsym_substitute (char *line, int forced)
   if (strstr (line, ".macro"))
     return line;
 
-  while (!is_end_of_line[(int) *ptr])
+  unsigned char current_char;
+  while (!is_end_of_line[(current_char = * (unsigned char *) ptr)])
     {
-      int current_char = *ptr;
-
       /* Need to update this since LINE may have been modified.  */
       if (eval_line)
        eval_end = strrchr (ptr, ',');
@@ -4677,8 +4425,7 @@ subsym_substitute (char *line, int forced)
              continue;
            }
          *ptr++ = '\0';
-         tmp = xmalloc (strlen (head) + 2 + strlen (ptr) + 1);
-         sprintf (tmp, "%s==%s", head, ptr);
+         tmp = concat (head, "==", ptr, (char *) NULL);
          /* Continue examining after the '=='.  */
          ptr = tmp + strlen (head) + 2;
          free (replacement);
@@ -4705,8 +4452,8 @@ subsym_substitute (char *line, int forced)
          if (forced)
            ++ptr;
 
-         name = input_line_pointer = ptr;
-         c = get_symbol_end ();
+         input_line_pointer = ptr;
+         c = get_symbol_name (&name);
          /* '?' is not normally part of a symbol, but it IS part of a local
             label.  */
          if (c == '?')
@@ -4717,7 +4464,7 @@ subsym_substitute (char *line, int forced)
            }
          /* Avoid infinite recursion; if a symbol shows up a second time for
             substitution, leave it as is.  */
-         if (hash_find (subsym_recurse_hash, name) == NULL)
+         if (str_hash_find (subsym_recurse_hash, name) == NULL)
            value = subsym_lookup (name, macro_level);
          else
            as_warn (_("%s symbol recursion stopped at "
@@ -4728,23 +4475,25 @@ subsym_substitute (char *line, int forced)
 
          /* Check for local labels; replace them with the appropriate
             substitution.  */
-         if ((*name == '$' && isdigit (name[1]) && name[2] == '\0')
+         if ((*name == '$' && ISDIGIT (name[1]) && name[2] == '\0')
              || name[strlen (name) - 1] == '?')
            {
              /* Use an existing identifier for that label if, available, or
                 create a new, unique identifier.  */
-             value = hash_find (local_label_hash[macro_level], name);
+             value = str_hash_find (local_label_hash[macro_level], name);
              if (value == NULL)
                {
                  char digit[11];
-                 char *namecopy = strcpy (xmalloc (strlen (name) + 1), name);
+                 char *namecopy = xstrdup (name);
+
                  value = strcpy (xmalloc (strlen (name) + sizeof (digit) + 1),
                                  name);
                  if (*value != '$')
                    value[strlen (value) - 1] = '\0';
                  sprintf (digit, ".%d", local_label_id++);
                  strcat (value, digit);
-                 hash_insert (local_label_hash[macro_level], namecopy, value);
+                 str_hash_insert (local_label_hash[macro_level],
+                                  namecopy, value, 0);
                }
              /* Indicate where to continue looking for substitutions.  */
              ptr = tail;
@@ -4753,7 +4502,7 @@ subsym_substitute (char *line, int forced)
          else if (value != NULL && *name == '$')
            {
              subsym_proc_entry *entry = (subsym_proc_entry *) value;
-             math_proc_entry *math_entry = hash_find (math_hash, name);
+             math_proc_entry *math_entry = str_hash_find (math_hash, name);
              char *arg1, *arg2 = NULL;
 
              *ptr = c;
@@ -4770,10 +4519,10 @@ subsym_substitute (char *line, int forced)
              ++ptr;
              if (math_entry != NULL)
                {
-                 float arg1, arg2 = 0;
+                 float farg1, farg2 = 0;
                  volatile float fresult;
 
-                 arg1 = (float) strtod (ptr, &ptr);
+                 farg1 = (float) strtod (ptr, &ptr);
                  if (math_entry->nargs == 2)
                    {
                      if (*ptr++ != ',')
@@ -4781,10 +4530,10 @@ subsym_substitute (char *line, int forced)
                          as_bad (_("Expecting second argument"));
                          break;
                        }
-                     arg2 = (float) strtod (ptr, &ptr);
+                     farg2 = (float) strtod (ptr, &ptr);
                    }
-                 fresult = (*math_entry->proc) (arg1, arg2);
-                 value = xmalloc (128);
+                 fresult = (*math_entry->proc) (farg1, farg2);
+                 value = XNEWVEC (char, 128);
                  if (math_entry->int_return)
                    sprintf (value, "%d", (int) fresult);
                  else
@@ -4803,6 +4552,7 @@ subsym_substitute (char *line, int forced)
                  int val;
                  int arg_type[2] = { *ptr == '"' , 0 };
                  int ismember = !strcmp (entry->name, "$ismember");
+
                  /* Parse one or two args, which must be a substitution
                     symbol, string or a character-string constant.  */
                  /* For all functions, a string or substitution symbol may be
@@ -4821,7 +4571,7 @@ subsym_substitute (char *line, int forced)
                        }
                      /* Character constants are converted to numerics
                         by the preprocessor.  */
-                     arg_type[1] = (isdigit (*ptr)) ? 2 : (*ptr == '"');
+                     arg_type[1] = (ISDIGIT (*ptr)) ? 2 : (*ptr == '"');
                      ptr = subsym_get_arg (ptr, ")", &arg2, ismember);
                    }
                  /* Args checking.  */
@@ -4844,7 +4594,7 @@ subsym_substitute (char *line, int forced)
                      break;
                    }
                  val = (*entry->proc) (arg1, arg2);
-                 value = xmalloc (64);
+                 value = XNEWVEC (char, 64);
                  sprintf (value, "%d", val);
                }
              /* Fix things up to replace the entire expression, not just the
@@ -4860,13 +4610,13 @@ subsym_substitute (char *line, int forced)
                 substitutions are performed, or a substitution that has been
                 previously made is encountered again.
 
-                put the symbol into the recursion hash table so we only
+                Put the symbol into the recursion hash table so we only
                 try to replace a symbol once.  */
              if (recurse)
                {
-                 hash_insert (subsym_recurse_hash, name, name);
+                 str_hash_insert (subsym_recurse_hash, name, name, 0);
                  value = subsym_substitute (value, macro_level > 0);
-                 hash_delete (subsym_recurse_hash, name);
+                 str_hash_delete (subsym_recurse_hash, name);
                }
 
              /* Temporarily zero-terminate where the symbol started.  */
@@ -4877,11 +4627,10 @@ subsym_substitute (char *line, int forced)
                    {
                      /* Subscripted substitution symbol -- use just the
                         indicated portion of the string; the description
-                        kinda indicates that forced substituion is not
+                        kinda indicates that forced substitution is not
                         supposed to be recursive, but I'm not sure.  */
                      unsigned beg, len = 1; /* default to a single char */
-                     char *newval = strcpy (xmalloc (strlen (value) + 1),
-                                            value);
+                     char *newval = xstrdup (value);
 
                      savedp = input_line_pointer;
                      input_line_pointer = tail + 1;
@@ -4889,7 +4638,7 @@ subsym_substitute (char *line, int forced)
                      if (beg < 1)
                        {
                          as_bad (_("Invalid subscript (use 1 to %d)"),
-                                 strlen (value));
+                                 (int) strlen (value));
                          break;
                        }
                      if (*input_line_pointer == ',')
@@ -4898,8 +4647,8 @@ subsym_substitute (char *line, int forced)
                          len = get_absolute_expression ();
                          if (beg + len > strlen (value))
                            {
-                             as_bad (_("Invalid length (use 0 to %d"),
-                                     strlen (value) - beg);
+                             as_bad (_("Invalid length (use 0 to %d)"),
+                                     (int) strlen (value) - beg);
                              break;
                            }
                        }
@@ -4932,24 +4681,6 @@ subsym_substitute (char *line, int forced)
                      break;
                    }
                  ++tail;
-#if 0
-                 /* Try to replace required whitespace
-                    eliminated by the preprocessor; technically, a forced
-                    substitution could come anywhere, even mid-symbol,
-                    e.g. if x is "0", 'sym:x:end' should result in 'sym0end',
-                    but 'sym:x: end' should result in 'sym0 end'.
-                    FIXME -- this should really be fixed in the preprocessor,
-                    but would require several new states;
-                    KEEP_WHITE_AROUND_COLON does part of the job, but isn't
-                    complete.  */
-                 if ((is_part_of_name (tail[1])
-                      && tail[1] != '.'
-                      && tail[1] != '$')
-                     || tail[1] == '\0' || tail[1] == ',' || tail[1] == '"')
-                   ++tail;
-                 else
-                   *tail = ' ';
-#endif
                }
              else
                /* Restore the character after the symbol end.  */
@@ -4984,21 +4715,20 @@ subsym_substitute (char *line, int forced)
    returns the new buffer limit.  */
 
 void
-tic54x_start_line_hook ()
+tic54x_start_line_hook (void)
 {
   char *line, *endp;
   char *replacement = NULL;
 
   /* Work with a copy of the input line, including EOL char.  */
-  endp = input_line_pointer;
-  while (!is_end_of_line[(int) *endp++])
-    ;
-  line = xmalloc (endp - input_line_pointer + 1);
-  strncpy (line, input_line_pointer, endp - input_line_pointer + 1);
-  line[endp - input_line_pointer] = 0;
+  for (endp = input_line_pointer; *endp != 0; )
+    if (is_end_of_line[(unsigned char) *endp++])
+      break;
+
+  line = xmemdup0 (input_line_pointer, endp - input_line_pointer);
 
   /* Scan ahead for parallel insns.  */
-  parallel_on_next_line_hint = next_line_shows_parallel (endp + 1);
+  parallel_on_next_line_hint = next_line_shows_parallel (endp);
 
   /* If within a macro, first process forced replacements.  */
   if (macro_level > 0)
@@ -5026,7 +4756,7 @@ tic54x_start_line_hook ()
        comment = replacement + strlen (replacement) - 1;
 
       /* Trim trailing whitespace.  */
-      while (isspace (*comment))
+      while (ISSPACE (*comment))
        {
          comment[0] = endc;
          comment[1] = 0;
@@ -5034,7 +4764,7 @@ tic54x_start_line_hook ()
        }
 
       /* Compact leading whitespace.  */
-      while (isspace (tmp[0]) && isspace (tmp[1]))
+      while (ISSPACE (tmp[0]) && ISSPACE (tmp[1]))
        ++tmp;
 
       input_line_pointer = endp;
@@ -5056,8 +4786,7 @@ tic54x_start_line_hook ()
    machine dependent instruction.  This function is supposed to emit
    the frags/bytes it assembles to.  */
 void
-md_assemble (line)
-     char *line;
+md_assemble (char *line)
 {
   static int repeat_slot = 0;
   static int delay_slots = 0; /* How many delay slots left to fill?  */
@@ -5068,7 +4797,7 @@ md_assemble (line)
   int c;
 
   input_line_pointer = line;
-  c = get_symbol_end ();
+  c = get_symbol_name (&line);
 
   if (cpu == VNONE)
     cpu = V542;
@@ -5101,8 +4830,11 @@ md_assemble (line)
            {
              if (words > delay_slots)
                {
-                 as_bad (_("Instruction does not fit in available delay "
-                           "slots (%d-word insn, %d slots left)"),
+                 as_bad (ngettext ("Instruction does not fit in available "
+                                   "delay slots (%d-word insn, %d slot left)",
+                                   "Instruction does not fit in available "
+                                   "delay slots (%d-word insn, %d slots left)",
+                                   delay_slots),
                          words, delay_slots);
                  delay_slots = 0;
                  return;
@@ -5135,7 +4867,7 @@ md_assemble (line)
             otherwise let the assembler pick up the next line for us.  */
          if (tmp != NULL)
            {
-             while (isspace (tmp[2]))
+             while (ISSPACE (tmp[2]))
                ++tmp;
              md_assemble (tmp + 2);
            }
@@ -5173,9 +4905,13 @@ md_assemble (line)
        {
          if (words > delay_slots)
            {
-             as_warn (_("Instruction does not fit in available delay "
-                        "slots (%d-word insn, %d slots left). "
-                        "Resulting behavior is undefined."),
+             as_warn (ngettext ("Instruction does not fit in available "
+                                "delay slots (%d-word insn, %d slot left). "
+                                "Resulting behavior is undefined.",
+                                "Instruction does not fit in available "
+                                "delay slots (%d-word insn, %d slots left). "
+                                "Resulting behavior is undefined.",
+                                delay_slots),
                       words, delay_slots);
              delay_slots = 0;
              return;
@@ -5223,15 +4959,14 @@ md_assemble (line)
    a ".file" symbol.  */
 
 void
-tic54x_adjust_symtab ()
+tic54x_adjust_symtab (void)
 {
   if (symbol_rootP == NULL
       || S_GET_STORAGE_CLASS (symbol_rootP) != C_FILE)
     {
-      char *filename;
       unsigned lineno;
-      as_where (&filename, &lineno);
-      c_dot_file_symbol (filename);
+      const char * filename = as_where (&lineno);
+      c_dot_file_symbol (filename, 0);
     }
 }
 
@@ -5251,14 +4986,8 @@ tic54x_unrecognized_line (int c)
    FIXME -- obviously this isn't done yet.  These locals still show up in the
    symbol table.  */
 void
-tic54x_define_label (sym)
-     symbolS *sym;
+tic54x_define_label (symbolS *sym)
 {
-#if 0
-  static int local_label_count = 0;
-  const char *name = S_GET_NAME (sym);
-#endif
-
   /* Just in case we need this later; note that this is not necessarily the
      same thing as line_label...
      When aligning or assigning labels to fields, sometimes the label is
@@ -5271,30 +5000,23 @@ tic54x_define_label (sym)
 /* Try to parse something that normal parsing failed at.  */
 
 symbolS *
-tic54x_undefined_symbol (name)
-     char *name;
+tic54x_undefined_symbol (char *name)
 {
-  symbol *sym;
+  tic54x_symbol *sym;
 
   /* Not sure how to handle predefined symbols.  */
-  if ((sym = (symbol *) hash_find (cc_hash, name)) != NULL ||
-      (sym = (symbol *) hash_find (cc2_hash, name)) != NULL ||
-      (sym = (symbol *) hash_find (cc3_hash, name)) != NULL ||
-      (sym = (symbol *) hash_find (misc_symbol_hash, name)) != NULL ||
-      (sym = (symbol *) hash_find (sbit_hash, name)) != NULL)
-    {
-      return symbol_new (name, reg_section,
-                        (valueT) sym->value,
-                        &zero_address_frag);
-    }
-
-  if ((sym = (symbol *) hash_find (reg_hash, name)) != NULL ||
-      (sym = (symbol *) hash_find (mmreg_hash, name)) != NULL ||
-      !strcasecmp (name, "a") || !strcasecmp (name, "b"))
+  if ((sym = (tic54x_symbol *) str_hash_find (cc_hash, name)) != NULL
+      || (sym = (tic54x_symbol *) str_hash_find (cc2_hash, name)) != NULL
+      || (sym = (tic54x_symbol *) str_hash_find (cc3_hash, name)) != NULL
+      || str_hash_find (misc_symbol_hash, name) != NULL
+      || (sym = (tic54x_symbol *) str_hash_find (sbit_hash, name)) != NULL
+      || (sym = (tic54x_symbol *) str_hash_find (reg_hash, name)) != NULL
+      || (sym = (tic54x_symbol *) str_hash_find (mmreg_hash, name)) != NULL
+      || !strcasecmp (name, "a")
+      || !strcasecmp (name, "b"))
     {
-      return symbol_new (name, reg_section,
-                        (valueT) sym ? sym->value : 0,
-                        &zero_address_frag);
+      return symbol_new (name, reg_section, &zero_address_frag,
+                        sym ? sym->value : 0);
     }
 
   return NULL;
@@ -5304,62 +5026,29 @@ tic54x_undefined_symbol (name)
    it.  */
 
 int
-tic54x_parse_name (name, exp)
-     char *name ATTRIBUTE_UNUSED;
-     expressionS *exp ATTRIBUTE_UNUSED;
+tic54x_parse_name (char *name ATTRIBUTE_UNUSED,
+                  expressionS *expn ATTRIBUTE_UNUSED)
 {
-#if 0
-  symbol *sym = (symbol *) hash_find (mmreg_hash, name);
-
-  /* If it's a MMREG, replace it with its constant value.  */
-  if (sym)
-    {
-      exp->X_op = O_constant;
-      exp->X_add_number = sym->value;
-      return 1;
-    }
-#endif
   return 0;
 }
 
-char *
-md_atof (type, literalP, sizeP)
-     int type;
-     char *literalP;
-     int *sizeP;
+const char *
+md_atof (int type, char *literalP, int *sizeP)
 {
-#define MAX_LITTLENUMS 2
-  LITTLENUM_TYPE words[MAX_LITTLENUMS];
-  LITTLENUM_TYPE *word;
-  /* Only one precision on the c54x.  */
-  int prec = 2;
-  char *t = atof_ieee (input_line_pointer, type, words);
-  if (t)
-    input_line_pointer = t;
-  *sizeP = 4;
-
   /* Target data is little-endian, but floats are stored
      big-"word"ian.  ugh.  */
-  for (word = words; prec--;)
-    {
-      md_number_to_chars (literalP, (long) (*word++), sizeof (LITTLENUM_TYPE));
-      literalP += sizeof (LITTLENUM_TYPE);
-    }
-
-  return 0;
+  return ieee_md_atof (type, literalP, sizeP, TRUE);
 }
 
 arelent *
-tc_gen_reloc (section, fixP)
-     asection *section;
-     fixS *fixP;
+tc_gen_reloc (asection *section, fixS *fixP)
 {
   arelent *rel;
   bfd_reloc_code_real_type code = fixP->fx_r_type;
   asymbol *sym = symbol_get_bfdsym (fixP->fx_addsy);
 
-  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 = sym;
   /* We assume that all rel->address are host byte offsets.  */
   rel->address = fixP->fx_frag->fr_address + fixP->fx_where;
@@ -5383,9 +5072,9 @@ tc_gen_reloc (section, fixP)
 /* Handle cons expressions.  */
 
 void
-tic54x_cons_fix_new (fragS *frag, int where, int octets, expressionS *exp)
+tic54x_cons_fix_new (fragS *frag, int where, int octets, expressionS *expn,
+                    bfd_reloc_code_real_type r)
 {
-  bfd_reloc_code_real_type r;
   switch (octets)
     {
     default:
@@ -5405,7 +5094,7 @@ tic54x_cons_fix_new (fragS *frag, int where, int octets, expressionS *exp)
        r = BFD_RELOC_32;
       break;
     }
-  fix_new_exp (frag, where, octets, exp, 0, r);
+  fix_new_exp (frag, where, octets, expn, 0, r);
 }
 
 /* Attempt to simplify or even eliminate a fixup.
@@ -5413,19 +5102,17 @@ tic54x_cons_fix_new (fragS *frag, int where, int octets, expressionS *exp)
 
    If fixp->fx_addsy is non-NULL, we'll have to generate a reloc entry.   */
 
-int
-md_apply_fix (fixP, valP)
-     fixS *fixP;
-     valueT *valP;
+void
+md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
 {
   char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
-  valueT val = *valP;
+  valueT val = * valP;
 
   switch (fixP->fx_r_type)
     {
     default:
       as_fatal ("Bad relocation type: 0x%02x", fixP->fx_r_type);
-      return 0;
+      return;
     case BFD_RELOC_TIC54X_MS7_OF_23:
       val = (val >> 16) & 0x7F;
       /* Fall through.  */
@@ -5459,46 +5146,30 @@ md_apply_fix (fixP, valP)
       break;
     }
 
-  return 0; /* Return value is ignored.  */
+  if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0)
+    fixP->fx_done = 1;
 }
 
 /* This is our chance to record section alignment
    don't need to do anything here, since BFD does the proper encoding.  */
 
 valueT
-md_section_align (segment, section_size)
-     segT segment ATTRIBUTE_UNUSED;
-     valueT section_size;
+md_section_align (segT segment ATTRIBUTE_UNUSED, valueT section_size)
 {
   return section_size;
 }
 
 long
-md_pcrel_from (fixP)
-     fixS *fixP ATTRIBUTE_UNUSED;
+md_pcrel_from (fixS *fixP ATTRIBUTE_UNUSED)
 {
   return 0;
 }
 
-#if defined OBJ_COFF
-
-short
-tc_coff_fix2rtype (fixP)
-     fixS *fixP;
-{
-  return (fixP->fx_r_type);
-}
-
-#endif /* OBJ_COFF */
-
 /* Mostly little-endian, but longwords (4 octets) get MS word stored
    first.  */
 
 void
-tic54x_number_to_chars (buf, val, n)
-     char *buf;
-     valueT val;
-     int n;
+tic54x_number_to_chars (char *buf, valueT val, int n)
 {
   if (n != 4)
     number_to_chars_littleendian (buf, val, n);
@@ -5510,9 +5181,8 @@ tic54x_number_to_chars (buf, val, n)
 }
 
 int
-tic54x_estimate_size_before_relax (frag, seg)
-     fragS *frag ATTRIBUTE_UNUSED;
-     segT seg ATTRIBUTE_UNUSED;
+tic54x_estimate_size_before_relax (fragS *frag ATTRIBUTE_UNUSED,
+                                  segT seg ATTRIBUTE_UNUSED)
 {
   return 0;
 }
@@ -5521,9 +5191,7 @@ tic54x_estimate_size_before_relax (frag, seg)
    to symbols being in different frags.  return number of octets added.  */
 
 int
-tic54x_relax_frag (frag, stretch)
-     fragS *frag;
-     long stretch ATTRIBUTE_UNUSED;
+tic54x_relax_frag (fragS *frag, long stretch ATTRIBUTE_UNUSED)
 {
   symbolS *sym = frag->fr_symbol;
   int growth = 0;
@@ -5559,6 +5227,7 @@ tic54x_relax_frag (frag, stretch)
          if (bit_offset != 0 && available >= size)
            {
              char *p = prev_frag->fr_literal;
+
              valueT value = bi->value;
              value <<= available - size;
              value |= ((unsigned short) p[1] << 8) | p[0];
@@ -5575,6 +5244,7 @@ tic54x_relax_frag (frag, stretch)
          else
            {
              char *p = frag->fr_literal;
+
              valueT value = bi->value << (16 - size);
              md_number_to_chars (p, value, 2);
              if ((frag->tc_frag_data = size) == 16)
@@ -5620,10 +5290,9 @@ tic54x_relax_frag (frag, stretch)
 }
 
 void
-tic54x_convert_frag (abfd, seg, frag)
-     bfd *abfd ATTRIBUTE_UNUSED;
-     segT seg ATTRIBUTE_UNUSED;
-     fragS *frag;
+tic54x_convert_frag (bfd *abfd ATTRIBUTE_UNUSED,
+                    segT seg ATTRIBUTE_UNUSED,
+                    fragS *frag)
 {
   /* Offset is in bytes.  */
   frag->fr_offset = (frag->fr_next->fr_address
@@ -5643,49 +5312,43 @@ tic54x_convert_frag (abfd, seg, frag)
    syntax puts the symbol *before* the pseudo (which is kinda like MRI syntax,
    I guess, except I've never seen a definition of MRI syntax).
 
-   C is the character that used to be at *REST, which points to the end of the
-   label.
-
    Don't allow labels to start with '.'  */
 
 int
-tic54x_start_label (c, rest)
-     int c;
-     char *rest;
+tic54x_start_label (char * label_start, int nul_char, int next_char)
 {
+  char *rest;
+
   /* If within .struct/.union, no auto line labels, please.  */
   if (current_stag != NULL)
     return 0;
 
   /* Disallow labels starting with "."  */
-  if (c != ':')
+  if (next_char != ':')
     {
-      char *label = rest;
-      while (!is_end_of_line[(int) label[-1]])
-       --label;
-      if (*label == '.')
+      if (*label_start == '.')
        {
-         as_bad (_("Invalid label '%s'"), label);
+         as_bad (_("Invalid label '%s'"), label_start);
          return 0;
        }
     }
 
-  if (is_end_of_line[(int) c])
+  if (is_end_of_line[(unsigned char) next_char])
     return 1;
 
-  if (isspace (c))
-    while (isspace (c = *++rest))
-      ;
-  if (c == '.')
-    {
-      /* Don't let colon () define a label for any of these...  */
-      return (strncasecmp (rest, ".tag", 4) != 0 || !isspace (rest[4]))
-       && (strncasecmp (rest, ".struct", 7) != 0 || !isspace (rest[7]))
-       && (strncasecmp (rest, ".union", 6) != 0 || !isspace (rest[6]))
-       && (strncasecmp (rest, ".macro", 6) != 0 || !isspace (rest[6]))
-       && (strncasecmp (rest, ".set", 4) != 0 || !isspace (rest[4]))
-       && (strncasecmp (rest, ".equ", 4) != 0 || !isspace (rest[4]));
-    }
+  rest = input_line_pointer;
+  if (nul_char == '"')
+    ++rest;
+  while (ISSPACE (next_char))
+    next_char = *++rest;
+  if (next_char != '.')
+    return 1;
 
-  return 1;
+  /* Don't let colon () define a label for any of these...  */
+  return ((strncasecmp (rest, ".tag", 4) != 0 || !ISSPACE (rest[4]))
+         && (strncasecmp (rest, ".struct", 7) != 0 || !ISSPACE (rest[7]))
+         && (strncasecmp (rest, ".union", 6) != 0 || !ISSPACE (rest[6]))
+         && (strncasecmp (rest, ".macro", 6) != 0 || !ISSPACE (rest[6]))
+         && (strncasecmp (rest, ".set", 4) != 0 || !ISSPACE (rest[4]))
+         && (strncasecmp (rest, ".equ", 4) != 0 || !ISSPACE (rest[4])));
 }