/* tc-m68k.c -- Assemble for the m68k family
- Copyright (C) 1987, 91, 92, 93, 94, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1987, 91, 92, 93, 94, 95, 96, 97, 98, 1999
+ Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
02111-1307, USA. */
#include <ctype.h>
-#define NO_RELOC 0
#include "as.h"
#include "obstack.h"
#include "subsegs.h"
#include "opcode/m68k.h"
#include "m68k-parse.h"
-/* This array holds the chars that always start a comment. If the
- pre-processor is disabled, these aren't very useful */
-#ifdef OBJ_ELF
-CONST char comment_chars[] = "|#";
+#if defined (OBJ_ELF)
+#include "elf/m68k.h"
+#endif
+
+/* This string holds the chars that always start a comment. If the
+ pre-processor is disabled, these aren't very useful. The macro
+ tc_comment_chars points to this. We use this, rather than the
+ usual comment_chars, so that the --bitwise-or option will work. */
+#if defined (TE_SVR4) || defined (TE_DELTA)
+const char *m68k_comment_chars = "|#";
#else
-CONST char comment_chars[] = "|";
+const char *m68k_comment_chars = "|";
#endif
/* This array holds the chars that only start a comment at the beginning of
first line of the input file. This is because the compiler outputs
#NO_APP at the beginning of its output. */
/* 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 */
CONST char EXP_CHARS[] = "eE";
/* Are we trying to generate PIC code? If so, absolute references
ought to be made into linkage table references or pc-relative
- references. */
+ references. Not implemented. For ELF there are other means
+ to denote pic relocations. */
int flag_want_pic;
static int flag_short_refs; /* -l option */
int flag_reg_prefix_optional;
#endif
+/* Whether --register-prefix-optional was used on the command line. */
+static int reg_prefix_optional_seen;
+
/* The floating point coprocessor to use by default. */
static enum m68k_register m68k_float_copnum = COP1;
be 32 bits. */
static int m68k_rel32 = 1;
+/* This is non-zero if m68k_rel32 was set from the command line. */
+static int m68k_rel32_from_cmdline;
+
+/* The default width to use for an index register when using a base
+ displacement. */
+static enum m68k_size m68k_index_width_default = SIZE_LONG;
+
+/* 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
+ label. */
+
+struct label_line
+{
+ struct label_line *next;
+ symbolS *label;
+ char *file;
+ unsigned int line;
+ int text;
+};
+
+/* The list of labels. */
+
+static struct label_line *labels;
+
+/* The current label. */
+
+static struct label_line *current_label;
+
/* Its an arbitrary name: This means I don't approve of it */
/* See flames below */
static struct obstack robyn;
USP, VBR, URP, SRP, PCR,
0
};
+static const enum m68k_register mcf_control_regs[] = {
+ CACR, TC, ITT0, ITT1, DTT0, DTT1, VBR, ROMBAR,
+ RAMBAR0, RAMBAR1, MBAR,
+ 0
+};
#define cpu32_control_regs m68010_control_regs
static const enum m68k_register *control_regs;
{
int fragoff; /* Where in the current opcode the frag ends */
symbolS *fadd;
- long foff;
+ offsetT foff;
int fragty;
}
fragb[4];
significance of some values (in the branch instruction, for
example). */
int pcrel_fix;
+#ifdef OBJ_ELF
+ /* Whether this expression needs special pic relocation, and if
+ so, which. */
+ enum pic_relocation pic_reloc;
+#endif
}
reloc[5]; /* Five is enough??? */
};
-#define cpu_of_arch(x) ((x) & m68000up)
+#define cpu_of_arch(x) ((x) & (m68000up|mcf))
#define float_of_arch(x) ((x) & mfloat)
#define mmu_of_arch(x) ((x) & mmmu)
+#define arch_coldfire_p(x) (((x) & mcf) != 0)
+
+/* Macros for determining if cpu supports a specific addressing mode */
+#define HAVE_LONG_BRANCH(x) ((x) & (m68020|m68030|m68040|m68060|cpu32))
static struct m68k_it the_ins; /* the instruction being assembled */
#define addword(w) the_ins.opcode[the_ins.numo++]=(w)
+/* Static functions. */
+
+static void insop PARAMS ((int, const struct m68k_incant *));
+static void add_fix PARAMS ((int, struct m68k_exp *, int, int));
+static void add_frag PARAMS ((symbolS *, offsetT, int));
+
/* Like addword, but goes BEFORE general operands */
static void
insop (w, opcode)
int w;
- struct m68k_incant *opcode;
+ const struct m68k_incant *opcode;
{
int z;
for(z=the_ins.numo;z>opcode->m_codenum;--z)
Blecch. */
static void
add_fix (width, exp, pc_rel, pc_fix)
- char width;
+ int width;
struct m68k_exp *exp;
int pc_rel;
int pc_fix;
{
- the_ins.reloc[the_ins.nrel].n = (((width)=='B')
+ the_ins.reloc[the_ins.nrel].n = ((width == 'B' || width == '3')
? (the_ins.numo*2-1)
: (((width)=='b')
? (the_ins.numo*2+1)
the_ins.reloc[the_ins.nrel].exp = exp->exp;
the_ins.reloc[the_ins.nrel].wid = width;
the_ins.reloc[the_ins.nrel].pcrel_fix = pc_fix;
+#ifdef OBJ_ELF
+ the_ins.reloc[the_ins.nrel].pic_reloc = exp->pic_reloc;
+#endif
the_ins.reloc[the_ins.nrel++].pcrel = pc_rel;
}
ADD becomes the FR_SYMBOL field of the frag, and OFF the FR_OFFSET. */
static void
-add_frag(add,off,type)
+add_frag (add, off, type)
symbolS *add;
- long off;
+ offsetT off;
int type;
{
the_ins.fragb[the_ins.nfrag].fragoff=the_ins.numo;
static char *crack_operand PARAMS ((char *str, struct m68k_op *opP));
static int get_num PARAMS ((struct m68k_exp *exp, int ok));
+static void m68k_ip PARAMS ((char *));
+static void insert_reg PARAMS ((const char *, int));
+static void select_control_regs PARAMS ((void));
+static void init_regtable PARAMS ((void));
static int reverse_16_bits PARAMS ((int in));
static int reverse_8_bits PARAMS ((int in));
static void install_gen_operand PARAMS ((int mode, int val));
static void s_mri_until PARAMS ((int));
static void s_mri_while PARAMS ((int));
static void s_mri_endw PARAMS ((int));
+static void md_apply_fix_2 PARAMS ((fixS *, offsetT));
+static void md_convert_frag_1 PARAMS ((fragS *));
static int current_architecture;
struct m68k_cpu {
unsigned long arch;
const char *name;
+ int alias;
};
static const struct m68k_cpu archs[] = {
- { m68000, "68000" },
- { m68010, "68010" },
- { m68020, "68020" },
- { m68030, "68030" },
- { m68040, "68040" },
- { m68060, "68060" },
- { cpu32, "cpu32" },
- { m68881, "68881" },
- { m68851, "68851" },
+ { m68000, "68000", 0 },
+ { m68010, "68010", 0 },
+ { m68020, "68020", 0 },
+ { m68030, "68030", 0 },
+ { m68040, "68040", 0 },
+ { m68060, "68060", 0 },
+ { cpu32, "cpu32", 0 },
+ { m68881, "68881", 0 },
+ { m68851, "68851", 0 },
+ { mcf5200, "5200", 0 },
+ { mcf5206e, "5206e", 0 },
+ { mcf5307, "5307", 0},
/* Aliases (effectively, so far as gas is concerned) for the above
cpus. */
- { m68020, "68k" },
- { m68000, "68302" },
- { m68000, "68008" },
- { m68000, "68ec000" },
- { m68000, "68hc000" },
- { m68000, "68hc001" },
- { m68020, "68ec020" },
- { m68030, "68ec030" },
- { m68040, "68ec040" },
- { cpu32, "68330" },
- { cpu32, "68331" },
- { cpu32, "68332" },
- { cpu32, "68333" },
- { cpu32, "68340" },
- { cpu32, "68360" },
- { m68881, "68882" },
+ { m68020, "68k", 1 },
+ { m68000, "68008", 1 },
+ { m68000, "68302", 1 },
+ { m68000, "68306", 1 },
+ { m68000, "68307", 1 },
+ { m68000, "68322", 1 },
+ { m68000, "68356", 1 },
+ { m68000, "68ec000", 1 },
+ { m68000, "68hc000", 1 },
+ { m68000, "68hc001", 1 },
+ { m68020, "68ec020", 1 },
+ { m68030, "68ec030", 1 },
+ { m68040, "68ec040", 1 },
+ { m68060, "68ec060", 1 },
+ { cpu32, "68330", 1 },
+ { cpu32, "68331", 1 },
+ { cpu32, "68332", 1 },
+ { cpu32, "68333", 1 },
+ { cpu32, "68334", 1 },
+ { cpu32, "68336", 1 },
+ { cpu32, "68340", 1 },
+ { cpu32, "68341", 1 },
+ { cpu32, "68349", 1 },
+ { cpu32, "68360", 1 },
+ { m68881, "68882", 1 },
+ { mcf5200, "5202", 1 },
+ { mcf5200, "5204", 1 },
+ { mcf5200, "5206", 1 },
};
static const int n_archs = sizeof (archs) / sizeof (archs[0]);
function to call to execute this pseudo-op
Integer arg to pass to the function
*/
-CONST pseudo_typeS md_pseudo_table[] =
+const pseudo_typeS md_pseudo_table[] =
{
{"data1", s_data1, 0},
{"data2", s_data2, 0},
{"even", s_even, 0},
{"skip", s_space, 0},
{"proc", s_proc, 0},
-#ifdef TE_SUN3
+#if defined (TE_SUN3) || defined (OBJ_ELF)
{"align", s_align_bytes, 0},
#endif
#ifdef OBJ_ELF
{"swbeg", s_ignore, 0},
#endif
+ {"extend", float_cons, 'x'},
+ {"ldouble", float_cons, 'x'},
/* The following pseudo-ops are supported for MRI compatibility. */
{"chip", s_chip, 0},
/* The mote pseudo ops are put into the opcode table, since they
don't start with a . they look like opcodes to gas.
*/
-extern void obj_coff_section ();
+
+#ifdef M68KCOFF
+extern void obj_coff_section PARAMS ((int));
+#endif
CONST pseudo_typeS mote_pseudo_table[] =
{
{"dsb", s_space, 1},
{"xdef", s_globl, 0},
+#ifdef OBJ_ELF
+ {"align", s_align_bytes, 0},
+#else
{"align", s_align_ptwo, 0},
+#endif
#ifdef M68KCOFF
{"sect", obj_coff_section, 0},
{"section", obj_coff_section, 0},
#define isuword(x) ((x)>=0 && (x)<=65535)
#define isbyte(x) ((x)>= -255 && (x)<=255)
-#define isword(x) ((x)>=-32768 && (x)<=65535)
+#define isword(x) ((x)>=-65536 && (x)<=65535)
#define islong(x) (1)
extern char *input_line_pointer;
opcode[1] = 0xb9;
}
else
- as_fatal ("Unknown PC relative instruction");
+ as_fatal (_("Unknown PC relative instruction"));
*add_number -= 4;
return 0;
}
tc_coff_fix2rtype (fixP)
fixS *fixP;
{
+ if (fixP->fx_tcbit && fixP->fx_size == 4)
+ return R_RELLONG_NEG;
#ifdef NO_PCREL_RELOCS
know (fixP->fx_pcrel == 0);
return (fixP->fx_size == 1 ? R_RELBYTE
#endif
+#ifdef OBJ_ELF
+
+/* Compute the relocation code for a fixup of SIZE bytes, using pc
+ relative relocation if PCREL is non-zero. PIC says whether a special
+ pic relocation was requested. */
+
+static bfd_reloc_code_real_type get_reloc_code
+ PARAMS ((int, int, enum pic_relocation));
+
+static bfd_reloc_code_real_type
+get_reloc_code (size, pcrel, pic)
+ int size;
+ int pcrel;
+ enum pic_relocation pic;
+{
+ switch (pic)
+ {
+ case pic_got_pcrel:
+ switch (size)
+ {
+ case 1:
+ return BFD_RELOC_8_GOT_PCREL;
+ case 2:
+ return BFD_RELOC_16_GOT_PCREL;
+ case 4:
+ return BFD_RELOC_32_GOT_PCREL;
+ }
+ break;
+
+ case pic_got_off:
+ switch (size)
+ {
+ case 1:
+ return BFD_RELOC_8_GOTOFF;
+ case 2:
+ return BFD_RELOC_16_GOTOFF;
+ case 4:
+ return BFD_RELOC_32_GOTOFF;
+ }
+ break;
+
+ case pic_plt_pcrel:
+ switch (size)
+ {
+ case 1:
+ return BFD_RELOC_8_PLT_PCREL;
+ case 2:
+ return BFD_RELOC_16_PLT_PCREL;
+ case 4:
+ return BFD_RELOC_32_PLT_PCREL;
+ }
+ break;
+
+ case pic_plt_off:
+ switch (size)
+ {
+ case 1:
+ return BFD_RELOC_8_PLTOFF;
+ case 2:
+ return BFD_RELOC_16_PLTOFF;
+ case 4:
+ return BFD_RELOC_32_PLTOFF;
+ }
+ break;
+
+ case pic_none:
+ if (pcrel)
+ {
+ switch (size)
+ {
+ case 1:
+ return BFD_RELOC_8_PCREL;
+ case 2:
+ return BFD_RELOC_16_PCREL;
+ case 4:
+ return BFD_RELOC_32_PCREL;
+ }
+ }
+ else
+ {
+ switch (size)
+ {
+ case 1:
+ return BFD_RELOC_8;
+ case 2:
+ return BFD_RELOC_16;
+ case 4:
+ return BFD_RELOC_32;
+ }
+ }
+ }
+
+ if (pcrel)
+ {
+ if (pic == pic_none)
+ as_bad (_("Can not do %d byte pc-relative relocation"), size);
+ else
+ as_bad (_("Can not do %d byte pc-relative pic relocation"), size);
+ }
+ else
+ {
+ if (pic == pic_none)
+ as_bad (_("Can not do %d byte relocation"), size);
+ else
+ as_bad (_("Can not do %d byte pic relocation"), size);
+ }
+
+ return BFD_RELOC_NONE;
+}
+
+/* Here we decide which fixups can be adjusted to make them relative
+ to the beginning of the section instead of the symbol. Basically
+ we need to make sure that the dynamic relocations are done
+ correctly, so in some cases we force the original symbol to be
+ used. */
+int
+tc_m68k_fix_adjustable (fixP)
+ fixS *fixP;
+{
+ /* Prevent all adjustments to global symbols. */
+ if (S_IS_EXTERNAL (fixP->fx_addsy)
+ || S_IS_WEAK (fixP->fx_addsy))
+ return 0;
+
+ /* adjust_reloc_syms doesn't know about the GOT */
+ switch (fixP->fx_r_type)
+ {
+ case BFD_RELOC_8_GOT_PCREL:
+ case BFD_RELOC_16_GOT_PCREL:
+ case BFD_RELOC_32_GOT_PCREL:
+ case BFD_RELOC_8_GOTOFF:
+ case BFD_RELOC_16_GOTOFF:
+ case BFD_RELOC_32_GOTOFF:
+ case BFD_RELOC_8_PLT_PCREL:
+ case BFD_RELOC_16_PLT_PCREL:
+ case BFD_RELOC_32_PLT_PCREL:
+ case BFD_RELOC_8_PLTOFF:
+ case BFD_RELOC_16_PLTOFF:
+ case BFD_RELOC_32_PLTOFF:
+ return 0;
+
+ case BFD_RELOC_VTABLE_INHERIT:
+ case BFD_RELOC_VTABLE_ENTRY:
+ return 0;
+
+ default:
+ return 1;
+ }
+}
+
+#else /* !OBJ_ELF */
+
+#define get_reloc_code(SIZE,PCREL,OTHER) NO_RELOC
+
+#endif /* OBJ_ELF */
+
#ifdef BFD_ASSEMBLER
arelent *
arelent *reloc;
bfd_reloc_code_real_type code;
-#define F(SZ,PCREL) (((SZ) << 1) + (PCREL))
- switch (F (fixp->fx_size, fixp->fx_pcrel))
+ if (fixp->fx_tcbit)
+ abort ();
+
+ if (fixp->fx_r_type != BFD_RELOC_NONE)
{
+ code = fixp->fx_r_type;
+
+ /* Since DIFF_EXPR_OK is defined in tc-m68k.h, it is possible
+ that fixup_segment converted a non-PC relative reloc into a
+ PC relative reloc. In such a case, we need to convert the
+ reloc code. */
+ if (fixp->fx_pcrel)
+ {
+ switch (code)
+ {
+ case BFD_RELOC_8:
+ code = BFD_RELOC_8_PCREL;
+ break;
+ case BFD_RELOC_16:
+ code = BFD_RELOC_16_PCREL;
+ break;
+ case BFD_RELOC_32:
+ code = BFD_RELOC_32_PCREL;
+ break;
+ case BFD_RELOC_8_PCREL:
+ case BFD_RELOC_16_PCREL:
+ case BFD_RELOC_32_PCREL:
+ case BFD_RELOC_8_GOT_PCREL:
+ case BFD_RELOC_16_GOT_PCREL:
+ case BFD_RELOC_32_GOT_PCREL:
+ case BFD_RELOC_8_GOTOFF:
+ case BFD_RELOC_16_GOTOFF:
+ case BFD_RELOC_32_GOTOFF:
+ case BFD_RELOC_8_PLT_PCREL:
+ case BFD_RELOC_16_PLT_PCREL:
+ case BFD_RELOC_32_PLT_PCREL:
+ case BFD_RELOC_8_PLTOFF:
+ case BFD_RELOC_16_PLTOFF:
+ case BFD_RELOC_32_PLTOFF:
+ break;
+ default:
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ _("Cannot make %s relocation PC relative"),
+ bfd_get_reloc_code_name (code));
+ }
+ }
+ }
+ else
+ {
+#define F(SZ,PCREL) (((SZ) << 1) + (PCREL))
+ switch (F (fixp->fx_size, fixp->fx_pcrel))
+ {
#define MAP(SZ,PCREL,TYPE) case F(SZ,PCREL): code = (TYPE); break
- MAP (1, 0, BFD_RELOC_8);
- MAP (2, 0, BFD_RELOC_16);
- MAP (4, 0, BFD_RELOC_32);
- MAP (1, 1, BFD_RELOC_8_PCREL);
- MAP (2, 1, BFD_RELOC_16_PCREL);
- MAP (4, 1, BFD_RELOC_32_PCREL);
- default:
- abort ();
+ MAP (1, 0, BFD_RELOC_8);
+ MAP (2, 0, BFD_RELOC_16);
+ MAP (4, 0, BFD_RELOC_32);
+ MAP (1, 1, BFD_RELOC_8_PCREL);
+ MAP (2, 1, BFD_RELOC_16_PCREL);
+ MAP (4, 1, BFD_RELOC_32_PCREL);
+ default:
+ abort ();
+ }
}
+#undef F
+#undef MAP
- reloc = (arelent *) bfd_alloc_by_size_t (stdoutput, sizeof (arelent));
- assert (reloc != 0);
- reloc->sym_ptr_ptr = &fixp->fx_addsy->bsym;
+ reloc = (arelent *) xmalloc (sizeof (arelent));
+ reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
+ *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
+#ifndef OBJ_ELF
if (fixp->fx_pcrel)
reloc->addend = fixp->fx_addnumber;
else
reloc->addend = 0;
+#else
+ if (!fixp->fx_pcrel)
+ reloc->addend = fixp->fx_addnumber;
+ else
+ reloc->addend = (section->vma
+ + (fixp->fx_pcrel_adjust == 64
+ ? -1 : fixp->fx_pcrel_adjust)
+ + fixp->fx_addnumber
+ + md_pcrel_from (fixp));
+#endif
reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
assert (reloc->howto != 0);
#endif /* BFD_ASSEMBLER */
+/* Return zero if the reference to SYMBOL from within the same segment may
+ be relaxed. */
+#ifdef OBJ_ELF
+
+/* On an ELF system, we can't relax an externally visible symbol,
+ because it may be overridden by a shared library. However, if
+ 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
+ libraries, and we can relax anything. */
+
+#define relaxable_symbol(symbol) \
+ (strcmp (TARGET_OS, "elf") == 0 \
+ || (! S_IS_EXTERNAL (symbol) \
+ && ! S_IS_WEAK (symbol)))
+
+#else
+
+#define relaxable_symbol(symbol) 1
+
+#endif
+
/* Handle of the OPCODE hash table. NULL means any use before
m68k_ip_begin() will crash. */
static struct hash_control *op_hash;
\f
/* Assemble an m68k instruction. */
-void
+static void
m68k_ip (instring)
char *instring;
{
register char *p;
register struct m68k_op *opP;
- register struct m68k_incant *opcode;
+ register const struct m68k_incant *opcode;
register const char *s;
register int tmpreg = 0, baseo = 0, outro = 0, nextword;
char *pdot, *pdotmove;
char c;
int losing;
int opsfound;
- char *crack_operand ();
LITTLENUM_TYPE words[6];
LITTLENUM_TYPE *wordp;
unsigned long ok_arch = 0;
if (p == instring)
{
- the_ins.error = "No operator";
+ the_ins.error = _("No operator");
return;
}
c = *p;
*p = '\0';
- opcode = (struct m68k_incant *) hash_find (op_hash, instring);
+ opcode = (const struct m68k_incant *) hash_find (op_hash, instring);
*p = c;
if (pdot != NULL)
if (opcode == NULL)
{
- the_ins.error = "Unknown operator";
+ the_ins.error = _("Unknown operator");
return;
}
return;
}
+ if (flag_mri && opcode->m_opnum == 0)
+ {
+ /* In MRI mode, random garbage is allowed after an instruction
+ which accepts no operands. */
+ the_ins.args = opcode->m_operands;
+ the_ins.numargs = opcode->m_opnum;
+ the_ins.numo = opcode->m_codenum;
+ the_ins.opcode[0] = getone (opcode);
+ the_ins.opcode[1] = gettwo (opcode);
+ return;
+ }
+
for (opP = &the_ins.operands[0]; *p; opP++)
{
p = crack_operand (p, opP);
/* If we didn't get the right number of ops, or we have no
common model with this pattern then reject this pattern. */
+ ok_arch |= opcode->m_arch;
if (opsfound != opcode->m_opnum
|| ((opcode->m_arch & current_architecture) == 0))
- {
- ++losing;
- ok_arch |= opcode->m_arch;
- }
+ ++losing;
else
{
for (s = opcode->m_operands, opP = &the_ins.operands[0];
}
break;
- case '`':
+ case '<':
switch (opP->mode)
{
+ case DREG:
+ case AREG:
+ case FPREG:
+ case CONTROL:
case IMMED:
+ case ADEC:
+ case REGLST:
+ losing++;
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case '>':
+ switch (opP->mode)
+ {
case DREG:
case AREG:
case FPREG:
case CONTROL:
+ case IMMED:
case AINC:
case REGLST:
+ losing++;
+ break;
+ case ABSL:
+ break;
+ default:
+ if (opP->reg == PC
+ || opP->reg == ZPC)
+ losing++;
+ break;
+ }
+ break;
+
+ case 'm':
+ switch (opP->mode)
+ {
+ case DREG:
+ case AREG:
+ case AINDR:
+ case AINC:
+ case ADEC:
+ break;
+ default:
+ losing++;
+ }
+ break;
+
+ case 'n':
+ switch (opP->mode)
+ {
+ case DISP:
+ break;
+ default:
+ losing++;
+ }
+ break;
+
+ case 'o':
+ switch (opP->mode)
+ {
+ case BASE:
+ case ABSL:
+ case IMMED:
+ break;
+ default:
+ losing++;
+ }
+ break;
+
+ case 'p':
+ switch (opP->mode)
+ {
+ case DREG:
+ case AREG:
+ case AINDR:
+ case AINC:
+ case ADEC:
+ break;
+ case DISP:
+ if (opP->reg == PC || opP->reg == ZPC)
+ losing++;
+ break;
+ default:
+ losing++;
+ }
+ break;
+
+ case 'q':
+ switch (opP->mode)
+ {
+ case DREG:
case AINDR:
+ case AINC:
+ case ADEC:
+ break;
+ case DISP:
+ if (opP->reg == PC || opP->reg == ZPC)
+ losing++;
+ break;
+ default:
losing++;
break;
+ }
+ break;
+
+ case 'v':
+ switch (opP->mode)
+ {
+ case DREG:
+ case AINDR:
+ case AINC:
+ case ADEC:
+ case ABSL:
+ break;
+ case DISP:
+ if (opP->reg == PC || opP->reg == ZPC)
+ losing++;
+ break;
default:
+ losing++;
break;
}
break;
&& (opP->disp.exp.X_op != O_constant
|| ! isbyte (opP->disp.exp.X_add_number)))
losing++;
+ else if (s[1] == 'B'
+ && ! isvar (&opP->disp)
+ && (opP->disp.exp.X_op != O_constant
+ || ! issbyte (opP->disp.exp.X_add_number)))
+ losing++;
else if (s[1] == 'w'
&& ! isvar (&opP->disp)
&& (opP->disp.exp.X_op != O_constant
|| ! isword (opP->disp.exp.X_add_number)))
losing++;
+ else if (s[1] == 'W'
+ && ! isvar (&opP->disp)
+ && (opP->disp.exp.X_op != O_constant
+ || ! issword (opP->disp.exp.X_add_number)))
+ losing++;
break;
case '^':
if (opP->mode == CONTROL
|| opP->mode == FPREG
|| opP->mode == REGLST
+ || opP->mode == IMMED
|| (opP->mode != ABSL
- && opP->mode != IMMED
&& (opP->reg == PC
|| opP->reg == ZPC)))
losing++;
losing++;
break;
+ case 'E':
+ if (opP->reg != ACC)
+ losing++;
+ break;
+
case 'F':
if (opP->mode != FPREG)
losing++;
break;
+ case 'G':
+ if (opP->reg != MACSR)
+ losing++;
+ break;
+
+ case 'H':
+ if (opP->reg != MASK)
+ losing++;
+ break;
+
case 'I':
if (opP->mode != CONTROL
|| opP->reg < COP0
opP->mode = REGLST;
}
}
- else if (opP->mode == ABSL
- && opP->disp.size == SIZE_UNSPEC
- && opP->disp.exp.X_op == O_constant)
- {
- /* This is what the MRI REG pseudo-op generates. */
- opP->mode = REGLST;
- opP->mask = opP->disp.exp.X_add_number;
- }
else if (opP->mode != REGLST)
losing++;
else if (s[1] == '8' && (opP->mask & 0x0ffffff) != 0)
break;
case 'O':
- if (opP->mode != DREG && opP->mode != IMMED)
+ if (opP->mode != DREG
+ && opP->mode != IMMED
+ && opP->mode != ABSL)
losing++;
break;
|| opP->mode == AREG
|| opP->mode == REGLST)
losing++;
+ /* We should accept immediate operands, but they
+ supposedly have to be quad word, and we don't
+ handle that. I would like to see what a Motorola
+ assembler does before doing something here. */
+ if (opP->mode == IMMED)
+ losing++;
break;
case 'f':
losing++;
break;
- case 'P':
+ case '0':
+ if (opP->mode != CONTROL || opP->reg != TC)
+ losing++;
+ break;
+
+ case '1':
+ if (opP->mode != CONTROL || opP->reg != AC)
+ losing++;
+ break;
+
+ case '2':
if (opP->mode != CONTROL
- || (opP->reg != TC
- && opP->reg != CAL
+ || (opP->reg != CAL
&& opP->reg != VAL
- && opP->reg != SCC
- && opP->reg != AC))
+ && opP->reg != SCC))
losing++;
break;
++losing;
break;
+ case 'u':
+ if (opP->reg < DATA0L || opP->reg > ADDR7U)
+ losing++;
+ /* FIXME: kludge instead of fixing parser:
+ upper/lower registers are *not* CONTROL
+ registers, but ordinary ones. */
+ if ((opP->reg >= DATA0L && opP->reg <= DATA7L)
+ || (opP->reg >= DATA0U && opP->reg <= DATA7U))
+ opP->mode = DREG;
+ else
+ opP->mode = AREG;
+ break;
+
default:
abort ();
} /* switch on type of operand */
&& !(ok_arch & current_architecture))
{
char buf[200], *cp;
- int len;
+
strcpy (buf,
- "invalid instruction for this architecture; needs ");
+ _("invalid instruction for this architecture; needs "));
cp = buf + strlen (buf);
switch (ok_arch)
{
case mfloat:
- strcpy (cp, "fpu (68040, 68060 or 68881/68882)");
+ strcpy (cp, _("fpu (68040, 68060 or 68881/68882)"));
break;
case mmmu:
- strcpy (cp, "mmu (68030 or 68851)");
+ strcpy (cp, _("mmu (68030 or 68851)"));
break;
case m68020up:
- strcpy (cp, "68020 or higher");
+ strcpy (cp, _("68020 or higher"));
break;
case m68000up:
- strcpy (cp, "68000 or higher");
+ strcpy (cp, _("68000 or higher"));
break;
case m68010up:
- strcpy (cp, "68010 or higher");
+ strcpy (cp, _("68010 or higher"));
break;
default:
{
for (idx = 0; idx < sizeof (archs) / sizeof (archs[0]);
idx++)
{
- if (archs[idx].arch & ok_arch)
+ if ((archs[idx].arch & ok_arch)
+ && ! archs[idx].alias)
{
if (got_one)
{
}
}
}
- len = cp - buf + 1;
- cp = malloc (len);
+ cp = xmalloc (strlen (buf) + 1);
strcpy (cp, buf);
the_ins.error = cp;
}
else
- the_ins.error = "operands mismatch";
+ the_ins.error = _("operands mismatch");
return;
} /* Fell off the end */
case '$':
case '?':
case '/':
- case '`':
+ case '<':
+ case '>':
+ case 'm':
+ case 'n':
+ case 'o':
+ case 'p':
+ case 'q':
+ case 'v':
#ifndef NO_68851
case '|':
#endif
{
case 'b':
if (!isbyte (nextword))
- opP->error = "operand out of range";
+ opP->error = _("operand out of range");
addword (nextword);
baseo = 0;
break;
case 'w':
if (!isword (nextword))
- opP->error = "operand out of range";
+ opP->error = _("operand out of range");
+ addword (nextword);
+ baseo = 0;
+ break;
+ case 'W':
+ if (!issword (nextword))
+ opP->error = _("operand out of range");
addword (nextword);
baseo = 0;
break;
{
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]);
offs (&opP->disp) = baseo;
}
|| (isvar (&opP->disp)
&& ((opP->disp.size == SIZE_UNSPEC
&& flag_short_refs == 0
- && cpu_of_arch (current_architecture) >= m68020)
+ && cpu_of_arch (current_architecture) >= m68020
+ && ! arch_coldfire_p (current_architecture))
|| opP->disp.size == SIZE_LONG)))
{
+ if (cpu_of_arch (current_architecture) < m68020
+ || arch_coldfire_p (current_architecture))
+ opP->error =
+ _("displacement too large for this architecture; needs 68020 or higher");
if (opP->reg == PC)
tmpreg = 0x3B; /* 7.3 */
else
{
if (opP->reg == PC)
{
-#if 0
- addword (0x0170);
- add_fix ('l', &opP->disp, 1, 2);
- addword (0), addword (0);
-#else
- add_frag (adds (&opP->disp),
- offs (&opP->disp),
- TAB (PCLEA, SZ_UNDEF));
+ if (opP->disp.size == SIZE_LONG
+#ifdef OBJ_ELF
+ /* If the displacement needs pic
+ relocation it cannot be relaxed. */
+ || opP->disp.pic_reloc != pic_none
#endif
- break;
+ )
+ {
+ addword (0x0170);
+ add_fix ('l', &opP->disp, 1, 2);
+ }
+ else
+ {
+ add_frag (adds (&opP->disp),
+ offs (&opP->disp),
+ TAB (PCLEA, SZ_UNDEF));
+ break;
+ }
}
else
{
{
nextword |= (opP->index.reg - DATA) << 12;
- if (opP->index.size == SIZE_UNSPEC
- || opP->index.size == SIZE_LONG)
+ if (opP->index.size == SIZE_LONG
+ || (opP->index.size == SIZE_UNSPEC
+ && m68k_index_width_default == SIZE_LONG))
nextword |= 0x800;
- if (cpu_of_arch (current_architecture) < m68020)
+ if ((opP->index.scale != 1
+ && cpu_of_arch (current_architecture) < m68020)
+ || (opP->index.scale == 8
+ && arch_coldfire_p (current_architecture)))
{
- if (opP->index.scale != 1)
- {
- opP->error =
- "scale factor invalid on this architecture; needs 68020 or higher";
- }
+ opP->error =
+ _("scale factor invalid on this architecture; needs cpu32 or 68020 or higher");
}
+ if (arch_coldfire_p (current_architecture)
+ && opP->index.size == SIZE_WORD)
+ opP->error = _("invalid index size for coldfire");
+
switch (opP->index.scale)
{
case 1:
{
if (siz1 == SIZE_BYTE
|| cpu_of_arch (current_architecture) < m68020
+ || arch_coldfire_p (current_architecture)
|| (siz1 == SIZE_UNSPEC
&& ! isvar (&opP->disp)
&& issbyte (baseo)))
else if (siz1 != SIZE_BYTE)
{
if (siz1 != SIZE_UNSPEC)
- as_warn ("Forcing byte displacement");
+ as_warn (_("Forcing byte displacement"));
if (! issbyte (baseo))
- opP->error = "byte displacement out of range";
+ opP->error = _("byte displacement out of range");
}
break;
else if (siz1 == SIZE_UNSPEC
&& opP->reg == PC
&& isvar (&opP->disp)
- && subs (&opP->disp) == NULL)
+ && subs (&opP->disp) == NULL
+#ifdef OBJ_ELF
+ /* If the displacement needs pic
+ relocation it cannot be relaxed. */
+ && opP->disp.pic_reloc == pic_none
+#endif
+ )
{
+ /* The code in md_convert_frag_1 needs to be
+ able to adjust nextword. Call frag_grow
+ to ensure that we have enough space in
+ the frag obstack to make all the bytes
+ contiguous. */
+ frag_grow (14);
nextword += baseo & 0xff;
addword (nextword);
add_frag (adds (&opP->disp), offs (&opP->disp),
/* It isn't simple. */
- if (cpu_of_arch (current_architecture) < m68020)
+ if (cpu_of_arch (current_architecture) < m68020
+ || arch_coldfire_p (current_architecture))
opP->error =
- "invalid operand mode for this architecture; needs 68020 or higher";
+ _("invalid operand mode for this architecture; needs 68020 or higher");
nextword |= 0x100;
/* If the guy specified a width, we assume that it is
}
break;
case SIZE_BYTE:
- as_warn (":b not permitted; defaulting to :w");
+ as_warn (_(":b not permitted; defaulting to :w"));
/* Fall through. */
case SIZE_WORD:
nextword |= 0x20;
/* Figure out innner displacement stuff */
if (opP->mode == POST || opP->mode == PRE)
{
+ if (cpu_of_arch (current_architecture) & cpu32)
+ opP->error = _("invalid operand mode for this architecture; needs 68020 or higher");
switch (siz2)
{
case SIZE_UNSPEC:
siz2 = SIZE_LONG;
nextword |= 0x3;
}
- else if (! isvar (&opP->disp) && outro == 0)
+ else if (! isvar (&opP->odisp) && outro == 0)
nextword |= 0x1;
else
{
}
break;
case 1:
- as_warn (":b not permitted; defaulting to :w");
+ as_warn (_(":b not permitted; defaulting to :w"));
/* Fall through. */
case 2:
nextword |= 0x2;
nextword |= 0x3;
break;
}
- if (opP->mode == POST)
+ if (opP->mode == POST
+ && (nextword & 0x40) == 0)
nextword |= 0x04;
}
addword (nextword);
if (isvar (&opP->disp)
&& !subs (&opP->disp)
&& adds (&opP->disp)
- && (S_GET_SEGMENT (adds (&opP->disp)) == text_section)
- && now_seg == text_section
- && cpu_of_arch (current_architecture) >= m68020
+#ifdef OBJ_ELF
+ /* If the displacement needs pic relocation it
+ cannot be relaxed. */
+ && opP->disp.pic_reloc == pic_none
+#endif
+ && S_GET_SEGMENT (adds (&opP->disp)) == now_seg
+ && relaxable_symbol (adds (&opP->disp))
+ && HAVE_LONG_BRANCH(current_architecture)
&& !flag_long_jumps
&& !strchr ("~%&$?", s[0]))
{
addword (nextword);
break;
+ case SIZE_BYTE:
+ as_bad (_("unsupported byte value; use a different suffix"));
+ /* Fall through. */
case SIZE_WORD: /* Word */
if (isvar (&opP->disp))
add_fix ('w', &opP->disp, 0, 0);
case CONTROL:
case FPREG:
default:
- as_bad ("unknown/incorrect operand");
+ as_bad (_("unknown/incorrect operand"));
/* abort(); */
}
install_gen_operand (s[1], tmpreg);
certain types of overflow.
user beware! */
if (!isbyte (tmpreg))
- opP->error = "out of range";
+ opP->error = _("out of range");
insop (tmpreg, opcode);
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 + 1;
+ break;
+ case 'B':
+ if (!issbyte (tmpreg))
+ opP->error = _("out of range");
+ the_ins.opcode[the_ins.numo - 1] |= tmpreg & 0xff;
+ if (isvar (&opP->disp))
+ the_ins.reloc[the_ins.nrel - 1].n = opcode->m_codenum * 2 - 1;
break;
case 'w':
if (!isword (tmpreg))
- opP->error = "out of range";
+ opP->error = _("out of range");
+ insop (tmpreg, opcode);
+ if (isvar (&opP->disp))
+ the_ins.reloc[the_ins.nrel - 1].n = (opcode->m_codenum) * 2;
+ break;
+ case 'W':
+ if (!issword (tmpreg))
+ opP->error = _("out of range");
insop (tmpreg, opcode);
if (isvar (&opP->disp))
the_ins.reloc[the_ins.nrel - 1].n = (opcode->m_codenum) * 2;
tmpreg &= 0xFF;
case '8':
case 'C':
+ case 'j':
install_operand (s[1], tmpreg);
break;
default:
break;
case 'L':
long_branch:
- if (cpu_of_arch (current_architecture) < m68020)
- as_warn ("Can't use long branches on 68000/68010");
+ if (!HAVE_LONG_BRANCH(current_architecture))
+ as_warn (_("Can't use long branches on 68000/68010/5200"));
the_ins.opcode[the_ins.numo - 1] |= 0xff;
add_fix ('l', &opP->disp, 1, 0);
addword (0);
if (subs (&opP->disp)) /* We can't relax it */
goto long_branch;
+#ifdef OBJ_ELF
+ /* If the displacement needs pic relocation it cannot be
+ relaxed. */
+ if (opP->disp.pic_reloc != pic_none)
+ goto long_branch;
+#endif
+
/* This could either be a symbol, or an absolute
address. No matter, the frag hacking will finger it
out. Not quite: it can't switch from BRANCH to
BCC68000 for the case where opnd is absolute (it
needs to use the 68000 hack since no conditional abs
jumps). */
- if (((cpu_of_arch (current_architecture) < m68020)
+ if (( !HAVE_LONG_BRANCH(current_architecture)
|| (0 == adds (&opP->disp)))
&& (the_ins.opcode[0] >= 0x6200)
&& (the_ins.opcode[0] <= 0x6f00))
if (subs (&opP->disp))
{
add_fix ('l', &opP->disp, 1, 0);
- add_frag ((symbolS *) 0, (long) 0, TAB (FBRANCH, LONG));
+ add_frag ((symbolS *) 0, (offsetT) 0, TAB (FBRANCH, LONG));
}
else if (adds (&opP->disp))
add_frag (adds (&opP->disp), offs (&opP->disp),
TAB (FBRANCH, SZ_UNDEF));
else
{
- /* add_frag((symbolS *) 0, offs(&opP->disp),
- TAB(FBRANCH,SHORT)); */
+ /* add_frag ((symbolS *) 0, offs (&opP->disp),
+ TAB(FBRANCH,SHORT)); */
the_ins.opcode[the_ins.numo - 1] |= 0x40;
add_fix ('l', &opP->disp, 1, 0);
addword (0);
tmpreg = get_num (&opP->disp, 80);
if (!issword (tmpreg))
{
- as_warn ("Expression out of range, using 0");
+ as_warn (_("Expression out of range, using 0"));
tmpreg = 0;
}
addword (tmpreg);
install_operand (s[1], opP->reg - DATA);
break;
+ case 'E': /* Ignore it */
+ break;
+
case 'F':
install_operand (s[1], opP->reg - FP0);
break;
+ case 'G': /* Ignore it */
+ case 'H':
+ break;
+
case 'I':
tmpreg = opP->reg - COP0;
install_operand (s[1], tmpreg);
case PCR:
tmpreg = 0x808;
break;
+ case ROMBAR:
+ tmpreg = 0xC00;
+ break;
+ case RAMBAR0:
+ tmpreg = 0xC04;
+ break;
+ case RAMBAR1:
+ tmpreg = 0xC05;
+ break;
+ case MBAR:
+ tmpreg = 0xC0F;
+ break;
default:
abort ();
}
if (s[1] == 'w')
{
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);
}
else
{
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));
}
break;
if (s[1] == 'w')
{
if (tmpreg & 0x7FF0000)
- as_bad ("Floating point register in register list");
+ as_bad (_("Floating point register in register list"));
insop (tmpreg, opcode);
}
else if (s[1] == '8')
{
if (tmpreg & 0x0FFFFFF)
- as_bad ("incorrect register in reglist");
+ as_bad (_("incorrect register in reglist"));
install_operand (s[1], tmpreg >> 24);
}
else
{
if (tmpreg & 0x700FFFF)
- as_bad ("wrong register in floating-point reglist");
+ as_bad (_("wrong register in floating-point reglist"));
else
install_operand (s[1], tmpreg >> 16);
}
tmpreg = 3;
break;
default:
- as_fatal ("failed sanity check");
+ as_fatal (_("failed sanity check"));
} /* switch on cache token */
install_operand (s[1], tmpreg);
break;
install_operand (s[1], tmpreg);
break;
- case 'P':
+ case '0':
+ case '1':
+ case '2':
switch (opP->reg)
{
case TC:
install_operand (s[1], tmpreg);
break;
case '_': /* used only for move16 absolute 32-bit address */
+ if (isvar (&opP->disp))
+ add_fix ('l', &opP->disp, 0, 0);
tmpreg = get_num (&opP->disp, 80);
addword (tmpreg >> 16);
addword (tmpreg & 0xFFFF);
break;
+ case 'u':
+ install_operand (s[1], opP->reg - DATA0L);
+ opP->reg -= (DATA0L);
+ opP->reg &= 0x0F; /* remove upper/lower bit */
+ break;
default:
abort ();
}
break;
case 'b':
case 'w':
+ case 'W':
case 'l':
break;
case 'e':
the_ins.opcode[1] = (val >> 16);
the_ins.opcode[2] = val & 0xffff;
break;
+ case 'm':
+ the_ins.opcode[0] |= ((val & 0x8) << (6 - 3));
+ the_ins.opcode[0] |= ((val & 0x7) << 9);
+ the_ins.opcode[1] |= ((val & 0x10) << (7 - 4));
+ break;
+ case 'n':
+ the_ins.opcode[0] |= ((val & 0x8) << (6 - 3));
+ the_ins.opcode[0] |= ((val & 0x7) << 9);
+ break;
+ case 'o':
+ the_ins.opcode[1] |= val << 12;
+ the_ins.opcode[1] |= ((val & 0x10) << (7 - 4));
+ break;
+ case 'M':
+ the_ins.opcode[0] |= (val & 0xF);
+ the_ins.opcode[1] |= ((val & 0x10) << (6 - 4));
+ break;
+ case 'N':
+ the_ins.opcode[1] |= (val & 0xF);
+ the_ins.opcode[1] |= ((val & 0x10) << (6 - 4));
+ break;
+ case 'h':
+ the_ins.opcode[1] |= ((val != 1) << 10);
+ break;
case 'c':
default:
- as_fatal ("failed sanity check.");
+ as_fatal (_("failed sanity check."));
}
} /* install_operand() */
break;
/* more stuff goes here */
default:
- as_fatal ("failed sanity check.");
+ as_fatal (_("failed sanity check."));
}
} /* install_gen_operand() */
register int parens;
register int c;
register char *beg_str;
+ int inquote = 0;
if (!str)
{
return str;
}
beg_str = str;
- for (parens = 0; *str && (parens > 0 || notend (str)); str++)
+ for (parens = 0; *str && (parens > 0 || inquote || notend (str)); str++)
{
- if (*str == '(')
- parens++;
- else if (*str == ')')
+ if (! inquote)
{
- if (!parens)
- { /* ERROR */
- opP->error = "Extra )";
- return str;
+ if (*str == '(')
+ parens++;
+ else if (*str == ')')
+ {
+ if (!parens)
+ { /* ERROR */
+ opP->error = _("Extra )");
+ return str;
+ }
+ --parens;
}
- --parens;
}
+ if (flag_mri && *str == '\'')
+ inquote = ! inquote;
}
if (!*str && parens)
{ /* ERROR */
- opP->error = "Missing )";
+ opP->error = _("Missing )");
return str;
}
c = *str;
{
c = *++str;
if (!c)
- as_bad ("Missing operand");
+ as_bad (_("Missing operand"));
+ }
+
+ /* Detect MRI REG symbols and convert them to REGLSTs. */
+ if (opP->mode == CONTROL && (int)opP->reg < 0)
+ {
+ opP->mode = REGLST;
+ opP->mask = ~(int)opP->reg;
+ opP->reg = 0;
}
+
return str;
}
the frags/bytes it assembles to.
*/
-void
+static void
insert_reg (regname, regnum)
- char *regname;
+ const char *regname;
int regnum;
{
char buf[100];
{ "ccr", CCR },
{ "cc", CCR },
- { "usp", USP },
- { "isp", ISP },
- { "sfc", SFC },
+ { "acc", ACC },
+ { "macsr", MACSR },
+ { "mask", MASK },
+
+ /* control registers */
+ { "sfc", SFC }, /* Source Function Code */
{ "sfcr", SFC },
- { "dfc", DFC },
+ { "dfc", DFC }, /* Destination Function Code */
{ "dfcr", DFC },
- { "cacr", CACR },
- { "caar", CAAR },
-
- { "vbr", VBR },
-
- { "msp", MSP },
- { "itt0", ITT0 },
- { "itt1", ITT1 },
- { "dtt0", DTT0 },
- { "dtt1", DTT1 },
- { "mmusr", MMUSR },
- { "tc", TC },
- { "srp", SRP },
- { "urp", URP },
+ { "cacr", CACR }, /* Cache Control Register */
+ { "caar", CAAR }, /* Cache Address Register */
+
+ { "usp", USP }, /* User Stack Pointer */
+ { "vbr", VBR }, /* Vector Base Register */
+ { "msp", MSP }, /* Master Stack Pointer */
+ { "isp", ISP }, /* Interrupt Stack Pointer */
+
+ { "itt0", ITT0 }, /* Instruction Transparent Translation Reg 0 */
+ { "itt1", ITT1 }, /* Instruction Transparent Translation Reg 1 */
+ { "dtt0", DTT0 }, /* Data Transparent Translation Register 0 */
+ { "dtt1", DTT1 }, /* Data Transparent Translation Register 1 */
+
+ /* 68ec040 versions of same */
+ { "iacr0", ITT0 }, /* Instruction Access Control Register 0 */
+ { "iacr1", ITT1 }, /* Instruction Access Control Register 0 */
+ { "dacr0", DTT0 }, /* Data Access Control Register 0 */
+ { "dacr1", DTT1 }, /* Data Access Control Register 0 */
+
+ /* mcf5200 versions of same. The ColdFire programmer's reference
+ 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. */
+ { "acr0", ITT0 }, /* Access Control Unit 0 */
+ { "acr1", ITT1 }, /* Access Control Unit 1 */
+ { "acr2", DTT0 }, /* Access Control Unit 2 */
+ { "acr3", DTT1 }, /* Access Control Unit 3 */
+
+ { "tc", TC }, /* MMU Translation Control Register */
+ { "tcr", TC },
+
+ { "mmusr", MMUSR }, /* MMU Status Register */
+ { "srp", SRP }, /* User Root Pointer */
+ { "urp", URP }, /* Supervisor Root Pointer */
+
{ "buscr", BUSCR },
{ "pcr", PCR },
+ { "rombar", ROMBAR }, /* ROM Base Address Register */
+ { "rambar0", RAMBAR0 }, /* ROM Base Address Register */
+ { "rambar1", RAMBAR1 }, /* ROM Base Address Register */
+ { "mbar", MBAR }, /* Module Base Address Register */
+ /* end of control registers */
+
{ "ac", AC },
{ "bc", BC },
{ "cal", CAL },
{ "za6", ZADDR6 },
{ "za7", ZADDR7 },
+ /* Upper and lower data and address registers, used by macw and msacw. */
+ { "d0l", DATA0L },
+ { "d1l", DATA1L },
+ { "d2l", DATA2L },
+ { "d3l", DATA3L },
+ { "d4l", DATA4L },
+ { "d5l", DATA5L },
+ { "d6l", DATA6L },
+ { "d7l", DATA7L },
+
+ { "a0l", ADDR0L },
+ { "a1l", ADDR1L },
+ { "a2l", ADDR2L },
+ { "a3l", ADDR3L },
+ { "a4l", ADDR4L },
+ { "a5l", ADDR5L },
+ { "a6l", ADDR6L },
+ { "a7l", ADDR7L },
+
+ { "d0u", DATA0U },
+ { "d1u", DATA1U },
+ { "d2u", DATA2U },
+ { "d3u", DATA3U },
+ { "d4u", DATA4U },
+ { "d5u", DATA5U },
+ { "d6u", DATA6U },
+ { "d7u", DATA7U },
+
+ { "a0u", ADDR0U },
+ { "a1u", ADDR1U },
+ { "a2u", ADDR2U },
+ { "a3u", ADDR3U },
+ { "a4u", ADDR4U },
+ { "a5u", ADDR5U },
+ { "a6u", ADDR6U },
+ { "a7u", ADDR7U },
+
{ 0, 0 }
};
-void
+static void
init_regtable ()
{
int i;
int shorts_this_frag;
fixS *fixP;
+ /* In MRI mode, the instruction and operands are separated by a
+ space. Anything following the operands is a comment. The label
+ has already been removed. */
+ if (flag_mri)
+ {
+ char *s;
+ int fields = 0;
+ int infield = 0;
+ int inquote = 0;
+
+ for (s = str; *s != '\0'; s++)
+ {
+ if ((*s == ' ' || *s == '\t') && ! inquote)
+ {
+ if (infield)
+ {
+ ++fields;
+ if (fields >= 2)
+ {
+ *s = '\0';
+ break;
+ }
+ infield = 0;
+ }
+ }
+ else
+ {
+ if (! infield)
+ infield = 1;
+ if (*s == '\'')
+ inquote = ! inquote;
+ }
+ }
+ }
+
memset ((char *) (&the_ins), '\0', sizeof (the_ins));
m68k_ip (str);
er = the_ins.error;
}
if (er)
{
- as_bad ("%s -- statement `%s' ignored", er, str);
+ as_bad (_("%s -- statement `%s' ignored"), er, str);
return;
}
+ /* If there is a current label, record that it marks an instruction. */
+ if (current_label != NULL)
+ {
+ current_label->text = 1;
+ current_label = NULL;
+ }
+
if (the_ins.nfrag == 0)
{
/* No frag hacking involved; just put it out */
n = 1;
break;
case '3':
- n = 2;
+ n = 1;
break;
case 'w':
+ case 'W':
n = 2;
break;
case 'l':
n = 4;
break;
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);
}
n,
&the_ins.reloc[m].exp,
the_ins.reloc[m].pcrel,
- NO_RELOC);
+ get_reloc_code (n, the_ins.reloc[m].pcrel,
+ the_ins.reloc[m].pic_reloc));
fixP->fx_pcrel_adjust = the_ins.reloc[m].pcrel_fix;
+ if (the_ins.reloc[m].wid == 'B')
+ fixP->fx_signed = 1;
}
return;
}
wid,
&the_ins.reloc[m].exp,
the_ins.reloc[m].pcrel,
- NO_RELOC);
+ get_reloc_code (wid, the_ins.reloc[m].pcrel,
+ the_ins.reloc[m].pic_reloc));
fixP->fx_pcrel_adjust = the_ins.reloc[m].pcrel_fix;
}
(void) frag_var (rs_machine_dependent, 10, 0,
wid,
&the_ins.reloc[m].exp,
the_ins.reloc[m].pcrel,
- NO_RELOC);
+ get_reloc_code (wid, the_ins.reloc[m].pcrel,
+ the_ins.reloc[m].pic_reloc));
fixP->fx_pcrel_adjust = the_ins.reloc[m].pcrel_fix;
}
}
{
flag_reg_prefix_optional = 1;
m68k_abspcadd = 1;
- m68k_rel32 = 0;
+ if (! m68k_rel32_from_cmdline)
+ m68k_rel32 = 0;
}
op_hash = hash_new ();
retval = hash_insert (op_hash, ins->name, (char *) hack);
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++)
const char *alias = m68k_opcode_aliases[i].alias;
PTR val = hash_find (op_hash, name);
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);
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,
const char *alias = mri_aliases[i].alias;
PTR val = hash_find (op_hash, name);
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);
if (retval)
- as_fatal ("Internal Error: Can't hash %s: %s", alias, retval);
+ as_fatal (_("Internal Error: Can't hash %s: %s"), alias, retval);
}
}
*/
alt_notend_table['@'] = 1;
+ /* We need to put digits in alt_notend_table to handle
+ bfextu %d0{24:1},%d0
+ */
+ alt_notend_table['0'] = 1;
+ alt_notend_table['1'] = 1;
+ alt_notend_table['2'] = 1;
+ alt_notend_table['3'] = 1;
+ alt_notend_table['4'] = 1;
+ alt_notend_table['5'] = 1;
+ alt_notend_table['6'] = 1;
+ alt_notend_table['7'] = 1;
+ alt_notend_table['8'] = 1;
+ alt_notend_table['9'] = 1;
+
#ifndef MIT_SYNTAX_ONLY
/* Insert pseudo ops, these have to go into the opcode table since
gas expects pseudo ops to start with a dot */
#endif
init_regtable ();
+
+#ifdef OBJ_ELF
+ record_alignment (text_section, 2);
+ record_alignment (data_section, 2);
+ record_alignment (bss_section, 2);
+#endif
+}
+
+static void
+select_control_regs ()
+{
+ /* Note which set of "movec" control registers is available. */
+ switch (cpu_of_arch (current_architecture))
+ {
+ case m68000:
+ control_regs = m68000_control_regs;
+ break;
+ case m68010:
+ control_regs = m68010_control_regs;
+ break;
+ case m68020:
+ case m68030:
+ control_regs = m68020_control_regs;
+ break;
+ case m68040:
+ control_regs = m68040_control_regs;
+ break;
+ case m68060:
+ control_regs = m68060_control_regs;
+ break;
+ case cpu32:
+ control_regs = cpu32_control_regs;
+ break;
+ case mcf5200:
+ case mcf5206e:
+ case mcf5307:
+ control_regs = mcf_control_regs;
+ break;
+ default:
+ abort ();
+ }
}
void
break;
if (i == n_archs)
{
- as_bad ("unrecognized default cpu `%s' ???", TARGET_CPU);
+ as_bad (_("unrecognized default cpu `%s' ???"), TARGET_CPU);
current_architecture |= m68020;
}
else
{
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? */
current_architecture |= m68851;
}
if (no_68881 && (current_architecture & m68881))
- as_bad ("options for 68881 and no-68881 both given");
+ as_bad (_("options for 68881 and no-68881 both given"));
if (no_68851 && (current_architecture & m68851))
- as_bad ("options for 68851 and no-68851 both given");
+ as_bad (_("options for 68851 and no-68851 both given"));
#ifdef OBJ_AOUT
/* Work out the magic number. This isn't very general. */
#endif
/* Note which set of "movec" control registers is available. */
- switch (cpu_of_arch (current_architecture))
+ select_control_regs ();
+
+ if (cpu_of_arch (current_architecture) < m68020
+ || arch_coldfire_p (current_architecture))
+ md_relax_table[TAB (PCINDEX, BYTE)].rlx_more = 0;
+}
+\f
+/* This is called when a label is defined. */
+
+void
+m68k_frob_label (sym)
+ symbolS *sym;
+{
+ struct label_line *n;
+
+ n = (struct label_line *) xmalloc (sizeof *n);
+ n->next = labels;
+ n->label = sym;
+ as_where (&n->file, &n->line);
+ n->text = 0;
+ labels = n;
+ current_label = n;
+}
+
+/* This is called when a value that is not an instruction is emitted. */
+
+void
+m68k_flush_pending_output ()
+{
+ current_label = NULL;
+}
+
+/* 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
+ odd location. */
+
+void
+m68k_frob_symbol (sym)
+ symbolS *sym;
+{
+ if (S_GET_SEGMENT (sym) == reg_section
+ && (int) S_GET_VALUE (sym) < 0)
{
- case m68000:
- control_regs = m68000_control_regs;
- break;
- case m68010:
- control_regs = m68010_control_regs;
- break;
- case m68020:
- case m68030:
- control_regs = m68020_control_regs;
- break;
- case m68040:
- control_regs = m68040_control_regs;
- break;
- case m68060:
- control_regs = m68060_control_regs;
- break;
- case cpu32:
- control_regs = cpu32_control_regs;
- break;
- default:
- abort ();
+ S_SET_SEGMENT (sym, absolute_section);
+ S_SET_VALUE (sym, ~(int)S_GET_VALUE (sym));
}
+ else if ((S_GET_VALUE (sym) & 1) != 0)
+ {
+ struct label_line *l;
- if (cpu_of_arch (current_architecture) < m68020)
- md_relax_table[TAB (PCINDEX, BYTE)].rlx_more = 0;
+ for (l = labels; l != NULL; l = l->next)
+ {
+ if (l->label == sym)
+ {
+ if (l->text)
+ as_warn_where (l->file, l->line,
+ _("text label `%s' aligned to odd boundary"),
+ S_GET_NAME (sym));
+ break;
+ }
+ }
+ }
+}
+\f
+/* This is called if we go in or out of MRI mode because of the .mri
+ pseudo-op. */
+
+void
+m68k_mri_mode_change (on)
+ int on;
+{
+ if (on)
+ {
+ if (! flag_reg_prefix_optional)
+ {
+ flag_reg_prefix_optional = 1;
+#ifdef REGISTER_PREFIX
+ init_regtable ();
+#endif
+ }
+ m68k_abspcadd = 1;
+ if (! m68k_rel32_from_cmdline)
+ m68k_rel32 = 0;
+ }
+ else
+ {
+ if (! reg_prefix_optional_seen)
+ {
+#ifdef REGISTER_PREFIX_OPTIONAL
+ flag_reg_prefix_optional = REGISTER_PREFIX_OPTIONAL;
+#else
+ flag_reg_prefix_optional = 0;
+#endif
+#ifdef REGISTER_PREFIX
+ init_regtable ();
+#endif
+ }
+ m68k_abspcadd = 0;
+ if (! m68k_rel32_from_cmdline)
+ m68k_rel32 = 1;
+ }
}
/* Equal to MAX_PRECISION in atof-ieee.c */
LITTLENUM_TYPE words[MAX_LITTLENUMS];
LITTLENUM_TYPE *wordP;
char *t;
- char *atof_ieee ();
switch (type)
{
default:
*sizeP = 0;
- return "Bad call to MD_ATOF()";
+ return _("Bad call to MD_ATOF()");
}
t = atof_ieee (input_line_pointer, type, words);
if (t)
else
val &= 0x7fffffff;
+#ifdef OBJ_ELF
+ if (fixP->fx_addsy)
+ {
+ memset (buf, 0, fixP->fx_size);
+ fixP->fx_addnumber = val; /* Remember value for emit_reloc */
+
+ if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
+ && !S_IS_DEFINED (fixP->fx_addsy)
+ && !S_IS_WEAK (fixP->fx_addsy))
+ S_SET_WEAK (fixP->fx_addsy);
+ return;
+ }
+#endif
+
+#ifdef BFD_ASSEMBLER
+ if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
+ || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
+ return;
+#endif
+
switch (fixP->fx_size)
{
/* The cast to offsetT below are necessary to make code correct for
BAD_CASE (fixP->fx_size);
}
+ /* Fix up a negative reloc. */
+ if (fixP->fx_addsy == NULL && fixP->fx_subsy != NULL)
+ {
+ fixP->fx_addsy = fixP->fx_subsy;
+ fixP->fx_subsy = NULL;
+ fixP->fx_tcbit = 1;
+ }
+
/* 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
to accept such numbers. We arbitrarily disallow "-0xff" or "0xff+0xff",
so that we can do any range checking at all. */
- if (!fixP->fx_pcrel)
+ if (! fixP->fx_pcrel && ! fixP->fx_signed)
upper_limit = upper_limit * 2 + 1;
if ((addressT) val > upper_limit
&& (val > 0 || val < lower_limit))
- as_bad_where (fixP->fx_file, fixP->fx_line, "value out of range");
+ as_bad_where (fixP->fx_file, fixP->fx_line, _("value out of range"));
/* 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
- different opcodes (branches with longer offsets). */
- if (fixP->fx_pcrel
+ different opcodes (branches with longer offsets). fixup_segment
+ in write.c may have clobbered fx_pcrel, so we need to examine the
+ reloc type. */
+ if ((fixP->fx_pcrel
+#ifdef BFD_ASSEMBLER
+ || fixP->fx_r_type == BFD_RELOC_8_PCREL
+#endif
+ )
&& fixP->fx_size == 1
&& (fixP->fx_addsy == NULL
|| S_IS_DEFINED (fixP->fx_addsy))
&& (val == 0 || val == -1))
- as_bad_where (fixP->fx_file, fixP->fx_line, "invalid byte branch offset");
+ as_bad_where (fixP->fx_file, fixP->fx_line, _("invalid byte branch offset"));
}
#ifdef BFD_ASSEMBLER
the bytes inside it modified to conform to the new size There is UGLY
MAGIC here. ..
*/
-void
+static void
md_convert_frag_1 (fragP)
register fragS *fragP;
{
disp = (disp + fragP->fr_offset) - object_address;
#ifdef BFD_ASSEMBLER
- disp += fragP->fr_symbol->sy_frag->fr_address;
+ disp += symbol_get_frag (fragP->fr_symbol)->fr_address;
#endif
switch (fragP->fr_subtype)
case TAB (ABRANCH, BYTE):
know (issbyte (disp));
if (disp == 0)
- as_bad ("short branch with zero offset: use :w");
+ as_bad (_("short branch with zero offset: use :w"));
fragP->fr_opcode[1] = disp;
ext = 0;
break;
ext = 2;
break;
case TAB (ABRANCH, LONG):
- if (cpu_of_arch (current_architecture) < m68020)
+ if (!HAVE_LONG_BRANCH(current_architecture))
{
if (fragP->fr_opcode[0] == 0x61)
/* BSR */
{
fragP->fr_opcode[0] = 0x4E;
fragP->fr_opcode[1] = (char) 0xB9; /* JBSR with ABSL LONG offset */
- subseg_change (text_section, 0); /* @@ */
fix_new (fragP,
fragP->fr_fix,
{
fragP->fr_opcode[0] = 0x4E;
fragP->fr_opcode[1] = (char) 0xF9; /* JMP with ABSL LONG offset */
- subseg_change (text_section, 0); /* @@ */
fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol,
fragP->fr_offset, 0, NO_RELOC);
fragP->fr_fix += 4;
}
else
{
- as_bad ("Long branch offset not supported.");
+ as_bad (_("Long branch offset not supported."));
}
}
else
*buffer_address++ = 0x4e; /* put in jmp long (0x4ef9) */
*buffer_address++ = (char) 0xf9;
fragP->fr_fix += 2; /* account for jmp instruction */
- subseg_change (text_section, 0);
fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol,
fragP->fr_offset, 0, NO_RELOC);
fragP->fr_fix += 4;
*buffer_address++ = (char) 0xf9;
fragP->fr_fix += 6; /* account for bra/jmp instructions */
- subseg_change (text_section, 0);
fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol,
fragP->fr_offset, 0, NO_RELOC);
fragP->fr_fix += 4;
/* The thing to do here is force it to ABSOLUTE LONG, since
PCREL is really trying to shorten an ABSOLUTE address anyway */
/* JF FOO This code has not been tested */
- subseg_change (text_section, 0);
fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol, fragP->fr_offset,
0, NO_RELOC);
if ((fragP->fr_opcode[1] & 0x3F) != 0x3A)
- as_bad ("Internal error (long PC-relative operand) for insn 0x%04x at 0x%lx",
+ as_bad (_("Internal error (long PC-relative operand) for insn 0x%04x at 0x%lx"),
(unsigned) fragP->fr_opcode[0],
(unsigned long) fragP->fr_address);
fragP->fr_opcode[1] &= ~0x3F;
ext = 0;
break;
case TAB (PCLEA, SHORT):
- subseg_change (text_section, 0);
fix_new (fragP, (int) (fragP->fr_fix), 2, fragP->fr_symbol,
fragP->fr_offset, 1, NO_RELOC);
fragP->fr_opcode[1] &= ~0x3F;
ext = 2;
break;
case TAB (PCLEA, LONG):
- subseg_change (text_section, 0);
fixP = fix_new (fragP, (int) (fragP->fr_fix) + 2, 4, fragP->fr_symbol,
fragP->fr_offset, 1, NO_RELOC);
fixP->fx_pcrel_adjust = 2;
disp += 2;
if (!issbyte (disp))
{
- as_bad ("displacement doesn't fit in one byte");
+ as_bad (_("displacement doesn't fit in one byte"));
disp = 0;
}
assert (fragP->fr_fix >= 2);
ext = 0;
break;
case TAB (PCINDEX, SHORT):
- subseg_change (text_section, 0);
disp += 2;
assert (issword (disp));
assert (fragP->fr_fix >= 2);
ext = 2;
break;
case TAB (PCINDEX, LONG):
- subseg_change (text_section, 0);
disp += 2;
fixP = fix_new (fragP, (int) (fragP->fr_fix), 4, fragP->fr_symbol,
fragP->fr_offset, (fragP->fr_opcode[1] & 077) == 073,
void
md_convert_frag (abfd, sec, fragP)
- bfd *abfd;
- segT sec;
+ bfd *abfd ATTRIBUTE_UNUSED;
+ segT sec ATTRIBUTE_UNUSED;
fragS *fragP;
{
md_convert_frag_1 (fragP);
case TAB (ABRANCH, SZ_UNDEF):
{
if ((fragP->fr_symbol != NULL) /* Not absolute */
- && S_GET_SEGMENT (fragP->fr_symbol) == segment)
+ && S_GET_SEGMENT (fragP->fr_symbol) == segment
+ && relaxable_symbol (fragP->fr_symbol))
{
fragP->fr_subtype = TAB (TABTYPE (fragP->fr_subtype), BYTE);
break;
}
- else if ((fragP->fr_symbol == 0) || (cpu_of_arch (current_architecture) < m68020))
+ else if ((fragP->fr_symbol == 0) || !HAVE_LONG_BRANCH(current_architecture))
{
/* On 68000, or for absolute value, switch to abs long */
/* FIXME, we should check abs val, pick short or long */
{
fragP->fr_opcode[0] = 0x4E;
fragP->fr_opcode[1] = (char) 0xB9; /* JBSR with ABSL LONG offset */
- subseg_change (text_section, 0);
fix_new (fragP, fragP->fr_fix, 4,
fragP->fr_symbol, fragP->fr_offset, 0, NO_RELOC);
fragP->fr_fix += 4;
{
fragP->fr_opcode[0] = 0x4E;
fragP->fr_opcode[1] = (char) 0xF9; /* JMP with ABSL LONG offset */
- subseg_change (text_section, 0);
fix_new (fragP, fragP->fr_fix, 4,
fragP->fr_symbol, fragP->fr_offset, 0, NO_RELOC);
fragP->fr_fix += 4;
}
else
{
- as_warn ("Long branch offset to extern symbol not supported.");
+ as_warn (_("Long branch offset to extern symbol not supported."));
}
}
else
case TAB (FBRANCH, SZ_UNDEF):
{
- if (S_GET_SEGMENT (fragP->fr_symbol) == segment || flag_short_refs)
+ if ((S_GET_SEGMENT (fragP->fr_symbol) == segment
+ && relaxable_symbol (fragP->fr_symbol))
+ || flag_short_refs)
{
fragP->fr_subtype = TAB (FBRANCH, SHORT);
fragP->fr_var += 2;
case TAB (PCREL, SZ_UNDEF):
{
- if (S_GET_SEGMENT (fragP->fr_symbol) == segment
+ if ((S_GET_SEGMENT (fragP->fr_symbol) == segment
+ && relaxable_symbol (fragP->fr_symbol))
|| flag_short_refs
- || cpu_of_arch (current_architecture) < m68020)
+ || cpu_of_arch (current_architecture) < m68020
+ || cpu_of_arch (current_architecture) == mcf5200)
{
fragP->fr_subtype = TAB (PCREL, SHORT);
fragP->fr_var += 2;
case TAB (BCC68000, SZ_UNDEF):
{
if ((fragP->fr_symbol != NULL)
- && S_GET_SEGMENT (fragP->fr_symbol) == segment)
+ && S_GET_SEGMENT (fragP->fr_symbol) == segment
+ && relaxable_symbol (fragP->fr_symbol))
{
fragP->fr_subtype = TAB (BCC68000, BYTE);
break;
buffer_address[0] = 0x4e; /* put in jmp long (0x4ef9) */
buffer_address[1] = (char) 0xf8;
fragP->fr_fix += 2; /* account for jmp instruction */
- subseg_change (text_section, 0);
fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol,
fragP->fr_offset, 0, NO_RELOC);
fragP->fr_fix += 2;
buffer_address[0] = 0x4e; /* put in jmp long (0x4ef9) */
buffer_address[1] = (char) 0xf9;
fragP->fr_fix += 2; /* account for jmp instruction */
- subseg_change (text_section, 0);
fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol,
fragP->fr_offset, 0, NO_RELOC);
fragP->fr_fix += 4;
case TAB (DBCC, SZ_UNDEF):
{
- if (fragP->fr_symbol != NULL && S_GET_SEGMENT (fragP->fr_symbol) == segment)
+ if (fragP->fr_symbol != NULL
+ && S_GET_SEGMENT (fragP->fr_symbol) == segment
+ && relaxable_symbol (fragP->fr_symbol))
{
fragP->fr_subtype = TAB (DBCC, SHORT);
fragP->fr_var += 2;
buffer_address[4] = 0x4e; /* Put in Jump Word */
buffer_address[5] = (char) 0xf8;
fragP->fr_fix += 6; /* account for bra/jmp instruction */
- subseg_change (text_section, 0);
fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol,
fragP->fr_offset, 0, NO_RELOC);
fragP->fr_fix += 2;
buffer_address[4] = 0x4e; /* put in jmp long (0x4ef9) */
buffer_address[5] = (char) 0xf9;
fragP->fr_fix += 6; /* account for bra/jmp instruction */
- subseg_change (text_section, 0);
fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol,
fragP->fr_offset, 0, NO_RELOC);
fragP->fr_fix += 4;
case TAB (PCLEA, SZ_UNDEF):
{
- if ((S_GET_SEGMENT (fragP->fr_symbol)) == segment
+ if (((S_GET_SEGMENT (fragP->fr_symbol)) == segment
+ && relaxable_symbol (fragP->fr_symbol))
|| flag_short_refs
- || cpu_of_arch (current_architecture) < m68020)
+ || cpu_of_arch (current_architecture) < m68020
+ || cpu_of_arch (current_architecture) == mcf5200)
{
fragP->fr_subtype = TAB (PCLEA, SHORT);
fragP->fr_var += 2;
} /* TAB(PCLEA,SZ_UNDEF) */
case TAB (PCINDEX, SZ_UNDEF):
- if (S_GET_SEGMENT (fragP->fr_symbol) == segment
- || cpu_of_arch (current_architecture) < m68020)
+ if ((S_GET_SEGMENT (fragP->fr_symbol) == segment
+ && relaxable_symbol (fragP->fr_symbol))
+ || cpu_of_arch (current_architecture) < m68020
+ || cpu_of_arch (current_architecture) == mcf5200)
{
fragP->fr_subtype = TAB (PCINDEX, BYTE);
}
{
case TAB (BCC68000, BYTE):
case TAB (ABRANCH, BYTE):
- /* We can't do a short jump to the next instruction,
- so we force word mode. */
- if (fragP->fr_symbol && S_GET_VALUE (fragP->fr_symbol) == 0 &&
- fragP->fr_symbol->sy_frag == fragP->fr_next)
+ /* We can't do a short jump to the next instruction, so in that
+ case we force word mode. At this point S_GET_VALUE should
+ return the offset of the symbol within its frag. If the
+ symbol is at the start of a frag, and it is the next frag
+ with any data in it (usually this is just the next frag, but
+ assembler listings may introduce empty frags), we must use
+ word mode. */
+ if (fragP->fr_symbol && S_GET_VALUE (fragP->fr_symbol) == 0)
{
- fragP->fr_subtype = TAB (TABTYPE (fragP->fr_subtype), SHORT);
- fragP->fr_var += 2;
+ fragS *stop;
+ fragS *l;
+
+ stop = symbol_get_frag (fragP->fr_symbol);
+ for (l = fragP->fr_next; l != stop; l = l->fr_next)
+ if (l->fr_fix + l->fr_var != 0)
+ break;
+ if (l == stop)
+ {
+ fragP->fr_subtype = TAB (TABTYPE (fragP->fr_subtype), SHORT);
+ fragP->fr_var += 2;
+ }
}
break;
default:
md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol)
char *ptr;
addressT from_addr, to_addr;
- fragS *frag;
- symbolS *to_symbol;
+ fragS *frag ATTRIBUTE_UNUSED;
+ symbolS *to_symbol ATTRIBUTE_UNUSED;
{
valueT offset;
{
valueT offset;
- if (cpu_of_arch (current_architecture) < m68020)
+ if (!HAVE_LONG_BRANCH(current_architecture))
{
offset = to_addr - S_GET_VALUE (to_symbol);
md_number_to_chars (ptr, (valueT) 0x4EF9, 2);
offs (exp) = 0;
if (ok == 10)
{
- as_warn ("expression out of range: defaulting to 1");
+ as_warn (_("expression out of range: defaulting to 1"));
offs (exp) = 1;
}
}
case 10:
if (offs (exp) < 1 || offs (exp) > 8)
{
- as_warn ("expression out of range: defaulting to 1");
+ as_warn (_("expression out of range: defaulting to 1"));
offs (exp) = 1;
}
break;
if (offs (exp) < 0 || offs (exp) > 4095)
{
outrange:
- as_warn ("expression out of range: defaulting to 0");
+ as_warn (_("expression out of range: defaulting to 0"));
offs (exp) = 0;
}
break;
adds (exp) = 0;
subs (exp) = 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"),
offs (exp));
}
}
adds (exp) = 0;
subs (exp) = 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"),
offs (exp));
}
}
break;
case SIZE_BYTE:
if (!isbyte (offs (exp)))
- as_warn ("expression doesn't fit in BYTE");
+ as_warn (_("expression doesn't fit in BYTE"));
break;
case SIZE_WORD:
if (!isword (offs (exp)))
- as_warn ("expression doesn't fit in WORD");
+ as_warn (_("expression doesn't fit in WORD"));
break;
}
}
}
/* These are the back-ends for the various machine dependent pseudo-ops. */
-void demand_empty_rest_of_line (); /* Hate those extra verbose names */
static void
s_data1 (ignore)
- int ignore;
+ int ignore ATTRIBUTE_UNUSED;
{
subseg_set (data_section, 1);
demand_empty_rest_of_line ();
static void
s_data2 (ignore)
- int ignore;
+ int ignore ATTRIBUTE_UNUSED;
{
subseg_set (data_section, 2);
demand_empty_rest_of_line ();
static void
s_bss (ignore)
- int ignore;
+ int ignore ATTRIBUTE_UNUSED;
{
/* We don't support putting frags in the BSS segment, we fake it
by marking in_bss, then looking at s_skip for clues. */
static void
s_even (ignore)
- int ignore;
+ int ignore ATTRIBUTE_UNUSED;
{
register int temp;
register long temp_fill;
temp = 1; /* JF should be 2? */
temp_fill = get_absolute_expression ();
if (!need_pass_2) /* Never make frag if expect extra pass. */
- frag_align (temp, (int) temp_fill);
+ frag_align (temp, (int) temp_fill, 0);
demand_empty_rest_of_line ();
+ record_alignment (now_seg, temp);
}
static void
s_proc (ignore)
- int ignore;
+ int ignore ATTRIBUTE_UNUSED;
{
demand_empty_rest_of_line ();
}
\f
/* Pseudo-ops handled for MRI compatibility. */
+/* This function returns non-zero if the argument is a conditional
+ pseudo-op. This is called when checking whether a pending
+ alignment is needed. */
+
+int
+m68k_conditional_pseudoop (pop)
+ pseudo_typeS *pop;
+{
+ return (pop->poc_handler == s_mri_if
+ || pop->poc_handler == s_mri_else);
+}
+
/* Handle an MRI style chip specification. */
static void
int i;
s = input_line_pointer;
- c = get_symbol_end ();
+ /* We can't use get_symbol_end since the processor names are not proper
+ symbols. */
+ while (is_part_of_name (c = *input_line_pointer++))
+ ;
+ *--input_line_pointer = 0;
for (i = 0; i < n_archs; i++)
if (strcasecmp (s, archs[i].name) == 0)
break;
if (i >= n_archs)
{
- as_bad ("%s: unrecognized processor name", s);
+ as_bad (_("%s: unrecognized processor name"), s);
*input_line_pointer = c;
ignore_rest_of_line ();
return;
{
++input_line_pointer;
s = input_line_pointer;
- c = get_symbol_end ();
+ /* We can't use get_symbol_end since the processor names are not
+ proper symbols. */
+ while (is_part_of_name (c = *input_line_pointer++))
+ ;
+ *--input_line_pointer = 0;
if (strcmp (s, "68881") == 0)
current_architecture |= m68881;
else if (strcmp (s, "68851") == 0)
current_architecture |= m68851;
*input_line_pointer = c;
}
+
+ /* Update info about available control registers. */
+ select_control_regs ();
}
/* The MRI CHIP pseudo-op. */
static void
s_chip (ignore)
- int ignore;
+ int ignore ATTRIBUTE_UNUSED;
{
+ char *stop = NULL;
+ char stopc;
+
+ if (flag_mri)
+ stop = mri_comment_field (&stopc);
mri_chip ();
+ if (flag_mri)
+ mri_comment_end (stop, stopc);
demand_empty_rest_of_line ();
}
static void
s_fopt (ignore)
- int ignore;
+ int ignore ATTRIBUTE_UNUSED;
{
SKIP_WHITESPACE ();
input_line_pointer += 3;
temp = get_absolute_expression ();
if (temp < 0 || temp > 7)
- as_bad ("bad coprocessor id");
+ as_bad (_("bad coprocessor id"));
else
m68k_float_copnum = COP0 + temp;
}
else
{
- as_bad ("unrecognized fopt option");
+ as_bad (_("unrecognized fopt option"));
ignore_rest_of_line ();
return;
}
/* The table used to handle the MRI OPT pseudo-op. */
static void skip_to_comma PARAMS ((int, int));
+static void opt_nest PARAMS ((int, int));
static void opt_chip PARAMS ((int, int));
static void opt_list PARAMS ((int, int));
static void opt_list_symbols PARAMS ((int, int));
{ "mex", 0, 0, 0, 0 },
{ "mc", 0, 0, 0, 0 },
{ "md", 0, 0, 0, 0 },
+ { "nest", opt_nest, 0, 0, 0 },
{ "next", skip_to_comma, 0, 0, 0 },
{ "o", 0, 0, 0, 0 },
{ "old", 0, 0, 0, 0 },
static void
s_opt (ignore)
- int ignore;
+ int ignore ATTRIBUTE_UNUSED;
{
do
{
else if (o->pvar != NULL)
{
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;
*o->pvar = t ? o->arg : o->notarg;
}
}
if (i >= OPTCOUNT)
{
- as_bad ("option `%s' not recognized", s);
+ as_bad (_("option `%s' not recognized"), s);
*input_line_pointer = c;
}
}
static void
skip_to_comma (arg, on)
- int arg;
- int on;
+ int arg ATTRIBUTE_UNUSED;
+ int on ATTRIBUTE_UNUSED;
{
while (*input_line_pointer != ','
&& ! is_end_of_line[(unsigned char) *input_line_pointer])
++input_line_pointer;
}
+/* Handle the OPT NEST=depth option. */
+
+static void
+opt_nest (arg, on)
+ int arg ATTRIBUTE_UNUSED;
+ int on ATTRIBUTE_UNUSED;
+{
+ if (*input_line_pointer != '=')
+ {
+ as_bad (_("bad format of OPT NEST=depth"));
+ return;
+ }
+
+ ++input_line_pointer;
+ max_macro_nest = get_absolute_expression ();
+}
+
/* Handle the OPT P=chip option. */
static void
opt_chip (arg, on)
- int arg;
- int on;
+ int arg ATTRIBUTE_UNUSED;
+ int on ATTRIBUTE_UNUSED;
{
if (*input_line_pointer != '=')
{
static void
opt_list (arg, on)
- int arg;
+ int arg ATTRIBUTE_UNUSED;
int on;
{
listing_list (on);
static void
opt_list_symbols (arg, on)
- int arg;
+ int arg ATTRIBUTE_UNUSED;
int on;
{
if (on)
static void
s_reg (ignore)
- int ignore;
+ int ignore ATTRIBUTE_UNUSED;
{
char *s;
int c;
struct m68k_op rop;
- unsigned long mask;
+ int mask;
+ char *stop = NULL;
+ char stopc;
- if (mri_line_label == NULL)
+ if (line_label == NULL)
{
- as_bad ("missing label");
+ as_bad (_("missing label"));
ignore_rest_of_line ();
return;
}
+ if (flag_mri)
+ stop = mri_comment_field (&stopc);
+
SKIP_WHITESPACE ();
s = input_line_pointer;
if (m68k_ip_op (s, &rop) != 0)
{
if (rop.error == NULL)
- as_bad ("bad register list");
+ as_bad (_("bad register list"));
else
- as_bad ("bad register list: %s", rop.error);
+ as_bad (_("bad register list: %s"), rop.error);
*input_line_pointer = c;
ignore_rest_of_line ();
return;
mask = 1 << 26;
else
{
- as_bad ("bad register list");
+ as_bad (_("bad register list"));
ignore_rest_of_line ();
return;
}
- S_SET_SEGMENT (mri_line_label, absolute_section);
- S_SET_VALUE (mri_line_label, mask);
- mri_line_label->sy_frag = &zero_address_frag;
+ S_SET_SEGMENT (line_label, reg_section);
+ S_SET_VALUE (line_label, ~mask);
+ symbol_set_frag (line_label, &zero_address_frag);
+
+ if (flag_mri)
+ mri_comment_end (stop, stopc);
demand_empty_rest_of_line ();
}
static void
s_save (ignore)
- int ignore;
+ int ignore ATTRIBUTE_UNUSED;
{
struct save_opts *s;
static void
s_restore (ignore)
- int ignore;
+ int ignore ATTRIBUTE_UNUSED;
{
struct save_opts *s;
if (save_stack == NULL)
{
- as_bad ("restore without save");
+ as_bad (_("restore without save"));
ignore_rest_of_line ();
return;
}
/* Some function prototypes. */
+static void mri_assemble PARAMS ((char *));
static char *mri_control_label PARAMS ((void));
static struct mri_control_info *push_mri_control
PARAMS ((enum mri_control_type));
static void pop_mri_control PARAMS ((void));
static int parse_mri_condition PARAMS ((int *));
static int parse_mri_control_operand
- PARAMS ((int *, const char **, const char **, const char **, const char **));
+ PARAMS ((int *, char **, char **, char **, char **));
static int swap_mri_condition PARAMS ((int));
static int reverse_mri_condition PARAMS ((int));
static void build_mri_control_operand
- PARAMS ((int, int, const char *, const char *, const char *, const char *,
- const char *, const char *, int));
+ PARAMS ((int, int, char *, char *, char *, char *, const char *,
+ const char *, int));
static void parse_mri_control_expression
PARAMS ((char *, int, const char *, const char *, int));
+/* Assemble an instruction for an MRI structured control directive. */
+
+static void
+mri_assemble (str)
+ char *str;
+{
+ char *s;
+
+ /* md_assemble expects the opcode to be in lower case. */
+ for (s = str; *s != ' ' && *s != '\0'; s++)
+ {
+ if (isupper ((unsigned char) *s))
+ *s = tolower ((unsigned char) *s);
+ }
+
+ md_assemble (str);
+}
+
/* Generate a new MRI label structured control directive label name. */
static char *
if (*input_line_pointer != '>')
{
- as_bad ("syntax error in structured control directive");
+ as_bad (_("syntax error in structured control directive"));
return 0;
}
static int
parse_mri_control_operand (pcc, leftstart, leftstop, rightstart, rightstop)
int *pcc;
- const char **leftstart;
- const char **leftstop;
- const char **rightstart;
- const char **rightstop;
+ char **leftstart;
+ char **leftstop;
+ char **rightstart;
+ char **rightstop;
{
char *s;
}
if (*s == '\0')
{
- as_bad ("missing condition code in structured control directive");
+ as_bad (_("missing condition code in structured control directive"));
return 0;
}
*leftstart = input_line_pointer;
*leftstop = s;
+ if (*leftstop > *leftstart
+ && ((*leftstop)[-1] == ' ' || (*leftstop)[-1] == '\t'))
+ --*leftstop;
input_line_pointer = s;
if (! parse_mri_condition (pcc))
*rightstart = input_line_pointer;
*rightstop = s;
+ if (*rightstop > *rightstart
+ && ((*rightstop)[-1] == ' ' || (*rightstop)[-1] == '\t'))
+ --*rightstop;
input_line_pointer = s;
rightstop, truelab, falselab, extent)
int qual;
int cc;
- const char *leftstart;
- const char *leftstop;
- const char *rightstart;
- const char *rightstop;
+ char *leftstart;
+ char *leftstop;
+ char *rightstart;
+ char *rightstop;
const char *truelab;
const char *falselab;
int extent;
char *buf;
char *s;
- /* The 68k can't do a general comparision with an immediate operand
- on the right hand side. */
- if (rightstart != NULL && *rightstart == '#')
+ if (leftstart != NULL)
{
- const char *temp;
+ struct m68k_op leftop, rightop;
+ char c;
- cc = swap_mri_condition (cc);
- temp = leftstart;
- leftstart = rightstart;
- rightstart = temp;
- temp = leftstop;
- leftstop = rightstop;
- rightstop = temp;
+ /* Swap the compare operands, if necessary, to produce a legal
+ m68k compare instruction. Comparing a register operand with
+ a non-register operand requires the register to be on the
+ right (cmp, cmpa). Comparing an immediate value with
+ anything requires the immediate value to be on the left
+ (cmpi). */
+
+ c = *leftstop;
+ *leftstop = '\0';
+ (void) m68k_ip_op (leftstart, &leftop);
+ *leftstop = c;
+
+ c = *rightstop;
+ *rightstop = '\0';
+ (void) m68k_ip_op (rightstart, &rightop);
+ *rightstop = c;
+
+ if (rightop.mode == IMMED
+ || ((leftop.mode == DREG || leftop.mode == AREG)
+ && (rightop.mode != DREG && rightop.mode != AREG)))
+ {
+ char *temp;
+
+ cc = swap_mri_condition (cc);
+ temp = leftstart;
+ leftstart = rightstart;
+ rightstart = temp;
+ temp = leftstop;
+ leftstop = rightstop;
+ rightstop = temp;
+ }
}
if (truelab == NULL)
memcpy (s, rightstart, rightstop - rightstart);
s += rightstop - rightstart;
*s = '\0';
- md_assemble (buf);
+ mri_assemble (buf);
free (buf);
}
*s++ = extent;
*s++ = ' ';
strcpy (s, truelab);
- md_assemble (buf);
+ mri_assemble (buf);
free (buf);
}
{
int c;
int cc;
- const char *leftstart;
- const char *leftstop;
- const char *rightstart;
- const char *rightstop;
+ char *leftstart;
+ char *leftstop;
+ char *rightstart;
+ char *rightstop;
c = *stop;
*stop = '\0';
*stop = c;
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
/* A structured control directive must end with THEN with an
optional qualifier. */
s = input_line_pointer;
- while (! is_end_of_line[(unsigned char) *s])
+ while (! is_end_of_line[(unsigned char) *s]
+ && (! flag_mri || *s != '*'))
++s;
--s;
while (s > input_line_pointer && (*s == ' ' || *s == '\t'))
{
if (qual != '\0')
{
- as_bad ("missing then");
+ as_bad (_("missing then"));
ignore_rest_of_line ();
return;
}
else
input_line_pointer = s + 1;
+ if (flag_mri)
+ {
+ while (! is_end_of_line[(unsigned char) *input_line_pointer])
+ ++input_line_pointer;
+ }
+
demand_empty_rest_of_line ();
}
|| mri_control_stack->type != mri_if
|| mri_control_stack->else_seen)
{
- as_bad ("else without matching if");
+ as_bad (_("else without matching if"));
ignore_rest_of_line ();
return;
}
q[0] = qual;
q[1] = '\0';
sprintf (buf, "bra%s %s", q, mri_control_stack->bottom);
- md_assemble (buf);
+ mri_assemble (buf);
free (buf);
colon (mri_control_stack->next);
+ if (flag_mri)
+ {
+ while (! is_end_of_line[(unsigned char) *input_line_pointer])
+ ++input_line_pointer;
+ }
+
demand_empty_rest_of_line ();
}
static void
s_mri_endi (ignore)
- int ignore;
+ int ignore ATTRIBUTE_UNUSED;
{
if (mri_control_stack == NULL
|| mri_control_stack->type != mri_if)
{
- as_bad ("endi without matching if");
+ as_bad (_("endi without matching if"));
ignore_rest_of_line ();
return;
}
pop_mri_control ();
+ if (flag_mri)
+ {
+ while (! is_end_of_line[(unsigned char) *input_line_pointer])
+ ++input_line_pointer;
+ }
+
demand_empty_rest_of_line ();
}
n = n->outer;
if (n == NULL)
{
- as_bad ("break outside of structured loop");
+ as_bad (_("break outside of structured loop"));
ignore_rest_of_line ();
return;
}
ex[0] = extent;
ex[1] = '\0';
sprintf (buf, "bra%s %s", ex, n->bottom);
- md_assemble (buf);
+ mri_assemble (buf);
free (buf);
+ if (flag_mri)
+ {
+ while (! is_end_of_line[(unsigned char) *input_line_pointer])
+ ++input_line_pointer;
+ }
+
demand_empty_rest_of_line ();
}
n = n->outer;
if (n == NULL)
{
- as_bad ("next outside of structured loop");
+ as_bad (_("next outside of structured loop"));
ignore_rest_of_line ();
return;
}
ex[0] = extent;
ex[1] = '\0';
sprintf (buf, "bra%s %s", ex, n->next);
- md_assemble (buf);
+ mri_assemble (buf);
free (buf);
+ if (flag_mri)
+ {
+ while (! is_end_of_line[(unsigned char) *input_line_pointer])
+ ++input_line_pointer;
+ }
+
demand_empty_rest_of_line ();
}
FOR.q var = init { TO | DOWNTO } end [ BY by ] DO.e
*/
+ SKIP_WHITESPACE ();
varstart = input_line_pointer;
/* Look for the '='. */
++input_line_pointer;
if (*input_line_pointer != '=')
{
- as_bad ("missing =");
+ as_bad (_("missing ="));
ignore_rest_of_line ();
return;
}
varstop = input_line_pointer;
+ if (varstop > varstart
+ && (varstop[-1] == ' ' || varstop[-1] == '\t'))
+ --varstop;
++input_line_pointer;
}
if (initstop == NULL)
{
- as_bad ("missing to or downto");
+ as_bad (_("missing to or downto"));
ignore_rest_of_line ();
return;
}
+ if (initstop > initstart
+ && (initstop[-1] == ' ' || initstop[-1] == '\t'))
+ --initstop;
+ SKIP_WHITESPACE ();
endstart = input_line_pointer;
/* Look for BY or DO. */
}
if (endstop == NULL)
{
- as_bad ("missing do");
+ as_bad (_("missing do"));
ignore_rest_of_line ();
return;
}
+ if (endstop > endstart
+ && (endstop[-1] == ' ' || endstop[-1] == '\t'))
+ --endstop;
if (! by)
{
}
else
{
+ SKIP_WHITESPACE ();
bystart = input_line_pointer;
/* Look for DO. */
}
if (bystop == NULL)
{
- as_bad ("missing do");
+ as_bad (_("missing do"));
ignore_rest_of_line ();
return;
}
+ if (bystop > bystart
+ && (bystop[-1] == ' ' || bystop[-1] == '\t'))
+ --bystop;
}
if (*input_line_pointer != '.')
memcpy (s, varstart, varstop - varstart);
s += varstop - varstart;
*s = '\0';
- md_assemble (buf);
+ mri_assemble (buf);
colon (n->top);
memcpy (s, varstart, varstop - varstart);
s += varstop - varstart;
*s = '\0';
- md_assemble (buf);
+ mri_assemble (buf);
/* bcc bottom */
ex[0] = extent;
sprintf (buf, "blt%s %s", ex, n->bottom);
else
sprintf (buf, "bgt%s %s", ex, n->bottom);
- md_assemble (buf);
+ mri_assemble (buf);
/* Put together the add or sub instruction used by ENDF. */
s = buf;
*s = '\0';
n->incr = buf;
+ if (flag_mri)
+ {
+ while (! is_end_of_line[(unsigned char) *input_line_pointer])
+ ++input_line_pointer;
+ }
+
demand_empty_rest_of_line ();
}
static void
s_mri_endf (ignore)
- int ignore;
+ int ignore ATTRIBUTE_UNUSED;
{
if (mri_control_stack == NULL
|| mri_control_stack->type != mri_for)
{
- as_bad ("endf without for");
+ as_bad (_("endf without for"));
ignore_rest_of_line ();
return;
}
colon (mri_control_stack->next);
- md_assemble (mri_control_stack->incr);
+ mri_assemble (mri_control_stack->incr);
sprintf (mri_control_stack->incr, "bra %s", mri_control_stack->top);
- md_assemble (mri_control_stack->incr);
+ mri_assemble (mri_control_stack->incr);
free (mri_control_stack->incr);
pop_mri_control ();
+ if (flag_mri)
+ {
+ while (! is_end_of_line[(unsigned char) *input_line_pointer])
+ ++input_line_pointer;
+ }
+
demand_empty_rest_of_line ();
}
static void
s_mri_repeat (ignore)
- int ignore;
+ int ignore ATTRIBUTE_UNUSED;
{
struct mri_control_info *n;
n = push_mri_control (mri_repeat);
colon (n->top);
+ if (flag_mri)
+ {
+ while (! is_end_of_line[(unsigned char) *input_line_pointer])
+ ++input_line_pointer;
+ }
demand_empty_rest_of_line ();
}
if (mri_control_stack == NULL
|| mri_control_stack->type != mri_repeat)
{
- as_bad ("until without repeat");
+ as_bad (_("until without repeat"));
ignore_rest_of_line ();
return;
}
input_line_pointer = s;
+ pop_mri_control ();
+
+ if (flag_mri)
+ {
+ while (! is_end_of_line[(unsigned char) *input_line_pointer])
+ ++input_line_pointer;
+ }
+
demand_empty_rest_of_line ();
}
struct mri_control_info *n;
s = input_line_pointer;
- while (! is_end_of_line[(unsigned char) *s])
+ while (! is_end_of_line[(unsigned char) *s]
+ && (! flag_mri || *s != '*'))
s++;
--s;
while (*s == ' ' || *s == '\t')
if (s - input_line_pointer < 2
|| strncasecmp (s - 1, "DO", 2) != 0)
{
- as_bad ("missing do");
+ as_bad (_("missing do"));
ignore_rest_of_line ();
return;
}
if (*input_line_pointer == '.')
input_line_pointer += 2;
+ if (flag_mri)
+ {
+ while (! is_end_of_line[(unsigned char) *input_line_pointer])
+ ++input_line_pointer;
+ }
+
demand_empty_rest_of_line ();
}
static void
s_mri_endw (ignore)
- int ignore;
+ int ignore ATTRIBUTE_UNUSED;
{
char *buf;
if (mri_control_stack == NULL
|| mri_control_stack->type != mri_while)
{
- as_bad ("endw without while");
+ as_bad (_("endw without while"));
ignore_rest_of_line ();
return;
}
buf = (char *) xmalloc (20 + strlen (mri_control_stack->next));
sprintf (buf, "bra %s", mri_control_stack->next);
- md_assemble (buf);
+ mri_assemble (buf);
free (buf);
colon (mri_control_stack->bottom);
pop_mri_control ();
+ if (flag_mri)
+ {
+ while (! is_end_of_line[(unsigned char) *input_line_pointer])
+ ++input_line_pointer;
+ }
+
demand_empty_rest_of_line ();
}
\f
* -pic Indicates PIC.
* -k Indicates PIC. (Sun 3 only.)
*
+ * --bitwise-or
+ * Permit `|' to be used in expressions.
+ *
*/
#ifdef OBJ_ELF
#define OPTION_REGISTER_PREFIX_OPTIONAL (OPTION_MD_BASE + 1)
{"register-prefix-optional", no_argument, NULL,
OPTION_REGISTER_PREFIX_OPTIONAL},
+#define OPTION_BITWISE_OR (OPTION_MD_BASE + 2)
+ {"bitwise-or", no_argument, NULL, OPTION_BITWISE_OR},
+#define OPTION_BASE_SIZE_DEFAULT_16 (OPTION_MD_BASE + 3)
+ {"base-size-default-16", no_argument, NULL, OPTION_BASE_SIZE_DEFAULT_16},
+#define OPTION_BASE_SIZE_DEFAULT_32 (OPTION_MD_BASE + 4)
+ {"base-size-default-32", no_argument, NULL, OPTION_BASE_SIZE_DEFAULT_32},
+#define OPTION_DISP_SIZE_DEFAULT_16 (OPTION_MD_BASE + 5)
+ {"disp-size-default-16", no_argument, NULL, OPTION_DISP_SIZE_DEFAULT_16},
+#define OPTION_DISP_SIZE_DEFAULT_32 (OPTION_MD_BASE + 6)
+ {"disp-size-default-32", no_argument, NULL, OPTION_DISP_SIZE_DEFAULT_32},
{NULL, no_argument, NULL, 0}
};
size_t md_longopts_size = sizeof(md_longopts);
if (i == n_archs)
{
unknown:
- as_bad ("unrecognized option `%s'", oarg);
+ as_bad (_("unrecognized option `%s'"), oarg);
return 0;
}
arch = archs[i].arch;
}
if (i == n_archs)
{
- as_bad ("unrecognized architecture specification `%s'", arg);
+ as_bad (_("unrecognized architecture specification `%s'"), arg);
return 0;
}
}
case OPTION_REGISTER_PREFIX_OPTIONAL:
flag_reg_prefix_optional = 1;
+ reg_prefix_optional_seen = 1;
break;
- case 'Q':
+ /* -V: SVR4 argument to print version ID. */
case 'V':
+ print_version_id ();
+ break;
+
+ /* -Qy, -Qn: SVR4 arguments controlling whether a .comment section
+ should be emitted or not. FIXME: Not implemented. */
+ case 'Q':
+ break;
+
+ case OPTION_BITWISE_OR:
+ {
+ char *n, *t;
+ const char *s;
+
+ n = (char *) xmalloc (strlen (m68k_comment_chars) + 1);
+ t = n;
+ for (s = m68k_comment_chars; *s != '\0'; s++)
+ if (*s != '|')
+ *t++ = *s;
+ *t = '\0';
+ m68k_comment_chars = n;
+ }
+ break;
+
+ case OPTION_BASE_SIZE_DEFAULT_16:
+ m68k_index_width_default = SIZE_WORD;
+ break;
+
+ case OPTION_BASE_SIZE_DEFAULT_32:
+ m68k_index_width_default = SIZE_LONG;
+ break;
+
+ case OPTION_DISP_SIZE_DEFAULT_16:
+ m68k_rel32 = 0;
+ m68k_rel32_from_cmdline = 1;
+ break;
+
+ case OPTION_DISP_SIZE_DEFAULT_32:
+ m68k_rel32 = 1;
+ m68k_rel32_from_cmdline = 1;
break;
default:
md_show_usage (stream)
FILE *stream;
{
- fprintf(stream, "\
+ fprintf(stream, _("\
680X0 options:\n\
-l use 1 word for refs to undefined symbols [default 2]\n\
-m68000 | -m68008 | -m68010 | -m68020 | -m68030 | -m68040 | -m68060\n\
| -m68302 | -m68331 | -m68332 | -m68333 | -m68340 | -m68360\n\
- | -mcpu32\n\
+ | -mcpu32 | -m5200\n\
specify variant of 680X0 architecture [default 68020]\n\
-m68881 | -m68882 | -mno-68881 | -mno-68882\n\
target has/lacks floating-point coprocessor\n\
- [default yes for 68020, 68030, and cpu32]\n\
+ [default yes for 68020, 68030, and cpu32]\n"));
+ fprintf(stream, _("\
-m68851 | -mno-68851\n\
target has/lacks memory-management unit coprocessor\n\
[default yes for 68020 and up]\n\
-pic, -k generate position independent code\n\
-S turn jbsr into jsr\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"));
+ fprintf (stream, _("\
+--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\
+--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"));
}
\f
#ifdef TEST2
m68k_ip (&the_ins, buf);
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
{
- 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++)
printf (" 0x%x", the_ins.opcode[n] & 0xffff);
printf (" ");
/* ARGSUSED */
symbolS *
md_undefined_symbol (name)
- char *name;
+ char *name ATTRIBUTE_UNUSED;
{
return 0;
}
/* Round up a section size to the appropriate boundary. */
valueT
md_section_align (segment, size)
- segT segment;
+ segT segment ATTRIBUTE_UNUSED;
valueT size;
{
- return size; /* Byte alignment is fine */
+#ifdef OBJ_AOUT
+#ifdef BFD_ASSEMBLER
+ /* 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
+ 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
+ work. */
+ int align;
+
+ align = bfd_get_section_alignment (stdoutput, segment);
+ size = ((size + (1 << align) - 1) & ((valueT) -1 << align));
+#endif
+#endif
+
+ return size;
}
/* Exactly what point is a PC-relative offset relative TO?
}
#ifndef BFD_ASSEMBLER
+#ifdef OBJ_COFF
+
/*ARGSUSED*/
void
tc_coff_symbol_emit_hook (ignore)
return 0;
}
}
-#endif
+#endif
+#endif
+#ifdef OBJ_ELF
+void m68k_elf_final_processing()
+{
+ /* Set file-specific flags if this is a cpu32 processor */
+ if (cpu_of_arch (current_architecture) & cpu32)
+ elf_elfheader (stdoutput)->e_flags |= EF_CPU32;
+}
+#endif
/* end of tc-m68k.c */