pulled in from hack's unfinished work
authorK. Richard Pixley <rich@cygnus>
Tue, 18 Feb 1992 11:27:34 +0000 (11:27 +0000)
committerK. Richard Pixley <rich@cygnus>
Tue, 18 Feb 1992 11:27:34 +0000 (11:27 +0000)
gas/config/ChangeLog
gas/config/m88k-opcode.h [new file with mode: 0644]
gas/config/tc-m88k.c [new file with mode: 0644]
gas/config/tc-m88k.h [new file with mode: 0644]

index 84254d14db19038e86d2fd356c583c25901dd21c..493f9c322470c33e84f5b2ce803819788f702d78 100644 (file)
@@ -1,5 +1,8 @@
 Tue Feb 18 02:11:10 1992  K. Richard Pixley  (rich at cygnus.com)
 
+       * tc-m88k.[hc]: pulled in from hack's unfinished work.  These
+         aren't yet integrated.
+
        * tc-i860.[hc]: blew off the dust.  Something must still be done
          about conflicting relocation types.
 
diff --git a/gas/config/m88k-opcode.h b/gas/config/m88k-opcode.h
new file mode 100644 (file)
index 0000000..5f685b9
--- /dev/null
@@ -0,0 +1,282 @@
+/* m88k-opcode.h -- Instruction information 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.
+
+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)
+any later version.
+
+GAS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+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.  */
+
+#if !defined(__STDC__) && !defined(const)
+#define const
+#endif
+
+/*
+  Character codes for op_spec field below.
+  Reserved for direct matching: x , [ ]
+
+  d = GRF Destination register (21:5)
+  1 = Source register 1 (16:5)
+  2 = Source register 2 (0:5)
+  3 = Both source registers (same value) (0:5 and 16:5)
+  I = IMM16 (0:16)
+  b = bit field spec. (0:10)
+  p = 16 bit pc displ. (0:16)
+  P = 26 bit pc displ. (0:26)
+  B = bb0/bb1 condition (21:5)
+  M = bcnd condition (21:5)
+  f = fcr (5:6)
+  c = cr (5:6)
+  V = VEC9 (0:9)
+  ? = Give warning for this insn/operand combination
+ */
+
+/* instruction descriptor structure */
+
+struct m88k_opcode
+{
+  unsigned int opcode;
+  char         *name;
+  char         *op_spec;
+};
+
+/* and introducing... the Motorola 88100 instruction sets... */
+
+/* These macros may seem silly, but they are in preparation
+   for future versions of the 88000 family.  */
+
+#define _MC88100(OPCODE,MNEM,OP_SPEC) {OPCODE,MNEM,OP_SPEC},
+#define _MC88xxx(OPCODE,MNEM,OP_SPEC) {OPCODE,MNEM,OP_SPEC},
+
+/* Equal mnemonics must be adjacent.
+   More specific operand specification must go before more general.
+   For example, "d,1,2" must go before "d,1,I" as a register for s2
+   would otherwise be considered a variable name.  */
+
+static struct m88k_opcode m88k_opcodes[] =
+{
+  /*  Opcode     Mnemonic         Opspec */
+
+  _MC88xxx(0xf4007000, "add",          "d,1,2")
+  _MC88xxx(0x70000000, "add",          "d,1,I")
+  _MC88xxx(0xf4007200, "add.ci",       "d,1,2")
+  _MC88xxx(0xf4007300, "add.cio",      "d,1,2")
+  _MC88xxx(0xf4007100, "add.co",       "d,1,2")
+  _MC88xxx(0xf4006000, "addu",         "d,1,2")
+  _MC88xxx(0x60000000, "addu",         "d,1,I")
+  _MC88xxx(0xf4006200, "addu.ci",      "d,1,2")
+  _MC88xxx(0xf4006300, "addu.cio",     "d,1,2")
+  _MC88xxx(0xf4006100, "addu.co",      "d,1,2")
+  _MC88xxx(0xf4004000, "and",          "d,1,2")
+  _MC88xxx(0x40000000, "and",          "d,1,I")
+  _MC88xxx(0xf4004400, "and.c",                "d,1,2")
+  _MC88xxx(0x44000000, "and.u",                "d,1,I")
+  _MC88xxx(0xd0000000, "bb0",          "B,1,p")
+  _MC88xxx(0xd4000000, "bb0.n",                "B,1,p")
+  _MC88xxx(0xd8000000, "bb1",          "B,1,p")
+  _MC88xxx(0xdc000000, "bb1.n",                "B,1,p")
+  _MC88xxx(0xe8000000, "bcnd",         "M,1,p")
+  _MC88xxx(0xec000000, "bcnd.n",       "M,1,p")
+  _MC88xxx(0xc0000000, "br",           "P")
+  _MC88xxx(0xc4000000, "br.n",         "P")
+  _MC88xxx(0xc8000000, "bsr",          "P")
+  _MC88xxx(0xcc000000, "bsr.n",                "P")
+  _MC88xxx(0xf4008000, "clr",          "d,1,2")
+  _MC88xxx(0xf0008000, "clr",          "d,1,b")
+  _MC88xxx(0xf4007c00, "cmp",          "d,1,2")
+  _MC88xxx(0x7c000000, "cmp",          "d,1,I")
+  _MC88xxx(0xf4007800, "div",          "d,1,2")
+  _MC88xxx(0x78000000, "div",          "d,1,I")
+  _MC88xxx(0xf4007800, "divs",         "d,1,2")
+  _MC88xxx(0x78000000, "divs",         "d,1,I")
+  _MC88xxx(0xf4006800, "divu",         "d,1,2")
+  _MC88xxx(0x68000000, "divu",         "d,1,I")
+  _MC88xxx(0xf4009000, "ext",          "d,1,2")
+  _MC88xxx(0xf0009000, "ext",          "d,1,b")
+  _MC88xxx(0xf4009800, "extu",         "d,1,2")
+  _MC88xxx(0xf0009800, "extu",         "d,1,b")
+  _MC88xxx(0x84002800, "fadd.sss",     "d,1,2")
+  _MC88xxx(0x84002880, "fadd.ssd",     "d,1,2")
+  _MC88xxx(0x84002a00, "fadd.sds",     "d,1,2")
+  _MC88xxx(0x84002a80, "fadd.sdd",     "d,1,2")
+  _MC88xxx(0x84002820, "fadd.dss",     "d,1,2")
+  _MC88xxx(0x840028a0, "fadd.dsd",     "d,1,2")
+  _MC88xxx(0x84002a20, "fadd.dds",     "d,1,2")
+  _MC88xxx(0x84002aa0, "fadd.ddd",     "d,1,2")
+  _MC88xxx(0x84003a80, "fcmp.sdd",     "d,1,2")
+  _MC88xxx(0x84003a00, "fcmp.sds",     "d,1,2")
+  _MC88xxx(0x84003880, "fcmp.ssd",     "d,1,2")
+  _MC88xxx(0x84003800, "fcmp.sss",     "d,1,2")
+  _MC88xxx(0x84007000, "fdiv.sss",     "d,1,2")
+  _MC88xxx(0x84007080, "fdiv.ssd",     "d,1,2")
+  _MC88xxx(0x84007200, "fdiv.sds",     "d,1,2")
+  _MC88xxx(0x84007280, "fdiv.sdd",     "d,1,2")
+  _MC88xxx(0x84007020, "fdiv.dss",     "d,1,2")
+  _MC88xxx(0x840070a0, "fdiv.dsd",     "d,1,2")
+  _MC88xxx(0x84007220, "fdiv.dds",     "d,1,2")
+  _MC88xxx(0x840072a0, "fdiv.ddd",     "d,1,2")
+  _MC88xxx(0xf400ec00, "ff0",          "d,2")
+  _MC88xxx(0xf400e800, "ff1",          "d,2")
+  _MC88xxx(0x80004800, "fldcr",                "d,f")
+  _MC88xxx(0x84002020, "flt.ds",       "d,2")
+  _MC88xxx(0x84002000, "flt.ss",       "d,2")
+  _MC88xxx(0x84000000, "fmul.sss",     "d,1,2")
+  _MC88xxx(0x84000080, "fmul.ssd",     "d,1,2")
+  _MC88xxx(0x84000200, "fmul.sds",     "d,1,2")
+  _MC88xxx(0x84000280, "fmul.sdd",     "d,1,2")
+  _MC88xxx(0x84000020, "fmul.dss",     "d,1,2")
+  _MC88xxx(0x840000a0, "fmul.dsd",     "d,1,2")
+  _MC88xxx(0x84000220, "fmul.dds",     "d,1,2")
+  _MC88xxx(0x840002a0, "fmul.ddd",     "d,1,2")
+  _MC88xxx(0x80008800, "fstcr",                "3,f")
+  _MC88xxx(0x84003000, "fsub.sss",     "d,1,2")
+  _MC88xxx(0x84003080, "fsub.ssd",     "d,1,2")
+  _MC88xxx(0x84003200, "fsub.sds",     "d,1,2")
+  _MC88xxx(0x84003280, "fsub.sdd",     "d,1,2")
+  _MC88xxx(0x84003020, "fsub.dss",     "d,1,2")
+  _MC88xxx(0x840030a0, "fsub.dsd",     "d,1,2")
+  _MC88xxx(0x84003220, "fsub.dds",     "d,1,2")
+  _MC88xxx(0x840032a0, "fsub.ddd",     "d,1,2")
+  _MC88xxx(0x8000c800, "fxcr",         "d,3,f")
+  _MC88xxx(0x8400fc01, "illop1",       "")
+  _MC88xxx(0x8400fc02, "illop2",       "")
+  _MC88xxx(0x8400fc03, "illop3",       "")
+  _MC88xxx(0x84004880, "int.sd",       "d,2")
+  _MC88xxx(0x84004800, "int.ss",       "d,2")
+  _MC88xxx(0xf400c000, "jmp",          "2")
+  _MC88xxx(0xf400c400, "jmp.n",                "2")
+  _MC88xxx(0xf400c800, "jsr",          "2")
+  _MC88xxx(0xf400cc00, "jsr.n",                "2")
+  _MC88xxx(0xf4001400, "ld",           "d,1,2")
+  _MC88xxx(0xf4001600, "ld",           "d,1[2]")
+  _MC88xxx(0x14000000, "ld",           "d,1,I")
+  _MC88xxx(0xf4001e00, "ld.b",         "d,1[2]")
+  _MC88xxx(0xf4001c00, "ld.b",         "d,1,2")
+  _MC88xxx(0x1c000000, "ld.b",         "d,1,I")
+  _MC88xxx(0xf4001d00, "ld.b.usr",     "d,1,2")
+  _MC88xxx(0xf4001f00, "ld.b.usr",     "d,1[2]")
+  _MC88xxx(0xf4000e00, "ld.bu",                "d,1[2]")
+  _MC88xxx(0xf4000c00, "ld.bu",                "d,1,2")
+  _MC88xxx(0x0c000000, "ld.bu",                "d,1,I")
+  _MC88xxx(0xf4000d00, "ld.bu.usr",    "d,1,2")
+  _MC88xxx(0xf4000f00, "ld.bu.usr",    "d,1[2]")
+  _MC88xxx(0xf4001200, "ld.d",         "d,1[2]")
+  _MC88xxx(0xf4001000, "ld.d",         "d,1,2")
+  _MC88xxx(0x10000000, "ld.d",         "d,1,I")
+  _MC88xxx(0xf4001100, "ld.d.usr",     "d,1,2")
+  _MC88xxx(0xf4001300, "ld.d.usr",     "d,1[2]")
+  _MC88xxx(0xf4001a00, "ld.h",         "d,1[2]")
+  _MC88xxx(0xf4001800, "ld.h",         "d,1,2")
+  _MC88xxx(0x18000000, "ld.h",         "d,1,I")
+  _MC88xxx(0xf4001900, "ld.h.usr",     "d,1,2")
+  _MC88xxx(0xf4001b00, "ld.h.usr",     "d,1[2]")
+  _MC88xxx(0xf4000a00, "ld.hu",                "d,1[2]")
+  _MC88xxx(0xf4000800, "ld.hu",                "d,1,2")
+  _MC88xxx(0x08000000, "ld.hu",                "d,1,I")
+  _MC88xxx(0xf4000900, "ld.hu.usr",    "d,1,2")
+  _MC88xxx(0xf4000b00, "ld.hu.usr",    "d,1[2]")
+  _MC88xxx(0xf4001500, "ld.usr",       "d,1,2")
+  _MC88xxx(0xf4001700, "ld.usr",       "d,1[2]")
+  _MC88xxx(0xf4003600, "lda",          "d,1[2]")
+  _MC88xxx(0xf4006000, "lda",          "?d,1,2")       /* Output addu */
+  _MC88xxx(0x60000000, "lda",          "?d,1,I")       /* Output addu */
+  _MC88xxx(0xf4006000, "lda.b",                "?d,1[2]")      /* Output addu */
+  _MC88xxx(0xf4006000, "lda.b",                "?d,1,2")       /* Output addu */
+  _MC88xxx(0x60000000, "lda.b",                "?d,1,I")       /* Output addu */
+  _MC88xxx(0xf4003200, "lda.d",                "d,1[2]")
+  _MC88xxx(0xf4006000, "lda.d",                "?d,1,2")       /* Output addu */
+  _MC88xxx(0x60000000, "lda.d",                "?d,1,I")       /* Output addu */
+  _MC88xxx(0xf4003a00, "lda.h",                "d,1[2]")
+  _MC88xxx(0xf4006000, "lda.h",                "?d,1,2")       /* Output addu */
+  _MC88xxx(0x60000000, "lda.h",                "?d,1,I")       /* Output addu */
+  _MC88xxx(0x80004000, "ldcr",         "d,c")
+  _MC88xxx(0xf400a000, "mak",          "d,1,2")
+  _MC88xxx(0xf000a000, "mak",          "d,1,b")
+  _MC88xxx(0x48000000, "mask",         "d,1,I")
+  _MC88xxx(0x4c000000, "mask.u",       "d,1,I")
+  _MC88xxx(0xf4006c00, "mul",          "d,1,2")
+  _MC88xxx(0x6c000000, "mul",          "d,1,I")
+  _MC88xxx(0xf4006c00, "mulu",         "d,1,2")        /* synonym for mul */
+  _MC88xxx(0x6c000000, "mulu",         "d,1,I")        /* synonym for mul */
+  _MC88xxx(0x84005080, "nint.sd",      "d,2")
+  _MC88xxx(0x84005000, "nint.ss",      "d,2")
+  _MC88xxx(0xf4005800, "or",           "d,1,2")
+  _MC88xxx(0x58000000, "or",           "d,1,I")
+  _MC88xxx(0xf4005c00, "or.c",         "d,1,2")
+  _MC88xxx(0x5c000000, "or.u",         "d,1,I")
+  _MC88xxx(0xf000a800, "rot",          "d,1,b")
+  _MC88xxx(0xf400a800, "rot",          "d,1,2")
+  _MC88xxx(0xf400fc00, "rte",          "")
+  _MC88xxx(0xf4008800, "set",          "d,1,2")
+  _MC88xxx(0xf0008800, "set",          "d,1,b")
+  _MC88xxx(0xf4002600, "st",           "d,1[2]")
+  _MC88xxx(0xf4002400, "st",           "d,1,2")
+  _MC88xxx(0x24000000, "st",           "d,1,I")
+  _MC88xxx(0xf4002e00, "st.b",         "d,1[2]")
+  _MC88xxx(0xf4002c00, "st.b",         "d,1,2")
+  _MC88xxx(0x2c000000, "st.b",         "d,1,I")
+  _MC88xxx(0xf4002d00, "st.b.usr",     "d,1,2")
+  _MC88xxx(0xf4002f00, "st.b.usr",     "d,1[2]")
+  _MC88xxx(0xf4002200, "st.d",         "d,1[2]")
+  _MC88xxx(0xf4002000, "st.d",         "d,1,2")
+  _MC88xxx(0x20000000, "st.d",         "d,1,I")
+  _MC88xxx(0xf4002100, "st.d.usr",     "d,1,2")
+  _MC88xxx(0xf4002300, "st.d.usr",     "d,1[2]")
+  _MC88xxx(0xf4002a00, "st.h",         "d,1[2]")
+  _MC88xxx(0xf4002800, "st.h",         "d,1,2")
+  _MC88xxx(0x28000000, "st.h",         "d,1,I")
+  _MC88xxx(0xf4002900, "st.h.usr",     "d,1,2")
+  _MC88xxx(0xf4002b00, "st.h.usr",     "d,1[2]")
+  _MC88xxx(0xf4002500, "st.usr",       "d,1,2")
+  _MC88xxx(0xf4002700, "st.usr",       "d,1[2]")
+  _MC88xxx(0x80008000, "stcr",         "3,c")
+  _MC88xxx(0xf4007400, "sub",          "d,1,2")
+  _MC88xxx(0x74000000, "sub",          "d,1,I")
+  _MC88xxx(0xf4007600, "sub.ci",       "d,1,2")
+  _MC88xxx(0xf4007700, "sub.cio",      "d,1,2")
+  _MC88xxx(0xf4007500, "sub.co",       "d,1,2")
+  _MC88xxx(0xf4006400, "subu",         "d,1,2")
+  _MC88xxx(0x64000000, "subu",         "d,1,I")
+  _MC88xxx(0xf4006600, "subu.ci",      "d,1,2")
+  _MC88xxx(0xf4006700, "subu.cio",     "d,1,2")
+  _MC88xxx(0xf4006500, "subu.co",      "d,1,2")
+  _MC88xxx(0xf000d000, "tb0",          "B,1,V")
+  _MC88xxx(0xf000d800, "tb1",          "B,1,V")
+  _MC88xxx(0xf400f800, "tbnd",         "1,2")
+  _MC88xxx(0xf8000000, "tbnd",         "1,I")
+  _MC88xxx(0xf000e800, "tcnd",         "M,1,V")
+  _MC88xxx(0x84005880, "trnc.sd",      "d,2")
+  _MC88xxx(0x84005800, "trnc.ss",      "d,2")
+  _MC88xxx(0x8000c000, "xcr",          "d,1,c")
+  _MC88xxx(0xf4000600, "xmem",         "d,1[2]")
+  _MC88xxx(0xf4000400, "xmem",         "d,1,2")
+  _MC88100(0x04000000, "xmem",         "?d,1,I")
+  _MC88xxx(0xf4000200, "xmem.bu",      "d,1[2]")
+  _MC88xxx(0xf4000000, "xmem.bu",      "d,1,2")
+  _MC88100(0x00000000, "xmem.bu",      "?d,1,I")
+  _MC88xxx(0xf4000300, "xmem.bu.usr",  "d,1[2]")
+  _MC88xxx(0xf4000100, "xmem.bu.usr",  "d,1,2")
+  _MC88100(0x00000100, "xmem.bu.usr",  "?d,1,I")
+  _MC88xxx(0xf4000700, "xmem.usr",     "d,1[2]")
+  _MC88xxx(0xf4000500, "xmem.usr",     "d,1,2")
+  _MC88100(0x04000100, "xmem.usr",     "?d,1,I")
+  _MC88xxx(0xf4005000, "xor",          "d,1,2")
+  _MC88xxx(0x50000000, "xor",          "d,1,I")
+  _MC88xxx(0xf4005400, "xor.c",                "d,1,2")
+  _MC88xxx(0x54000000, "xor.u",                "d,1,I")
+  _MC88xxx(0x00000000, "",         0)
+};
+
+#define NUMOPCODES ((sizeof m88k_opcodes)/(sizeof m88k_opcodes[0]))
diff --git a/gas/config/tc-m88k.c b/gas/config/tc-m88k.c
new file mode 100644 (file)
index 0000000..67edb55
--- /dev/null
@@ -0,0 +1,1268 @@
+/* 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.
+
+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)
+any later version.
+
+GAS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+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.  */
+
+#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 ();
+
+struct field_val_assoc
+{
+  char *name;
+  unsigned val;
+};
+
+struct field_val_assoc cr_regs[] =
+{
+  {"PID", 0},
+  {"PSR", 1},
+  {"EPSR", 2},
+  {"SSBR", 3},
+  {"SXIP", 4},
+  {"SNIP", 5},
+  {"SFIP", 6},
+  {"VBR", 7},
+  {"DMT0", 8},
+  {"DMD0", 9},
+  {"DMA0", 10},
+  {"DMT1", 11},
+  {"DMD1", 12},
+  {"DMA1", 13},
+  {"DMT2", 14},
+  {"DMD2", 15},
+  {"DMA2", 16},
+  {"SR0", 17},
+  {"SR1", 18},
+  {"SR2", 19},
+  {"SR3", 20},
+
+  {NULL, 0},
+};
+
+struct field_val_assoc fcr_regs[] =
+{
+  {"FPECR", 0},
+  {"FPHS1", 1},
+  {"FPLS1", 2},
+  {"FPHS2", 3},
+  {"FPLS2", 4},
+  {"FPPT", 5},
+  {"FPRH", 6},
+  {"FPRL", 7},
+  {"FPIT", 8},
+
+  {"FPSR", 62},
+  {"FPCR", 63},
+
+  {NULL, 0},
+};
+
+struct field_val_assoc cmpslot[] =
+{
+/* Integer  Floating point */
+               {"nc", 0},
+               {"cp", 1},
+  {"eq", 2},
+  {"ne", 3},
+  {"gt", 4},
+  {"le", 5},
+  {"lt", 6},
+  {"ge", 7},
+  {"hi", 8},   {"ou", 8},
+  {"ls", 9},   {"ib", 9},
+  {"lo", 10},  {"in", 10},
+  {"hs", 11},  {"ob", 11},
+
+  {NULL, 0},
+};
+
+struct field_val_assoc cndmsk[] =
+{
+  {"gt0", 1},
+  {"eq0", 2},
+  {"ge0", 3},
+  {"lt0", 12},
+  {"ne0", 13},
+  {"le0", 14},
+
+  {NULL, 0},
+};
+
+struct m88k_insn
+{
+  unsigned long opcode;
+  expressionS exp;
+  enum reloc_type reloc;
+};
+
+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 */
+char comment_chars[] = ";";
+
+/* These chars only start a comment at the beginning of a line. */
+char line_comment_chars[] = "#";
+
+/* Chars that can be used to separate mant from exp in floating point nums */
+char EXP_CHARS[] = "eE";
+
+/* Chars that mean this number is a floating point constant */
+/* as in 0f123.456 */
+/* or    0H1.234E-12 (see exp chars above) */
+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 ();
+
+const pseudo_typeS md_pseudo_table[] =
+{
+  {"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},
+  {"string", stringer, 0},
+  {"word", cons, 4 },
+  {"zero", s_space, 0},
+  {0}
+};
+
+void
+md_begin ()
+{
+  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 */
+
+  while (*m88k_opcodes[i].name)
+    {
+      char *name = m88k_opcodes[i].name;
+
+      /* hash each mnemonic and record its position */
+
+      retval = hash_insert (op_hash, name, &m88k_opcodes[i]);
+
+      if (retval != NULL && *retval != '\0')
+       as_fatal ("Can't hash instruction '%s':%s",
+                m88k_opcodes[i].name, retval);
+
+      /* skip to next unique mnemonic or end of list */
+
+      for (i++; !strcmp (m88k_opcodes[i].name, name); i++)
+       ;
+    }
+}
+
+void
+md_parse_option (argP, cntP, vecP)
+     char **argP;
+     int *cntP;
+     char ***vecP;
+{
+  as_warn ("unknown option: -%s", *argP);
+}
+
+void
+md_assemble (op)
+     char *op;
+{
+  char *param, *thisfrag;
+  struct m88k_opcode *format;
+  struct m88k_insn insn;
+
+  assert (op);
+
+  /* skip over instruction to find parameters */
+
+  for (param = op; *param != 0 && !isspace (*param); param++)
+    ;
+  if (*param != 0)
+    *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);
+      return;
+    }
+
+  /* try parsing this instruction into insn */
+
+  insn.exp.X_add_symbol = 0;
+  insn.exp.X_subtract_symbol = 0;
+  insn.exp.X_add_number = 0;
+  insn.exp.X_seg = 0;
+  insn.reloc = NO_RELOC;
+
+  while (!calcop (format, param, &insn))
+    {
+      /* if it doesn't parse try the next instruction */
+
+      if (!strcmp (format[0].name, format[1].name))
+       format++;
+      else
+       {
+         as_fatal ("Parameter syntax error");
+         return;
+       }
+    }
+
+  /* grow the current frag and plop in the opcode */
+
+  thisfrag = frag_more (4);
+  md_number_to_chars (thisfrag, insn.opcode, 4);
+
+  /* if this instruction requires labels mark it for later */
+
+  switch (insn.reloc)
+    {
+    case NO_RELOC:
+      break;
+
+    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);
+      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);
+      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);
+      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);
+      break;
+
+    default:
+      as_fatal ("Unknown relocation type");
+      break;
+    }
+}
+
+int
+calcop (format, param, insn)
+     struct m88k_opcode *format;
+     char *param;
+     struct m88k_insn *insn;
+{
+  char *fmt = format->op_spec;
+  int f;
+  unsigned val;
+  unsigned opcode;
+
+  insn->opcode = format->opcode;
+  opcode = 0;
+
+  for (;;)
+    {
+      if (param == 0)
+       return 0;
+      f = *fmt++;
+      switch (f)
+       {
+       case 0:
+         insn->opcode |= opcode;
+         return *param == 0;
+
+       default:
+         if (f != *param++)
+           return 0;
+         break;
+
+       case 'd':
+         param = get_reg (param, &val);
+         opcode |= val << 21;
+         break;
+
+       case '1':
+         param = get_reg (param, &val);
+         opcode |= val << 16;
+         break;
+
+       case '2':
+         param = get_reg (param, &val);
+         opcode |= val;
+         break;
+
+       case '3':
+         param = get_reg (param, &val);
+         opcode |= (val << 16) | val;
+         break;
+
+       case 'I':
+         param = get_imm16 (param, insn);
+         break;
+
+       case 'b':
+         param = get_bf (param, &val);
+         opcode |= val;
+         break;
+
+       case 'p':
+         param = get_pcr (param, insn, RELOC_PC16);
+         break;
+
+       case 'P':
+         param = get_pcr (param, insn, RELOC_PC26);
+         break;
+
+       case 'B':
+         param = get_cmp (param, &val);
+         opcode |= val;
+         break;
+
+       case 'M':
+         param = get_cnd (param, &val);
+         opcode |= val;
+         break;
+
+       case 'c':
+         param = get_cr (param, &val);
+         opcode |= val << 5;
+         break;
+
+       case 'f':
+         param = get_fcr (param, &val);
+         opcode |= val << 5;
+         break;
+
+       case 'V':
+         param = get_vec9 (param, &val);
+         opcode |= val;
+         break;
+
+       case '?':
+         /* Having this here repeats the warning somtimes.
+          But can't we stand that?  */
+         as_warn ("Use of obsolete instruction");
+         break;
+       }
+    }
+}
+
+char *
+match_name (param, assoc_tab, valp)
+     char *param;
+     struct field_val_assoc *assoc_tab;
+     unsigned *valp;
+{
+  int i;
+  char *name;
+  int name_len;
+
+  for (i = 0;; i++)
+    {
+      name = assoc_tab[i].name;
+      if (name == NULL)
+       return NULL;
+      name_len = strlen (name);
+      if (!strncmp (param, name, name_len))
+       {
+         *valp = assoc_tab[i].val;
+         return param + name_len;
+       }
+    }
+}
+
+char *
+get_reg (param, regnop)
+     char *param;
+     unsigned *regnop;
+{
+  unsigned c;
+  unsigned regno;
+
+  c = *param++;
+  if (c == 'r')
+    {
+      regno = *param++ - '0';
+      if (regno < 10)
+       {
+         if (regno == 0)
+           {
+             *regnop = 0;
+             return param;
+           }
+         c = *param - '0';
+         if (c < 10)
+           {
+             regno = regno * 10 + c;
+             if (c < 32)
+               {
+                 *regnop = regno;
+                 return param + 1;
+               }
+           }
+         else
+           {
+             *regnop = regno;
+             return param;
+           }
+       }
+      return NULL;
+    }
+  else if (c == 's' && param[0] == 'p')
+    {
+      *regnop = 31;
+      return param + 1;
+    }
+
+  return 0;
+}
+
+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]))
+    {
+      reloc = RELOC_HI16;
+      param += 4;
+    }
+  else if (!strncmp (param, "lo16", 4) && !isalnum (param[4]))
+    {
+      reloc = RELOC_LO16;
+      param += 4;
+    }
+  else if (!strncmp (param, "iw16", 4) && !isalnum (param[4]))
+    {
+      reloc = RELOC_IW16;
+      param += 4;
+    }
+
+  save_ptr = input_line_pointer;
+  input_line_pointer = param;
+  seg = expression (&insn->exp);
+  param = input_line_pointer;
+  input_line_pointer = save_ptr;
+
+  val = insn->exp.X_add_number;
+
+  if (seg == SEG_ABSOLUTE)
+    {
+      /* 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");
+       }
+
+      if (reloc == RELOC_HI16)
+       val >>= 16;
+
+      insn->opcode |= val & 0xffff;
+      reloc = NO_RELOC;
+    }
+  else if (reloc == NO_RELOC)
+    /* We accept a symbol even without lo16, hi16, etc, and assume
+       lo16 was intended.  */
+    reloc = RELOC_LO16;
+
+  insn->reloc = reloc;
+
+  return param;
+}
+
+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);
+
+  saveparam = input_line_pointer;
+  input_line_pointer = saveptr;
+
+  /* Botch: We should relocate now if SEG_ABSOLUTE.  */
+  insn->reloc = reloc;
+
+  return saveparam;
+}
+
+char *
+get_cmp (param, valp)
+     char *param;
+     unsigned *valp;
+{
+  unsigned int val;
+  char *save_ptr;
+
+  save_ptr = param;
+
+  param = match_name (param, cmpslot, valp);
+  val = *valp;
+
+  if (param == NULL)
+    {
+      param = 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 >= 32)
+       {
+         as_warn ("Expression truncated to 5 bits");
+         val %= 32;
+       }
+    }
+
+  *valp = val << 21;
+  return param;
+}
+
+char *
+get_cnd (param, valp)
+     char *param;
+     unsigned *valp;
+{
+  unsigned int val;
+
+  if (isdigit (*param))
+    {
+      param = getval (param, &val);
+
+      if (val >= 32)
+       {
+         as_warn ("Expression truncated to 5 bits");
+         val %= 32;
+       }
+    }
+  else
+    {
+      if (isupper (*param))
+       *param = tolower (*param);
+
+      if (isupper (param[1]))
+       param[1] = tolower (param[1]);
+
+      param = match_name (param, cndmsk, valp);
+
+      if (param == NULL)
+       return NULL;
+
+      val = *valp;
+    }
+
+  *valp = val << 21;
+  return param;
+}
+
+char *
+get_bf2 (param, bc)
+     char *param;
+     int bc;
+{
+  int depth = 0;
+  int c;
+
+  for (;;)
+    {
+      c = *param;
+      if (c == 0)
+       return param;
+      else if (c == '(')
+       depth++;
+      else if (c == ')')
+       depth--;
+      else if (c == bc && depth <= 0)
+       return param;
+      param++;
+    }
+}
+
+char *
+get_bf_offset_expression (param, offsetp)
+     char *param;
+     unsigned *offsetp;
+{
+  unsigned offset;
+
+  if (isalpha (param[0]))
+    {
+      if (isupper (param[0]))
+       param[0] = tolower (param[0]);
+      if (isupper (param[1]))
+       param[1] = tolower (param[1]);
+
+      param = match_name (param, cmpslot, offsetp);
+
+      return param;
+    }
+  else
+    {
+      input_line_pointer = param;
+      offset = get_absolute_expression ();
+      param = input_line_pointer;
+    }
+
+  *offsetp = offset;
+  return param;
+}
+
+char *
+get_bf (param, valp)
+     char *param;
+     unsigned *valp;
+{
+  unsigned offset = 0;
+  unsigned width = 0;
+  char *xp;
+  char *save_ptr;
+
+  xp = get_bf2 (param, '<');
+
+  save_ptr = input_line_pointer;
+  input_line_pointer = param;
+  if (*xp == 0)
+    {
+      /* We did not find '<'.  We have an offset (width implicitly 32).  */
+      param = get_bf_offset_expression (param, &offset);
+      if (param == NULL)
+       return NULL;
+      input_line_pointer = save_ptr;
+    }
+  else
+    {
+      *xp++ = 0;               /* Overwrite the '<' */
+      param = get_bf2 (xp, '>');
+      if (*param == 0)
+       return NULL;
+      *param++ = 0;            /* Overwrite the '>' */
+
+      width = get_absolute_expression ();
+      xp =  get_bf_offset_expression (xp, &offset);
+      input_line_pointer = save_ptr;
+
+      if (xp + 1 != param)
+       return NULL;
+    }
+
+  *valp = ((width % 32) << 5) | (offset % 32);
+
+  return param;
+}
+
+char *
+get_cr (param, regnop)
+     char *param;
+     unsigned *regnop;
+{
+  unsigned regno;
+  unsigned c;
+  int i;
+  int name_len;
+
+  if (!strncmp (param, "cr", 2))
+    {
+      param += 2;
+
+      regno = *param++ - '0';
+      if (regno < 10)
+       {
+         if (regno == 0)
+           {
+             *regnop = 0;
+             return param;
+           }
+         c = *param - '0';
+         if (c < 10)
+           {
+             regno = regno * 10 + c;
+             if (c < 64)
+               {
+                 *regnop = regno;
+                 return param + 1;
+               }
+           }
+         else
+           {
+             *regnop = regno;
+             return param;
+           }
+       }
+      return NULL;
+    }
+
+  param = match_name (param, cr_regs, regnop);
+
+  return param;
+}
+
+char *
+get_fcr (param, regnop)
+     char *param;
+     unsigned *regnop;
+{
+  unsigned regno;
+  unsigned c;
+  int i;
+  int name_len;
+
+  if (!strncmp (param, "fcr", 3))
+    {
+      param += 3;
+
+      regno = *param++ - '0';
+      if (regno < 10)
+       {
+         if (regno == 0)
+           {
+             *regnop = 0;
+             return param;
+           }
+         c = *param - '0';
+         if (c < 10)
+           {
+             regno = regno * 10 + c;
+             if (c < 64)
+               {
+                 *regnop = regno;
+                 return param + 1;
+               }
+           }
+         else
+           {
+             *regnop = regno;
+             return param;
+           }
+       }
+      return NULL;
+    }
+
+  param = match_name (param, fcr_regs, regnop);
+
+  return param;
+}
+
+char *
+get_vec9 (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 >= 1 << 9)
+    as_warn ("Expression truncated to 9 bits");
+
+  *valp = val % (1 << 9);
+
+  return param;
+}
+  
+#define hexval(z) \
+  (isdigit (z) ? (z) - '0' :                                           \
+   islower (z) ? (z) - 'a' + 10 :                                      \
+   isupper (z) ? (z) - 'A' + 10 : -1)
+
+char *
+getval (param, valp)
+     char *param;
+     unsigned int *valp;
+{
+  unsigned int val = 0;
+  unsigned int c;
+
+  c = *param++;
+  if (c == '0')
+    {
+      c = *param++;
+      if (c == 'x' || c == 'X')
+       {
+         c = *param++;
+         c = hexval (c);
+         while (c < 16)
+           {
+             val = val * 16 + c;
+             c = *param++;
+             c = hexval (c);
+           }
+       }
+      else
+       {
+         c -= '0';
+         while (c < 8)
+           {
+             val = val * 8 + c;
+             c = *param++ - '0';
+           }
+       }
+    }
+  else
+    {
+      c -= '0';
+      while (c < 10)
+       {
+         val = val * 10 + c;
+         c = *param++ - '0';
+       }
+    }
+
+  *valp = val;
+  return param - 1;
+}
+
+void
+md_number_to_chars (buf, val, nbytes)
+char *buf;
+int 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 ();
+    }
+}
+
+void
+md_number_to_imm (buf, val, nbytes, fixP, seg_type)
+unsigned char *buf;
+unsigned int val;
+int nbytes;
+fixS *fixP;
+int seg_type;
+{
+  if (seg_type != N_TEXT || fixP->fx_r_type == NO_RELOC)
+    {
+      switch (nbytes)
+       {
+       case 4:
+         *buf++ = val >> 24;
+         *buf++ = val >> 16;
+       case 2:
+         *buf++ = val >> 8;
+       case 1:
+         *buf = val;
+         break;
+
+       default:
+         abort ();
+       }
+      return;
+    }
+
+  switch (fixP->fx_r_type)
+    {
+    case RELOC_IW16:
+      buf[2] = val >> 8;
+      buf[3] = val;
+      break;
+
+    case RELOC_LO16:
+      buf[0] = val >> 8;
+      buf[1] = val;
+      break;
+
+    case RELOC_HI16:
+      buf[0] = val >> 24;
+      buf[1] = val >> 16;
+      break;
+
+    case RELOC_PC16:
+      val += 4;
+      buf[0] = val >> 10;
+      buf[1] = val >> 2;
+      break;
+
+    case RELOC_PC26:
+      val += 4;
+      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:
+      as_fatal ("Bad relocation type");
+      break;
+    }
+}
+
+void
+md_number_to_disp (buf, val, nbytes)
+char *buf;
+int val;
+int nbytes;
+{
+  as_fatal ("md_number_to_disp not defined");
+  md_number_to_chars (buf, val, nbytes);
+}
+
+void
+md_number_to_field (buf, val, nbytes)
+char *buf;
+int val;
+int nbytes;
+{
+  as_fatal ("md_number_to_field not defined");
+  md_number_to_chars (buf, val, nbytes);
+}
+
+#define MAX_LITTLENUMS 6
+
+/* Turn a string in input_line_pointer into a floating point constant of type
+   type, and store the appropriate bytes in *litP.  The number of LITTLENUMS
+   emitted is stored in *sizeP .  An error message is returned, or NULL on OK.
+ */
+char *
+md_atof (type, litP, sizeP)
+     char type;
+     char *litP;
+     int *sizeP;
+{
+  int  prec;
+  LITTLENUM_TYPE words[MAX_LITTLENUMS];
+  LITTLENUM_TYPE *wordP;
+  char *t;
+  char *atof_ieee ();
+
+  switch (type)
+    {
+    case 'f':
+    case 'F':
+    case 's':
+    case 'S':
+      prec = 2;
+      break;
+
+    case 'd':
+    case 'D':
+    case 'r':
+    case 'R':
+      prec = 4;
+      break;
+
+    case 'x':
+    case 'X':
+      prec = 6;
+      break;
+
+    case 'p':
+    case 'P':
+      prec = 6;
+      break;
+
+    default:
+      *sizeP=0;
+      return "Bad call to MD_ATOF()";
+    }
+  t=atof_ieee (input_line_pointer, type, words);
+  if (t)
+    input_line_pointer=t;
+
+  *sizeP=prec * sizeof (LITTLENUM_TYPE);
+  for (wordP=words;prec--;)
+    {
+      md_number_to_chars (litP, (long) (*wordP++), sizeof (LITTLENUM_TYPE));
+      litP+=sizeof (LITTLENUM_TYPE);
+    }
+  return "";   /* Someone should teach Dean about null pointers */
+}
+
+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;
+     fragS *frag;
+     symbolS *to_symbol;
+{
+  ptr[0] = 0xc0; ptr[1] = 0x00; ptr[2] = 0x00; ptr[3] = 0x00;
+  fix_new (frag,
+          ptr - frag->fr_literal,
+          4,
+          to_symbol,
+          (symbolS *) 0,
+          (long int) 0,
+          0,
+          RELOC_PC26);         /* Botch: Shouldn't this be RELOC_PC16? */
+}
+
+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;
+     fragS *frag;
+     symbolS *to_symbol;
+{
+  ptr[0] = 0xc0; ptr[1] = 0x00; ptr[2] = 0x00; ptr[3] = 0x00;
+  fix_new (frag,
+          ptr - frag->fr_literal,
+          4,
+          to_symbol,
+          (symbolS *) 0,
+          (long int) 0,
+          0,
+          RELOC_PC26);
+}
+
+int
+md_estimate_size_before_relax (fragP, segment_type)
+     fragS *fragP;
+     int segment_type;
+{
+  as_fatal ("Relaxation should never occur");
+}
+
+const relax_typeS md_relax_table[] = {0};
+
+void
+md_convert_frag (fragP)
+     fragS *fragP;
+{
+  as_fatal ("Relaxation should never occur");
+}
+
+void
+md_end ()
+{
+}
+
+/*
+ * Risc relocations are completely different, so it needs
+ * this machine dependent routine to emit them.
+ */
+void
+emit_relocations (fixP, segment_address_in_file)
+    fixS *fixP;
+    relax_addressT segment_address_in_file;
+{
+    struct reloc_info_m88k ri;
+    symbolS *symbolP;
+    extern char *next_object_file_charP;
+
+    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);
+           abort ();
+       }
+
+       if ((symbolP = fixP->fx_addsy) != NULL) {
+           ri.r_address = fixP->fx_frag->fr_address +
+               fixP->fx_where - segment_address_in_file;
+           if ((symbolP->sy_type & N_TYPE) == N_UNDF) {
+               ri.r_extern = 1;
+               ri.r_symbolnum = symbolP->sy_number;
+           } else {
+               ri.r_extern = 0;
+               ri.r_symbolnum = symbolP->sy_type & N_TYPE;
+           }
+           if (symbolP && symbolP->sy_frag) {
+               ri.r_addend = symbolP->sy_frag->fr_address;
+           }
+           ri.r_type = fixP->fx_r_type;
+           if (fixP->fx_pcrel) {
+/*             ri.r_addend -= fixP->fx_where;          */
+               ri.r_addend -= ri.r_address;            
+           } else {
+               ri.r_addend = fixP->fx_addnumber;
+           }
+
+/*         md_ri_to_chars ((char *) &ri, ri);        */
+           append (&next_object_file_charP, (char *)& ri, sizeof (ri));
+       }
+    }
+    return;
+}
+
+static void
+s_bss()
+{
+  char *name;
+  char c;
+  char *p;
+  int temp, bss_align = 1;
+  symbolS *symbolP;
+  extern const char is_end_of_line [256];
+
+  name = input_line_pointer;
+  c = get_symbol_end();
+  p = input_line_pointer;
+  *p = c;
+  SKIP_WHITESPACE();
+  if ( * input_line_pointer != ',' )
+    {
+      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);
+      ignore_rest_of_line();
+      return;
+    }
+  *p = 0;
+  symbolP = symbol_find_or_make(name);
+  *p = c;
+  if (*input_line_pointer == ',')
+    {
+      input_line_pointer++;
+      bss_align = get_absolute_expression();
+      while (local_bss_counter % bss_align != 0)
+       local_bss_counter++;
+    }
+
+  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)))
+    {
+      symbolP->sy_value = local_bss_counter;
+      symbolP->sy_type  = N_BSS;
+      symbolP->sy_frag  = & bss_address_frag;
+      local_bss_counter += temp;
+    }
+  else
+    {
+      as_warn( "Ignoring attempt to re-define symbol from %d. to %d.",
+             symbolP->sy_value, local_bss_counter );
+    }
+  while (!is_end_of_line[*input_line_pointer])
+    {
+      input_line_pointer++;
+    }
+
+  return;
+}
diff --git a/gas/config/tc-m88k.h b/gas/config/tc-m88k.h
new file mode 100644 (file)
index 0000000..9e158c8
--- /dev/null
@@ -0,0 +1,48 @@
+/* m88k.h -- 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.
+
+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)
+any later version.
+
+GAS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+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.  */
+
+/* different type of relocation available in the m88k */
+
+enum reloc_type
+{
+  RELOC_LO16,                  /* lo16(sym) */
+  RELOC_HI16,                  /* hi16(sym) */
+  RELOC_PC16,                  /* bb0, bb1, bcnd */
+  RELOC_PC26,                  /* br, bsr */
+  RELOC_32,                    /* jump tables, etc */
+  RELOC_IW16,                  /* global access through linker regs 28 */
+  NO_RELOC
+};
+
+struct reloc_info_m88k
+{
+    unsigned long int r_address;
+    unsigned int r_symbolnum: 24;
+    unsigned int r_extern   : 1;
+    unsigned int r_pad      : 3;
+    enum reloc_type r_type  : 4;
+    long int r_addend;
+};
+
+#define relocation_info reloc_info_m88k
+
+#define LOCAL_LABEL(name) (name[0] =='@' \
+                         && ( name [1] == 'L' || name [1] == '.' ))