OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [binutils-2.18.50/] [gas/] [config/] [tc-m68k.c] - Diff between revs 156 and 816

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 156 Rev 816
/* tc-m68k.c -- Assemble for the m68k family
/* tc-m68k.c -- Assemble for the m68k family
   Copyright 1987, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
   Copyright 1987, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
 
 
   This file is part of GAS, the GNU Assembler.
   This file is part of GAS, the GNU Assembler.
 
 
   GAS is free software; you can redistribute it and/or modify
   GAS is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3, or (at your option)
   the Free Software Foundation; either version 3, or (at your option)
   any later version.
   any later version.
 
 
   GAS is distributed in the hope that it will be useful,
   GAS is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
   GNU General Public License for more details.
 
 
   You should have received a copy of the GNU General Public License
   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
   along with GAS; see the file COPYING.  If not, write to the Free
   Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
   Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
   02110-1301, USA.  */
   02110-1301, USA.  */
 
 
#include "as.h"
#include "as.h"
#include "safe-ctype.h"
#include "safe-ctype.h"
#include "obstack.h"
#include "obstack.h"
#include "subsegs.h"
#include "subsegs.h"
#include "dwarf2dbg.h"
#include "dwarf2dbg.h"
#include "dw2gencfi.h"
#include "dw2gencfi.h"
 
 
#include "opcode/m68k.h"
#include "opcode/m68k.h"
#include "m68k-parse.h"
#include "m68k-parse.h"
 
 
#if defined (OBJ_ELF)
#if defined (OBJ_ELF)
#include "elf/m68k.h"
#include "elf/m68k.h"
#endif
#endif
 
 
#ifdef M68KCOFF
#ifdef M68KCOFF
#include "obj-coff.h"
#include "obj-coff.h"
#endif
#endif
 
 
/* This string holds the chars that always start a comment.  If the
/* This string holds the chars that always start a comment.  If the
   pre-processor is disabled, these aren't very useful.  The macro
   pre-processor is disabled, these aren't very useful.  The macro
   tc_comment_chars points to this.  We use this, rather than the
   tc_comment_chars points to this.  We use this, rather than the
   usual comment_chars, so that the --bitwise-or option will work.  */
   usual comment_chars, so that the --bitwise-or option will work.  */
#if defined (TE_SVR4) || defined (TE_DELTA)
#if defined (TE_SVR4) || defined (TE_DELTA)
const char *m68k_comment_chars = "|#";
const char *m68k_comment_chars = "|#";
#else
#else
const char *m68k_comment_chars = "|";
const char *m68k_comment_chars = "|";
#endif
#endif
 
 
/* This array holds the chars that only start a comment at the beginning of
/* This array holds the chars that only start a comment at the beginning of
   a line.  If the line seems to have the form '# 123 filename'
   a line.  If the line seems to have the form '# 123 filename'
   .line and .file directives will appear in the pre-processed output */
   .line and .file directives will appear in the pre-processed output */
/* Note that input_file.c hand checks for '#' at the beginning of the
/* Note that input_file.c hand checks for '#' at the beginning of the
   first line of the input file.  This is because the compiler outputs
   first line of the input file.  This is because the compiler outputs
   #NO_APP at the beginning of its output.  */
   #NO_APP at the beginning of its output.  */
/* Also note that comments like this one will always work.  */
/* Also note that comments like this one will always work.  */
const char line_comment_chars[] = "#*";
const char line_comment_chars[] = "#*";
 
 
const char line_separator_chars[] = ";";
const char line_separator_chars[] = ";";
 
 
/* Chars that can be used to separate mant from exp in floating point nums.  */
/* Chars that can be used to separate mant from exp in floating point nums.  */
const char EXP_CHARS[] = "eE";
const char EXP_CHARS[] = "eE";
 
 
/* Chars that mean this number is a floating point constant, as
/* Chars that mean this number is a floating point constant, as
   in "0f12.456" or "0d1.2345e12".  */
   in "0f12.456" or "0d1.2345e12".  */
 
 
const char FLT_CHARS[] = "rRsSfFdDxXeEpP";
const char FLT_CHARS[] = "rRsSfFdDxXeEpP";
 
 
/* Also be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be
/* Also be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be
   changed in read.c .  Ideally it shouldn't have to know about it at all,
   changed in read.c .  Ideally it shouldn't have to know about it at all,
   but nothing is ideal around here.  */
   but nothing is ideal around here.  */
 
 
/* Are we trying to generate PIC code?  If so, absolute references
/* Are we trying to generate PIC code?  If so, absolute references
   ought to be made into linkage table references or pc-relative
   ought to be made into linkage table references or pc-relative
   references.  Not implemented.  For ELF there are other means
   references.  Not implemented.  For ELF there are other means
   to denote pic relocations.  */
   to denote pic relocations.  */
int flag_want_pic;
int flag_want_pic;
 
 
static int flag_short_refs;     /* -l option.  */
static int flag_short_refs;     /* -l option.  */
static int flag_long_jumps;     /* -S option.  */
static int flag_long_jumps;     /* -S option.  */
static int flag_keep_pcrel;     /* --pcrel option.  */
static int flag_keep_pcrel;     /* --pcrel option.  */
 
 
#ifdef REGISTER_PREFIX_OPTIONAL
#ifdef REGISTER_PREFIX_OPTIONAL
int flag_reg_prefix_optional = REGISTER_PREFIX_OPTIONAL;
int flag_reg_prefix_optional = REGISTER_PREFIX_OPTIONAL;
#else
#else
int flag_reg_prefix_optional;
int flag_reg_prefix_optional;
#endif
#endif
 
 
/* Whether --register-prefix-optional was used on the command line.  */
/* Whether --register-prefix-optional was used on the command line.  */
static int reg_prefix_optional_seen;
static int reg_prefix_optional_seen;
 
 
/* The floating point coprocessor to use by default.  */
/* The floating point coprocessor to use by default.  */
static enum m68k_register m68k_float_copnum = COP1;
static enum m68k_register m68k_float_copnum = COP1;
 
 
/* If this is non-zero, then references to number(%pc) will be taken
/* If this is non-zero, then references to number(%pc) will be taken
   to refer to number, rather than to %pc + number.  */
   to refer to number, rather than to %pc + number.  */
static int m68k_abspcadd;
static int m68k_abspcadd;
 
 
/* If this is non-zero, then the quick forms of the move, add, and sub
/* If this is non-zero, then the quick forms of the move, add, and sub
   instructions are used when possible.  */
   instructions are used when possible.  */
static int m68k_quick = 1;
static int m68k_quick = 1;
 
 
/* If this is non-zero, then if the size is not specified for a base
/* If this is non-zero, then if the size is not specified for a base
   or outer displacement, the assembler assumes that the size should
   or outer displacement, the assembler assumes that the size should
   be 32 bits.  */
   be 32 bits.  */
static int m68k_rel32 = 1;
static int m68k_rel32 = 1;
 
 
/* This is non-zero if m68k_rel32 was set from the command line.  */
/* This is non-zero if m68k_rel32 was set from the command line.  */
static int m68k_rel32_from_cmdline;
static int m68k_rel32_from_cmdline;
 
 
/* The default width to use for an index register when using a base
/* The default width to use for an index register when using a base
   displacement.  */
   displacement.  */
static enum m68k_size m68k_index_width_default = SIZE_LONG;
static enum m68k_size m68k_index_width_default = SIZE_LONG;
 
 
/* We want to warn if any text labels are misaligned.  In order to get
/* We want to warn if any text labels are misaligned.  In order to get
   the right line number, we need to record the line number for each
   the right line number, we need to record the line number for each
   label.  */
   label.  */
struct label_line
struct label_line
{
{
  struct label_line *next;
  struct label_line *next;
  symbolS *label;
  symbolS *label;
  char *file;
  char *file;
  unsigned int line;
  unsigned int line;
  int text;
  int text;
};
};
 
 
/* The list of labels.  */
/* The list of labels.  */
 
 
static struct label_line *labels;
static struct label_line *labels;
 
 
/* The current label.  */
/* The current label.  */
 
 
static struct label_line *current_label;
static struct label_line *current_label;
 
 
/* Pointer to list holding the opcodes sorted by name.  */
/* Pointer to list holding the opcodes sorted by name.  */
static struct m68k_opcode const ** m68k_sorted_opcodes;
static struct m68k_opcode const ** m68k_sorted_opcodes;
 
 
/* Its an arbitrary name:  This means I don't approve of it.
/* Its an arbitrary name:  This means I don't approve of it.
   See flames below.  */
   See flames below.  */
static struct obstack robyn;
static struct obstack robyn;
 
 
struct m68k_incant
struct m68k_incant
  {
  {
    const char *m_operands;
    const char *m_operands;
    unsigned long m_opcode;
    unsigned long m_opcode;
    short m_opnum;
    short m_opnum;
    short m_codenum;
    short m_codenum;
    int m_arch;
    int m_arch;
    struct m68k_incant *m_next;
    struct m68k_incant *m_next;
  };
  };
 
 
#define getone(x)       ((((x)->m_opcode)>>16)&0xffff)
#define getone(x)       ((((x)->m_opcode)>>16)&0xffff)
#define gettwo(x)       (((x)->m_opcode)&0xffff)
#define gettwo(x)       (((x)->m_opcode)&0xffff)
 
 
static const enum m68k_register m68000_ctrl[] = { 0 };
static const enum m68k_register m68000_ctrl[] = { 0 };
static const enum m68k_register m68010_ctrl[] = {
static const enum m68k_register m68010_ctrl[] = {
  SFC, DFC, USP, VBR,
  SFC, DFC, USP, VBR,
  0
  0
};
};
static const enum m68k_register m68020_ctrl[] = {
static const enum m68k_register m68020_ctrl[] = {
  SFC, DFC, USP, VBR, CACR, CAAR, MSP, ISP,
  SFC, DFC, USP, VBR, CACR, CAAR, MSP, ISP,
  0
  0
};
};
static const enum m68k_register m68040_ctrl[] = {
static const enum m68k_register m68040_ctrl[] = {
  SFC, DFC, CACR, TC, ITT0, ITT1, DTT0, DTT1,
  SFC, DFC, CACR, TC, ITT0, ITT1, DTT0, DTT1,
  USP, VBR, MSP, ISP, MMUSR, URP, SRP,
  USP, VBR, MSP, ISP, MMUSR, URP, SRP,
  0
  0
};
};
static const enum m68k_register m68060_ctrl[] = {
static const enum m68k_register m68060_ctrl[] = {
  SFC, DFC, CACR, TC, ITT0, ITT1, DTT0, DTT1, BUSCR,
  SFC, DFC, CACR, TC, ITT0, ITT1, DTT0, DTT1, BUSCR,
  USP, VBR, URP, SRP, PCR,
  USP, VBR, URP, SRP, PCR,
  0
  0
};
};
static const enum m68k_register mcf_ctrl[] = {
static const enum m68k_register mcf_ctrl[] = {
  CACR, TC, ACR0, ACR1, ACR2, ACR3, VBR, ROMBAR,
  CACR, TC, ACR0, ACR1, ACR2, ACR3, VBR, ROMBAR,
  RAMBAR0, RAMBAR1, RAMBAR, MBAR,
  RAMBAR0, RAMBAR1, RAMBAR, MBAR,
  0
  0
};
};
static const enum m68k_register mcf51qe_ctrl[] = {
static const enum m68k_register mcf51qe_ctrl[] = {
  VBR,
  VBR,
  0
  0
};
};
static const enum m68k_register mcf5206_ctrl[] = {
static const enum m68k_register mcf5206_ctrl[] = {
  CACR, ACR0, ACR1,  VBR, RAMBAR0, RAMBAR_ALT, MBAR,
  CACR, ACR0, ACR1,  VBR, RAMBAR0, RAMBAR_ALT, MBAR,
  0
  0
};
};
static const enum m68k_register mcf5208_ctrl[] = {
static const enum m68k_register mcf5208_ctrl[] = {
  CACR, ACR0, ACR1, VBR,  RAMBAR, RAMBAR1,
  CACR, ACR0, ACR1, VBR,  RAMBAR, RAMBAR1,
  0
  0
};
};
static const enum m68k_register mcf5210a_ctrl[] = {
static const enum m68k_register mcf5210a_ctrl[] = {
  VBR, CACR, ACR0, ACR1, ROMBAR, RAMBAR, RAMBAR1, MBAR,
  VBR, CACR, ACR0, ACR1, ROMBAR, RAMBAR, RAMBAR1, MBAR,
  0
  0
};
};
static const enum m68k_register mcf5213_ctrl[] = {
static const enum m68k_register mcf5213_ctrl[] = {
  VBR, RAMBAR, RAMBAR1, FLASHBAR,
  VBR, RAMBAR, RAMBAR1, FLASHBAR,
  0
  0
};
};
static const enum m68k_register mcf5216_ctrl[] = {
static const enum m68k_register mcf5216_ctrl[] = {
  VBR, CACR, ACR0, ACR1, FLASHBAR, RAMBAR, RAMBAR1,
  VBR, CACR, ACR0, ACR1, FLASHBAR, RAMBAR, RAMBAR1,
  0
  0
};
};
static const enum m68k_register mcf52223_ctrl[] = {
static const enum m68k_register mcf52223_ctrl[] = {
  VBR, CACR, ACR0, ACR1, FLASHBAR, RAMBAR, RAMBAR1,
  VBR, CACR, ACR0, ACR1, FLASHBAR, RAMBAR, RAMBAR1,
  0
  0
};
};
static const enum m68k_register mcf52235_ctrl[] = {
static const enum m68k_register mcf52235_ctrl[] = {
  VBR, CACR, ACR0, ACR1, FLASHBAR, RAMBAR, RAMBAR1,
  VBR, CACR, ACR0, ACR1, FLASHBAR, RAMBAR, RAMBAR1,
  0
  0
};
};
static const enum m68k_register mcf5225_ctrl[] = {
static const enum m68k_register mcf5225_ctrl[] = {
  VBR, CACR, ACR0, ACR1, FLASHBAR, RAMBAR, MBAR, RAMBAR1,
  VBR, CACR, ACR0, ACR1, FLASHBAR, RAMBAR, MBAR, RAMBAR1,
  0
  0
};
};
static const enum m68k_register mcf5235_ctrl[] = {
static const enum m68k_register mcf5235_ctrl[] = {
  VBR, CACR, ACR0, ACR1, RAMBAR, RAMBAR1,
  VBR, CACR, ACR0, ACR1, RAMBAR, RAMBAR1,
  0
  0
};
};
static const enum m68k_register mcf5249_ctrl[] = {
static const enum m68k_register mcf5249_ctrl[] = {
  VBR, CACR, ACR0, ACR1, RAMBAR0, RAMBAR1, RAMBAR, MBAR, MBAR2,
  VBR, CACR, ACR0, ACR1, RAMBAR0, RAMBAR1, RAMBAR, MBAR, MBAR2,
  0
  0
};
};
static const enum m68k_register mcf5250_ctrl[] = {
static const enum m68k_register mcf5250_ctrl[] = {
  VBR,
  VBR,
  0
  0
};
};
static const enum m68k_register mcf5253_ctrl[] = {
static const enum m68k_register mcf5253_ctrl[] = {
  VBR, CACR, ACR0, ACR1, RAMBAR0, RAMBAR1, RAMBAR, MBAR, MBAR2,
  VBR, CACR, ACR0, ACR1, RAMBAR0, RAMBAR1, RAMBAR, MBAR, MBAR2,
  0
  0
};
};
static const enum m68k_register mcf5271_ctrl[] = {
static const enum m68k_register mcf5271_ctrl[] = {
  VBR, CACR, ACR0, ACR1, RAMBAR, RAMBAR1,
  VBR, CACR, ACR0, ACR1, RAMBAR, RAMBAR1,
  0
  0
};
};
static const enum m68k_register mcf5272_ctrl[] = {
static const enum m68k_register mcf5272_ctrl[] = {
  VBR, CACR, ACR0, ACR1, ROMBAR, RAMBAR_ALT, RAMBAR0, MBAR,
  VBR, CACR, ACR0, ACR1, ROMBAR, RAMBAR_ALT, RAMBAR0, MBAR,
  0
  0
};
};
static const enum m68k_register mcf5275_ctrl[] = {
static const enum m68k_register mcf5275_ctrl[] = {
  VBR, CACR, ACR0, ACR1, RAMBAR, RAMBAR1,
  VBR, CACR, ACR0, ACR1, RAMBAR, RAMBAR1,
  0
  0
};
};
static const enum m68k_register mcf5282_ctrl[] = {
static const enum m68k_register mcf5282_ctrl[] = {
  VBR, CACR, ACR0, ACR1, FLASHBAR, RAMBAR, RAMBAR1,
  VBR, CACR, ACR0, ACR1, FLASHBAR, RAMBAR, RAMBAR1,
  0
  0
};
};
static const enum m68k_register mcf5307_ctrl[] = {
static const enum m68k_register mcf5307_ctrl[] = {
  CACR, ACR0, ACR1,  VBR, RAMBAR0, RAMBAR_ALT, MBAR,
  CACR, ACR0, ACR1,  VBR, RAMBAR0, RAMBAR_ALT, MBAR,
  0
  0
};
};
static const enum m68k_register mcf5329_ctrl[] = {
static const enum m68k_register mcf5329_ctrl[] = {
  VBR, CACR, ACR0, ACR1, RAMBAR, RAMBAR1,
  VBR, CACR, ACR0, ACR1, RAMBAR, RAMBAR1,
  0
  0
};
};
static const enum m68k_register mcf5373_ctrl[] = {
static const enum m68k_register mcf5373_ctrl[] = {
  VBR, CACR, ACR0, ACR1, RAMBAR, RAMBAR1,
  VBR, CACR, ACR0, ACR1, RAMBAR, RAMBAR1,
  0
  0
};
};
static const enum m68k_register mcfv4e_ctrl[] = {
static const enum m68k_register mcfv4e_ctrl[] = {
  CACR, ASID, ACR0, ACR1, ACR2, ACR3, MMUBAR,
  CACR, ASID, ACR0, ACR1, ACR2, ACR3, MMUBAR,
  VBR, PC, ROMBAR0, ROMBAR1, RAMBAR0, RAMBAR1,
  VBR, PC, ROMBAR0, ROMBAR1, RAMBAR0, RAMBAR1,
  MBAR, SECMBAR,
  MBAR, SECMBAR,
  MPCR /* Multiprocessor Control register */,
  MPCR /* Multiprocessor Control register */,
  EDRAMBAR /* Embedded DRAM Base Address Register */,
  EDRAMBAR /* Embedded DRAM Base Address Register */,
  /* Permutation control registers.  */
  /* Permutation control registers.  */
  PCR1U0, PCR1L0, PCR1U1, PCR1L1, PCR2U0, PCR2L0, PCR2U1, PCR2L1,
  PCR1U0, PCR1L0, PCR1U1, PCR1L1, PCR2U0, PCR2L0, PCR2U1, PCR2L1,
  PCR3U0, PCR3L0, PCR3U1, PCR3L1,
  PCR3U0, PCR3L0, PCR3U1, PCR3L1,
  /* Legacy names */
  /* Legacy names */
  TC /* ASID */, BUSCR /* MMUBAR */,
  TC /* ASID */, BUSCR /* MMUBAR */,
  ITT0 /* ACR0 */, ITT1 /* ACR1 */, DTT0 /* ACR2 */, DTT1 /* ACR3 */,
  ITT0 /* ACR0 */, ITT1 /* ACR1 */, DTT0 /* ACR2 */, DTT1 /* ACR3 */,
  MBAR1 /* MBAR */, MBAR2 /* SECMBAR */, MBAR0 /* SECMBAR */,
  MBAR1 /* MBAR */, MBAR2 /* SECMBAR */, MBAR0 /* SECMBAR */,
  ROMBAR /* ROMBAR0 */, RAMBAR /* RAMBAR1 */,
  ROMBAR /* ROMBAR0 */, RAMBAR /* RAMBAR1 */,
  0
  0
};
};
static const enum m68k_register mcf5407_ctrl[] = {
static const enum m68k_register mcf5407_ctrl[] = {
  CACR, ASID, ACR0, ACR1, ACR2, ACR3,
  CACR, ASID, ACR0, ACR1, ACR2, ACR3,
  VBR, PC, RAMBAR0, RAMBAR1, MBAR,
  VBR, PC, RAMBAR0, RAMBAR1, MBAR,
  /* Legacy names */
  /* Legacy names */
  TC /* ASID */,
  TC /* ASID */,
  ITT0 /* ACR0 */, ITT1 /* ACR1 */, DTT0 /* ACR2 */, DTT1 /* ACR3 */,
  ITT0 /* ACR0 */, ITT1 /* ACR1 */, DTT0 /* ACR2 */, DTT1 /* ACR3 */,
  MBAR1 /* MBAR */, RAMBAR /* RAMBAR1 */,
  MBAR1 /* MBAR */, RAMBAR /* RAMBAR1 */,
  0
  0
};
};
static const enum m68k_register mcf54455_ctrl[] = {
static const enum m68k_register mcf54455_ctrl[] = {
  CACR, ASID, ACR0, ACR1, ACR2, ACR3, MMUBAR,
  CACR, ASID, ACR0, ACR1, ACR2, ACR3, MMUBAR,
  VBR, PC, RAMBAR1, MBAR,
  VBR, PC, RAMBAR1, MBAR,
  /* Legacy names */
  /* Legacy names */
  TC /* ASID */, BUSCR /* MMUBAR */,
  TC /* ASID */, BUSCR /* MMUBAR */,
  ITT0 /* ACR0 */, ITT1 /* ACR1 */, DTT0 /* ACR2 */, DTT1 /* ACR3 */,
  ITT0 /* ACR0 */, ITT1 /* ACR1 */, DTT0 /* ACR2 */, DTT1 /* ACR3 */,
  MBAR1 /* MBAR */,  RAMBAR /* RAMBAR1 */,
  MBAR1 /* MBAR */,  RAMBAR /* RAMBAR1 */,
  0
  0
};
};
static const enum m68k_register mcf5475_ctrl[] = {
static const enum m68k_register mcf5475_ctrl[] = {
  CACR, ASID, ACR0, ACR1, ACR2, ACR3, MMUBAR,
  CACR, ASID, ACR0, ACR1, ACR2, ACR3, MMUBAR,
  VBR, PC, RAMBAR0, RAMBAR1, MBAR,
  VBR, PC, RAMBAR0, RAMBAR1, MBAR,
  /* Legacy names */
  /* Legacy names */
  TC /* ASID */, BUSCR /* MMUBAR */,
  TC /* ASID */, BUSCR /* MMUBAR */,
  ITT0 /* ACR0 */, ITT1 /* ACR1 */, DTT0 /* ACR2 */, DTT1 /* ACR3 */,
  ITT0 /* ACR0 */, ITT1 /* ACR1 */, DTT0 /* ACR2 */, DTT1 /* ACR3 */,
  MBAR1 /* MBAR */, RAMBAR /* RAMBAR1 */,
  MBAR1 /* MBAR */, RAMBAR /* RAMBAR1 */,
  0
  0
};
};
static const enum m68k_register mcf5485_ctrl[] = {
static const enum m68k_register mcf5485_ctrl[] = {
  CACR, ASID, ACR0, ACR1, ACR2, ACR3, MMUBAR,
  CACR, ASID, ACR0, ACR1, ACR2, ACR3, MMUBAR,
  VBR, PC, RAMBAR0, RAMBAR1, MBAR,
  VBR, PC, RAMBAR0, RAMBAR1, MBAR,
  /* Legacy names */
  /* Legacy names */
  TC /* ASID */, BUSCR /* MMUBAR */,
  TC /* ASID */, BUSCR /* MMUBAR */,
  ITT0 /* ACR0 */, ITT1 /* ACR1 */, DTT0 /* ACR2 */, DTT1 /* ACR3 */,
  ITT0 /* ACR0 */, ITT1 /* ACR1 */, DTT0 /* ACR2 */, DTT1 /* ACR3 */,
  MBAR1 /* MBAR */, RAMBAR /* RAMBAR1 */,
  MBAR1 /* MBAR */, RAMBAR /* RAMBAR1 */,
  0
  0
};
};
static const enum m68k_register fido_ctrl[] = {
static const enum m68k_register fido_ctrl[] = {
  SFC, DFC, USP, VBR, CAC, MBO,
  SFC, DFC, USP, VBR, CAC, MBO,
  0
  0
};
};
#define cpu32_ctrl m68010_ctrl
#define cpu32_ctrl m68010_ctrl
 
 
static const enum m68k_register *control_regs;
static const enum m68k_register *control_regs;
 
 
/* Internal form of a 68020 instruction.  */
/* Internal form of a 68020 instruction.  */
struct m68k_it
struct m68k_it
{
{
  const char *error;
  const char *error;
  const char *args;             /* List of opcode info.  */
  const char *args;             /* List of opcode info.  */
  int numargs;
  int numargs;
 
 
  int numo;                     /* Number of shorts in opcode.  */
  int numo;                     /* Number of shorts in opcode.  */
  short opcode[11];
  short opcode[11];
 
 
  struct m68k_op operands[6];
  struct m68k_op operands[6];
 
 
  int nexp;                     /* Number of exprs in use.  */
  int nexp;                     /* Number of exprs in use.  */
  struct m68k_exp exprs[4];
  struct m68k_exp exprs[4];
 
 
  int nfrag;                    /* Number of frags we have to produce.  */
  int nfrag;                    /* Number of frags we have to produce.  */
  struct
  struct
    {
    {
      int fragoff;              /* Where in the current opcode the frag ends.  */
      int fragoff;              /* Where in the current opcode the frag ends.  */
      symbolS *fadd;
      symbolS *fadd;
      offsetT foff;
      offsetT foff;
      int fragty;
      int fragty;
    }
    }
  fragb[4];
  fragb[4];
 
 
  int nrel;                     /* Num of reloc strucs in use.  */
  int nrel;                     /* Num of reloc strucs in use.  */
  struct
  struct
    {
    {
      int n;
      int n;
      expressionS exp;
      expressionS exp;
      char wid;
      char wid;
      char pcrel;
      char pcrel;
      /* In a pc relative address the difference between the address
      /* In a pc relative address the difference between the address
         of the offset and the address that the offset is relative
         of the offset and the address that the offset is relative
         to.  This depends on the addressing mode.  Basically this
         to.  This depends on the addressing mode.  Basically this
         is the value to put in the offset field to address the
         is the value to put in the offset field to address the
         first byte of the offset, without regarding the special
         first byte of the offset, without regarding the special
         significance of some values (in the branch instruction, for
         significance of some values (in the branch instruction, for
         example).  */
         example).  */
      int pcrel_fix;
      int pcrel_fix;
#ifdef OBJ_ELF
#ifdef OBJ_ELF
      /* Whether this expression needs special pic relocation, and if
      /* Whether this expression needs special pic relocation, and if
         so, which.  */
         so, which.  */
      enum pic_relocation pic_reloc;
      enum pic_relocation pic_reloc;
#endif
#endif
    }
    }
  reloc[5];                     /* Five is enough???  */
  reloc[5];                     /* Five is enough???  */
};
};
 
 
#define cpu_of_arch(x)          ((x) & (m68000up | mcfisa_a | fido_a))
#define cpu_of_arch(x)          ((x) & (m68000up | mcfisa_a | fido_a))
#define float_of_arch(x)        ((x) & mfloat)
#define float_of_arch(x)        ((x) & mfloat)
#define mmu_of_arch(x)          ((x) & mmmu)
#define mmu_of_arch(x)          ((x) & mmmu)
#define arch_coldfire_p(x)      ((x) & mcfisa_a)
#define arch_coldfire_p(x)      ((x) & mcfisa_a)
#define arch_coldfire_fpu(x)    ((x) & cfloat)
#define arch_coldfire_fpu(x)    ((x) & cfloat)
 
 
/* Macros for determining if cpu supports a specific addressing mode.  */
/* Macros for determining if cpu supports a specific addressing mode.  */
#define HAVE_LONG_DISP(x)       \
#define HAVE_LONG_DISP(x)       \
        ((x) & (m68020|m68030|m68040|m68060|cpu32|fido_a|mcfisa_b|mcfisa_c))
        ((x) & (m68020|m68030|m68040|m68060|cpu32|fido_a|mcfisa_b|mcfisa_c))
#define HAVE_LONG_CALL(x)       \
#define HAVE_LONG_CALL(x)       \
        ((x) & (m68020|m68030|m68040|m68060|cpu32|fido_a|mcfisa_b|mcfisa_c))
        ((x) & (m68020|m68030|m68040|m68060|cpu32|fido_a|mcfisa_b|mcfisa_c))
#define HAVE_LONG_COND(x)       \
#define HAVE_LONG_COND(x)       \
        ((x) & (m68020|m68030|m68040|m68060|cpu32|fido_a|mcfisa_b|mcfisa_c))
        ((x) & (m68020|m68030|m68040|m68060|cpu32|fido_a|mcfisa_b|mcfisa_c))
#define HAVE_LONG_BRANCH(x)     \
#define HAVE_LONG_BRANCH(x)     \
        ((x) & (m68020|m68030|m68040|m68060|cpu32|fido_a|mcfisa_b))
        ((x) & (m68020|m68030|m68040|m68060|cpu32|fido_a|mcfisa_b))
#define LONG_BRANCH_VIA_COND(x) (HAVE_LONG_COND(x) && !HAVE_LONG_BRANCH(x))
#define LONG_BRANCH_VIA_COND(x) (HAVE_LONG_COND(x) && !HAVE_LONG_BRANCH(x))
 
 
static struct m68k_it the_ins;  /* The instruction being assembled.  */
static struct m68k_it the_ins;  /* The instruction being assembled.  */
 
 
#define op(ex)          ((ex)->exp.X_op)
#define op(ex)          ((ex)->exp.X_op)
#define adds(ex)        ((ex)->exp.X_add_symbol)
#define adds(ex)        ((ex)->exp.X_add_symbol)
#define subs(ex)        ((ex)->exp.X_op_symbol)
#define subs(ex)        ((ex)->exp.X_op_symbol)
#define offs(ex)        ((ex)->exp.X_add_number)
#define offs(ex)        ((ex)->exp.X_add_number)
 
 
/* Macros for adding things to the m68k_it struct.  */
/* Macros for adding things to the m68k_it struct.  */
#define addword(w)      (the_ins.opcode[the_ins.numo++] = (w))
#define addword(w)      (the_ins.opcode[the_ins.numo++] = (w))
 
 
/* Like addword, but goes BEFORE general operands.  */
/* Like addword, but goes BEFORE general operands.  */
 
 
static void
static void
insop (int w, const struct m68k_incant *opcode)
insop (int w, const struct m68k_incant *opcode)
{
{
  int z;
  int z;
  for (z = the_ins.numo; z > opcode->m_codenum; --z)
  for (z = the_ins.numo; z > opcode->m_codenum; --z)
    the_ins.opcode[z] = the_ins.opcode[z - 1];
    the_ins.opcode[z] = the_ins.opcode[z - 1];
  for (z = 0; z < the_ins.nrel; z++)
  for (z = 0; z < the_ins.nrel; z++)
    the_ins.reloc[z].n += 2;
    the_ins.reloc[z].n += 2;
  for (z = 0; z < the_ins.nfrag; z++)
  for (z = 0; z < the_ins.nfrag; z++)
    the_ins.fragb[z].fragoff++;
    the_ins.fragb[z].fragoff++;
  the_ins.opcode[opcode->m_codenum] = w;
  the_ins.opcode[opcode->m_codenum] = w;
  the_ins.numo++;
  the_ins.numo++;
}
}
 
 
/* The numo+1 kludge is so we can hit the low order byte of the prev word.
/* The numo+1 kludge is so we can hit the low order byte of the prev word.
   Blecch.  */
   Blecch.  */
static void
static void
add_fix (int width, struct m68k_exp *exp, int pc_rel, int pc_fix)
add_fix (int width, struct m68k_exp *exp, int pc_rel, int pc_fix)
{
{
  the_ins.reloc[the_ins.nrel].n = (width == 'B' || width == '3'
  the_ins.reloc[the_ins.nrel].n = (width == 'B' || width == '3'
                                   ? the_ins.numo * 2 - 1
                                   ? the_ins.numo * 2 - 1
                                   : (width == 'b'
                                   : (width == 'b'
                                      ? the_ins.numo * 2 + 1
                                      ? the_ins.numo * 2 + 1
                                      : the_ins.numo * 2));
                                      : the_ins.numo * 2));
  the_ins.reloc[the_ins.nrel].exp = exp->exp;
  the_ins.reloc[the_ins.nrel].exp = exp->exp;
  the_ins.reloc[the_ins.nrel].wid = width;
  the_ins.reloc[the_ins.nrel].wid = width;
  the_ins.reloc[the_ins.nrel].pcrel_fix = pc_fix;
  the_ins.reloc[the_ins.nrel].pcrel_fix = pc_fix;
#ifdef OBJ_ELF
#ifdef OBJ_ELF
  the_ins.reloc[the_ins.nrel].pic_reloc = exp->pic_reloc;
  the_ins.reloc[the_ins.nrel].pic_reloc = exp->pic_reloc;
#endif
#endif
  the_ins.reloc[the_ins.nrel++].pcrel = pc_rel;
  the_ins.reloc[the_ins.nrel++].pcrel = pc_rel;
}
}
 
 
/* Cause an extra frag to be generated here, inserting up to 10 bytes
/* Cause an extra frag to be generated here, inserting up to 10 bytes
   (that value is chosen in the frag_var call in md_assemble).  TYPE
   (that value is chosen in the frag_var call in md_assemble).  TYPE
   is the subtype of the frag to be generated; its primary type is
   is the subtype of the frag to be generated; its primary type is
   rs_machine_dependent.
   rs_machine_dependent.
 
 
   The TYPE parameter is also used by md_convert_frag_1 and
   The TYPE parameter is also used by md_convert_frag_1 and
   md_estimate_size_before_relax.  The appropriate type of fixup will
   md_estimate_size_before_relax.  The appropriate type of fixup will
   be emitted by md_convert_frag_1.
   be emitted by md_convert_frag_1.
 
 
   ADD becomes the FR_SYMBOL field of the frag, and OFF the FR_OFFSET.  */
   ADD becomes the FR_SYMBOL field of the frag, and OFF the FR_OFFSET.  */
static void
static void
add_frag (symbolS *add, offsetT off, int type)
add_frag (symbolS *add, offsetT off, int type)
{
{
  the_ins.fragb[the_ins.nfrag].fragoff = the_ins.numo;
  the_ins.fragb[the_ins.nfrag].fragoff = the_ins.numo;
  the_ins.fragb[the_ins.nfrag].fadd = add;
  the_ins.fragb[the_ins.nfrag].fadd = add;
  the_ins.fragb[the_ins.nfrag].foff = off;
  the_ins.fragb[the_ins.nfrag].foff = off;
  the_ins.fragb[the_ins.nfrag++].fragty = type;
  the_ins.fragb[the_ins.nfrag++].fragty = type;
}
}
 
 
#define isvar(ex) \
#define isvar(ex) \
  (op (ex) != O_constant && op (ex) != O_big)
  (op (ex) != O_constant && op (ex) != O_big)
 
 
static char *crack_operand (char *str, struct m68k_op *opP);
static char *crack_operand (char *str, struct m68k_op *opP);
static int get_num (struct m68k_exp *exp, int ok);
static int get_num (struct m68k_exp *exp, int ok);
static int reverse_16_bits (int in);
static int reverse_16_bits (int in);
static int reverse_8_bits (int in);
static int reverse_8_bits (int in);
static void install_gen_operand (int mode, int val);
static void install_gen_operand (int mode, int val);
static void install_operand (int mode, int val);
static void install_operand (int mode, int val);
static void s_bss (int);
static void s_bss (int);
static void s_data1 (int);
static void s_data1 (int);
static void s_data2 (int);
static void s_data2 (int);
static void s_even (int);
static void s_even (int);
static void s_proc (int);
static void s_proc (int);
static void s_chip (int);
static void s_chip (int);
static void s_fopt (int);
static void s_fopt (int);
static void s_opt (int);
static void s_opt (int);
static void s_reg (int);
static void s_reg (int);
static void s_restore (int);
static void s_restore (int);
static void s_save (int);
static void s_save (int);
static void s_mri_if (int);
static void s_mri_if (int);
static void s_mri_else (int);
static void s_mri_else (int);
static void s_mri_endi (int);
static void s_mri_endi (int);
static void s_mri_break (int);
static void s_mri_break (int);
static void s_mri_next (int);
static void s_mri_next (int);
static void s_mri_for (int);
static void s_mri_for (int);
static void s_mri_endf (int);
static void s_mri_endf (int);
static void s_mri_repeat (int);
static void s_mri_repeat (int);
static void s_mri_until (int);
static void s_mri_until (int);
static void s_mri_while (int);
static void s_mri_while (int);
static void s_mri_endw (int);
static void s_mri_endw (int);
static void s_m68k_cpu (int);
static void s_m68k_cpu (int);
static void s_m68k_arch (int);
static void s_m68k_arch (int);
 
 
struct m68k_cpu
struct m68k_cpu
{
{
  unsigned long arch;   /* Architecture features.  */
  unsigned long arch;   /* Architecture features.  */
  const enum m68k_register *control_regs;       /* Control regs on chip */
  const enum m68k_register *control_regs;       /* Control regs on chip */
  const char *name;     /* Name */
  const char *name;     /* Name */
  int alias;            /* Alias for a cannonical name.  If 1, then
  int alias;            /* Alias for a cannonical name.  If 1, then
                           succeeds canonical name, if -1 then
                           succeeds canonical name, if -1 then
                           succeeds canonical name, if <-1 ||>1 this is a
                           succeeds canonical name, if <-1 ||>1 this is a
                           deprecated name, and the next/previous name
                           deprecated name, and the next/previous name
                           should be used. */
                           should be used. */
};
};
 
 
/* We hold flags for features explicitly enabled and explicitly
/* We hold flags for features explicitly enabled and explicitly
   disabled.  */
   disabled.  */
static int current_architecture;
static int current_architecture;
static int not_current_architecture;
static int not_current_architecture;
static const struct m68k_cpu *selected_arch;
static const struct m68k_cpu *selected_arch;
static const struct m68k_cpu *selected_cpu;
static const struct m68k_cpu *selected_cpu;
static int initialized;
static int initialized;
 
 
/* Architecture models.  */
/* Architecture models.  */
static const struct m68k_cpu m68k_archs[] =
static const struct m68k_cpu m68k_archs[] =
{
{
  {m68000,                                      m68000_ctrl, "68000", 0},
  {m68000,                                      m68000_ctrl, "68000", 0},
  {m68010,                                      m68010_ctrl, "68010", 0},
  {m68010,                                      m68010_ctrl, "68010", 0},
  {m68020|m68881|m68851,                        m68020_ctrl, "68020", 0},
  {m68020|m68881|m68851,                        m68020_ctrl, "68020", 0},
  {m68030|m68881|m68851,                        m68020_ctrl, "68030", 0},
  {m68030|m68881|m68851,                        m68020_ctrl, "68030", 0},
  {m68040,                                      m68040_ctrl, "68040", 0},
  {m68040,                                      m68040_ctrl, "68040", 0},
  {m68060,                                      m68060_ctrl, "68060", 0},
  {m68060,                                      m68060_ctrl, "68060", 0},
  {cpu32|m68881,                                cpu32_ctrl, "cpu32", 0},
  {cpu32|m68881,                                cpu32_ctrl, "cpu32", 0},
  {fido_a,                                      fido_ctrl, "fidoa", 0},
  {fido_a,                                      fido_ctrl, "fidoa", 0},
  {mcfisa_a|mcfhwdiv,                           NULL, "isaa", 0},
  {mcfisa_a|mcfhwdiv,                           NULL, "isaa", 0},
  {mcfisa_a|mcfhwdiv|mcfisa_aa|mcfusp,          NULL, "isaaplus", 0},
  {mcfisa_a|mcfhwdiv|mcfisa_aa|mcfusp,          NULL, "isaaplus", 0},
  {mcfisa_a|mcfhwdiv|mcfisa_b|mcfusp,           NULL, "isab", 0},
  {mcfisa_a|mcfhwdiv|mcfisa_b|mcfusp,           NULL, "isab", 0},
  {mcfisa_a|mcfhwdiv|mcfisa_c|mcfusp,           NULL, "isac", 0},
  {mcfisa_a|mcfhwdiv|mcfisa_c|mcfusp,           NULL, "isac", 0},
  {mcfisa_a|mcfhwdiv|mcfisa_b|mcfmac|mcfusp,    mcf_ctrl, "cfv4", 0},
  {mcfisa_a|mcfhwdiv|mcfisa_b|mcfmac|mcfusp,    mcf_ctrl, "cfv4", 0},
  {mcfisa_a|mcfhwdiv|mcfisa_b|mcfemac|mcfusp|cfloat, mcfv4e_ctrl, "cfv4e", 0},
  {mcfisa_a|mcfhwdiv|mcfisa_b|mcfemac|mcfusp|cfloat, mcfv4e_ctrl, "cfv4e", 0},
  {0,0,NULL, 0}
  {0,0,NULL, 0}
};
};
 
 
/* Architecture extensions, here 'alias' -1 for m68k, +1 for cf and 0
/* Architecture extensions, here 'alias' -1 for m68k, +1 for cf and 0
   for either.  */
   for either.  */
static const struct m68k_cpu m68k_extensions[] =
static const struct m68k_cpu m68k_extensions[] =
{
{
  {m68851,                                      NULL, "68851", -1},
  {m68851,                                      NULL, "68851", -1},
  {m68881,                                      NULL, "68881", -1},
  {m68881,                                      NULL, "68881", -1},
  {m68881,                                      NULL, "68882", -1},
  {m68881,                                      NULL, "68882", -1},
 
 
  {cfloat|m68881,                               NULL, "float", 0},
  {cfloat|m68881,                               NULL, "float", 0},
 
 
  {mcfhwdiv,                                    NULL, "div", 1},
  {mcfhwdiv,                                    NULL, "div", 1},
  {mcfusp,                                      NULL, "usp", 1},
  {mcfusp,                                      NULL, "usp", 1},
  {mcfmac,                                      NULL, "mac", 1},
  {mcfmac,                                      NULL, "mac", 1},
  {mcfemac,                                     NULL, "emac", 1},
  {mcfemac,                                     NULL, "emac", 1},
 
 
  {0,NULL,NULL, 0}
  {0,NULL,NULL, 0}
};
};
 
 
/* Processor list */
/* Processor list */
static const struct m68k_cpu m68k_cpus[] =
static const struct m68k_cpu m68k_cpus[] =
{
{
  {m68000,                                      m68000_ctrl, "68000", 0},
  {m68000,                                      m68000_ctrl, "68000", 0},
  {m68000,                                      m68000_ctrl, "68ec000", 1},
  {m68000,                                      m68000_ctrl, "68ec000", 1},
  {m68000,                                      m68000_ctrl, "68hc000", 1},
  {m68000,                                      m68000_ctrl, "68hc000", 1},
  {m68000,                                      m68000_ctrl, "68hc001", 1},
  {m68000,                                      m68000_ctrl, "68hc001", 1},
  {m68000,                                      m68000_ctrl, "68008", 1},
  {m68000,                                      m68000_ctrl, "68008", 1},
  {m68000,                                      m68000_ctrl, "68302", 1},
  {m68000,                                      m68000_ctrl, "68302", 1},
  {m68000,                                      m68000_ctrl, "68306", 1},
  {m68000,                                      m68000_ctrl, "68306", 1},
  {m68000,                                      m68000_ctrl, "68307", 1},
  {m68000,                                      m68000_ctrl, "68307", 1},
  {m68000,                                      m68000_ctrl, "68322", 1},
  {m68000,                                      m68000_ctrl, "68322", 1},
  {m68000,                                      m68000_ctrl, "68356", 1},
  {m68000,                                      m68000_ctrl, "68356", 1},
  {m68010,                                      m68010_ctrl, "68010", 0},
  {m68010,                                      m68010_ctrl, "68010", 0},
  {m68020|m68881|m68851,                        m68020_ctrl, "68020", 0},
  {m68020|m68881|m68851,                        m68020_ctrl, "68020", 0},
  {m68020|m68881|m68851,                        m68020_ctrl, "68k", 1},
  {m68020|m68881|m68851,                        m68020_ctrl, "68k", 1},
  {m68020|m68881|m68851,                        m68020_ctrl, "68ec020", 1},
  {m68020|m68881|m68851,                        m68020_ctrl, "68ec020", 1},
  {m68030|m68881|m68851,                        m68020_ctrl, "68030", 0},
  {m68030|m68881|m68851,                        m68020_ctrl, "68030", 0},
  {m68030|m68881|m68851,                        m68020_ctrl, "68ec030", 1},
  {m68030|m68881|m68851,                        m68020_ctrl, "68ec030", 1},
  {m68040,                                      m68040_ctrl, "68040", 0},
  {m68040,                                      m68040_ctrl, "68040", 0},
  {m68040,                                      m68040_ctrl, "68ec040", 1},
  {m68040,                                      m68040_ctrl, "68ec040", 1},
  {m68060,                                      m68060_ctrl, "68060", 0},
  {m68060,                                      m68060_ctrl, "68060", 0},
  {m68060,                                      m68060_ctrl, "68ec060", 1},
  {m68060,                                      m68060_ctrl, "68ec060", 1},
 
 
  {cpu32|m68881,                                cpu32_ctrl, "cpu32",  0},
  {cpu32|m68881,                                cpu32_ctrl, "cpu32",  0},
  {cpu32|m68881,                                cpu32_ctrl, "68330", 1},
  {cpu32|m68881,                                cpu32_ctrl, "68330", 1},
  {cpu32|m68881,                                cpu32_ctrl, "68331", 1},
  {cpu32|m68881,                                cpu32_ctrl, "68331", 1},
  {cpu32|m68881,                                cpu32_ctrl, "68332", 1},
  {cpu32|m68881,                                cpu32_ctrl, "68332", 1},
  {cpu32|m68881,                                cpu32_ctrl, "68333", 1},
  {cpu32|m68881,                                cpu32_ctrl, "68333", 1},
  {cpu32|m68881,                                cpu32_ctrl, "68334", 1},
  {cpu32|m68881,                                cpu32_ctrl, "68334", 1},
  {cpu32|m68881,                                cpu32_ctrl, "68336", 1},
  {cpu32|m68881,                                cpu32_ctrl, "68336", 1},
  {cpu32|m68881,                                cpu32_ctrl, "68340", 1},
  {cpu32|m68881,                                cpu32_ctrl, "68340", 1},
  {cpu32|m68881,                                cpu32_ctrl, "68341", 1},
  {cpu32|m68881,                                cpu32_ctrl, "68341", 1},
  {cpu32|m68881,                                cpu32_ctrl, "68349", 1},
  {cpu32|m68881,                                cpu32_ctrl, "68349", 1},
  {cpu32|m68881,                                cpu32_ctrl, "68360", 1},
  {cpu32|m68881,                                cpu32_ctrl, "68360", 1},
 
 
  {mcfisa_a|mcfisa_c|mcfusp,                    mcf51qe_ctrl, "51qe", 0},
  {mcfisa_a|mcfisa_c|mcfusp,                    mcf51qe_ctrl, "51qe", 0},
 
 
  {mcfisa_a,                                    mcf_ctrl, "5200", 0},
  {mcfisa_a,                                    mcf_ctrl, "5200", 0},
  {mcfisa_a,                                    mcf_ctrl, "5202", 1},
  {mcfisa_a,                                    mcf_ctrl, "5202", 1},
  {mcfisa_a,                                    mcf_ctrl, "5204", 1},
  {mcfisa_a,                                    mcf_ctrl, "5204", 1},
  {mcfisa_a,                                    mcf5206_ctrl, "5206", 1},
  {mcfisa_a,                                    mcf5206_ctrl, "5206", 1},
 
 
  {mcfisa_a|mcfhwdiv|mcfmac,                    mcf5206_ctrl, "5206e", 0},
  {mcfisa_a|mcfhwdiv|mcfmac,                    mcf5206_ctrl, "5206e", 0},
 
 
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp,  mcf5208_ctrl, "5207", -1},
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp,  mcf5208_ctrl, "5207", -1},
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp,  mcf5208_ctrl, "5208", 0},
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp,  mcf5208_ctrl, "5208", 0},
 
 
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfmac|mcfusp,   mcf5210a_ctrl, "5210a", 0},
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfmac|mcfusp,   mcf5210a_ctrl, "5210a", 0},
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfmac|mcfusp,   mcf5210a_ctrl, "5211a", 1},
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfmac|mcfusp,   mcf5210a_ctrl, "5211a", 1},
 
 
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfmac|mcfusp,   mcf5213_ctrl, "5211", -1},
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfmac|mcfusp,   mcf5213_ctrl, "5211", -1},
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfmac|mcfusp,   mcf5213_ctrl, "5212", -1},
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfmac|mcfusp,   mcf5213_ctrl, "5212", -1},
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfmac|mcfusp,   mcf5213_ctrl, "5213", 0},
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfmac|mcfusp,   mcf5213_ctrl, "5213", 0},
 
 
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp,  mcf5216_ctrl, "5214", -1},
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp,  mcf5216_ctrl, "5214", -1},
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp,  mcf5216_ctrl, "5216", 0},
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp,  mcf5216_ctrl, "5216", 0},
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp,  mcf5216_ctrl, "521x", 2},
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp,  mcf5216_ctrl, "521x", 2},
 
 
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfmac|mcfusp,   mcf52223_ctrl, "52221", -1},
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfmac|mcfusp,   mcf52223_ctrl, "52221", -1},
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfmac|mcfusp,   mcf52223_ctrl, "52223", 0},
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfmac|mcfusp,   mcf52223_ctrl, "52223", 0},
 
 
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp,  mcf52235_ctrl, "52230", -1},
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp,  mcf52235_ctrl, "52230", -1},
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp,  mcf52235_ctrl, "52233", -1},
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp,  mcf52235_ctrl, "52233", -1},
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp,  mcf52235_ctrl, "52234", -1},
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp,  mcf52235_ctrl, "52234", -1},
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp,  mcf52235_ctrl, "52235", 0},
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp,  mcf52235_ctrl, "52235", 0},
 
 
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfmac|mcfusp,   mcf5225_ctrl, "5224", -1},
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfmac|mcfusp,   mcf5225_ctrl, "5224", -1},
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfmac|mcfusp,   mcf5225_ctrl, "5225", 0},
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfmac|mcfusp,   mcf5225_ctrl, "5225", 0},
 
 
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp,  mcf5235_ctrl, "5232", -1},
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp,  mcf5235_ctrl, "5232", -1},
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp,  mcf5235_ctrl, "5233", -1},
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp,  mcf5235_ctrl, "5233", -1},
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp,  mcf5235_ctrl, "5234", -1},
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp,  mcf5235_ctrl, "5234", -1},
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp,  mcf5235_ctrl, "5235", -1},
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp,  mcf5235_ctrl, "5235", -1},
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp,  mcf5235_ctrl, "523x", 0},
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp,  mcf5235_ctrl, "523x", 0},
 
 
  {mcfisa_a|mcfhwdiv|mcfemac,                   mcf5249_ctrl, "5249", 0},
  {mcfisa_a|mcfhwdiv|mcfemac,                   mcf5249_ctrl, "5249", 0},
  {mcfisa_a|mcfhwdiv|mcfemac,                   mcf5250_ctrl, "5250", 0},
  {mcfisa_a|mcfhwdiv|mcfemac,                   mcf5250_ctrl, "5250", 0},
  {mcfisa_a|mcfhwdiv|mcfemac,                   mcf5253_ctrl, "5253", 0},
  {mcfisa_a|mcfhwdiv|mcfemac,                   mcf5253_ctrl, "5253", 0},
 
 
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp,  mcf5271_ctrl, "5270", -1},
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp,  mcf5271_ctrl, "5270", -1},
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp,  mcf5271_ctrl, "5271", 0},
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp,  mcf5271_ctrl, "5271", 0},
 
 
  {mcfisa_a|mcfhwdiv|mcfmac,                    mcf5272_ctrl, "5272", 0},
  {mcfisa_a|mcfhwdiv|mcfmac,                    mcf5272_ctrl, "5272", 0},
 
 
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp,  mcf5275_ctrl, "5274", -1},
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp,  mcf5275_ctrl, "5274", -1},
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp,  mcf5275_ctrl, "5275", 0},
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp,  mcf5275_ctrl, "5275", 0},
 
 
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp,  mcf5282_ctrl, "5280", -1},
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp,  mcf5282_ctrl, "5280", -1},
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp,  mcf5282_ctrl, "5281", -1},
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp,  mcf5282_ctrl, "5281", -1},
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp,  mcf5282_ctrl, "5282", -1},
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp,  mcf5282_ctrl, "5282", -1},
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp,  mcf5282_ctrl, "528x", 0},
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp,  mcf5282_ctrl, "528x", 0},
 
 
  {mcfisa_a|mcfhwdiv|mcfmac,                    mcf5307_ctrl, "5307", 0},
  {mcfisa_a|mcfhwdiv|mcfmac,                    mcf5307_ctrl, "5307", 0},
 
 
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp,  mcf5329_ctrl, "5327", -1},
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp,  mcf5329_ctrl, "5327", -1},
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp,  mcf5329_ctrl, "5328", -1},
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp,  mcf5329_ctrl, "5328", -1},
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp,  mcf5329_ctrl, "5329", -1},
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp,  mcf5329_ctrl, "5329", -1},
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp,  mcf5329_ctrl, "532x", 0},
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp,  mcf5329_ctrl, "532x", 0},
 
 
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp,  mcf5373_ctrl, "5372", -1},
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp,  mcf5373_ctrl, "5372", -1},
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp,  mcf5373_ctrl, "5373", -1},
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp,  mcf5373_ctrl, "5373", -1},
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp,  mcf5373_ctrl, "537x", 0},
  {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp,  mcf5373_ctrl, "537x", 0},
 
 
  {mcfisa_a|mcfisa_b|mcfhwdiv|mcfmac,           mcf5407_ctrl, "5407",0},
  {mcfisa_a|mcfisa_b|mcfhwdiv|mcfmac,           mcf5407_ctrl, "5407",0},
 
 
  {mcfisa_a|mcfisa_c|mcfhwdiv|mcfemac|mcfusp,   mcf54455_ctrl, "54450", -1},
  {mcfisa_a|mcfisa_c|mcfhwdiv|mcfemac|mcfusp,   mcf54455_ctrl, "54450", -1},
  {mcfisa_a|mcfisa_c|mcfhwdiv|mcfemac|mcfusp,   mcf54455_ctrl, "54451", -1},
  {mcfisa_a|mcfisa_c|mcfhwdiv|mcfemac|mcfusp,   mcf54455_ctrl, "54451", -1},
  {mcfisa_a|mcfisa_c|mcfhwdiv|mcfemac|mcfusp,   mcf54455_ctrl, "54452", -1},
  {mcfisa_a|mcfisa_c|mcfhwdiv|mcfemac|mcfusp,   mcf54455_ctrl, "54452", -1},
  {mcfisa_a|mcfisa_c|mcfhwdiv|mcfemac|mcfusp,   mcf54455_ctrl, "54453", -1},
  {mcfisa_a|mcfisa_c|mcfhwdiv|mcfemac|mcfusp,   mcf54455_ctrl, "54453", -1},
  {mcfisa_a|mcfisa_c|mcfhwdiv|mcfemac|mcfusp,   mcf54455_ctrl, "54454", -1},
  {mcfisa_a|mcfisa_c|mcfhwdiv|mcfemac|mcfusp,   mcf54455_ctrl, "54454", -1},
  {mcfisa_a|mcfisa_c|mcfhwdiv|mcfemac|mcfusp,   mcf54455_ctrl, "54455", 0},
  {mcfisa_a|mcfisa_c|mcfhwdiv|mcfemac|mcfusp,   mcf54455_ctrl, "54455", 0},
 
 
  {mcfisa_a|mcfisa_b|mcfhwdiv|mcfemac|mcfusp|cfloat, mcf5475_ctrl, "5470", -1},
  {mcfisa_a|mcfisa_b|mcfhwdiv|mcfemac|mcfusp|cfloat, mcf5475_ctrl, "5470", -1},
  {mcfisa_a|mcfisa_b|mcfhwdiv|mcfemac|mcfusp|cfloat, mcf5475_ctrl, "5471", -1},
  {mcfisa_a|mcfisa_b|mcfhwdiv|mcfemac|mcfusp|cfloat, mcf5475_ctrl, "5471", -1},
  {mcfisa_a|mcfisa_b|mcfhwdiv|mcfemac|mcfusp|cfloat, mcf5475_ctrl, "5472", -1},
  {mcfisa_a|mcfisa_b|mcfhwdiv|mcfemac|mcfusp|cfloat, mcf5475_ctrl, "5472", -1},
  {mcfisa_a|mcfisa_b|mcfhwdiv|mcfemac|mcfusp|cfloat, mcf5475_ctrl, "5473", -1},
  {mcfisa_a|mcfisa_b|mcfhwdiv|mcfemac|mcfusp|cfloat, mcf5475_ctrl, "5473", -1},
  {mcfisa_a|mcfisa_b|mcfhwdiv|mcfemac|mcfusp|cfloat, mcf5475_ctrl, "5474", -1},
  {mcfisa_a|mcfisa_b|mcfhwdiv|mcfemac|mcfusp|cfloat, mcf5475_ctrl, "5474", -1},
  {mcfisa_a|mcfisa_b|mcfhwdiv|mcfemac|mcfusp|cfloat, mcf5475_ctrl, "5475", -1},
  {mcfisa_a|mcfisa_b|mcfhwdiv|mcfemac|mcfusp|cfloat, mcf5475_ctrl, "5475", -1},
  {mcfisa_a|mcfisa_b|mcfhwdiv|mcfemac|mcfusp|cfloat, mcf5475_ctrl, "547x", 0},
  {mcfisa_a|mcfisa_b|mcfhwdiv|mcfemac|mcfusp|cfloat, mcf5475_ctrl, "547x", 0},
 
 
  {mcfisa_a|mcfisa_b|mcfhwdiv|mcfemac|mcfusp|cfloat, mcf5485_ctrl, "5480", -1},
  {mcfisa_a|mcfisa_b|mcfhwdiv|mcfemac|mcfusp|cfloat, mcf5485_ctrl, "5480", -1},
  {mcfisa_a|mcfisa_b|mcfhwdiv|mcfemac|mcfusp|cfloat, mcf5485_ctrl, "5481", -1},
  {mcfisa_a|mcfisa_b|mcfhwdiv|mcfemac|mcfusp|cfloat, mcf5485_ctrl, "5481", -1},
  {mcfisa_a|mcfisa_b|mcfhwdiv|mcfemac|mcfusp|cfloat, mcf5485_ctrl, "5482", -1},
  {mcfisa_a|mcfisa_b|mcfhwdiv|mcfemac|mcfusp|cfloat, mcf5485_ctrl, "5482", -1},
  {mcfisa_a|mcfisa_b|mcfhwdiv|mcfemac|mcfusp|cfloat, mcf5485_ctrl, "5483", -1},
  {mcfisa_a|mcfisa_b|mcfhwdiv|mcfemac|mcfusp|cfloat, mcf5485_ctrl, "5483", -1},
  {mcfisa_a|mcfisa_b|mcfhwdiv|mcfemac|mcfusp|cfloat, mcf5485_ctrl, "5484", -1},
  {mcfisa_a|mcfisa_b|mcfhwdiv|mcfemac|mcfusp|cfloat, mcf5485_ctrl, "5484", -1},
  {mcfisa_a|mcfisa_b|mcfhwdiv|mcfemac|mcfusp|cfloat, mcf5485_ctrl, "5485", -1},
  {mcfisa_a|mcfisa_b|mcfhwdiv|mcfemac|mcfusp|cfloat, mcf5485_ctrl, "5485", -1},
  {mcfisa_a|mcfisa_b|mcfhwdiv|mcfemac|mcfusp|cfloat, mcf5485_ctrl, "548x", 0},
  {mcfisa_a|mcfisa_b|mcfhwdiv|mcfemac|mcfusp|cfloat, mcf5485_ctrl, "548x", 0},
 
 
  {fido_a,                              fido_ctrl, "fidoa", 0},
  {fido_a,                              fido_ctrl, "fidoa", 0},
  {fido_a,                              fido_ctrl, "fido", 1},
  {fido_a,                              fido_ctrl, "fido", 1},
 
 
  {0,NULL,NULL, 0}
  {0,NULL,NULL, 0}
  };
  };
 
 
static const struct m68k_cpu *m68k_lookup_cpu
static const struct m68k_cpu *m68k_lookup_cpu
(const char *, const struct m68k_cpu *, int, int *);
(const char *, const struct m68k_cpu *, int, int *);
static int m68k_set_arch (const char *, int, int);
static int m68k_set_arch (const char *, int, int);
static int m68k_set_cpu (const char *, int, int);
static int m68k_set_cpu (const char *, int, int);
static int m68k_set_extension (const char *, int, int);
static int m68k_set_extension (const char *, int, int);
static void m68k_init_arch (void);
static void m68k_init_arch (void);
 
 
/* This is the assembler relaxation table for m68k. m68k is a rich CISC
/* This is the assembler relaxation table for m68k. m68k is a rich CISC
   architecture and we have a lot of relaxation modes.  */
   architecture and we have a lot of relaxation modes.  */
 
 
/* Macros used in the relaxation code.  */
/* Macros used in the relaxation code.  */
#define TAB(x,y)        (((x) << 2) + (y))
#define TAB(x,y)        (((x) << 2) + (y))
#define TABTYPE(x)      ((x) >> 2)
#define TABTYPE(x)      ((x) >> 2)
 
 
/* Relaxation states.  */
/* Relaxation states.  */
#define BYTE            0
#define BYTE            0
#define SHORT           1
#define SHORT           1
#define LONG            2
#define LONG            2
#define SZ_UNDEF        3
#define SZ_UNDEF        3
 
 
/* Here are all the relaxation modes we support.  First we can relax ordinary
/* Here are all the relaxation modes we support.  First we can relax ordinary
   branches.  On 68020 and higher and on CPU32 all branch instructions take
   branches.  On 68020 and higher and on CPU32 all branch instructions take
   three forms, so on these CPUs all branches always remain as such.  When we
   three forms, so on these CPUs all branches always remain as such.  When we
   have to expand to the LONG form on a 68000, though, we substitute an
   have to expand to the LONG form on a 68000, though, we substitute an
   absolute jump instead.  This is a direct replacement for unconditional
   absolute jump instead.  This is a direct replacement for unconditional
   branches and a branch over a jump for conditional branches.  However, if the
   branches and a branch over a jump for conditional branches.  However, if the
   user requires PIC and disables this with --pcrel, we can only relax between
   user requires PIC and disables this with --pcrel, we can only relax between
   BYTE and SHORT forms, punting if that isn't enough.  This gives us four
   BYTE and SHORT forms, punting if that isn't enough.  This gives us four
   different relaxation modes for branches:  */
   different relaxation modes for branches:  */
 
 
#define BRANCHBWL       0        /* Branch byte, word, or long.  */
#define BRANCHBWL       0        /* Branch byte, word, or long.  */
#define BRABSJUNC       1       /* Absolute jump for LONG, unconditional.  */
#define BRABSJUNC       1       /* Absolute jump for LONG, unconditional.  */
#define BRABSJCOND      2       /* Absolute jump for LONG, conditional.  */
#define BRABSJCOND      2       /* Absolute jump for LONG, conditional.  */
#define BRANCHBW        3       /* Branch byte or word.  */
#define BRANCHBW        3       /* Branch byte or word.  */
 
 
/* We also relax coprocessor branches and DBcc's.  All CPUs that support
/* We also relax coprocessor branches and DBcc's.  All CPUs that support
   coprocessor branches support them in word and long forms, so we have only
   coprocessor branches support them in word and long forms, so we have only
   one relaxation mode for them.  DBcc's are word only on all CPUs.  We can
   one relaxation mode for them.  DBcc's are word only on all CPUs.  We can
   relax them to the LONG form with a branch-around sequence.  This sequence
   relax them to the LONG form with a branch-around sequence.  This sequence
   can use a long branch (if available) or an absolute jump (if acceptable).
   can use a long branch (if available) or an absolute jump (if acceptable).
   This gives us two relaxation modes.  If long branches are not available and
   This gives us two relaxation modes.  If long branches are not available and
   absolute jumps are not acceptable, we don't relax DBcc's.  */
   absolute jumps are not acceptable, we don't relax DBcc's.  */
 
 
#define FBRANCH         4       /* Coprocessor branch.  */
#define FBRANCH         4       /* Coprocessor branch.  */
#define DBCCLBR         5       /* DBcc relaxable with a long branch.  */
#define DBCCLBR         5       /* DBcc relaxable with a long branch.  */
#define DBCCABSJ        6       /* DBcc relaxable with an absolute jump.  */
#define DBCCABSJ        6       /* DBcc relaxable with an absolute jump.  */
 
 
/* That's all for instruction relaxation.  However, we also relax PC-relative
/* That's all for instruction relaxation.  However, we also relax PC-relative
   operands.  Specifically, we have three operand relaxation modes.  On the
   operands.  Specifically, we have three operand relaxation modes.  On the
   68000 PC-relative operands can only be 16-bit, but on 68020 and higher and
   68000 PC-relative operands can only be 16-bit, but on 68020 and higher and
   on CPU32 they may be 16-bit or 32-bit.  For the latter we relax between the
   on CPU32 they may be 16-bit or 32-bit.  For the latter we relax between the
   two.  Also PC+displacement+index operands in their simple form (with a non-
   two.  Also PC+displacement+index operands in their simple form (with a non-
   suppressed index without memory indirection) are supported on all CPUs, but
   suppressed index without memory indirection) are supported on all CPUs, but
   on the 68000 the displacement can be 8-bit only, whereas on 68020 and higher
   on the 68000 the displacement can be 8-bit only, whereas on 68020 and higher
   and on CPU32 we relax it to SHORT and LONG forms as well using the extended
   and on CPU32 we relax it to SHORT and LONG forms as well using the extended
   form of the PC+displacement+index operand.  Finally, some absolute operands
   form of the PC+displacement+index operand.  Finally, some absolute operands
   can be relaxed down to 16-bit PC-relative.  */
   can be relaxed down to 16-bit PC-relative.  */
 
 
#define PCREL1632       7       /* 16-bit or 32-bit PC-relative.  */
#define PCREL1632       7       /* 16-bit or 32-bit PC-relative.  */
#define PCINDEX         8       /* PC + displacement + index. */
#define PCINDEX         8       /* PC + displacement + index. */
#define ABSTOPCREL      9       /* Absolute relax down to 16-bit PC-relative.  */
#define ABSTOPCREL      9       /* Absolute relax down to 16-bit PC-relative.  */
 
 
/* This relaxation is required for branches where there is no long
/* This relaxation is required for branches where there is no long
   branch and we are in pcrel mode.  We generate a bne/beq pair.  */
   branch and we are in pcrel mode.  We generate a bne/beq pair.  */
#define BRANCHBWPL      10      /* Branch byte, word or pair of longs
#define BRANCHBWPL      10      /* Branch byte, word or pair of longs
                                   */
                                   */
 
 
/* Note that calls to frag_var need to specify the maximum expansion
/* Note that calls to frag_var need to specify the maximum expansion
   needed; this is currently 12 bytes for bne/beq pair.  */
   needed; this is currently 12 bytes for bne/beq pair.  */
#define FRAG_VAR_SIZE 12
#define FRAG_VAR_SIZE 12
 
 
/* The fields are:
/* The fields are:
   How far Forward this mode will reach:
   How far Forward this mode will reach:
   How far Backward this mode will reach:
   How far Backward this mode will reach:
   How many bytes this mode will add to the size of the frag
   How many bytes this mode will add to the size of the frag
   Which mode to go to if the offset won't fit in this one
   Which mode to go to if the offset won't fit in this one
 
 
   Please check tc-m68k.h:md_prepare_relax_scan if changing this table.  */
   Please check tc-m68k.h:md_prepare_relax_scan if changing this table.  */
relax_typeS md_relax_table[] =
relax_typeS md_relax_table[] =
{
{
  {   127,   -128,  0, TAB (BRANCHBWL, SHORT) },
  {   127,   -128,  0, TAB (BRANCHBWL, SHORT) },
  { 32767, -32768,  2, TAB (BRANCHBWL, LONG) },
  { 32767, -32768,  2, TAB (BRANCHBWL, LONG) },
  {     0,       0,  4, 0 },
  {     0,       0,  4, 0 },
  {     1,      1,  0, 0 },
  {     1,      1,  0, 0 },
 
 
  {   127,   -128,  0, TAB (BRABSJUNC, SHORT) },
  {   127,   -128,  0, TAB (BRABSJUNC, SHORT) },
  { 32767, -32768,  2, TAB (BRABSJUNC, LONG) },
  { 32767, -32768,  2, TAB (BRABSJUNC, LONG) },
  {     0,       0,  4, 0 },
  {     0,       0,  4, 0 },
  {     1,      1,  0, 0 },
  {     1,      1,  0, 0 },
 
 
  {   127,   -128,  0, TAB (BRABSJCOND, SHORT) },
  {   127,   -128,  0, TAB (BRABSJCOND, SHORT) },
  { 32767, -32768,  2, TAB (BRABSJCOND, LONG) },
  { 32767, -32768,  2, TAB (BRABSJCOND, LONG) },
  {     0,       0,  6, 0 },
  {     0,       0,  6, 0 },
  {     1,      1,  0, 0 },
  {     1,      1,  0, 0 },
 
 
  {   127,   -128,  0, TAB (BRANCHBW, SHORT) },
  {   127,   -128,  0, TAB (BRANCHBW, SHORT) },
  {     0,       0,  2, 0 },
  {     0,       0,  2, 0 },
  {     1,      1,  0, 0 },
  {     1,      1,  0, 0 },
  {     1,      1,  0, 0 },
  {     1,      1,  0, 0 },
 
 
  {     1,      1,  0, 0 },               /* FBRANCH doesn't come BYTE.  */
  {     1,      1,  0, 0 },               /* FBRANCH doesn't come BYTE.  */
  { 32767, -32768,  2, TAB (FBRANCH, LONG) },
  { 32767, -32768,  2, TAB (FBRANCH, LONG) },
  {     0,       0,  4, 0 },
  {     0,       0,  4, 0 },
  {     1,      1,  0, 0 },
  {     1,      1,  0, 0 },
 
 
  {     1,      1,  0, 0 },               /* DBCC doesn't come BYTE.  */
  {     1,      1,  0, 0 },               /* DBCC doesn't come BYTE.  */
  { 32767, -32768,  2, TAB (DBCCLBR, LONG) },
  { 32767, -32768,  2, TAB (DBCCLBR, LONG) },
  {     0,       0, 10, 0 },
  {     0,       0, 10, 0 },
  {     1,      1,  0, 0 },
  {     1,      1,  0, 0 },
 
 
  {     1,      1,  0, 0 },               /* DBCC doesn't come BYTE.  */
  {     1,      1,  0, 0 },               /* DBCC doesn't come BYTE.  */
  { 32767, -32768,  2, TAB (DBCCABSJ, LONG) },
  { 32767, -32768,  2, TAB (DBCCABSJ, LONG) },
  {     0,       0, 10, 0 },
  {     0,       0, 10, 0 },
  {     1,      1,  0, 0 },
  {     1,      1,  0, 0 },
 
 
  {     1,      1,  0, 0 },               /* PCREL1632 doesn't come BYTE.  */
  {     1,      1,  0, 0 },               /* PCREL1632 doesn't come BYTE.  */
  { 32767, -32768,  2, TAB (PCREL1632, LONG) },
  { 32767, -32768,  2, TAB (PCREL1632, LONG) },
  {     0,       0,  6, 0 },
  {     0,       0,  6, 0 },
  {     1,      1,  0, 0 },
  {     1,      1,  0, 0 },
 
 
  {   125,   -130,  0, TAB (PCINDEX, SHORT) },
  {   125,   -130,  0, TAB (PCINDEX, SHORT) },
  { 32765, -32770,  2, TAB (PCINDEX, LONG) },
  { 32765, -32770,  2, TAB (PCINDEX, LONG) },
  {     0,       0,  4, 0 },
  {     0,       0,  4, 0 },
  {     1,      1,  0, 0 },
  {     1,      1,  0, 0 },
 
 
  {     1,      1,  0, 0 },               /* ABSTOPCREL doesn't come BYTE.  */
  {     1,      1,  0, 0 },               /* ABSTOPCREL doesn't come BYTE.  */
  { 32767, -32768,  2, TAB (ABSTOPCREL, LONG) },
  { 32767, -32768,  2, TAB (ABSTOPCREL, LONG) },
  {     0,       0,  4, 0 },
  {     0,       0,  4, 0 },
  {     1,      1,  0, 0 },
  {     1,      1,  0, 0 },
 
 
  {   127,   -128,  0, TAB (BRANCHBWPL, SHORT) },
  {   127,   -128,  0, TAB (BRANCHBWPL, SHORT) },
  { 32767, -32768,  2, TAB (BRANCHBWPL, LONG) },
  { 32767, -32768,  2, TAB (BRANCHBWPL, LONG) },
  {     0,       0,  10, 0 },
  {     0,       0,  10, 0 },
  {     1,      1,  0, 0 },
  {     1,      1,  0, 0 },
};
};
 
 
/* These are the machine dependent pseudo-ops.  These are included so
/* These are the machine dependent pseudo-ops.  These are included so
   the assembler can work on the output from the SUN C compiler, which
   the assembler can work on the output from the SUN C compiler, which
   generates these.  */
   generates these.  */
 
 
/* This table describes all the machine specific pseudo-ops the assembler
/* This table describes all the machine specific pseudo-ops the assembler
   has to support.  The fields are:
   has to support.  The fields are:
   pseudo-op name without dot
   pseudo-op name without dot
   function to call to execute this pseudo-op
   function to call to execute this pseudo-op
   Integer arg to pass to the function.  */
   Integer arg to pass to the function.  */
const pseudo_typeS md_pseudo_table[] =
const pseudo_typeS md_pseudo_table[] =
{
{
  {"data1", s_data1, 0},
  {"data1", s_data1, 0},
  {"data2", s_data2, 0},
  {"data2", s_data2, 0},
  {"bss", s_bss, 0},
  {"bss", s_bss, 0},
  {"even", s_even, 0},
  {"even", s_even, 0},
  {"skip", s_space, 0},
  {"skip", s_space, 0},
  {"proc", s_proc, 0},
  {"proc", s_proc, 0},
#if defined (TE_SUN3) || defined (OBJ_ELF)
#if defined (TE_SUN3) || defined (OBJ_ELF)
  {"align", s_align_bytes, 0},
  {"align", s_align_bytes, 0},
#endif
#endif
#ifdef OBJ_ELF
#ifdef OBJ_ELF
  {"swbeg", s_ignore, 0},
  {"swbeg", s_ignore, 0},
#endif
#endif
  {"extend", float_cons, 'x'},
  {"extend", float_cons, 'x'},
  {"ldouble", float_cons, 'x'},
  {"ldouble", float_cons, 'x'},
 
 
  {"arch", s_m68k_arch, 0},
  {"arch", s_m68k_arch, 0},
  {"cpu", s_m68k_cpu, 0},
  {"cpu", s_m68k_cpu, 0},
 
 
  /* The following pseudo-ops are supported for MRI compatibility.  */
  /* The following pseudo-ops are supported for MRI compatibility.  */
  {"chip", s_chip, 0},
  {"chip", s_chip, 0},
  {"comline", s_space, 1},
  {"comline", s_space, 1},
  {"fopt", s_fopt, 0},
  {"fopt", s_fopt, 0},
  {"mask2", s_ignore, 0},
  {"mask2", s_ignore, 0},
  {"opt", s_opt, 0},
  {"opt", s_opt, 0},
  {"reg", s_reg, 0},
  {"reg", s_reg, 0},
  {"restore", s_restore, 0},
  {"restore", s_restore, 0},
  {"save", s_save, 0},
  {"save", s_save, 0},
 
 
  {"if", s_mri_if, 0},
  {"if", s_mri_if, 0},
  {"if.b", s_mri_if, 'b'},
  {"if.b", s_mri_if, 'b'},
  {"if.w", s_mri_if, 'w'},
  {"if.w", s_mri_if, 'w'},
  {"if.l", s_mri_if, 'l'},
  {"if.l", s_mri_if, 'l'},
  {"else", s_mri_else, 0},
  {"else", s_mri_else, 0},
  {"else.s", s_mri_else, 's'},
  {"else.s", s_mri_else, 's'},
  {"else.l", s_mri_else, 'l'},
  {"else.l", s_mri_else, 'l'},
  {"endi", s_mri_endi, 0},
  {"endi", s_mri_endi, 0},
  {"break", s_mri_break, 0},
  {"break", s_mri_break, 0},
  {"break.s", s_mri_break, 's'},
  {"break.s", s_mri_break, 's'},
  {"break.l", s_mri_break, 'l'},
  {"break.l", s_mri_break, 'l'},
  {"next", s_mri_next, 0},
  {"next", s_mri_next, 0},
  {"next.s", s_mri_next, 's'},
  {"next.s", s_mri_next, 's'},
  {"next.l", s_mri_next, 'l'},
  {"next.l", s_mri_next, 'l'},
  {"for", s_mri_for, 0},
  {"for", s_mri_for, 0},
  {"for.b", s_mri_for, 'b'},
  {"for.b", s_mri_for, 'b'},
  {"for.w", s_mri_for, 'w'},
  {"for.w", s_mri_for, 'w'},
  {"for.l", s_mri_for, 'l'},
  {"for.l", s_mri_for, 'l'},
  {"endf", s_mri_endf, 0},
  {"endf", s_mri_endf, 0},
  {"repeat", s_mri_repeat, 0},
  {"repeat", s_mri_repeat, 0},
  {"until", s_mri_until, 0},
  {"until", s_mri_until, 0},
  {"until.b", s_mri_until, 'b'},
  {"until.b", s_mri_until, 'b'},
  {"until.w", s_mri_until, 'w'},
  {"until.w", s_mri_until, 'w'},
  {"until.l", s_mri_until, 'l'},
  {"until.l", s_mri_until, 'l'},
  {"while", s_mri_while, 0},
  {"while", s_mri_while, 0},
  {"while.b", s_mri_while, 'b'},
  {"while.b", s_mri_while, 'b'},
  {"while.w", s_mri_while, 'w'},
  {"while.w", s_mri_while, 'w'},
  {"while.l", s_mri_while, 'l'},
  {"while.l", s_mri_while, 'l'},
  {"endw", s_mri_endw, 0},
  {"endw", s_mri_endw, 0},
 
 
  {0, 0, 0}
  {0, 0, 0}
};
};
 
 
/* The mote pseudo ops are put into the opcode table, since they
/* The mote pseudo ops are put into the opcode table, since they
   don't start with a . they look like opcodes to gas.  */
   don't start with a . they look like opcodes to gas.  */
 
 
const pseudo_typeS mote_pseudo_table[] =
const pseudo_typeS mote_pseudo_table[] =
{
{
 
 
  {"dcl", cons, 4},
  {"dcl", cons, 4},
  {"dc", cons, 2},
  {"dc", cons, 2},
  {"dcw", cons, 2},
  {"dcw", cons, 2},
  {"dcb", cons, 1},
  {"dcb", cons, 1},
 
 
  {"dsl", s_space, 4},
  {"dsl", s_space, 4},
  {"ds", s_space, 2},
  {"ds", s_space, 2},
  {"dsw", s_space, 2},
  {"dsw", s_space, 2},
  {"dsb", s_space, 1},
  {"dsb", s_space, 1},
 
 
  {"xdef", s_globl, 0},
  {"xdef", s_globl, 0},
#ifdef OBJ_ELF
#ifdef OBJ_ELF
  {"align", s_align_bytes, 0},
  {"align", s_align_bytes, 0},
#else
#else
  {"align", s_align_ptwo, 0},
  {"align", s_align_ptwo, 0},
#endif
#endif
#ifdef M68KCOFF
#ifdef M68KCOFF
  {"sect", obj_coff_section, 0},
  {"sect", obj_coff_section, 0},
  {"section", obj_coff_section, 0},
  {"section", obj_coff_section, 0},
#endif
#endif
  {0, 0, 0}
  {0, 0, 0}
};
};
 
 
/* Truncate and sign-extend at 32 bits, so that building on a 64-bit host
/* Truncate and sign-extend at 32 bits, so that building on a 64-bit host
   gives identical results to a 32-bit host.  */
   gives identical results to a 32-bit host.  */
#define TRUNC(X)        ((valueT) (X) & 0xffffffff)
#define TRUNC(X)        ((valueT) (X) & 0xffffffff)
#define SEXT(X)         ((TRUNC (X) ^ 0x80000000) - 0x80000000)
#define SEXT(X)         ((TRUNC (X) ^ 0x80000000) - 0x80000000)
 
 
#define issbyte(x)      ((valueT) SEXT (x) + 0x80 < 0x100)
#define issbyte(x)      ((valueT) SEXT (x) + 0x80 < 0x100)
#define isubyte(x)      ((valueT) TRUNC (x) < 0x100)
#define isubyte(x)      ((valueT) TRUNC (x) < 0x100)
#define issword(x)      ((valueT) SEXT (x) + 0x8000 < 0x10000)
#define issword(x)      ((valueT) SEXT (x) + 0x8000 < 0x10000)
#define isuword(x)      ((valueT) TRUNC (x) < 0x10000)
#define isuword(x)      ((valueT) TRUNC (x) < 0x10000)
 
 
#define isbyte(x)       ((valueT) SEXT (x) + 0xff < 0x1ff)
#define isbyte(x)       ((valueT) SEXT (x) + 0xff < 0x1ff)
#define isword(x)       ((valueT) SEXT (x) + 0xffff < 0x1ffff)
#define isword(x)       ((valueT) SEXT (x) + 0xffff < 0x1ffff)
#define islong(x)       (1)
#define islong(x)       (1)
 
 
static char notend_table[256];
static char notend_table[256];
static char alt_notend_table[256];
static char alt_notend_table[256];
#define notend(s)                                               \
#define notend(s)                                               \
  (! (notend_table[(unsigned char) *s]                          \
  (! (notend_table[(unsigned char) *s]                          \
      || (*s == ':'                                             \
      || (*s == ':'                                             \
          && alt_notend_table[(unsigned char) s[1]])))
          && alt_notend_table[(unsigned char) s[1]])))
 
 
#ifdef OBJ_ELF
#ifdef OBJ_ELF
 
 
/* Return zero if the reference to SYMBOL from within the same segment may
/* Return zero if the reference to SYMBOL from within the same segment may
   be relaxed.  */
   be relaxed.  */
 
 
/* On an ELF system, we can't relax an externally visible symbol,
/* On an ELF system, we can't relax an externally visible symbol,
   because it may be overridden by a shared library.  However, if
   because it may be overridden by a shared library.  However, if
   TARGET_OS is "elf", then we presume that we are assembling for an
   TARGET_OS is "elf", then we presume that we are assembling for an
   embedded system, in which case we don't have to worry about shared
   embedded system, in which case we don't have to worry about shared
   libraries, and we can relax any external sym.  */
   libraries, and we can relax any external sym.  */
 
 
#define relaxable_symbol(symbol) \
#define relaxable_symbol(symbol) \
  (!((S_IS_EXTERNAL (symbol) && EXTERN_FORCE_RELOC) \
  (!((S_IS_EXTERNAL (symbol) && EXTERN_FORCE_RELOC) \
     || S_IS_WEAK (symbol)))
     || S_IS_WEAK (symbol)))
 
 
/* Compute the relocation code for a fixup of SIZE bytes, using pc
/* Compute the relocation code for a fixup of SIZE bytes, using pc
   relative relocation if PCREL is non-zero.  PIC says whether a special
   relative relocation if PCREL is non-zero.  PIC says whether a special
   pic relocation was requested.  */
   pic relocation was requested.  */
 
 
static bfd_reloc_code_real_type
static bfd_reloc_code_real_type
get_reloc_code (int size, int pcrel, enum pic_relocation pic)
get_reloc_code (int size, int pcrel, enum pic_relocation pic)
{
{
  switch (pic)
  switch (pic)
    {
    {
    case pic_got_pcrel:
    case pic_got_pcrel:
      switch (size)
      switch (size)
        {
        {
        case 1:
        case 1:
          return BFD_RELOC_8_GOT_PCREL;
          return BFD_RELOC_8_GOT_PCREL;
        case 2:
        case 2:
          return BFD_RELOC_16_GOT_PCREL;
          return BFD_RELOC_16_GOT_PCREL;
        case 4:
        case 4:
          return BFD_RELOC_32_GOT_PCREL;
          return BFD_RELOC_32_GOT_PCREL;
        }
        }
      break;
      break;
 
 
    case pic_got_off:
    case pic_got_off:
      switch (size)
      switch (size)
        {
        {
        case 1:
        case 1:
          return BFD_RELOC_8_GOTOFF;
          return BFD_RELOC_8_GOTOFF;
        case 2:
        case 2:
          return BFD_RELOC_16_GOTOFF;
          return BFD_RELOC_16_GOTOFF;
        case 4:
        case 4:
          return BFD_RELOC_32_GOTOFF;
          return BFD_RELOC_32_GOTOFF;
        }
        }
      break;
      break;
 
 
    case pic_plt_pcrel:
    case pic_plt_pcrel:
      switch (size)
      switch (size)
        {
        {
        case 1:
        case 1:
          return BFD_RELOC_8_PLT_PCREL;
          return BFD_RELOC_8_PLT_PCREL;
        case 2:
        case 2:
          return BFD_RELOC_16_PLT_PCREL;
          return BFD_RELOC_16_PLT_PCREL;
        case 4:
        case 4:
          return BFD_RELOC_32_PLT_PCREL;
          return BFD_RELOC_32_PLT_PCREL;
        }
        }
      break;
      break;
 
 
    case pic_plt_off:
    case pic_plt_off:
      switch (size)
      switch (size)
        {
        {
        case 1:
        case 1:
          return BFD_RELOC_8_PLTOFF;
          return BFD_RELOC_8_PLTOFF;
        case 2:
        case 2:
          return BFD_RELOC_16_PLTOFF;
          return BFD_RELOC_16_PLTOFF;
        case 4:
        case 4:
          return BFD_RELOC_32_PLTOFF;
          return BFD_RELOC_32_PLTOFF;
        }
        }
      break;
      break;
 
 
    case pic_none:
    case pic_none:
      if (pcrel)
      if (pcrel)
        {
        {
          switch (size)
          switch (size)
            {
            {
            case 1:
            case 1:
              return BFD_RELOC_8_PCREL;
              return BFD_RELOC_8_PCREL;
            case 2:
            case 2:
              return BFD_RELOC_16_PCREL;
              return BFD_RELOC_16_PCREL;
            case 4:
            case 4:
              return BFD_RELOC_32_PCREL;
              return BFD_RELOC_32_PCREL;
            }
            }
        }
        }
      else
      else
        {
        {
          switch (size)
          switch (size)
            {
            {
            case 1:
            case 1:
              return BFD_RELOC_8;
              return BFD_RELOC_8;
            case 2:
            case 2:
              return BFD_RELOC_16;
              return BFD_RELOC_16;
            case 4:
            case 4:
              return BFD_RELOC_32;
              return BFD_RELOC_32;
            }
            }
        }
        }
    }
    }
 
 
  if (pcrel)
  if (pcrel)
    {
    {
      if (pic == pic_none)
      if (pic == pic_none)
        as_bad (_("Can not do %d byte pc-relative relocation"), size);
        as_bad (_("Can not do %d byte pc-relative relocation"), size);
      else
      else
        as_bad (_("Can not do %d byte pc-relative pic relocation"), size);
        as_bad (_("Can not do %d byte pc-relative pic relocation"), size);
    }
    }
  else
  else
    {
    {
      if (pic == pic_none)
      if (pic == pic_none)
        as_bad (_("Can not do %d byte relocation"), size);
        as_bad (_("Can not do %d byte relocation"), size);
      else
      else
        as_bad (_("Can not do %d byte pic relocation"), size);
        as_bad (_("Can not do %d byte pic relocation"), size);
    }
    }
 
 
  return BFD_RELOC_NONE;
  return BFD_RELOC_NONE;
}
}
 
 
/* Here we decide which fixups can be adjusted to make them relative
/* Here we decide which fixups can be adjusted to make them relative
   to the beginning of the section instead of the symbol.  Basically
   to the beginning of the section instead of the symbol.  Basically
   we need to make sure that the dynamic relocations are done
   we need to make sure that the dynamic relocations are done
   correctly, so in some cases we force the original symbol to be
   correctly, so in some cases we force the original symbol to be
   used.  */
   used.  */
int
int
tc_m68k_fix_adjustable (fixS *fixP)
tc_m68k_fix_adjustable (fixS *fixP)
{
{
  /* Adjust_reloc_syms doesn't know about the GOT.  */
  /* Adjust_reloc_syms doesn't know about the GOT.  */
  switch (fixP->fx_r_type)
  switch (fixP->fx_r_type)
    {
    {
    case BFD_RELOC_8_GOT_PCREL:
    case BFD_RELOC_8_GOT_PCREL:
    case BFD_RELOC_16_GOT_PCREL:
    case BFD_RELOC_16_GOT_PCREL:
    case BFD_RELOC_32_GOT_PCREL:
    case BFD_RELOC_32_GOT_PCREL:
    case BFD_RELOC_8_GOTOFF:
    case BFD_RELOC_8_GOTOFF:
    case BFD_RELOC_16_GOTOFF:
    case BFD_RELOC_16_GOTOFF:
    case BFD_RELOC_32_GOTOFF:
    case BFD_RELOC_32_GOTOFF:
    case BFD_RELOC_8_PLT_PCREL:
    case BFD_RELOC_8_PLT_PCREL:
    case BFD_RELOC_16_PLT_PCREL:
    case BFD_RELOC_16_PLT_PCREL:
    case BFD_RELOC_32_PLT_PCREL:
    case BFD_RELOC_32_PLT_PCREL:
    case BFD_RELOC_8_PLTOFF:
    case BFD_RELOC_8_PLTOFF:
    case BFD_RELOC_16_PLTOFF:
    case BFD_RELOC_16_PLTOFF:
    case BFD_RELOC_32_PLTOFF:
    case BFD_RELOC_32_PLTOFF:
      return 0;
      return 0;
 
 
    case BFD_RELOC_VTABLE_INHERIT:
    case BFD_RELOC_VTABLE_INHERIT:
    case BFD_RELOC_VTABLE_ENTRY:
    case BFD_RELOC_VTABLE_ENTRY:
      return 0;
      return 0;
 
 
    default:
    default:
      return 1;
      return 1;
    }
    }
}
}
 
 
#else /* !OBJ_ELF */
#else /* !OBJ_ELF */
 
 
#define get_reloc_code(SIZE,PCREL,OTHER) NO_RELOC
#define get_reloc_code(SIZE,PCREL,OTHER) NO_RELOC
 
 
/* PR gas/3041 Weak symbols are not relaxable
/* PR gas/3041 Weak symbols are not relaxable
   because they must be treated as extern.  */
   because they must be treated as extern.  */
#define relaxable_symbol(symbol)   (!(S_IS_WEAK (symbol)))
#define relaxable_symbol(symbol)   (!(S_IS_WEAK (symbol)))
 
 
#endif /* OBJ_ELF */
#endif /* OBJ_ELF */
 
 
arelent *
arelent *
tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
{
{
  arelent *reloc;
  arelent *reloc;
  bfd_reloc_code_real_type code;
  bfd_reloc_code_real_type code;
 
 
  /* If the tcbit is set, then this was a fixup of a negative value
  /* If the tcbit is set, then this was a fixup of a negative value
     that was never resolved.  We do not have a reloc to handle this,
     that was never resolved.  We do not have a reloc to handle this,
     so just return.  We assume that other code will have detected this
     so just return.  We assume that other code will have detected this
     situation and produced a helpful error message, so we just tell the
     situation and produced a helpful error message, so we just tell the
     user that the reloc cannot be produced.  */
     user that the reloc cannot be produced.  */
  if (fixp->fx_tcbit)
  if (fixp->fx_tcbit)
    {
    {
      if (fixp->fx_addsy)
      if (fixp->fx_addsy)
        as_bad_where (fixp->fx_file, fixp->fx_line,
        as_bad_where (fixp->fx_file, fixp->fx_line,
                      _("Unable to produce reloc against symbol '%s'"),
                      _("Unable to produce reloc against symbol '%s'"),
                      S_GET_NAME (fixp->fx_addsy));
                      S_GET_NAME (fixp->fx_addsy));
      return NULL;
      return NULL;
    }
    }
 
 
  if (fixp->fx_r_type != BFD_RELOC_NONE)
  if (fixp->fx_r_type != BFD_RELOC_NONE)
    {
    {
      code = fixp->fx_r_type;
      code = fixp->fx_r_type;
 
 
      /* Since DIFF_EXPR_OK is defined in tc-m68k.h, it is possible
      /* Since DIFF_EXPR_OK is defined in tc-m68k.h, it is possible
         that fixup_segment converted a non-PC relative reloc into a
         that fixup_segment converted a non-PC relative reloc into a
         PC relative reloc.  In such a case, we need to convert the
         PC relative reloc.  In such a case, we need to convert the
         reloc code.  */
         reloc code.  */
      if (fixp->fx_pcrel)
      if (fixp->fx_pcrel)
        {
        {
          switch (code)
          switch (code)
            {
            {
            case BFD_RELOC_8:
            case BFD_RELOC_8:
              code = BFD_RELOC_8_PCREL;
              code = BFD_RELOC_8_PCREL;
              break;
              break;
            case BFD_RELOC_16:
            case BFD_RELOC_16:
              code = BFD_RELOC_16_PCREL;
              code = BFD_RELOC_16_PCREL;
              break;
              break;
            case BFD_RELOC_32:
            case BFD_RELOC_32:
              code = BFD_RELOC_32_PCREL;
              code = BFD_RELOC_32_PCREL;
              break;
              break;
            case BFD_RELOC_8_PCREL:
            case BFD_RELOC_8_PCREL:
            case BFD_RELOC_16_PCREL:
            case BFD_RELOC_16_PCREL:
            case BFD_RELOC_32_PCREL:
            case BFD_RELOC_32_PCREL:
            case BFD_RELOC_8_GOT_PCREL:
            case BFD_RELOC_8_GOT_PCREL:
            case BFD_RELOC_16_GOT_PCREL:
            case BFD_RELOC_16_GOT_PCREL:
            case BFD_RELOC_32_GOT_PCREL:
            case BFD_RELOC_32_GOT_PCREL:
            case BFD_RELOC_8_GOTOFF:
            case BFD_RELOC_8_GOTOFF:
            case BFD_RELOC_16_GOTOFF:
            case BFD_RELOC_16_GOTOFF:
            case BFD_RELOC_32_GOTOFF:
            case BFD_RELOC_32_GOTOFF:
            case BFD_RELOC_8_PLT_PCREL:
            case BFD_RELOC_8_PLT_PCREL:
            case BFD_RELOC_16_PLT_PCREL:
            case BFD_RELOC_16_PLT_PCREL:
            case BFD_RELOC_32_PLT_PCREL:
            case BFD_RELOC_32_PLT_PCREL:
            case BFD_RELOC_8_PLTOFF:
            case BFD_RELOC_8_PLTOFF:
            case BFD_RELOC_16_PLTOFF:
            case BFD_RELOC_16_PLTOFF:
            case BFD_RELOC_32_PLTOFF:
            case BFD_RELOC_32_PLTOFF:
              break;
              break;
            default:
            default:
              as_bad_where (fixp->fx_file, fixp->fx_line,
              as_bad_where (fixp->fx_file, fixp->fx_line,
                            _("Cannot make %s relocation PC relative"),
                            _("Cannot make %s relocation PC relative"),
                            bfd_get_reloc_code_name (code));
                            bfd_get_reloc_code_name (code));
            }
            }
        }
        }
    }
    }
  else
  else
    {
    {
#define F(SZ,PCREL)             (((SZ) << 1) + (PCREL))
#define F(SZ,PCREL)             (((SZ) << 1) + (PCREL))
      switch (F (fixp->fx_size, fixp->fx_pcrel))
      switch (F (fixp->fx_size, fixp->fx_pcrel))
        {
        {
#define MAP(SZ,PCREL,TYPE)      case F(SZ,PCREL): code = (TYPE); break
#define MAP(SZ,PCREL,TYPE)      case F(SZ,PCREL): code = (TYPE); break
          MAP (1, 0, BFD_RELOC_8);
          MAP (1, 0, BFD_RELOC_8);
          MAP (2, 0, BFD_RELOC_16);
          MAP (2, 0, BFD_RELOC_16);
          MAP (4, 0, BFD_RELOC_32);
          MAP (4, 0, BFD_RELOC_32);
          MAP (1, 1, BFD_RELOC_8_PCREL);
          MAP (1, 1, BFD_RELOC_8_PCREL);
          MAP (2, 1, BFD_RELOC_16_PCREL);
          MAP (2, 1, BFD_RELOC_16_PCREL);
          MAP (4, 1, BFD_RELOC_32_PCREL);
          MAP (4, 1, BFD_RELOC_32_PCREL);
        default:
        default:
          abort ();
          abort ();
        }
        }
    }
    }
#undef F
#undef F
#undef MAP
#undef MAP
 
 
  reloc = (arelent *) xmalloc (sizeof (arelent));
  reloc = (arelent *) xmalloc (sizeof (arelent));
  reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
  reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
  *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
  *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
  reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
  reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
#ifndef OBJ_ELF
#ifndef OBJ_ELF
  if (fixp->fx_pcrel)
  if (fixp->fx_pcrel)
    reloc->addend = fixp->fx_addnumber;
    reloc->addend = fixp->fx_addnumber;
  else if (OUTPUT_FLAVOR == bfd_target_aout_flavour
  else if (OUTPUT_FLAVOR == bfd_target_aout_flavour
           && fixp->fx_addsy
           && fixp->fx_addsy
           && S_IS_WEAK (fixp->fx_addsy)
           && S_IS_WEAK (fixp->fx_addsy)
           && ! bfd_is_und_section (S_GET_SEGMENT (fixp->fx_addsy)))
           && ! bfd_is_und_section (S_GET_SEGMENT (fixp->fx_addsy)))
    /* PR gas/3041 Adjust addend in order to force bfd_install_relocation()
    /* PR gas/3041 Adjust addend in order to force bfd_install_relocation()
       to put the symbol offset into frags referencing a weak symbol.  */
       to put the symbol offset into frags referencing a weak symbol.  */
    reloc->addend = fixp->fx_addnumber
    reloc->addend = fixp->fx_addnumber
                    - (S_GET_VALUE (fixp->fx_addsy) * 2);
                    - (S_GET_VALUE (fixp->fx_addsy) * 2);
  else
  else
    reloc->addend = 0;
    reloc->addend = 0;
#else
#else
  if (!fixp->fx_pcrel)
  if (!fixp->fx_pcrel)
    reloc->addend = fixp->fx_addnumber;
    reloc->addend = fixp->fx_addnumber;
  else
  else
    reloc->addend = (section->vma
    reloc->addend = (section->vma
                     /* Explicit sign extension in case char is
                     /* Explicit sign extension in case char is
                        unsigned.  */
                        unsigned.  */
                     + ((fixp->fx_pcrel_adjust & 0xff) ^ 0x80) - 0x80
                     + ((fixp->fx_pcrel_adjust & 0xff) ^ 0x80) - 0x80
                     + fixp->fx_addnumber
                     + fixp->fx_addnumber
                     + md_pcrel_from (fixp));
                     + md_pcrel_from (fixp));
#endif
#endif
 
 
  reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
  reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
  assert (reloc->howto != 0);
  assert (reloc->howto != 0);
 
 
  return reloc;
  return reloc;
}
}
 
 
/* Handle of the OPCODE hash table.  NULL means any use before
/* Handle of the OPCODE hash table.  NULL means any use before
   m68k_ip_begin() will crash.  */
   m68k_ip_begin() will crash.  */
static struct hash_control *op_hash;
static struct hash_control *op_hash;


/* Assemble an m68k instruction.  */
/* Assemble an m68k instruction.  */
 
 
static void
static void
m68k_ip (char *instring)
m68k_ip (char *instring)
{
{
  register char *p;
  register char *p;
  register struct m68k_op *opP;
  register struct m68k_op *opP;
  register const struct m68k_incant *opcode;
  register const struct m68k_incant *opcode;
  register const char *s;
  register const char *s;
  register int tmpreg = 0, baseo = 0, outro = 0, nextword;
  register int tmpreg = 0, baseo = 0, outro = 0, nextword;
  char *pdot, *pdotmove;
  char *pdot, *pdotmove;
  enum m68k_size siz1, siz2;
  enum m68k_size siz1, siz2;
  char c;
  char c;
  int losing;
  int losing;
  int opsfound;
  int opsfound;
  struct m68k_op operands_backup[6];
  struct m68k_op operands_backup[6];
  LITTLENUM_TYPE words[6];
  LITTLENUM_TYPE words[6];
  LITTLENUM_TYPE *wordp;
  LITTLENUM_TYPE *wordp;
  unsigned long ok_arch = 0;
  unsigned long ok_arch = 0;
 
 
  if (*instring == ' ')
  if (*instring == ' ')
    instring++;                 /* Skip leading whitespace.  */
    instring++;                 /* Skip leading whitespace.  */
 
 
  /* Scan up to end of operation-code, which MUST end in end-of-string
  /* Scan up to end of operation-code, which MUST end in end-of-string
     or exactly 1 space.  */
     or exactly 1 space.  */
  pdot = 0;
  pdot = 0;
  for (p = instring; *p != '\0'; p++)
  for (p = instring; *p != '\0'; p++)
    {
    {
      if (*p == ' ')
      if (*p == ' ')
        break;
        break;
      if (*p == '.')
      if (*p == '.')
        pdot = p;
        pdot = p;
    }
    }
 
 
  if (p == instring)
  if (p == instring)
    {
    {
      the_ins.error = _("No operator");
      the_ins.error = _("No operator");
      return;
      return;
    }
    }
 
 
  /* p now points to the end of the opcode name, probably whitespace.
  /* p now points to the end of the opcode name, probably whitespace.
     Make sure the name is null terminated by clobbering the
     Make sure the name is null terminated by clobbering the
     whitespace, look it up in the hash table, then fix it back.
     whitespace, look it up in the hash table, then fix it back.
     Remove a dot, first, since the opcode tables have none.  */
     Remove a dot, first, since the opcode tables have none.  */
  if (pdot != NULL)
  if (pdot != NULL)
    {
    {
      for (pdotmove = pdot; pdotmove < p; pdotmove++)
      for (pdotmove = pdot; pdotmove < p; pdotmove++)
        *pdotmove = pdotmove[1];
        *pdotmove = pdotmove[1];
      p--;
      p--;
    }
    }
 
 
  c = *p;
  c = *p;
  *p = '\0';
  *p = '\0';
  opcode = (const struct m68k_incant *) hash_find (op_hash, instring);
  opcode = (const struct m68k_incant *) hash_find (op_hash, instring);
  *p = c;
  *p = c;
 
 
  if (pdot != NULL)
  if (pdot != NULL)
    {
    {
      for (pdotmove = p; pdotmove > pdot; pdotmove--)
      for (pdotmove = p; pdotmove > pdot; pdotmove--)
        *pdotmove = pdotmove[-1];
        *pdotmove = pdotmove[-1];
      *pdot = '.';
      *pdot = '.';
      ++p;
      ++p;
    }
    }
 
 
  if (opcode == NULL)
  if (opcode == NULL)
    {
    {
      the_ins.error = _("Unknown operator");
      the_ins.error = _("Unknown operator");
      return;
      return;
    }
    }
 
 
  /* Found a legitimate opcode, start matching operands.  */
  /* Found a legitimate opcode, start matching operands.  */
  while (*p == ' ')
  while (*p == ' ')
    ++p;
    ++p;
 
 
  if (opcode->m_operands == 0)
  if (opcode->m_operands == 0)
    {
    {
      char *old = input_line_pointer;
      char *old = input_line_pointer;
      *old = '\n';
      *old = '\n';
      input_line_pointer = p;
      input_line_pointer = p;
      /* Ahh - it's a motorola style psuedo op.  */
      /* Ahh - it's a motorola style psuedo op.  */
      mote_pseudo_table[opcode->m_opnum].poc_handler
      mote_pseudo_table[opcode->m_opnum].poc_handler
        (mote_pseudo_table[opcode->m_opnum].poc_val);
        (mote_pseudo_table[opcode->m_opnum].poc_val);
      input_line_pointer = old;
      input_line_pointer = old;
      *old = 0;
      *old = 0;
 
 
      return;
      return;
    }
    }
 
 
  if (flag_mri && opcode->m_opnum == 0)
  if (flag_mri && opcode->m_opnum == 0)
    {
    {
      /* In MRI mode, random garbage is allowed after an instruction
      /* In MRI mode, random garbage is allowed after an instruction
         which accepts no operands.  */
         which accepts no operands.  */
      the_ins.args = opcode->m_operands;
      the_ins.args = opcode->m_operands;
      the_ins.numargs = opcode->m_opnum;
      the_ins.numargs = opcode->m_opnum;
      the_ins.numo = opcode->m_codenum;
      the_ins.numo = opcode->m_codenum;
      the_ins.opcode[0] = getone (opcode);
      the_ins.opcode[0] = getone (opcode);
      the_ins.opcode[1] = gettwo (opcode);
      the_ins.opcode[1] = gettwo (opcode);
      return;
      return;
    }
    }
 
 
  for (opP = &the_ins.operands[0]; *p; opP++)
  for (opP = &the_ins.operands[0]; *p; opP++)
    {
    {
      p = crack_operand (p, opP);
      p = crack_operand (p, opP);
 
 
      if (opP->error)
      if (opP->error)
        {
        {
          the_ins.error = opP->error;
          the_ins.error = opP->error;
          return;
          return;
        }
        }
    }
    }
 
 
  opsfound = opP - &the_ins.operands[0];
  opsfound = opP - &the_ins.operands[0];
 
 
  /* This ugly hack is to support the floating pt opcodes in their
  /* This ugly hack is to support the floating pt opcodes in their
     standard form.  Essentially, we fake a first enty of type COP#1 */
     standard form.  Essentially, we fake a first enty of type COP#1 */
  if (opcode->m_operands[0] == 'I')
  if (opcode->m_operands[0] == 'I')
    {
    {
      int n;
      int n;
 
 
      for (n = opsfound; n > 0; --n)
      for (n = opsfound; n > 0; --n)
        the_ins.operands[n] = the_ins.operands[n - 1];
        the_ins.operands[n] = the_ins.operands[n - 1];
 
 
      memset (&the_ins.operands[0], '\0', sizeof (the_ins.operands[0]));
      memset (&the_ins.operands[0], '\0', sizeof (the_ins.operands[0]));
      the_ins.operands[0].mode = CONTROL;
      the_ins.operands[0].mode = CONTROL;
      the_ins.operands[0].reg = m68k_float_copnum;
      the_ins.operands[0].reg = m68k_float_copnum;
      opsfound++;
      opsfound++;
    }
    }
 
 
  /* We've got the operands.  Find an opcode that'll accept them.  */
  /* We've got the operands.  Find an opcode that'll accept them.  */
  for (losing = 0;;)
  for (losing = 0;;)
    {
    {
      /* If we didn't get the right number of ops, or we have no
      /* If we didn't get the right number of ops, or we have no
         common model with this pattern then reject this pattern.  */
         common model with this pattern then reject this pattern.  */
 
 
      ok_arch |= opcode->m_arch;
      ok_arch |= opcode->m_arch;
      if (opsfound != opcode->m_opnum
      if (opsfound != opcode->m_opnum
          || ((opcode->m_arch & current_architecture) == 0))
          || ((opcode->m_arch & current_architecture) == 0))
        ++losing;
        ++losing;
      else
      else
        {
        {
          int i;
          int i;
 
 
          /* Make a copy of the operands of this insn so that
          /* Make a copy of the operands of this insn so that
             we can modify them safely, should we want to.  */
             we can modify them safely, should we want to.  */
          assert (opsfound <= (int) ARRAY_SIZE (operands_backup));
          assert (opsfound <= (int) ARRAY_SIZE (operands_backup));
          for (i = 0; i < opsfound; i++)
          for (i = 0; i < opsfound; i++)
            operands_backup[i] = the_ins.operands[i];
            operands_backup[i] = the_ins.operands[i];
 
 
          for (s = opcode->m_operands, opP = &operands_backup[0];
          for (s = opcode->m_operands, opP = &operands_backup[0];
               *s && !losing;
               *s && !losing;
               s += 2, opP++)
               s += 2, opP++)
            {
            {
              /* Warning: this switch is huge! */
              /* Warning: this switch is huge! */
              /* I've tried to organize the cases into this order:
              /* I've tried to organize the cases into this order:
                 non-alpha first, then alpha by letter.  Lower-case
                 non-alpha first, then alpha by letter.  Lower-case
                 goes directly before uppercase counterpart.  */
                 goes directly before uppercase counterpart.  */
              /* Code with multiple case ...: gets sorted by the lowest
              /* Code with multiple case ...: gets sorted by the lowest
                 case ... it belongs to.  I hope this makes sense.  */
                 case ... it belongs to.  I hope this makes sense.  */
              switch (*s)
              switch (*s)
                {
                {
                case '!':
                case '!':
                  switch (opP->mode)
                  switch (opP->mode)
                    {
                    {
                    case IMMED:
                    case IMMED:
                    case DREG:
                    case DREG:
                    case AREG:
                    case AREG:
                    case FPREG:
                    case FPREG:
                    case CONTROL:
                    case CONTROL:
                    case AINC:
                    case AINC:
                    case ADEC:
                    case ADEC:
                    case REGLST:
                    case REGLST:
                      losing++;
                      losing++;
                      break;
                      break;
                    default:
                    default:
                      break;
                      break;
                    }
                    }
                  break;
                  break;
 
 
                case '<':
                case '<':
                  switch (opP->mode)
                  switch (opP->mode)
                    {
                    {
                    case DREG:
                    case DREG:
                    case AREG:
                    case AREG:
                    case FPREG:
                    case FPREG:
                    case CONTROL:
                    case CONTROL:
                    case IMMED:
                    case IMMED:
                    case ADEC:
                    case ADEC:
                    case REGLST:
                    case REGLST:
                      losing++;
                      losing++;
                      break;
                      break;
                    default:
                    default:
                      break;
                      break;
                    }
                    }
                  break;
                  break;
 
 
                case '>':
                case '>':
                  switch (opP->mode)
                  switch (opP->mode)
                    {
                    {
                    case DREG:
                    case DREG:
                    case AREG:
                    case AREG:
                    case FPREG:
                    case FPREG:
                    case CONTROL:
                    case CONTROL:
                    case IMMED:
                    case IMMED:
                    case AINC:
                    case AINC:
                    case REGLST:
                    case REGLST:
                      losing++;
                      losing++;
                      break;
                      break;
                    case ABSL:
                    case ABSL:
                      break;
                      break;
                    default:
                    default:
                      if (opP->reg == PC
                      if (opP->reg == PC
                          || opP->reg == ZPC)
                          || opP->reg == ZPC)
                        losing++;
                        losing++;
                      break;
                      break;
                    }
                    }
                  break;
                  break;
 
 
                case 'm':
                case 'm':
                  switch (opP->mode)
                  switch (opP->mode)
                    {
                    {
                    case DREG:
                    case DREG:
                    case AREG:
                    case AREG:
                    case AINDR:
                    case AINDR:
                    case AINC:
                    case AINC:
                    case ADEC:
                    case ADEC:
                      break;
                      break;
                    default:
                    default:
                      losing++;
                      losing++;
                    }
                    }
                  break;
                  break;
 
 
                case 'n':
                case 'n':
                  switch (opP->mode)
                  switch (opP->mode)
                    {
                    {
                    case DISP:
                    case DISP:
                      break;
                      break;
                    default:
                    default:
                      losing++;
                      losing++;
                    }
                    }
                  break;
                  break;
 
 
                case 'o':
                case 'o':
                  switch (opP->mode)
                  switch (opP->mode)
                    {
                    {
                    case BASE:
                    case BASE:
                    case ABSL:
                    case ABSL:
                    case IMMED:
                    case IMMED:
                      break;
                      break;
                    default:
                    default:
                      losing++;
                      losing++;
                    }
                    }
                  break;
                  break;
 
 
                case 'p':
                case 'p':
                  switch (opP->mode)
                  switch (opP->mode)
                    {
                    {
                    case DREG:
                    case DREG:
                    case AREG:
                    case AREG:
                    case AINDR:
                    case AINDR:
                    case AINC:
                    case AINC:
                    case ADEC:
                    case ADEC:
                      break;
                      break;
                    case DISP:
                    case DISP:
                      if (opP->reg == PC || opP->reg == ZPC)
                      if (opP->reg == PC || opP->reg == ZPC)
                        losing++;
                        losing++;
                      break;
                      break;
                    default:
                    default:
                      losing++;
                      losing++;
                    }
                    }
                  break;
                  break;
 
 
                case 'q':
                case 'q':
                  switch (opP->mode)
                  switch (opP->mode)
                    {
                    {
                    case DREG:
                    case DREG:
                    case AINDR:
                    case AINDR:
                    case AINC:
                    case AINC:
                    case ADEC:
                    case ADEC:
                      break;
                      break;
                    case DISP:
                    case DISP:
                      if (opP->reg == PC || opP->reg == ZPC)
                      if (opP->reg == PC || opP->reg == ZPC)
                        losing++;
                        losing++;
                      break;
                      break;
                    default:
                    default:
                      losing++;
                      losing++;
                      break;
                      break;
                    }
                    }
                  break;
                  break;
 
 
                case 'v':
                case 'v':
                  switch (opP->mode)
                  switch (opP->mode)
                    {
                    {
                    case DREG:
                    case DREG:
                    case AINDR:
                    case AINDR:
                    case AINC:
                    case AINC:
                    case ADEC:
                    case ADEC:
                    case ABSL:
                    case ABSL:
                      break;
                      break;
                    case DISP:
                    case DISP:
                      if (opP->reg == PC || opP->reg == ZPC)
                      if (opP->reg == PC || opP->reg == ZPC)
                        losing++;
                        losing++;
                      break;
                      break;
                    default:
                    default:
                      losing++;
                      losing++;
                      break;
                      break;
                    }
                    }
                  break;
                  break;
 
 
                case '#':
                case '#':
                  if (opP->mode != IMMED)
                  if (opP->mode != IMMED)
                    losing++;
                    losing++;
                  else if (s[1] == 'b'
                  else if (s[1] == 'b'
                           && ! isvar (&opP->disp)
                           && ! isvar (&opP->disp)
                           && (opP->disp.exp.X_op != O_constant
                           && (opP->disp.exp.X_op != O_constant
                               || ! isbyte (opP->disp.exp.X_add_number)))
                               || ! isbyte (opP->disp.exp.X_add_number)))
                    losing++;
                    losing++;
                  else if (s[1] == 'B'
                  else if (s[1] == 'B'
                           && ! isvar (&opP->disp)
                           && ! isvar (&opP->disp)
                           && (opP->disp.exp.X_op != O_constant
                           && (opP->disp.exp.X_op != O_constant
                               || ! issbyte (opP->disp.exp.X_add_number)))
                               || ! issbyte (opP->disp.exp.X_add_number)))
                    losing++;
                    losing++;
                  else if (s[1] == 'w'
                  else if (s[1] == 'w'
                           && ! isvar (&opP->disp)
                           && ! isvar (&opP->disp)
                           && (opP->disp.exp.X_op != O_constant
                           && (opP->disp.exp.X_op != O_constant
                               || ! isword (opP->disp.exp.X_add_number)))
                               || ! isword (opP->disp.exp.X_add_number)))
                    losing++;
                    losing++;
                  else if (s[1] == 'W'
                  else if (s[1] == 'W'
                           && ! isvar (&opP->disp)
                           && ! isvar (&opP->disp)
                           && (opP->disp.exp.X_op != O_constant
                           && (opP->disp.exp.X_op != O_constant
                               || ! issword (opP->disp.exp.X_add_number)))
                               || ! issword (opP->disp.exp.X_add_number)))
                    losing++;
                    losing++;
                  break;
                  break;
 
 
                case '^':
                case '^':
                case 'T':
                case 'T':
                  if (opP->mode != IMMED)
                  if (opP->mode != IMMED)
                    losing++;
                    losing++;
                  break;
                  break;
 
 
                case '$':
                case '$':
                  if (opP->mode == AREG
                  if (opP->mode == AREG
                      || opP->mode == CONTROL
                      || opP->mode == CONTROL
                      || opP->mode == FPREG
                      || opP->mode == FPREG
                      || opP->mode == IMMED
                      || opP->mode == IMMED
                      || opP->mode == REGLST
                      || opP->mode == REGLST
                      || (opP->mode != ABSL
                      || (opP->mode != ABSL
                          && (opP->reg == PC
                          && (opP->reg == PC
                              || opP->reg == ZPC)))
                              || opP->reg == ZPC)))
                    losing++;
                    losing++;
                  break;
                  break;
 
 
                case '%':
                case '%':
                  if (opP->mode == CONTROL
                  if (opP->mode == CONTROL
                      || opP->mode == FPREG
                      || opP->mode == FPREG
                      || opP->mode == REGLST
                      || opP->mode == REGLST
                      || opP->mode == IMMED
                      || opP->mode == IMMED
                      || (opP->mode != ABSL
                      || (opP->mode != ABSL
                          && (opP->reg == PC
                          && (opP->reg == PC
                              || opP->reg == ZPC)))
                              || opP->reg == ZPC)))
                    losing++;
                    losing++;
                  break;
                  break;
 
 
                case '&':
                case '&':
                  switch (opP->mode)
                  switch (opP->mode)
                    {
                    {
                    case DREG:
                    case DREG:
                    case AREG:
                    case AREG:
                    case FPREG:
                    case FPREG:
                    case CONTROL:
                    case CONTROL:
                    case IMMED:
                    case IMMED:
                    case AINC:
                    case AINC:
                    case ADEC:
                    case ADEC:
                    case REGLST:
                    case REGLST:
                      losing++;
                      losing++;
                      break;
                      break;
                    case ABSL:
                    case ABSL:
                      break;
                      break;
                    default:
                    default:
                      if (opP->reg == PC
                      if (opP->reg == PC
                          || opP->reg == ZPC)
                          || opP->reg == ZPC)
                        losing++;
                        losing++;
                      break;
                      break;
                    }
                    }
                  break;
                  break;
 
 
                case '*':
                case '*':
                  if (opP->mode == CONTROL
                  if (opP->mode == CONTROL
                      || opP->mode == FPREG
                      || opP->mode == FPREG
                      || opP->mode == REGLST)
                      || opP->mode == REGLST)
                    losing++;
                    losing++;
                  break;
                  break;
 
 
                case '+':
                case '+':
                  if (opP->mode != AINC)
                  if (opP->mode != AINC)
                    losing++;
                    losing++;
                  break;
                  break;
 
 
                case '-':
                case '-':
                  if (opP->mode != ADEC)
                  if (opP->mode != ADEC)
                    losing++;
                    losing++;
                  break;
                  break;
 
 
                case '/':
                case '/':
                  switch (opP->mode)
                  switch (opP->mode)
                    {
                    {
                    case AREG:
                    case AREG:
                    case CONTROL:
                    case CONTROL:
                    case FPREG:
                    case FPREG:
                    case AINC:
                    case AINC:
                    case ADEC:
                    case ADEC:
                    case IMMED:
                    case IMMED:
                    case REGLST:
                    case REGLST:
                      losing++;
                      losing++;
                      break;
                      break;
                    default:
                    default:
                      break;
                      break;
                    }
                    }
                  break;
                  break;
 
 
                case ';':
                case ';':
                  switch (opP->mode)
                  switch (opP->mode)
                    {
                    {
                    case AREG:
                    case AREG:
                    case CONTROL:
                    case CONTROL:
                    case FPREG:
                    case FPREG:
                    case REGLST:
                    case REGLST:
                      losing++;
                      losing++;
                      break;
                      break;
                    default:
                    default:
                      break;
                      break;
                    }
                    }
                  break;
                  break;
 
 
                case '?':
                case '?':
                  switch (opP->mode)
                  switch (opP->mode)
                    {
                    {
                    case AREG:
                    case AREG:
                    case CONTROL:
                    case CONTROL:
                    case FPREG:
                    case FPREG:
                    case AINC:
                    case AINC:
                    case ADEC:
                    case ADEC:
                    case IMMED:
                    case IMMED:
                    case REGLST:
                    case REGLST:
                      losing++;
                      losing++;
                      break;
                      break;
                    case ABSL:
                    case ABSL:
                      break;
                      break;
                    default:
                    default:
                      if (opP->reg == PC || opP->reg == ZPC)
                      if (opP->reg == PC || opP->reg == ZPC)
                        losing++;
                        losing++;
                      break;
                      break;
                    }
                    }
                  break;
                  break;
 
 
                case '@':
                case '@':
                  switch (opP->mode)
                  switch (opP->mode)
                    {
                    {
                    case AREG:
                    case AREG:
                    case CONTROL:
                    case CONTROL:
                    case FPREG:
                    case FPREG:
                    case IMMED:
                    case IMMED:
                    case REGLST:
                    case REGLST:
                      losing++;
                      losing++;
                      break;
                      break;
                    default:
                    default:
                      break;
                      break;
                    }
                    }
                  break;
                  break;
 
 
                case '~':       /* For now! (JF FOO is this right?) */
                case '~':       /* For now! (JF FOO is this right?) */
                  switch (opP->mode)
                  switch (opP->mode)
                    {
                    {
                    case DREG:
                    case DREG:
                    case AREG:
                    case AREG:
                    case CONTROL:
                    case CONTROL:
                    case FPREG:
                    case FPREG:
                    case IMMED:
                    case IMMED:
                    case REGLST:
                    case REGLST:
                      losing++;
                      losing++;
                      break;
                      break;
                    case ABSL:
                    case ABSL:
                      break;
                      break;
                    default:
                    default:
                      if (opP->reg == PC
                      if (opP->reg == PC
                          || opP->reg == ZPC)
                          || opP->reg == ZPC)
                        losing++;
                        losing++;
                      break;
                      break;
                    }
                    }
                  break;
                  break;
 
 
                case '3':
                case '3':
                  if (opP->mode != CONTROL
                  if (opP->mode != CONTROL
                      || (opP->reg != TT0 && opP->reg != TT1))
                      || (opP->reg != TT0 && opP->reg != TT1))
                    losing++;
                    losing++;
                  break;
                  break;
 
 
                case 'A':
                case 'A':
                  if (opP->mode != AREG)
                  if (opP->mode != AREG)
                    losing++;
                    losing++;
                  break;
                  break;
 
 
                case 'a':
                case 'a':
                  if (opP->mode != AINDR)
                  if (opP->mode != AINDR)
                    ++losing;
                    ++losing;
                  break;
                  break;
 
 
                case '4':
                case '4':
                  if (opP->mode != AINDR && opP->mode != AINC && opP->mode != ADEC
                  if (opP->mode != AINDR && opP->mode != AINC && opP->mode != ADEC
                      && (opP->mode != DISP
                      && (opP->mode != DISP
                           || opP->reg < ADDR0
                           || opP->reg < ADDR0
                           || opP->reg > ADDR7))
                           || opP->reg > ADDR7))
                    ++losing;
                    ++losing;
                  break;
                  break;
 
 
                case 'B':       /* FOO */
                case 'B':       /* FOO */
                  if (opP->mode != ABSL
                  if (opP->mode != ABSL
                      || (flag_long_jumps
                      || (flag_long_jumps
                          && strncmp (instring, "jbsr", 4) == 0))
                          && strncmp (instring, "jbsr", 4) == 0))
                    losing++;
                    losing++;
                  break;
                  break;
 
 
                case 'b':
                case 'b':
                  switch (opP->mode)
                  switch (opP->mode)
                    {
                    {
                    case IMMED:
                    case IMMED:
                    case ABSL:
                    case ABSL:
                    case AREG:
                    case AREG:
                    case FPREG:
                    case FPREG:
                    case CONTROL:
                    case CONTROL:
                    case POST:
                    case POST:
                    case PRE:
                    case PRE:
                    case REGLST:
                    case REGLST:
                      losing++;
                      losing++;
                      break;
                      break;
                    default:
                    default:
                      break;
                      break;
                    }
                    }
                  break;
                  break;
 
 
                case 'C':
                case 'C':
                  if (opP->mode != CONTROL || opP->reg != CCR)
                  if (opP->mode != CONTROL || opP->reg != CCR)
                    losing++;
                    losing++;
                  break;
                  break;
 
 
                case 'd':
                case 'd':
                  if (opP->mode != DISP
                  if (opP->mode != DISP
                      || opP->reg < ADDR0
                      || opP->reg < ADDR0
                      || opP->reg > ADDR7)
                      || opP->reg > ADDR7)
                    losing++;
                    losing++;
                  break;
                  break;
 
 
                case 'D':
                case 'D':
                  if (opP->mode != DREG)
                  if (opP->mode != DREG)
                    losing++;
                    losing++;
                  break;
                  break;
 
 
                case 'E':
                case 'E':
                  if (opP->reg != ACC)
                  if (opP->reg != ACC)
                    losing++;
                    losing++;
                  break;
                  break;
 
 
                case 'e':
                case 'e':
                  if (opP->reg != ACC && opP->reg != ACC1
                  if (opP->reg != ACC && opP->reg != ACC1
                      && opP->reg != ACC2 && opP->reg != ACC3)
                      && opP->reg != ACC2 && opP->reg != ACC3)
                    losing++;
                    losing++;
                  break;
                  break;
 
 
                case 'F':
                case 'F':
                  if (opP->mode != FPREG)
                  if (opP->mode != FPREG)
                    losing++;
                    losing++;
                  break;
                  break;
 
 
                case 'G':
                case 'G':
                  if (opP->reg != MACSR)
                  if (opP->reg != MACSR)
                    losing++;
                    losing++;
                  break;
                  break;
 
 
                case 'g':
                case 'g':
                  if (opP->reg != ACCEXT01 && opP->reg != ACCEXT23)
                  if (opP->reg != ACCEXT01 && opP->reg != ACCEXT23)
                    losing++;
                    losing++;
                  break;
                  break;
 
 
                case 'H':
                case 'H':
                  if (opP->reg != MASK)
                  if (opP->reg != MASK)
                    losing++;
                    losing++;
                  break;
                  break;
 
 
                case 'I':
                case 'I':
                  if (opP->mode != CONTROL
                  if (opP->mode != CONTROL
                      || opP->reg < COP0
                      || opP->reg < COP0
                      || opP->reg > COP7)
                      || opP->reg > COP7)
                    losing++;
                    losing++;
                  break;
                  break;
 
 
                case 'i':
                case 'i':
                  if (opP->mode != LSH && opP->mode != RSH)
                  if (opP->mode != LSH && opP->mode != RSH)
                    losing++;
                    losing++;
                  break;
                  break;
 
 
                case 'J':
                case 'J':
                  if (opP->mode != CONTROL
                  if (opP->mode != CONTROL
                      || opP->reg < USP
                      || opP->reg < USP
                      || opP->reg > last_movec_reg
                      || opP->reg > last_movec_reg
                      || !control_regs)
                      || !control_regs)
                    losing++;
                    losing++;
                  else
                  else
                    {
                    {
                      const enum m68k_register *rp;
                      const enum m68k_register *rp;
 
 
                      for (rp = control_regs; *rp; rp++)
                      for (rp = control_regs; *rp; rp++)
                        {
                        {
                          if (*rp == opP->reg)
                          if (*rp == opP->reg)
                            break;
                            break;
                          /* In most CPUs RAMBAR refers to control reg
                          /* In most CPUs RAMBAR refers to control reg
                             c05 (RAMBAR1), but a few CPUs have it
                             c05 (RAMBAR1), but a few CPUs have it
                             refer to c04 (RAMBAR0).  */
                             refer to c04 (RAMBAR0).  */
                          else if (*rp == RAMBAR_ALT && opP->reg == RAMBAR)
                          else if (*rp == RAMBAR_ALT && opP->reg == RAMBAR)
                            {
                            {
                              opP->reg = RAMBAR_ALT;
                              opP->reg = RAMBAR_ALT;
                              break;
                              break;
                            }
                            }
                        }
                        }
                      if (*rp == 0)
                      if (*rp == 0)
                        losing++;
                        losing++;
                    }
                    }
                  break;
                  break;
 
 
                case 'k':
                case 'k':
                  if (opP->mode != IMMED)
                  if (opP->mode != IMMED)
                    losing++;
                    losing++;
                  break;
                  break;
 
 
                case 'l':
                case 'l':
                case 'L':
                case 'L':
                  if (opP->mode == DREG
                  if (opP->mode == DREG
                      || opP->mode == AREG
                      || opP->mode == AREG
                      || opP->mode == FPREG)
                      || opP->mode == FPREG)
                    {
                    {
                      if (s[1] == '8')
                      if (s[1] == '8')
                        losing++;
                        losing++;
                      else
                      else
                        {
                        {
                          switch (opP->mode)
                          switch (opP->mode)
                            {
                            {
                            case DREG:
                            case DREG:
                              opP->mask = 1 << (opP->reg - DATA0);
                              opP->mask = 1 << (opP->reg - DATA0);
                              break;
                              break;
                            case AREG:
                            case AREG:
                              opP->mask = 1 << (opP->reg - ADDR0 + 8);
                              opP->mask = 1 << (opP->reg - ADDR0 + 8);
                              break;
                              break;
                            case FPREG:
                            case FPREG:
                              opP->mask = 1 << (opP->reg - FP0 + 16);
                              opP->mask = 1 << (opP->reg - FP0 + 16);
                              break;
                              break;
                            default:
                            default:
                              abort ();
                              abort ();
                            }
                            }
                          opP->mode = REGLST;
                          opP->mode = REGLST;
                        }
                        }
                    }
                    }
                  else if (opP->mode == CONTROL)
                  else if (opP->mode == CONTROL)
                    {
                    {
                      if (s[1] != '8')
                      if (s[1] != '8')
                        losing++;
                        losing++;
                      else
                      else
                        {
                        {
                          switch (opP->reg)
                          switch (opP->reg)
                            {
                            {
                            case FPI:
                            case FPI:
                              opP->mask = 1 << 24;
                              opP->mask = 1 << 24;
                              break;
                              break;
                            case FPS:
                            case FPS:
                              opP->mask = 1 << 25;
                              opP->mask = 1 << 25;
                              break;
                              break;
                            case FPC:
                            case FPC:
                              opP->mask = 1 << 26;
                              opP->mask = 1 << 26;
                              break;
                              break;
                            default:
                            default:
                              losing++;
                              losing++;
                              break;
                              break;
                            }
                            }
                          opP->mode = REGLST;
                          opP->mode = REGLST;
                        }
                        }
                    }
                    }
                  else if (opP->mode != REGLST)
                  else if (opP->mode != REGLST)
                    losing++;
                    losing++;
                  else if (s[1] == '8' && (opP->mask & 0x0ffffff) != 0)
                  else if (s[1] == '8' && (opP->mask & 0x0ffffff) != 0)
                    losing++;
                    losing++;
                  else if (s[1] == '3' && (opP->mask & 0x7000000) != 0)
                  else if (s[1] == '3' && (opP->mask & 0x7000000) != 0)
                    losing++;
                    losing++;
                  break;
                  break;
 
 
                case 'M':
                case 'M':
                  if (opP->mode != IMMED)
                  if (opP->mode != IMMED)
                    losing++;
                    losing++;
                  else if (opP->disp.exp.X_op != O_constant
                  else if (opP->disp.exp.X_op != O_constant
                           || ! issbyte (opP->disp.exp.X_add_number))
                           || ! issbyte (opP->disp.exp.X_add_number))
                    losing++;
                    losing++;
                  else if (! m68k_quick
                  else if (! m68k_quick
                           && instring[3] != 'q'
                           && instring[3] != 'q'
                           && instring[4] != 'q')
                           && instring[4] != 'q')
                    losing++;
                    losing++;
                  break;
                  break;
 
 
                case 'O':
                case 'O':
                  if (opP->mode != DREG
                  if (opP->mode != DREG
                      && opP->mode != IMMED
                      && opP->mode != IMMED
                      && opP->mode != ABSL)
                      && opP->mode != ABSL)
                    losing++;
                    losing++;
                  break;
                  break;
 
 
                case 'Q':
                case 'Q':
                  if (opP->mode != IMMED)
                  if (opP->mode != IMMED)
                    losing++;
                    losing++;
                  else if (opP->disp.exp.X_op != O_constant
                  else if (opP->disp.exp.X_op != O_constant
                           || TRUNC (opP->disp.exp.X_add_number) - 1 > 7)
                           || TRUNC (opP->disp.exp.X_add_number) - 1 > 7)
                    losing++;
                    losing++;
                  else if (! m68k_quick
                  else if (! m68k_quick
                           && (strncmp (instring, "add", 3) == 0
                           && (strncmp (instring, "add", 3) == 0
                               || strncmp (instring, "sub", 3) == 0)
                               || strncmp (instring, "sub", 3) == 0)
                           && instring[3] != 'q')
                           && instring[3] != 'q')
                    losing++;
                    losing++;
                  break;
                  break;
 
 
                case 'R':
                case 'R':
                  if (opP->mode != DREG && opP->mode != AREG)
                  if (opP->mode != DREG && opP->mode != AREG)
                    losing++;
                    losing++;
                  break;
                  break;
 
 
                case 'r':
                case 'r':
                  if (opP->mode != AINDR
                  if (opP->mode != AINDR
                      && (opP->mode != BASE
                      && (opP->mode != BASE
                          || (opP->reg != 0
                          || (opP->reg != 0
                              && opP->reg != ZADDR0)
                              && opP->reg != ZADDR0)
                          || opP->disp.exp.X_op != O_absent
                          || opP->disp.exp.X_op != O_absent
                          || ((opP->index.reg < DATA0
                          || ((opP->index.reg < DATA0
                               || opP->index.reg > DATA7)
                               || opP->index.reg > DATA7)
                              && (opP->index.reg < ADDR0
                              && (opP->index.reg < ADDR0
                                  || opP->index.reg > ADDR7))
                                  || opP->index.reg > ADDR7))
                          || opP->index.size != SIZE_UNSPEC
                          || opP->index.size != SIZE_UNSPEC
                          || opP->index.scale != 1))
                          || opP->index.scale != 1))
                    losing++;
                    losing++;
                  break;
                  break;
 
 
                case 's':
                case 's':
                  if (opP->mode != CONTROL
                  if (opP->mode != CONTROL
                      || ! (opP->reg == FPI
                      || ! (opP->reg == FPI
                            || opP->reg == FPS
                            || opP->reg == FPS
                            || opP->reg == FPC))
                            || opP->reg == FPC))
                    losing++;
                    losing++;
                  break;
                  break;
 
 
                case 'S':
                case 'S':
                  if (opP->mode != CONTROL || opP->reg != SR)
                  if (opP->mode != CONTROL || opP->reg != SR)
                    losing++;
                    losing++;
                  break;
                  break;
 
 
                case 't':
                case 't':
                  if (opP->mode != IMMED)
                  if (opP->mode != IMMED)
                    losing++;
                    losing++;
                  else if (opP->disp.exp.X_op != O_constant
                  else if (opP->disp.exp.X_op != O_constant
                           || TRUNC (opP->disp.exp.X_add_number) > 7)
                           || TRUNC (opP->disp.exp.X_add_number) > 7)
                    losing++;
                    losing++;
                  break;
                  break;
 
 
                case 'U':
                case 'U':
                  if (opP->mode != CONTROL || opP->reg != USP)
                  if (opP->mode != CONTROL || opP->reg != USP)
                    losing++;
                    losing++;
                  break;
                  break;
 
 
                case 'x':
                case 'x':
                  if (opP->mode != IMMED)
                  if (opP->mode != IMMED)
                    losing++;
                    losing++;
                  else if (opP->disp.exp.X_op != O_constant
                  else if (opP->disp.exp.X_op != O_constant
                           || (TRUNC (opP->disp.exp.X_add_number) != 0xffffffff
                           || (TRUNC (opP->disp.exp.X_add_number) != 0xffffffff
                               && TRUNC (opP->disp.exp.X_add_number) - 1 > 6))
                               && TRUNC (opP->disp.exp.X_add_number) - 1 > 6))
                    losing++;
                    losing++;
                  break;
                  break;
 
 
                case 'j':
                case 'j':
                  if (opP->mode != IMMED)
                  if (opP->mode != IMMED)
                    losing++;
                    losing++;
                  else if (opP->disp.exp.X_op != O_constant
                  else if (opP->disp.exp.X_op != O_constant
                           || TRUNC (opP->disp.exp.X_add_number) - 1 > 7)
                           || TRUNC (opP->disp.exp.X_add_number) - 1 > 7)
                    losing++;
                    losing++;
                  break;
                  break;
 
 
                case 'K':
                case 'K':
                  if (opP->mode != IMMED)
                  if (opP->mode != IMMED)
                    losing++;
                    losing++;
                  else if (opP->disp.exp.X_op != O_constant
                  else if (opP->disp.exp.X_op != O_constant
                           || TRUNC (opP->disp.exp.X_add_number) > 511)
                           || TRUNC (opP->disp.exp.X_add_number) > 511)
                    losing++;
                    losing++;
                  break;
                  break;
 
 
                  /* JF these are out of order.  We could put them
                  /* JF these are out of order.  We could put them
                     in order if we were willing to put up with
                     in order if we were willing to put up with
                     bunches of #ifdef m68851s in the code.
                     bunches of #ifdef m68851s in the code.
 
 
                     Don't forget that you need these operands
                     Don't forget that you need these operands
                     to use 68030 MMU instructions.  */
                     to use 68030 MMU instructions.  */
#ifndef NO_68851
#ifndef NO_68851
                  /* Memory addressing mode used by pflushr.  */
                  /* Memory addressing mode used by pflushr.  */
                case '|':
                case '|':
                  if (opP->mode == CONTROL
                  if (opP->mode == CONTROL
                      || opP->mode == FPREG
                      || opP->mode == FPREG
                      || opP->mode == DREG
                      || opP->mode == DREG
                      || opP->mode == AREG
                      || opP->mode == AREG
                      || opP->mode == REGLST)
                      || opP->mode == REGLST)
                    losing++;
                    losing++;
                  /* We should accept immediate operands, but they
                  /* We should accept immediate operands, but they
                     supposedly have to be quad word, and we don't
                     supposedly have to be quad word, and we don't
                     handle that.  I would like to see what a Motorola
                     handle that.  I would like to see what a Motorola
                     assembler does before doing something here.  */
                     assembler does before doing something here.  */
                  if (opP->mode == IMMED)
                  if (opP->mode == IMMED)
                    losing++;
                    losing++;
                  break;
                  break;
 
 
                case 'f':
                case 'f':
                  if (opP->mode != CONTROL
                  if (opP->mode != CONTROL
                      || (opP->reg != SFC && opP->reg != DFC))
                      || (opP->reg != SFC && opP->reg != DFC))
                    losing++;
                    losing++;
                  break;
                  break;
 
 
                case '0':
                case '0':
                  if (opP->mode != CONTROL || opP->reg != TC)
                  if (opP->mode != CONTROL || opP->reg != TC)
                    losing++;
                    losing++;
                  break;
                  break;
 
 
                case '1':
                case '1':
                  if (opP->mode != CONTROL || opP->reg != AC)
                  if (opP->mode != CONTROL || opP->reg != AC)
                    losing++;
                    losing++;
                  break;
                  break;
 
 
                case '2':
                case '2':
                  if (opP->mode != CONTROL
                  if (opP->mode != CONTROL
                      || (opP->reg != CAL
                      || (opP->reg != CAL
                          && opP->reg != VAL
                          && opP->reg != VAL
                          && opP->reg != SCC))
                          && opP->reg != SCC))
                    losing++;
                    losing++;
                  break;
                  break;
 
 
                case 'V':
                case 'V':
                  if (opP->mode != CONTROL
                  if (opP->mode != CONTROL
                      || opP->reg != VAL)
                      || opP->reg != VAL)
                    losing++;
                    losing++;
                  break;
                  break;
 
 
                case 'W':
                case 'W':
                  if (opP->mode != CONTROL
                  if (opP->mode != CONTROL
                      || (opP->reg != DRP
                      || (opP->reg != DRP
                          && opP->reg != SRP
                          && opP->reg != SRP
                          && opP->reg != CRP))
                          && opP->reg != CRP))
                    losing++;
                    losing++;
                  break;
                  break;
 
 
                case 'w':
                case 'w':
                  switch (opP->mode)
                  switch (opP->mode)
                    {
                    {
                      case IMMED:
                      case IMMED:
                      case ABSL:
                      case ABSL:
                      case AREG:
                      case AREG:
                      case DREG:
                      case DREG:
                      case FPREG:
                      case FPREG:
                      case CONTROL:
                      case CONTROL:
                      case POST:
                      case POST:
                      case PRE:
                      case PRE:
                      case REGLST:
                      case REGLST:
                        losing++;
                        losing++;
                        break;
                        break;
                      default:
                      default:
                        break;
                        break;
                    }
                    }
                  break;
                  break;
 
 
                case 'X':
                case 'X':
                  if (opP->mode != CONTROL
                  if (opP->mode != CONTROL
                      || (!(opP->reg >= BAD && opP->reg <= BAD + 7)
                      || (!(opP->reg >= BAD && opP->reg <= BAD + 7)
                          && !(opP->reg >= BAC && opP->reg <= BAC + 7)))
                          && !(opP->reg >= BAC && opP->reg <= BAC + 7)))
                    losing++;
                    losing++;
                  break;
                  break;
 
 
                case 'Y':
                case 'Y':
                  if (opP->mode != CONTROL || opP->reg != PSR)
                  if (opP->mode != CONTROL || opP->reg != PSR)
                    losing++;
                    losing++;
                  break;
                  break;
 
 
                case 'Z':
                case 'Z':
                  if (opP->mode != CONTROL || opP->reg != PCSR)
                  if (opP->mode != CONTROL || opP->reg != PCSR)
                    losing++;
                    losing++;
                  break;
                  break;
#endif
#endif
                case 'c':
                case 'c':
                  if (opP->mode != CONTROL
                  if (opP->mode != CONTROL
                      || (opP->reg != NC
                      || (opP->reg != NC
                          && opP->reg != IC
                          && opP->reg != IC
                          && opP->reg != DC
                          && opP->reg != DC
                          && opP->reg != BC))
                          && opP->reg != BC))
                    losing++;
                    losing++;
                  break;
                  break;
 
 
                case '_':
                case '_':
                  if (opP->mode != ABSL)
                  if (opP->mode != ABSL)
                    ++losing;
                    ++losing;
                  break;
                  break;
 
 
                case 'u':
                case 'u':
                  if (opP->reg < DATA0L || opP->reg > ADDR7U)
                  if (opP->reg < DATA0L || opP->reg > ADDR7U)
                    losing++;
                    losing++;
                  /* FIXME: kludge instead of fixing parser:
                  /* FIXME: kludge instead of fixing parser:
                     upper/lower registers are *not* CONTROL
                     upper/lower registers are *not* CONTROL
                     registers, but ordinary ones.  */
                     registers, but ordinary ones.  */
                  if ((opP->reg >= DATA0L && opP->reg <= DATA7L)
                  if ((opP->reg >= DATA0L && opP->reg <= DATA7L)
                      || (opP->reg >= DATA0U && opP->reg <= DATA7U))
                      || (opP->reg >= DATA0U && opP->reg <= DATA7U))
                    opP->mode = DREG;
                    opP->mode = DREG;
                  else
                  else
                    opP->mode = AREG;
                    opP->mode = AREG;
                  break;
                  break;
 
 
                 case 'y':
                 case 'y':
                   if (!(opP->mode == AINDR
                   if (!(opP->mode == AINDR
                         || (opP->mode == DISP
                         || (opP->mode == DISP
                             && !(opP->reg == PC || opP->reg == ZPC))))
                             && !(opP->reg == PC || opP->reg == ZPC))))
                     losing++;
                     losing++;
                   break;
                   break;
 
 
                 case 'z':
                 case 'z':
                   if (!(opP->mode == AINDR || opP->mode == DISP))
                   if (!(opP->mode == AINDR || opP->mode == DISP))
                     losing++;
                     losing++;
                   break;
                   break;
 
 
                default:
                default:
                  abort ();
                  abort ();
                }
                }
 
 
              if (losing)
              if (losing)
                break;
                break;
            }
            }
 
 
          /* Since we have found the correct instruction, copy
          /* Since we have found the correct instruction, copy
             in the modifications that we may have made.  */
             in the modifications that we may have made.  */
          if (!losing)
          if (!losing)
            for (i = 0; i < opsfound; i++)
            for (i = 0; i < opsfound; i++)
              the_ins.operands[i] = operands_backup[i];
              the_ins.operands[i] = operands_backup[i];
        }
        }
 
 
      if (!losing)
      if (!losing)
        break;
        break;
 
 
      opcode = opcode->m_next;
      opcode = opcode->m_next;
 
 
      if (!opcode)
      if (!opcode)
        {
        {
          if (ok_arch
          if (ok_arch
              && !(ok_arch & current_architecture))
              && !(ok_arch & current_architecture))
            {
            {
              const struct m68k_cpu *cpu;
              const struct m68k_cpu *cpu;
              int any = 0;
              int any = 0;
              size_t space = 400;
              size_t space = 400;
              char *buf = xmalloc (space + 1);
              char *buf = xmalloc (space + 1);
              size_t len;
              size_t len;
              int paren = 1;
              int paren = 1;
 
 
              the_ins.error = buf;
              the_ins.error = buf;
              /* Make sure there's a NUL at the end of the buffer -- strncpy
              /* Make sure there's a NUL at the end of the buffer -- strncpy
                 won't write one when it runs out of buffer.  */
                 won't write one when it runs out of buffer.  */
              buf[space] = 0;
              buf[space] = 0;
#define APPEND(STRING) \
#define APPEND(STRING) \
  (strncpy (buf, STRING, space), len = strlen (buf), buf += len, space -= len)
  (strncpy (buf, STRING, space), len = strlen (buf), buf += len, space -= len)
 
 
              APPEND (_("invalid instruction for this architecture; needs "));
              APPEND (_("invalid instruction for this architecture; needs "));
              switch (ok_arch)
              switch (ok_arch)
                {
                {
                case mcfisa_a:
                case mcfisa_a:
                  APPEND ("ColdFire ISA_A");
                  APPEND ("ColdFire ISA_A");
                  break;
                  break;
                case mcfhwdiv:
                case mcfhwdiv:
                  APPEND ("ColdFire ");
                  APPEND ("ColdFire ");
                  APPEND (_("hardware divide"));
                  APPEND (_("hardware divide"));
                  break;
                  break;
                case mcfisa_aa:
                case mcfisa_aa:
                  APPEND ("ColdFire ISA_A+");
                  APPEND ("ColdFire ISA_A+");
                  break;
                  break;
                case mcfisa_b:
                case mcfisa_b:
                  APPEND ("ColdFire ISA_B");
                  APPEND ("ColdFire ISA_B");
                  break;
                  break;
                case mcfisa_c:
                case mcfisa_c:
                  APPEND ("ColdFire ISA_C");
                  APPEND ("ColdFire ISA_C");
                  break;
                  break;
                case cfloat:
                case cfloat:
                  APPEND ("ColdFire fpu");
                  APPEND ("ColdFire fpu");
                  break;
                  break;
                case mfloat:
                case mfloat:
                  APPEND ("M68K fpu");
                  APPEND ("M68K fpu");
                  break;
                  break;
                case mmmu:
                case mmmu:
                  APPEND ("M68K mmu");
                  APPEND ("M68K mmu");
                  break;
                  break;
                case m68020up:
                case m68020up:
                  APPEND ("68020 ");
                  APPEND ("68020 ");
                  APPEND (_("or higher"));
                  APPEND (_("or higher"));
                  break;
                  break;
                case m68000up:
                case m68000up:
                  APPEND ("68000 ");
                  APPEND ("68000 ");
                  APPEND (_("or higher"));
                  APPEND (_("or higher"));
                  break;
                  break;
                case m68010up:
                case m68010up:
                  APPEND ("68010 ");
                  APPEND ("68010 ");
                  APPEND (_("or higher"));
                  APPEND (_("or higher"));
                  break;
                  break;
                default:
                default:
                  paren = 0;
                  paren = 0;
                }
                }
              if (paren)
              if (paren)
                APPEND (" (");
                APPEND (" (");
 
 
              for (cpu = m68k_cpus; cpu->name; cpu++)
              for (cpu = m68k_cpus; cpu->name; cpu++)
                if (!cpu->alias && (cpu->arch & ok_arch))
                if (!cpu->alias && (cpu->arch & ok_arch))
                  {
                  {
                    const struct m68k_cpu *alias;
                    const struct m68k_cpu *alias;
                    int seen_master = 0;
                    int seen_master = 0;
 
 
                    if (any)
                    if (any)
                      APPEND (", ");
                      APPEND (", ");
                    any = 0;
                    any = 0;
                    APPEND (cpu->name);
                    APPEND (cpu->name);
                    for (alias = cpu; alias != m68k_cpus; alias--)
                    for (alias = cpu; alias != m68k_cpus; alias--)
                      if (alias[-1].alias >= 0)
                      if (alias[-1].alias >= 0)
                        break;
                        break;
                    for (; !seen_master || alias->alias > 0; alias++)
                    for (; !seen_master || alias->alias > 0; alias++)
                        {
                        {
                          if (!alias->alias)
                          if (!alias->alias)
                            seen_master = 1;
                            seen_master = 1;
                          else
                          else
                            {
                            {
                              if (any)
                              if (any)
                                APPEND (", ");
                                APPEND (", ");
                              else
                              else
                                APPEND (" [");
                                APPEND (" [");
                              APPEND (alias->name);
                              APPEND (alias->name);
                              any = 1;
                              any = 1;
                            }
                            }
                        }
                        }
                    if (any)
                    if (any)
                      APPEND ("]");
                      APPEND ("]");
                    any = 1;
                    any = 1;
                  }
                  }
              if (paren)
              if (paren)
                APPEND (")");
                APPEND (")");
#undef APPEND
#undef APPEND
              if (!space)
              if (!space)
                {
                {
                  /* We ran out of space, so replace the end of the list
                  /* We ran out of space, so replace the end of the list
                     with ellipsis.  */
                     with ellipsis.  */
                  buf -= 4;
                  buf -= 4;
                  while (*buf != ' ')
                  while (*buf != ' ')
                    buf--;
                    buf--;
                  strcpy (buf, " ...");
                  strcpy (buf, " ...");
                }
                }
            }
            }
          else
          else
            the_ins.error = _("operands mismatch");
            the_ins.error = _("operands mismatch");
          return;
          return;
        }
        }
 
 
      losing = 0;
      losing = 0;
    }
    }
 
 
  /* Now assemble it.  */
  /* Now assemble it.  */
  the_ins.args = opcode->m_operands;
  the_ins.args = opcode->m_operands;
  the_ins.numargs = opcode->m_opnum;
  the_ins.numargs = opcode->m_opnum;
  the_ins.numo = opcode->m_codenum;
  the_ins.numo = opcode->m_codenum;
  the_ins.opcode[0] = getone (opcode);
  the_ins.opcode[0] = getone (opcode);
  the_ins.opcode[1] = gettwo (opcode);
  the_ins.opcode[1] = gettwo (opcode);
 
 
  for (s = the_ins.args, opP = &the_ins.operands[0]; *s; s += 2, opP++)
  for (s = the_ins.args, opP = &the_ins.operands[0]; *s; s += 2, opP++)
    {
    {
      int have_disp = 0;
      int have_disp = 0;
      int use_pl = 0;
      int use_pl = 0;
 
 
      /* This switch is a doozy.
      /* This switch is a doozy.
         Watch the first step; its a big one! */
         Watch the first step; its a big one! */
      switch (s[0])
      switch (s[0])
        {
        {
 
 
        case '*':
        case '*':
        case '~':
        case '~':
        case '%':
        case '%':
        case ';':
        case ';':
        case '@':
        case '@':
        case '!':
        case '!':
        case '&':
        case '&':
        case '$':
        case '$':
        case '?':
        case '?':
        case '/':
        case '/':
        case '<':
        case '<':
        case '>':
        case '>':
        case 'b':
        case 'b':
        case 'm':
        case 'm':
        case 'n':
        case 'n':
        case 'o':
        case 'o':
        case 'p':
        case 'p':
        case 'q':
        case 'q':
        case 'v':
        case 'v':
        case 'w':
        case 'w':
        case 'y':
        case 'y':
        case 'z':
        case 'z':
        case '4':
        case '4':
#ifndef NO_68851
#ifndef NO_68851
        case '|':
        case '|':
#endif
#endif
          switch (opP->mode)
          switch (opP->mode)
            {
            {
            case IMMED:
            case IMMED:
              tmpreg = 0x3c;    /* 7.4 */
              tmpreg = 0x3c;    /* 7.4 */
              if (strchr ("bwl", s[1]))
              if (strchr ("bwl", s[1]))
                nextword = get_num (&opP->disp, 90);
                nextword = get_num (&opP->disp, 90);
              else
              else
                nextword = get_num (&opP->disp, 0);
                nextword = get_num (&opP->disp, 0);
              if (isvar (&opP->disp))
              if (isvar (&opP->disp))
                add_fix (s[1], &opP->disp, 0, 0);
                add_fix (s[1], &opP->disp, 0, 0);
              switch (s[1])
              switch (s[1])
                {
                {
                case 'b':
                case 'b':
                  if (!isbyte (nextword))
                  if (!isbyte (nextword))
                    opP->error = _("operand out of range");
                    opP->error = _("operand out of range");
                  addword (nextword);
                  addword (nextword);
                  baseo = 0;
                  baseo = 0;
                  break;
                  break;
                case 'w':
                case 'w':
                  if (!isword (nextword))
                  if (!isword (nextword))
                    opP->error = _("operand out of range");
                    opP->error = _("operand out of range");
                  addword (nextword);
                  addword (nextword);
                  baseo = 0;
                  baseo = 0;
                  break;
                  break;
                case 'W':
                case 'W':
                  if (!issword (nextword))
                  if (!issword (nextword))
                    opP->error = _("operand out of range");
                    opP->error = _("operand out of range");
                  addword (nextword);
                  addword (nextword);
                  baseo = 0;
                  baseo = 0;
                  break;
                  break;
                case 'l':
                case 'l':
                  addword (nextword >> 16);
                  addword (nextword >> 16);
                  addword (nextword);
                  addword (nextword);
                  baseo = 0;
                  baseo = 0;
                  break;
                  break;
 
 
                case 'f':
                case 'f':
                  baseo = 2;
                  baseo = 2;
                  outro = 8;
                  outro = 8;
                  break;
                  break;
                case 'F':
                case 'F':
                  baseo = 4;
                  baseo = 4;
                  outro = 11;
                  outro = 11;
                  break;
                  break;
                case 'x':
                case 'x':
                  baseo = 6;
                  baseo = 6;
                  outro = 15;
                  outro = 15;
                  break;
                  break;
                case 'p':
                case 'p':
                  baseo = 6;
                  baseo = 6;
                  outro = -1;
                  outro = -1;
                  break;
                  break;
                default:
                default:
                  abort ();
                  abort ();
                }
                }
              if (!baseo)
              if (!baseo)
                break;
                break;
 
 
              /* We gotta put out some float.  */
              /* We gotta put out some float.  */
              if (op (&opP->disp) != O_big)
              if (op (&opP->disp) != O_big)
                {
                {
                  valueT val;
                  valueT val;
                  int gencnt;
                  int gencnt;
 
 
                  /* Can other cases happen here?  */
                  /* Can other cases happen here?  */
                  if (op (&opP->disp) != O_constant)
                  if (op (&opP->disp) != O_constant)
                    abort ();
                    abort ();
 
 
                  val = (valueT) offs (&opP->disp);
                  val = (valueT) offs (&opP->disp);
                  gencnt = 0;
                  gencnt = 0;
                  do
                  do
                    {
                    {
                      generic_bignum[gencnt] = (LITTLENUM_TYPE) val;
                      generic_bignum[gencnt] = (LITTLENUM_TYPE) val;
                      val >>= LITTLENUM_NUMBER_OF_BITS;
                      val >>= LITTLENUM_NUMBER_OF_BITS;
                      ++gencnt;
                      ++gencnt;
                    }
                    }
                  while (val != 0);
                  while (val != 0);
                  offs (&opP->disp) = gencnt;
                  offs (&opP->disp) = gencnt;
                }
                }
              if (offs (&opP->disp) > 0)
              if (offs (&opP->disp) > 0)
                {
                {
                  if (offs (&opP->disp) > baseo)
                  if (offs (&opP->disp) > baseo)
                    {
                    {
                      as_warn (_("Bignum too big for %c format; truncated"),
                      as_warn (_("Bignum too big for %c format; truncated"),
                               s[1]);
                               s[1]);
                      offs (&opP->disp) = baseo;
                      offs (&opP->disp) = baseo;
                    }
                    }
                  baseo -= offs (&opP->disp);
                  baseo -= offs (&opP->disp);
                  while (baseo--)
                  while (baseo--)
                    addword (0);
                    addword (0);
                  for (wordp = generic_bignum + offs (&opP->disp) - 1;
                  for (wordp = generic_bignum + offs (&opP->disp) - 1;
                       offs (&opP->disp)--;
                       offs (&opP->disp)--;
                       --wordp)
                       --wordp)
                    addword (*wordp);
                    addword (*wordp);
                  break;
                  break;
                }
                }
              gen_to_words (words, baseo, (long) outro);
              gen_to_words (words, baseo, (long) outro);
              for (wordp = words; baseo--; wordp++)
              for (wordp = words; baseo--; wordp++)
                addword (*wordp);
                addword (*wordp);
              break;
              break;
            case DREG:
            case DREG:
              tmpreg = opP->reg - DATA; /* 0.dreg */
              tmpreg = opP->reg - DATA; /* 0.dreg */
              break;
              break;
            case AREG:
            case AREG:
              tmpreg = 0x08 + opP->reg - ADDR;  /* 1.areg */
              tmpreg = 0x08 + opP->reg - ADDR;  /* 1.areg */
              break;
              break;
            case AINDR:
            case AINDR:
              tmpreg = 0x10 + opP->reg - ADDR;  /* 2.areg */
              tmpreg = 0x10 + opP->reg - ADDR;  /* 2.areg */
              break;
              break;
            case ADEC:
            case ADEC:
              tmpreg = 0x20 + opP->reg - ADDR;  /* 4.areg */
              tmpreg = 0x20 + opP->reg - ADDR;  /* 4.areg */
              break;
              break;
            case AINC:
            case AINC:
              tmpreg = 0x18 + opP->reg - ADDR;  /* 3.areg */
              tmpreg = 0x18 + opP->reg - ADDR;  /* 3.areg */
              break;
              break;
            case DISP:
            case DISP:
 
 
              nextword = get_num (&opP->disp, 90);
              nextword = get_num (&opP->disp, 90);
 
 
              /* Convert mode 5 addressing with a zero offset into
              /* Convert mode 5 addressing with a zero offset into
                 mode 2 addressing to reduce the instruction size by a
                 mode 2 addressing to reduce the instruction size by a
                 word.  */
                 word.  */
              if (! isvar (&opP->disp)
              if (! isvar (&opP->disp)
                  && (nextword == 0)
                  && (nextword == 0)
                  && (opP->disp.size == SIZE_UNSPEC)
                  && (opP->disp.size == SIZE_UNSPEC)
                  && (opP->reg >= ADDR0)
                  && (opP->reg >= ADDR0)
                  && (opP->reg <= ADDR7))
                  && (opP->reg <= ADDR7))
                {
                {
                  tmpreg = 0x10 + opP->reg - ADDR; /* 2.areg */
                  tmpreg = 0x10 + opP->reg - ADDR; /* 2.areg */
                  break;
                  break;
                }
                }
 
 
              if (opP->reg == PC
              if (opP->reg == PC
                  && ! isvar (&opP->disp)
                  && ! isvar (&opP->disp)
                  && m68k_abspcadd)
                  && m68k_abspcadd)
                {
                {
                  opP->disp.exp.X_op = O_symbol;
                  opP->disp.exp.X_op = O_symbol;
                  opP->disp.exp.X_add_symbol =
                  opP->disp.exp.X_add_symbol =
                    section_symbol (absolute_section);
                    section_symbol (absolute_section);
                }
                }
 
 
              /* Force into index mode.  Hope this works.  */
              /* Force into index mode.  Hope this works.  */
 
 
              /* We do the first bit for 32-bit displacements, and the
              /* We do the first bit for 32-bit displacements, and the
                 second bit for 16 bit ones.  It is possible that we
                 second bit for 16 bit ones.  It is possible that we
                 should make the default be WORD instead of LONG, but
                 should make the default be WORD instead of LONG, but
                 I think that'd break GCC, so we put up with a little
                 I think that'd break GCC, so we put up with a little
                 inefficiency for the sake of working output.  */
                 inefficiency for the sake of working output.  */
 
 
              if (!issword (nextword)
              if (!issword (nextword)
                  || (isvar (&opP->disp)
                  || (isvar (&opP->disp)
                      && ((opP->disp.size == SIZE_UNSPEC
                      && ((opP->disp.size == SIZE_UNSPEC
                           && flag_short_refs == 0
                           && flag_short_refs == 0
                           && cpu_of_arch (current_architecture) >= m68020
                           && cpu_of_arch (current_architecture) >= m68020
                           && ! arch_coldfire_p (current_architecture))
                           && ! arch_coldfire_p (current_architecture))
                          || opP->disp.size == SIZE_LONG)))
                          || opP->disp.size == SIZE_LONG)))
                {
                {
                  if (cpu_of_arch (current_architecture) < m68020
                  if (cpu_of_arch (current_architecture) < m68020
                      || arch_coldfire_p (current_architecture))
                      || arch_coldfire_p (current_architecture))
                    opP->error =
                    opP->error =
                      _("displacement too large for this architecture; needs 68020 or higher");
                      _("displacement too large for this architecture; needs 68020 or higher");
                  if (opP->reg == PC)
                  if (opP->reg == PC)
                    tmpreg = 0x3B;      /* 7.3 */
                    tmpreg = 0x3B;      /* 7.3 */
                  else
                  else
                    tmpreg = 0x30 + opP->reg - ADDR;    /* 6.areg */
                    tmpreg = 0x30 + opP->reg - ADDR;    /* 6.areg */
                  if (isvar (&opP->disp))
                  if (isvar (&opP->disp))
                    {
                    {
                      if (opP->reg == PC)
                      if (opP->reg == PC)
                        {
                        {
                          if (opP->disp.size == SIZE_LONG
                          if (opP->disp.size == SIZE_LONG
#ifdef OBJ_ELF
#ifdef OBJ_ELF
                              /* If the displacement needs pic
                              /* If the displacement needs pic
                                 relocation it cannot be relaxed.  */
                                 relocation it cannot be relaxed.  */
                              || opP->disp.pic_reloc != pic_none
                              || opP->disp.pic_reloc != pic_none
#endif
#endif
                              )
                              )
                            {
                            {
                              addword (0x0170);
                              addword (0x0170);
                              add_fix ('l', &opP->disp, 1, 2);
                              add_fix ('l', &opP->disp, 1, 2);
                            }
                            }
                          else
                          else
                            {
                            {
                              add_frag (adds (&opP->disp),
                              add_frag (adds (&opP->disp),
                                        SEXT (offs (&opP->disp)),
                                        SEXT (offs (&opP->disp)),
                                        TAB (PCREL1632, SZ_UNDEF));
                                        TAB (PCREL1632, SZ_UNDEF));
                              break;
                              break;
                            }
                            }
                        }
                        }
                      else
                      else
                        {
                        {
                          addword (0x0170);
                          addword (0x0170);
                          add_fix ('l', &opP->disp, 0, 0);
                          add_fix ('l', &opP->disp, 0, 0);
                        }
                        }
                    }
                    }
                  else
                  else
                    addword (0x0170);
                    addword (0x0170);
                  addword (nextword >> 16);
                  addword (nextword >> 16);
                }
                }
              else
              else
                {
                {
                  if (opP->reg == PC)
                  if (opP->reg == PC)
                    tmpreg = 0x3A;      /* 7.2 */
                    tmpreg = 0x3A;      /* 7.2 */
                  else
                  else
                    tmpreg = 0x28 + opP->reg - ADDR;    /* 5.areg */
                    tmpreg = 0x28 + opP->reg - ADDR;    /* 5.areg */
 
 
                  if (isvar (&opP->disp))
                  if (isvar (&opP->disp))
                    {
                    {
                      if (opP->reg == PC)
                      if (opP->reg == PC)
                        {
                        {
                          add_fix ('w', &opP->disp, 1, 0);
                          add_fix ('w', &opP->disp, 1, 0);
                        }
                        }
                      else
                      else
                        add_fix ('w', &opP->disp, 0, 0);
                        add_fix ('w', &opP->disp, 0, 0);
                    }
                    }
                }
                }
              addword (nextword);
              addword (nextword);
              break;
              break;
 
 
            case POST:
            case POST:
            case PRE:
            case PRE:
            case BASE:
            case BASE:
              nextword = 0;
              nextword = 0;
              baseo = get_num (&opP->disp, 90);
              baseo = get_num (&opP->disp, 90);
              if (opP->mode == POST || opP->mode == PRE)
              if (opP->mode == POST || opP->mode == PRE)
                outro = get_num (&opP->odisp, 90);
                outro = get_num (&opP->odisp, 90);
              /* Figure out the `addressing mode'.
              /* Figure out the `addressing mode'.
                 Also turn on the BASE_DISABLE bit, if needed.  */
                 Also turn on the BASE_DISABLE bit, if needed.  */
              if (opP->reg == PC || opP->reg == ZPC)
              if (opP->reg == PC || opP->reg == ZPC)
                {
                {
                  tmpreg = 0x3b;        /* 7.3 */
                  tmpreg = 0x3b;        /* 7.3 */
                  if (opP->reg == ZPC)
                  if (opP->reg == ZPC)
                    nextword |= 0x80;
                    nextword |= 0x80;
                }
                }
              else if (opP->reg == 0)
              else if (opP->reg == 0)
                {
                {
                  nextword |= 0x80;
                  nextword |= 0x80;
                  tmpreg = 0x30;        /* 6.garbage */
                  tmpreg = 0x30;        /* 6.garbage */
                }
                }
              else if (opP->reg >= ZADDR0 && opP->reg <= ZADDR7)
              else if (opP->reg >= ZADDR0 && opP->reg <= ZADDR7)
                {
                {
                  nextword |= 0x80;
                  nextword |= 0x80;
                  tmpreg = 0x30 + opP->reg - ZADDR0;
                  tmpreg = 0x30 + opP->reg - ZADDR0;
                }
                }
              else
              else
                tmpreg = 0x30 + opP->reg - ADDR;        /* 6.areg */
                tmpreg = 0x30 + opP->reg - ADDR;        /* 6.areg */
 
 
              siz1 = opP->disp.size;
              siz1 = opP->disp.size;
              if (opP->mode == POST || opP->mode == PRE)
              if (opP->mode == POST || opP->mode == PRE)
                siz2 = opP->odisp.size;
                siz2 = opP->odisp.size;
              else
              else
                siz2 = SIZE_UNSPEC;
                siz2 = SIZE_UNSPEC;
 
 
              /* Index register stuff.  */
              /* Index register stuff.  */
              if (opP->index.reg != 0
              if (opP->index.reg != 0
                  && opP->index.reg >= DATA
                  && opP->index.reg >= DATA
                  && opP->index.reg <= ADDR7)
                  && opP->index.reg <= ADDR7)
                {
                {
                  nextword |= (opP->index.reg - DATA) << 12;
                  nextword |= (opP->index.reg - DATA) << 12;
 
 
                  if (opP->index.size == SIZE_LONG
                  if (opP->index.size == SIZE_LONG
                      || (opP->index.size == SIZE_UNSPEC
                      || (opP->index.size == SIZE_UNSPEC
                          && m68k_index_width_default == SIZE_LONG))
                          && m68k_index_width_default == SIZE_LONG))
                    nextword |= 0x800;
                    nextword |= 0x800;
 
 
                  if ((opP->index.scale != 1
                  if ((opP->index.scale != 1
                       && cpu_of_arch (current_architecture) < m68020)
                       && cpu_of_arch (current_architecture) < m68020)
                      || (opP->index.scale == 8
                      || (opP->index.scale == 8
                          && (arch_coldfire_p (current_architecture)
                          && (arch_coldfire_p (current_architecture)
                              && !arch_coldfire_fpu (current_architecture))))
                              && !arch_coldfire_fpu (current_architecture))))
                    {
                    {
                      opP->error =
                      opP->error =
                        _("scale factor invalid on this architecture; needs cpu32 or 68020 or higher");
                        _("scale factor invalid on this architecture; needs cpu32 or 68020 or higher");
                    }
                    }
 
 
                  if (arch_coldfire_p (current_architecture)
                  if (arch_coldfire_p (current_architecture)
                      && opP->index.size == SIZE_WORD)
                      && opP->index.size == SIZE_WORD)
                    opP->error = _("invalid index size for coldfire");
                    opP->error = _("invalid index size for coldfire");
 
 
                  switch (opP->index.scale)
                  switch (opP->index.scale)
                    {
                    {
                    case 1:
                    case 1:
                      break;
                      break;
                    case 2:
                    case 2:
                      nextword |= 0x200;
                      nextword |= 0x200;
                      break;
                      break;
                    case 4:
                    case 4:
                      nextword |= 0x400;
                      nextword |= 0x400;
                      break;
                      break;
                    case 8:
                    case 8:
                      nextword |= 0x600;
                      nextword |= 0x600;
                      break;
                      break;
                    default:
                    default:
                      abort ();
                      abort ();
                    }
                    }
                  /* IF its simple,
                  /* IF its simple,
                     GET US OUT OF HERE! */
                     GET US OUT OF HERE! */
 
 
                  /* Must be INDEX, with an index register.  Address
                  /* Must be INDEX, with an index register.  Address
                     register cannot be ZERO-PC, and either :b was
                     register cannot be ZERO-PC, and either :b was
                     forced, or we know it will fit.  For a 68000 or
                     forced, or we know it will fit.  For a 68000 or
                     68010, force this mode anyways, because the
                     68010, force this mode anyways, because the
                     larger modes aren't supported.  */
                     larger modes aren't supported.  */
                  if (opP->mode == BASE
                  if (opP->mode == BASE
                      && ((opP->reg >= ADDR0
                      && ((opP->reg >= ADDR0
                           && opP->reg <= ADDR7)
                           && opP->reg <= ADDR7)
                          || opP->reg == PC))
                          || opP->reg == PC))
                    {
                    {
                      if (siz1 == SIZE_BYTE
                      if (siz1 == SIZE_BYTE
                          || cpu_of_arch (current_architecture) < m68020
                          || cpu_of_arch (current_architecture) < m68020
                          || arch_coldfire_p (current_architecture)
                          || arch_coldfire_p (current_architecture)
                          || (siz1 == SIZE_UNSPEC
                          || (siz1 == SIZE_UNSPEC
                              && ! isvar (&opP->disp)
                              && ! isvar (&opP->disp)
                              && issbyte (baseo)))
                              && issbyte (baseo)))
                        {
                        {
                          nextword += baseo & 0xff;
                          nextword += baseo & 0xff;
                          addword (nextword);
                          addword (nextword);
                          if (isvar (&opP->disp))
                          if (isvar (&opP->disp))
                            {
                            {
                              /* Do a byte relocation.  If it doesn't
                              /* Do a byte relocation.  If it doesn't
                                 fit (possible on m68000) let the
                                 fit (possible on m68000) let the
                                 fixup processing complain later.  */
                                 fixup processing complain later.  */
                              if (opP->reg == PC)
                              if (opP->reg == PC)
                                add_fix ('B', &opP->disp, 1, 1);
                                add_fix ('B', &opP->disp, 1, 1);
                              else
                              else
                                add_fix ('B', &opP->disp, 0, 0);
                                add_fix ('B', &opP->disp, 0, 0);
                            }
                            }
                          else if (siz1 != SIZE_BYTE)
                          else if (siz1 != SIZE_BYTE)
                            {
                            {
                              if (siz1 != SIZE_UNSPEC)
                              if (siz1 != SIZE_UNSPEC)
                                as_warn (_("Forcing byte displacement"));
                                as_warn (_("Forcing byte displacement"));
                              if (! issbyte (baseo))
                              if (! issbyte (baseo))
                                opP->error = _("byte displacement out of range");
                                opP->error = _("byte displacement out of range");
                            }
                            }
 
 
                          break;
                          break;
                        }
                        }
                      else if (siz1 == SIZE_UNSPEC
                      else if (siz1 == SIZE_UNSPEC
                               && opP->reg == PC
                               && opP->reg == PC
                               && isvar (&opP->disp)
                               && isvar (&opP->disp)
                               && subs (&opP->disp) == NULL
                               && subs (&opP->disp) == NULL
#ifdef OBJ_ELF
#ifdef OBJ_ELF
                               /* If the displacement needs pic
                               /* If the displacement needs pic
                                  relocation it cannot be relaxed.  */
                                  relocation it cannot be relaxed.  */
                               && opP->disp.pic_reloc == pic_none
                               && opP->disp.pic_reloc == pic_none
#endif
#endif
                               )
                               )
                        {
                        {
                          /* The code in md_convert_frag_1 needs to be
                          /* The code in md_convert_frag_1 needs to be
                             able to adjust nextword.  Call frag_grow
                             able to adjust nextword.  Call frag_grow
                             to ensure that we have enough space in
                             to ensure that we have enough space in
                             the frag obstack to make all the bytes
                             the frag obstack to make all the bytes
                             contiguous.  */
                             contiguous.  */
                          frag_grow (14);
                          frag_grow (14);
                          nextword += baseo & 0xff;
                          nextword += baseo & 0xff;
                          addword (nextword);
                          addword (nextword);
                          add_frag (adds (&opP->disp),
                          add_frag (adds (&opP->disp),
                                    SEXT (offs (&opP->disp)),
                                    SEXT (offs (&opP->disp)),
                                    TAB (PCINDEX, SZ_UNDEF));
                                    TAB (PCINDEX, SZ_UNDEF));
 
 
                          break;
                          break;
                        }
                        }
                    }
                    }
                }
                }
              else
              else
                {
                {
                  nextword |= 0x40;     /* No index reg.  */
                  nextword |= 0x40;     /* No index reg.  */
                  if (opP->index.reg >= ZDATA0
                  if (opP->index.reg >= ZDATA0
                      && opP->index.reg <= ZDATA7)
                      && opP->index.reg <= ZDATA7)
                    nextword |= (opP->index.reg - ZDATA0) << 12;
                    nextword |= (opP->index.reg - ZDATA0) << 12;
                  else if (opP->index.reg >= ZADDR0
                  else if (opP->index.reg >= ZADDR0
                           || opP->index.reg <= ZADDR7)
                           || opP->index.reg <= ZADDR7)
                    nextword |= (opP->index.reg - ZADDR0 + 8) << 12;
                    nextword |= (opP->index.reg - ZADDR0 + 8) << 12;
                }
                }
 
 
              /* It isn't simple.  */
              /* It isn't simple.  */
 
 
              if (cpu_of_arch (current_architecture) < m68020
              if (cpu_of_arch (current_architecture) < m68020
                  || arch_coldfire_p (current_architecture))
                  || arch_coldfire_p (current_architecture))
                opP->error =
                opP->error =
                  _("invalid operand mode for this architecture; needs 68020 or higher");
                  _("invalid operand mode for this architecture; needs 68020 or higher");
 
 
              nextword |= 0x100;
              nextword |= 0x100;
              /* If the guy specified a width, we assume that it is
              /* If the guy specified a width, we assume that it is
                 wide enough.  Maybe it isn't.  If so, we lose.  */
                 wide enough.  Maybe it isn't.  If so, we lose.  */
              switch (siz1)
              switch (siz1)
                {
                {
                case SIZE_UNSPEC:
                case SIZE_UNSPEC:
                  if (isvar (&opP->disp)
                  if (isvar (&opP->disp)
                      ? m68k_rel32
                      ? m68k_rel32
                      : ! issword (baseo))
                      : ! issword (baseo))
                    {
                    {
                      siz1 = SIZE_LONG;
                      siz1 = SIZE_LONG;
                      nextword |= 0x30;
                      nextword |= 0x30;
                    }
                    }
                  else if (! isvar (&opP->disp) && baseo == 0)
                  else if (! isvar (&opP->disp) && baseo == 0)
                    nextword |= 0x10;
                    nextword |= 0x10;
                  else
                  else
                    {
                    {
                      nextword |= 0x20;
                      nextword |= 0x20;
                      siz1 = SIZE_WORD;
                      siz1 = SIZE_WORD;
                    }
                    }
                  break;
                  break;
                case SIZE_BYTE:
                case SIZE_BYTE:
                  as_warn (_(":b not permitted; defaulting to :w"));
                  as_warn (_(":b not permitted; defaulting to :w"));
                  /* Fall through.  */
                  /* Fall through.  */
                case SIZE_WORD:
                case SIZE_WORD:
                  nextword |= 0x20;
                  nextword |= 0x20;
                  break;
                  break;
                case SIZE_LONG:
                case SIZE_LONG:
                  nextword |= 0x30;
                  nextword |= 0x30;
                  break;
                  break;
                }
                }
 
 
              /* Figure out inner displacement stuff.  */
              /* Figure out inner displacement stuff.  */
              if (opP->mode == POST || opP->mode == PRE)
              if (opP->mode == POST || opP->mode == PRE)
                {
                {
                  if (cpu_of_arch (current_architecture) & cpu32)
                  if (cpu_of_arch (current_architecture) & cpu32)
                    opP->error = _("invalid operand mode for this architecture; needs 68020 or higher");
                    opP->error = _("invalid operand mode for this architecture; needs 68020 or higher");
                  switch (siz2)
                  switch (siz2)
                    {
                    {
                    case SIZE_UNSPEC:
                    case SIZE_UNSPEC:
                      if (isvar (&opP->odisp)
                      if (isvar (&opP->odisp)
                          ? m68k_rel32
                          ? m68k_rel32
                          : ! issword (outro))
                          : ! issword (outro))
                        {
                        {
                          siz2 = SIZE_LONG;
                          siz2 = SIZE_LONG;
                          nextword |= 0x3;
                          nextword |= 0x3;
                        }
                        }
                      else if (! isvar (&opP->odisp) && outro == 0)
                      else if (! isvar (&opP->odisp) && outro == 0)
                        nextword |= 0x1;
                        nextword |= 0x1;
                      else
                      else
                        {
                        {
                          nextword |= 0x2;
                          nextword |= 0x2;
                          siz2 = SIZE_WORD;
                          siz2 = SIZE_WORD;
                        }
                        }
                      break;
                      break;
                    case 1:
                    case 1:
                      as_warn (_(":b not permitted; defaulting to :w"));
                      as_warn (_(":b not permitted; defaulting to :w"));
                      /* Fall through.  */
                      /* Fall through.  */
                    case 2:
                    case 2:
                      nextword |= 0x2;
                      nextword |= 0x2;
                      break;
                      break;
                    case 3:
                    case 3:
                      nextword |= 0x3;
                      nextword |= 0x3;
                      break;
                      break;
                    }
                    }
                  if (opP->mode == POST
                  if (opP->mode == POST
                      && (nextword & 0x40) == 0)
                      && (nextword & 0x40) == 0)
                    nextword |= 0x04;
                    nextword |= 0x04;
                }
                }
              addword (nextword);
              addword (nextword);
 
 
              if (siz1 != SIZE_UNSPEC && isvar (&opP->disp))
              if (siz1 != SIZE_UNSPEC && isvar (&opP->disp))
                {
                {
                  if (opP->reg == PC || opP->reg == ZPC)
                  if (opP->reg == PC || opP->reg == ZPC)
                    add_fix (siz1 == SIZE_LONG ? 'l' : 'w', &opP->disp, 1, 2);
                    add_fix (siz1 == SIZE_LONG ? 'l' : 'w', &opP->disp, 1, 2);
                  else
                  else
                    add_fix (siz1 == SIZE_LONG ? 'l' : 'w', &opP->disp, 0, 0);
                    add_fix (siz1 == SIZE_LONG ? 'l' : 'w', &opP->disp, 0, 0);
                }
                }
              if (siz1 == SIZE_LONG)
              if (siz1 == SIZE_LONG)
                addword (baseo >> 16);
                addword (baseo >> 16);
              if (siz1 != SIZE_UNSPEC)
              if (siz1 != SIZE_UNSPEC)
                addword (baseo);
                addword (baseo);
 
 
              if (siz2 != SIZE_UNSPEC && isvar (&opP->odisp))
              if (siz2 != SIZE_UNSPEC && isvar (&opP->odisp))
                add_fix (siz2 == SIZE_LONG ? 'l' : 'w', &opP->odisp, 0, 0);
                add_fix (siz2 == SIZE_LONG ? 'l' : 'w', &opP->odisp, 0, 0);
              if (siz2 == SIZE_LONG)
              if (siz2 == SIZE_LONG)
                addword (outro >> 16);
                addword (outro >> 16);
              if (siz2 != SIZE_UNSPEC)
              if (siz2 != SIZE_UNSPEC)
                addword (outro);
                addword (outro);
 
 
              break;
              break;
 
 
            case ABSL:
            case ABSL:
              nextword = get_num (&opP->disp, 90);
              nextword = get_num (&opP->disp, 90);
              switch (opP->disp.size)
              switch (opP->disp.size)
                {
                {
                default:
                default:
                  abort ();
                  abort ();
                case SIZE_UNSPEC:
                case SIZE_UNSPEC:
                  if (!isvar (&opP->disp) && issword (offs (&opP->disp)))
                  if (!isvar (&opP->disp) && issword (offs (&opP->disp)))
                    {
                    {
                      tmpreg = 0x38;    /* 7.0 */
                      tmpreg = 0x38;    /* 7.0 */
                      addword (nextword);
                      addword (nextword);
                      break;
                      break;
                    }
                    }
                  if (isvar (&opP->disp)
                  if (isvar (&opP->disp)
                      && !subs (&opP->disp)
                      && !subs (&opP->disp)
                      && adds (&opP->disp)
                      && adds (&opP->disp)
#ifdef OBJ_ELF
#ifdef OBJ_ELF
                      /* If the displacement needs pic relocation it
                      /* If the displacement needs pic relocation it
                         cannot be relaxed.  */
                         cannot be relaxed.  */
                      && opP->disp.pic_reloc == pic_none
                      && opP->disp.pic_reloc == pic_none
#endif
#endif
                      && !flag_long_jumps
                      && !flag_long_jumps
                      && !strchr ("~%&$?", s[0]))
                      && !strchr ("~%&$?", s[0]))
                    {
                    {
                      tmpreg = 0x3A;    /* 7.2 */
                      tmpreg = 0x3A;    /* 7.2 */
                      add_frag (adds (&opP->disp),
                      add_frag (adds (&opP->disp),
                                SEXT (offs (&opP->disp)),
                                SEXT (offs (&opP->disp)),
                                TAB (ABSTOPCREL, SZ_UNDEF));
                                TAB (ABSTOPCREL, SZ_UNDEF));
                      break;
                      break;
                    }
                    }
                  /* Fall through into long.  */
                  /* Fall through into long.  */
                case SIZE_LONG:
                case SIZE_LONG:
                  if (isvar (&opP->disp))
                  if (isvar (&opP->disp))
                    add_fix ('l', &opP->disp, 0, 0);
                    add_fix ('l', &opP->disp, 0, 0);
 
 
                  tmpreg = 0x39;/* 7.1 mode */
                  tmpreg = 0x39;/* 7.1 mode */
                  addword (nextword >> 16);
                  addword (nextword >> 16);
                  addword (nextword);
                  addword (nextword);
                  break;
                  break;
 
 
                case SIZE_BYTE:
                case SIZE_BYTE:
                  as_bad (_("unsupported byte value; use a different suffix"));
                  as_bad (_("unsupported byte value; use a different suffix"));
                  /* Fall through.  */
                  /* Fall through.  */
 
 
                case SIZE_WORD:
                case SIZE_WORD:
                  if (isvar (&opP->disp))
                  if (isvar (&opP->disp))
                    add_fix ('w', &opP->disp, 0, 0);
                    add_fix ('w', &opP->disp, 0, 0);
 
 
                  tmpreg = 0x38;/* 7.0 mode */
                  tmpreg = 0x38;/* 7.0 mode */
                  addword (nextword);
                  addword (nextword);
                  break;
                  break;
                }
                }
              break;
              break;
            case CONTROL:
            case CONTROL:
            case FPREG:
            case FPREG:
            default:
            default:
              as_bad (_("unknown/incorrect operand"));
              as_bad (_("unknown/incorrect operand"));
              /* abort (); */
              /* abort (); */
            }
            }
 
 
          /* If s[0] is '4', then this is for the mac instructions
          /* If s[0] is '4', then this is for the mac instructions
             that can have a trailing_ampersand set.  If so, set 0x100
             that can have a trailing_ampersand set.  If so, set 0x100
             bit on tmpreg so install_gen_operand can check for it and
             bit on tmpreg so install_gen_operand can check for it and
             set the appropriate bit (word2, bit 5).  */
             set the appropriate bit (word2, bit 5).  */
          if (s[0] == '4')
          if (s[0] == '4')
            {
            {
              if (opP->trailing_ampersand)
              if (opP->trailing_ampersand)
                tmpreg |= 0x100;
                tmpreg |= 0x100;
            }
            }
          install_gen_operand (s[1], tmpreg);
          install_gen_operand (s[1], tmpreg);
          break;
          break;
 
 
        case '#':
        case '#':
        case '^':
        case '^':
          switch (s[1])
          switch (s[1])
            {                   /* JF: I hate floating point! */
            {                   /* JF: I hate floating point! */
            case 'j':
            case 'j':
              tmpreg = 70;
              tmpreg = 70;
              break;
              break;
            case '8':
            case '8':
              tmpreg = 20;
              tmpreg = 20;
              break;
              break;
            case 'C':
            case 'C':
              tmpreg = 50;
              tmpreg = 50;
              break;
              break;
            case '3':
            case '3':
            default:
            default:
              tmpreg = 90;
              tmpreg = 90;
              break;
              break;
            }
            }
          tmpreg = get_num (&opP->disp, tmpreg);
          tmpreg = get_num (&opP->disp, tmpreg);
          if (isvar (&opP->disp))
          if (isvar (&opP->disp))
            add_fix (s[1], &opP->disp, 0, 0);
            add_fix (s[1], &opP->disp, 0, 0);
          switch (s[1])
          switch (s[1])
            {
            {
            case 'b':           /* Danger:  These do no check for
            case 'b':           /* Danger:  These do no check for
                                   certain types of overflow.
                                   certain types of overflow.
                                   user beware! */
                                   user beware! */
              if (!isbyte (tmpreg))
              if (!isbyte (tmpreg))
                opP->error = _("out of range");
                opP->error = _("out of range");
              insop (tmpreg, opcode);
              insop (tmpreg, opcode);
              if (isvar (&opP->disp))
              if (isvar (&opP->disp))
                the_ins.reloc[the_ins.nrel - 1].n =
                the_ins.reloc[the_ins.nrel - 1].n =
                  (opcode->m_codenum) * 2 + 1;
                  (opcode->m_codenum) * 2 + 1;
              break;
              break;
            case 'B':
            case 'B':
              if (!issbyte (tmpreg))
              if (!issbyte (tmpreg))
                opP->error = _("out of range");
                opP->error = _("out of range");
              the_ins.opcode[the_ins.numo - 1] |= tmpreg & 0xff;
              the_ins.opcode[the_ins.numo - 1] |= tmpreg & 0xff;
              if (isvar (&opP->disp))
              if (isvar (&opP->disp))
                the_ins.reloc[the_ins.nrel - 1].n = opcode->m_codenum * 2 - 1;
                the_ins.reloc[the_ins.nrel - 1].n = opcode->m_codenum * 2 - 1;
              break;
              break;
            case 'w':
            case 'w':
              if (!isword (tmpreg))
              if (!isword (tmpreg))
                opP->error = _("out of range");
                opP->error = _("out of range");
              insop (tmpreg, opcode);
              insop (tmpreg, opcode);
              if (isvar (&opP->disp))
              if (isvar (&opP->disp))
                the_ins.reloc[the_ins.nrel - 1].n = (opcode->m_codenum) * 2;
                the_ins.reloc[the_ins.nrel - 1].n = (opcode->m_codenum) * 2;
              break;
              break;
            case 'W':
            case 'W':
              if (!issword (tmpreg))
              if (!issword (tmpreg))
                opP->error = _("out of range");
                opP->error = _("out of range");
              insop (tmpreg, opcode);
              insop (tmpreg, opcode);
              if (isvar (&opP->disp))
              if (isvar (&opP->disp))
                the_ins.reloc[the_ins.nrel - 1].n = (opcode->m_codenum) * 2;
                the_ins.reloc[the_ins.nrel - 1].n = (opcode->m_codenum) * 2;
              break;
              break;
            case 'l':
            case 'l':
              /* Because of the way insop works, we put these two out
              /* Because of the way insop works, we put these two out
                 backwards.  */
                 backwards.  */
              insop (tmpreg, opcode);
              insop (tmpreg, opcode);
              insop (tmpreg >> 16, opcode);
              insop (tmpreg >> 16, opcode);
              if (isvar (&opP->disp))
              if (isvar (&opP->disp))
                the_ins.reloc[the_ins.nrel - 1].n = (opcode->m_codenum) * 2;
                the_ins.reloc[the_ins.nrel - 1].n = (opcode->m_codenum) * 2;
              break;
              break;
            case '3':
            case '3':
              tmpreg &= 0xFF;
              tmpreg &= 0xFF;
            case '8':
            case '8':
            case 'C':
            case 'C':
            case 'j':
            case 'j':
              install_operand (s[1], tmpreg);
              install_operand (s[1], tmpreg);
              break;
              break;
            default:
            default:
              abort ();
              abort ();
            }
            }
          break;
          break;
 
 
        case '+':
        case '+':
        case '-':
        case '-':
        case 'A':
        case 'A':
        case 'a':
        case 'a':
          install_operand (s[1], opP->reg - ADDR);
          install_operand (s[1], opP->reg - ADDR);
          break;
          break;
 
 
        case 'B':
        case 'B':
          tmpreg = get_num (&opP->disp, 90);
          tmpreg = get_num (&opP->disp, 90);
 
 
          switch (s[1])
          switch (s[1])
            {
            {
            case 'B':
            case 'B':
              add_fix ('B', &opP->disp, 1, -1);
              add_fix ('B', &opP->disp, 1, -1);
              break;
              break;
            case 'W':
            case 'W':
              add_fix ('w', &opP->disp, 1, 0);
              add_fix ('w', &opP->disp, 1, 0);
              addword (0);
              addword (0);
              break;
              break;
            case 'L':
            case 'L':
            long_branch:
            long_branch:
              the_ins.opcode[0] |= 0xff;
              the_ins.opcode[0] |= 0xff;
              add_fix ('l', &opP->disp, 1, 0);
              add_fix ('l', &opP->disp, 1, 0);
              addword (0);
              addword (0);
              addword (0);
              addword (0);
              break;
              break;
            case 'g': /* Conditional branch */
            case 'g': /* Conditional branch */
              have_disp = HAVE_LONG_CALL (current_architecture);
              have_disp = HAVE_LONG_CALL (current_architecture);
              goto var_branch;
              goto var_branch;
 
 
            case 'b': /* Unconditional branch */
            case 'b': /* Unconditional branch */
              have_disp = HAVE_LONG_BRANCH (current_architecture);
              have_disp = HAVE_LONG_BRANCH (current_architecture);
              use_pl = LONG_BRANCH_VIA_COND (current_architecture);
              use_pl = LONG_BRANCH_VIA_COND (current_architecture);
              goto var_branch;
              goto var_branch;
 
 
            case 's': /* Unconditional subroutine */
            case 's': /* Unconditional subroutine */
              have_disp = HAVE_LONG_CALL (current_architecture);
              have_disp = HAVE_LONG_CALL (current_architecture);
 
 
              var_branch:
              var_branch:
              if (subs (&opP->disp)     /* We can't relax it.  */
              if (subs (&opP->disp)     /* We can't relax it.  */
#ifdef OBJ_ELF
#ifdef OBJ_ELF
                  /* If the displacement needs pic relocation it cannot be
                  /* If the displacement needs pic relocation it cannot be
                     relaxed.  */
                     relaxed.  */
                  || opP->disp.pic_reloc != pic_none
                  || opP->disp.pic_reloc != pic_none
#endif
#endif
                  || 0)
                  || 0)
                {
                {
                  if (!have_disp)
                  if (!have_disp)
                    as_warn (_("Can't use long branches on this architecture"));
                    as_warn (_("Can't use long branches on this architecture"));
                  goto long_branch;
                  goto long_branch;
                }
                }
 
 
              /* This could either be a symbol, or an absolute
              /* This could either be a symbol, or an absolute
                 address.  If it's an absolute address, turn it into
                 address.  If it's an absolute address, turn it into
                 an absolute jump right here and keep it out of the
                 an absolute jump right here and keep it out of the
                 relaxer.  */
                 relaxer.  */
              if (adds (&opP->disp) == 0)
              if (adds (&opP->disp) == 0)
                {
                {
                  if (the_ins.opcode[0] == 0x6000)       /* jbra */
                  if (the_ins.opcode[0] == 0x6000)       /* jbra */
                    the_ins.opcode[0] = 0x4EF9;
                    the_ins.opcode[0] = 0x4EF9;
                  else if (the_ins.opcode[0] == 0x6100)  /* jbsr */
                  else if (the_ins.opcode[0] == 0x6100)  /* jbsr */
                    the_ins.opcode[0] = 0x4EB9;
                    the_ins.opcode[0] = 0x4EB9;
                  else                                  /* jCC */
                  else                                  /* jCC */
                    {
                    {
                      the_ins.opcode[0] ^= 0x0100;
                      the_ins.opcode[0] ^= 0x0100;
                      the_ins.opcode[0] |= 0x0006;
                      the_ins.opcode[0] |= 0x0006;
                      addword (0x4EF9);
                      addword (0x4EF9);
                    }
                    }
                  add_fix ('l', &opP->disp, 0, 0);
                  add_fix ('l', &opP->disp, 0, 0);
                  addword (0);
                  addword (0);
                  addword (0);
                  addword (0);
                  break;
                  break;
                }
                }
 
 
              /* Now we know it's going into the relaxer.  Now figure
              /* Now we know it's going into the relaxer.  Now figure
                 out which mode.  We try in this order of preference:
                 out which mode.  We try in this order of preference:
                 long branch, absolute jump, byte/word branches only.  */
                 long branch, absolute jump, byte/word branches only.  */
              if (have_disp)
              if (have_disp)
                add_frag (adds (&opP->disp),
                add_frag (adds (&opP->disp),
                          SEXT (offs (&opP->disp)),
                          SEXT (offs (&opP->disp)),
                          TAB (BRANCHBWL, SZ_UNDEF));
                          TAB (BRANCHBWL, SZ_UNDEF));
              else if (! flag_keep_pcrel)
              else if (! flag_keep_pcrel)
                {
                {
                  if ((the_ins.opcode[0] == 0x6000)
                  if ((the_ins.opcode[0] == 0x6000)
                      || (the_ins.opcode[0] == 0x6100))
                      || (the_ins.opcode[0] == 0x6100))
                    add_frag (adds (&opP->disp),
                    add_frag (adds (&opP->disp),
                              SEXT (offs (&opP->disp)),
                              SEXT (offs (&opP->disp)),
                              TAB (BRABSJUNC, SZ_UNDEF));
                              TAB (BRABSJUNC, SZ_UNDEF));
                  else
                  else
                    add_frag (adds (&opP->disp),
                    add_frag (adds (&opP->disp),
                              SEXT (offs (&opP->disp)),
                              SEXT (offs (&opP->disp)),
                              TAB (BRABSJCOND, SZ_UNDEF));
                              TAB (BRABSJCOND, SZ_UNDEF));
                }
                }
              else
              else
                add_frag (adds (&opP->disp),
                add_frag (adds (&opP->disp),
                          SEXT (offs (&opP->disp)),
                          SEXT (offs (&opP->disp)),
                          (use_pl ? TAB (BRANCHBWPL, SZ_UNDEF)
                          (use_pl ? TAB (BRANCHBWPL, SZ_UNDEF)
                           : TAB (BRANCHBW, SZ_UNDEF)));
                           : TAB (BRANCHBW, SZ_UNDEF)));
              break;
              break;
            case 'w':
            case 'w':
              if (isvar (&opP->disp))
              if (isvar (&opP->disp))
                {
                {
                  /* Check for DBcc instructions.  We can relax them,
                  /* Check for DBcc instructions.  We can relax them,
                     but only if we have long branches and/or absolute
                     but only if we have long branches and/or absolute
                     jumps.  */
                     jumps.  */
                  if (((the_ins.opcode[0] & 0xf0f8) == 0x50c8)
                  if (((the_ins.opcode[0] & 0xf0f8) == 0x50c8)
                      && (HAVE_LONG_BRANCH (current_architecture)
                      && (HAVE_LONG_BRANCH (current_architecture)
                          || ! flag_keep_pcrel))
                          || ! flag_keep_pcrel))
                    {
                    {
                      if (HAVE_LONG_BRANCH (current_architecture))
                      if (HAVE_LONG_BRANCH (current_architecture))
                        add_frag (adds (&opP->disp),
                        add_frag (adds (&opP->disp),
                                  SEXT (offs (&opP->disp)),
                                  SEXT (offs (&opP->disp)),
                                  TAB (DBCCLBR, SZ_UNDEF));
                                  TAB (DBCCLBR, SZ_UNDEF));
                      else
                      else
                        add_frag (adds (&opP->disp),
                        add_frag (adds (&opP->disp),
                                  SEXT (offs (&opP->disp)),
                                  SEXT (offs (&opP->disp)),
                                  TAB (DBCCABSJ, SZ_UNDEF));
                                  TAB (DBCCABSJ, SZ_UNDEF));
                      break;
                      break;
                    }
                    }
                  add_fix ('w', &opP->disp, 1, 0);
                  add_fix ('w', &opP->disp, 1, 0);
                }
                }
              addword (0);
              addword (0);
              break;
              break;
            case 'C':           /* Fixed size LONG coproc branches.  */
            case 'C':           /* Fixed size LONG coproc branches.  */
              add_fix ('l', &opP->disp, 1, 0);
              add_fix ('l', &opP->disp, 1, 0);
              addword (0);
              addword (0);
              addword (0);
              addword (0);
              break;
              break;
            case 'c':           /* Var size Coprocesssor branches.  */
            case 'c':           /* Var size Coprocesssor branches.  */
              if (subs (&opP->disp) || (adds (&opP->disp) == 0))
              if (subs (&opP->disp) || (adds (&opP->disp) == 0))
                {
                {
                  the_ins.opcode[the_ins.numo - 1] |= 0x40;
                  the_ins.opcode[the_ins.numo - 1] |= 0x40;
                  add_fix ('l', &opP->disp, 1, 0);
                  add_fix ('l', &opP->disp, 1, 0);
                  addword (0);
                  addword (0);
                  addword (0);
                  addword (0);
                }
                }
              else
              else
                add_frag (adds (&opP->disp),
                add_frag (adds (&opP->disp),
                          SEXT (offs (&opP->disp)),
                          SEXT (offs (&opP->disp)),
                          TAB (FBRANCH, SZ_UNDEF));
                          TAB (FBRANCH, SZ_UNDEF));
              break;
              break;
            default:
            default:
              abort ();
              abort ();
            }
            }
          break;
          break;
 
 
        case 'C':               /* Ignore it.  */
        case 'C':               /* Ignore it.  */
          break;
          break;
 
 
        case 'd':               /* JF this is a kludge.  */
        case 'd':               /* JF this is a kludge.  */
          install_operand ('s', opP->reg - ADDR);
          install_operand ('s', opP->reg - ADDR);
          tmpreg = get_num (&opP->disp, 90);
          tmpreg = get_num (&opP->disp, 90);
          if (!issword (tmpreg))
          if (!issword (tmpreg))
            {
            {
              as_warn (_("Expression out of range, using 0"));
              as_warn (_("Expression out of range, using 0"));
              tmpreg = 0;
              tmpreg = 0;
            }
            }
          addword (tmpreg);
          addword (tmpreg);
          break;
          break;
 
 
        case 'D':
        case 'D':
          install_operand (s[1], opP->reg - DATA);
          install_operand (s[1], opP->reg - DATA);
          break;
          break;
 
 
        case 'e':  /* EMAC ACCx, reg/reg.  */
        case 'e':  /* EMAC ACCx, reg/reg.  */
          install_operand (s[1], opP->reg - ACC);
          install_operand (s[1], opP->reg - ACC);
          break;
          break;
 
 
        case 'E':               /* Ignore it.  */
        case 'E':               /* Ignore it.  */
          break;
          break;
 
 
        case 'F':
        case 'F':
          install_operand (s[1], opP->reg - FP0);
          install_operand (s[1], opP->reg - FP0);
          break;
          break;
 
 
        case 'g':  /* EMAC ACCEXTx.  */
        case 'g':  /* EMAC ACCEXTx.  */
          install_operand (s[1], opP->reg - ACCEXT01);
          install_operand (s[1], opP->reg - ACCEXT01);
          break;
          break;
 
 
        case 'G':               /* Ignore it.  */
        case 'G':               /* Ignore it.  */
        case 'H':
        case 'H':
          break;
          break;
 
 
        case 'I':
        case 'I':
          tmpreg = opP->reg - COP0;
          tmpreg = opP->reg - COP0;
          install_operand (s[1], tmpreg);
          install_operand (s[1], tmpreg);
          break;
          break;
 
 
        case 'i':  /* MAC/EMAC scale factor.  */
        case 'i':  /* MAC/EMAC scale factor.  */
          install_operand (s[1], opP->mode == LSH ? 0x1 : 0x3);
          install_operand (s[1], opP->mode == LSH ? 0x1 : 0x3);
          break;
          break;
 
 
        case 'J':               /* JF foo.  */
        case 'J':               /* JF foo.  */
          switch (opP->reg)
          switch (opP->reg)
            {
            {
            case SFC:
            case SFC:
              tmpreg = 0x000;
              tmpreg = 0x000;
              break;
              break;
            case DFC:
            case DFC:
              tmpreg = 0x001;
              tmpreg = 0x001;
              break;
              break;
            case CACR:
            case CACR:
              tmpreg = 0x002;
              tmpreg = 0x002;
              break;
              break;
            case TC:
            case TC:
            case ASID:
            case ASID:
              tmpreg = 0x003;
              tmpreg = 0x003;
              break;
              break;
            case ACR0:
            case ACR0:
            case ITT0:
            case ITT0:
              tmpreg = 0x004;
              tmpreg = 0x004;
              break;
              break;
            case ACR1:
            case ACR1:
            case ITT1:
            case ITT1:
              tmpreg = 0x005;
              tmpreg = 0x005;
              break;
              break;
            case ACR2:
            case ACR2:
            case DTT0:
            case DTT0:
              tmpreg = 0x006;
              tmpreg = 0x006;
              break;
              break;
            case ACR3:
            case ACR3:
            case DTT1:
            case DTT1:
              tmpreg = 0x007;
              tmpreg = 0x007;
              break;
              break;
            case BUSCR:
            case BUSCR:
            case MMUBAR:
            case MMUBAR:
              tmpreg = 0x008;
              tmpreg = 0x008;
              break;
              break;
 
 
            case USP:
            case USP:
              tmpreg = 0x800;
              tmpreg = 0x800;
              break;
              break;
            case VBR:
            case VBR:
              tmpreg = 0x801;
              tmpreg = 0x801;
              break;
              break;
            case CAAR:
            case CAAR:
              tmpreg = 0x802;
              tmpreg = 0x802;
              break;
              break;
            case MSP:
            case MSP:
              tmpreg = 0x803;
              tmpreg = 0x803;
              break;
              break;
            case ISP:
            case ISP:
              tmpreg = 0x804;
              tmpreg = 0x804;
              break;
              break;
            case MMUSR:
            case MMUSR:
              tmpreg = 0x805;
              tmpreg = 0x805;
              break;
              break;
            case URP:
            case URP:
              tmpreg = 0x806;
              tmpreg = 0x806;
              break;
              break;
            case SRP:
            case SRP:
              tmpreg = 0x807;
              tmpreg = 0x807;
              break;
              break;
            case PCR:
            case PCR:
              tmpreg = 0x808;
              tmpreg = 0x808;
              break;
              break;
            case ROMBAR:
            case ROMBAR:
            case ROMBAR0:
            case ROMBAR0:
              tmpreg = 0xC00;
              tmpreg = 0xC00;
              break;
              break;
            case ROMBAR1:
            case ROMBAR1:
              tmpreg = 0xC01;
              tmpreg = 0xC01;
              break;
              break;
            case FLASHBAR:
            case FLASHBAR:
            case RAMBAR0:
            case RAMBAR0:
            case RAMBAR_ALT:
            case RAMBAR_ALT:
              tmpreg = 0xC04;
              tmpreg = 0xC04;
              break;
              break;
            case RAMBAR:
            case RAMBAR:
            case RAMBAR1:
            case RAMBAR1:
              tmpreg = 0xC05;
              tmpreg = 0xC05;
              break;
              break;
            case MPCR:
            case MPCR:
              tmpreg = 0xC0C;
              tmpreg = 0xC0C;
              break;
              break;
            case EDRAMBAR:
            case EDRAMBAR:
              tmpreg = 0xC0D;
              tmpreg = 0xC0D;
              break;
              break;
            case MBAR0:
            case MBAR0:
            case MBAR2:
            case MBAR2:
            case SECMBAR:
            case SECMBAR:
              tmpreg = 0xC0E;
              tmpreg = 0xC0E;
              break;
              break;
            case MBAR1:
            case MBAR1:
            case MBAR:
            case MBAR:
              tmpreg = 0xC0F;
              tmpreg = 0xC0F;
              break;
              break;
            case PCR1U0:
            case PCR1U0:
              tmpreg = 0xD02;
              tmpreg = 0xD02;
              break;
              break;
            case PCR1L0:
            case PCR1L0:
              tmpreg = 0xD03;
              tmpreg = 0xD03;
              break;
              break;
            case PCR2U0:
            case PCR2U0:
              tmpreg = 0xD04;
              tmpreg = 0xD04;
              break;
              break;
            case PCR2L0:
            case PCR2L0:
              tmpreg = 0xD05;
              tmpreg = 0xD05;
              break;
              break;
            case PCR3U0:
            case PCR3U0:
              tmpreg = 0xD06;
              tmpreg = 0xD06;
              break;
              break;
            case PCR3L0:
            case PCR3L0:
              tmpreg = 0xD07;
              tmpreg = 0xD07;
              break;
              break;
            case PCR1L1:
            case PCR1L1:
              tmpreg = 0xD0A;
              tmpreg = 0xD0A;
              break;
              break;
            case PCR1U1:
            case PCR1U1:
              tmpreg = 0xD0B;
              tmpreg = 0xD0B;
              break;
              break;
            case PCR2L1:
            case PCR2L1:
              tmpreg = 0xD0C;
              tmpreg = 0xD0C;
              break;
              break;
            case PCR2U1:
            case PCR2U1:
              tmpreg = 0xD0D;
              tmpreg = 0xD0D;
              break;
              break;
            case PCR3L1:
            case PCR3L1:
              tmpreg = 0xD0E;
              tmpreg = 0xD0E;
              break;
              break;
            case PCR3U1:
            case PCR3U1:
              tmpreg = 0xD0F;
              tmpreg = 0xD0F;
              break;
              break;
            case CAC:
            case CAC:
              tmpreg = 0xFFE;
              tmpreg = 0xFFE;
              break;
              break;
            case MBO:
            case MBO:
              tmpreg = 0xFFF;
              tmpreg = 0xFFF;
              break;
              break;
            default:
            default:
              abort ();
              abort ();
            }
            }
          install_operand (s[1], tmpreg);
          install_operand (s[1], tmpreg);
          break;
          break;
 
 
        case 'k':
        case 'k':
          tmpreg = get_num (&opP->disp, 55);
          tmpreg = get_num (&opP->disp, 55);
          install_operand (s[1], tmpreg & 0x7f);
          install_operand (s[1], tmpreg & 0x7f);
          break;
          break;
 
 
        case 'l':
        case 'l':
          tmpreg = opP->mask;
          tmpreg = opP->mask;
          if (s[1] == 'w')
          if (s[1] == 'w')
            {
            {
              if (tmpreg & 0x7FF0000)
              if (tmpreg & 0x7FF0000)
                as_bad (_("Floating point register in register list"));
                as_bad (_("Floating point register in register list"));
              insop (reverse_16_bits (tmpreg), opcode);
              insop (reverse_16_bits (tmpreg), opcode);
            }
            }
          else
          else
            {
            {
              if (tmpreg & 0x700FFFF)
              if (tmpreg & 0x700FFFF)
                as_bad (_("Wrong register in floating-point reglist"));
                as_bad (_("Wrong register in floating-point reglist"));
              install_operand (s[1], reverse_8_bits (tmpreg >> 16));
              install_operand (s[1], reverse_8_bits (tmpreg >> 16));
            }
            }
          break;
          break;
 
 
        case 'L':
        case 'L':
          tmpreg = opP->mask;
          tmpreg = opP->mask;
          if (s[1] == 'w')
          if (s[1] == 'w')
            {
            {
              if (tmpreg & 0x7FF0000)
              if (tmpreg & 0x7FF0000)
                as_bad (_("Floating point register in register list"));
                as_bad (_("Floating point register in register list"));
              insop (tmpreg, opcode);
              insop (tmpreg, opcode);
            }
            }
          else if (s[1] == '8')
          else if (s[1] == '8')
            {
            {
              if (tmpreg & 0x0FFFFFF)
              if (tmpreg & 0x0FFFFFF)
                as_bad (_("incorrect register in reglist"));
                as_bad (_("incorrect register in reglist"));
              install_operand (s[1], tmpreg >> 24);
              install_operand (s[1], tmpreg >> 24);
            }
            }
          else
          else
            {
            {
              if (tmpreg & 0x700FFFF)
              if (tmpreg & 0x700FFFF)
                as_bad (_("wrong register in floating-point reglist"));
                as_bad (_("wrong register in floating-point reglist"));
              else
              else
                install_operand (s[1], tmpreg >> 16);
                install_operand (s[1], tmpreg >> 16);
            }
            }
          break;
          break;
 
 
        case 'M':
        case 'M':
          install_operand (s[1], get_num (&opP->disp, 60));
          install_operand (s[1], get_num (&opP->disp, 60));
          break;
          break;
 
 
        case 'O':
        case 'O':
          tmpreg = ((opP->mode == DREG)
          tmpreg = ((opP->mode == DREG)
                    ? 0x20 + (int) (opP->reg - DATA)
                    ? 0x20 + (int) (opP->reg - DATA)
                    : (get_num (&opP->disp, 40) & 0x1F));
                    : (get_num (&opP->disp, 40) & 0x1F));
          install_operand (s[1], tmpreg);
          install_operand (s[1], tmpreg);
          break;
          break;
 
 
        case 'Q':
        case 'Q':
          tmpreg = get_num (&opP->disp, 10);
          tmpreg = get_num (&opP->disp, 10);
          if (tmpreg == 8)
          if (tmpreg == 8)
            tmpreg = 0;
            tmpreg = 0;
          install_operand (s[1], tmpreg);
          install_operand (s[1], tmpreg);
          break;
          break;
 
 
        case 'R':
        case 'R':
          /* This depends on the fact that ADDR registers are eight
          /* This depends on the fact that ADDR registers are eight
             more than their corresponding DATA regs, so the result
             more than their corresponding DATA regs, so the result
             will have the ADDR_REG bit set.  */
             will have the ADDR_REG bit set.  */
          install_operand (s[1], opP->reg - DATA);
          install_operand (s[1], opP->reg - DATA);
          break;
          break;
 
 
        case 'r':
        case 'r':
          if (opP->mode == AINDR)
          if (opP->mode == AINDR)
            install_operand (s[1], opP->reg - DATA);
            install_operand (s[1], opP->reg - DATA);
          else
          else
            install_operand (s[1], opP->index.reg - DATA);
            install_operand (s[1], opP->index.reg - DATA);
          break;
          break;
 
 
        case 's':
        case 's':
          if (opP->reg == FPI)
          if (opP->reg == FPI)
            tmpreg = 0x1;
            tmpreg = 0x1;
          else if (opP->reg == FPS)
          else if (opP->reg == FPS)
            tmpreg = 0x2;
            tmpreg = 0x2;
          else if (opP->reg == FPC)
          else if (opP->reg == FPC)
            tmpreg = 0x4;
            tmpreg = 0x4;
          else
          else
            abort ();
            abort ();
          install_operand (s[1], tmpreg);
          install_operand (s[1], tmpreg);
          break;
          break;
 
 
        case 'S':               /* Ignore it.  */
        case 'S':               /* Ignore it.  */
          break;
          break;
 
 
        case 'T':
        case 'T':
          install_operand (s[1], get_num (&opP->disp, 30));
          install_operand (s[1], get_num (&opP->disp, 30));
          break;
          break;
 
 
        case 'U':               /* Ignore it.  */
        case 'U':               /* Ignore it.  */
          break;
          break;
 
 
        case 'c':
        case 'c':
          switch (opP->reg)
          switch (opP->reg)
            {
            {
            case NC:
            case NC:
              tmpreg = 0;
              tmpreg = 0;
              break;
              break;
            case DC:
            case DC:
              tmpreg = 1;
              tmpreg = 1;
              break;
              break;
            case IC:
            case IC:
              tmpreg = 2;
              tmpreg = 2;
              break;
              break;
            case BC:
            case BC:
              tmpreg = 3;
              tmpreg = 3;
              break;
              break;
            default:
            default:
              as_fatal (_("failed sanity check"));
              as_fatal (_("failed sanity check"));
            }                   /* switch on cache token.  */
            }                   /* switch on cache token.  */
          install_operand (s[1], tmpreg);
          install_operand (s[1], tmpreg);
          break;
          break;
#ifndef NO_68851
#ifndef NO_68851
          /* JF: These are out of order, I fear.  */
          /* JF: These are out of order, I fear.  */
        case 'f':
        case 'f':
          switch (opP->reg)
          switch (opP->reg)
            {
            {
            case SFC:
            case SFC:
              tmpreg = 0;
              tmpreg = 0;
              break;
              break;
            case DFC:
            case DFC:
              tmpreg = 1;
              tmpreg = 1;
              break;
              break;
            default:
            default:
              abort ();
              abort ();
            }
            }
          install_operand (s[1], tmpreg);
          install_operand (s[1], tmpreg);
          break;
          break;
 
 
        case '0':
        case '0':
        case '1':
        case '1':
        case '2':
        case '2':
          switch (opP->reg)
          switch (opP->reg)
            {
            {
            case TC:
            case TC:
              tmpreg = 0;
              tmpreg = 0;
              break;
              break;
            case CAL:
            case CAL:
              tmpreg = 4;
              tmpreg = 4;
              break;
              break;
            case VAL:
            case VAL:
              tmpreg = 5;
              tmpreg = 5;
              break;
              break;
            case SCC:
            case SCC:
              tmpreg = 6;
              tmpreg = 6;
              break;
              break;
            case AC:
            case AC:
              tmpreg = 7;
              tmpreg = 7;
              break;
              break;
            default:
            default:
              abort ();
              abort ();
            }
            }
          install_operand (s[1], tmpreg);
          install_operand (s[1], tmpreg);
          break;
          break;
 
 
        case 'V':
        case 'V':
          if (opP->reg == VAL)
          if (opP->reg == VAL)
            break;
            break;
          abort ();
          abort ();
 
 
        case 'W':
        case 'W':
          switch (opP->reg)
          switch (opP->reg)
            {
            {
            case DRP:
            case DRP:
              tmpreg = 1;
              tmpreg = 1;
              break;
              break;
            case SRP:
            case SRP:
              tmpreg = 2;
              tmpreg = 2;
              break;
              break;
            case CRP:
            case CRP:
              tmpreg = 3;
              tmpreg = 3;
              break;
              break;
            default:
            default:
              abort ();
              abort ();
            }
            }
          install_operand (s[1], tmpreg);
          install_operand (s[1], tmpreg);
          break;
          break;
 
 
        case 'X':
        case 'X':
          switch (opP->reg)
          switch (opP->reg)
            {
            {
            case BAD:
            case BAD:
            case BAD + 1:
            case BAD + 1:
            case BAD + 2:
            case BAD + 2:
            case BAD + 3:
            case BAD + 3:
            case BAD + 4:
            case BAD + 4:
            case BAD + 5:
            case BAD + 5:
            case BAD + 6:
            case BAD + 6:
            case BAD + 7:
            case BAD + 7:
              tmpreg = (4 << 10) | ((opP->reg - BAD) << 2);
              tmpreg = (4 << 10) | ((opP->reg - BAD) << 2);
              break;
              break;
 
 
            case BAC:
            case BAC:
            case BAC + 1:
            case BAC + 1:
            case BAC + 2:
            case BAC + 2:
            case BAC + 3:
            case BAC + 3:
            case BAC + 4:
            case BAC + 4:
            case BAC + 5:
            case BAC + 5:
            case BAC + 6:
            case BAC + 6:
            case BAC + 7:
            case BAC + 7:
              tmpreg = (5 << 10) | ((opP->reg - BAC) << 2);
              tmpreg = (5 << 10) | ((opP->reg - BAC) << 2);
              break;
              break;
 
 
            default:
            default:
              abort ();
              abort ();
            }
            }
          install_operand (s[1], tmpreg);
          install_operand (s[1], tmpreg);
          break;
          break;
        case 'Y':
        case 'Y':
          know (opP->reg == PSR);
          know (opP->reg == PSR);
          break;
          break;
        case 'Z':
        case 'Z':
          know (opP->reg == PCSR);
          know (opP->reg == PCSR);
          break;
          break;
#endif /* m68851 */
#endif /* m68851 */
        case '3':
        case '3':
          switch (opP->reg)
          switch (opP->reg)
            {
            {
            case TT0:
            case TT0:
              tmpreg = 2;
              tmpreg = 2;
              break;
              break;
            case TT1:
            case TT1:
              tmpreg = 3;
              tmpreg = 3;
              break;
              break;
            default:
            default:
              abort ();
              abort ();
            }
            }
          install_operand (s[1], tmpreg);
          install_operand (s[1], tmpreg);
          break;
          break;
        case 't':
        case 't':
          tmpreg = get_num (&opP->disp, 20);
          tmpreg = get_num (&opP->disp, 20);
          install_operand (s[1], tmpreg);
          install_operand (s[1], tmpreg);
          break;
          break;
        case '_':       /* used only for move16 absolute 32-bit address.  */
        case '_':       /* used only for move16 absolute 32-bit address.  */
          if (isvar (&opP->disp))
          if (isvar (&opP->disp))
            add_fix ('l', &opP->disp, 0, 0);
            add_fix ('l', &opP->disp, 0, 0);
          tmpreg = get_num (&opP->disp, 90);
          tmpreg = get_num (&opP->disp, 90);
          addword (tmpreg >> 16);
          addword (tmpreg >> 16);
          addword (tmpreg & 0xFFFF);
          addword (tmpreg & 0xFFFF);
          break;
          break;
        case 'u':
        case 'u':
          install_operand (s[1], opP->reg - DATA0L);
          install_operand (s[1], opP->reg - DATA0L);
          opP->reg -= (DATA0L);
          opP->reg -= (DATA0L);
          opP->reg &= 0x0F;     /* remove upper/lower bit.  */
          opP->reg &= 0x0F;     /* remove upper/lower bit.  */
          break;
          break;
        case 'x':
        case 'x':
          tmpreg = get_num (&opP->disp, 80);
          tmpreg = get_num (&opP->disp, 80);
          if (tmpreg == -1)
          if (tmpreg == -1)
            tmpreg = 0;
            tmpreg = 0;
          install_operand (s[1], tmpreg);
          install_operand (s[1], tmpreg);
          break;
          break;
        case 'j':
        case 'j':
          tmpreg = get_num (&opP->disp, 10);
          tmpreg = get_num (&opP->disp, 10);
          install_operand (s[1], tmpreg - 1);
          install_operand (s[1], tmpreg - 1);
          break;
          break;
        case 'K':
        case 'K':
          tmpreg = get_num (&opP->disp, 65);
          tmpreg = get_num (&opP->disp, 65);
          install_operand (s[1], tmpreg);
          install_operand (s[1], tmpreg);
          break;
          break;
        default:
        default:
          abort ();
          abort ();
        }
        }
    }
    }
 
 
  /* By the time whe get here (FINALLY) the_ins contains the complete
  /* By the time whe get here (FINALLY) the_ins contains the complete
     instruction, ready to be emitted. . .  */
     instruction, ready to be emitted. . .  */
}
}
 
 
static int
static int
reverse_16_bits (int in)
reverse_16_bits (int in)
{
{
  int out = 0;
  int out = 0;
  int n;
  int n;
 
 
  static int mask[16] =
  static int mask[16] =
  {
  {
    0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080,
    0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080,
    0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000
    0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000
  };
  };
  for (n = 0; n < 16; n++)
  for (n = 0; n < 16; n++)
    {
    {
      if (in & mask[n])
      if (in & mask[n])
        out |= mask[15 - n];
        out |= mask[15 - n];
    }
    }
  return out;
  return out;
}                               /* reverse_16_bits() */
}                               /* reverse_16_bits() */
 
 
static int
static int
reverse_8_bits (int in)
reverse_8_bits (int in)
{
{
  int out = 0;
  int out = 0;
  int n;
  int n;
 
 
  static int mask[8] =
  static int mask[8] =
  {
  {
    0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080,
    0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080,
  };
  };
 
 
  for (n = 0; n < 8; n++)
  for (n = 0; n < 8; n++)
    {
    {
      if (in & mask[n])
      if (in & mask[n])
        out |= mask[7 - n];
        out |= mask[7 - n];
    }
    }
  return out;
  return out;
}                               /* reverse_8_bits() */
}                               /* reverse_8_bits() */
 
 
/* Cause an extra frag to be generated here, inserting up to
/* Cause an extra frag to be generated here, inserting up to
   FRAG_VAR_SIZE bytes.  TYPE is the subtype of the frag to be
   FRAG_VAR_SIZE bytes.  TYPE is the subtype of the frag to be
   generated; its primary type is rs_machine_dependent.
   generated; its primary type is rs_machine_dependent.
 
 
   The TYPE parameter is also used by md_convert_frag_1 and
   The TYPE parameter is also used by md_convert_frag_1 and
   md_estimate_size_before_relax.  The appropriate type of fixup will
   md_estimate_size_before_relax.  The appropriate type of fixup will
   be emitted by md_convert_frag_1.
   be emitted by md_convert_frag_1.
 
 
   ADD becomes the FR_SYMBOL field of the frag, and OFF the FR_OFFSET.  */
   ADD becomes the FR_SYMBOL field of the frag, and OFF the FR_OFFSET.  */
static void
static void
install_operand (int mode, int val)
install_operand (int mode, int val)
{
{
  switch (mode)
  switch (mode)
    {
    {
    case 's':
    case 's':
      the_ins.opcode[0] |= val & 0xFF;   /* JF FF is for M kludge.  */
      the_ins.opcode[0] |= val & 0xFF;   /* JF FF is for M kludge.  */
      break;
      break;
    case 'd':
    case 'd':
      the_ins.opcode[0] |= val << 9;
      the_ins.opcode[0] |= val << 9;
      break;
      break;
    case 'E':
    case 'E':
      the_ins.opcode[1] |= val << 9;
      the_ins.opcode[1] |= val << 9;
      break;
      break;
    case '1':
    case '1':
      the_ins.opcode[1] |= val << 12;
      the_ins.opcode[1] |= val << 12;
      break;
      break;
    case '2':
    case '2':
      the_ins.opcode[1] |= val << 6;
      the_ins.opcode[1] |= val << 6;
      break;
      break;
    case '3':
    case '3':
      the_ins.opcode[1] |= val;
      the_ins.opcode[1] |= val;
      break;
      break;
    case '4':
    case '4':
      the_ins.opcode[2] |= val << 12;
      the_ins.opcode[2] |= val << 12;
      break;
      break;
    case '5':
    case '5':
      the_ins.opcode[2] |= val << 6;
      the_ins.opcode[2] |= val << 6;
      break;
      break;
    case '6':
    case '6':
      /* DANGER!  This is a hack to force cas2l and cas2w cmds to be
      /* DANGER!  This is a hack to force cas2l and cas2w cmds to be
         three words long! */
         three words long! */
      the_ins.numo++;
      the_ins.numo++;
      the_ins.opcode[2] |= val;
      the_ins.opcode[2] |= val;
      break;
      break;
    case '7':
    case '7':
      the_ins.opcode[1] |= val << 7;
      the_ins.opcode[1] |= val << 7;
      break;
      break;
    case '8':
    case '8':
      the_ins.opcode[1] |= val << 10;
      the_ins.opcode[1] |= val << 10;
      break;
      break;
#ifndef NO_68851
#ifndef NO_68851
    case '9':
    case '9':
      the_ins.opcode[1] |= val << 5;
      the_ins.opcode[1] |= val << 5;
      break;
      break;
#endif
#endif
 
 
    case 't':
    case 't':
      the_ins.opcode[1] |= (val << 10) | (val << 7);
      the_ins.opcode[1] |= (val << 10) | (val << 7);
      break;
      break;
    case 'D':
    case 'D':
      the_ins.opcode[1] |= (val << 12) | val;
      the_ins.opcode[1] |= (val << 12) | val;
      break;
      break;
    case 'g':
    case 'g':
      the_ins.opcode[0] |= val = 0xff;
      the_ins.opcode[0] |= val = 0xff;
      break;
      break;
    case 'i':
    case 'i':
      the_ins.opcode[0] |= val << 9;
      the_ins.opcode[0] |= val << 9;
      break;
      break;
    case 'C':
    case 'C':
      the_ins.opcode[1] |= val;
      the_ins.opcode[1] |= val;
      break;
      break;
    case 'j':
    case 'j':
      the_ins.opcode[1] |= val;
      the_ins.opcode[1] |= val;
      the_ins.numo++;           /* What a hack.  */
      the_ins.numo++;           /* What a hack.  */
      break;
      break;
    case 'k':
    case 'k':
      the_ins.opcode[1] |= val << 4;
      the_ins.opcode[1] |= val << 4;
      break;
      break;
    case 'b':
    case 'b':
    case 'w':
    case 'w':
    case 'W':
    case 'W':
    case 'l':
    case 'l':
      break;
      break;
    case 'e':
    case 'e':
      the_ins.opcode[0] |= (val << 6);
      the_ins.opcode[0] |= (val << 6);
      break;
      break;
    case 'L':
    case 'L':
      the_ins.opcode[1] = (val >> 16);
      the_ins.opcode[1] = (val >> 16);
      the_ins.opcode[2] = val & 0xffff;
      the_ins.opcode[2] = val & 0xffff;
      break;
      break;
    case 'm':
    case 'm':
      the_ins.opcode[0] |= ((val & 0x8) << (6 - 3));
      the_ins.opcode[0] |= ((val & 0x8) << (6 - 3));
      the_ins.opcode[0] |= ((val & 0x7) << 9);
      the_ins.opcode[0] |= ((val & 0x7) << 9);
      the_ins.opcode[1] |= ((val & 0x10) << (7 - 4));
      the_ins.opcode[1] |= ((val & 0x10) << (7 - 4));
      break;
      break;
    case 'n': /* MAC/EMAC Rx on !load.  */
    case 'n': /* MAC/EMAC Rx on !load.  */
      the_ins.opcode[0] |= ((val & 0x8) << (6 - 3));
      the_ins.opcode[0] |= ((val & 0x8) << (6 - 3));
      the_ins.opcode[0] |= ((val & 0x7) << 9);
      the_ins.opcode[0] |= ((val & 0x7) << 9);
      the_ins.opcode[1] |= ((val & 0x10) << (7 - 4));
      the_ins.opcode[1] |= ((val & 0x10) << (7 - 4));
      break;
      break;
    case 'o': /* MAC/EMAC Rx on load.  */
    case 'o': /* MAC/EMAC Rx on load.  */
      the_ins.opcode[1] |= val << 12;
      the_ins.opcode[1] |= val << 12;
      the_ins.opcode[1] |= ((val & 0x10) << (7 - 4));
      the_ins.opcode[1] |= ((val & 0x10) << (7 - 4));
      break;
      break;
    case 'M': /* MAC/EMAC Ry on !load.  */
    case 'M': /* MAC/EMAC Ry on !load.  */
      the_ins.opcode[0] |= (val & 0xF);
      the_ins.opcode[0] |= (val & 0xF);
      the_ins.opcode[1] |= ((val & 0x10) << (6 - 4));
      the_ins.opcode[1] |= ((val & 0x10) << (6 - 4));
      break;
      break;
    case 'N': /* MAC/EMAC Ry on load.  */
    case 'N': /* MAC/EMAC Ry on load.  */
      the_ins.opcode[1] |= (val & 0xF);
      the_ins.opcode[1] |= (val & 0xF);
      the_ins.opcode[1] |= ((val & 0x10) << (6 - 4));
      the_ins.opcode[1] |= ((val & 0x10) << (6 - 4));
      break;
      break;
    case 'h':
    case 'h':
      the_ins.opcode[1] |= ((val != 1) << 10);
      the_ins.opcode[1] |= ((val != 1) << 10);
      break;
      break;
    case 'F':
    case 'F':
      the_ins.opcode[0] |= ((val & 0x3) << 9);
      the_ins.opcode[0] |= ((val & 0x3) << 9);
      break;
      break;
    case 'f':
    case 'f':
      the_ins.opcode[0] |= ((val & 0x3) << 0);
      the_ins.opcode[0] |= ((val & 0x3) << 0);
      break;
      break;
    case 'G':  /* EMAC accumulator in a EMAC load instruction.  */
    case 'G':  /* EMAC accumulator in a EMAC load instruction.  */
      the_ins.opcode[0] |= ((~val & 0x1) << 7);
      the_ins.opcode[0] |= ((~val & 0x1) << 7);
      the_ins.opcode[1] |= ((val & 0x2) << (4 - 1));
      the_ins.opcode[1] |= ((val & 0x2) << (4 - 1));
      break;
      break;
    case 'H':  /* EMAC accumulator in a EMAC non-load instruction.  */
    case 'H':  /* EMAC accumulator in a EMAC non-load instruction.  */
      the_ins.opcode[0] |= ((val & 0x1) << 7);
      the_ins.opcode[0] |= ((val & 0x1) << 7);
      the_ins.opcode[1] |= ((val & 0x2) << (4 - 1));
      the_ins.opcode[1] |= ((val & 0x2) << (4 - 1));
      break;
      break;
    case 'I':
    case 'I':
      the_ins.opcode[1] |= ((val & 0x3) << 9);
      the_ins.opcode[1] |= ((val & 0x3) << 9);
      break;
      break;
    case ']':
    case ']':
      the_ins.opcode[0] |= (val & 0x1) <<10;
      the_ins.opcode[0] |= (val & 0x1) <<10;
      break;
      break;
    case 'c':
    case 'c':
    default:
    default:
      as_fatal (_("failed sanity check."));
      as_fatal (_("failed sanity check."));
    }
    }
}
}
 
 
static void
static void
install_gen_operand (int mode, int val)
install_gen_operand (int mode, int val)
{
{
  switch (mode)
  switch (mode)
    {
    {
    case '/':  /* Special for mask loads for mac/msac insns with
    case '/':  /* Special for mask loads for mac/msac insns with
                  possible mask; trailing_ampersend set in bit 8.  */
                  possible mask; trailing_ampersend set in bit 8.  */
      the_ins.opcode[0] |= (val & 0x3f);
      the_ins.opcode[0] |= (val & 0x3f);
      the_ins.opcode[1] |= (((val & 0x100) >> 8) << 5);
      the_ins.opcode[1] |= (((val & 0x100) >> 8) << 5);
      break;
      break;
    case 's':
    case 's':
      the_ins.opcode[0] |= val;
      the_ins.opcode[0] |= val;
      break;
      break;
    case 'd':
    case 'd':
      /* This is a kludge!!! */
      /* This is a kludge!!! */
      the_ins.opcode[0] |= (val & 0x07) << 9 | (val & 0x38) << 3;
      the_ins.opcode[0] |= (val & 0x07) << 9 | (val & 0x38) << 3;
      break;
      break;
    case 'b':
    case 'b':
    case 'w':
    case 'w':
    case 'l':
    case 'l':
    case 'f':
    case 'f':
    case 'F':
    case 'F':
    case 'x':
    case 'x':
    case 'p':
    case 'p':
      the_ins.opcode[0] |= val;
      the_ins.opcode[0] |= val;
      break;
      break;
      /* more stuff goes here.  */
      /* more stuff goes here.  */
    default:
    default:
      as_fatal (_("failed sanity check."));
      as_fatal (_("failed sanity check."));
    }
    }
}
}
 
 
/* Verify that we have some number of paren pairs, do m68k_ip_op(), and
/* Verify that we have some number of paren pairs, do m68k_ip_op(), and
   then deal with the bitfield hack.  */
   then deal with the bitfield hack.  */
 
 
static char *
static char *
crack_operand (char *str, struct m68k_op *opP)
crack_operand (char *str, struct m68k_op *opP)
{
{
  register int parens;
  register int parens;
  register int c;
  register int c;
  register char *beg_str;
  register char *beg_str;
  int inquote = 0;
  int inquote = 0;
 
 
  if (!str)
  if (!str)
    {
    {
      return str;
      return str;
    }
    }
  beg_str = str;
  beg_str = str;
  for (parens = 0; *str && (parens > 0 || inquote || notend (str)); str++)
  for (parens = 0; *str && (parens > 0 || inquote || notend (str)); str++)
    {
    {
      if (! inquote)
      if (! inquote)
        {
        {
          if (*str == '(')
          if (*str == '(')
            parens++;
            parens++;
          else if (*str == ')')
          else if (*str == ')')
            {
            {
              if (!parens)
              if (!parens)
                {                       /* ERROR.  */
                {                       /* ERROR.  */
                  opP->error = _("Extra )");
                  opP->error = _("Extra )");
                  return str;
                  return str;
                }
                }
              --parens;
              --parens;
            }
            }
        }
        }
      if (flag_mri && *str == '\'')
      if (flag_mri && *str == '\'')
        inquote = ! inquote;
        inquote = ! inquote;
    }
    }
  if (!*str && parens)
  if (!*str && parens)
    {                           /* ERROR.  */
    {                           /* ERROR.  */
      opP->error = _("Missing )");
      opP->error = _("Missing )");
      return str;
      return str;
    }
    }
  c = *str;
  c = *str;
  *str = '\0';
  *str = '\0';
  if (m68k_ip_op (beg_str, opP) != 0)
  if (m68k_ip_op (beg_str, opP) != 0)
    {
    {
      *str = c;
      *str = c;
      return str;
      return str;
    }
    }
  *str = c;
  *str = c;
  if (c == '}')
  if (c == '}')
    c = *++str;                 /* JF bitfield hack.  */
    c = *++str;                 /* JF bitfield hack.  */
  if (c)
  if (c)
    {
    {
      c = *++str;
      c = *++str;
      if (!c)
      if (!c)
        as_bad (_("Missing operand"));
        as_bad (_("Missing operand"));
    }
    }
 
 
  /* Detect MRI REG symbols and convert them to REGLSTs.  */
  /* Detect MRI REG symbols and convert them to REGLSTs.  */
  if (opP->mode == CONTROL && (int)opP->reg < 0)
  if (opP->mode == CONTROL && (int)opP->reg < 0)
    {
    {
      opP->mode = REGLST;
      opP->mode = REGLST;
      opP->mask = ~(int)opP->reg;
      opP->mask = ~(int)opP->reg;
      opP->reg = 0;
      opP->reg = 0;
    }
    }
 
 
  return str;
  return str;
}
}
 
 
/* This is the guts of the machine-dependent assembler.  STR points to a
/* This is the guts of the machine-dependent assembler.  STR points to a
   machine dependent instruction.  This function is supposed to emit
   machine dependent instruction.  This function is supposed to emit
   the frags/bytes it assembles to.
   the frags/bytes it assembles to.
   */
   */
 
 
static void
static void
insert_reg (const char *regname, int regnum)
insert_reg (const char *regname, int regnum)
{
{
  char buf[100];
  char buf[100];
  int i;
  int i;
 
 
#ifdef REGISTER_PREFIX
#ifdef REGISTER_PREFIX
  if (!flag_reg_prefix_optional)
  if (!flag_reg_prefix_optional)
    {
    {
      buf[0] = REGISTER_PREFIX;
      buf[0] = REGISTER_PREFIX;
      strcpy (buf + 1, regname);
      strcpy (buf + 1, regname);
      regname = buf;
      regname = buf;
    }
    }
#endif
#endif
 
 
  symbol_table_insert (symbol_new (regname, reg_section, regnum,
  symbol_table_insert (symbol_new (regname, reg_section, regnum,
                                   &zero_address_frag));
                                   &zero_address_frag));
 
 
  for (i = 0; regname[i]; i++)
  for (i = 0; regname[i]; i++)
    buf[i] = TOUPPER (regname[i]);
    buf[i] = TOUPPER (regname[i]);
  buf[i] = '\0';
  buf[i] = '\0';
 
 
  symbol_table_insert (symbol_new (buf, reg_section, regnum,
  symbol_table_insert (symbol_new (buf, reg_section, regnum,
                                   &zero_address_frag));
                                   &zero_address_frag));
}
}
 
 
struct init_entry
struct init_entry
  {
  {
    const char *name;
    const char *name;
    int number;
    int number;
  };
  };
 
 
static const struct init_entry init_table[] =
static const struct init_entry init_table[] =
{
{
  { "d0", DATA0 },
  { "d0", DATA0 },
  { "d1", DATA1 },
  { "d1", DATA1 },
  { "d2", DATA2 },
  { "d2", DATA2 },
  { "d3", DATA3 },
  { "d3", DATA3 },
  { "d4", DATA4 },
  { "d4", DATA4 },
  { "d5", DATA5 },
  { "d5", DATA5 },
  { "d6", DATA6 },
  { "d6", DATA6 },
  { "d7", DATA7 },
  { "d7", DATA7 },
  { "a0", ADDR0 },
  { "a0", ADDR0 },
  { "a1", ADDR1 },
  { "a1", ADDR1 },
  { "a2", ADDR2 },
  { "a2", ADDR2 },
  { "a3", ADDR3 },
  { "a3", ADDR3 },
  { "a4", ADDR4 },
  { "a4", ADDR4 },
  { "a5", ADDR5 },
  { "a5", ADDR5 },
  { "a6", ADDR6 },
  { "a6", ADDR6 },
  { "fp", ADDR6 },
  { "fp", ADDR6 },
  { "a7", ADDR7 },
  { "a7", ADDR7 },
  { "sp", ADDR7 },
  { "sp", ADDR7 },
  { "ssp", ADDR7 },
  { "ssp", ADDR7 },
  { "fp0", FP0 },
  { "fp0", FP0 },
  { "fp1", FP1 },
  { "fp1", FP1 },
  { "fp2", FP2 },
  { "fp2", FP2 },
  { "fp3", FP3 },
  { "fp3", FP3 },
  { "fp4", FP4 },
  { "fp4", FP4 },
  { "fp5", FP5 },
  { "fp5", FP5 },
  { "fp6", FP6 },
  { "fp6", FP6 },
  { "fp7", FP7 },
  { "fp7", FP7 },
  { "fpi", FPI },
  { "fpi", FPI },
  { "fpiar", FPI },
  { "fpiar", FPI },
  { "fpc", FPI },
  { "fpc", FPI },
  { "fps", FPS },
  { "fps", FPS },
  { "fpsr", FPS },
  { "fpsr", FPS },
  { "fpc", FPC },
  { "fpc", FPC },
  { "fpcr", FPC },
  { "fpcr", FPC },
  { "control", FPC },
  { "control", FPC },
  { "status", FPS },
  { "status", FPS },
  { "iaddr", FPI },
  { "iaddr", FPI },
 
 
  { "cop0", COP0 },
  { "cop0", COP0 },
  { "cop1", COP1 },
  { "cop1", COP1 },
  { "cop2", COP2 },
  { "cop2", COP2 },
  { "cop3", COP3 },
  { "cop3", COP3 },
  { "cop4", COP4 },
  { "cop4", COP4 },
  { "cop5", COP5 },
  { "cop5", COP5 },
  { "cop6", COP6 },
  { "cop6", COP6 },
  { "cop7", COP7 },
  { "cop7", COP7 },
  { "pc", PC },
  { "pc", PC },
  { "zpc", ZPC },
  { "zpc", ZPC },
  { "sr", SR },
  { "sr", SR },
 
 
  { "ccr", CCR },
  { "ccr", CCR },
  { "cc", CCR },
  { "cc", CCR },
 
 
  { "acc", ACC },
  { "acc", ACC },
  { "acc0", ACC },
  { "acc0", ACC },
  { "acc1", ACC1 },
  { "acc1", ACC1 },
  { "acc2", ACC2 },
  { "acc2", ACC2 },
  { "acc3", ACC3 },
  { "acc3", ACC3 },
  { "accext01", ACCEXT01 },
  { "accext01", ACCEXT01 },
  { "accext23", ACCEXT23 },
  { "accext23", ACCEXT23 },
  { "macsr", MACSR },
  { "macsr", MACSR },
  { "mask", MASK },
  { "mask", MASK },
 
 
  /* Control registers.  */
  /* Control registers.  */
  { "sfc", SFC },               /* Source Function Code.  */
  { "sfc", SFC },               /* Source Function Code.  */
  { "sfcr", SFC },
  { "sfcr", SFC },
  { "dfc", DFC },               /* Destination Function Code.  */
  { "dfc", DFC },               /* Destination Function Code.  */
  { "dfcr", DFC },
  { "dfcr", DFC },
  { "cacr", CACR },             /* Cache Control Register.  */
  { "cacr", CACR },             /* Cache Control Register.  */
  { "caar", CAAR },             /* Cache Address Register.  */
  { "caar", CAAR },             /* Cache Address Register.  */
 
 
  { "usp", USP },               /* User Stack Pointer.  */
  { "usp", USP },               /* User Stack Pointer.  */
  { "vbr", VBR },               /* Vector Base Register.  */
  { "vbr", VBR },               /* Vector Base Register.  */
  { "msp", MSP },               /* Master Stack Pointer.  */
  { "msp", MSP },               /* Master Stack Pointer.  */
  { "isp", ISP },               /* Interrupt Stack Pointer.  */
  { "isp", ISP },               /* Interrupt Stack Pointer.  */
 
 
  { "itt0", ITT0 },             /* Instruction Transparent Translation Reg 0.  */
  { "itt0", ITT0 },             /* Instruction Transparent Translation Reg 0.  */
  { "itt1", ITT1 },             /* Instruction Transparent Translation Reg 1.  */
  { "itt1", ITT1 },             /* Instruction Transparent Translation Reg 1.  */
  { "dtt0", DTT0 },             /* Data Transparent Translation Register 0.  */
  { "dtt0", DTT0 },             /* Data Transparent Translation Register 0.  */
  { "dtt1", DTT1 },             /* Data Transparent Translation Register 1.  */
  { "dtt1", DTT1 },             /* Data Transparent Translation Register 1.  */
 
 
  /* 68ec040 versions of same */
  /* 68ec040 versions of same */
  { "iacr0", ITT0 },            /* Instruction Access Control Register 0.  */
  { "iacr0", ITT0 },            /* Instruction Access Control Register 0.  */
  { "iacr1", ITT1 },            /* Instruction Access Control Register 0.  */
  { "iacr1", ITT1 },            /* Instruction Access Control Register 0.  */
  { "dacr0", DTT0 },            /* Data Access Control Register 0.  */
  { "dacr0", DTT0 },            /* Data Access Control Register 0.  */
  { "dacr1", DTT1 },            /* Data Access Control Register 0.  */
  { "dacr1", DTT1 },            /* Data Access Control Register 0.  */
 
 
  /* Coldfire versions of same.  The ColdFire programmer's reference
  /* Coldfire versions of same.  The ColdFire programmer's reference
     manual indicated that the order is 2,3,0,1, but Ken Rose
     manual indicated that the order is 2,3,0,1, but Ken Rose
     <rose@netcom.com> says that 0,1,2,3 is the correct order.  */
     <rose@netcom.com> says that 0,1,2,3 is the correct order.  */
  { "acr0", ACR0 },             /* Access Control Unit 0.  */
  { "acr0", ACR0 },             /* Access Control Unit 0.  */
  { "acr1", ACR1 },             /* Access Control Unit 1.  */
  { "acr1", ACR1 },             /* Access Control Unit 1.  */
  { "acr2", ACR2 },             /* Access Control Unit 2.  */
  { "acr2", ACR2 },             /* Access Control Unit 2.  */
  { "acr3", ACR3 },             /* Access Control Unit 3.  */
  { "acr3", ACR3 },             /* Access Control Unit 3.  */
 
 
  { "tc", TC },                 /* MMU Translation Control Register.  */
  { "tc", TC },                 /* MMU Translation Control Register.  */
  { "tcr", TC },
  { "tcr", TC },
  { "asid", ASID },
  { "asid", ASID },
 
 
  { "mmusr", MMUSR },           /* MMU Status Register.  */
  { "mmusr", MMUSR },           /* MMU Status Register.  */
  { "srp", SRP },               /* User Root Pointer.  */
  { "srp", SRP },               /* User Root Pointer.  */
  { "urp", URP },               /* Supervisor Root Pointer.  */
  { "urp", URP },               /* Supervisor Root Pointer.  */
 
 
  { "buscr", BUSCR },
  { "buscr", BUSCR },
  { "mmubar", MMUBAR },
  { "mmubar", MMUBAR },
  { "pcr", PCR },
  { "pcr", PCR },
 
 
  { "rombar", ROMBAR },         /* ROM Base Address Register.  */
  { "rombar", ROMBAR },         /* ROM Base Address Register.  */
  { "rambar0", RAMBAR0 },       /* ROM Base Address Register.  */
  { "rambar0", RAMBAR0 },       /* ROM Base Address Register.  */
  { "rambar1", RAMBAR1 },       /* ROM Base Address Register.  */
  { "rambar1", RAMBAR1 },       /* ROM Base Address Register.  */
  { "mbar", MBAR },             /* Module Base Address Register.  */
  { "mbar", MBAR },             /* Module Base Address Register.  */
 
 
  { "mbar0",    MBAR0 },        /* mcfv4e registers.  */
  { "mbar0",    MBAR0 },        /* mcfv4e registers.  */
  { "mbar1",    MBAR1 },        /* mcfv4e registers.  */
  { "mbar1",    MBAR1 },        /* mcfv4e registers.  */
  { "rombar0",  ROMBAR0 },      /* mcfv4e registers.  */
  { "rombar0",  ROMBAR0 },      /* mcfv4e registers.  */
  { "rombar1",  ROMBAR1 },      /* mcfv4e registers.  */
  { "rombar1",  ROMBAR1 },      /* mcfv4e registers.  */
  { "mpcr",     MPCR },         /* mcfv4e registers.  */
  { "mpcr",     MPCR },         /* mcfv4e registers.  */
  { "edrambar", EDRAMBAR },     /* mcfv4e registers.  */
  { "edrambar", EDRAMBAR },     /* mcfv4e registers.  */
  { "secmbar",  SECMBAR },      /* mcfv4e registers.  */
  { "secmbar",  SECMBAR },      /* mcfv4e registers.  */
  { "asid",     TC },           /* mcfv4e registers.  */
  { "asid",     TC },           /* mcfv4e registers.  */
  { "mmubar",   BUSCR },        /* mcfv4e registers.  */
  { "mmubar",   BUSCR },        /* mcfv4e registers.  */
  { "pcr1u0",   PCR1U0 },       /* mcfv4e registers.  */
  { "pcr1u0",   PCR1U0 },       /* mcfv4e registers.  */
  { "pcr1l0",   PCR1L0 },       /* mcfv4e registers.  */
  { "pcr1l0",   PCR1L0 },       /* mcfv4e registers.  */
  { "pcr2u0",   PCR2U0 },       /* mcfv4e registers.  */
  { "pcr2u0",   PCR2U0 },       /* mcfv4e registers.  */
  { "pcr2l0",   PCR2L0 },       /* mcfv4e registers.  */
  { "pcr2l0",   PCR2L0 },       /* mcfv4e registers.  */
  { "pcr3u0",   PCR3U0 },       /* mcfv4e registers.  */
  { "pcr3u0",   PCR3U0 },       /* mcfv4e registers.  */
  { "pcr3l0",   PCR3L0 },       /* mcfv4e registers.  */
  { "pcr3l0",   PCR3L0 },       /* mcfv4e registers.  */
  { "pcr1u1",   PCR1U1 },       /* mcfv4e registers.  */
  { "pcr1u1",   PCR1U1 },       /* mcfv4e registers.  */
  { "pcr1l1",   PCR1L1 },       /* mcfv4e registers.  */
  { "pcr1l1",   PCR1L1 },       /* mcfv4e registers.  */
  { "pcr2u1",   PCR2U1 },       /* mcfv4e registers.  */
  { "pcr2u1",   PCR2U1 },       /* mcfv4e registers.  */
  { "pcr2l1",   PCR2L1 },       /* mcfv4e registers.  */
  { "pcr2l1",   PCR2L1 },       /* mcfv4e registers.  */
  { "pcr3u1",   PCR3U1 },       /* mcfv4e registers.  */
  { "pcr3u1",   PCR3U1 },       /* mcfv4e registers.  */
  { "pcr3l1",   PCR3L1 },       /* mcfv4e registers.  */
  { "pcr3l1",   PCR3L1 },       /* mcfv4e registers.  */
 
 
  { "flashbar", FLASHBAR },     /* mcf528x registers.  */
  { "flashbar", FLASHBAR },     /* mcf528x registers.  */
  { "rambar",   RAMBAR },       /* mcf528x registers.  */
  { "rambar",   RAMBAR },       /* mcf528x registers.  */
 
 
  { "mbar2",    MBAR2 },        /* mcf5249 registers.  */
  { "mbar2",    MBAR2 },        /* mcf5249 registers.  */
 
 
  { "cac",    CAC },            /* fido registers.  */
  { "cac",    CAC },            /* fido registers.  */
  { "mbb",    MBO },            /* fido registers (obsolete).  */
  { "mbb",    MBO },            /* fido registers (obsolete).  */
  { "mbo",    MBO },            /* fido registers.  */
  { "mbo",    MBO },            /* fido registers.  */
  /* End of control registers.  */
  /* End of control registers.  */
 
 
  { "ac", AC },
  { "ac", AC },
  { "bc", BC },
  { "bc", BC },
  { "cal", CAL },
  { "cal", CAL },
  { "crp", CRP },
  { "crp", CRP },
  { "drp", DRP },
  { "drp", DRP },
  { "pcsr", PCSR },
  { "pcsr", PCSR },
  { "psr", PSR },
  { "psr", PSR },
  { "scc", SCC },
  { "scc", SCC },
  { "val", VAL },
  { "val", VAL },
  { "bad0", BAD0 },
  { "bad0", BAD0 },
  { "bad1", BAD1 },
  { "bad1", BAD1 },
  { "bad2", BAD2 },
  { "bad2", BAD2 },
  { "bad3", BAD3 },
  { "bad3", BAD3 },
  { "bad4", BAD4 },
  { "bad4", BAD4 },
  { "bad5", BAD5 },
  { "bad5", BAD5 },
  { "bad6", BAD6 },
  { "bad6", BAD6 },
  { "bad7", BAD7 },
  { "bad7", BAD7 },
  { "bac0", BAC0 },
  { "bac0", BAC0 },
  { "bac1", BAC1 },
  { "bac1", BAC1 },
  { "bac2", BAC2 },
  { "bac2", BAC2 },
  { "bac3", BAC3 },
  { "bac3", BAC3 },
  { "bac4", BAC4 },
  { "bac4", BAC4 },
  { "bac5", BAC5 },
  { "bac5", BAC5 },
  { "bac6", BAC6 },
  { "bac6", BAC6 },
  { "bac7", BAC7 },
  { "bac7", BAC7 },
 
 
  { "ic", IC },
  { "ic", IC },
  { "dc", DC },
  { "dc", DC },
  { "nc", NC },
  { "nc", NC },
 
 
  { "tt0", TT0 },
  { "tt0", TT0 },
  { "tt1", TT1 },
  { "tt1", TT1 },
  /* 68ec030 versions of same.  */
  /* 68ec030 versions of same.  */
  { "ac0", TT0 },
  { "ac0", TT0 },
  { "ac1", TT1 },
  { "ac1", TT1 },
  /* 68ec030 access control unit, identical to 030 MMU status reg.  */
  /* 68ec030 access control unit, identical to 030 MMU status reg.  */
  { "acusr", PSR },
  { "acusr", PSR },
 
 
  /* Suppressed data and address registers.  */
  /* Suppressed data and address registers.  */
  { "zd0", ZDATA0 },
  { "zd0", ZDATA0 },
  { "zd1", ZDATA1 },
  { "zd1", ZDATA1 },
  { "zd2", ZDATA2 },
  { "zd2", ZDATA2 },
  { "zd3", ZDATA3 },
  { "zd3", ZDATA3 },
  { "zd4", ZDATA4 },
  { "zd4", ZDATA4 },
  { "zd5", ZDATA5 },
  { "zd5", ZDATA5 },
  { "zd6", ZDATA6 },
  { "zd6", ZDATA6 },
  { "zd7", ZDATA7 },
  { "zd7", ZDATA7 },
  { "za0", ZADDR0 },
  { "za0", ZADDR0 },
  { "za1", ZADDR1 },
  { "za1", ZADDR1 },
  { "za2", ZADDR2 },
  { "za2", ZADDR2 },
  { "za3", ZADDR3 },
  { "za3", ZADDR3 },
  { "za4", ZADDR4 },
  { "za4", ZADDR4 },
  { "za5", ZADDR5 },
  { "za5", ZADDR5 },
  { "za6", ZADDR6 },
  { "za6", ZADDR6 },
  { "za7", ZADDR7 },
  { "za7", ZADDR7 },
 
 
  /* Upper and lower data and address registers, used by macw and msacw.  */
  /* Upper and lower data and address registers, used by macw and msacw.  */
  { "d0l", DATA0L },
  { "d0l", DATA0L },
  { "d1l", DATA1L },
  { "d1l", DATA1L },
  { "d2l", DATA2L },
  { "d2l", DATA2L },
  { "d3l", DATA3L },
  { "d3l", DATA3L },
  { "d4l", DATA4L },
  { "d4l", DATA4L },
  { "d5l", DATA5L },
  { "d5l", DATA5L },
  { "d6l", DATA6L },
  { "d6l", DATA6L },
  { "d7l", DATA7L },
  { "d7l", DATA7L },
 
 
  { "a0l", ADDR0L },
  { "a0l", ADDR0L },
  { "a1l", ADDR1L },
  { "a1l", ADDR1L },
  { "a2l", ADDR2L },
  { "a2l", ADDR2L },
  { "a3l", ADDR3L },
  { "a3l", ADDR3L },
  { "a4l", ADDR4L },
  { "a4l", ADDR4L },
  { "a5l", ADDR5L },
  { "a5l", ADDR5L },
  { "a6l", ADDR6L },
  { "a6l", ADDR6L },
  { "a7l", ADDR7L },
  { "a7l", ADDR7L },
 
 
  { "d0u", DATA0U },
  { "d0u", DATA0U },
  { "d1u", DATA1U },
  { "d1u", DATA1U },
  { "d2u", DATA2U },
  { "d2u", DATA2U },
  { "d3u", DATA3U },
  { "d3u", DATA3U },
  { "d4u", DATA4U },
  { "d4u", DATA4U },
  { "d5u", DATA5U },
  { "d5u", DATA5U },
  { "d6u", DATA6U },
  { "d6u", DATA6U },
  { "d7u", DATA7U },
  { "d7u", DATA7U },
 
 
  { "a0u", ADDR0U },
  { "a0u", ADDR0U },
  { "a1u", ADDR1U },
  { "a1u", ADDR1U },
  { "a2u", ADDR2U },
  { "a2u", ADDR2U },
  { "a3u", ADDR3U },
  { "a3u", ADDR3U },
  { "a4u", ADDR4U },
  { "a4u", ADDR4U },
  { "a5u", ADDR5U },
  { "a5u", ADDR5U },
  { "a6u", ADDR6U },
  { "a6u", ADDR6U },
  { "a7u", ADDR7U },
  { "a7u", ADDR7U },
 
 
  { 0, 0 }
  { 0, 0 }
};
};
 
 
static void
static void
init_regtable (void)
init_regtable (void)
{
{
  int i;
  int i;
  for (i = 0; init_table[i].name; i++)
  for (i = 0; init_table[i].name; i++)
    insert_reg (init_table[i].name, init_table[i].number);
    insert_reg (init_table[i].name, init_table[i].number);
}
}
 
 
void
void
md_assemble (char *str)
md_assemble (char *str)
{
{
  const char *er;
  const char *er;
  short *fromP;
  short *fromP;
  char *toP = NULL;
  char *toP = NULL;
  int m, n = 0;
  int m, n = 0;
  char *to_beg_P;
  char *to_beg_P;
  int shorts_this_frag;
  int shorts_this_frag;
  fixS *fixP;
  fixS *fixP;
 
 
  if (!selected_cpu && !selected_arch)
  if (!selected_cpu && !selected_arch)
    {
    {
      /* We've not selected an architecture yet.  Set the default
      /* We've not selected an architecture yet.  Set the default
         now.  We do this lazily so that an initial .cpu or .arch directive
         now.  We do this lazily so that an initial .cpu or .arch directive
         can specify.  */
         can specify.  */
      if (!m68k_set_cpu (TARGET_CPU, 1, 1))
      if (!m68k_set_cpu (TARGET_CPU, 1, 1))
        as_bad (_("unrecognized default cpu `%s'"), TARGET_CPU);
        as_bad (_("unrecognized default cpu `%s'"), TARGET_CPU);
    }
    }
  if (!initialized)
  if (!initialized)
    m68k_init_arch ();
    m68k_init_arch ();
 
 
  /* In MRI mode, the instruction and operands are separated by a
  /* In MRI mode, the instruction and operands are separated by a
     space.  Anything following the operands is a comment.  The label
     space.  Anything following the operands is a comment.  The label
     has already been removed.  */
     has already been removed.  */
  if (flag_mri)
  if (flag_mri)
    {
    {
      char *s;
      char *s;
      int fields = 0;
      int fields = 0;
      int infield = 0;
      int infield = 0;
      int inquote = 0;
      int inquote = 0;
 
 
      for (s = str; *s != '\0'; s++)
      for (s = str; *s != '\0'; s++)
        {
        {
          if ((*s == ' ' || *s == '\t') && ! inquote)
          if ((*s == ' ' || *s == '\t') && ! inquote)
            {
            {
              if (infield)
              if (infield)
                {
                {
                  ++fields;
                  ++fields;
                  if (fields >= 2)
                  if (fields >= 2)
                    {
                    {
                      *s = '\0';
                      *s = '\0';
                      break;
                      break;
                    }
                    }
                  infield = 0;
                  infield = 0;
                }
                }
            }
            }
          else
          else
            {
            {
              if (! infield)
              if (! infield)
                infield = 1;
                infield = 1;
              if (*s == '\'')
              if (*s == '\'')
                inquote = ! inquote;
                inquote = ! inquote;
            }
            }
        }
        }
    }
    }
 
 
  memset (&the_ins, '\0', sizeof (the_ins));
  memset (&the_ins, '\0', sizeof (the_ins));
  m68k_ip (str);
  m68k_ip (str);
  er = the_ins.error;
  er = the_ins.error;
  if (!er)
  if (!er)
    {
    {
      for (n = 0; n < the_ins.numargs; n++)
      for (n = 0; n < the_ins.numargs; n++)
        if (the_ins.operands[n].error)
        if (the_ins.operands[n].error)
          {
          {
            er = the_ins.operands[n].error;
            er = the_ins.operands[n].error;
            break;
            break;
          }
          }
    }
    }
  if (er)
  if (er)
    {
    {
      as_bad (_("%s -- statement `%s' ignored"), er, str);
      as_bad (_("%s -- statement `%s' ignored"), er, str);
      return;
      return;
    }
    }
 
 
  /* If there is a current label, record that it marks an instruction.  */
  /* If there is a current label, record that it marks an instruction.  */
  if (current_label != NULL)
  if (current_label != NULL)
    {
    {
      current_label->text = 1;
      current_label->text = 1;
      current_label = NULL;
      current_label = NULL;
    }
    }
 
 
#ifdef OBJ_ELF
#ifdef OBJ_ELF
  /* Tie dwarf2 debug info to the address at the start of the insn.  */
  /* Tie dwarf2 debug info to the address at the start of the insn.  */
  dwarf2_emit_insn (0);
  dwarf2_emit_insn (0);
#endif
#endif
 
 
  if (the_ins.nfrag == 0)
  if (the_ins.nfrag == 0)
    {
    {
      /* No frag hacking involved; just put it out.  */
      /* No frag hacking involved; just put it out.  */
      toP = frag_more (2 * the_ins.numo);
      toP = frag_more (2 * the_ins.numo);
      fromP = &the_ins.opcode[0];
      fromP = &the_ins.opcode[0];
      for (m = the_ins.numo; m; --m)
      for (m = the_ins.numo; m; --m)
        {
        {
          md_number_to_chars (toP, (long) (*fromP), 2);
          md_number_to_chars (toP, (long) (*fromP), 2);
          toP += 2;
          toP += 2;
          fromP++;
          fromP++;
        }
        }
      /* Put out symbol-dependent info.  */
      /* Put out symbol-dependent info.  */
      for (m = 0; m < the_ins.nrel; m++)
      for (m = 0; m < the_ins.nrel; m++)
        {
        {
          switch (the_ins.reloc[m].wid)
          switch (the_ins.reloc[m].wid)
            {
            {
            case 'B':
            case 'B':
              n = 1;
              n = 1;
              break;
              break;
            case 'b':
            case 'b':
              n = 1;
              n = 1;
              break;
              break;
            case '3':
            case '3':
              n = 1;
              n = 1;
              break;
              break;
            case 'w':
            case 'w':
            case 'W':
            case 'W':
              n = 2;
              n = 2;
              break;
              break;
            case 'l':
            case 'l':
              n = 4;
              n = 4;
              break;
              break;
            default:
            default:
              as_fatal (_("Don't know how to figure width of %c in md_assemble()"),
              as_fatal (_("Don't know how to figure width of %c in md_assemble()"),
                        the_ins.reloc[m].wid);
                        the_ins.reloc[m].wid);
            }
            }
 
 
          fixP = fix_new_exp (frag_now,
          fixP = fix_new_exp (frag_now,
                              ((toP - frag_now->fr_literal)
                              ((toP - frag_now->fr_literal)
                               - the_ins.numo * 2 + the_ins.reloc[m].n),
                               - the_ins.numo * 2 + the_ins.reloc[m].n),
                              n,
                              n,
                              &the_ins.reloc[m].exp,
                              &the_ins.reloc[m].exp,
                              the_ins.reloc[m].pcrel,
                              the_ins.reloc[m].pcrel,
                              get_reloc_code (n, the_ins.reloc[m].pcrel,
                              get_reloc_code (n, the_ins.reloc[m].pcrel,
                                              the_ins.reloc[m].pic_reloc));
                                              the_ins.reloc[m].pic_reloc));
          fixP->fx_pcrel_adjust = the_ins.reloc[m].pcrel_fix;
          fixP->fx_pcrel_adjust = the_ins.reloc[m].pcrel_fix;
          if (the_ins.reloc[m].wid == 'B')
          if (the_ins.reloc[m].wid == 'B')
            fixP->fx_signed = 1;
            fixP->fx_signed = 1;
        }
        }
      return;
      return;
    }
    }
 
 
  /* There's some frag hacking.  */
  /* There's some frag hacking.  */
  {
  {
    /* Calculate the max frag size.  */
    /* Calculate the max frag size.  */
    int wid;
    int wid;
 
 
    wid = 2 * the_ins.fragb[0].fragoff;
    wid = 2 * the_ins.fragb[0].fragoff;
    for (n = 1; n < the_ins.nfrag; n++)
    for (n = 1; n < the_ins.nfrag; n++)
      wid += 2 * (the_ins.numo - the_ins.fragb[n - 1].fragoff);
      wid += 2 * (the_ins.numo - the_ins.fragb[n - 1].fragoff);
    /* frag_var part.  */
    /* frag_var part.  */
    wid += FRAG_VAR_SIZE;
    wid += FRAG_VAR_SIZE;
    /* Make sure the whole insn fits in one chunk, in particular that
    /* Make sure the whole insn fits in one chunk, in particular that
       the var part is attached, as we access one byte before the
       the var part is attached, as we access one byte before the
       variable frag for byte branches.  */
       variable frag for byte branches.  */
    frag_grow (wid);
    frag_grow (wid);
  }
  }
 
 
  for (n = 0, fromP = &the_ins.opcode[0]; n < the_ins.nfrag; n++)
  for (n = 0, fromP = &the_ins.opcode[0]; n < the_ins.nfrag; n++)
    {
    {
      int wid;
      int wid;
 
 
      if (n == 0)
      if (n == 0)
        wid = 2 * the_ins.fragb[n].fragoff;
        wid = 2 * the_ins.fragb[n].fragoff;
      else
      else
        wid = 2 * (the_ins.numo - the_ins.fragb[n - 1].fragoff);
        wid = 2 * (the_ins.numo - the_ins.fragb[n - 1].fragoff);
      toP = frag_more (wid);
      toP = frag_more (wid);
      to_beg_P = toP;
      to_beg_P = toP;
      shorts_this_frag = 0;
      shorts_this_frag = 0;
      for (m = wid / 2; m; --m)
      for (m = wid / 2; m; --m)
        {
        {
          md_number_to_chars (toP, (long) (*fromP), 2);
          md_number_to_chars (toP, (long) (*fromP), 2);
          toP += 2;
          toP += 2;
          fromP++;
          fromP++;
          shorts_this_frag++;
          shorts_this_frag++;
        }
        }
      for (m = 0; m < the_ins.nrel; m++)
      for (m = 0; m < the_ins.nrel; m++)
        {
        {
          if ((the_ins.reloc[m].n) >= 2 * shorts_this_frag)
          if ((the_ins.reloc[m].n) >= 2 * shorts_this_frag)
            {
            {
              the_ins.reloc[m].n -= 2 * shorts_this_frag;
              the_ins.reloc[m].n -= 2 * shorts_this_frag;
              break;
              break;
            }
            }
          wid = the_ins.reloc[m].wid;
          wid = the_ins.reloc[m].wid;
          if (wid == 0)
          if (wid == 0)
            continue;
            continue;
          the_ins.reloc[m].wid = 0;
          the_ins.reloc[m].wid = 0;
          wid = (wid == 'b') ? 1 : (wid == 'w') ? 2 : (wid == 'l') ? 4 : 4000;
          wid = (wid == 'b') ? 1 : (wid == 'w') ? 2 : (wid == 'l') ? 4 : 4000;
 
 
          fixP = fix_new_exp (frag_now,
          fixP = fix_new_exp (frag_now,
                              ((toP - frag_now->fr_literal)
                              ((toP - frag_now->fr_literal)
                               - the_ins.numo * 2 + the_ins.reloc[m].n),
                               - the_ins.numo * 2 + the_ins.reloc[m].n),
                              wid,
                              wid,
                              &the_ins.reloc[m].exp,
                              &the_ins.reloc[m].exp,
                              the_ins.reloc[m].pcrel,
                              the_ins.reloc[m].pcrel,
                              get_reloc_code (wid, the_ins.reloc[m].pcrel,
                              get_reloc_code (wid, the_ins.reloc[m].pcrel,
                                              the_ins.reloc[m].pic_reloc));
                                              the_ins.reloc[m].pic_reloc));
          fixP->fx_pcrel_adjust = the_ins.reloc[m].pcrel_fix;
          fixP->fx_pcrel_adjust = the_ins.reloc[m].pcrel_fix;
        }
        }
      (void) frag_var (rs_machine_dependent, FRAG_VAR_SIZE, 0,
      (void) frag_var (rs_machine_dependent, FRAG_VAR_SIZE, 0,
                       (relax_substateT) (the_ins.fragb[n].fragty),
                       (relax_substateT) (the_ins.fragb[n].fragty),
                       the_ins.fragb[n].fadd, the_ins.fragb[n].foff, to_beg_P);
                       the_ins.fragb[n].fadd, the_ins.fragb[n].foff, to_beg_P);
    }
    }
  n = (the_ins.numo - the_ins.fragb[n - 1].fragoff);
  n = (the_ins.numo - the_ins.fragb[n - 1].fragoff);
  shorts_this_frag = 0;
  shorts_this_frag = 0;
  if (n)
  if (n)
    {
    {
      toP = frag_more (n * 2);
      toP = frag_more (n * 2);
      while (n--)
      while (n--)
        {
        {
          md_number_to_chars (toP, (long) (*fromP), 2);
          md_number_to_chars (toP, (long) (*fromP), 2);
          toP += 2;
          toP += 2;
          fromP++;
          fromP++;
          shorts_this_frag++;
          shorts_this_frag++;
        }
        }
    }
    }
  for (m = 0; m < the_ins.nrel; m++)
  for (m = 0; m < the_ins.nrel; m++)
    {
    {
      int wid;
      int wid;
 
 
      wid = the_ins.reloc[m].wid;
      wid = the_ins.reloc[m].wid;
      if (wid == 0)
      if (wid == 0)
        continue;
        continue;
      the_ins.reloc[m].wid = 0;
      the_ins.reloc[m].wid = 0;
      wid = (wid == 'b') ? 1 : (wid == 'w') ? 2 : (wid == 'l') ? 4 : 4000;
      wid = (wid == 'b') ? 1 : (wid == 'w') ? 2 : (wid == 'l') ? 4 : 4000;
 
 
      fixP = fix_new_exp (frag_now,
      fixP = fix_new_exp (frag_now,
                          ((the_ins.reloc[m].n + toP - frag_now->fr_literal)
                          ((the_ins.reloc[m].n + toP - frag_now->fr_literal)
                           - shorts_this_frag * 2),
                           - shorts_this_frag * 2),
                          wid,
                          wid,
                          &the_ins.reloc[m].exp,
                          &the_ins.reloc[m].exp,
                          the_ins.reloc[m].pcrel,
                          the_ins.reloc[m].pcrel,
                          get_reloc_code (wid, the_ins.reloc[m].pcrel,
                          get_reloc_code (wid, the_ins.reloc[m].pcrel,
                                          the_ins.reloc[m].pic_reloc));
                                          the_ins.reloc[m].pic_reloc));
      fixP->fx_pcrel_adjust = the_ins.reloc[m].pcrel_fix;
      fixP->fx_pcrel_adjust = the_ins.reloc[m].pcrel_fix;
    }
    }
}
}
 
 
/* Comparison function used by qsort to rank the opcode entries by name.  */
/* Comparison function used by qsort to rank the opcode entries by name.  */
 
 
static int
static int
m68k_compare_opcode (const void * v1, const void * v2)
m68k_compare_opcode (const void * v1, const void * v2)
{
{
  struct m68k_opcode * op1, * op2;
  struct m68k_opcode * op1, * op2;
  int ret;
  int ret;
 
 
  if (v1 == v2)
  if (v1 == v2)
    return 0;
    return 0;
 
 
  op1 = *(struct m68k_opcode **) v1;
  op1 = *(struct m68k_opcode **) v1;
  op2 = *(struct m68k_opcode **) v2;
  op2 = *(struct m68k_opcode **) v2;
 
 
  /* Compare the two names.  If different, return the comparison.
  /* Compare the two names.  If different, return the comparison.
     If the same, return the order they are in the opcode table.  */
     If the same, return the order they are in the opcode table.  */
  ret = strcmp (op1->name, op2->name);
  ret = strcmp (op1->name, op2->name);
  if (ret)
  if (ret)
    return ret;
    return ret;
  if (op1 < op2)
  if (op1 < op2)
    return -1;
    return -1;
  return 1;
  return 1;
}
}
 
 
void
void
md_begin (void)
md_begin (void)
{
{
  const struct m68k_opcode *ins;
  const struct m68k_opcode *ins;
  struct m68k_incant *hack, *slak;
  struct m68k_incant *hack, *slak;
  const char *retval = 0;        /* Empty string, or error msg text.  */
  const char *retval = 0;        /* Empty string, or error msg text.  */
  int i;
  int i;
 
 
  /* Set up hash tables with 68000 instructions.
  /* Set up hash tables with 68000 instructions.
     similar to what the vax assembler does.  */
     similar to what the vax assembler does.  */
  /* RMS claims the thing to do is take the m68k-opcode.h table, and make
  /* RMS claims the thing to do is take the m68k-opcode.h table, and make
     a copy of it at runtime, adding in the information we want but isn't
     a copy of it at runtime, adding in the information we want but isn't
     there.  I think it'd be better to have an awk script hack the table
     there.  I think it'd be better to have an awk script hack the table
     at compile time.  Or even just xstr the table and use it as-is.  But
     at compile time.  Or even just xstr the table and use it as-is.  But
     my lord ghod hath spoken, so we do it this way.  Excuse the ugly var
     my lord ghod hath spoken, so we do it this way.  Excuse the ugly var
     names.  */
     names.  */
 
 
  if (flag_mri)
  if (flag_mri)
    {
    {
      flag_reg_prefix_optional = 1;
      flag_reg_prefix_optional = 1;
      m68k_abspcadd = 1;
      m68k_abspcadd = 1;
      if (! m68k_rel32_from_cmdline)
      if (! m68k_rel32_from_cmdline)
        m68k_rel32 = 0;
        m68k_rel32 = 0;
    }
    }
 
 
  /* First sort the opcode table into alphabetical order to seperate
  /* First sort the opcode table into alphabetical order to seperate
     the order that the assembler wants to see the opcodes from the
     the order that the assembler wants to see the opcodes from the
     order that the disassembler wants to see them.  */
     order that the disassembler wants to see them.  */
  m68k_sorted_opcodes = xmalloc (m68k_numopcodes * sizeof (* m68k_sorted_opcodes));
  m68k_sorted_opcodes = xmalloc (m68k_numopcodes * sizeof (* m68k_sorted_opcodes));
  if (!m68k_sorted_opcodes)
  if (!m68k_sorted_opcodes)
    as_fatal (_("Internal Error:  Can't allocate m68k_sorted_opcodes of size %d"),
    as_fatal (_("Internal Error:  Can't allocate m68k_sorted_opcodes of size %d"),
              m68k_numopcodes * ((int) sizeof (* m68k_sorted_opcodes)));
              m68k_numopcodes * ((int) sizeof (* m68k_sorted_opcodes)));
 
 
  for (i = m68k_numopcodes; i--;)
  for (i = m68k_numopcodes; i--;)
    m68k_sorted_opcodes[i] = m68k_opcodes + i;
    m68k_sorted_opcodes[i] = m68k_opcodes + i;
 
 
  qsort (m68k_sorted_opcodes, m68k_numopcodes,
  qsort (m68k_sorted_opcodes, m68k_numopcodes,
         sizeof (m68k_sorted_opcodes[0]), m68k_compare_opcode);
         sizeof (m68k_sorted_opcodes[0]), m68k_compare_opcode);
 
 
  op_hash = hash_new ();
  op_hash = hash_new ();
 
 
  obstack_begin (&robyn, 4000);
  obstack_begin (&robyn, 4000);
  for (i = 0; i < m68k_numopcodes; i++)
  for (i = 0; i < m68k_numopcodes; i++)
    {
    {
      hack = slak = (struct m68k_incant *) obstack_alloc (&robyn, sizeof (struct m68k_incant));
      hack = slak = (struct m68k_incant *) obstack_alloc (&robyn, sizeof (struct m68k_incant));
      do
      do
        {
        {
          ins = m68k_sorted_opcodes[i];
          ins = m68k_sorted_opcodes[i];
 
 
          /* We must enter all insns into the table, because .arch and
          /* We must enter all insns into the table, because .arch and
             .cpu directives can change things.  */
             .cpu directives can change things.  */
          slak->m_operands = ins->args;
          slak->m_operands = ins->args;
          slak->m_arch = ins->arch;
          slak->m_arch = ins->arch;
          slak->m_opcode = ins->opcode;
          slak->m_opcode = ins->opcode;
 
 
          /* In most cases we can determine the number of opcode words
          /* In most cases we can determine the number of opcode words
             by checking the second word of the mask.  Unfortunately
             by checking the second word of the mask.  Unfortunately
             some instructions have 2 opcode words, but no fixed bits
             some instructions have 2 opcode words, but no fixed bits
             in the second word.  A leading dot in the operands
             in the second word.  A leading dot in the operands
             string also indicates 2 opcodes.  */
             string also indicates 2 opcodes.  */
          if (*slak->m_operands == '.')
          if (*slak->m_operands == '.')
            {
            {
              slak->m_operands++;
              slak->m_operands++;
              slak->m_codenum = 2;
              slak->m_codenum = 2;
            }
            }
          else if (ins->match & 0xffffL)
          else if (ins->match & 0xffffL)
            slak->m_codenum = 2;
            slak->m_codenum = 2;
          else
          else
            slak->m_codenum = 1;
            slak->m_codenum = 1;
          slak->m_opnum = strlen (slak->m_operands) / 2;
          slak->m_opnum = strlen (slak->m_operands) / 2;
 
 
          if (i + 1 != m68k_numopcodes
          if (i + 1 != m68k_numopcodes
              && !strcmp (ins->name, m68k_sorted_opcodes[i + 1]->name))
              && !strcmp (ins->name, m68k_sorted_opcodes[i + 1]->name))
            {
            {
              slak->m_next = obstack_alloc (&robyn, sizeof (struct m68k_incant));
              slak->m_next = obstack_alloc (&robyn, sizeof (struct m68k_incant));
              i++;
              i++;
            }
            }
          else
          else
            slak->m_next = 0;
            slak->m_next = 0;
          slak = slak->m_next;
          slak = slak->m_next;
        }
        }
      while (slak);
      while (slak);
 
 
      retval = hash_insert (op_hash, ins->name, (char *) hack);
      retval = hash_insert (op_hash, ins->name, (char *) hack);
      if (retval)
      if (retval)
        as_fatal (_("Internal Error:  Can't hash %s: %s"), ins->name, retval);
        as_fatal (_("Internal Error:  Can't hash %s: %s"), ins->name, retval);
    }
    }
 
 
  for (i = 0; i < m68k_numaliases; i++)
  for (i = 0; i < m68k_numaliases; i++)
    {
    {
      const char *name = m68k_opcode_aliases[i].primary;
      const char *name = m68k_opcode_aliases[i].primary;
      const char *alias = m68k_opcode_aliases[i].alias;
      const char *alias = m68k_opcode_aliases[i].alias;
      PTR val = hash_find (op_hash, name);
      PTR val = hash_find (op_hash, name);
 
 
      if (!val)
      if (!val)
        as_fatal (_("Internal Error: Can't find %s in hash table"), name);
        as_fatal (_("Internal Error: Can't find %s in hash table"), name);
      retval = hash_insert (op_hash, alias, val);
      retval = hash_insert (op_hash, alias, val);
      if (retval)
      if (retval)
        as_fatal (_("Internal Error: Can't hash %s: %s"), alias, retval);
        as_fatal (_("Internal Error: Can't hash %s: %s"), alias, retval);
    }
    }
 
 
  /* In MRI mode, all unsized branches are variable sized.  Normally,
  /* In MRI mode, all unsized branches are variable sized.  Normally,
     they are word sized.  */
     they are word sized.  */
  if (flag_mri)
  if (flag_mri)
    {
    {
      static struct m68k_opcode_alias mri_aliases[] =
      static struct m68k_opcode_alias mri_aliases[] =
        {
        {
          { "bhi",      "jhi", },
          { "bhi",      "jhi", },
          { "bls",      "jls", },
          { "bls",      "jls", },
          { "bcc",      "jcc", },
          { "bcc",      "jcc", },
          { "bcs",      "jcs", },
          { "bcs",      "jcs", },
          { "bne",      "jne", },
          { "bne",      "jne", },
          { "beq",      "jeq", },
          { "beq",      "jeq", },
          { "bvc",      "jvc", },
          { "bvc",      "jvc", },
          { "bvs",      "jvs", },
          { "bvs",      "jvs", },
          { "bpl",      "jpl", },
          { "bpl",      "jpl", },
          { "bmi",      "jmi", },
          { "bmi",      "jmi", },
          { "bge",      "jge", },
          { "bge",      "jge", },
          { "blt",      "jlt", },
          { "blt",      "jlt", },
          { "bgt",      "jgt", },
          { "bgt",      "jgt", },
          { "ble",      "jle", },
          { "ble",      "jle", },
          { "bra",      "jra", },
          { "bra",      "jra", },
          { "bsr",      "jbsr", },
          { "bsr",      "jbsr", },
        };
        };
 
 
      for (i = 0;
      for (i = 0;
           i < (int) (sizeof mri_aliases / sizeof mri_aliases[0]);
           i < (int) (sizeof mri_aliases / sizeof mri_aliases[0]);
           i++)
           i++)
        {
        {
          const char *name = mri_aliases[i].primary;
          const char *name = mri_aliases[i].primary;
          const char *alias = mri_aliases[i].alias;
          const char *alias = mri_aliases[i].alias;
          PTR val = hash_find (op_hash, name);
          PTR val = hash_find (op_hash, name);
 
 
          if (!val)
          if (!val)
            as_fatal (_("Internal Error: Can't find %s in hash table"), name);
            as_fatal (_("Internal Error: Can't find %s in hash table"), name);
          retval = hash_jam (op_hash, alias, val);
          retval = hash_jam (op_hash, alias, val);
          if (retval)
          if (retval)
            as_fatal (_("Internal Error: Can't hash %s: %s"), alias, retval);
            as_fatal (_("Internal Error: Can't hash %s: %s"), alias, retval);
        }
        }
    }
    }
 
 
  for (i = 0; i < (int) sizeof (notend_table); i++)
  for (i = 0; i < (int) sizeof (notend_table); i++)
    {
    {
      notend_table[i] = 0;
      notend_table[i] = 0;
      alt_notend_table[i] = 0;
      alt_notend_table[i] = 0;
    }
    }
 
 
  notend_table[','] = 1;
  notend_table[','] = 1;
  notend_table['{'] = 1;
  notend_table['{'] = 1;
  notend_table['}'] = 1;
  notend_table['}'] = 1;
  alt_notend_table['a'] = 1;
  alt_notend_table['a'] = 1;
  alt_notend_table['A'] = 1;
  alt_notend_table['A'] = 1;
  alt_notend_table['d'] = 1;
  alt_notend_table['d'] = 1;
  alt_notend_table['D'] = 1;
  alt_notend_table['D'] = 1;
  alt_notend_table['#'] = 1;
  alt_notend_table['#'] = 1;
  alt_notend_table['&'] = 1;
  alt_notend_table['&'] = 1;
  alt_notend_table['f'] = 1;
  alt_notend_table['f'] = 1;
  alt_notend_table['F'] = 1;
  alt_notend_table['F'] = 1;
#ifdef REGISTER_PREFIX
#ifdef REGISTER_PREFIX
  alt_notend_table[REGISTER_PREFIX] = 1;
  alt_notend_table[REGISTER_PREFIX] = 1;
#endif
#endif
 
 
  /* We need to put '(' in alt_notend_table to handle
  /* We need to put '(' in alt_notend_table to handle
       cas2 %d0:%d2,%d3:%d4,(%a0):(%a1)  */
       cas2 %d0:%d2,%d3:%d4,(%a0):(%a1)  */
  alt_notend_table['('] = 1;
  alt_notend_table['('] = 1;
 
 
  /* We need to put '@' in alt_notend_table to handle
  /* We need to put '@' in alt_notend_table to handle
       cas2 %d0:%d2,%d3:%d4,@(%d0):@(%d1)  */
       cas2 %d0:%d2,%d3:%d4,@(%d0):@(%d1)  */
  alt_notend_table['@'] = 1;
  alt_notend_table['@'] = 1;
 
 
  /* We need to put digits in alt_notend_table to handle
  /* We need to put digits in alt_notend_table to handle
       bfextu %d0{24:1},%d0  */
       bfextu %d0{24:1},%d0  */
  alt_notend_table['0'] = 1;
  alt_notend_table['0'] = 1;
  alt_notend_table['1'] = 1;
  alt_notend_table['1'] = 1;
  alt_notend_table['2'] = 1;
  alt_notend_table['2'] = 1;
  alt_notend_table['3'] = 1;
  alt_notend_table['3'] = 1;
  alt_notend_table['4'] = 1;
  alt_notend_table['4'] = 1;
  alt_notend_table['5'] = 1;
  alt_notend_table['5'] = 1;
  alt_notend_table['6'] = 1;
  alt_notend_table['6'] = 1;
  alt_notend_table['7'] = 1;
  alt_notend_table['7'] = 1;
  alt_notend_table['8'] = 1;
  alt_notend_table['8'] = 1;
  alt_notend_table['9'] = 1;
  alt_notend_table['9'] = 1;
 
 
#ifndef MIT_SYNTAX_ONLY
#ifndef MIT_SYNTAX_ONLY
  /* Insert pseudo ops, these have to go into the opcode table since
  /* Insert pseudo ops, these have to go into the opcode table since
     gas expects pseudo ops to start with a dot.  */
     gas expects pseudo ops to start with a dot.  */
  {
  {
    int n = 0;
    int n = 0;
 
 
    while (mote_pseudo_table[n].poc_name)
    while (mote_pseudo_table[n].poc_name)
      {
      {
        hack = obstack_alloc (&robyn, sizeof (struct m68k_incant));
        hack = obstack_alloc (&robyn, sizeof (struct m68k_incant));
        hash_insert (op_hash,
        hash_insert (op_hash,
                     mote_pseudo_table[n].poc_name, (char *) hack);
                     mote_pseudo_table[n].poc_name, (char *) hack);
        hack->m_operands = 0;
        hack->m_operands = 0;
        hack->m_opnum = n;
        hack->m_opnum = n;
        n++;
        n++;
      }
      }
  }
  }
#endif
#endif
 
 
  init_regtable ();
  init_regtable ();
 
 
#ifdef OBJ_ELF
#ifdef OBJ_ELF
  record_alignment (text_section, 2);
  record_alignment (text_section, 2);
  record_alignment (data_section, 2);
  record_alignment (data_section, 2);
  record_alignment (bss_section, 2);
  record_alignment (bss_section, 2);
#endif
#endif
}
}
 
 


/* This is called when a label is defined.  */
/* This is called when a label is defined.  */
 
 
void
void
m68k_frob_label (symbolS *sym)
m68k_frob_label (symbolS *sym)
{
{
  struct label_line *n;
  struct label_line *n;
 
 
  n = (struct label_line *) xmalloc (sizeof *n);
  n = (struct label_line *) xmalloc (sizeof *n);
  n->next = labels;
  n->next = labels;
  n->label = sym;
  n->label = sym;
  as_where (&n->file, &n->line);
  as_where (&n->file, &n->line);
  n->text = 0;
  n->text = 0;
  labels = n;
  labels = n;
  current_label = n;
  current_label = n;
 
 
#ifdef OBJ_ELF
#ifdef OBJ_ELF
  dwarf2_emit_label (sym);
  dwarf2_emit_label (sym);
#endif
#endif
}
}
 
 
/* This is called when a value that is not an instruction is emitted.  */
/* This is called when a value that is not an instruction is emitted.  */
 
 
void
void
m68k_flush_pending_output (void)
m68k_flush_pending_output (void)
{
{
  current_label = NULL;
  current_label = NULL;
}
}
 
 
/* This is called at the end of the assembly, when the final value of
/* This is called at the end of the assembly, when the final value of
   the label is known.  We warn if this is a text symbol aligned at an
   the label is known.  We warn if this is a text symbol aligned at an
   odd location.  */
   odd location.  */
 
 
void
void
m68k_frob_symbol (symbolS *sym)
m68k_frob_symbol (symbolS *sym)
{
{
  if (S_GET_SEGMENT (sym) == reg_section
  if (S_GET_SEGMENT (sym) == reg_section
      && (int) S_GET_VALUE (sym) < 0)
      && (int) S_GET_VALUE (sym) < 0)
    {
    {
      S_SET_SEGMENT (sym, absolute_section);
      S_SET_SEGMENT (sym, absolute_section);
      S_SET_VALUE (sym, ~(int)S_GET_VALUE (sym));
      S_SET_VALUE (sym, ~(int)S_GET_VALUE (sym));
    }
    }
  else if ((S_GET_VALUE (sym) & 1) != 0)
  else if ((S_GET_VALUE (sym) & 1) != 0)
    {
    {
      struct label_line *l;
      struct label_line *l;
 
 
      for (l = labels; l != NULL; l = l->next)
      for (l = labels; l != NULL; l = l->next)
        {
        {
          if (l->label == sym)
          if (l->label == sym)
            {
            {
              if (l->text)
              if (l->text)
                as_warn_where (l->file, l->line,
                as_warn_where (l->file, l->line,
                               _("text label `%s' aligned to odd boundary"),
                               _("text label `%s' aligned to odd boundary"),
                               S_GET_NAME (sym));
                               S_GET_NAME (sym));
              break;
              break;
            }
            }
        }
        }
    }
    }
}
}


/* This is called if we go in or out of MRI mode because of the .mri
/* This is called if we go in or out of MRI mode because of the .mri
   pseudo-op.  */
   pseudo-op.  */
 
 
void
void
m68k_mri_mode_change (int on)
m68k_mri_mode_change (int on)
{
{
  if (on)
  if (on)
    {
    {
      if (! flag_reg_prefix_optional)
      if (! flag_reg_prefix_optional)
        {
        {
          flag_reg_prefix_optional = 1;
          flag_reg_prefix_optional = 1;
#ifdef REGISTER_PREFIX
#ifdef REGISTER_PREFIX
          init_regtable ();
          init_regtable ();
#endif
#endif
        }
        }
      m68k_abspcadd = 1;
      m68k_abspcadd = 1;
      if (! m68k_rel32_from_cmdline)
      if (! m68k_rel32_from_cmdline)
        m68k_rel32 = 0;
        m68k_rel32 = 0;
    }
    }
  else
  else
    {
    {
      if (! reg_prefix_optional_seen)
      if (! reg_prefix_optional_seen)
        {
        {
#ifdef REGISTER_PREFIX_OPTIONAL
#ifdef REGISTER_PREFIX_OPTIONAL
          flag_reg_prefix_optional = REGISTER_PREFIX_OPTIONAL;
          flag_reg_prefix_optional = REGISTER_PREFIX_OPTIONAL;
#else
#else
          flag_reg_prefix_optional = 0;
          flag_reg_prefix_optional = 0;
#endif
#endif
#ifdef REGISTER_PREFIX
#ifdef REGISTER_PREFIX
          init_regtable ();
          init_regtable ();
#endif
#endif
        }
        }
      m68k_abspcadd = 0;
      m68k_abspcadd = 0;
      if (! m68k_rel32_from_cmdline)
      if (! m68k_rel32_from_cmdline)
        m68k_rel32 = 1;
        m68k_rel32 = 1;
    }
    }
}
}
 
 
char *
char *
md_atof (int type, char *litP, int *sizeP)
md_atof (int type, char *litP, int *sizeP)
{
{
  return ieee_md_atof (type, litP, sizeP, TRUE);
  return ieee_md_atof (type, litP, sizeP, TRUE);
}
}
 
 
void
void
md_number_to_chars (char *buf, valueT val, int n)
md_number_to_chars (char *buf, valueT val, int n)
{
{
  number_to_chars_bigendian (buf, val, n);
  number_to_chars_bigendian (buf, val, n);
}
}
 
 
void
void
md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
{
{
  offsetT val = *valP;
  offsetT val = *valP;
  addressT upper_limit;
  addressT upper_limit;
  offsetT lower_limit;
  offsetT lower_limit;
 
 
  /* This is unnecessary but it convinces the native rs6000 compiler
  /* This is unnecessary but it convinces the native rs6000 compiler
     to generate the code we want.  */
     to generate the code we want.  */
  char *buf = fixP->fx_frag->fr_literal;
  char *buf = fixP->fx_frag->fr_literal;
  buf += fixP->fx_where;
  buf += fixP->fx_where;
  /* End ibm compiler workaround.  */
  /* End ibm compiler workaround.  */
 
 
  val = SEXT (val);
  val = SEXT (val);
 
 
  if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0)
  if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0)
    fixP->fx_done = 1;
    fixP->fx_done = 1;
 
 
#ifdef OBJ_ELF
#ifdef OBJ_ELF
  if (fixP->fx_addsy)
  if (fixP->fx_addsy)
    {
    {
      memset (buf, 0, fixP->fx_size);
      memset (buf, 0, fixP->fx_size);
      fixP->fx_addnumber = val; /* Remember value for emit_reloc.  */
      fixP->fx_addnumber = val; /* Remember value for emit_reloc.  */
 
 
      if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
      if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
          && !S_IS_DEFINED (fixP->fx_addsy)
          && !S_IS_DEFINED (fixP->fx_addsy)
          && !S_IS_WEAK (fixP->fx_addsy))
          && !S_IS_WEAK (fixP->fx_addsy))
        S_SET_WEAK (fixP->fx_addsy);
        S_SET_WEAK (fixP->fx_addsy);
      return;
      return;
    }
    }
#elif defined(OBJ_AOUT)
#elif defined(OBJ_AOUT)
  /* PR gas/3041 Do not fix frags referencing a weak symbol.  */
  /* PR gas/3041 Do not fix frags referencing a weak symbol.  */
  if (fixP->fx_addsy && S_IS_WEAK (fixP->fx_addsy))
  if (fixP->fx_addsy && S_IS_WEAK (fixP->fx_addsy))
    {
    {
      memset (buf, 0, fixP->fx_size);
      memset (buf, 0, fixP->fx_size);
      fixP->fx_addnumber = val; /* Remember value for emit_reloc.  */
      fixP->fx_addnumber = val; /* Remember value for emit_reloc.  */
      return;
      return;
    }
    }
#endif
#endif
 
 
  if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
  if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
      || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
      || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
    return;
    return;
 
 
  switch (fixP->fx_size)
  switch (fixP->fx_size)
    {
    {
      /* The cast to offsetT below are necessary to make code
      /* The cast to offsetT below are necessary to make code
         correct for machines where ints are smaller than offsetT.  */
         correct for machines where ints are smaller than offsetT.  */
    case 1:
    case 1:
      *buf++ = val;
      *buf++ = val;
      upper_limit = 0x7f;
      upper_limit = 0x7f;
      lower_limit = - (offsetT) 0x80;
      lower_limit = - (offsetT) 0x80;
      break;
      break;
    case 2:
    case 2:
      *buf++ = (val >> 8);
      *buf++ = (val >> 8);
      *buf++ = val;
      *buf++ = val;
      upper_limit = 0x7fff;
      upper_limit = 0x7fff;
      lower_limit = - (offsetT) 0x8000;
      lower_limit = - (offsetT) 0x8000;
      break;
      break;
    case 4:
    case 4:
      *buf++ = (val >> 24);
      *buf++ = (val >> 24);
      *buf++ = (val >> 16);
      *buf++ = (val >> 16);
      *buf++ = (val >> 8);
      *buf++ = (val >> 8);
      *buf++ = val;
      *buf++ = val;
      upper_limit = 0x7fffffff;
      upper_limit = 0x7fffffff;
      lower_limit = - (offsetT) 0x7fffffff - 1; /* Avoid constant overflow.  */
      lower_limit = - (offsetT) 0x7fffffff - 1; /* Avoid constant overflow.  */
      break;
      break;
    default:
    default:
      BAD_CASE (fixP->fx_size);
      BAD_CASE (fixP->fx_size);
    }
    }
 
 
  /* Fix up a negative reloc.  */
  /* Fix up a negative reloc.  */
  if (fixP->fx_addsy == NULL && fixP->fx_subsy != NULL)
  if (fixP->fx_addsy == NULL && fixP->fx_subsy != NULL)
    {
    {
      fixP->fx_addsy = fixP->fx_subsy;
      fixP->fx_addsy = fixP->fx_subsy;
      fixP->fx_subsy = NULL;
      fixP->fx_subsy = NULL;
      fixP->fx_tcbit = 1;
      fixP->fx_tcbit = 1;
    }
    }
 
 
  /* For non-pc-relative values, it's conceivable we might get something
  /* For non-pc-relative values, it's conceivable we might get something
     like "0xff" for a byte field.  So extend the upper part of the range
     like "0xff" for a byte field.  So extend the upper part of the range
     to accept such numbers.  We arbitrarily disallow "-0xff" or "0xff+0xff",
     to accept such numbers.  We arbitrarily disallow "-0xff" or "0xff+0xff",
     so that we can do any range checking at all.  */
     so that we can do any range checking at all.  */
  if (! fixP->fx_pcrel && ! fixP->fx_signed)
  if (! fixP->fx_pcrel && ! fixP->fx_signed)
    upper_limit = upper_limit * 2 + 1;
    upper_limit = upper_limit * 2 + 1;
 
 
  if ((addressT) val > upper_limit
  if ((addressT) val > upper_limit
      && (val > 0 || val < lower_limit))
      && (val > 0 || val < lower_limit))
    as_bad_where (fixP->fx_file, fixP->fx_line,
    as_bad_where (fixP->fx_file, fixP->fx_line,
                  _("value %ld out of range"), (long)val);
                  _("value %ld out of range"), (long)val);
 
 
  /* A one byte PC-relative reloc means a short branch.  We can't use
  /* A one byte PC-relative reloc means a short branch.  We can't use
     a short branch with a value of 0 or -1, because those indicate
     a short branch with a value of 0 or -1, because those indicate
     different opcodes (branches with longer offsets).  fixup_segment
     different opcodes (branches with longer offsets).  fixup_segment
     in write.c may have clobbered fx_pcrel, so we need to examine the
     in write.c may have clobbered fx_pcrel, so we need to examine the
     reloc type.  */
     reloc type.  */
  if ((fixP->fx_pcrel
  if ((fixP->fx_pcrel
       || fixP->fx_r_type == BFD_RELOC_8_PCREL)
       || fixP->fx_r_type == BFD_RELOC_8_PCREL)
      && fixP->fx_size == 1
      && fixP->fx_size == 1
      && (fixP->fx_addsy == NULL
      && (fixP->fx_addsy == NULL
          || S_IS_DEFINED (fixP->fx_addsy))
          || S_IS_DEFINED (fixP->fx_addsy))
      && (val == 0 || val == -1))
      && (val == 0 || val == -1))
    as_bad_where (fixP->fx_file, fixP->fx_line,
    as_bad_where (fixP->fx_file, fixP->fx_line,
                  _("invalid byte branch offset"));
                  _("invalid byte branch offset"));
}
}
 
 
/* *fragP has been relaxed to its final size, and now needs to have
/* *fragP has been relaxed to its final size, and now needs to have
   the bytes inside it modified to conform to the new size  There is UGLY
   the bytes inside it modified to conform to the new size  There is UGLY
   MAGIC here. ..
   MAGIC here. ..
   */
   */
static void
static void
md_convert_frag_1 (fragS *fragP)
md_convert_frag_1 (fragS *fragP)
{
{
  long disp;
  long disp;
  fixS *fixP = NULL;
  fixS *fixP = NULL;
 
 
  /* Address in object code of the displacement.  */
  /* Address in object code of the displacement.  */
  register int object_address = fragP->fr_fix + fragP->fr_address;
  register int object_address = fragP->fr_fix + fragP->fr_address;
 
 
  /* Address in gas core of the place to store the displacement.  */
  /* Address in gas core of the place to store the displacement.  */
  /* This convinces the native rs6000 compiler to generate the code we
  /* This convinces the native rs6000 compiler to generate the code we
     want.  */
     want.  */
  register char *buffer_address = fragP->fr_literal;
  register char *buffer_address = fragP->fr_literal;
  buffer_address += fragP->fr_fix;
  buffer_address += fragP->fr_fix;
  /* End ibm compiler workaround.  */
  /* End ibm compiler workaround.  */
 
 
  /* The displacement of the address, from current location.  */
  /* The displacement of the address, from current location.  */
  disp = fragP->fr_symbol ? S_GET_VALUE (fragP->fr_symbol) : 0;
  disp = fragP->fr_symbol ? S_GET_VALUE (fragP->fr_symbol) : 0;
  disp = (disp + fragP->fr_offset) - object_address;
  disp = (disp + fragP->fr_offset) - object_address;
 
 
  switch (fragP->fr_subtype)
  switch (fragP->fr_subtype)
    {
    {
    case TAB (BRANCHBWL, BYTE):
    case TAB (BRANCHBWL, BYTE):
    case TAB (BRABSJUNC, BYTE):
    case TAB (BRABSJUNC, BYTE):
    case TAB (BRABSJCOND, BYTE):
    case TAB (BRABSJCOND, BYTE):
    case TAB (BRANCHBW, BYTE):
    case TAB (BRANCHBW, BYTE):
    case TAB (BRANCHBWPL, BYTE):
    case TAB (BRANCHBWPL, BYTE):
      know (issbyte (disp));
      know (issbyte (disp));
      if (disp == 0)
      if (disp == 0)
        as_bad_where (fragP->fr_file, fragP->fr_line,
        as_bad_where (fragP->fr_file, fragP->fr_line,
                      _("short branch with zero offset: use :w"));
                      _("short branch with zero offset: use :w"));
      fixP = fix_new (fragP, fragP->fr_fix - 1, 1, fragP->fr_symbol,
      fixP = fix_new (fragP, fragP->fr_fix - 1, 1, fragP->fr_symbol,
                      fragP->fr_offset, 1, RELAX_RELOC_PC8);
                      fragP->fr_offset, 1, RELAX_RELOC_PC8);
      fixP->fx_pcrel_adjust = -1;
      fixP->fx_pcrel_adjust = -1;
      break;
      break;
    case TAB (BRANCHBWL, SHORT):
    case TAB (BRANCHBWL, SHORT):
    case TAB (BRABSJUNC, SHORT):
    case TAB (BRABSJUNC, SHORT):
    case TAB (BRABSJCOND, SHORT):
    case TAB (BRABSJCOND, SHORT):
    case TAB (BRANCHBW, SHORT):
    case TAB (BRANCHBW, SHORT):
    case TAB (BRANCHBWPL, SHORT):
    case TAB (BRANCHBWPL, SHORT):
      fragP->fr_opcode[1] = 0x00;
      fragP->fr_opcode[1] = 0x00;
      fixP = fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol,
      fixP = fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol,
                      fragP->fr_offset, 1, RELAX_RELOC_PC16);
                      fragP->fr_offset, 1, RELAX_RELOC_PC16);
      fragP->fr_fix += 2;
      fragP->fr_fix += 2;
      break;
      break;
    case TAB (BRANCHBWL, LONG):
    case TAB (BRANCHBWL, LONG):
      fragP->fr_opcode[1] = (char) 0xFF;
      fragP->fr_opcode[1] = (char) 0xFF;
      fixP = fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol,
      fixP = fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol,
                      fragP->fr_offset, 1, RELAX_RELOC_PC32);
                      fragP->fr_offset, 1, RELAX_RELOC_PC32);
      fragP->fr_fix += 4;
      fragP->fr_fix += 4;
      break;
      break;
    case TAB (BRANCHBWPL, LONG):
    case TAB (BRANCHBWPL, LONG):
      /* Here we are converting an unconditional branch into a pair of
      /* Here we are converting an unconditional branch into a pair of
         conditional branches, in order to get the range.  */
         conditional branches, in order to get the range.  */
      fragP->fr_opcode[0] = 0x66; /* bne */
      fragP->fr_opcode[0] = 0x66; /* bne */
      fragP->fr_opcode[1] = 0xFF;
      fragP->fr_opcode[1] = 0xFF;
      fixP = fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol,
      fixP = fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol,
                      fragP->fr_offset, 1, RELAX_RELOC_PC32);
                      fragP->fr_offset, 1, RELAX_RELOC_PC32);
      fixP->fx_file = fragP->fr_file;
      fixP->fx_file = fragP->fr_file;
      fixP->fx_line = fragP->fr_line;
      fixP->fx_line = fragP->fr_line;
      fragP->fr_fix += 4;  /* Skip first offset */
      fragP->fr_fix += 4;  /* Skip first offset */
      buffer_address += 4;
      buffer_address += 4;
      *buffer_address++ = 0x67; /* beq */
      *buffer_address++ = 0x67; /* beq */
      *buffer_address++ = 0xff;
      *buffer_address++ = 0xff;
      fragP->fr_fix += 2;  /* Skip second branch opcode */
      fragP->fr_fix += 2;  /* Skip second branch opcode */
      fixP = fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol,
      fixP = fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol,
                      fragP->fr_offset, 1, RELAX_RELOC_PC32);
                      fragP->fr_offset, 1, RELAX_RELOC_PC32);
      fragP->fr_fix += 4;
      fragP->fr_fix += 4;
      break;
      break;
    case TAB (BRABSJUNC, LONG):
    case TAB (BRABSJUNC, LONG):
      if (fragP->fr_opcode[0] == 0x61)           /* jbsr */
      if (fragP->fr_opcode[0] == 0x61)           /* jbsr */
        {
        {
          if (flag_keep_pcrel)
          if (flag_keep_pcrel)
            as_bad_where (fragP->fr_file, fragP->fr_line,
            as_bad_where (fragP->fr_file, fragP->fr_line,
                          _("Conversion of PC relative BSR to absolute JSR"));
                          _("Conversion of PC relative BSR to absolute JSR"));
          fragP->fr_opcode[0] = 0x4E;
          fragP->fr_opcode[0] = 0x4E;
          fragP->fr_opcode[1] = (char) 0xB9; /* JSR with ABSL LONG operand.  */
          fragP->fr_opcode[1] = (char) 0xB9; /* JSR with ABSL LONG operand.  */
          fixP = fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol,
          fixP = fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol,
                          fragP->fr_offset, 0, RELAX_RELOC_ABS32);
                          fragP->fr_offset, 0, RELAX_RELOC_ABS32);
          fragP->fr_fix += 4;
          fragP->fr_fix += 4;
        }
        }
      else if (fragP->fr_opcode[0] == 0x60)      /* jbra */
      else if (fragP->fr_opcode[0] == 0x60)      /* jbra */
        {
        {
          if (flag_keep_pcrel)
          if (flag_keep_pcrel)
            as_bad_where (fragP->fr_file, fragP->fr_line,
            as_bad_where (fragP->fr_file, fragP->fr_line,
                      _("Conversion of PC relative branch to absolute jump"));
                      _("Conversion of PC relative branch to absolute jump"));
          fragP->fr_opcode[0] = 0x4E;
          fragP->fr_opcode[0] = 0x4E;
          fragP->fr_opcode[1] = (char) 0xF9; /* JMP with ABSL LONG operand.  */
          fragP->fr_opcode[1] = (char) 0xF9; /* JMP with ABSL LONG operand.  */
          fixP = fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol,
          fixP = fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol,
                          fragP->fr_offset, 0, RELAX_RELOC_ABS32);
                          fragP->fr_offset, 0, RELAX_RELOC_ABS32);
          fragP->fr_fix += 4;
          fragP->fr_fix += 4;
        }
        }
      else
      else
        {
        {
          /* This cannot happen, because jbsr and jbra are the only two
          /* This cannot happen, because jbsr and jbra are the only two
             unconditional branches.  */
             unconditional branches.  */
          abort ();
          abort ();
        }
        }
      break;
      break;
    case TAB (BRABSJCOND, LONG):
    case TAB (BRABSJCOND, LONG):
      if (flag_keep_pcrel)
      if (flag_keep_pcrel)
        as_bad_where (fragP->fr_file, fragP->fr_line,
        as_bad_where (fragP->fr_file, fragP->fr_line,
                  _("Conversion of PC relative conditional branch to absolute jump"));
                  _("Conversion of PC relative conditional branch to absolute jump"));
 
 
      /* Only Bcc 68000 instructions can come here
      /* Only Bcc 68000 instructions can come here
         Change bcc into b!cc/jmp absl long.  */
         Change bcc into b!cc/jmp absl long.  */
      fragP->fr_opcode[0] ^= 0x01;       /* Invert bcc.  */
      fragP->fr_opcode[0] ^= 0x01;       /* Invert bcc.  */
      fragP->fr_opcode[1]  = 0x06;      /* Branch offset = 6.  */
      fragP->fr_opcode[1]  = 0x06;      /* Branch offset = 6.  */
 
 
      /* JF: these used to be fr_opcode[2,3], but they may be in a
      /* JF: these used to be fr_opcode[2,3], but they may be in a
           different frag, in which case referring to them is a no-no.
           different frag, in which case referring to them is a no-no.
           Only fr_opcode[0,1] are guaranteed to work.  */
           Only fr_opcode[0,1] are guaranteed to work.  */
      *buffer_address++ = 0x4e; /* put in jmp long (0x4ef9) */
      *buffer_address++ = 0x4e; /* put in jmp long (0x4ef9) */
      *buffer_address++ = (char) 0xf9;
      *buffer_address++ = (char) 0xf9;
      fragP->fr_fix += 2;       /* Account for jmp instruction.  */
      fragP->fr_fix += 2;       /* Account for jmp instruction.  */
      fixP = fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol,
      fixP = fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol,
                      fragP->fr_offset, 0, RELAX_RELOC_ABS32);
                      fragP->fr_offset, 0, RELAX_RELOC_ABS32);
      fragP->fr_fix += 4;
      fragP->fr_fix += 4;
      break;
      break;
    case TAB (FBRANCH, SHORT):
    case TAB (FBRANCH, SHORT):
      know ((fragP->fr_opcode[1] & 0x40) == 0);
      know ((fragP->fr_opcode[1] & 0x40) == 0);
      fixP = fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol,
      fixP = fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol,
                      fragP->fr_offset, 1, RELAX_RELOC_PC16);
                      fragP->fr_offset, 1, RELAX_RELOC_PC16);
      fragP->fr_fix += 2;
      fragP->fr_fix += 2;
      break;
      break;
    case TAB (FBRANCH, LONG):
    case TAB (FBRANCH, LONG):
      fragP->fr_opcode[1] |= 0x40;      /* Turn on LONG bit.  */
      fragP->fr_opcode[1] |= 0x40;      /* Turn on LONG bit.  */
      fixP = fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol,
      fixP = fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol,
                      fragP->fr_offset, 1, RELAX_RELOC_PC32);
                      fragP->fr_offset, 1, RELAX_RELOC_PC32);
      fragP->fr_fix += 4;
      fragP->fr_fix += 4;
      break;
      break;
    case TAB (DBCCLBR, SHORT):
    case TAB (DBCCLBR, SHORT):
    case TAB (DBCCABSJ, SHORT):
    case TAB (DBCCABSJ, SHORT):
      fixP = fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol,
      fixP = fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol,
                      fragP->fr_offset, 1, RELAX_RELOC_PC16);
                      fragP->fr_offset, 1, RELAX_RELOC_PC16);
      fragP->fr_fix += 2;
      fragP->fr_fix += 2;
      break;
      break;
    case TAB (DBCCLBR, LONG):
    case TAB (DBCCLBR, LONG):
      /* Only DBcc instructions can come here.
      /* Only DBcc instructions can come here.
         Change dbcc into dbcc/bral.
         Change dbcc into dbcc/bral.
         JF: these used to be fr_opcode[2-7], but that's wrong.  */
         JF: these used to be fr_opcode[2-7], but that's wrong.  */
      if (flag_keep_pcrel)
      if (flag_keep_pcrel)
        as_bad_where (fragP->fr_file, fragP->fr_line,
        as_bad_where (fragP->fr_file, fragP->fr_line,
                  _("Conversion of DBcc to absolute jump"));
                  _("Conversion of DBcc to absolute jump"));
 
 
      *buffer_address++ = 0x00; /* Branch offset = 4.  */
      *buffer_address++ = 0x00; /* Branch offset = 4.  */
      *buffer_address++ = 0x04;
      *buffer_address++ = 0x04;
      *buffer_address++ = 0x60; /* Put in bra pc+6.  */
      *buffer_address++ = 0x60; /* Put in bra pc+6.  */
      *buffer_address++ = 0x06;
      *buffer_address++ = 0x06;
      *buffer_address++ = 0x60;     /* Put in bral (0x60ff).  */
      *buffer_address++ = 0x60;     /* Put in bral (0x60ff).  */
      *buffer_address++ = (char) 0xff;
      *buffer_address++ = (char) 0xff;
 
 
      fragP->fr_fix += 6;       /* Account for bra/jmp instructions.  */
      fragP->fr_fix += 6;       /* Account for bra/jmp instructions.  */
      fixP = fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol,
      fixP = fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol,
                      fragP->fr_offset, 1, RELAX_RELOC_PC32);
                      fragP->fr_offset, 1, RELAX_RELOC_PC32);
      fragP->fr_fix += 4;
      fragP->fr_fix += 4;
      break;
      break;
    case TAB (DBCCABSJ, LONG):
    case TAB (DBCCABSJ, LONG):
      /* Only DBcc instructions can come here.
      /* Only DBcc instructions can come here.
         Change dbcc into dbcc/jmp.
         Change dbcc into dbcc/jmp.
         JF: these used to be fr_opcode[2-7], but that's wrong.  */
         JF: these used to be fr_opcode[2-7], but that's wrong.  */
      if (flag_keep_pcrel)
      if (flag_keep_pcrel)
        as_bad_where (fragP->fr_file, fragP->fr_line,
        as_bad_where (fragP->fr_file, fragP->fr_line,
                      _("Conversion of PC relative conditional branch to absolute jump"));
                      _("Conversion of PC relative conditional branch to absolute jump"));
 
 
      *buffer_address++ = 0x00;         /* Branch offset = 4.  */
      *buffer_address++ = 0x00;         /* Branch offset = 4.  */
      *buffer_address++ = 0x04;
      *buffer_address++ = 0x04;
      *buffer_address++ = 0x60;         /* Put in bra pc + 6.  */
      *buffer_address++ = 0x60;         /* Put in bra pc + 6.  */
      *buffer_address++ = 0x06;
      *buffer_address++ = 0x06;
      *buffer_address++ = 0x4e;         /* Put in jmp long (0x4ef9).  */
      *buffer_address++ = 0x4e;         /* Put in jmp long (0x4ef9).  */
      *buffer_address++ = (char) 0xf9;
      *buffer_address++ = (char) 0xf9;
 
 
      fragP->fr_fix += 6;               /* Account for bra/jmp instructions.  */
      fragP->fr_fix += 6;               /* Account for bra/jmp instructions.  */
      fixP = fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol,
      fixP = fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol,
                      fragP->fr_offset, 0, RELAX_RELOC_ABS32);
                      fragP->fr_offset, 0, RELAX_RELOC_ABS32);
      fragP->fr_fix += 4;
      fragP->fr_fix += 4;
      break;
      break;
    case TAB (PCREL1632, SHORT):
    case TAB (PCREL1632, SHORT):
      fragP->fr_opcode[1] &= ~0x3F;
      fragP->fr_opcode[1] &= ~0x3F;
      fragP->fr_opcode[1] |= 0x3A; /* 072 - mode 7.2 */
      fragP->fr_opcode[1] |= 0x3A; /* 072 - mode 7.2 */
      fixP = fix_new (fragP, (int) (fragP->fr_fix), 2, fragP->fr_symbol,
      fixP = fix_new (fragP, (int) (fragP->fr_fix), 2, fragP->fr_symbol,
                      fragP->fr_offset, 1, RELAX_RELOC_PC16);
                      fragP->fr_offset, 1, RELAX_RELOC_PC16);
      fragP->fr_fix += 2;
      fragP->fr_fix += 2;
      break;
      break;
    case TAB (PCREL1632, LONG):
    case TAB (PCREL1632, LONG):
      /* Already set to mode 7.3; this indicates: PC indirect with
      /* Already set to mode 7.3; this indicates: PC indirect with
         suppressed index, 32-bit displacement.  */
         suppressed index, 32-bit displacement.  */
      *buffer_address++ = 0x01;
      *buffer_address++ = 0x01;
      *buffer_address++ = 0x70;
      *buffer_address++ = 0x70;
      fragP->fr_fix += 2;
      fragP->fr_fix += 2;
      fixP = fix_new (fragP, (int) (fragP->fr_fix), 4, fragP->fr_symbol,
      fixP = fix_new (fragP, (int) (fragP->fr_fix), 4, fragP->fr_symbol,
                      fragP->fr_offset, 1, RELAX_RELOC_PC32);
                      fragP->fr_offset, 1, RELAX_RELOC_PC32);
      fixP->fx_pcrel_adjust = 2;
      fixP->fx_pcrel_adjust = 2;
      fragP->fr_fix += 4;
      fragP->fr_fix += 4;
      break;
      break;
    case TAB (PCINDEX, BYTE):
    case TAB (PCINDEX, BYTE):
      assert (fragP->fr_fix >= 2);
      assert (fragP->fr_fix >= 2);
      buffer_address[-2] &= ~1;
      buffer_address[-2] &= ~1;
      fixP = fix_new (fragP, fragP->fr_fix - 1, 1, fragP->fr_symbol,
      fixP = fix_new (fragP, fragP->fr_fix - 1, 1, fragP->fr_symbol,
                      fragP->fr_offset, 1, RELAX_RELOC_PC8);
                      fragP->fr_offset, 1, RELAX_RELOC_PC8);
      fixP->fx_pcrel_adjust = 1;
      fixP->fx_pcrel_adjust = 1;
      break;
      break;
    case TAB (PCINDEX, SHORT):
    case TAB (PCINDEX, SHORT):
      assert (fragP->fr_fix >= 2);
      assert (fragP->fr_fix >= 2);
      buffer_address[-2] |= 0x1;
      buffer_address[-2] |= 0x1;
      buffer_address[-1] = 0x20;
      buffer_address[-1] = 0x20;
      fixP = fix_new (fragP, (int) (fragP->fr_fix), 2, fragP->fr_symbol,
      fixP = fix_new (fragP, (int) (fragP->fr_fix), 2, fragP->fr_symbol,
                      fragP->fr_offset, 1, RELAX_RELOC_PC16);
                      fragP->fr_offset, 1, RELAX_RELOC_PC16);
      fixP->fx_pcrel_adjust = 2;
      fixP->fx_pcrel_adjust = 2;
      fragP->fr_fix += 2;
      fragP->fr_fix += 2;
      break;
      break;
    case TAB (PCINDEX, LONG):
    case TAB (PCINDEX, LONG):
      assert (fragP->fr_fix >= 2);
      assert (fragP->fr_fix >= 2);
      buffer_address[-2] |= 0x1;
      buffer_address[-2] |= 0x1;
      buffer_address[-1] = 0x30;
      buffer_address[-1] = 0x30;
      fixP = fix_new (fragP, (int) (fragP->fr_fix), 4, fragP->fr_symbol,
      fixP = fix_new (fragP, (int) (fragP->fr_fix), 4, fragP->fr_symbol,
                      fragP->fr_offset, 1, RELAX_RELOC_PC32);
                      fragP->fr_offset, 1, RELAX_RELOC_PC32);
      fixP->fx_pcrel_adjust = 2;
      fixP->fx_pcrel_adjust = 2;
      fragP->fr_fix += 4;
      fragP->fr_fix += 4;
      break;
      break;
    case TAB (ABSTOPCREL, SHORT):
    case TAB (ABSTOPCREL, SHORT):
      fixP = fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol,
      fixP = fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol,
                      fragP->fr_offset, 1, RELAX_RELOC_PC16);
                      fragP->fr_offset, 1, RELAX_RELOC_PC16);
      fragP->fr_fix += 2;
      fragP->fr_fix += 2;
      break;
      break;
    case TAB (ABSTOPCREL, LONG):
    case TAB (ABSTOPCREL, LONG):
      if (flag_keep_pcrel)
      if (flag_keep_pcrel)
        as_bad_where (fragP->fr_file, fragP->fr_line,
        as_bad_where (fragP->fr_file, fragP->fr_line,
                      _("Conversion of PC relative displacement to absolute"));
                      _("Conversion of PC relative displacement to absolute"));
      /* The thing to do here is force it to ABSOLUTE LONG, since
      /* The thing to do here is force it to ABSOLUTE LONG, since
         ABSTOPCREL is really trying to shorten an ABSOLUTE address anyway.  */
         ABSTOPCREL is really trying to shorten an ABSOLUTE address anyway.  */
      if ((fragP->fr_opcode[1] & 0x3F) != 0x3A)
      if ((fragP->fr_opcode[1] & 0x3F) != 0x3A)
        abort ();
        abort ();
      fragP->fr_opcode[1] &= ~0x3F;
      fragP->fr_opcode[1] &= ~0x3F;
      fragP->fr_opcode[1] |= 0x39;      /* Mode 7.1 */
      fragP->fr_opcode[1] |= 0x39;      /* Mode 7.1 */
      fixP = fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol,
      fixP = fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol,
                      fragP->fr_offset, 0, RELAX_RELOC_ABS32);
                      fragP->fr_offset, 0, RELAX_RELOC_ABS32);
      fragP->fr_fix += 4;
      fragP->fr_fix += 4;
      break;
      break;
    }
    }
  if (fixP)
  if (fixP)
    {
    {
      fixP->fx_file = fragP->fr_file;
      fixP->fx_file = fragP->fr_file;
      fixP->fx_line = fragP->fr_line;
      fixP->fx_line = fragP->fr_line;
    }
    }
}
}
 
 
void
void
md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED,
md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED,
                 segT sec ATTRIBUTE_UNUSED,
                 segT sec ATTRIBUTE_UNUSED,
                 fragS *fragP)
                 fragS *fragP)
{
{
  md_convert_frag_1 (fragP);
  md_convert_frag_1 (fragP);
}
}
 
 
/* Force truly undefined symbols to their maximum size, and generally set up
/* Force truly undefined symbols to their maximum size, and generally set up
   the frag list to be relaxed
   the frag list to be relaxed
   */
   */
int
int
md_estimate_size_before_relax (fragS *fragP, segT segment)
md_estimate_size_before_relax (fragS *fragP, segT segment)
{
{
  /* Handle SZ_UNDEF first, it can be changed to BYTE or SHORT.  */
  /* Handle SZ_UNDEF first, it can be changed to BYTE or SHORT.  */
  switch (fragP->fr_subtype)
  switch (fragP->fr_subtype)
    {
    {
    case TAB (BRANCHBWL, SZ_UNDEF):
    case TAB (BRANCHBWL, SZ_UNDEF):
    case TAB (BRANCHBWPL, SZ_UNDEF):
    case TAB (BRANCHBWPL, SZ_UNDEF):
    case TAB (BRABSJUNC, SZ_UNDEF):
    case TAB (BRABSJUNC, SZ_UNDEF):
    case TAB (BRABSJCOND, SZ_UNDEF):
    case TAB (BRABSJCOND, SZ_UNDEF):
      {
      {
        if (S_GET_SEGMENT (fragP->fr_symbol) == segment
        if (S_GET_SEGMENT (fragP->fr_symbol) == segment
            && relaxable_symbol (fragP->fr_symbol))
            && relaxable_symbol (fragP->fr_symbol))
          {
          {
            fragP->fr_subtype = TAB (TABTYPE (fragP->fr_subtype), BYTE);
            fragP->fr_subtype = TAB (TABTYPE (fragP->fr_subtype), BYTE);
          }
          }
        else if (flag_short_refs)
        else if (flag_short_refs)
          {
          {
            /* Symbol is undefined and we want short ref.  */
            /* Symbol is undefined and we want short ref.  */
            fragP->fr_subtype = TAB (TABTYPE (fragP->fr_subtype), SHORT);
            fragP->fr_subtype = TAB (TABTYPE (fragP->fr_subtype), SHORT);
          }
          }
        else
        else
          {
          {
            /* Symbol is still undefined.  Make it LONG.  */
            /* Symbol is still undefined.  Make it LONG.  */
            fragP->fr_subtype = TAB (TABTYPE (fragP->fr_subtype), LONG);
            fragP->fr_subtype = TAB (TABTYPE (fragP->fr_subtype), LONG);
          }
          }
        break;
        break;
      }
      }
 
 
    case TAB (BRANCHBW, SZ_UNDEF):
    case TAB (BRANCHBW, SZ_UNDEF):
      {
      {
        if (S_GET_SEGMENT (fragP->fr_symbol) == segment
        if (S_GET_SEGMENT (fragP->fr_symbol) == segment
            && relaxable_symbol (fragP->fr_symbol))
            && relaxable_symbol (fragP->fr_symbol))
          {
          {
            fragP->fr_subtype = TAB (TABTYPE (fragP->fr_subtype), BYTE);
            fragP->fr_subtype = TAB (TABTYPE (fragP->fr_subtype), BYTE);
          }
          }
        else
        else
          {
          {
            /* Symbol is undefined and we don't have long branches.  */
            /* Symbol is undefined and we don't have long branches.  */
            fragP->fr_subtype = TAB (TABTYPE (fragP->fr_subtype), SHORT);
            fragP->fr_subtype = TAB (TABTYPE (fragP->fr_subtype), SHORT);
          }
          }
        break;
        break;
      }
      }
 
 
    case TAB (FBRANCH, SZ_UNDEF):
    case TAB (FBRANCH, SZ_UNDEF):
    case TAB (DBCCLBR, SZ_UNDEF):
    case TAB (DBCCLBR, SZ_UNDEF):
    case TAB (DBCCABSJ, SZ_UNDEF):
    case TAB (DBCCABSJ, SZ_UNDEF):
    case TAB (PCREL1632, SZ_UNDEF):
    case TAB (PCREL1632, SZ_UNDEF):
      {
      {
        if ((S_GET_SEGMENT (fragP->fr_symbol) == segment
        if ((S_GET_SEGMENT (fragP->fr_symbol) == segment
             && relaxable_symbol (fragP->fr_symbol))
             && relaxable_symbol (fragP->fr_symbol))
            || flag_short_refs)
            || flag_short_refs)
          {
          {
            fragP->fr_subtype = TAB (TABTYPE (fragP->fr_subtype), SHORT);
            fragP->fr_subtype = TAB (TABTYPE (fragP->fr_subtype), SHORT);
          }
          }
        else
        else
          {
          {
            fragP->fr_subtype = TAB (TABTYPE (fragP->fr_subtype), LONG);
            fragP->fr_subtype = TAB (TABTYPE (fragP->fr_subtype), LONG);
          }
          }
        break;
        break;
      }
      }
 
 
    case TAB (PCINDEX, SZ_UNDEF):
    case TAB (PCINDEX, SZ_UNDEF):
      if ((S_GET_SEGMENT (fragP->fr_symbol) == segment
      if ((S_GET_SEGMENT (fragP->fr_symbol) == segment
           && relaxable_symbol (fragP->fr_symbol)))
           && relaxable_symbol (fragP->fr_symbol)))
        {
        {
          fragP->fr_subtype = TAB (PCINDEX, BYTE);
          fragP->fr_subtype = TAB (PCINDEX, BYTE);
        }
        }
      else
      else
        {
        {
          fragP->fr_subtype = TAB (PCINDEX, LONG);
          fragP->fr_subtype = TAB (PCINDEX, LONG);
        }
        }
      break;
      break;
 
 
    case TAB (ABSTOPCREL, SZ_UNDEF):
    case TAB (ABSTOPCREL, SZ_UNDEF):
      {
      {
        if ((S_GET_SEGMENT (fragP->fr_symbol) == segment
        if ((S_GET_SEGMENT (fragP->fr_symbol) == segment
             && relaxable_symbol (fragP->fr_symbol)))
             && relaxable_symbol (fragP->fr_symbol)))
          {
          {
            fragP->fr_subtype = TAB (ABSTOPCREL, SHORT);
            fragP->fr_subtype = TAB (ABSTOPCREL, SHORT);
          }
          }
        else
        else
          {
          {
            fragP->fr_subtype = TAB (ABSTOPCREL, LONG);
            fragP->fr_subtype = TAB (ABSTOPCREL, LONG);
          }
          }
        break;
        break;
      }
      }
 
 
    default:
    default:
      break;
      break;
    }
    }
 
 
  /* Now that SZ_UNDEF are taken care of, check others.  */
  /* Now that SZ_UNDEF are taken care of, check others.  */
  switch (fragP->fr_subtype)
  switch (fragP->fr_subtype)
    {
    {
    case TAB (BRANCHBWL, BYTE):
    case TAB (BRANCHBWL, BYTE):
    case TAB (BRABSJUNC, BYTE):
    case TAB (BRABSJUNC, BYTE):
    case TAB (BRABSJCOND, BYTE):
    case TAB (BRABSJCOND, BYTE):
    case TAB (BRANCHBW, BYTE):
    case TAB (BRANCHBW, BYTE):
      /* We can't do a short jump to the next instruction, so in that
      /* We can't do a short jump to the next instruction, so in that
         case we force word mode.  If the symbol is at the start of a
         case we force word mode.  If the symbol is at the start of a
         frag, and it is the next frag with any data in it (usually
         frag, and it is the next frag with any data in it (usually
         this is just the next frag, but assembler listings may
         this is just the next frag, but assembler listings may
         introduce empty frags), we must use word mode.  */
         introduce empty frags), we must use word mode.  */
      if (fragP->fr_symbol)
      if (fragP->fr_symbol)
        {
        {
          fragS *sym_frag;
          fragS *sym_frag;
 
 
          sym_frag = symbol_get_frag (fragP->fr_symbol);
          sym_frag = symbol_get_frag (fragP->fr_symbol);
          if (S_GET_VALUE (fragP->fr_symbol) == sym_frag->fr_address)
          if (S_GET_VALUE (fragP->fr_symbol) == sym_frag->fr_address)
            {
            {
              fragS *l;
              fragS *l;
 
 
              for (l = fragP->fr_next; l && l != sym_frag; l = l->fr_next)
              for (l = fragP->fr_next; l && l != sym_frag; l = l->fr_next)
                if (l->fr_fix != 0)
                if (l->fr_fix != 0)
                  break;
                  break;
              if (l == sym_frag)
              if (l == sym_frag)
                fragP->fr_subtype = TAB (TABTYPE (fragP->fr_subtype), SHORT);
                fragP->fr_subtype = TAB (TABTYPE (fragP->fr_subtype), SHORT);
            }
            }
        }
        }
      break;
      break;
    default:
    default:
      break;
      break;
    }
    }
  return md_relax_table[fragP->fr_subtype].rlx_length;
  return md_relax_table[fragP->fr_subtype].rlx_length;
}
}
 
 
#if defined(OBJ_AOUT) | defined(OBJ_BOUT)
#if defined(OBJ_AOUT) | defined(OBJ_BOUT)
/* the bit-field entries in the relocation_info struct plays hell
/* the bit-field entries in the relocation_info struct plays hell
   with the byte-order problems of cross-assembly.  So as a hack,
   with the byte-order problems of cross-assembly.  So as a hack,
   I added this mach. dependent ri twiddler.  Ugly, but it gets
   I added this mach. dependent ri twiddler.  Ugly, but it gets
   you there. -KWK  */
   you there. -KWK  */
/* on m68k: first 4 bytes are normal unsigned long, next three bytes
/* on m68k: first 4 bytes are normal unsigned long, next three bytes
   are symbolnum, most sig. byte first.  Last byte is broken up with
   are symbolnum, most sig. byte first.  Last byte is broken up with
   bit 7 as pcrel, bits 6 & 5 as length, bit 4 as pcrel, and the lower
   bit 7 as pcrel, bits 6 & 5 as length, bit 4 as pcrel, and the lower
   nibble as nuthin. (on Sun 3 at least) */
   nibble as nuthin. (on Sun 3 at least) */
/* Translate the internal relocation information into target-specific
/* Translate the internal relocation information into target-specific
   format.  */
   format.  */
#ifdef comment
#ifdef comment
void
void
md_ri_to_chars (char *the_bytes, struct reloc_info_generic *ri)
md_ri_to_chars (char *the_bytes, struct reloc_info_generic *ri)
{
{
  /* This is easy.  */
  /* This is easy.  */
  md_number_to_chars (the_bytes, ri->r_address, 4);
  md_number_to_chars (the_bytes, ri->r_address, 4);
  /* Now the fun stuff.  */
  /* Now the fun stuff.  */
  the_bytes[4] = (ri->r_symbolnum >> 16) & 0x0ff;
  the_bytes[4] = (ri->r_symbolnum >> 16) & 0x0ff;
  the_bytes[5] = (ri->r_symbolnum >>  8) & 0x0ff;
  the_bytes[5] = (ri->r_symbolnum >>  8) & 0x0ff;
  the_bytes[6] =  ri->r_symbolnum        & 0x0ff;
  the_bytes[6] =  ri->r_symbolnum        & 0x0ff;
  the_bytes[7] = (((ri->r_pcrel << 7) & 0x80)
  the_bytes[7] = (((ri->r_pcrel << 7) & 0x80)
                  | ((ri->r_length << 5) & 0x60)
                  | ((ri->r_length << 5) & 0x60)
                  | ((ri->r_extern << 4) & 0x10));
                  | ((ri->r_extern << 4) & 0x10));
}
}
 
 
#endif
#endif
 
 
#endif /* OBJ_AOUT or OBJ_BOUT */
#endif /* OBJ_AOUT or OBJ_BOUT */
 
 
#ifndef WORKING_DOT_WORD
#ifndef WORKING_DOT_WORD
int md_short_jump_size = 4;
int md_short_jump_size = 4;
int md_long_jump_size = 6;
int md_long_jump_size = 6;
 
 
void
void
md_create_short_jump (char *ptr, addressT from_addr, addressT to_addr,
md_create_short_jump (char *ptr, addressT from_addr, addressT to_addr,
                      fragS *frag ATTRIBUTE_UNUSED,
                      fragS *frag ATTRIBUTE_UNUSED,
                      symbolS *to_symbol ATTRIBUTE_UNUSED)
                      symbolS *to_symbol ATTRIBUTE_UNUSED)
{
{
  valueT offset;
  valueT offset;
 
 
  offset = to_addr - (from_addr + 2);
  offset = to_addr - (from_addr + 2);
 
 
  md_number_to_chars (ptr, (valueT) 0x6000, 2);
  md_number_to_chars (ptr, (valueT) 0x6000, 2);
  md_number_to_chars (ptr + 2, (valueT) offset, 2);
  md_number_to_chars (ptr + 2, (valueT) offset, 2);
}
}
 
 
void
void
md_create_long_jump (char *ptr, addressT from_addr, addressT to_addr,
md_create_long_jump (char *ptr, addressT from_addr, addressT to_addr,
                     fragS *frag, symbolS *to_symbol)
                     fragS *frag, symbolS *to_symbol)
{
{
  valueT offset;
  valueT offset;
 
 
  if (!HAVE_LONG_BRANCH (current_architecture))
  if (!HAVE_LONG_BRANCH (current_architecture))
    {
    {
      if (flag_keep_pcrel)
      if (flag_keep_pcrel)
        as_fatal (_("Tried to convert PC relative branch to absolute jump"));
        as_fatal (_("Tried to convert PC relative branch to absolute jump"));
      offset = to_addr - S_GET_VALUE (to_symbol);
      offset = to_addr - S_GET_VALUE (to_symbol);
      md_number_to_chars (ptr, (valueT) 0x4EF9, 2);
      md_number_to_chars (ptr, (valueT) 0x4EF9, 2);
      md_number_to_chars (ptr + 2, (valueT) offset, 4);
      md_number_to_chars (ptr + 2, (valueT) offset, 4);
      fix_new (frag, (ptr + 2) - frag->fr_literal, 4, to_symbol, (offsetT) 0,
      fix_new (frag, (ptr + 2) - frag->fr_literal, 4, to_symbol, (offsetT) 0,
               0, NO_RELOC);
               0, NO_RELOC);
    }
    }
  else
  else
    {
    {
      offset = to_addr - (from_addr + 2);
      offset = to_addr - (from_addr + 2);
      md_number_to_chars (ptr, (valueT) 0x60ff, 2);
      md_number_to_chars (ptr, (valueT) 0x60ff, 2);
      md_number_to_chars (ptr + 2, (valueT) offset, 4);
      md_number_to_chars (ptr + 2, (valueT) offset, 4);
    }
    }
}
}
 
 
#endif
#endif
 
 
/* Different values of OK tell what its OK to return.  Things that
/* Different values of OK tell what its OK to return.  Things that
   aren't OK are an error (what a shock, no?)
   aren't OK are an error (what a shock, no?)
 
 
   0:  Everything is OK
   0:  Everything is OK
   10:  Absolute 1:8       only
   10:  Absolute 1:8       only
   20:  Absolute 0:7       only
   20:  Absolute 0:7       only
   30:  absolute 0:15      only
   30:  absolute 0:15      only
   40:  Absolute 0:31      only
   40:  Absolute 0:31      only
   50:  absolute 0:127     only
   50:  absolute 0:127     only
   55:  absolute -64:63    only
   55:  absolute -64:63    only
   60:  absolute -128:127  only
   60:  absolute -128:127  only
   65:  absolute 0:511     only
   65:  absolute 0:511     only
   70:  absolute 0:4095    only
   70:  absolute 0:4095    only
   80:  absolute -1, 1:7   only
   80:  absolute -1, 1:7   only
   90:  No bignums.          */
   90:  No bignums.          */
 
 
static int
static int
get_num (struct m68k_exp *exp, int ok)
get_num (struct m68k_exp *exp, int ok)
{
{
  if (exp->exp.X_op == O_absent)
  if (exp->exp.X_op == O_absent)
    {
    {
      /* Do the same thing the VAX asm does.  */
      /* Do the same thing the VAX asm does.  */
      op (exp) = O_constant;
      op (exp) = O_constant;
      adds (exp) = 0;
      adds (exp) = 0;
      subs (exp) = 0;
      subs (exp) = 0;
      offs (exp) = 0;
      offs (exp) = 0;
      if (ok == 10)
      if (ok == 10)
        {
        {
          as_warn (_("expression out of range: defaulting to 1"));
          as_warn (_("expression out of range: defaulting to 1"));
          offs (exp) = 1;
          offs (exp) = 1;
        }
        }
    }
    }
  else if (exp->exp.X_op == O_constant)
  else if (exp->exp.X_op == O_constant)
    {
    {
      switch (ok)
      switch (ok)
        {
        {
        case 10:
        case 10:
          if ((valueT) TRUNC (offs (exp)) - 1 > 7)
          if ((valueT) TRUNC (offs (exp)) - 1 > 7)
            {
            {
              as_warn (_("expression out of range: defaulting to 1"));
              as_warn (_("expression out of range: defaulting to 1"));
              offs (exp) = 1;
              offs (exp) = 1;
            }
            }
          break;
          break;
        case 20:
        case 20:
          if ((valueT) TRUNC (offs (exp)) > 7)
          if ((valueT) TRUNC (offs (exp)) > 7)
            goto outrange;
            goto outrange;
          break;
          break;
        case 30:
        case 30:
          if ((valueT) TRUNC (offs (exp)) > 15)
          if ((valueT) TRUNC (offs (exp)) > 15)
            goto outrange;
            goto outrange;
          break;
          break;
        case 40:
        case 40:
          if ((valueT) TRUNC (offs (exp)) > 32)
          if ((valueT) TRUNC (offs (exp)) > 32)
            goto outrange;
            goto outrange;
          break;
          break;
        case 50:
        case 50:
          if ((valueT) TRUNC (offs (exp)) > 127)
          if ((valueT) TRUNC (offs (exp)) > 127)
            goto outrange;
            goto outrange;
          break;
          break;
        case 55:
        case 55:
          if ((valueT) SEXT (offs (exp)) + 64 > 127)
          if ((valueT) SEXT (offs (exp)) + 64 > 127)
            goto outrange;
            goto outrange;
          break;
          break;
        case 60:
        case 60:
          if ((valueT) SEXT (offs (exp)) + 128 > 255)
          if ((valueT) SEXT (offs (exp)) + 128 > 255)
            goto outrange;
            goto outrange;
          break;
          break;
        case 65:
        case 65:
          if ((valueT) TRUNC (offs (exp)) > 511)
          if ((valueT) TRUNC (offs (exp)) > 511)
            goto outrange;
            goto outrange;
          break;
          break;
        case 70:
        case 70:
          if ((valueT) TRUNC (offs (exp)) > 4095)
          if ((valueT) TRUNC (offs (exp)) > 4095)
            {
            {
            outrange:
            outrange:
              as_warn (_("expression out of range: defaulting to 0"));
              as_warn (_("expression out of range: defaulting to 0"));
              offs (exp) = 0;
              offs (exp) = 0;
            }
            }
          break;
          break;
        case 80:
        case 80:
          if ((valueT) TRUNC (offs (exp)) != 0xffffffff
          if ((valueT) TRUNC (offs (exp)) != 0xffffffff
              && (valueT) TRUNC (offs (exp)) - 1 > 6)
              && (valueT) TRUNC (offs (exp)) - 1 > 6)
            {
            {
              as_warn (_("expression out of range: defaulting to 1"));
              as_warn (_("expression out of range: defaulting to 1"));
              offs (exp) = 1;
              offs (exp) = 1;
            }
            }
          break;
          break;
        default:
        default:
          break;
          break;
        }
        }
    }
    }
  else if (exp->exp.X_op == O_big)
  else if (exp->exp.X_op == O_big)
    {
    {
      if (offs (exp) <= 0        /* flonum.  */
      if (offs (exp) <= 0        /* flonum.  */
          && (ok == 90          /* no bignums */
          && (ok == 90          /* no bignums */
              || (ok > 10       /* Small-int ranges including 0 ok.  */
              || (ok > 10       /* Small-int ranges including 0 ok.  */
                  /* If we have a flonum zero, a zero integer should
                  /* If we have a flonum zero, a zero integer should
                     do as well (e.g., in moveq).  */
                     do as well (e.g., in moveq).  */
                  && generic_floating_point_number.exponent == 0
                  && generic_floating_point_number.exponent == 0
                  && generic_floating_point_number.low[0] == 0)))
                  && generic_floating_point_number.low[0] == 0)))
        {
        {
          /* HACK! Turn it into a long.  */
          /* HACK! Turn it into a long.  */
          LITTLENUM_TYPE words[6];
          LITTLENUM_TYPE words[6];
 
 
          gen_to_words (words, 2, 8L);  /* These numbers are magic!  */
          gen_to_words (words, 2, 8L);  /* These numbers are magic!  */
          op (exp) = O_constant;
          op (exp) = O_constant;
          adds (exp) = 0;
          adds (exp) = 0;
          subs (exp) = 0;
          subs (exp) = 0;
          offs (exp) = words[1] | (words[0] << 16);
          offs (exp) = words[1] | (words[0] << 16);
        }
        }
      else if (ok != 0)
      else if (ok != 0)
        {
        {
          op (exp) = O_constant;
          op (exp) = O_constant;
          adds (exp) = 0;
          adds (exp) = 0;
          subs (exp) = 0;
          subs (exp) = 0;
          offs (exp) = (ok == 10) ? 1 : 0;
          offs (exp) = (ok == 10) ? 1 : 0;
          as_warn (_("Can't deal with expression; defaulting to %ld"),
          as_warn (_("Can't deal with expression; defaulting to %ld"),
                   (long) offs (exp));
                   (long) offs (exp));
        }
        }
    }
    }
  else
  else
    {
    {
      if (ok >= 10 && ok <= 80)
      if (ok >= 10 && ok <= 80)
        {
        {
          op (exp) = O_constant;
          op (exp) = O_constant;
          adds (exp) = 0;
          adds (exp) = 0;
          subs (exp) = 0;
          subs (exp) = 0;
          offs (exp) = (ok == 10) ? 1 : 0;
          offs (exp) = (ok == 10) ? 1 : 0;
          as_warn (_("Can't deal with expression; defaulting to %ld"),
          as_warn (_("Can't deal with expression; defaulting to %ld"),
                   (long) offs (exp));
                   (long) offs (exp));
        }
        }
    }
    }
 
 
  if (exp->size != SIZE_UNSPEC)
  if (exp->size != SIZE_UNSPEC)
    {
    {
      switch (exp->size)
      switch (exp->size)
        {
        {
        case SIZE_UNSPEC:
        case SIZE_UNSPEC:
        case SIZE_LONG:
        case SIZE_LONG:
          break;
          break;
        case SIZE_BYTE:
        case SIZE_BYTE:
          if (!isbyte (offs (exp)))
          if (!isbyte (offs (exp)))
            as_warn (_("expression doesn't fit in BYTE"));
            as_warn (_("expression doesn't fit in BYTE"));
          break;
          break;
        case SIZE_WORD:
        case SIZE_WORD:
          if (!isword (offs (exp)))
          if (!isword (offs (exp)))
            as_warn (_("expression doesn't fit in WORD"));
            as_warn (_("expression doesn't fit in WORD"));
          break;
          break;
        }
        }
    }
    }
 
 
  return offs (exp);
  return offs (exp);
}
}
 
 
/* These are the back-ends for the various machine dependent pseudo-ops.  */
/* These are the back-ends for the various machine dependent pseudo-ops.  */
 
 
static void
static void
s_data1 (int ignore ATTRIBUTE_UNUSED)
s_data1 (int ignore ATTRIBUTE_UNUSED)
{
{
  subseg_set (data_section, 1);
  subseg_set (data_section, 1);
  demand_empty_rest_of_line ();
  demand_empty_rest_of_line ();
}
}
 
 
static void
static void
s_data2 (int ignore ATTRIBUTE_UNUSED)
s_data2 (int ignore ATTRIBUTE_UNUSED)
{
{
  subseg_set (data_section, 2);
  subseg_set (data_section, 2);
  demand_empty_rest_of_line ();
  demand_empty_rest_of_line ();
}
}
 
 
static void
static void
s_bss (int ignore ATTRIBUTE_UNUSED)
s_bss (int ignore ATTRIBUTE_UNUSED)
{
{
  /* We don't support putting frags in the BSS segment, we fake it
  /* We don't support putting frags in the BSS segment, we fake it
     by marking in_bss, then looking at s_skip for clues.  */
     by marking in_bss, then looking at s_skip for clues.  */
 
 
  subseg_set (bss_section, 0);
  subseg_set (bss_section, 0);
  demand_empty_rest_of_line ();
  demand_empty_rest_of_line ();
}
}
 
 
static void
static void
s_even (int ignore ATTRIBUTE_UNUSED)
s_even (int ignore ATTRIBUTE_UNUSED)
{
{
  register int temp;
  register int temp;
  register long temp_fill;
  register long temp_fill;
 
 
  temp = 1;                     /* JF should be 2? */
  temp = 1;                     /* JF should be 2? */
  temp_fill = get_absolute_expression ();
  temp_fill = get_absolute_expression ();
  if (!need_pass_2)             /* Never make frag if expect extra pass.  */
  if (!need_pass_2)             /* Never make frag if expect extra pass.  */
    frag_align (temp, (int) temp_fill, 0);
    frag_align (temp, (int) temp_fill, 0);
  demand_empty_rest_of_line ();
  demand_empty_rest_of_line ();
  record_alignment (now_seg, temp);
  record_alignment (now_seg, temp);
}
}
 
 
static void
static void
s_proc (int ignore ATTRIBUTE_UNUSED)
s_proc (int ignore ATTRIBUTE_UNUSED)
{
{
  demand_empty_rest_of_line ();
  demand_empty_rest_of_line ();
}
}


/* Pseudo-ops handled for MRI compatibility.  */
/* Pseudo-ops handled for MRI compatibility.  */
 
 
/* This function returns non-zero if the argument is a conditional
/* This function returns non-zero if the argument is a conditional
   pseudo-op.  This is called when checking whether a pending
   pseudo-op.  This is called when checking whether a pending
   alignment is needed.  */
   alignment is needed.  */
 
 
int
int
m68k_conditional_pseudoop (pseudo_typeS *pop)
m68k_conditional_pseudoop (pseudo_typeS *pop)
{
{
  return (pop->poc_handler == s_mri_if
  return (pop->poc_handler == s_mri_if
          || pop->poc_handler == s_mri_else);
          || pop->poc_handler == s_mri_else);
}
}
 
 
/* Handle an MRI style chip specification.  */
/* Handle an MRI style chip specification.  */
 
 
static void
static void
mri_chip (void)
mri_chip (void)
{
{
  char *s;
  char *s;
  char c;
  char c;
  int i;
  int i;
 
 
  s = input_line_pointer;
  s = input_line_pointer;
  /* We can't use get_symbol_end since the processor names are not proper
  /* We can't use get_symbol_end since the processor names are not proper
     symbols.  */
     symbols.  */
  while (is_part_of_name (c = *input_line_pointer++))
  while (is_part_of_name (c = *input_line_pointer++))
    ;
    ;
  *--input_line_pointer = 0;
  *--input_line_pointer = 0;
  for (i = 0; m68k_cpus[i].name; i++)
  for (i = 0; m68k_cpus[i].name; i++)
    if (strcasecmp (s, m68k_cpus[i].name) == 0)
    if (strcasecmp (s, m68k_cpus[i].name) == 0)
      break;
      break;
  if (!m68k_cpus[i].name)
  if (!m68k_cpus[i].name)
    {
    {
      as_bad (_("%s: unrecognized processor name"), s);
      as_bad (_("%s: unrecognized processor name"), s);
      *input_line_pointer = c;
      *input_line_pointer = c;
      ignore_rest_of_line ();
      ignore_rest_of_line ();
      return;
      return;
    }
    }
  *input_line_pointer = c;
  *input_line_pointer = c;
 
 
  if (*input_line_pointer == '/')
  if (*input_line_pointer == '/')
    current_architecture = 0;
    current_architecture = 0;
  else
  else
    current_architecture &= m68881 | m68851;
    current_architecture &= m68881 | m68851;
  current_architecture |= m68k_cpus[i].arch & ~(m68881 | m68851);
  current_architecture |= m68k_cpus[i].arch & ~(m68881 | m68851);
  control_regs = m68k_cpus[i].control_regs;
  control_regs = m68k_cpus[i].control_regs;
 
 
  while (*input_line_pointer == '/')
  while (*input_line_pointer == '/')
    {
    {
      ++input_line_pointer;
      ++input_line_pointer;
      s = input_line_pointer;
      s = input_line_pointer;
      /* We can't use get_symbol_end since the processor names are not
      /* We can't use get_symbol_end since the processor names are not
         proper symbols.  */
         proper symbols.  */
      while (is_part_of_name (c = *input_line_pointer++))
      while (is_part_of_name (c = *input_line_pointer++))
        ;
        ;
      *--input_line_pointer = 0;
      *--input_line_pointer = 0;
      if (strcmp (s, "68881") == 0)
      if (strcmp (s, "68881") == 0)
        current_architecture |= m68881;
        current_architecture |= m68881;
      else if (strcmp (s, "68851") == 0)
      else if (strcmp (s, "68851") == 0)
        current_architecture |= m68851;
        current_architecture |= m68851;
      *input_line_pointer = c;
      *input_line_pointer = c;
    }
    }
}
}
 
 
/* The MRI CHIP pseudo-op.  */
/* The MRI CHIP pseudo-op.  */
 
 
static void
static void
s_chip (int ignore ATTRIBUTE_UNUSED)
s_chip (int ignore ATTRIBUTE_UNUSED)
{
{
  char *stop = NULL;
  char *stop = NULL;
  char stopc;
  char stopc;
 
 
  if (flag_mri)
  if (flag_mri)
    stop = mri_comment_field (&stopc);
    stop = mri_comment_field (&stopc);
  mri_chip ();
  mri_chip ();
  if (flag_mri)
  if (flag_mri)
    mri_comment_end (stop, stopc);
    mri_comment_end (stop, stopc);
  demand_empty_rest_of_line ();
  demand_empty_rest_of_line ();
}
}
 
 
/* The MRI FOPT pseudo-op.  */
/* The MRI FOPT pseudo-op.  */
 
 
static void
static void
s_fopt (int ignore ATTRIBUTE_UNUSED)
s_fopt (int ignore ATTRIBUTE_UNUSED)
{
{
  SKIP_WHITESPACE ();
  SKIP_WHITESPACE ();
 
 
  if (strncasecmp (input_line_pointer, "ID=", 3) == 0)
  if (strncasecmp (input_line_pointer, "ID=", 3) == 0)
    {
    {
      int temp;
      int temp;
 
 
      input_line_pointer += 3;
      input_line_pointer += 3;
      temp = get_absolute_expression ();
      temp = get_absolute_expression ();
      if (temp < 0 || temp > 7)
      if (temp < 0 || temp > 7)
        as_bad (_("bad coprocessor id"));
        as_bad (_("bad coprocessor id"));
      else
      else
        m68k_float_copnum = COP0 + temp;
        m68k_float_copnum = COP0 + temp;
    }
    }
  else
  else
    {
    {
      as_bad (_("unrecognized fopt option"));
      as_bad (_("unrecognized fopt option"));
      ignore_rest_of_line ();
      ignore_rest_of_line ();
      return;
      return;
    }
    }
 
 
  demand_empty_rest_of_line ();
  demand_empty_rest_of_line ();
}
}
 
 
/* The structure used to handle the MRI OPT pseudo-op.  */
/* The structure used to handle the MRI OPT pseudo-op.  */
 
 
struct opt_action
struct opt_action
{
{
  /* The name of the option.  */
  /* The name of the option.  */
  const char *name;
  const char *name;
 
 
  /* If this is not NULL, just call this function.  The first argument
  /* If this is not NULL, just call this function.  The first argument
     is the ARG field of this structure, the second argument is
     is the ARG field of this structure, the second argument is
     whether the option was negated.  */
     whether the option was negated.  */
  void (*pfn) (int arg, int on);
  void (*pfn) (int arg, int on);
 
 
  /* If this is not NULL, and the PFN field is NULL, set the variable
  /* If this is not NULL, and the PFN field is NULL, set the variable
     this points to.  Set it to the ARG field if the option was not
     this points to.  Set it to the ARG field if the option was not
     negated, and the NOTARG field otherwise.  */
     negated, and the NOTARG field otherwise.  */
  int *pvar;
  int *pvar;
 
 
  /* The value to pass to PFN or to assign to *PVAR.  */
  /* The value to pass to PFN or to assign to *PVAR.  */
  int arg;
  int arg;
 
 
  /* The value to assign to *PVAR if the option is negated.  If PFN is
  /* The value to assign to *PVAR if the option is negated.  If PFN is
     NULL, and PVAR is not NULL, and ARG and NOTARG are the same, then
     NULL, and PVAR is not NULL, and ARG and NOTARG are the same, then
     the option may not be negated.  */
     the option may not be negated.  */
  int notarg;
  int notarg;
};
};
 
 
/* The table used to handle the MRI OPT pseudo-op.  */
/* The table used to handle the MRI OPT pseudo-op.  */
 
 
static void skip_to_comma (int, int);
static void skip_to_comma (int, int);
static void opt_nest (int, int);
static void opt_nest (int, int);
static void opt_chip (int, int);
static void opt_chip (int, int);
static void opt_list (int, int);
static void opt_list (int, int);
static void opt_list_symbols (int, int);
static void opt_list_symbols (int, int);
 
 
static const struct opt_action opt_table[] =
static const struct opt_action opt_table[] =
{
{
  { "abspcadd", 0, &m68k_abspcadd, 1, 0 },
  { "abspcadd", 0, &m68k_abspcadd, 1, 0 },
 
 
  /* We do relaxing, so there is little use for these options.  */
  /* We do relaxing, so there is little use for these options.  */
  { "b", 0, 0, 0, 0 },
  { "b", 0, 0, 0, 0 },
  { "brs", 0, 0, 0, 0 },
  { "brs", 0, 0, 0, 0 },
  { "brb", 0, 0, 0, 0 },
  { "brb", 0, 0, 0, 0 },
  { "brl", 0, 0, 0, 0 },
  { "brl", 0, 0, 0, 0 },
  { "brw", 0, 0, 0, 0 },
  { "brw", 0, 0, 0, 0 },
 
 
  { "c", 0, 0, 0, 0 },
  { "c", 0, 0, 0, 0 },
  { "cex", 0, 0, 0, 0 },
  { "cex", 0, 0, 0, 0 },
  { "case", 0, &symbols_case_sensitive, 1, 0 },
  { "case", 0, &symbols_case_sensitive, 1, 0 },
  { "cl", 0, 0, 0, 0 },
  { "cl", 0, 0, 0, 0 },
  { "cre", 0, 0, 0, 0 },
  { "cre", 0, 0, 0, 0 },
  { "d", 0, &flag_keep_locals, 1, 0 },
  { "d", 0, &flag_keep_locals, 1, 0 },
  { "e", 0, 0, 0, 0 },
  { "e", 0, 0, 0, 0 },
  { "f", 0, &flag_short_refs, 1, 0 },
  { "f", 0, &flag_short_refs, 1, 0 },
  { "frs", 0, &flag_short_refs, 1, 0 },
  { "frs", 0, &flag_short_refs, 1, 0 },
  { "frl", 0, &flag_short_refs, 0, 1 },
  { "frl", 0, &flag_short_refs, 0, 1 },
  { "g", 0, 0, 0, 0 },
  { "g", 0, 0, 0, 0 },
  { "i", 0, 0, 0, 0 },
  { "i", 0, 0, 0, 0 },
  { "m", 0, 0, 0, 0 },
  { "m", 0, 0, 0, 0 },
  { "mex", 0, 0, 0, 0 },
  { "mex", 0, 0, 0, 0 },
  { "mc", 0, 0, 0, 0 },
  { "mc", 0, 0, 0, 0 },
  { "md", 0, 0, 0, 0 },
  { "md", 0, 0, 0, 0 },
  { "nest", opt_nest, 0, 0, 0 },
  { "nest", opt_nest, 0, 0, 0 },
  { "next", skip_to_comma, 0, 0, 0 },
  { "next", skip_to_comma, 0, 0, 0 },
  { "o", 0, 0, 0, 0 },
  { "o", 0, 0, 0, 0 },
  { "old", 0, 0, 0, 0 },
  { "old", 0, 0, 0, 0 },
  { "op", skip_to_comma, 0, 0, 0 },
  { "op", skip_to_comma, 0, 0, 0 },
  { "pco", 0, 0, 0, 0 },
  { "pco", 0, 0, 0, 0 },
  { "p", opt_chip, 0, 0, 0 },
  { "p", opt_chip, 0, 0, 0 },
  { "pcr", 0, 0, 0, 0 },
  { "pcr", 0, 0, 0, 0 },
  { "pcs", 0, 0, 0, 0 },
  { "pcs", 0, 0, 0, 0 },
  { "r", 0, 0, 0, 0 },
  { "r", 0, 0, 0, 0 },
  { "quick", 0, &m68k_quick, 1, 0 },
  { "quick", 0, &m68k_quick, 1, 0 },
  { "rel32", 0, &m68k_rel32, 1, 0 },
  { "rel32", 0, &m68k_rel32, 1, 0 },
  { "s", opt_list, 0, 0, 0 },
  { "s", opt_list, 0, 0, 0 },
  { "t", opt_list_symbols, 0, 0, 0 },
  { "t", opt_list_symbols, 0, 0, 0 },
  { "w", 0, &flag_no_warnings, 0, 1 },
  { "w", 0, &flag_no_warnings, 0, 1 },
  { "x", 0, 0, 0, 0 }
  { "x", 0, 0, 0, 0 }
};
};
 
 
#define OPTCOUNT ((int) (sizeof opt_table / sizeof opt_table[0]))
#define OPTCOUNT ((int) (sizeof opt_table / sizeof opt_table[0]))
 
 
/* The MRI OPT pseudo-op.  */
/* The MRI OPT pseudo-op.  */
 
 
static void
static void
s_opt (int ignore ATTRIBUTE_UNUSED)
s_opt (int ignore ATTRIBUTE_UNUSED)
{
{
  do
  do
    {
    {
      int t;
      int t;
      char *s;
      char *s;
      char c;
      char c;
      int i;
      int i;
      const struct opt_action *o;
      const struct opt_action *o;
 
 
      SKIP_WHITESPACE ();
      SKIP_WHITESPACE ();
 
 
      t = 1;
      t = 1;
      if (*input_line_pointer == '-')
      if (*input_line_pointer == '-')
        {
        {
          ++input_line_pointer;
          ++input_line_pointer;
          t = 0;
          t = 0;
        }
        }
      else if (strncasecmp (input_line_pointer, "NO", 2) == 0)
      else if (strncasecmp (input_line_pointer, "NO", 2) == 0)
        {
        {
          input_line_pointer += 2;
          input_line_pointer += 2;
          t = 0;
          t = 0;
        }
        }
 
 
      s = input_line_pointer;
      s = input_line_pointer;
      c = get_symbol_end ();
      c = get_symbol_end ();
 
 
      for (i = 0, o = opt_table; i < OPTCOUNT; i++, o++)
      for (i = 0, o = opt_table; i < OPTCOUNT; i++, o++)
        {
        {
          if (strcasecmp (s, o->name) == 0)
          if (strcasecmp (s, o->name) == 0)
            {
            {
              if (o->pfn)
              if (o->pfn)
                {
                {
                  /* Restore input_line_pointer now in case the option
                  /* Restore input_line_pointer now in case the option
                     takes arguments.  */
                     takes arguments.  */
                  *input_line_pointer = c;
                  *input_line_pointer = c;
                  (*o->pfn) (o->arg, t);
                  (*o->pfn) (o->arg, t);
                }
                }
              else if (o->pvar != NULL)
              else if (o->pvar != NULL)
                {
                {
                  if (! t && o->arg == o->notarg)
                  if (! t && o->arg == o->notarg)
                    as_bad (_("option `%s' may not be negated"), s);
                    as_bad (_("option `%s' may not be negated"), s);
                  *input_line_pointer = c;
                  *input_line_pointer = c;
                  *o->pvar = t ? o->arg : o->notarg;
                  *o->pvar = t ? o->arg : o->notarg;
                }
                }
              else
              else
                *input_line_pointer = c;
                *input_line_pointer = c;
              break;
              break;
            }
            }
        }
        }
      if (i >= OPTCOUNT)
      if (i >= OPTCOUNT)
        {
        {
          as_bad (_("option `%s' not recognized"), s);
          as_bad (_("option `%s' not recognized"), s);
          *input_line_pointer = c;
          *input_line_pointer = c;
        }
        }
    }
    }
  while (*input_line_pointer++ == ',');
  while (*input_line_pointer++ == ',');
 
 
  /* Move back to terminating character.  */
  /* Move back to terminating character.  */
  --input_line_pointer;
  --input_line_pointer;
  demand_empty_rest_of_line ();
  demand_empty_rest_of_line ();
}
}
 
 
/* Skip ahead to a comma.  This is used for OPT options which we do
/* Skip ahead to a comma.  This is used for OPT options which we do
   not support and which take arguments.  */
   not support and which take arguments.  */
 
 
static void
static void
skip_to_comma (int arg ATTRIBUTE_UNUSED, int on ATTRIBUTE_UNUSED)
skip_to_comma (int arg ATTRIBUTE_UNUSED, int on ATTRIBUTE_UNUSED)
{
{
  while (*input_line_pointer != ','
  while (*input_line_pointer != ','
         && ! is_end_of_line[(unsigned char) *input_line_pointer])
         && ! is_end_of_line[(unsigned char) *input_line_pointer])
    ++input_line_pointer;
    ++input_line_pointer;
}
}
 
 
/* Handle the OPT NEST=depth option.  */
/* Handle the OPT NEST=depth option.  */
 
 
static void
static void
opt_nest (int arg ATTRIBUTE_UNUSED, int on ATTRIBUTE_UNUSED)
opt_nest (int arg ATTRIBUTE_UNUSED, int on ATTRIBUTE_UNUSED)
{
{
  if (*input_line_pointer != '=')
  if (*input_line_pointer != '=')
    {
    {
      as_bad (_("bad format of OPT NEST=depth"));
      as_bad (_("bad format of OPT NEST=depth"));
      return;
      return;
    }
    }
 
 
  ++input_line_pointer;
  ++input_line_pointer;
  max_macro_nest = get_absolute_expression ();
  max_macro_nest = get_absolute_expression ();
}
}
 
 
/* Handle the OPT P=chip option.  */
/* Handle the OPT P=chip option.  */
 
 
static void
static void
opt_chip (int arg ATTRIBUTE_UNUSED, int on ATTRIBUTE_UNUSED)
opt_chip (int arg ATTRIBUTE_UNUSED, int on ATTRIBUTE_UNUSED)
{
{
  if (*input_line_pointer != '=')
  if (*input_line_pointer != '=')
    {
    {
      /* This is just OPT P, which we do not support.  */
      /* This is just OPT P, which we do not support.  */
      return;
      return;
    }
    }
 
 
  ++input_line_pointer;
  ++input_line_pointer;
  mri_chip ();
  mri_chip ();
}
}
 
 
/* Handle the OPT S option.  */
/* Handle the OPT S option.  */
 
 
static void
static void
opt_list (int arg ATTRIBUTE_UNUSED, int on)
opt_list (int arg ATTRIBUTE_UNUSED, int on)
{
{
  listing_list (on);
  listing_list (on);
}
}
 
 
/* Handle the OPT T option.  */
/* Handle the OPT T option.  */
 
 
static void
static void
opt_list_symbols (int arg ATTRIBUTE_UNUSED, int on)
opt_list_symbols (int arg ATTRIBUTE_UNUSED, int on)
{
{
  if (on)
  if (on)
    listing |= LISTING_SYMBOLS;
    listing |= LISTING_SYMBOLS;
  else
  else
    listing &= ~LISTING_SYMBOLS;
    listing &= ~LISTING_SYMBOLS;
}
}
 
 
/* Handle the MRI REG pseudo-op.  */
/* Handle the MRI REG pseudo-op.  */
 
 
static void
static void
s_reg (int ignore ATTRIBUTE_UNUSED)
s_reg (int ignore ATTRIBUTE_UNUSED)
{
{
  char *s;
  char *s;
  int c;
  int c;
  struct m68k_op rop;
  struct m68k_op rop;
  int mask;
  int mask;
  char *stop = NULL;
  char *stop = NULL;
  char stopc;
  char stopc;
 
 
  if (line_label == NULL)
  if (line_label == NULL)
    {
    {
      as_bad (_("missing label"));
      as_bad (_("missing label"));
      ignore_rest_of_line ();
      ignore_rest_of_line ();
      return;
      return;
    }
    }
 
 
  if (flag_mri)
  if (flag_mri)
    stop = mri_comment_field (&stopc);
    stop = mri_comment_field (&stopc);
 
 
  SKIP_WHITESPACE ();
  SKIP_WHITESPACE ();
 
 
  s = input_line_pointer;
  s = input_line_pointer;
  while (ISALNUM (*input_line_pointer)
  while (ISALNUM (*input_line_pointer)
#ifdef REGISTER_PREFIX
#ifdef REGISTER_PREFIX
         || *input_line_pointer == REGISTER_PREFIX
         || *input_line_pointer == REGISTER_PREFIX
#endif
#endif
         || *input_line_pointer == '/'
         || *input_line_pointer == '/'
         || *input_line_pointer == '-')
         || *input_line_pointer == '-')
    ++input_line_pointer;
    ++input_line_pointer;
  c = *input_line_pointer;
  c = *input_line_pointer;
  *input_line_pointer = '\0';
  *input_line_pointer = '\0';
 
 
  if (m68k_ip_op (s, &rop) != 0)
  if (m68k_ip_op (s, &rop) != 0)
    {
    {
      if (rop.error == NULL)
      if (rop.error == NULL)
        as_bad (_("bad register list"));
        as_bad (_("bad register list"));
      else
      else
        as_bad (_("bad register list: %s"), rop.error);
        as_bad (_("bad register list: %s"), rop.error);
      *input_line_pointer = c;
      *input_line_pointer = c;
      ignore_rest_of_line ();
      ignore_rest_of_line ();
      return;
      return;
    }
    }
 
 
  *input_line_pointer = c;
  *input_line_pointer = c;
 
 
  if (rop.mode == REGLST)
  if (rop.mode == REGLST)
    mask = rop.mask;
    mask = rop.mask;
  else if (rop.mode == DREG)
  else if (rop.mode == DREG)
    mask = 1 << (rop.reg - DATA0);
    mask = 1 << (rop.reg - DATA0);
  else if (rop.mode == AREG)
  else if (rop.mode == AREG)
    mask = 1 << (rop.reg - ADDR0 + 8);
    mask = 1 << (rop.reg - ADDR0 + 8);
  else if (rop.mode == FPREG)
  else if (rop.mode == FPREG)
    mask = 1 << (rop.reg - FP0 + 16);
    mask = 1 << (rop.reg - FP0 + 16);
  else if (rop.mode == CONTROL
  else if (rop.mode == CONTROL
           && rop.reg == FPI)
           && rop.reg == FPI)
    mask = 1 << 24;
    mask = 1 << 24;
  else if (rop.mode == CONTROL
  else if (rop.mode == CONTROL
           && rop.reg == FPS)
           && rop.reg == FPS)
    mask = 1 << 25;
    mask = 1 << 25;
  else if (rop.mode == CONTROL
  else if (rop.mode == CONTROL
           && rop.reg == FPC)
           && rop.reg == FPC)
    mask = 1 << 26;
    mask = 1 << 26;
  else
  else
    {
    {
      as_bad (_("bad register list"));
      as_bad (_("bad register list"));
      ignore_rest_of_line ();
      ignore_rest_of_line ();
      return;
      return;
    }
    }
 
 
  S_SET_SEGMENT (line_label, reg_section);
  S_SET_SEGMENT (line_label, reg_section);
  S_SET_VALUE (line_label, ~mask);
  S_SET_VALUE (line_label, ~mask);
  symbol_set_frag (line_label, &zero_address_frag);
  symbol_set_frag (line_label, &zero_address_frag);
 
 
  if (flag_mri)
  if (flag_mri)
    mri_comment_end (stop, stopc);
    mri_comment_end (stop, stopc);
 
 
  demand_empty_rest_of_line ();
  demand_empty_rest_of_line ();
}
}
 
 
/* This structure is used for the MRI SAVE and RESTORE pseudo-ops.  */
/* This structure is used for the MRI SAVE and RESTORE pseudo-ops.  */
 
 
struct save_opts
struct save_opts
{
{
  struct save_opts *next;
  struct save_opts *next;
  int abspcadd;
  int abspcadd;
  int symbols_case_sensitive;
  int symbols_case_sensitive;
  int keep_locals;
  int keep_locals;
  int short_refs;
  int short_refs;
  int architecture;
  int architecture;
  const enum m68k_register *control_regs;
  const enum m68k_register *control_regs;
  int quick;
  int quick;
  int rel32;
  int rel32;
  int listing;
  int listing;
  int no_warnings;
  int no_warnings;
  /* FIXME: We don't save OPT S.  */
  /* FIXME: We don't save OPT S.  */
};
};
 
 
/* This variable holds the stack of saved options.  */
/* This variable holds the stack of saved options.  */
 
 
static struct save_opts *save_stack;
static struct save_opts *save_stack;
 
 
/* The MRI SAVE pseudo-op.  */
/* The MRI SAVE pseudo-op.  */
 
 
static void
static void
s_save (int ignore ATTRIBUTE_UNUSED)
s_save (int ignore ATTRIBUTE_UNUSED)
{
{
  struct save_opts *s;
  struct save_opts *s;
 
 
  s = (struct save_opts *) xmalloc (sizeof (struct save_opts));
  s = (struct save_opts *) xmalloc (sizeof (struct save_opts));
  s->abspcadd = m68k_abspcadd;
  s->abspcadd = m68k_abspcadd;
  s->symbols_case_sensitive = symbols_case_sensitive;
  s->symbols_case_sensitive = symbols_case_sensitive;
  s->keep_locals = flag_keep_locals;
  s->keep_locals = flag_keep_locals;
  s->short_refs = flag_short_refs;
  s->short_refs = flag_short_refs;
  s->architecture = current_architecture;
  s->architecture = current_architecture;
  s->control_regs = control_regs;
  s->control_regs = control_regs;
  s->quick = m68k_quick;
  s->quick = m68k_quick;
  s->rel32 = m68k_rel32;
  s->rel32 = m68k_rel32;
  s->listing = listing;
  s->listing = listing;
  s->no_warnings = flag_no_warnings;
  s->no_warnings = flag_no_warnings;
 
 
  s->next = save_stack;
  s->next = save_stack;
  save_stack = s;
  save_stack = s;
 
 
  demand_empty_rest_of_line ();
  demand_empty_rest_of_line ();
}
}
 
 
/* The MRI RESTORE pseudo-op.  */
/* The MRI RESTORE pseudo-op.  */
 
 
static void
static void
s_restore (int ignore ATTRIBUTE_UNUSED)
s_restore (int ignore ATTRIBUTE_UNUSED)
{
{
  struct save_opts *s;
  struct save_opts *s;
 
 
  if (save_stack == NULL)
  if (save_stack == NULL)
    {
    {
      as_bad (_("restore without save"));
      as_bad (_("restore without save"));
      ignore_rest_of_line ();
      ignore_rest_of_line ();
      return;
      return;
    }
    }
 
 
  s = save_stack;
  s = save_stack;
  save_stack = s->next;
  save_stack = s->next;
 
 
  m68k_abspcadd = s->abspcadd;
  m68k_abspcadd = s->abspcadd;
  symbols_case_sensitive = s->symbols_case_sensitive;
  symbols_case_sensitive = s->symbols_case_sensitive;
  flag_keep_locals = s->keep_locals;
  flag_keep_locals = s->keep_locals;
  flag_short_refs = s->short_refs;
  flag_short_refs = s->short_refs;
  current_architecture = s->architecture;
  current_architecture = s->architecture;
  control_regs = s->control_regs;
  control_regs = s->control_regs;
  m68k_quick = s->quick;
  m68k_quick = s->quick;
  m68k_rel32 = s->rel32;
  m68k_rel32 = s->rel32;
  listing = s->listing;
  listing = s->listing;
  flag_no_warnings = s->no_warnings;
  flag_no_warnings = s->no_warnings;
 
 
  free (s);
  free (s);
 
 
  demand_empty_rest_of_line ();
  demand_empty_rest_of_line ();
}
}
 
 
/* Types of MRI structured control directives.  */
/* Types of MRI structured control directives.  */
 
 
enum mri_control_type
enum mri_control_type
{
{
  mri_for,
  mri_for,
  mri_if,
  mri_if,
  mri_repeat,
  mri_repeat,
  mri_while
  mri_while
};
};
 
 
/* This structure is used to stack the MRI structured control
/* This structure is used to stack the MRI structured control
   directives.  */
   directives.  */
 
 
struct mri_control_info
struct mri_control_info
{
{
  /* The directive within which this one is enclosed.  */
  /* The directive within which this one is enclosed.  */
  struct mri_control_info *outer;
  struct mri_control_info *outer;
 
 
  /* The type of directive.  */
  /* The type of directive.  */
  enum mri_control_type type;
  enum mri_control_type type;
 
 
  /* Whether an ELSE has been in an IF.  */
  /* Whether an ELSE has been in an IF.  */
  int else_seen;
  int else_seen;
 
 
  /* The add or sub statement at the end of a FOR.  */
  /* The add or sub statement at the end of a FOR.  */
  char *incr;
  char *incr;
 
 
  /* The label of the top of a FOR or REPEAT loop.  */
  /* The label of the top of a FOR or REPEAT loop.  */
  char *top;
  char *top;
 
 
  /* The label to jump to for the next iteration, or the else
  /* The label to jump to for the next iteration, or the else
     expression of a conditional.  */
     expression of a conditional.  */
  char *next;
  char *next;
 
 
  /* The label to jump to to break out of the loop, or the label past
  /* The label to jump to to break out of the loop, or the label past
     the end of a conditional.  */
     the end of a conditional.  */
  char *bottom;
  char *bottom;
};
};
 
 
/* The stack of MRI structured control directives.  */
/* The stack of MRI structured control directives.  */
 
 
static struct mri_control_info *mri_control_stack;
static struct mri_control_info *mri_control_stack;
 
 
/* The current MRI structured control directive index number, used to
/* The current MRI structured control directive index number, used to
   generate label names.  */
   generate label names.  */
 
 
static int mri_control_index;
static int mri_control_index;
 
 
/* Assemble an instruction for an MRI structured control directive.  */
/* Assemble an instruction for an MRI structured control directive.  */
 
 
static void
static void
mri_assemble (char *str)
mri_assemble (char *str)
{
{
  char *s;
  char *s;
 
 
  /* md_assemble expects the opcode to be in lower case.  */
  /* md_assemble expects the opcode to be in lower case.  */
  for (s = str; *s != ' ' && *s != '\0'; s++)
  for (s = str; *s != ' ' && *s != '\0'; s++)
    *s = TOLOWER (*s);
    *s = TOLOWER (*s);
 
 
  md_assemble (str);
  md_assemble (str);
}
}
 
 
/* Generate a new MRI label structured control directive label name.  */
/* Generate a new MRI label structured control directive label name.  */
 
 
static char *
static char *
mri_control_label (void)
mri_control_label (void)
{
{
  char *n;
  char *n;
 
 
  n = (char *) xmalloc (20);
  n = (char *) xmalloc (20);
  sprintf (n, "%smc%d", FAKE_LABEL_NAME, mri_control_index);
  sprintf (n, "%smc%d", FAKE_LABEL_NAME, mri_control_index);
  ++mri_control_index;
  ++mri_control_index;
  return n;
  return n;
}
}
 
 
/* Create a new MRI structured control directive.  */
/* Create a new MRI structured control directive.  */
 
 
static struct mri_control_info *
static struct mri_control_info *
push_mri_control (enum mri_control_type type)
push_mri_control (enum mri_control_type type)
{
{
  struct mri_control_info *n;
  struct mri_control_info *n;
 
 
  n = (struct mri_control_info *) xmalloc (sizeof (struct mri_control_info));
  n = (struct mri_control_info *) xmalloc (sizeof (struct mri_control_info));
 
 
  n->type = type;
  n->type = type;
  n->else_seen = 0;
  n->else_seen = 0;
  if (type == mri_if || type == mri_while)
  if (type == mri_if || type == mri_while)
    n->top = NULL;
    n->top = NULL;
  else
  else
    n->top = mri_control_label ();
    n->top = mri_control_label ();
  n->next = mri_control_label ();
  n->next = mri_control_label ();
  n->bottom = mri_control_label ();
  n->bottom = mri_control_label ();
 
 
  n->outer = mri_control_stack;
  n->outer = mri_control_stack;
  mri_control_stack = n;
  mri_control_stack = n;
 
 
  return n;
  return n;
}
}
 
 
/* Pop off the stack of MRI structured control directives.  */
/* Pop off the stack of MRI structured control directives.  */
 
 
static void
static void
pop_mri_control (void)
pop_mri_control (void)
{
{
  struct mri_control_info *n;
  struct mri_control_info *n;
 
 
  n = mri_control_stack;
  n = mri_control_stack;
  mri_control_stack = n->outer;
  mri_control_stack = n->outer;
  if (n->top != NULL)
  if (n->top != NULL)
    free (n->top);
    free (n->top);
  free (n->next);
  free (n->next);
  free (n->bottom);
  free (n->bottom);
  free (n);
  free (n);
}
}
 
 
/* Recognize a condition code in an MRI structured control expression.  */
/* Recognize a condition code in an MRI structured control expression.  */
 
 
static int
static int
parse_mri_condition (int *pcc)
parse_mri_condition (int *pcc)
{
{
  char c1, c2;
  char c1, c2;
 
 
  know (*input_line_pointer == '<');
  know (*input_line_pointer == '<');
 
 
  ++input_line_pointer;
  ++input_line_pointer;
  c1 = *input_line_pointer++;
  c1 = *input_line_pointer++;
  c2 = *input_line_pointer++;
  c2 = *input_line_pointer++;
 
 
  if (*input_line_pointer != '>')
  if (*input_line_pointer != '>')
    {
    {
      as_bad (_("syntax error in structured control directive"));
      as_bad (_("syntax error in structured control directive"));
      return 0;
      return 0;
    }
    }
 
 
  ++input_line_pointer;
  ++input_line_pointer;
  SKIP_WHITESPACE ();
  SKIP_WHITESPACE ();
 
 
  c1 = TOLOWER (c1);
  c1 = TOLOWER (c1);
  c2 = TOLOWER (c2);
  c2 = TOLOWER (c2);
 
 
  *pcc = (c1 << 8) | c2;
  *pcc = (c1 << 8) | c2;
 
 
  return 1;
  return 1;
}
}
 
 
/* Parse a single operand in an MRI structured control expression.  */
/* Parse a single operand in an MRI structured control expression.  */
 
 
static int
static int
parse_mri_control_operand (int *pcc, char **leftstart, char **leftstop,
parse_mri_control_operand (int *pcc, char **leftstart, char **leftstop,
                           char **rightstart, char **rightstop)
                           char **rightstart, char **rightstop)
{
{
  char *s;
  char *s;
 
 
  SKIP_WHITESPACE ();
  SKIP_WHITESPACE ();
 
 
  *pcc = -1;
  *pcc = -1;
  *leftstart = NULL;
  *leftstart = NULL;
  *leftstop = NULL;
  *leftstop = NULL;
  *rightstart = NULL;
  *rightstart = NULL;
  *rightstop = NULL;
  *rightstop = NULL;
 
 
  if (*input_line_pointer == '<')
  if (*input_line_pointer == '<')
    {
    {
      /* It's just a condition code.  */
      /* It's just a condition code.  */
      return parse_mri_condition (pcc);
      return parse_mri_condition (pcc);
    }
    }
 
 
  /* Look ahead for the condition code.  */
  /* Look ahead for the condition code.  */
  for (s = input_line_pointer; *s != '\0'; ++s)
  for (s = input_line_pointer; *s != '\0'; ++s)
    {
    {
      if (*s == '<' && s[1] != '\0' && s[2] != '\0' && s[3] == '>')
      if (*s == '<' && s[1] != '\0' && s[2] != '\0' && s[3] == '>')
        break;
        break;
    }
    }
  if (*s == '\0')
  if (*s == '\0')
    {
    {
      as_bad (_("missing condition code in structured control directive"));
      as_bad (_("missing condition code in structured control directive"));
      return 0;
      return 0;
    }
    }
 
 
  *leftstart = input_line_pointer;
  *leftstart = input_line_pointer;
  *leftstop = s;
  *leftstop = s;
  if (*leftstop > *leftstart
  if (*leftstop > *leftstart
      && ((*leftstop)[-1] == ' ' || (*leftstop)[-1] == '\t'))
      && ((*leftstop)[-1] == ' ' || (*leftstop)[-1] == '\t'))
    --*leftstop;
    --*leftstop;
 
 
  input_line_pointer = s;
  input_line_pointer = s;
  if (! parse_mri_condition (pcc))
  if (! parse_mri_condition (pcc))
    return 0;
    return 0;
 
 
  /* Look ahead for AND or OR or end of line.  */
  /* Look ahead for AND or OR or end of line.  */
  for (s = input_line_pointer; *s != '\0'; ++s)
  for (s = input_line_pointer; *s != '\0'; ++s)
    {
    {
      /* We must make sure we don't misinterpret AND/OR at the end of labels!
      /* We must make sure we don't misinterpret AND/OR at the end of labels!
         if d0 <eq> #FOOAND and d1 <ne> #BAROR then
         if d0 <eq> #FOOAND and d1 <ne> #BAROR then
                        ^^^                 ^^ */
                        ^^^                 ^^ */
      if ((s == input_line_pointer
      if ((s == input_line_pointer
           || *(s-1) == ' '
           || *(s-1) == ' '
           || *(s-1) == '\t')
           || *(s-1) == '\t')
          && ((strncasecmp (s, "AND", 3) == 0
          && ((strncasecmp (s, "AND", 3) == 0
               && (s[3] == '.' || ! is_part_of_name (s[3])))
               && (s[3] == '.' || ! is_part_of_name (s[3])))
              || (strncasecmp (s, "OR", 2) == 0
              || (strncasecmp (s, "OR", 2) == 0
                  && (s[2] == '.' || ! is_part_of_name (s[2])))))
                  && (s[2] == '.' || ! is_part_of_name (s[2])))))
        break;
        break;
    }
    }
 
 
  *rightstart = input_line_pointer;
  *rightstart = input_line_pointer;
  *rightstop = s;
  *rightstop = s;
  if (*rightstop > *rightstart
  if (*rightstop > *rightstart
      && ((*rightstop)[-1] == ' ' || (*rightstop)[-1] == '\t'))
      && ((*rightstop)[-1] == ' ' || (*rightstop)[-1] == '\t'))
    --*rightstop;
    --*rightstop;
 
 
  input_line_pointer = s;
  input_line_pointer = s;
 
 
  return 1;
  return 1;
}
}
 
 
#define MCC(b1, b2) (((b1) << 8) | (b2))
#define MCC(b1, b2) (((b1) << 8) | (b2))
 
 
/* Swap the sense of a condition.  This changes the condition so that
/* Swap the sense of a condition.  This changes the condition so that
   it generates the same result when the operands are swapped.  */
   it generates the same result when the operands are swapped.  */
 
 
static int
static int
swap_mri_condition (int cc)
swap_mri_condition (int cc)
{
{
  switch (cc)
  switch (cc)
    {
    {
    case MCC ('h', 'i'): return MCC ('c', 's');
    case MCC ('h', 'i'): return MCC ('c', 's');
    case MCC ('l', 's'): return MCC ('c', 'c');
    case MCC ('l', 's'): return MCC ('c', 'c');
    /* <HS> is an alias for <CC>.  */
    /* <HS> is an alias for <CC>.  */
    case MCC ('h', 's'):
    case MCC ('h', 's'):
    case MCC ('c', 'c'): return MCC ('l', 's');
    case MCC ('c', 'c'): return MCC ('l', 's');
    /* <LO> is an alias for <CS>.  */
    /* <LO> is an alias for <CS>.  */
    case MCC ('l', 'o'):
    case MCC ('l', 'o'):
    case MCC ('c', 's'): return MCC ('h', 'i');
    case MCC ('c', 's'): return MCC ('h', 'i');
    case MCC ('p', 'l'): return MCC ('m', 'i');
    case MCC ('p', 'l'): return MCC ('m', 'i');
    case MCC ('m', 'i'): return MCC ('p', 'l');
    case MCC ('m', 'i'): return MCC ('p', 'l');
    case MCC ('g', 'e'): return MCC ('l', 'e');
    case MCC ('g', 'e'): return MCC ('l', 'e');
    case MCC ('l', 't'): return MCC ('g', 't');
    case MCC ('l', 't'): return MCC ('g', 't');
    case MCC ('g', 't'): return MCC ('l', 't');
    case MCC ('g', 't'): return MCC ('l', 't');
    case MCC ('l', 'e'): return MCC ('g', 'e');
    case MCC ('l', 'e'): return MCC ('g', 'e');
    /* Issue a warning for conditions we can not swap.  */
    /* Issue a warning for conditions we can not swap.  */
    case MCC ('n', 'e'): return MCC ('n', 'e'); // no problem here
    case MCC ('n', 'e'): return MCC ('n', 'e'); // no problem here
    case MCC ('e', 'q'): return MCC ('e', 'q'); // also no problem
    case MCC ('e', 'q'): return MCC ('e', 'q'); // also no problem
    case MCC ('v', 'c'):
    case MCC ('v', 'c'):
    case MCC ('v', 's'):
    case MCC ('v', 's'):
    default :
    default :
           as_warn (_("Condition <%c%c> in structured control directive can not be encoded correctly"),
           as_warn (_("Condition <%c%c> in structured control directive can not be encoded correctly"),
                         (char) (cc >> 8), (char) (cc));
                         (char) (cc >> 8), (char) (cc));
      break;
      break;
    }
    }
  return cc;
  return cc;
}
}
 
 
/* Reverse the sense of a condition.  */
/* Reverse the sense of a condition.  */
 
 
static int
static int
reverse_mri_condition (int cc)
reverse_mri_condition (int cc)
{
{
  switch (cc)
  switch (cc)
    {
    {
    case MCC ('h', 'i'): return MCC ('l', 's');
    case MCC ('h', 'i'): return MCC ('l', 's');
    case MCC ('l', 's'): return MCC ('h', 'i');
    case MCC ('l', 's'): return MCC ('h', 'i');
    /* <HS> is an alias for <CC> */
    /* <HS> is an alias for <CC> */
    case MCC ('h', 's'): return MCC ('l', 'o');
    case MCC ('h', 's'): return MCC ('l', 'o');
    case MCC ('c', 'c'): return MCC ('c', 's');
    case MCC ('c', 'c'): return MCC ('c', 's');
    /* <LO> is an alias for <CS> */
    /* <LO> is an alias for <CS> */
    case MCC ('l', 'o'): return MCC ('h', 's');
    case MCC ('l', 'o'): return MCC ('h', 's');
    case MCC ('c', 's'): return MCC ('c', 'c');
    case MCC ('c', 's'): return MCC ('c', 'c');
    case MCC ('n', 'e'): return MCC ('e', 'q');
    case MCC ('n', 'e'): return MCC ('e', 'q');
    case MCC ('e', 'q'): return MCC ('n', 'e');
    case MCC ('e', 'q'): return MCC ('n', 'e');
    case MCC ('v', 'c'): return MCC ('v', 's');
    case MCC ('v', 'c'): return MCC ('v', 's');
    case MCC ('v', 's'): return MCC ('v', 'c');
    case MCC ('v', 's'): return MCC ('v', 'c');
    case MCC ('p', 'l'): return MCC ('m', 'i');
    case MCC ('p', 'l'): return MCC ('m', 'i');
    case MCC ('m', 'i'): return MCC ('p', 'l');
    case MCC ('m', 'i'): return MCC ('p', 'l');
    case MCC ('g', 'e'): return MCC ('l', 't');
    case MCC ('g', 'e'): return MCC ('l', 't');
    case MCC ('l', 't'): return MCC ('g', 'e');
    case MCC ('l', 't'): return MCC ('g', 'e');
    case MCC ('g', 't'): return MCC ('l', 'e');
    case MCC ('g', 't'): return MCC ('l', 'e');
    case MCC ('l', 'e'): return MCC ('g', 't');
    case MCC ('l', 'e'): return MCC ('g', 't');
    }
    }
  return cc;
  return cc;
}
}
 
 
/* Build an MRI structured control expression.  This generates test
/* Build an MRI structured control expression.  This generates test
   and branch instructions.  It goes to TRUELAB if the condition is
   and branch instructions.  It goes to TRUELAB if the condition is
   true, and to FALSELAB if the condition is false.  Exactly one of
   true, and to FALSELAB if the condition is false.  Exactly one of
   TRUELAB and FALSELAB will be NULL, meaning to fall through.  QUAL
   TRUELAB and FALSELAB will be NULL, meaning to fall through.  QUAL
   is the size qualifier for the expression.  EXTENT is the size to
   is the size qualifier for the expression.  EXTENT is the size to
   use for the branch.  */
   use for the branch.  */
 
 
static void
static void
build_mri_control_operand (int qual, int cc, char *leftstart, char *leftstop,
build_mri_control_operand (int qual, int cc, char *leftstart, char *leftstop,
                           char *rightstart, char *rightstop,
                           char *rightstart, char *rightstop,
                           const char *truelab, const char *falselab,
                           const char *truelab, const char *falselab,
                           int extent)
                           int extent)
{
{
  char *buf;
  char *buf;
  char *s;
  char *s;
 
 
  if (leftstart != NULL)
  if (leftstart != NULL)
    {
    {
      struct m68k_op leftop, rightop;
      struct m68k_op leftop, rightop;
      char c;
      char c;
 
 
      /* Swap the compare operands, if necessary, to produce a legal
      /* Swap the compare operands, if necessary, to produce a legal
         m68k compare instruction.  Comparing a register operand with
         m68k compare instruction.  Comparing a register operand with
         a non-register operand requires the register to be on the
         a non-register operand requires the register to be on the
         right (cmp, cmpa).  Comparing an immediate value with
         right (cmp, cmpa).  Comparing an immediate value with
         anything requires the immediate value to be on the left
         anything requires the immediate value to be on the left
         (cmpi).  */
         (cmpi).  */
 
 
      c = *leftstop;
      c = *leftstop;
      *leftstop = '\0';
      *leftstop = '\0';
      (void) m68k_ip_op (leftstart, &leftop);
      (void) m68k_ip_op (leftstart, &leftop);
      *leftstop = c;
      *leftstop = c;
 
 
      c = *rightstop;
      c = *rightstop;
      *rightstop = '\0';
      *rightstop = '\0';
      (void) m68k_ip_op (rightstart, &rightop);
      (void) m68k_ip_op (rightstart, &rightop);
      *rightstop = c;
      *rightstop = c;
 
 
      if (rightop.mode == IMMED
      if (rightop.mode == IMMED
          || ((leftop.mode == DREG || leftop.mode == AREG)
          || ((leftop.mode == DREG || leftop.mode == AREG)
              && (rightop.mode != DREG && rightop.mode != AREG)))
              && (rightop.mode != DREG && rightop.mode != AREG)))
        {
        {
          char *temp;
          char *temp;
 
 
          /* Correct conditional handling:
          /* Correct conditional handling:
             if #1 <lt> d0 then  ;means if (1 < d0)
             if #1 <lt> d0 then  ;means if (1 < d0)
                ...
                ...
             endi
             endi
 
 
             should assemble to:
             should assemble to:
 
 
                cmp #1,d0        if we do *not* swap the operands
                cmp #1,d0        if we do *not* swap the operands
                bgt true         we need the swapped condition!
                bgt true         we need the swapped condition!
                ble false
                ble false
             true:
             true:
                ...
                ...
             false:
             false:
          */
          */
          temp = leftstart;
          temp = leftstart;
          leftstart = rightstart;
          leftstart = rightstart;
          rightstart = temp;
          rightstart = temp;
          temp = leftstop;
          temp = leftstop;
          leftstop = rightstop;
          leftstop = rightstop;
          rightstop = temp;
          rightstop = temp;
        }
        }
      else
      else
        {
        {
          cc = swap_mri_condition (cc);
          cc = swap_mri_condition (cc);
        }
        }
    }
    }
 
 
  if (truelab == NULL)
  if (truelab == NULL)
    {
    {
      cc = reverse_mri_condition (cc);
      cc = reverse_mri_condition (cc);
      truelab = falselab;
      truelab = falselab;
    }
    }
 
 
  if (leftstart != NULL)
  if (leftstart != NULL)
    {
    {
      buf = (char *) xmalloc (20
      buf = (char *) xmalloc (20
                              + (leftstop - leftstart)
                              + (leftstop - leftstart)
                              + (rightstop - rightstart));
                              + (rightstop - rightstart));
      s = buf;
      s = buf;
      *s++ = 'c';
      *s++ = 'c';
      *s++ = 'm';
      *s++ = 'm';
      *s++ = 'p';
      *s++ = 'p';
      if (qual != '\0')
      if (qual != '\0')
        *s++ = TOLOWER (qual);
        *s++ = TOLOWER (qual);
      *s++ = ' ';
      *s++ = ' ';
      memcpy (s, leftstart, leftstop - leftstart);
      memcpy (s, leftstart, leftstop - leftstart);
      s += leftstop - leftstart;
      s += leftstop - leftstart;
      *s++ = ',';
      *s++ = ',';
      memcpy (s, rightstart, rightstop - rightstart);
      memcpy (s, rightstart, rightstop - rightstart);
      s += rightstop - rightstart;
      s += rightstop - rightstart;
      *s = '\0';
      *s = '\0';
      mri_assemble (buf);
      mri_assemble (buf);
      free (buf);
      free (buf);
    }
    }
 
 
  buf = (char *) xmalloc (20 + strlen (truelab));
  buf = (char *) xmalloc (20 + strlen (truelab));
  s = buf;
  s = buf;
  *s++ = 'b';
  *s++ = 'b';
  *s++ = cc >> 8;
  *s++ = cc >> 8;
  *s++ = cc & 0xff;
  *s++ = cc & 0xff;
  if (extent != '\0')
  if (extent != '\0')
    *s++ = TOLOWER (extent);
    *s++ = TOLOWER (extent);
  *s++ = ' ';
  *s++ = ' ';
  strcpy (s, truelab);
  strcpy (s, truelab);
  mri_assemble (buf);
  mri_assemble (buf);
  free (buf);
  free (buf);
}
}
 
 
/* Parse an MRI structured control expression.  This generates test
/* Parse an MRI structured control expression.  This generates test
   and branch instructions.  STOP is where the expression ends.  It
   and branch instructions.  STOP is where the expression ends.  It
   goes to TRUELAB if the condition is true, and to FALSELAB if the
   goes to TRUELAB if the condition is true, and to FALSELAB if the
   condition is false.  Exactly one of TRUELAB and FALSELAB will be
   condition is false.  Exactly one of TRUELAB and FALSELAB will be
   NULL, meaning to fall through.  QUAL is the size qualifier for the
   NULL, meaning to fall through.  QUAL is the size qualifier for the
   expression.  EXTENT is the size to use for the branch.  */
   expression.  EXTENT is the size to use for the branch.  */
 
 
static void
static void
parse_mri_control_expression (char *stop, int qual, const char *truelab,
parse_mri_control_expression (char *stop, int qual, const char *truelab,
                              const char *falselab, int extent)
                              const char *falselab, int extent)
{
{
  int c;
  int c;
  int cc;
  int cc;
  char *leftstart;
  char *leftstart;
  char *leftstop;
  char *leftstop;
  char *rightstart;
  char *rightstart;
  char *rightstop;
  char *rightstop;
 
 
  c = *stop;
  c = *stop;
  *stop = '\0';
  *stop = '\0';
 
 
  if (! parse_mri_control_operand (&cc, &leftstart, &leftstop,
  if (! parse_mri_control_operand (&cc, &leftstart, &leftstop,
                                   &rightstart, &rightstop))
                                   &rightstart, &rightstop))
    {
    {
      *stop = c;
      *stop = c;
      return;
      return;
    }
    }
 
 
  if (strncasecmp (input_line_pointer, "AND", 3) == 0)
  if (strncasecmp (input_line_pointer, "AND", 3) == 0)
    {
    {
      const char *flab;
      const char *flab;
 
 
      if (falselab != NULL)
      if (falselab != NULL)
        flab = falselab;
        flab = falselab;
      else
      else
        flab = mri_control_label ();
        flab = mri_control_label ();
 
 
      build_mri_control_operand (qual, cc, leftstart, leftstop, rightstart,
      build_mri_control_operand (qual, cc, leftstart, leftstop, rightstart,
                                 rightstop, (const char *) NULL, flab, extent);
                                 rightstop, (const char *) NULL, flab, extent);
 
 
      input_line_pointer += 3;
      input_line_pointer += 3;
      if (*input_line_pointer != '.'
      if (*input_line_pointer != '.'
          || input_line_pointer[1] == '\0')
          || input_line_pointer[1] == '\0')
        qual = '\0';
        qual = '\0';
      else
      else
        {
        {
          qual = input_line_pointer[1];
          qual = input_line_pointer[1];
          input_line_pointer += 2;
          input_line_pointer += 2;
        }
        }
 
 
      if (! parse_mri_control_operand (&cc, &leftstart, &leftstop,
      if (! parse_mri_control_operand (&cc, &leftstart, &leftstop,
                                       &rightstart, &rightstop))
                                       &rightstart, &rightstop))
        {
        {
          *stop = c;
          *stop = c;
          return;
          return;
        }
        }
 
 
      build_mri_control_operand (qual, cc, leftstart, leftstop, rightstart,
      build_mri_control_operand (qual, cc, leftstart, leftstop, rightstart,
                                 rightstop, truelab, falselab, extent);
                                 rightstop, truelab, falselab, extent);
 
 
      if (falselab == NULL)
      if (falselab == NULL)
        colon (flab);
        colon (flab);
    }
    }
  else if (strncasecmp (input_line_pointer, "OR", 2) == 0)
  else if (strncasecmp (input_line_pointer, "OR", 2) == 0)
    {
    {
      const char *tlab;
      const char *tlab;
 
 
      if (truelab != NULL)
      if (truelab != NULL)
        tlab = truelab;
        tlab = truelab;
      else
      else
        tlab = mri_control_label ();
        tlab = mri_control_label ();
 
 
      build_mri_control_operand (qual, cc, leftstart, leftstop, rightstart,
      build_mri_control_operand (qual, cc, leftstart, leftstop, rightstart,
                                 rightstop, tlab, (const char *) NULL, extent);
                                 rightstop, tlab, (const char *) NULL, extent);
 
 
      input_line_pointer += 2;
      input_line_pointer += 2;
      if (*input_line_pointer != '.'
      if (*input_line_pointer != '.'
          || input_line_pointer[1] == '\0')
          || input_line_pointer[1] == '\0')
        qual = '\0';
        qual = '\0';
      else
      else
        {
        {
          qual = input_line_pointer[1];
          qual = input_line_pointer[1];
          input_line_pointer += 2;
          input_line_pointer += 2;
        }
        }
 
 
      if (! parse_mri_control_operand (&cc, &leftstart, &leftstop,
      if (! parse_mri_control_operand (&cc, &leftstart, &leftstop,
                                       &rightstart, &rightstop))
                                       &rightstart, &rightstop))
        {
        {
          *stop = c;
          *stop = c;
          return;
          return;
        }
        }
 
 
      build_mri_control_operand (qual, cc, leftstart, leftstop, rightstart,
      build_mri_control_operand (qual, cc, leftstart, leftstop, rightstart,
                                 rightstop, truelab, falselab, extent);
                                 rightstop, truelab, falselab, extent);
 
 
      if (truelab == NULL)
      if (truelab == NULL)
        colon (tlab);
        colon (tlab);
    }
    }
  else
  else
    {
    {
      build_mri_control_operand (qual, cc, leftstart, leftstop, rightstart,
      build_mri_control_operand (qual, cc, leftstart, leftstop, rightstart,
                                 rightstop, truelab, falselab, extent);
                                 rightstop, truelab, falselab, extent);
    }
    }
 
 
  *stop = c;
  *stop = c;
  if (input_line_pointer != stop)
  if (input_line_pointer != stop)
    as_bad (_("syntax error in structured control directive"));
    as_bad (_("syntax error in structured control directive"));
}
}
 
 
/* Handle the MRI IF pseudo-op.  This may be a structured control
/* Handle the MRI IF pseudo-op.  This may be a structured control
   directive, or it may be a regular assembler conditional, depending
   directive, or it may be a regular assembler conditional, depending
   on its operands.  */
   on its operands.  */
 
 
static void
static void
s_mri_if (int qual)
s_mri_if (int qual)
{
{
  char *s;
  char *s;
  int c;
  int c;
  struct mri_control_info *n;
  struct mri_control_info *n;
 
 
  /* A structured control directive must end with THEN with an
  /* A structured control directive must end with THEN with an
     optional qualifier.  */
     optional qualifier.  */
  s = input_line_pointer;
  s = input_line_pointer;
  /* We only accept '*' as introduction of comments if preceded by white space
  /* We only accept '*' as introduction of comments if preceded by white space
     or at first column of a line (I think this can't actually happen here?)
     or at first column of a line (I think this can't actually happen here?)
     This is important when assembling:
     This is important when assembling:
       if d0 <ne> 12(a0,d0*2) then
       if d0 <ne> 12(a0,d0*2) then
       if d0 <ne> #CONST*20   then.  */
       if d0 <ne> #CONST*20   then.  */
  while (! (is_end_of_line[(unsigned char) *s]
  while (! (is_end_of_line[(unsigned char) *s]
            || (flag_mri
            || (flag_mri
                && *s == '*'
                && *s == '*'
                && (s == input_line_pointer
                && (s == input_line_pointer
                    || *(s-1) == ' '
                    || *(s-1) == ' '
                    || *(s-1) == '\t'))))
                    || *(s-1) == '\t'))))
    ++s;
    ++s;
  --s;
  --s;
  while (s > input_line_pointer && (*s == ' ' || *s == '\t'))
  while (s > input_line_pointer && (*s == ' ' || *s == '\t'))
    --s;
    --s;
 
 
  if (s - input_line_pointer > 1
  if (s - input_line_pointer > 1
      && s[-1] == '.')
      && s[-1] == '.')
    s -= 2;
    s -= 2;
 
 
  if (s - input_line_pointer < 3
  if (s - input_line_pointer < 3
      || strncasecmp (s - 3, "THEN", 4) != 0)
      || strncasecmp (s - 3, "THEN", 4) != 0)
    {
    {
      if (qual != '\0')
      if (qual != '\0')
        {
        {
          as_bad (_("missing then"));
          as_bad (_("missing then"));
          ignore_rest_of_line ();
          ignore_rest_of_line ();
          return;
          return;
        }
        }
 
 
      /* It's a conditional.  */
      /* It's a conditional.  */
      s_if (O_ne);
      s_if (O_ne);
      return;
      return;
    }
    }
 
 
  /* Since this might be a conditional if, this pseudo-op will be
  /* Since this might be a conditional if, this pseudo-op will be
     called even if we are supported to be ignoring input.  Double
     called even if we are supported to be ignoring input.  Double
     check now.  Clobber *input_line_pointer so that ignore_input
     check now.  Clobber *input_line_pointer so that ignore_input
     thinks that this is not a special pseudo-op.  */
     thinks that this is not a special pseudo-op.  */
  c = *input_line_pointer;
  c = *input_line_pointer;
  *input_line_pointer = 0;
  *input_line_pointer = 0;
  if (ignore_input ())
  if (ignore_input ())
    {
    {
      *input_line_pointer = c;
      *input_line_pointer = c;
      while (! is_end_of_line[(unsigned char) *input_line_pointer])
      while (! is_end_of_line[(unsigned char) *input_line_pointer])
        ++input_line_pointer;
        ++input_line_pointer;
      demand_empty_rest_of_line ();
      demand_empty_rest_of_line ();
      return;
      return;
    }
    }
  *input_line_pointer = c;
  *input_line_pointer = c;
 
 
  n = push_mri_control (mri_if);
  n = push_mri_control (mri_if);
 
 
  parse_mri_control_expression (s - 3, qual, (const char *) NULL,
  parse_mri_control_expression (s - 3, qual, (const char *) NULL,
                                n->next, s[1] == '.' ? s[2] : '\0');
                                n->next, s[1] == '.' ? s[2] : '\0');
 
 
  if (s[1] == '.')
  if (s[1] == '.')
    input_line_pointer = s + 3;
    input_line_pointer = s + 3;
  else
  else
    input_line_pointer = s + 1;
    input_line_pointer = s + 1;
 
 
  if (flag_mri)
  if (flag_mri)
    {
    {
      while (! is_end_of_line[(unsigned char) *input_line_pointer])
      while (! is_end_of_line[(unsigned char) *input_line_pointer])
        ++input_line_pointer;
        ++input_line_pointer;
    }
    }
 
 
  demand_empty_rest_of_line ();
  demand_empty_rest_of_line ();
}
}
 
 
/* Handle the MRI else pseudo-op.  If we are currently doing an MRI
/* Handle the MRI else pseudo-op.  If we are currently doing an MRI
   structured IF, associate the ELSE with the IF.  Otherwise, assume
   structured IF, associate the ELSE with the IF.  Otherwise, assume
   it is a conditional else.  */
   it is a conditional else.  */
 
 
static void
static void
s_mri_else (int qual)
s_mri_else (int qual)
{
{
  int c;
  int c;
  char *buf;
  char *buf;
  char q[2];
  char q[2];
 
 
  if (qual == '\0'
  if (qual == '\0'
      && (mri_control_stack == NULL
      && (mri_control_stack == NULL
          || mri_control_stack->type != mri_if
          || mri_control_stack->type != mri_if
          || mri_control_stack->else_seen))
          || mri_control_stack->else_seen))
    {
    {
      s_else (0);
      s_else (0);
      return;
      return;
    }
    }
 
 
  c = *input_line_pointer;
  c = *input_line_pointer;
  *input_line_pointer = 0;
  *input_line_pointer = 0;
  if (ignore_input ())
  if (ignore_input ())
    {
    {
      *input_line_pointer = c;
      *input_line_pointer = c;
      while (! is_end_of_line[(unsigned char) *input_line_pointer])
      while (! is_end_of_line[(unsigned char) *input_line_pointer])
        ++input_line_pointer;
        ++input_line_pointer;
      demand_empty_rest_of_line ();
      demand_empty_rest_of_line ();
      return;
      return;
    }
    }
  *input_line_pointer = c;
  *input_line_pointer = c;
 
 
  if (mri_control_stack == NULL
  if (mri_control_stack == NULL
      || mri_control_stack->type != mri_if
      || mri_control_stack->type != mri_if
      || mri_control_stack->else_seen)
      || mri_control_stack->else_seen)
    {
    {
      as_bad (_("else without matching if"));
      as_bad (_("else without matching if"));
      ignore_rest_of_line ();
      ignore_rest_of_line ();
      return;
      return;
    }
    }
 
 
  mri_control_stack->else_seen = 1;
  mri_control_stack->else_seen = 1;
 
 
  buf = (char *) xmalloc (20 + strlen (mri_control_stack->bottom));
  buf = (char *) xmalloc (20 + strlen (mri_control_stack->bottom));
  q[0] = TOLOWER (qual);
  q[0] = TOLOWER (qual);
  q[1] = '\0';
  q[1] = '\0';
  sprintf (buf, "bra%s %s", q, mri_control_stack->bottom);
  sprintf (buf, "bra%s %s", q, mri_control_stack->bottom);
  mri_assemble (buf);
  mri_assemble (buf);
  free (buf);
  free (buf);
 
 
  colon (mri_control_stack->next);
  colon (mri_control_stack->next);
 
 
  if (flag_mri)
  if (flag_mri)
    {
    {
      while (! is_end_of_line[(unsigned char) *input_line_pointer])
      while (! is_end_of_line[(unsigned char) *input_line_pointer])
        ++input_line_pointer;
        ++input_line_pointer;
    }
    }
 
 
  demand_empty_rest_of_line ();
  demand_empty_rest_of_line ();
}
}
 
 
/* Handle the MRI ENDI pseudo-op.  */
/* Handle the MRI ENDI pseudo-op.  */
 
 
static void
static void
s_mri_endi (int ignore ATTRIBUTE_UNUSED)
s_mri_endi (int ignore ATTRIBUTE_UNUSED)
{
{
  if (mri_control_stack == NULL
  if (mri_control_stack == NULL
      || mri_control_stack->type != mri_if)
      || mri_control_stack->type != mri_if)
    {
    {
      as_bad (_("endi without matching if"));
      as_bad (_("endi without matching if"));
      ignore_rest_of_line ();
      ignore_rest_of_line ();
      return;
      return;
    }
    }
 
 
  /* ignore_input will not return true for ENDI, so we don't need to
  /* ignore_input will not return true for ENDI, so we don't need to
     worry about checking it again here.  */
     worry about checking it again here.  */
 
 
  if (! mri_control_stack->else_seen)
  if (! mri_control_stack->else_seen)
    colon (mri_control_stack->next);
    colon (mri_control_stack->next);
  colon (mri_control_stack->bottom);
  colon (mri_control_stack->bottom);
 
 
  pop_mri_control ();
  pop_mri_control ();
 
 
  if (flag_mri)
  if (flag_mri)
    {
    {
      while (! is_end_of_line[(unsigned char) *input_line_pointer])
      while (! is_end_of_line[(unsigned char) *input_line_pointer])
        ++input_line_pointer;
        ++input_line_pointer;
    }
    }
 
 
  demand_empty_rest_of_line ();
  demand_empty_rest_of_line ();
}
}
 
 
/* Handle the MRI BREAK pseudo-op.  */
/* Handle the MRI BREAK pseudo-op.  */
 
 
static void
static void
s_mri_break (int extent)
s_mri_break (int extent)
{
{
  struct mri_control_info *n;
  struct mri_control_info *n;
  char *buf;
  char *buf;
  char ex[2];
  char ex[2];
 
 
  n = mri_control_stack;
  n = mri_control_stack;
  while (n != NULL
  while (n != NULL
         && n->type != mri_for
         && n->type != mri_for
         && n->type != mri_repeat
         && n->type != mri_repeat
         && n->type != mri_while)
         && n->type != mri_while)
    n = n->outer;
    n = n->outer;
  if (n == NULL)
  if (n == NULL)
    {
    {
      as_bad (_("break outside of structured loop"));
      as_bad (_("break outside of structured loop"));
      ignore_rest_of_line ();
      ignore_rest_of_line ();
      return;
      return;
    }
    }
 
 
  buf = (char *) xmalloc (20 + strlen (n->bottom));
  buf = (char *) xmalloc (20 + strlen (n->bottom));
  ex[0] = TOLOWER (extent);
  ex[0] = TOLOWER (extent);
  ex[1] = '\0';
  ex[1] = '\0';
  sprintf (buf, "bra%s %s", ex, n->bottom);
  sprintf (buf, "bra%s %s", ex, n->bottom);
  mri_assemble (buf);
  mri_assemble (buf);
  free (buf);
  free (buf);
 
 
  if (flag_mri)
  if (flag_mri)
    {
    {
      while (! is_end_of_line[(unsigned char) *input_line_pointer])
      while (! is_end_of_line[(unsigned char) *input_line_pointer])
        ++input_line_pointer;
        ++input_line_pointer;
    }
    }
 
 
  demand_empty_rest_of_line ();
  demand_empty_rest_of_line ();
}
}
 
 
/* Handle the MRI NEXT pseudo-op.  */
/* Handle the MRI NEXT pseudo-op.  */
 
 
static void
static void
s_mri_next (int extent)
s_mri_next (int extent)
{
{
  struct mri_control_info *n;
  struct mri_control_info *n;
  char *buf;
  char *buf;
  char ex[2];
  char ex[2];
 
 
  n = mri_control_stack;
  n = mri_control_stack;
  while (n != NULL
  while (n != NULL
         && n->type != mri_for
         && n->type != mri_for
         && n->type != mri_repeat
         && n->type != mri_repeat
         && n->type != mri_while)
         && n->type != mri_while)
    n = n->outer;
    n = n->outer;
  if (n == NULL)
  if (n == NULL)
    {
    {
      as_bad (_("next outside of structured loop"));
      as_bad (_("next outside of structured loop"));
      ignore_rest_of_line ();
      ignore_rest_of_line ();
      return;
      return;
    }
    }
 
 
  buf = (char *) xmalloc (20 + strlen (n->next));
  buf = (char *) xmalloc (20 + strlen (n->next));
  ex[0] = TOLOWER (extent);
  ex[0] = TOLOWER (extent);
  ex[1] = '\0';
  ex[1] = '\0';
  sprintf (buf, "bra%s %s", ex, n->next);
  sprintf (buf, "bra%s %s", ex, n->next);
  mri_assemble (buf);
  mri_assemble (buf);
  free (buf);
  free (buf);
 
 
  if (flag_mri)
  if (flag_mri)
    {
    {
      while (! is_end_of_line[(unsigned char) *input_line_pointer])
      while (! is_end_of_line[(unsigned char) *input_line_pointer])
        ++input_line_pointer;
        ++input_line_pointer;
    }
    }
 
 
  demand_empty_rest_of_line ();
  demand_empty_rest_of_line ();
}
}
 
 
/* Handle the MRI FOR pseudo-op.  */
/* Handle the MRI FOR pseudo-op.  */
 
 
static void
static void
s_mri_for (int qual)
s_mri_for (int qual)
{
{
  const char *varstart, *varstop;
  const char *varstart, *varstop;
  const char *initstart, *initstop;
  const char *initstart, *initstop;
  const char *endstart, *endstop;
  const char *endstart, *endstop;
  const char *bystart, *bystop;
  const char *bystart, *bystop;
  int up;
  int up;
  int by;
  int by;
  int extent;
  int extent;
  struct mri_control_info *n;
  struct mri_control_info *n;
  char *buf;
  char *buf;
  char *s;
  char *s;
  char ex[2];
  char ex[2];
 
 
  /* The syntax is
  /* The syntax is
       FOR.q var = init { TO | DOWNTO } end [ BY by ] DO.e
       FOR.q var = init { TO | DOWNTO } end [ BY by ] DO.e
     */
     */
 
 
  SKIP_WHITESPACE ();
  SKIP_WHITESPACE ();
  varstart = input_line_pointer;
  varstart = input_line_pointer;
 
 
  /* Look for the '='.  */
  /* Look for the '='.  */
  while (! is_end_of_line[(unsigned char) *input_line_pointer]
  while (! is_end_of_line[(unsigned char) *input_line_pointer]
         && *input_line_pointer != '=')
         && *input_line_pointer != '=')
    ++input_line_pointer;
    ++input_line_pointer;
  if (*input_line_pointer != '=')
  if (*input_line_pointer != '=')
    {
    {
      as_bad (_("missing ="));
      as_bad (_("missing ="));
      ignore_rest_of_line ();
      ignore_rest_of_line ();
      return;
      return;
    }
    }
 
 
  varstop = input_line_pointer;
  varstop = input_line_pointer;
  if (varstop > varstart
  if (varstop > varstart
      && (varstop[-1] == ' ' || varstop[-1] == '\t'))
      && (varstop[-1] == ' ' || varstop[-1] == '\t'))
    --varstop;
    --varstop;
 
 
  ++input_line_pointer;
  ++input_line_pointer;
 
 
  initstart = input_line_pointer;
  initstart = input_line_pointer;
 
 
  /* Look for TO or DOWNTO.  */
  /* Look for TO or DOWNTO.  */
  up = 1;
  up = 1;
  initstop = NULL;
  initstop = NULL;
  while (! is_end_of_line[(unsigned char) *input_line_pointer])
  while (! is_end_of_line[(unsigned char) *input_line_pointer])
    {
    {
      if (strncasecmp (input_line_pointer, "TO", 2) == 0
      if (strncasecmp (input_line_pointer, "TO", 2) == 0
          && ! is_part_of_name (input_line_pointer[2]))
          && ! is_part_of_name (input_line_pointer[2]))
        {
        {
          initstop = input_line_pointer;
          initstop = input_line_pointer;
          input_line_pointer += 2;
          input_line_pointer += 2;
          break;
          break;
        }
        }
      if (strncasecmp (input_line_pointer, "DOWNTO", 6) == 0
      if (strncasecmp (input_line_pointer, "DOWNTO", 6) == 0
          && ! is_part_of_name (input_line_pointer[6]))
          && ! is_part_of_name (input_line_pointer[6]))
        {
        {
          initstop = input_line_pointer;
          initstop = input_line_pointer;
          up = 0;
          up = 0;
          input_line_pointer += 6;
          input_line_pointer += 6;
          break;
          break;
        }
        }
      ++input_line_pointer;
      ++input_line_pointer;
    }
    }
  if (initstop == NULL)
  if (initstop == NULL)
    {
    {
      as_bad (_("missing to or downto"));
      as_bad (_("missing to or downto"));
      ignore_rest_of_line ();
      ignore_rest_of_line ();
      return;
      return;
    }
    }
  if (initstop > initstart
  if (initstop > initstart
      && (initstop[-1] == ' ' || initstop[-1] == '\t'))
      && (initstop[-1] == ' ' || initstop[-1] == '\t'))
    --initstop;
    --initstop;
 
 
  SKIP_WHITESPACE ();
  SKIP_WHITESPACE ();
  endstart = input_line_pointer;
  endstart = input_line_pointer;
 
 
  /* Look for BY or DO.  */
  /* Look for BY or DO.  */
  by = 0;
  by = 0;
  endstop = NULL;
  endstop = NULL;
  while (! is_end_of_line[(unsigned char) *input_line_pointer])
  while (! is_end_of_line[(unsigned char) *input_line_pointer])
    {
    {
      if (strncasecmp (input_line_pointer, "BY", 2) == 0
      if (strncasecmp (input_line_pointer, "BY", 2) == 0
          && ! is_part_of_name (input_line_pointer[2]))
          && ! is_part_of_name (input_line_pointer[2]))
        {
        {
          endstop = input_line_pointer;
          endstop = input_line_pointer;
          by = 1;
          by = 1;
          input_line_pointer += 2;
          input_line_pointer += 2;
          break;
          break;
        }
        }
      if (strncasecmp (input_line_pointer, "DO", 2) == 0
      if (strncasecmp (input_line_pointer, "DO", 2) == 0
          && (input_line_pointer[2] == '.'
          && (input_line_pointer[2] == '.'
              || ! is_part_of_name (input_line_pointer[2])))
              || ! is_part_of_name (input_line_pointer[2])))
        {
        {
          endstop = input_line_pointer;
          endstop = input_line_pointer;
          input_line_pointer += 2;
          input_line_pointer += 2;
          break;
          break;
        }
        }
      ++input_line_pointer;
      ++input_line_pointer;
    }
    }
  if (endstop == NULL)
  if (endstop == NULL)
    {
    {
      as_bad (_("missing do"));
      as_bad (_("missing do"));
      ignore_rest_of_line ();
      ignore_rest_of_line ();
      return;
      return;
    }
    }
  if (endstop > endstart
  if (endstop > endstart
      && (endstop[-1] == ' ' || endstop[-1] == '\t'))
      && (endstop[-1] == ' ' || endstop[-1] == '\t'))
    --endstop;
    --endstop;
 
 
  if (! by)
  if (! by)
    {
    {
      bystart = "#1";
      bystart = "#1";
      bystop = bystart + 2;
      bystop = bystart + 2;
    }
    }
  else
  else
    {
    {
      SKIP_WHITESPACE ();
      SKIP_WHITESPACE ();
      bystart = input_line_pointer;
      bystart = input_line_pointer;
 
 
      /* Look for DO.  */
      /* Look for DO.  */
      bystop = NULL;
      bystop = NULL;
      while (! is_end_of_line[(unsigned char) *input_line_pointer])
      while (! is_end_of_line[(unsigned char) *input_line_pointer])
        {
        {
          if (strncasecmp (input_line_pointer, "DO", 2) == 0
          if (strncasecmp (input_line_pointer, "DO", 2) == 0
              && (input_line_pointer[2] == '.'
              && (input_line_pointer[2] == '.'
                  || ! is_part_of_name (input_line_pointer[2])))
                  || ! is_part_of_name (input_line_pointer[2])))
            {
            {
              bystop = input_line_pointer;
              bystop = input_line_pointer;
              input_line_pointer += 2;
              input_line_pointer += 2;
              break;
              break;
            }
            }
          ++input_line_pointer;
          ++input_line_pointer;
        }
        }
      if (bystop == NULL)
      if (bystop == NULL)
        {
        {
          as_bad (_("missing do"));
          as_bad (_("missing do"));
          ignore_rest_of_line ();
          ignore_rest_of_line ();
          return;
          return;
        }
        }
      if (bystop > bystart
      if (bystop > bystart
          && (bystop[-1] == ' ' || bystop[-1] == '\t'))
          && (bystop[-1] == ' ' || bystop[-1] == '\t'))
        --bystop;
        --bystop;
    }
    }
 
 
  if (*input_line_pointer != '.')
  if (*input_line_pointer != '.')
    extent = '\0';
    extent = '\0';
  else
  else
    {
    {
      extent = input_line_pointer[1];
      extent = input_line_pointer[1];
      input_line_pointer += 2;
      input_line_pointer += 2;
    }
    }
 
 
  /* We have fully parsed the FOR operands.  Now build the loop.  */
  /* We have fully parsed the FOR operands.  Now build the loop.  */
  n = push_mri_control (mri_for);
  n = push_mri_control (mri_for);
 
 
  buf = (char *) xmalloc (50 + (input_line_pointer - varstart));
  buf = (char *) xmalloc (50 + (input_line_pointer - varstart));
 
 
  /* Move init,var.  */
  /* Move init,var.  */
  s = buf;
  s = buf;
  *s++ = 'm';
  *s++ = 'm';
  *s++ = 'o';
  *s++ = 'o';
  *s++ = 'v';
  *s++ = 'v';
  *s++ = 'e';
  *s++ = 'e';
  if (qual != '\0')
  if (qual != '\0')
    *s++ = TOLOWER (qual);
    *s++ = TOLOWER (qual);
  *s++ = ' ';
  *s++ = ' ';
  memcpy (s, initstart, initstop - initstart);
  memcpy (s, initstart, initstop - initstart);
  s += initstop - initstart;
  s += initstop - initstart;
  *s++ = ',';
  *s++ = ',';
  memcpy (s, varstart, varstop - varstart);
  memcpy (s, varstart, varstop - varstart);
  s += varstop - varstart;
  s += varstop - varstart;
  *s = '\0';
  *s = '\0';
  mri_assemble (buf);
  mri_assemble (buf);
 
 
  colon (n->top);
  colon (n->top);
 
 
  /* cmp end,var.  */
  /* cmp end,var.  */
  s = buf;
  s = buf;
  *s++ = 'c';
  *s++ = 'c';
  *s++ = 'm';
  *s++ = 'm';
  *s++ = 'p';
  *s++ = 'p';
  if (qual != '\0')
  if (qual != '\0')
    *s++ = TOLOWER (qual);
    *s++ = TOLOWER (qual);
  *s++ = ' ';
  *s++ = ' ';
  memcpy (s, endstart, endstop - endstart);
  memcpy (s, endstart, endstop - endstart);
  s += endstop - endstart;
  s += endstop - endstart;
  *s++ = ',';
  *s++ = ',';
  memcpy (s, varstart, varstop - varstart);
  memcpy (s, varstart, varstop - varstart);
  s += varstop - varstart;
  s += varstop - varstart;
  *s = '\0';
  *s = '\0';
  mri_assemble (buf);
  mri_assemble (buf);
 
 
  /* bcc bottom.  */
  /* bcc bottom.  */
  ex[0] = TOLOWER (extent);
  ex[0] = TOLOWER (extent);
  ex[1] = '\0';
  ex[1] = '\0';
  if (up)
  if (up)
    sprintf (buf, "blt%s %s", ex, n->bottom);
    sprintf (buf, "blt%s %s", ex, n->bottom);
  else
  else
    sprintf (buf, "bgt%s %s", ex, n->bottom);
    sprintf (buf, "bgt%s %s", ex, n->bottom);
  mri_assemble (buf);
  mri_assemble (buf);
 
 
  /* Put together the add or sub instruction used by ENDF.  */
  /* Put together the add or sub instruction used by ENDF.  */
  s = buf;
  s = buf;
  if (up)
  if (up)
    strcpy (s, "add");
    strcpy (s, "add");
  else
  else
    strcpy (s, "sub");
    strcpy (s, "sub");
  s += 3;
  s += 3;
  if (qual != '\0')
  if (qual != '\0')
    *s++ = TOLOWER (qual);
    *s++ = TOLOWER (qual);
  *s++ = ' ';
  *s++ = ' ';
  memcpy (s, bystart, bystop - bystart);
  memcpy (s, bystart, bystop - bystart);
  s += bystop - bystart;
  s += bystop - bystart;
  *s++ = ',';
  *s++ = ',';
  memcpy (s, varstart, varstop - varstart);
  memcpy (s, varstart, varstop - varstart);
  s += varstop - varstart;
  s += varstop - varstart;
  *s = '\0';
  *s = '\0';
  n->incr = buf;
  n->incr = buf;
 
 
  if (flag_mri)
  if (flag_mri)
    {
    {
      while (! is_end_of_line[(unsigned char) *input_line_pointer])
      while (! is_end_of_line[(unsigned char) *input_line_pointer])
        ++input_line_pointer;
        ++input_line_pointer;
    }
    }
 
 
  demand_empty_rest_of_line ();
  demand_empty_rest_of_line ();
}
}
 
 
/* Handle the MRI ENDF pseudo-op.  */
/* Handle the MRI ENDF pseudo-op.  */
 
 
static void
static void
s_mri_endf (int ignore ATTRIBUTE_UNUSED)
s_mri_endf (int ignore ATTRIBUTE_UNUSED)
{
{
  if (mri_control_stack == NULL
  if (mri_control_stack == NULL
      || mri_control_stack->type != mri_for)
      || mri_control_stack->type != mri_for)
    {
    {
      as_bad (_("endf without for"));
      as_bad (_("endf without for"));
      ignore_rest_of_line ();
      ignore_rest_of_line ();
      return;
      return;
    }
    }
 
 
  colon (mri_control_stack->next);
  colon (mri_control_stack->next);
 
 
  mri_assemble (mri_control_stack->incr);
  mri_assemble (mri_control_stack->incr);
 
 
  sprintf (mri_control_stack->incr, "bra %s", mri_control_stack->top);
  sprintf (mri_control_stack->incr, "bra %s", mri_control_stack->top);
  mri_assemble (mri_control_stack->incr);
  mri_assemble (mri_control_stack->incr);
 
 
  free (mri_control_stack->incr);
  free (mri_control_stack->incr);
 
 
  colon (mri_control_stack->bottom);
  colon (mri_control_stack->bottom);
 
 
  pop_mri_control ();
  pop_mri_control ();
 
 
  if (flag_mri)
  if (flag_mri)
    {
    {
      while (! is_end_of_line[(unsigned char) *input_line_pointer])
      while (! is_end_of_line[(unsigned char) *input_line_pointer])
        ++input_line_pointer;
        ++input_line_pointer;
    }
    }
 
 
  demand_empty_rest_of_line ();
  demand_empty_rest_of_line ();
}
}
 
 
/* Handle the MRI REPEAT pseudo-op.  */
/* Handle the MRI REPEAT pseudo-op.  */
 
 
static void
static void
s_mri_repeat (int ignore ATTRIBUTE_UNUSED)
s_mri_repeat (int ignore ATTRIBUTE_UNUSED)
{
{
  struct mri_control_info *n;
  struct mri_control_info *n;
 
 
  n = push_mri_control (mri_repeat);
  n = push_mri_control (mri_repeat);
  colon (n->top);
  colon (n->top);
  if (flag_mri)
  if (flag_mri)
    {
    {
      while (! is_end_of_line[(unsigned char) *input_line_pointer])
      while (! is_end_of_line[(unsigned char) *input_line_pointer])
        ++input_line_pointer;
        ++input_line_pointer;
    }
    }
  demand_empty_rest_of_line ();
  demand_empty_rest_of_line ();
}
}
 
 
/* Handle the MRI UNTIL pseudo-op.  */
/* Handle the MRI UNTIL pseudo-op.  */
 
 
static void
static void
s_mri_until (int qual)
s_mri_until (int qual)
{
{
  char *s;
  char *s;
 
 
  if (mri_control_stack == NULL
  if (mri_control_stack == NULL
      || mri_control_stack->type != mri_repeat)
      || mri_control_stack->type != mri_repeat)
    {
    {
      as_bad (_("until without repeat"));
      as_bad (_("until without repeat"));
      ignore_rest_of_line ();
      ignore_rest_of_line ();
      return;
      return;
    }
    }
 
 
  colon (mri_control_stack->next);
  colon (mri_control_stack->next);
 
 
  for (s = input_line_pointer; ! is_end_of_line[(unsigned char) *s]; s++)
  for (s = input_line_pointer; ! is_end_of_line[(unsigned char) *s]; s++)
    ;
    ;
 
 
  parse_mri_control_expression (s, qual, (const char *) NULL,
  parse_mri_control_expression (s, qual, (const char *) NULL,
                                mri_control_stack->top, '\0');
                                mri_control_stack->top, '\0');
 
 
  colon (mri_control_stack->bottom);
  colon (mri_control_stack->bottom);
 
 
  input_line_pointer = s;
  input_line_pointer = s;
 
 
  pop_mri_control ();
  pop_mri_control ();
 
 
  if (flag_mri)
  if (flag_mri)
    {
    {
      while (! is_end_of_line[(unsigned char) *input_line_pointer])
      while (! is_end_of_line[(unsigned char) *input_line_pointer])
        ++input_line_pointer;
        ++input_line_pointer;
    }
    }
 
 
  demand_empty_rest_of_line ();
  demand_empty_rest_of_line ();
}
}
 
 
/* Handle the MRI WHILE pseudo-op.  */
/* Handle the MRI WHILE pseudo-op.  */
 
 
static void
static void
s_mri_while (int qual)
s_mri_while (int qual)
{
{
  char *s;
  char *s;
 
 
  struct mri_control_info *n;
  struct mri_control_info *n;
 
 
  s = input_line_pointer;
  s = input_line_pointer;
  /* We only accept '*' as introduction of comments if preceded by white space
  /* We only accept '*' as introduction of comments if preceded by white space
     or at first column of a line (I think this can't actually happen here?)
     or at first column of a line (I think this can't actually happen here?)
     This is important when assembling:
     This is important when assembling:
       while d0 <ne> 12(a0,d0*2) do
       while d0 <ne> 12(a0,d0*2) do
       while d0 <ne> #CONST*20   do.  */
       while d0 <ne> #CONST*20   do.  */
  while (! (is_end_of_line[(unsigned char) *s]
  while (! (is_end_of_line[(unsigned char) *s]
            || (flag_mri
            || (flag_mri
                && *s == '*'
                && *s == '*'
                && (s == input_line_pointer
                && (s == input_line_pointer
                    || *(s-1) == ' '
                    || *(s-1) == ' '
                    || *(s-1) == '\t'))))
                    || *(s-1) == '\t'))))
    s++;
    s++;
  --s;
  --s;
  while (*s == ' ' || *s == '\t')
  while (*s == ' ' || *s == '\t')
    --s;
    --s;
  if (s - input_line_pointer > 1
  if (s - input_line_pointer > 1
      && s[-1] == '.')
      && s[-1] == '.')
    s -= 2;
    s -= 2;
  if (s - input_line_pointer < 2
  if (s - input_line_pointer < 2
      || strncasecmp (s - 1, "DO", 2) != 0)
      || strncasecmp (s - 1, "DO", 2) != 0)
    {
    {
      as_bad (_("missing do"));
      as_bad (_("missing do"));
      ignore_rest_of_line ();
      ignore_rest_of_line ();
      return;
      return;
    }
    }
 
 
  n = push_mri_control (mri_while);
  n = push_mri_control (mri_while);
 
 
  colon (n->next);
  colon (n->next);
 
 
  parse_mri_control_expression (s - 1, qual, (const char *) NULL, n->bottom,
  parse_mri_control_expression (s - 1, qual, (const char *) NULL, n->bottom,
                                s[1] == '.' ? s[2] : '\0');
                                s[1] == '.' ? s[2] : '\0');
 
 
  input_line_pointer = s + 1;
  input_line_pointer = s + 1;
  if (*input_line_pointer == '.')
  if (*input_line_pointer == '.')
    input_line_pointer += 2;
    input_line_pointer += 2;
 
 
  if (flag_mri)
  if (flag_mri)
    {
    {
      while (! is_end_of_line[(unsigned char) *input_line_pointer])
      while (! is_end_of_line[(unsigned char) *input_line_pointer])
        ++input_line_pointer;
        ++input_line_pointer;
    }
    }
 
 
  demand_empty_rest_of_line ();
  demand_empty_rest_of_line ();
}
}
 
 
/* Handle the MRI ENDW pseudo-op.  */
/* Handle the MRI ENDW pseudo-op.  */
 
 
static void
static void
s_mri_endw (int ignore ATTRIBUTE_UNUSED)
s_mri_endw (int ignore ATTRIBUTE_UNUSED)
{
{
  char *buf;
  char *buf;
 
 
  if (mri_control_stack == NULL
  if (mri_control_stack == NULL
      || mri_control_stack->type != mri_while)
      || mri_control_stack->type != mri_while)
    {
    {
      as_bad (_("endw without while"));
      as_bad (_("endw without while"));
      ignore_rest_of_line ();
      ignore_rest_of_line ();
      return;
      return;
    }
    }
 
 
  buf = (char *) xmalloc (20 + strlen (mri_control_stack->next));
  buf = (char *) xmalloc (20 + strlen (mri_control_stack->next));
  sprintf (buf, "bra %s", mri_control_stack->next);
  sprintf (buf, "bra %s", mri_control_stack->next);
  mri_assemble (buf);
  mri_assemble (buf);
  free (buf);
  free (buf);
 
 
  colon (mri_control_stack->bottom);
  colon (mri_control_stack->bottom);
 
 
  pop_mri_control ();
  pop_mri_control ();
 
 
  if (flag_mri)
  if (flag_mri)
    {
    {
      while (! is_end_of_line[(unsigned char) *input_line_pointer])
      while (! is_end_of_line[(unsigned char) *input_line_pointer])
        ++input_line_pointer;
        ++input_line_pointer;
    }
    }
 
 
  demand_empty_rest_of_line ();
  demand_empty_rest_of_line ();
}
}


/* Parse a .cpu directive.  */
/* Parse a .cpu directive.  */
 
 
static void
static void
s_m68k_cpu (int ignored ATTRIBUTE_UNUSED)
s_m68k_cpu (int ignored ATTRIBUTE_UNUSED)
{
{
  char saved_char;
  char saved_char;
  char *name;
  char *name;
 
 
  if (initialized)
  if (initialized)
    {
    {
      as_bad (_("already assembled instructions"));
      as_bad (_("already assembled instructions"));
      ignore_rest_of_line ();
      ignore_rest_of_line ();
      return;
      return;
    }
    }
 
 
  name = input_line_pointer;
  name = input_line_pointer;
  while (*input_line_pointer && !ISSPACE(*input_line_pointer))
  while (*input_line_pointer && !ISSPACE(*input_line_pointer))
    input_line_pointer++;
    input_line_pointer++;
  saved_char = *input_line_pointer;
  saved_char = *input_line_pointer;
  *input_line_pointer = 0;
  *input_line_pointer = 0;
 
 
  m68k_set_cpu (name, 1, 0);
  m68k_set_cpu (name, 1, 0);
 
 
  *input_line_pointer = saved_char;
  *input_line_pointer = saved_char;
  demand_empty_rest_of_line ();
  demand_empty_rest_of_line ();
  return;
  return;
}
}
 
 
/* Parse a .arch directive.  */
/* Parse a .arch directive.  */
 
 
static void
static void
s_m68k_arch (int ignored ATTRIBUTE_UNUSED)
s_m68k_arch (int ignored ATTRIBUTE_UNUSED)
{
{
  char saved_char;
  char saved_char;
  char *name;
  char *name;
 
 
  if (initialized)
  if (initialized)
    {
    {
      as_bad (_("already assembled instructions"));
      as_bad (_("already assembled instructions"));
      ignore_rest_of_line ();
      ignore_rest_of_line ();
      return;
      return;
    }
    }
 
 
  name = input_line_pointer;
  name = input_line_pointer;
  while (*input_line_pointer && *input_line_pointer != ','
  while (*input_line_pointer && *input_line_pointer != ','
         && !ISSPACE (*input_line_pointer))
         && !ISSPACE (*input_line_pointer))
    input_line_pointer++;
    input_line_pointer++;
  saved_char = *input_line_pointer;
  saved_char = *input_line_pointer;
  *input_line_pointer = 0;
  *input_line_pointer = 0;
 
 
  if (m68k_set_arch (name, 1, 0))
  if (m68k_set_arch (name, 1, 0))
    {
    {
      /* Scan extensions. */
      /* Scan extensions. */
      do
      do
        {
        {
          *input_line_pointer++ = saved_char;
          *input_line_pointer++ = saved_char;
          if (!*input_line_pointer || ISSPACE (*input_line_pointer))
          if (!*input_line_pointer || ISSPACE (*input_line_pointer))
            break;
            break;
          name = input_line_pointer;
          name = input_line_pointer;
          while (*input_line_pointer && *input_line_pointer != ','
          while (*input_line_pointer && *input_line_pointer != ','
                 && !ISSPACE (*input_line_pointer))
                 && !ISSPACE (*input_line_pointer))
            input_line_pointer++;
            input_line_pointer++;
          saved_char = *input_line_pointer;
          saved_char = *input_line_pointer;
          *input_line_pointer = 0;
          *input_line_pointer = 0;
        }
        }
      while (m68k_set_extension (name, 1, 0));
      while (m68k_set_extension (name, 1, 0));
    }
    }
 
 
  *input_line_pointer = saved_char;
  *input_line_pointer = saved_char;
  demand_empty_rest_of_line ();
  demand_empty_rest_of_line ();
  return;
  return;
}
}


/* Lookup a cpu name in TABLE and return the slot found.  Return NULL
/* Lookup a cpu name in TABLE and return the slot found.  Return NULL
   if none is found, the caller is responsible for emitting an error
   if none is found, the caller is responsible for emitting an error
   message.  If ALLOW_M is non-zero, we allow an initial 'm' on the
   message.  If ALLOW_M is non-zero, we allow an initial 'm' on the
   cpu name, if it begins with a '6' (possibly skipping an intervening
   cpu name, if it begins with a '6' (possibly skipping an intervening
   'c'.  We also allow a 'c' in the same place.  if NEGATED is
   'c'.  We also allow a 'c' in the same place.  if NEGATED is
   non-zero, we accept a leading 'no-' and *NEGATED is set to true, if
   non-zero, we accept a leading 'no-' and *NEGATED is set to true, if
   the option is indeed negated.  */
   the option is indeed negated.  */
 
 
static const struct m68k_cpu *
static const struct m68k_cpu *
m68k_lookup_cpu (const char *arg, const struct m68k_cpu *table,
m68k_lookup_cpu (const char *arg, const struct m68k_cpu *table,
                 int allow_m, int *negated)
                 int allow_m, int *negated)
{
{
  /* allow negated value? */
  /* allow negated value? */
  if (negated)
  if (negated)
    {
    {
      *negated = 0;
      *negated = 0;
 
 
      if (arg[0] == 'n' && arg[1] == 'o' && arg[2] == '-')
      if (arg[0] == 'n' && arg[1] == 'o' && arg[2] == '-')
        {
        {
          arg += 3;
          arg += 3;
          *negated = 1;
          *negated = 1;
        }
        }
    }
    }
 
 
  /* Remove 'm' or 'mc' prefix from 68k variants.  */
  /* Remove 'm' or 'mc' prefix from 68k variants.  */
  if (allow_m)
  if (allow_m)
    {
    {
      if (arg[0] == 'm')
      if (arg[0] == 'm')
        {
        {
          if (arg[1] == '6')
          if (arg[1] == '6')
            arg += 1;
            arg += 1;
          else if (arg[1] == 'c'  && arg[2] == '6')
          else if (arg[1] == 'c'  && arg[2] == '6')
            arg += 2;
            arg += 2;
        }
        }
    }
    }
  else if (arg[0] == 'c' && arg[1] == '6')
  else if (arg[0] == 'c' && arg[1] == '6')
    arg += 1;
    arg += 1;
 
 
  for (; table->name; table++)
  for (; table->name; table++)
    if (!strcmp (arg, table->name))
    if (!strcmp (arg, table->name))
      {
      {
        if (table->alias < -1 || table->alias > 1)
        if (table->alias < -1 || table->alias > 1)
          as_bad (_("`%s' is deprecated, use `%s'"),
          as_bad (_("`%s' is deprecated, use `%s'"),
                  table->name, table[table->alias < 0 ? 1 : -1].name);
                  table->name, table[table->alias < 0 ? 1 : -1].name);
        return table;
        return table;
      }
      }
  return 0;
  return 0;
}
}
 
 
/* Set the cpu, issuing errors if it is unrecognized, or invalid */
/* Set the cpu, issuing errors if it is unrecognized, or invalid */
 
 
static int
static int
m68k_set_cpu (char const *name, int allow_m, int silent)
m68k_set_cpu (char const *name, int allow_m, int silent)
{
{
  const struct m68k_cpu *cpu;
  const struct m68k_cpu *cpu;
 
 
  cpu = m68k_lookup_cpu (name, m68k_cpus, allow_m, NULL);
  cpu = m68k_lookup_cpu (name, m68k_cpus, allow_m, NULL);
 
 
  if (!cpu)
  if (!cpu)
    {
    {
      if (!silent)
      if (!silent)
        as_bad (_("cpu `%s' unrecognized"), name);
        as_bad (_("cpu `%s' unrecognized"), name);
      return 0;
      return 0;
    }
    }
 
 
  if (selected_cpu && selected_cpu != cpu)
  if (selected_cpu && selected_cpu != cpu)
    {
    {
      as_bad (_("already selected `%s' processor"),
      as_bad (_("already selected `%s' processor"),
              selected_cpu->name);
              selected_cpu->name);
      return 0;
      return 0;
    }
    }
  selected_cpu = cpu;
  selected_cpu = cpu;
  return 1;
  return 1;
}
}
 
 
/* Set the architecture, issuing errors if it is unrecognized, or invalid */
/* Set the architecture, issuing errors if it is unrecognized, or invalid */
 
 
static int
static int
m68k_set_arch (char const *name, int allow_m, int silent)
m68k_set_arch (char const *name, int allow_m, int silent)
{
{
  const struct m68k_cpu *arch;
  const struct m68k_cpu *arch;
 
 
  arch = m68k_lookup_cpu (name, m68k_archs, allow_m, NULL);
  arch = m68k_lookup_cpu (name, m68k_archs, allow_m, NULL);
 
 
  if (!arch)
  if (!arch)
    {
    {
      if (!silent)
      if (!silent)
        as_bad (_("architecture `%s' unrecognized"), name);
        as_bad (_("architecture `%s' unrecognized"), name);
      return 0;
      return 0;
    }
    }
 
 
  if (selected_arch && selected_arch != arch)
  if (selected_arch && selected_arch != arch)
    {
    {
      as_bad (_("already selected `%s' architecture"),
      as_bad (_("already selected `%s' architecture"),
              selected_arch->name);
              selected_arch->name);
      return 0;
      return 0;
    }
    }
 
 
  selected_arch = arch;
  selected_arch = arch;
  return 1;
  return 1;
}
}
 
 
/* Set the architecture extension, issuing errors if it is
/* Set the architecture extension, issuing errors if it is
   unrecognized, or invalid */
   unrecognized, or invalid */
 
 
static int
static int
m68k_set_extension (char const *name, int allow_m, int silent)
m68k_set_extension (char const *name, int allow_m, int silent)
{
{
  int negated;
  int negated;
  const struct m68k_cpu *ext;
  const struct m68k_cpu *ext;
 
 
  ext = m68k_lookup_cpu (name, m68k_extensions, allow_m, &negated);
  ext = m68k_lookup_cpu (name, m68k_extensions, allow_m, &negated);
 
 
  if (!ext)
  if (!ext)
    {
    {
      if (!silent)
      if (!silent)
        as_bad (_("extension `%s' unrecognized"), name);
        as_bad (_("extension `%s' unrecognized"), name);
      return 0;
      return 0;
    }
    }
 
 
  if (negated)
  if (negated)
    not_current_architecture |= ext->arch;
    not_current_architecture |= ext->arch;
  else
  else
    current_architecture |= ext->arch;
    current_architecture |= ext->arch;
  return 1;
  return 1;
}
}
 
 
/* md_parse_option
/* md_parse_option
   Invocation line includes a switch not recognized by the base assembler.
   Invocation line includes a switch not recognized by the base assembler.
 */
 */
 
 
#ifdef OBJ_ELF
#ifdef OBJ_ELF
const char *md_shortopts = "lSA:m:kQ:V";
const char *md_shortopts = "lSA:m:kQ:V";
#else
#else
const char *md_shortopts = "lSA:m:k";
const char *md_shortopts = "lSA:m:k";
#endif
#endif
 
 
struct option md_longopts[] = {
struct option md_longopts[] = {
#define OPTION_PIC (OPTION_MD_BASE)
#define OPTION_PIC (OPTION_MD_BASE)
  {"pic", no_argument, NULL, OPTION_PIC},
  {"pic", no_argument, NULL, OPTION_PIC},
#define OPTION_REGISTER_PREFIX_OPTIONAL (OPTION_MD_BASE + 1)
#define OPTION_REGISTER_PREFIX_OPTIONAL (OPTION_MD_BASE + 1)
  {"register-prefix-optional", no_argument, NULL,
  {"register-prefix-optional", no_argument, NULL,
     OPTION_REGISTER_PREFIX_OPTIONAL},
     OPTION_REGISTER_PREFIX_OPTIONAL},
#define OPTION_BITWISE_OR (OPTION_MD_BASE + 2)
#define OPTION_BITWISE_OR (OPTION_MD_BASE + 2)
  {"bitwise-or", no_argument, NULL, OPTION_BITWISE_OR},
  {"bitwise-or", no_argument, NULL, OPTION_BITWISE_OR},
#define OPTION_BASE_SIZE_DEFAULT_16 (OPTION_MD_BASE + 3)
#define OPTION_BASE_SIZE_DEFAULT_16 (OPTION_MD_BASE + 3)
  {"base-size-default-16", no_argument, NULL, OPTION_BASE_SIZE_DEFAULT_16},
  {"base-size-default-16", no_argument, NULL, OPTION_BASE_SIZE_DEFAULT_16},
#define OPTION_BASE_SIZE_DEFAULT_32 (OPTION_MD_BASE + 4)
#define OPTION_BASE_SIZE_DEFAULT_32 (OPTION_MD_BASE + 4)
  {"base-size-default-32", no_argument, NULL, OPTION_BASE_SIZE_DEFAULT_32},
  {"base-size-default-32", no_argument, NULL, OPTION_BASE_SIZE_DEFAULT_32},
#define OPTION_DISP_SIZE_DEFAULT_16 (OPTION_MD_BASE + 5)
#define OPTION_DISP_SIZE_DEFAULT_16 (OPTION_MD_BASE + 5)
  {"disp-size-default-16", no_argument, NULL, OPTION_DISP_SIZE_DEFAULT_16},
  {"disp-size-default-16", no_argument, NULL, OPTION_DISP_SIZE_DEFAULT_16},
#define OPTION_DISP_SIZE_DEFAULT_32 (OPTION_MD_BASE + 6)
#define OPTION_DISP_SIZE_DEFAULT_32 (OPTION_MD_BASE + 6)
  {"disp-size-default-32", no_argument, NULL, OPTION_DISP_SIZE_DEFAULT_32},
  {"disp-size-default-32", no_argument, NULL, OPTION_DISP_SIZE_DEFAULT_32},
#define OPTION_PCREL (OPTION_MD_BASE + 7)
#define OPTION_PCREL (OPTION_MD_BASE + 7)
  {"pcrel", no_argument, NULL, OPTION_PCREL},
  {"pcrel", no_argument, NULL, OPTION_PCREL},
  {NULL, no_argument, NULL, 0}
  {NULL, no_argument, NULL, 0}
};
};
size_t md_longopts_size = sizeof (md_longopts);
size_t md_longopts_size = sizeof (md_longopts);
 
 
int
int
md_parse_option (int c, char *arg)
md_parse_option (int c, char *arg)
{
{
  switch (c)
  switch (c)
    {
    {
    case 'l':                   /* -l means keep external to 2 bit offset
    case 'l':                   /* -l means keep external to 2 bit offset
                                   rather than 16 bit one.  */
                                   rather than 16 bit one.  */
      flag_short_refs = 1;
      flag_short_refs = 1;
      break;
      break;
 
 
    case 'S':                   /* -S means that jbsr's always turn into
    case 'S':                   /* -S means that jbsr's always turn into
                                   jsr's.  */
                                   jsr's.  */
      flag_long_jumps = 1;
      flag_long_jumps = 1;
      break;
      break;
 
 
    case OPTION_PCREL:          /* --pcrel means never turn PC-relative
    case OPTION_PCREL:          /* --pcrel means never turn PC-relative
                                   branches into absolute jumps.  */
                                   branches into absolute jumps.  */
      flag_keep_pcrel = 1;
      flag_keep_pcrel = 1;
      break;
      break;
 
 
    case OPTION_PIC:
    case OPTION_PIC:
    case 'k':
    case 'k':
      flag_want_pic = 1;
      flag_want_pic = 1;
      break;                    /* -pic, Position Independent Code.  */
      break;                    /* -pic, Position Independent Code.  */
 
 
    case OPTION_REGISTER_PREFIX_OPTIONAL:
    case OPTION_REGISTER_PREFIX_OPTIONAL:
      flag_reg_prefix_optional = 1;
      flag_reg_prefix_optional = 1;
      reg_prefix_optional_seen = 1;
      reg_prefix_optional_seen = 1;
      break;
      break;
 
 
      /* -V: SVR4 argument to print version ID.  */
      /* -V: SVR4 argument to print version ID.  */
    case 'V':
    case 'V':
      print_version_id ();
      print_version_id ();
      break;
      break;
 
 
      /* -Qy, -Qn: SVR4 arguments controlling whether a .comment section
      /* -Qy, -Qn: SVR4 arguments controlling whether a .comment section
         should be emitted or not.  FIXME: Not implemented.  */
         should be emitted or not.  FIXME: Not implemented.  */
    case 'Q':
    case 'Q':
      break;
      break;
 
 
    case OPTION_BITWISE_OR:
    case OPTION_BITWISE_OR:
      {
      {
        char *n, *t;
        char *n, *t;
        const char *s;
        const char *s;
 
 
        n = (char *) xmalloc (strlen (m68k_comment_chars) + 1);
        n = (char *) xmalloc (strlen (m68k_comment_chars) + 1);
        t = n;
        t = n;
        for (s = m68k_comment_chars; *s != '\0'; s++)
        for (s = m68k_comment_chars; *s != '\0'; s++)
          if (*s != '|')
          if (*s != '|')
            *t++ = *s;
            *t++ = *s;
        *t = '\0';
        *t = '\0';
        m68k_comment_chars = n;
        m68k_comment_chars = n;
      }
      }
      break;
      break;
 
 
    case OPTION_BASE_SIZE_DEFAULT_16:
    case OPTION_BASE_SIZE_DEFAULT_16:
      m68k_index_width_default = SIZE_WORD;
      m68k_index_width_default = SIZE_WORD;
      break;
      break;
 
 
    case OPTION_BASE_SIZE_DEFAULT_32:
    case OPTION_BASE_SIZE_DEFAULT_32:
      m68k_index_width_default = SIZE_LONG;
      m68k_index_width_default = SIZE_LONG;
      break;
      break;
 
 
    case OPTION_DISP_SIZE_DEFAULT_16:
    case OPTION_DISP_SIZE_DEFAULT_16:
      m68k_rel32 = 0;
      m68k_rel32 = 0;
      m68k_rel32_from_cmdline = 1;
      m68k_rel32_from_cmdline = 1;
      break;
      break;
 
 
    case OPTION_DISP_SIZE_DEFAULT_32:
    case OPTION_DISP_SIZE_DEFAULT_32:
      m68k_rel32 = 1;
      m68k_rel32 = 1;
      m68k_rel32_from_cmdline = 1;
      m68k_rel32_from_cmdline = 1;
      break;
      break;
 
 
    case 'A':
    case 'A':
#if WARN_DEPRECATED
#if WARN_DEPRECATED
      as_tsktsk (_ ("option `-A%s' is deprecated: use `-%s'",
      as_tsktsk (_ ("option `-A%s' is deprecated: use `-%s'",
                    arg, arg));
                    arg, arg));
#endif
#endif
      /* Intentional fall-through.  */
      /* Intentional fall-through.  */
    case 'm':
    case 'm':
      if (!strncmp (arg, "arch=", 5))
      if (!strncmp (arg, "arch=", 5))
        m68k_set_arch (arg + 5, 1, 0);
        m68k_set_arch (arg + 5, 1, 0);
      else if (!strncmp (arg, "cpu=", 4))
      else if (!strncmp (arg, "cpu=", 4))
        m68k_set_cpu (arg + 4, 1, 0);
        m68k_set_cpu (arg + 4, 1, 0);
      else if (m68k_set_extension (arg, 0, 1))
      else if (m68k_set_extension (arg, 0, 1))
        ;
        ;
      else if (m68k_set_arch (arg, 0, 1))
      else if (m68k_set_arch (arg, 0, 1))
        ;
        ;
      else if (m68k_set_cpu (arg, 0, 1))
      else if (m68k_set_cpu (arg, 0, 1))
        ;
        ;
      else
      else
        return 0;
        return 0;
      break;
      break;
 
 
    default:
    default:
      return 0;
      return 0;
    }
    }
 
 
  return 1;
  return 1;
}
}
 
 
/* Setup tables from the selected arch and/or cpu */
/* Setup tables from the selected arch and/or cpu */
 
 
static void
static void
m68k_init_arch (void)
m68k_init_arch (void)
{
{
  if (not_current_architecture & current_architecture)
  if (not_current_architecture & current_architecture)
    {
    {
      as_bad (_("architecture features both enabled and disabled"));
      as_bad (_("architecture features both enabled and disabled"));
      not_current_architecture &= ~current_architecture;
      not_current_architecture &= ~current_architecture;
    }
    }
  if (selected_arch)
  if (selected_arch)
    {
    {
      current_architecture |= selected_arch->arch;
      current_architecture |= selected_arch->arch;
      control_regs = selected_arch->control_regs;
      control_regs = selected_arch->control_regs;
    }
    }
  else
  else
    current_architecture |= selected_cpu->arch;
    current_architecture |= selected_cpu->arch;
 
 
  current_architecture &= ~not_current_architecture;
  current_architecture &= ~not_current_architecture;
 
 
  if ((current_architecture & (cfloat | m68881)) == (cfloat | m68881))
  if ((current_architecture & (cfloat | m68881)) == (cfloat | m68881))
    {
    {
      /* Determine which float is really meant.  */
      /* Determine which float is really meant.  */
      if (current_architecture & (m68k_mask & ~m68881))
      if (current_architecture & (m68k_mask & ~m68881))
        current_architecture ^= cfloat;
        current_architecture ^= cfloat;
      else
      else
        current_architecture ^= m68881;
        current_architecture ^= m68881;
    }
    }
 
 
  if (selected_cpu)
  if (selected_cpu)
    {
    {
      control_regs = selected_cpu->control_regs;
      control_regs = selected_cpu->control_regs;
      if (current_architecture & ~selected_cpu->arch)
      if (current_architecture & ~selected_cpu->arch)
        {
        {
          as_bad (_("selected processor does not have all features of selected architecture"));
          as_bad (_("selected processor does not have all features of selected architecture"));
          current_architecture
          current_architecture
            = selected_cpu->arch & ~not_current_architecture;
            = selected_cpu->arch & ~not_current_architecture;
        }
        }
    }
    }
 
 
  if ((current_architecture & m68k_mask)
  if ((current_architecture & m68k_mask)
      && (current_architecture & ~m68k_mask))
      && (current_architecture & ~m68k_mask))
    {
    {
      as_bad (_ ("m68k and cf features both selected"));
      as_bad (_ ("m68k and cf features both selected"));
      if (current_architecture & m68k_mask)
      if (current_architecture & m68k_mask)
        current_architecture &= m68k_mask;
        current_architecture &= m68k_mask;
      else
      else
        current_architecture &= ~m68k_mask;
        current_architecture &= ~m68k_mask;
    }
    }
 
 
  /* Permit m68881 specification with all cpus; those that can't work
  /* Permit m68881 specification with all cpus; those that can't work
     with a coprocessor could be doing emulation.  */
     with a coprocessor could be doing emulation.  */
  if (current_architecture & m68851)
  if (current_architecture & m68851)
    {
    {
      if (current_architecture & m68040)
      if (current_architecture & m68040)
        as_warn (_("68040 and 68851 specified; mmu instructions may assemble incorrectly"));
        as_warn (_("68040 and 68851 specified; mmu instructions may assemble incorrectly"));
    }
    }
  /* What other incompatibilities could we check for?  */
  /* What other incompatibilities could we check for?  */
 
 
  if (cpu_of_arch (current_architecture) < m68020
  if (cpu_of_arch (current_architecture) < m68020
      || arch_coldfire_p (current_architecture))
      || arch_coldfire_p (current_architecture))
    md_relax_table[TAB (PCINDEX, BYTE)].rlx_more = 0;
    md_relax_table[TAB (PCINDEX, BYTE)].rlx_more = 0;
 
 
  initialized = 1;
  initialized = 1;
}
}
 
 
void
void
md_show_usage (FILE *stream)
md_show_usage (FILE *stream)
{
{
  const char *default_cpu = TARGET_CPU;
  const char *default_cpu = TARGET_CPU;
  int i;
  int i;
  unsigned int default_arch;
  unsigned int default_arch;
 
 
  /* Get the canonical name for the default target CPU.  */
  /* Get the canonical name for the default target CPU.  */
  if (*default_cpu == 'm')
  if (*default_cpu == 'm')
    default_cpu++;
    default_cpu++;
  for (i = 0; m68k_cpus[i].name; i++)
  for (i = 0; m68k_cpus[i].name; i++)
    {
    {
      if (strcasecmp (default_cpu, m68k_cpus[i].name) == 0)
      if (strcasecmp (default_cpu, m68k_cpus[i].name) == 0)
        {
        {
          default_arch = m68k_cpus[i].arch;
          default_arch = m68k_cpus[i].arch;
          while (m68k_cpus[i].alias > 0)
          while (m68k_cpus[i].alias > 0)
            i--;
            i--;
          while (m68k_cpus[i].alias < 0)
          while (m68k_cpus[i].alias < 0)
            i++;
            i++;
          default_cpu = m68k_cpus[i].name;
          default_cpu = m68k_cpus[i].name;
        }
        }
    }
    }
 
 
  fprintf (stream, _("\
  fprintf (stream, _("\
-march=<arch>           set architecture\n\
-march=<arch>           set architecture\n\
-mcpu=<cpu>             set cpu [default %s]\n\
-mcpu=<cpu>             set cpu [default %s]\n\
"), default_cpu);
"), default_cpu);
  for (i = 0; m68k_extensions[i].name; i++)
  for (i = 0; m68k_extensions[i].name; i++)
    fprintf (stream, _("\
    fprintf (stream, _("\
-m[no-]%-16s enable/disable%s architecture extension\n\
-m[no-]%-16s enable/disable%s architecture extension\n\
"), m68k_extensions[i].name,
"), m68k_extensions[i].name,
             m68k_extensions[i].alias > 0 ? " ColdFire"
             m68k_extensions[i].alias > 0 ? " ColdFire"
             : m68k_extensions[i].alias < 0 ? " m68k" : "");
             : m68k_extensions[i].alias < 0 ? " m68k" : "");
 
 
  fprintf (stream, _("\
  fprintf (stream, _("\
-l                      use 1 word for refs to undefined symbols [default 2]\n\
-l                      use 1 word for refs to undefined symbols [default 2]\n\
-pic, -k                generate position independent code\n\
-pic, -k                generate position independent code\n\
-S                      turn jbsr into jsr\n\
-S                      turn jbsr into jsr\n\
--pcrel                 never turn PC-relative branches into absolute jumps\n\
--pcrel                 never turn PC-relative branches into absolute jumps\n\
--register-prefix-optional\n\
--register-prefix-optional\n\
                        recognize register names without prefix character\n\
                        recognize register names without prefix character\n\
--bitwise-or            do not treat `|' as a comment character\n\
--bitwise-or            do not treat `|' as a comment character\n\
--base-size-default-16  base reg without size is 16 bits\n\
--base-size-default-16  base reg without size is 16 bits\n\
--base-size-default-32  base reg without size is 32 bits (default)\n\
--base-size-default-32  base reg without size is 32 bits (default)\n\
--disp-size-default-16  displacement with unknown size is 16 bits\n\
--disp-size-default-16  displacement with unknown size is 16 bits\n\
--disp-size-default-32  displacement with unknown size is 32 bits (default)\n\
--disp-size-default-32  displacement with unknown size is 32 bits (default)\n\
"));
"));
 
 
  fprintf (stream, _("Architecture variants are: "));
  fprintf (stream, _("Architecture variants are: "));
  for (i = 0; m68k_archs[i].name; i++)
  for (i = 0; m68k_archs[i].name; i++)
    {
    {
      if (i)
      if (i)
        fprintf (stream, " | ");
        fprintf (stream, " | ");
      fprintf (stream, m68k_archs[i].name);
      fprintf (stream, m68k_archs[i].name);
    }
    }
  fprintf (stream, "\n");
  fprintf (stream, "\n");
 
 
  fprintf (stream, _("Processor variants are: "));
  fprintf (stream, _("Processor variants are: "));
  for (i = 0; m68k_cpus[i].name; i++)
  for (i = 0; m68k_cpus[i].name; i++)
    {
    {
      if (i)
      if (i)
        fprintf (stream, " | ");
        fprintf (stream, " | ");
      fprintf (stream, m68k_cpus[i].name);
      fprintf (stream, m68k_cpus[i].name);
    }
    }
  fprintf (stream, _("\n"));
  fprintf (stream, _("\n"));
}
}


#ifdef TEST2
#ifdef TEST2
 
 
/* TEST2:  Test md_assemble() */
/* TEST2:  Test md_assemble() */
/* Warning, this routine probably doesn't work anymore.  */
/* Warning, this routine probably doesn't work anymore.  */
int
int
main (void)
main (void)
{
{
  struct m68k_it the_ins;
  struct m68k_it the_ins;
  char buf[120];
  char buf[120];
  char *cp;
  char *cp;
  int n;
  int n;
 
 
  m68k_ip_begin ();
  m68k_ip_begin ();
  for (;;)
  for (;;)
    {
    {
      if (!gets (buf) || !*buf)
      if (!gets (buf) || !*buf)
        break;
        break;
      if (buf[0] == '|' || buf[1] == '.')
      if (buf[0] == '|' || buf[1] == '.')
        continue;
        continue;
      for (cp = buf; *cp; cp++)
      for (cp = buf; *cp; cp++)
        if (*cp == '\t')
        if (*cp == '\t')
          *cp = ' ';
          *cp = ' ';
      if (is_label (buf))
      if (is_label (buf))
        continue;
        continue;
      memset (&the_ins, '\0', sizeof (the_ins));
      memset (&the_ins, '\0', sizeof (the_ins));
      m68k_ip (&the_ins, buf);
      m68k_ip (&the_ins, buf);
      if (the_ins.error)
      if (the_ins.error)
        {
        {
          printf (_("Error %s in %s\n"), the_ins.error, buf);
          printf (_("Error %s in %s\n"), the_ins.error, buf);
        }
        }
      else
      else
        {
        {
          printf (_("Opcode(%d.%s): "), the_ins.numo, the_ins.args);
          printf (_("Opcode(%d.%s): "), the_ins.numo, the_ins.args);
          for (n = 0; n < the_ins.numo; n++)
          for (n = 0; n < the_ins.numo; n++)
            printf (" 0x%x", the_ins.opcode[n] & 0xffff);
            printf (" 0x%x", the_ins.opcode[n] & 0xffff);
          printf ("    ");
          printf ("    ");
          print_the_insn (&the_ins.opcode[0], stdout);
          print_the_insn (&the_ins.opcode[0], stdout);
          (void) putchar ('\n');
          (void) putchar ('\n');
        }
        }
      for (n = 0; n < strlen (the_ins.args) / 2; n++)
      for (n = 0; n < strlen (the_ins.args) / 2; n++)
        {
        {
          if (the_ins.operands[n].error)
          if (the_ins.operands[n].error)
            {
            {
              printf ("op%d Error %s in %s\n", n, the_ins.operands[n].error, buf);
              printf ("op%d Error %s in %s\n", n, the_ins.operands[n].error, buf);
              continue;
              continue;
            }
            }
          printf ("mode %d, reg %d, ", the_ins.operands[n].mode,
          printf ("mode %d, reg %d, ", the_ins.operands[n].mode,
                  the_ins.operands[n].reg);
                  the_ins.operands[n].reg);
          if (the_ins.operands[n].b_const)
          if (the_ins.operands[n].b_const)
            printf ("Constant: '%.*s', ",
            printf ("Constant: '%.*s', ",
                    1 + the_ins.operands[n].e_const - the_ins.operands[n].b_const,
                    1 + the_ins.operands[n].e_const - the_ins.operands[n].b_const,
                    the_ins.operands[n].b_const);
                    the_ins.operands[n].b_const);
          printf ("ireg %d, isiz %d, imul %d, ", the_ins.operands[n].ireg,
          printf ("ireg %d, isiz %d, imul %d, ", the_ins.operands[n].ireg,
                  the_ins.operands[n].isiz, the_ins.operands[n].imul);
                  the_ins.operands[n].isiz, the_ins.operands[n].imul);
          if (the_ins.operands[n].b_iadd)
          if (the_ins.operands[n].b_iadd)
            printf ("Iadd: '%.*s',",
            printf ("Iadd: '%.*s',",
                    1 + the_ins.operands[n].e_iadd - the_ins.operands[n].b_iadd,
                    1 + the_ins.operands[n].e_iadd - the_ins.operands[n].b_iadd,
                    the_ins.operands[n].b_iadd);
                    the_ins.operands[n].b_iadd);
          putchar ('\n');
          putchar ('\n');
        }
        }
    }
    }
  m68k_ip_end ();
  m68k_ip_end ();
  return 0;
  return 0;
}
}
 
 
int
int
is_label (char *str)
is_label (char *str)
{
{
  while (*str == ' ')
  while (*str == ' ')
    str++;
    str++;
  while (*str && *str != ' ')
  while (*str && *str != ' ')
    str++;
    str++;
  if (str[-1] == ':' || str[1] == '=')
  if (str[-1] == ':' || str[1] == '=')
    return 1;
    return 1;
  return 0;
  return 0;
}
}
 
 
#endif
#endif
 
 
/* Possible states for relaxation:
/* Possible states for relaxation:
 
 
   0 0  branch offset   byte    (bra, etc)
   0 0  branch offset   byte    (bra, etc)
   0 1                  word
   0 1                  word
   0 2                  long
   0 2                  long
 
 
   1 0  indexed offsets byte    a0@(32,d4:w:1) etc
   1 0  indexed offsets byte    a0@(32,d4:w:1) etc
   1 1                  word
   1 1                  word
   1 2                  long
   1 2                  long
 
 
   2 0  two-offset index word-word a0@(32,d4)@(45) etc
   2 0  two-offset index word-word a0@(32,d4)@(45) etc
   2 1                  word-long
   2 1                  word-long
   2 2                  long-word
   2 2                  long-word
   2 3                  long-long
   2 3                  long-long
 
 
   */
   */
 
 
/* We have no need to default values of symbols.  */
/* We have no need to default values of symbols.  */
 
 
symbolS *
symbolS *
md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
{
{
  return 0;
  return 0;
}
}
 
 
/* Round up a section size to the appropriate boundary.  */
/* Round up a section size to the appropriate boundary.  */
valueT
valueT
md_section_align (segT segment ATTRIBUTE_UNUSED, valueT size)
md_section_align (segT segment ATTRIBUTE_UNUSED, valueT size)
{
{
#ifdef OBJ_AOUT
#ifdef OBJ_AOUT
  /* For a.out, force the section size to be aligned.  If we don't do
  /* For a.out, force the section size to be aligned.  If we don't do
     this, BFD will align it for us, but it will not write out the
     this, BFD will align it for us, but it will not write out the
     final bytes of the section.  This may be a bug in BFD, but it is
     final bytes of the section.  This may be a bug in BFD, but it is
     easier to fix it here since that is how the other a.out targets
     easier to fix it here since that is how the other a.out targets
     work.  */
     work.  */
  int align;
  int align;
 
 
  align = bfd_get_section_alignment (stdoutput, segment);
  align = bfd_get_section_alignment (stdoutput, segment);
  size = ((size + (1 << align) - 1) & ((valueT) -1 << align));
  size = ((size + (1 << align) - 1) & ((valueT) -1 << align));
#endif
#endif
 
 
  return size;
  return size;
}
}
 
 
/* Exactly what point is a PC-relative offset relative TO?
/* Exactly what point is a PC-relative offset relative TO?
   On the 68k, it is relative to the address of the first extension
   On the 68k, it is relative to the address of the first extension
   word.  The difference between the addresses of the offset and the
   word.  The difference between the addresses of the offset and the
   first extension word is stored in fx_pcrel_adjust.  */
   first extension word is stored in fx_pcrel_adjust.  */
long
long
md_pcrel_from (fixS *fixP)
md_pcrel_from (fixS *fixP)
{
{
  int adjust;
  int adjust;
 
 
  /* Because fx_pcrel_adjust is a char, and may be unsigned, we explicitly
  /* Because fx_pcrel_adjust is a char, and may be unsigned, we explicitly
     sign extend the value here.  */
     sign extend the value here.  */
  adjust = ((fixP->fx_pcrel_adjust & 0xff) ^ 0x80) - 0x80;
  adjust = ((fixP->fx_pcrel_adjust & 0xff) ^ 0x80) - 0x80;
  if (adjust == 64)
  if (adjust == 64)
    adjust = -1;
    adjust = -1;
  return fixP->fx_where + fixP->fx_frag->fr_address - adjust;
  return fixP->fx_where + fixP->fx_frag->fr_address - adjust;
}
}
 
 
#ifdef OBJ_ELF
#ifdef OBJ_ELF
void
void
m68k_elf_final_processing (void)
m68k_elf_final_processing (void)
{
{
  unsigned flags = 0;
  unsigned flags = 0;
 
 
  if (arch_coldfire_fpu (current_architecture))
  if (arch_coldfire_fpu (current_architecture))
    flags |= EF_M68K_CFV4E;
    flags |= EF_M68K_CFV4E;
  /* Set file-specific flags if this is a cpu32 processor.  */
  /* Set file-specific flags if this is a cpu32 processor.  */
  if (cpu_of_arch (current_architecture) & cpu32)
  if (cpu_of_arch (current_architecture) & cpu32)
    flags |= EF_M68K_CPU32;
    flags |= EF_M68K_CPU32;
  else if (cpu_of_arch (current_architecture) & fido_a)
  else if (cpu_of_arch (current_architecture) & fido_a)
    flags |= EF_M68K_FIDO;
    flags |= EF_M68K_FIDO;
  else if ((cpu_of_arch (current_architecture) & m68000up)
  else if ((cpu_of_arch (current_architecture) & m68000up)
           && !(cpu_of_arch (current_architecture) & m68020up))
           && !(cpu_of_arch (current_architecture) & m68020up))
    flags |= EF_M68K_M68000;
    flags |= EF_M68K_M68000;
 
 
  if (current_architecture & mcfisa_a)
  if (current_architecture & mcfisa_a)
    {
    {
      static const unsigned isa_features[][2] =
      static const unsigned isa_features[][2] =
      {
      {
        {EF_M68K_CF_ISA_A_NODIV,mcfisa_a},
        {EF_M68K_CF_ISA_A_NODIV,mcfisa_a},
        {EF_M68K_CF_ISA_A,      mcfisa_a|mcfhwdiv},
        {EF_M68K_CF_ISA_A,      mcfisa_a|mcfhwdiv},
        {EF_M68K_CF_ISA_A_PLUS, mcfisa_a|mcfisa_aa|mcfhwdiv|mcfusp},
        {EF_M68K_CF_ISA_A_PLUS, mcfisa_a|mcfisa_aa|mcfhwdiv|mcfusp},
        {EF_M68K_CF_ISA_B_NOUSP,mcfisa_a|mcfisa_b|mcfhwdiv},
        {EF_M68K_CF_ISA_B_NOUSP,mcfisa_a|mcfisa_b|mcfhwdiv},
        {EF_M68K_CF_ISA_B,      mcfisa_a|mcfisa_b|mcfhwdiv|mcfusp},
        {EF_M68K_CF_ISA_B,      mcfisa_a|mcfisa_b|mcfhwdiv|mcfusp},
        {EF_M68K_CF_ISA_C,      mcfisa_a|mcfisa_c|mcfhwdiv|mcfusp},
        {EF_M68K_CF_ISA_C,      mcfisa_a|mcfisa_c|mcfhwdiv|mcfusp},
        {EF_M68K_CF_ISA_C_NODIV,mcfisa_a|mcfisa_c|mcfusp},
        {EF_M68K_CF_ISA_C_NODIV,mcfisa_a|mcfisa_c|mcfusp},
        {0,0},
        {0,0},
      };
      };
      static const unsigned mac_features[][2] =
      static const unsigned mac_features[][2] =
      {
      {
        {EF_M68K_CF_MAC, mcfmac},
        {EF_M68K_CF_MAC, mcfmac},
        {EF_M68K_CF_EMAC, mcfemac},
        {EF_M68K_CF_EMAC, mcfemac},
        {0,0},
        {0,0},
      };
      };
      unsigned ix;
      unsigned ix;
      unsigned pattern;
      unsigned pattern;
 
 
      pattern = (current_architecture
      pattern = (current_architecture
                 & (mcfisa_a|mcfisa_aa|mcfisa_b|mcfisa_c|mcfhwdiv|mcfusp));
                 & (mcfisa_a|mcfisa_aa|mcfisa_b|mcfisa_c|mcfhwdiv|mcfusp));
      for (ix = 0; isa_features[ix][1]; ix++)
      for (ix = 0; isa_features[ix][1]; ix++)
        {
        {
          if (pattern == isa_features[ix][1])
          if (pattern == isa_features[ix][1])
            {
            {
              flags |= isa_features[ix][0];
              flags |= isa_features[ix][0];
              break;
              break;
            }
            }
        }
        }
      if (!isa_features[ix][1])
      if (!isa_features[ix][1])
        {
        {
        cf_bad:
        cf_bad:
          as_warn (_("Not a defined coldfire architecture"));
          as_warn (_("Not a defined coldfire architecture"));
        }
        }
      else
      else
        {
        {
          if (current_architecture & cfloat)
          if (current_architecture & cfloat)
            flags |= EF_M68K_CF_FLOAT | EF_M68K_CFV4E;
            flags |= EF_M68K_CF_FLOAT | EF_M68K_CFV4E;
 
 
          pattern = current_architecture & (mcfmac|mcfemac);
          pattern = current_architecture & (mcfmac|mcfemac);
          if (pattern)
          if (pattern)
            {
            {
              for (ix = 0; mac_features[ix][1]; ix++)
              for (ix = 0; mac_features[ix][1]; ix++)
                {
                {
                  if (pattern == mac_features[ix][1])
                  if (pattern == mac_features[ix][1])
                    {
                    {
                      flags |= mac_features[ix][0];
                      flags |= mac_features[ix][0];
                      break;
                      break;
                    }
                    }
                }
                }
              if (!mac_features[ix][1])
              if (!mac_features[ix][1])
                goto cf_bad;
                goto cf_bad;
            }
            }
        }
        }
    }
    }
  elf_elfheader (stdoutput)->e_flags |= flags;
  elf_elfheader (stdoutput)->e_flags |= flags;
}
}
#endif
#endif
 
 
int
int
tc_m68k_regname_to_dw2regnum (char *regname)
tc_m68k_regname_to_dw2regnum (char *regname)
{
{
  unsigned int regnum;
  unsigned int regnum;
  static const char *const regnames[] =
  static const char *const regnames[] =
    {
    {
      "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
      "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
      "a0", "a1", "a2", "a3", "a4", "a5", "a6", "sp",
      "a0", "a1", "a2", "a3", "a4", "a5", "a6", "sp",
      "fp0", "fp1", "fp2", "fp3", "fp4", "fp5", "fp6", "fp7",
      "fp0", "fp1", "fp2", "fp3", "fp4", "fp5", "fp6", "fp7",
      "pc"
      "pc"
    };
    };
 
 
  for (regnum = 0; regnum < ARRAY_SIZE (regnames); regnum++)
  for (regnum = 0; regnum < ARRAY_SIZE (regnames); regnum++)
    if (strcmp (regname, regnames[regnum]) == 0)
    if (strcmp (regname, regnames[regnum]) == 0)
      return regnum;
      return regnum;
 
 
  return -1;
  return -1;
}
}
 
 
void
void
tc_m68k_frame_initial_instructions (void)
tc_m68k_frame_initial_instructions (void)
{
{
  static int sp_regno = -1;
  static int sp_regno = -1;
 
 
  if (sp_regno < 0)
  if (sp_regno < 0)
    sp_regno = tc_m68k_regname_to_dw2regnum ("sp");
    sp_regno = tc_m68k_regname_to_dw2regnum ("sp");
 
 
  cfi_add_CFA_def_cfa (sp_regno, -DWARF2_CIE_DATA_ALIGNMENT);
  cfi_add_CFA_def_cfa (sp_regno, -DWARF2_CIE_DATA_ALIGNMENT);
  cfi_add_CFA_offset (DWARF2_DEFAULT_RETURN_COLUMN, DWARF2_CIE_DATA_ALIGNMENT);
  cfi_add_CFA_offset (DWARF2_DEFAULT_RETURN_COLUMN, DWARF2_CIE_DATA_ALIGNMENT);
}
}
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.