]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - gas/config/tc-m88k.c
* config/sh/tm-sh.h (BELIEVE_PCC_PROMOTION): Define, so that
[thirdparty/binutils-gdb.git] / gas / config / tc-m88k.c
index 31b7ebb7234b4bd578a01ceeb11181cb6d5aa690..931a496a54b794f2b7f372651ea0fb144ab24967 100644 (file)
@@ -1,13 +1,14 @@
 /* m88k.c -- Assembler for the Motorola 88000
    Contributed by Devon Bowen of Buffalo University
    and Torbjorn Granlund of the Swedish Institute of Computer Science.
-   Copyright (C) 1989, 1990, 1991 Free Software Foundation, Inc.
+   Copyright (C) 1989, 90, 91, 92, 93, 94, 95, 96, 1997
+   Free Software Foundation, Inc.
 
 This file is part of GAS, the GNU Assembler.
 
 GAS is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 1, or (at your option)
+the Free Software Foundation; either version 2, or (at your option)
 any later version.
 
 GAS is distributed in the hope that it will be useful,
@@ -16,37 +17,14 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 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, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+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.  */
 
 #include <ctype.h>
-#include "m88k-opcode.h"
 #include "as.h"
-#include "frags.h"
-#include "struc-symbol.h"
-#include "flonum.h"
-#include "expr.h"
-#include "hash.h"
-#include "md.h"
-#include "m88k.h"
-#include "write.h"
-#include "read.h"
-/*
-#include "obstack.h"
-#include "struc-symbol.h"
-*/
-#include "symbols.h"
-
-char *getval ();
-char *get_reg ();
-char *get_imm16 ();
-char *get_bf ();
-char *get_pcr ();
-char *get_cmp ();
-char *get_cnd ();
-char *get_cr ();
-char *get_fcr ();
-char *get_vec9 ();
+#include "subsegs.h"
+#include "m88k-opcode.h"
 
 struct field_val_assoc
 {
@@ -101,7 +79,7 @@ struct field_val_assoc fcr_regs[] =
 
 struct field_val_assoc cmpslot[] =
 {
-/* Integer  Floating point */
+/* Integer     Floating point */
   {"nc", 0},
   {"cp", 1},
   {"eq", 2},
@@ -110,14 +88,16 @@ struct field_val_assoc cmpslot[] =
   {"le", 5},
   {"lt", 6},
   {"ge", 7},
-  {"hi", 8},
-  {"ou", 8},
-  {"ls", 9},
-  {"ib", 9},
-  {"lo", 10},
-  {"in", 10},
-  {"hs", 11},
-  {"ob", 11},
+  {"hi", 8},   {"ou", 8},
+  {"ls", 9},   {"ib", 9},
+  {"lo", 10},  {"in", 10},
+  {"hs", 11},  {"ob", 11},
+  {"be", 12},  {"ue", 12},
+  {"nb", 13},  {"lg", 13},
+  {"he", 14},  {"ug", 14},
+  {"nh", 15},  {"ule", 15},
+               {"ul", 16},
+               {"uge", 17},
 
   {NULL, 0},
 };
@@ -141,15 +121,30 @@ struct m88k_insn
   enum reloc_type reloc;
 };
 
+static char *get_bf PARAMS ((char *param, unsigned *valp));
+static char *get_cmp PARAMS ((char *param, unsigned *valp));
+static char *get_cnd PARAMS ((char *param, unsigned *valp));
+static char *get_cr PARAMS ((char *param, unsigned *regnop));
+static char *get_fcr PARAMS ((char *param, unsigned *regnop));
+static char *get_imm16 PARAMS ((char *param, struct m88k_insn *insn));
+static char *get_o6 PARAMS ((char *param, unsigned *valp));
+static char *get_reg PARAMS ((char *param, unsigned *regnop, int reg_prefix));
+static char *get_vec9 PARAMS ((char *param, unsigned *valp));
+static char *getval PARAMS ((char *param, unsigned int *valp));
+
+static char *get_pcr PARAMS ((char *param, struct m88k_insn *insn,
+                     enum reloc_type reloc));
+
+static int calcop PARAMS ((struct m88k_opcode *format,
+                          char *param, struct m88k_insn *insn));
+
+
 extern char *myname;
 static struct hash_control *op_hash = NULL;
 
 /* These bits should be turned off in the first address of every segment */
 int md_seg_align = 7;
 
-/* This is the number to put at the beginning of the a.out file */
-long omagic = OMAGIC;
-
 /* These chars start a comment anywhere in a source file (except inside
    another comment */
 const char comment_chars[] = ";";
@@ -167,37 +162,35 @@ const char EXP_CHARS[] = "eE";
 /* or    0H1.234E-12 (see exp chars above) */
 const char FLT_CHARS[] = "dDfF";
 
-extern void float_cons (), cons (), s_globl (), s_line (), s_space (),
-  s_set (), stringer (), s_lcomm ();
-static void s_file ();
-static void s_bss ();
+extern void float_cons (), cons (), s_globl (), s_space (),
+  s_set (), s_lcomm ();
 
 const pseudo_typeS md_pseudo_table[] =
 {
+  {"align", s_align_bytes, 4},
   {"def", s_set, 0},
   {"dfloat", float_cons, 'd'},
   {"ffloat", float_cons, 'f'},
   {"global", s_globl, 0},
   {"half", cons, 2},
-  {"bss", s_bss, 0},
-  {"ln", s_line, 0},
+  {"bss", s_lcomm, 1},
   {"string", stringer, 0},
   {"word", cons, 4},
-  {"zero", s_space, 0},
+  /* Force set to be treated as an instruction.  */
+  {"set", NULL, 0},
+  {".set", s_set, 0},
   {0}
 };
 
 void
 md_begin ()
 {
-  char *retval = NULL;
+  const char *retval = NULL;
   unsigned int i = 0;
 
   /* initialize hash table */
 
   op_hash = hash_new ();
-  if (op_hash == NULL)
-    as_fatal ("Could not initialize hash table");
 
   /* loop until you see the end of the list */
 
@@ -209,8 +202,8 @@ md_begin ()
 
       retval = hash_insert (op_hash, name, &m88k_opcodes[i]);
 
-      if (retval != NULL && *retval != '\0')
-       as_fatal ("Can't hash instruction '%s':%s",
+      if (retval != NULL)
+       as_fatal (_("Can't hash instruction '%s':%s"),
                  m88k_opcodes[i].name, retval);
 
       /* skip to next unique mnemonic or end of list */
@@ -219,21 +212,33 @@ md_begin ()
        ;
     }
 }
+\f
+CONST char *md_shortopts = "";
+struct option md_longopts[] = {
+  {NULL, no_argument, NULL, 0}
+};
+size_t md_longopts_size = sizeof(md_longopts);
 
-void
-md_parse_option (argP, cntP, vecP)
-     char **argP;
-     int *cntP;
-     char ***vecP;
+int
+md_parse_option (c, arg)
+     int c;
+     char *arg;
 {
-  as_warn ("unknown option: -%s", *argP);
+  return 0;
 }
 
+void
+md_show_usage (stream)
+     FILE *stream;
+{
+}
+\f
 void
 md_assemble (op)
      char *op;
 {
   char *param, *thisfrag;
+  char c;
   struct m88k_opcode *format;
   struct m88k_insn insn;
 
@@ -243,23 +248,23 @@ md_assemble (op)
 
   for (param = op; *param != 0 && !isspace (*param); param++)
     ;
-  if (*param != 0)
-    *param++ = 0;
+  c = *param;
+  *param++ = '\0';
 
   /* try to find the instruction in the hash table */
 
   if ((format = (struct m88k_opcode *) hash_find (op_hash, op)) == NULL)
     {
-      as_fatal ("Invalid mnemonic '%s'", op);
+      as_bad (_("Invalid mnemonic '%s'"), op);
       return;
     }
 
   /* try parsing this instruction into insn */
 
   insn.exp.X_add_symbol = 0;
-  insn.exp.X_subtract_symbol = 0;
+  insn.exp.X_op_symbol = 0;
   insn.exp.X_add_number = 0;
-  insn.exp.X_seg = 0;
+  insn.exp.X_op = O_illegal;
   insn.reloc = NO_RELOC;
 
   while (!calcop (format, param, &insn))
@@ -270,7 +275,7 @@ md_assemble (op)
        format++;
       else
        {
-         as_fatal ("Parameter syntax error");
+         as_fatal (_("Parameter syntax error"));
          return;
        }
     }
@@ -289,56 +294,48 @@ md_assemble (op)
 
     case RELOC_LO16:
     case RELOC_HI16:
-      fix_new (frag_now,
-              thisfrag - frag_now->fr_literal + 2,
-              2,
-              insn.exp.X_add_symbol,
-              insn.exp.X_subtract_symbol,
-              insn.exp.X_add_number,
-              0,
-              insn.reloc);
+      fix_new_exp (frag_now,
+                  thisfrag - frag_now->fr_literal + 2,
+                  2,
+                  &insn.exp,
+                  0,
+                  insn.reloc);
       break;
 
     case RELOC_IW16:
-      fix_new (frag_now,
-              thisfrag - frag_now->fr_literal,
-              4,
-              insn.exp.X_add_symbol,
-              insn.exp.X_subtract_symbol,
-              insn.exp.X_add_number,
-              0,
-              insn.reloc);
+      fix_new_exp (frag_now,
+                  thisfrag - frag_now->fr_literal,
+                  4,
+                  &insn.exp,
+                  0,
+                  insn.reloc);
       break;
 
     case RELOC_PC16:
-      fix_new (frag_now,
-              thisfrag - frag_now->fr_literal + 2,
-              2,
-              insn.exp.X_add_symbol,
-              insn.exp.X_subtract_symbol,
-              insn.exp.X_add_number,
-              1,
-              insn.reloc);
+      fix_new_exp (frag_now,
+                  thisfrag - frag_now->fr_literal + 2,
+                  2,
+                  &insn.exp,
+                  1,
+                  insn.reloc);
       break;
 
     case RELOC_PC26:
-      fix_new (frag_now,
-              thisfrag - frag_now->fr_literal,
-              4,
-              insn.exp.X_add_symbol,
-              insn.exp.X_subtract_symbol,
-              insn.exp.X_add_number,
-              1,
-              insn.reloc);
+      fix_new_exp (frag_now,
+                  thisfrag - frag_now->fr_literal,
+                  4,
+                  &insn.exp,
+                  1,
+                  insn.reloc);
       break;
 
     default:
-      as_fatal ("Unknown relocation type");
+      as_fatal (_("Unknown relocation type"));
       break;
     }
 }
 
-int
+static int
 calcop (format, param, insn)
      struct m88k_opcode *format;
      char *param;
@@ -348,6 +345,7 @@ calcop (format, param, insn)
   int f;
   unsigned val;
   unsigned opcode;
+  int reg_prefix = 'r';
 
   insn->opcode = format->opcode;
   opcode = 0;
@@ -361,7 +359,7 @@ calcop (format, param, insn)
        {
        case 0:
          insn->opcode |= opcode;
-         return *param == 0;
+         return (*param == 0 || *param == '\n');
 
        default:
          if (f != *param++)
@@ -369,22 +367,34 @@ calcop (format, param, insn)
          break;
 
        case 'd':
-         param = get_reg (param, &val);
+         param = get_reg (param, &val, reg_prefix);
+         reg_prefix = 'r';
          opcode |= val << 21;
          break;
 
+       case 'o':
+         param = get_o6 (param, &val);
+         opcode |= ((val >> 2) << 7);
+         break;
+
+       case 'x':
+         reg_prefix = 'x';
+         break;
+
        case '1':
-         param = get_reg (param, &val);
+         param = get_reg (param, &val, reg_prefix);
+         reg_prefix = 'r';
          opcode |= val << 16;
          break;
 
        case '2':
-         param = get_reg (param, &val);
+         param = get_reg (param, &val, reg_prefix);
+         reg_prefix = 'r';
          opcode |= val;
          break;
 
        case '3':
-         param = get_reg (param, &val);
+         param = get_reg (param, &val, 'r');
          opcode |= (val << 16) | val;
          break;
 
@@ -433,13 +443,13 @@ calcop (format, param, insn)
        case '?':
          /* Having this here repeats the warning somtimes.
           But can't we stand that?  */
-         as_warn ("Use of obsolete instruction");
+         as_warn (_("Use of obsolete instruction"));
          break;
        }
     }
 }
 
-char *
+static char *
 match_name (param, assoc_tab, valp)
      char *param;
      struct field_val_assoc *assoc_tab;
@@ -463,16 +473,17 @@ match_name (param, assoc_tab, valp)
     }
 }
 
-char *
-get_reg (param, regnop)
+static char *
+get_reg (param, regnop, reg_prefix)
      char *param;
      unsigned *regnop;
+     int reg_prefix;
 {
   unsigned c;
   unsigned regno;
 
   c = *param++;
-  if (c == 'r')
+  if (c == reg_prefix)
     {
       regno = *param++ - '0';
       if (regno < 10)
@@ -509,14 +520,13 @@ get_reg (param, regnop)
   return 0;
 }
 
-char *
+static char *
 get_imm16 (param, insn)
      char *param;
      struct m88k_insn *insn;
 {
   enum reloc_type reloc = NO_RELOC;
   unsigned int val;
-  segT seg;
   char *save_ptr;
 
   if (!strncmp (param, "hi16", 4) && !isalnum (param[4]))
@@ -537,20 +547,20 @@ get_imm16 (param, insn)
 
   save_ptr = input_line_pointer;
   input_line_pointer = param;
-  seg = expression (&insn->exp);
+  expression (&insn->exp);
   param = input_line_pointer;
   input_line_pointer = save_ptr;
 
   val = insn->exp.X_add_number;
 
-  if (seg == SEG_ABSOLUTE)
+  if (insn->exp.X_op == O_constant)
     {
       /* Insert the value now, and reset reloc to NO_RELOC.  */
       if (reloc == NO_RELOC)
        {
          /* Warn about too big expressions if not surrounded by xx16.  */
          if (val > 0xffff)
-           as_warn ("Expression truncated to 16 bits");
+           as_warn (_("Expression truncated to 16 bits"));
        }
 
       if (reloc == RELOC_HI16)
@@ -569,30 +579,29 @@ get_imm16 (param, insn)
   return param;
 }
 
-char *
+static char *
 get_pcr (param, insn, reloc)
      char *param;
      struct m88k_insn *insn;
      enum reloc_type reloc;
 {
   char *saveptr, *saveparam;
-  segT seg;
 
   saveptr = input_line_pointer;
   input_line_pointer = param;
 
-  seg = expression (&insn->exp);
+  expression (&insn->exp);
 
   saveparam = input_line_pointer;
   input_line_pointer = saveptr;
 
-  /* Botch: We should relocate now if SEG_ABSOLUTE.  */
+  /* Botch: We should relocate now if O_constant.  */
   insn->reloc = reloc;
 
   return saveparam;
 }
 
-char *
+static char *
 get_cmp (param, valp)
      char *param;
      unsigned *valp;
@@ -617,7 +626,7 @@ get_cmp (param, valp)
 
       if (val >= 32)
        {
-         as_warn ("Expression truncated to 5 bits");
+         as_warn (_("Expression truncated to 5 bits"));
          val %= 32;
        }
     }
@@ -626,7 +635,7 @@ get_cmp (param, valp)
   return param;
 }
 
-char *
+static char *
 get_cnd (param, valp)
      char *param;
      unsigned *valp;
@@ -639,7 +648,7 @@ get_cnd (param, valp)
 
       if (val >= 32)
        {
-         as_warn ("Expression truncated to 5 bits");
+         as_warn (_("Expression truncated to 5 bits"));
          val %= 32;
        }
     }
@@ -663,7 +672,7 @@ get_cnd (param, valp)
   return param;
 }
 
-char *
+static char *
 get_bf2 (param, bc)
      char *param;
      int bc;
@@ -686,7 +695,7 @@ get_bf2 (param, bc)
     }
 }
 
-char *
+static char *
 get_bf_offset_expression (param, offsetp)
      char *param;
      unsigned *offsetp;
@@ -715,7 +724,7 @@ get_bf_offset_expression (param, offsetp)
   return param;
 }
 
-char *
+static char *
 get_bf (param, valp)
      char *param;
      unsigned *valp;
@@ -733,9 +742,9 @@ get_bf (param, valp)
     {
       /* We did not find '<'.  We have an offset (width implicitly 32).  */
       param = get_bf_offset_expression (param, &offset);
+      input_line_pointer = save_ptr;
       if (param == NULL)
        return NULL;
-      input_line_pointer = save_ptr;
     }
   else
     {
@@ -758,15 +767,13 @@ get_bf (param, valp)
   return param;
 }
 
-char *
+static char *
 get_cr (param, regnop)
      char *param;
      unsigned *regnop;
 {
   unsigned regno;
   unsigned c;
-  int i;
-  int name_len;
 
   if (!strncmp (param, "cr", 2))
     {
@@ -804,15 +811,13 @@ get_cr (param, regnop)
   return param;
 }
 
-char *
+static char *
 get_fcr (param, regnop)
      char *param;
      unsigned *regnop;
 {
   unsigned regno;
   unsigned c;
-  int i;
-  int name_len;
 
   if (!strncmp (param, "fcr", 3))
     {
@@ -850,7 +855,7 @@ get_fcr (param, regnop)
   return param;
 }
 
-char *
+static char *
 get_vec9 (param, valp)
      char *param;
      unsigned *valp;
@@ -865,19 +870,41 @@ get_vec9 (param, valp)
   input_line_pointer = save_ptr;
 
   if (val >= 1 << 9)
-    as_warn ("Expression truncated to 9 bits");
+    as_warn (_("Expression truncated to 9 bits"));
 
   *valp = val % (1 << 9);
 
   return param;
 }
 
+static char *
+get_o6 (param, valp)
+     char *param;
+     unsigned *valp;
+{
+  unsigned val;
+  char *save_ptr;
+
+  save_ptr = input_line_pointer;
+  input_line_pointer = param;
+  val = get_absolute_expression ();
+  param = input_line_pointer;
+  input_line_pointer = save_ptr;
+
+  if (val & 0x3)
+    as_warn (_("Removed lower 2 bits of expression"));
+
+  *valp = val;
+
+  return(param);
+}
+
 #define hexval(z) \
   (isdigit (z) ? (z) - '0' :                                           \
    islower (z) ? (z) - 'a' + 10 :                                      \
    isupper (z) ? (z) - 'A' + 10 : -1)
 
-char *
+static char *
 getval (param, valp)
      char *param;
      unsigned int *valp;
@@ -927,25 +954,17 @@ getval (param, valp)
 void
 md_number_to_chars (buf, val, nbytes)
      char *buf;
-     int val;
+     valueT val;
      int nbytes;
 {
-  switch (nbytes)
-    {
-    case 4:
-      *buf++ = val >> 24;
-      *buf++ = val >> 16;
-    case 2:
-      *buf++ = val >> 8;
-    case 1:
-      *buf = val;
-      break;
-
-    default:
-      abort ();
-    }
+  number_to_chars_bigendian (buf, val, nbytes);
 }
 
+#if 0
+
+/* This routine is never called.  What is it for?
+   Ian Taylor, Cygnus Support 13 Jul 1993 */
+
 void
 md_number_to_imm (buf, val, nbytes, fixP, seg_type)
      unsigned char *buf;
@@ -1012,18 +1031,20 @@ md_number_to_imm (buf, val, nbytes, fixP, seg_type)
       break;
 
     default:
-      as_fatal ("Bad relocation type");
+      as_fatal (_("Bad relocation type"));
       break;
     }
 }
 
+#endif /* 0 */
+
 void
 md_number_to_disp (buf, val, nbytes)
      char *buf;
      int val;
      int nbytes;
 {
-  as_fatal ("md_number_to_disp not defined");
+  as_fatal (_("md_number_to_disp not defined"));
   md_number_to_chars (buf, val, nbytes);
 }
 
@@ -1033,7 +1054,7 @@ md_number_to_field (buf, val, nbytes)
      int val;
      int nbytes;
 {
-  as_fatal ("md_number_to_field not defined");
+  as_fatal (_("md_number_to_field not defined"));
   md_number_to_chars (buf, val, nbytes);
 }
 
@@ -1053,7 +1074,6 @@ md_atof (type, litP, sizeP)
   LITTLENUM_TYPE words[MAX_LITTLENUMS];
   LITTLENUM_TYPE *wordP;
   char *t;
-  char *atof_ieee ();
 
   switch (type)
     {
@@ -1083,7 +1103,7 @@ md_atof (type, litP, sizeP)
 
     default:
       *sizeP = 0;
-      return "Bad call to MD_ATOF()";
+      return _("Bad call to MD_ATOF()");
     }
   t = atof_ieee (input_line_pointer, type, words);
   if (t)
@@ -1095,7 +1115,7 @@ md_atof (type, litP, sizeP)
       md_number_to_chars (litP, (long) (*wordP++), sizeof (LITTLENUM_TYPE));
       litP += sizeof (LITTLENUM_TYPE);
     }
-  return "";                   /* Someone should teach Dean about null pointers */
+  return 0;
 }
 
 int md_short_jump_size = 4;
@@ -1103,11 +1123,11 @@ int md_short_jump_size = 4;
 void
 md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol)
      char *ptr;
-     long from_addr, to_addr;
+     addressT from_addr, to_addr;
      fragS *frag;
      symbolS *to_symbol;
 {
-  ptr[0] = 0xc0;
+  ptr[0] = (char) 0xc0;
   ptr[1] = 0x00;
   ptr[2] = 0x00;
   ptr[3] = 0x00;
@@ -1115,8 +1135,7 @@ md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol)
           ptr - frag->fr_literal,
           4,
           to_symbol,
-          (symbolS *) 0,
-          (long int) 0,
+          (offsetT) 0,
           0,
           RELOC_PC26);         /* Botch: Shouldn't this be RELOC_PC16? */
 }
@@ -1126,11 +1145,11 @@ int md_long_jump_size = 4;
 void
 md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol)
      char *ptr;
-     long from_addr, to_addr;
+     addressT from_addr, to_addr;
      fragS *frag;
      symbolS *to_symbol;
 {
-  ptr[0] = 0xc0;
+  ptr[0] = (char) 0xc0;
   ptr[1] = 0x00;
   ptr[2] = 0x00;
   ptr[3] = 0x00;
@@ -1138,8 +1157,7 @@ md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol)
           ptr - frag->fr_literal,
           4,
           to_symbol,
-          (symbolS *) 0,
-          (long int) 0,
+          (offsetT) 0,
           0,
           RELOC_PC26);
 }
@@ -1147,25 +1165,18 @@ md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol)
 int
 md_estimate_size_before_relax (fragP, segment_type)
      fragS *fragP;
-     int segment_type;
+     segT segment_type;
 {
-  as_fatal ("Relaxation should never occur");
+  as_fatal (_("Relaxation should never occur"));
+  return (-1);
 }
 
-const relax_typeS md_relax_table[] =
-{0};
+#if 0
 
-void
-md_convert_frag (fragP)
-     fragS *fragP;
-{
-  as_fatal ("Relaxation should never occur");
-}
+/* As far as I can tell, this routine is never called.  What is it
+   doing here?
+   Ian Taylor, Cygnus Support 13 Jul 1993 */
 
-void
-md_end ()
-{
-}
 
 /*
  * Risc relocations are completely different, so it needs
@@ -1183,7 +1194,6 @@ emit_relocations (fixP, segment_address_in_file)
   bzero ((char *) &ri, sizeof (ri));
   for (; fixP; fixP = fixP->fx_next)
     {
-
       if (fixP->fx_r_type >= NO_RELOC)
        {
          fprintf (stderr, "fixP->fx_r_type = %d\n", fixP->fx_r_type);
@@ -1211,7 +1221,6 @@ emit_relocations (fixP, segment_address_in_file)
          ri.r_type = fixP->fx_r_type;
          if (fixP->fx_pcrel)
            {
-             /*                ri.r_addend -= fixP->fx_where;          */
              ri.r_addend -= ri.r_address;
            }
          else
@@ -1219,22 +1228,27 @@ emit_relocations (fixP, segment_address_in_file)
              ri.r_addend = fixP->fx_addnumber;
            }
 
-         /*        md_ri_to_chars ((char *) &ri, ri);        */
          append (&next_object_file_charP, (char *) &ri, sizeof (ri));
        }
     }
-  return;
 }
 
+#endif /* 0 */
+
+#if 0
+
+/* This routine can be subsumed by s_lcomm in read.c.
+   Ian Taylor, Cygnus Support 13 Jul 1993 */
+
+
 static void
 s_bss ()
 {
   char *name;
   char c;
   char *p;
-  int temp, bss_align = 1;
+  int temp, bss_align;
   symbolS *symbolP;
-  extern const char is_end_of_line[256];
 
   name = input_line_pointer;
   c = get_symbol_end ();
@@ -1243,14 +1257,14 @@ s_bss ()
   SKIP_WHITESPACE ();
   if (*input_line_pointer != ',')
     {
-      as_warn ("Expected comma after name");
+      as_warn (_("Expected comma after name"));
       ignore_rest_of_line ();
       return;
     }
   input_line_pointer++;
   if ((temp = get_absolute_expression ()) < 0)
     {
-      as_warn ("BSS length (%d.) <0! Ignored.", temp);
+      as_warn (_("BSS length (%d.) <0! Ignored."), temp);
       ignore_rest_of_line ();
       return;
     }
@@ -1261,31 +1275,178 @@ s_bss ()
     {
       input_line_pointer++;
       bss_align = get_absolute_expression ();
-      while (local_bss_counter % bss_align != 0)
-       local_bss_counter++;
     }
+  else
+    bss_align = 0;
 
-  if (symbolP->sy_other == 0
-      && symbolP->sy_desc == 0
-      && ((symbolP->sy_type == N_BSS
-          && symbolP->sy_value == local_bss_counter)
-         || ((symbolP->sy_type & N_TYPE) == N_UNDF
-             && symbolP->sy_value == 0)))
+  if (!S_IS_DEFINED(symbolP)
+      || S_GET_SEGMENT(symbolP) == SEG_BSS)
     {
-      symbolP->sy_value = local_bss_counter;
-      symbolP->sy_type = N_BSS;
-      symbolP->sy_frag = &bss_address_frag;
-      local_bss_counter += temp;
+      if (! need_pass_2)
+       {
+         char *p;
+         segT current_seg = now_seg;
+         subsegT current_subseg = now_subseg;
+
+         subseg_set (SEG_BSS, 1); /* switch to bss     */
+
+         if (bss_align)
+           frag_align (bss_align, 0, 0);
+
+         /* detach from old frag */
+         if (symbolP->sy_type == N_BSS && symbolP->sy_frag != NULL)
+           symbolP->sy_frag->fr_symbol = NULL;
+
+         symbolP->sy_frag  = frag_now;
+         p = frag_var (rs_org, 1, 1, (relax_substateT)0, symbolP,
+                       (offsetT) temp, (char *)0);
+         *p = 0;
+         S_SET_SEGMENT (symbolP, SEG_BSS);
+
+         subseg_set (current_seg, current_subseg);
+       }
     }
   else
     {
-      as_warn ("Ignoring attempt to re-define symbol from %d. to %d.",
-              symbolP->sy_value, local_bss_counter);
+      as_warn (_("Ignoring attempt to re-define symbol %s."), name);
     }
+
   while (!is_end_of_line[*input_line_pointer])
     {
       input_line_pointer++;
     }
+}
+
+#endif /* 0 */
 
-  return;
+#ifdef M88KCOFF
+
+/* These functions are needed if we are linking with obj-coffbfd.c.
+   That file may be replaced by a more BFD oriented version at some
+   point.  If that happens, these functions should be rexamined.
+
+   Ian Lance Taylor, Cygnus Support, 13 July 1993.  */
+
+/* Given a fixS structure (created by a call to fix_new, above),
+   return the BFD relocation type to use for it.  */
+
+short
+tc_coff_fix2rtype (fixp)
+     fixS *fixp;
+{
+  switch (fixp->fx_r_type)
+    {
+    case RELOC_LO16:
+      return R_LVRT16;
+    case RELOC_HI16:
+      return R_HVRT16;
+    case RELOC_PC16:
+      return R_PCR16L;
+    case RELOC_PC26:
+      return R_PCR26L;
+    case RELOC_32:
+      return R_VRT32;
+    case RELOC_IW16:
+      return R_VRT16;
+    default:
+      abort ();
+    }
 }
+
+/* Apply a fixS to the object file.  Since COFF does not use addends
+   in relocs, the addend is actually stored directly in the object
+   file itself.  */
+
+void
+md_apply_fix (fixp, val)
+     fixS *fixp;
+     long val;
+{
+  char *buf;
+
+  buf = fixp->fx_frag->fr_literal + fixp->fx_where;
+  fixp->fx_offset = 0;
+
+  switch (fixp->fx_r_type)
+    {
+    case RELOC_IW16:
+      fixp->fx_offset = val >> 16;
+      buf[2] = val >> 8;
+      buf[3] = val;
+      break;
+
+    case RELOC_LO16:
+      fixp->fx_offset = val >> 16;
+      buf[0] = val >> 8;
+      buf[1] = val;
+      break;
+
+    case RELOC_HI16:
+      fixp->fx_offset = val >> 16;
+      buf[0] = val >> 8;
+      buf[1] = val;
+      break;
+
+    case RELOC_PC16:
+      buf[0] = val >> 10;
+      buf[1] = val >> 2;
+      break;
+
+    case RELOC_PC26:
+      buf[0] |= (val >> 26) & 0x03;
+      buf[1] = val >> 18;
+      buf[2] = val >> 10;
+      buf[3] = val >> 2;
+      break;
+
+    case RELOC_32:
+      buf[0] = val >> 24;
+      buf[1] = val >> 16;
+      buf[2] = val >> 8;
+      buf[3] = val;
+      break;
+
+    default:
+      abort ();
+    }
+}
+
+/* Where a PC relative offset is calculated from.  On the m88k they
+   are calculated from just after the instruction.  */
+
+long
+md_pcrel_from (fixp)
+     fixS *fixp;
+{
+  switch (fixp->fx_r_type)
+    {
+    case RELOC_PC16:
+      return fixp->fx_frag->fr_address + fixp->fx_where - 2;
+    case RELOC_PC26:
+      return fixp->fx_frag->fr_address + fixp->fx_where;
+    default:
+      abort ();
+    }
+  /*NOTREACHED*/
+}
+
+/* When we align the .init section, insert the correct NOP pattern.  */
+
+int
+m88k_do_align (n, fill, max, len)
+     int n;
+     const char *fill;
+     int len;
+     int max;
+{
+  if (fill == NULL
+      && strcmp (obj_segment_name (now_seg), ".init") == 0)
+    {
+      static const unsigned char nop_pattern[] = { 0xf4, 0x00, 0x58, 0x00 };
+      frag_align_pattern (n, nop_pattern, sizeof (nop_pattern), max);
+      return 1;
+    }
+  return 0;
+}
+
+#endif /* M88KCOFF */