/* tc-m68k.c -- Assemble for the m68k family
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, 2008, 2009, 2010
+ Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
#include "obj-coff.h"
#endif
+#ifdef OBJ_ELF
+static void m68k_elf_cons (int);
+#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
RAMBAR0, RAMBAR1, RAMBAR, MBAR,
0
};
-static const enum m68k_register mcf51qe_ctrl[] = {
- VBR,
+static const enum m68k_register mcf51_ctrl[] = {
+ VBR, CPUCR,
0
};
static const enum m68k_register mcf5206_ctrl[] = {
- CACR, ACR0, ACR1, VBR, RAMBAR0, RAMBAR_ALT, MBAR,
+ CACR, ACR0, ACR1, VBR, RAMBAR0, RAMBAR_ALT, MBAR,
0
};
static const enum m68k_register mcf5208_ctrl[] = {
VBR, CACR, ACR0, ACR1, FLASHBAR, RAMBAR, RAMBAR1,
0
};
+static const enum m68k_register mcf5221x_ctrl[] = {
+ VBR, FLASHBAR, RAMBAR, RAMBAR1,
+ 0
+};
static const enum m68k_register mcf52223_ctrl[] = {
- VBR, CACR, ACR0, ACR1, FLASHBAR, RAMBAR, RAMBAR1,
+ VBR, FLASHBAR, RAMBAR, RAMBAR1,
0
};
static const enum m68k_register mcf52235_ctrl[] = {
- VBR, CACR, ACR0, ACR1, FLASHBAR, RAMBAR, RAMBAR1,
+ VBR, FLASHBAR, RAMBAR, RAMBAR1,
0
};
static const enum m68k_register mcf5225_ctrl[] = {
VBR, CACR, ACR0, ACR1, FLASHBAR, RAMBAR, MBAR, RAMBAR1,
0
};
+static const enum m68k_register mcf52259_ctrl[] = {
+ VBR, FLASHBAR, RAMBAR, RAMBAR1,
+ 0
+};
+static const enum m68k_register mcf52277_ctrl[] = {
+ VBR, CACR, ACR0, ACR1, RAMBAR, RAMBAR1,
+ 0
+};
static const enum m68k_register mcf5235_ctrl[] = {
VBR, CACR, ACR0, ACR1, RAMBAR, RAMBAR1,
0
VBR, CACR, ACR0, ACR1, FLASHBAR, RAMBAR, RAMBAR1,
0
};
+static const enum m68k_register mcf53017_ctrl[] = {
+ VBR, CACR, ACR0, ACR1, RAMBAR, RAMBAR1,
+ 0
+};
static const enum m68k_register mcf5307_ctrl[] = {
- CACR, ACR0, ACR1, VBR, RAMBAR0, RAMBAR_ALT, MBAR,
+ VBR, CACR, ACR0, ACR1, RAMBAR0, RAMBAR_ALT, MBAR,
0
};
static const enum m68k_register mcf5329_ctrl[] = {
MBAR1 /* MBAR */, RAMBAR /* RAMBAR1 */,
0
};
+static const enum m68k_register mcf54418_ctrl[] = {
+ CACR, ASID, ACR0, ACR1, ACR2, ACR3, ACR4, ACR5, ACR6, ACR7, MMUBAR, RGPIOBAR,
+ VBR, PC, RAMBAR1,
+ /* Legacy names */
+ TC /* ASID */, BUSCR /* MMUBAR */,
+ ITT0 /* ACR0 */, ITT1 /* ACR1 */, DTT0 /* ACR2 */, DTT1 /* ACR3 */,
+ RAMBAR /* RAMBAR1 */,
+ 0
+};
static const enum m68k_register mcf54455_ctrl[] = {
CACR, ASID, ACR0, ACR1, ACR2, ACR3, MMUBAR,
- VBR, PC, RAMBAR1, MBAR,
+ VBR, PC, RAMBAR1,
/* Legacy names */
TC /* ASID */, BUSCR /* MMUBAR */,
ITT0 /* ACR0 */, ITT1 /* ACR1 */, DTT0 /* ACR2 */, DTT1 /* ACR3 */,
- MBAR1 /* MBAR */, RAMBAR /* RAMBAR1 */,
+ RAMBAR /* RAMBAR1 */,
0
};
static const enum m68k_register mcf5475_ctrl[] = {
0
};
static const enum m68k_register fido_ctrl[] = {
- SFC, DFC, USP, VBR, CAC, MBB,
+ SFC, DFC, USP, VBR, CAC, MBO,
0
};
#define cpu32_ctrl m68010_ctrl
((x) & (m68020|m68030|m68040|m68060|cpu32|fido_a|mcfisa_b|mcfisa_c))
#define HAVE_LONG_BRANCH(x) \
((x) & (m68020|m68030|m68040|m68060|cpu32|fido_a|mcfisa_b))
+#define LONG_BRANCH_VIA_COND(x) (HAVE_LONG_COND(x) && !HAVE_LONG_BRANCH(x))
static struct m68k_it the_ins; /* The instruction being assembled. */
{0,0,NULL, 0}
};
+/* For -mno-mac we want to turn off all types of mac. */
+static const unsigned no_mac = mcfmac | mcfemac;
+
/* Architecture extensions, here 'alias' -1 for m68k, +1 for cf and 0
for either. */
static const struct m68k_cpu m68k_extensions[] =
{m68851, NULL, "68851", -1},
{m68881, NULL, "68881", -1},
{m68881, NULL, "68882", -1},
-
+
{cfloat|m68881, NULL, "float", 0},
-
+
{mcfhwdiv, NULL, "div", 1},
{mcfusp, NULL, "usp", 1},
- {mcfmac, NULL, "mac", 1},
+ {mcfmac, (void *)&no_mac, "mac", 1},
{mcfemac, NULL, "emac", 1},
-
+
{0,NULL,NULL, 0}
};
{m68040, m68040_ctrl, "68ec040", 1},
{m68060, m68060_ctrl, "68060", 0},
{m68060, m68060_ctrl, "68ec060", 1},
-
+
{cpu32|m68881, cpu32_ctrl, "cpu32", 0},
{cpu32|m68881, cpu32_ctrl, "68330", 1},
{cpu32|m68881, cpu32_ctrl, "68331", 1},
{cpu32|m68881, cpu32_ctrl, "68349", 1},
{cpu32|m68881, cpu32_ctrl, "68360", 1},
- {mcfisa_a|mcfisa_c|mcfusp, mcf51qe_ctrl, "51qe", 0},
-
+ {mcfisa_a|mcfisa_c|mcfusp, mcf51_ctrl, "51", 0},
+ {mcfisa_a|mcfisa_c|mcfusp, mcf51_ctrl, "51ac", 1},
+ {mcfisa_a|mcfisa_c|mcfusp, mcf51_ctrl, "51cn", 1},
+ {mcfisa_a|mcfisa_c|mcfusp|mcfmac, mcf51_ctrl, "51em", 1},
+ {mcfisa_a|mcfisa_c|mcfusp, mcf51_ctrl, "51jm", 1},
+ {mcfisa_a|mcfisa_c|mcfusp, mcf51_ctrl, "51qe", 1},
+
{mcfisa_a, mcf_ctrl, "5200", 0},
{mcfisa_a, mcf_ctrl, "5202", 1},
{mcfisa_a, mcf_ctrl, "5204", 1},
{mcfisa_a, mcf5206_ctrl, "5206", 1},
-
+
{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, "5208", 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, mcf5213_ctrl, "5211", -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|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, "521x", 2},
+ {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfmac|mcfusp, mcf5221x_ctrl, "5221x", 0},
+
{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|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, "52235", 0},
-
+
{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|mcfemac|mcfusp, mcf52277_ctrl, "52274", -1},
+ {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp, mcf52277_ctrl, "52277", 0},
{mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp, mcf5235_ctrl, "5232", -1},
{mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp, mcf5235_ctrl, "5233", -1},
{mcfisa_a|mcfhwdiv|mcfemac, mcf5249_ctrl, "5249", 0},
{mcfisa_a|mcfhwdiv|mcfemac, mcf5250_ctrl, "5250", 0},
{mcfisa_a|mcfhwdiv|mcfemac, mcf5253_ctrl, "5253", 0},
-
+
+ {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp, mcf52259_ctrl, "52252", -1},
+ {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp, mcf52259_ctrl, "52254", -1},
+ {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp, mcf52259_ctrl, "52255", -1},
+ {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp, mcf52259_ctrl, "52256", -1},
+ {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp, mcf52259_ctrl, "52258", -1},
+ {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp, mcf52259_ctrl, "52259", 0},
+
{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, mcf5282_ctrl, "5282", -1},
{mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp, mcf5282_ctrl, "528x", 0},
+ {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp, mcf53017_ctrl, "53011", -1},
+ {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp, mcf53017_ctrl, "53012", -1},
+ {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp, mcf53017_ctrl, "53013", -1},
+ {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp, mcf53017_ctrl, "53014", -1},
+ {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp, mcf53017_ctrl, "53015", -1},
+ {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp, mcf53017_ctrl, "53016", -1},
+ {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp, mcf53017_ctrl, "53017", 0},
+
{mcfisa_a|mcfhwdiv|mcfmac, mcf5307_ctrl, "5307", 0},
{mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp, mcf5329_ctrl, "5327", -1},
{mcfisa_a|mcfisa_b|mcfhwdiv|mcfmac, mcf5407_ctrl, "5407",0},
+ {mcfisa_a|mcfisa_c|mcfhwdiv|mcfemac|mcfusp, mcf54418_ctrl, "54410", -1},
+ {mcfisa_a|mcfisa_c|mcfhwdiv|mcfemac|mcfusp, mcf54418_ctrl, "54415", -1},
+ {mcfisa_a|mcfisa_c|mcfhwdiv|mcfemac|mcfusp, mcf54418_ctrl, "54416", -1},
+ {mcfisa_a|mcfisa_c|mcfhwdiv|mcfemac|mcfusp, mcf54418_ctrl, "54417", -1},
+ {mcfisa_a|mcfisa_c|mcfhwdiv|mcfemac|mcfusp, mcf54418_ctrl, "54418", 0},
+
{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, "54452", -1},
#define PCINDEX 8 /* PC + displacement + index. */
#define ABSTOPCREL 9 /* Absolute relax down to 16-bit PC-relative. */
+/* This relaxation is required for branches where there is no long
+ branch and we are in pcrel mode. We generate a bne/beq pair. */
+#define BRANCHBWPL 10 /* Branch byte, word or pair of longs
+ */
+
/* Note that calls to frag_var need to specify the maximum expansion
- needed; this is currently 10 bytes for DBCC. */
+ needed; this is currently 12 bytes for bne/beq pair. */
+#define FRAG_VAR_SIZE 12
/* The fields are:
How far Forward this mode will reach:
{ 32767, -32768, 2, TAB (ABSTOPCREL, LONG) },
{ 0, 0, 4, 0 },
{ 1, 1, 0, 0 },
+
+ { 127, -128, 0, TAB (BRANCHBWPL, SHORT) },
+ { 32767, -32768, 2, TAB (BRANCHBWPL, LONG) },
+ { 0, 0, 10, 0 },
+ { 1, 1, 0, 0 },
};
/* These are the machine dependent pseudo-ops. These are included so
#endif
#ifdef OBJ_ELF
{"swbeg", s_ignore, 0},
+ {"long", m68k_elf_cons, 4},
#endif
{"extend", float_cons, 'x'},
{"ldouble", float_cons, 'x'},
}
break;
+ case pic_tls_gd:
+ switch (size)
+ {
+ case 1:
+ return BFD_RELOC_68K_TLS_GD8;
+ case 2:
+ return BFD_RELOC_68K_TLS_GD16;
+ case 4:
+ return BFD_RELOC_68K_TLS_GD32;
+ }
+ break;
+
+ case pic_tls_ldm:
+ switch (size)
+ {
+ case 1:
+ return BFD_RELOC_68K_TLS_LDM8;
+ case 2:
+ return BFD_RELOC_68K_TLS_LDM16;
+ case 4:
+ return BFD_RELOC_68K_TLS_LDM32;
+ }
+ break;
+
+ case pic_tls_ldo:
+ switch (size)
+ {
+ case 1:
+ return BFD_RELOC_68K_TLS_LDO8;
+ case 2:
+ return BFD_RELOC_68K_TLS_LDO16;
+ case 4:
+ return BFD_RELOC_68K_TLS_LDO32;
+ }
+ break;
+
+ case pic_tls_ie:
+ switch (size)
+ {
+ case 1:
+ return BFD_RELOC_68K_TLS_IE8;
+ case 2:
+ return BFD_RELOC_68K_TLS_IE16;
+ case 4:
+ return BFD_RELOC_68K_TLS_IE32;
+ }
+ break;
+
+ case pic_tls_le:
+ switch (size)
+ {
+ case 1:
+ return BFD_RELOC_68K_TLS_LE8;
+ case 2:
+ return BFD_RELOC_68K_TLS_LE16;
+ case 4:
+ return BFD_RELOC_68K_TLS_LE32;
+ }
+ break;
+
case pic_none:
if (pcrel)
{
case BFD_RELOC_8_PLTOFF:
case BFD_RELOC_16_PLTOFF:
case BFD_RELOC_32_PLTOFF:
+ case BFD_RELOC_68K_TLS_GD32:
+ case BFD_RELOC_68K_TLS_GD16:
+ case BFD_RELOC_68K_TLS_GD8:
+ case BFD_RELOC_68K_TLS_LDM32:
+ case BFD_RELOC_68K_TLS_LDM16:
+ case BFD_RELOC_68K_TLS_LDM8:
+ case BFD_RELOC_68K_TLS_LDO32:
+ case BFD_RELOC_68K_TLS_LDO16:
+ case BFD_RELOC_68K_TLS_LDO8:
+ case BFD_RELOC_68K_TLS_IE32:
+ case BFD_RELOC_68K_TLS_IE16:
+ case BFD_RELOC_68K_TLS_IE8:
+ case BFD_RELOC_68K_TLS_LE32:
+ case BFD_RELOC_68K_TLS_LE16:
+ case BFD_RELOC_68K_TLS_LE8:
return 0;
case BFD_RELOC_VTABLE_INHERIT:
case BFD_RELOC_8_PLTOFF:
case BFD_RELOC_16_PLTOFF:
case BFD_RELOC_32_PLTOFF:
+ case BFD_RELOC_68K_TLS_GD32:
+ case BFD_RELOC_68K_TLS_GD16:
+ case BFD_RELOC_68K_TLS_GD8:
+ case BFD_RELOC_68K_TLS_LDM32:
+ case BFD_RELOC_68K_TLS_LDM16:
+ case BFD_RELOC_68K_TLS_LDM8:
+ case BFD_RELOC_68K_TLS_LDO32:
+ case BFD_RELOC_68K_TLS_LDO16:
+ case BFD_RELOC_68K_TLS_LDO8:
+ case BFD_RELOC_68K_TLS_IE32:
+ case BFD_RELOC_68K_TLS_IE16:
+ case BFD_RELOC_68K_TLS_IE8:
+ case BFD_RELOC_68K_TLS_LE32:
+ case BFD_RELOC_68K_TLS_LE16:
+ case BFD_RELOC_68K_TLS_LE8:
break;
default:
as_bad_where (fixp->fx_file, fixp->fx_line,
*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)
+ if (OUTPUT_FLAVOR == bfd_target_aout_flavour
+ && fixp->fx_addsy
+ && S_IS_WEAK (fixp->fx_addsy)
+ && ! bfd_is_und_section (S_GET_SEGMENT (fixp->fx_addsy)))
+ {
+ /* PR gas/3041 References to weak symbols must be treated as extern
+ in order to be overridable by the linker, even if they are defined
+ in the same object file. So the original addend must be written
+ "as is" into the output section without further processing.
+ The addend value must be hacked here in order to force
+ bfd_install_relocation() to write the original value into the
+ output section.
+ 1) MD_APPLY_SYM_VALUE() is set to 1 for m68k/a.out, so the symbol
+ value has already been added to the addend in fixup_segment(). We
+ have to remove it.
+ 2) bfd_install_relocation() will incorrectly treat this symbol as
+ resolved, so it will write the symbol value plus its addend and
+ section VMA. As a workaround we can tweak the addend value here in
+ order to get the original value in the section after the call to
+ bfd_install_relocation(). */
+ reloc->addend = fixp->fx_addnumber
+ /* Fix because of MD_APPLY_SYM_VALUE() */
+ - S_GET_VALUE (fixp->fx_addsy)
+ /* Fix for bfd_install_relocation() */
+ - (S_GET_VALUE (fixp->fx_addsy)
+ + S_GET_SEGMENT (fixp->fx_addsy)->vma);
+ }
+ else if (fixp->fx_pcrel)
reloc->addend = fixp->fx_addnumber;
- else if (OUTPUT_FLAVOR == bfd_target_aout_flavour
- && fixp->fx_addsy
- && S_IS_WEAK (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()
- to put the symbol offset into frags referencing a weak symbol. */
- reloc->addend = fixp->fx_addnumber
- - (S_GET_VALUE (fixp->fx_addsy) * 2);
else
reloc->addend = 0;
#else
#endif
reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
- assert (reloc->howto != 0);
+ gas_assert (reloc->howto != 0);
return reloc;
}
/* Make a copy of the operands of this insn so that
we can modify them safely, should we want to. */
- assert (opsfound <= (int) ARRAY_SIZE (operands_backup));
+ gas_assert (opsfound <= (int) ARRAY_SIZE (operands_backup));
for (i = 0; i < opsfound; i++)
operands_backup[i] = the_ins.operands[i];
the_ins.error = buf;
/* 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;
#define APPEND(STRING) \
(strncpy (buf, STRING, space), len = strlen (buf), buf += len, space -= len)
switch (ok_arch)
{
case mcfisa_a:
- APPEND (_("ColdFire ISA_A"));
+ APPEND ("ColdFire ISA_A");
break;
case mcfhwdiv:
- APPEND (_("ColdFire hardware divide"));
+ APPEND ("ColdFire ");
+ APPEND (_("hardware divide"));
break;
case mcfisa_aa:
- APPEND (_("ColdFire ISA_A+"));
+ APPEND ("ColdFire ISA_A+");
break;
case mcfisa_b:
- APPEND (_("ColdFire ISA_B"));
+ APPEND ("ColdFire ISA_B");
break;
case mcfisa_c:
- APPEND (_("ColdFire ISA_C"));
+ APPEND ("ColdFire ISA_C");
break;
case cfloat:
- APPEND (_("ColdFire fpu"));
+ APPEND ("ColdFire fpu");
break;
case mfloat:
- APPEND (_("M68K fpu"));
+ APPEND ("M68K fpu");
break;
case mmmu:
- APPEND (_("M68K mmu"));
+ APPEND ("M68K mmu");
break;
case m68020up:
- APPEND (_("68020 or higher"));
+ APPEND ("68020 ");
+ APPEND (_("or higher"));
break;
case m68000up:
- APPEND (_("68000 or higher"));
+ APPEND ("68000 ");
+ APPEND (_("or higher"));
break;
case m68010up:
- APPEND (_("68010 or higher"));
+ APPEND ("68010 ");
+ APPEND (_("or higher"));
break;
default:
paren = 0;
#undef APPEND
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. */
buf -= 4;
while (*buf != ' ')
for (s = the_ins.args, opP = &the_ins.operands[0]; *s; s += 2, opP++)
{
int have_disp = 0;
+ int use_pl = 0;
/* This switch is a doozy.
Watch the first step; its a big one! */
case 'b': /* Unconditional branch */
have_disp = HAVE_LONG_BRANCH (current_architecture);
+ use_pl = LONG_BRANCH_VIA_COND (current_architecture);
goto var_branch;
case 's': /* Unconditional subroutine */
else
add_frag (adds (&opP->disp),
SEXT (offs (&opP->disp)),
- TAB (BRANCHBW, SZ_UNDEF));
+ (use_pl ? TAB (BRANCHBWPL, SZ_UNDEF)
+ : TAB (BRANCHBW, SZ_UNDEF)));
break;
case 'w':
if (isvar (&opP->disp))
case MMUBAR:
tmpreg = 0x008;
break;
+ case RGPIOBAR:
+ tmpreg = 0x009;
+ break;
+ case ACR4:
+ case ACR5:
+ case ACR6:
+ case ACR7:
+ tmpreg = 0x00c + (opP->reg - ACR4);
+ break;
case USP:
tmpreg = 0x800;
tmpreg = 0x801;
break;
case CAAR:
+ case CPUCR:
tmpreg = 0x802;
break;
case MSP:
case CAC:
tmpreg = 0xFFE;
break;
- case MBB:
+ case MBO:
tmpreg = 0xFFF;
break;
default:
return out;
} /* reverse_8_bits() */
-/* 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
- is the subtype of the frag to be generated; its primary type is
- rs_machine_dependent.
+/* Cause an extra frag to be generated here, inserting up to
+ FRAG_VAR_SIZE bytes. TYPE is the subtype of the frag to be
+ generated; its primary type is rs_machine_dependent.
The TYPE parameter is also used by md_convert_frag_1 and
md_estimate_size_before_relax. The appropriate type of fixup will
{ "dfcr", DFC },
{ "cacr", CACR }, /* Cache Control Register. */
{ "caar", CAAR }, /* Cache Address Register. */
+ { "cpucr", CPUCR }, /* CPU Control Register. */
{ "usp", USP }, /* User Stack Pointer. */
{ "vbr", VBR }, /* Vector Base Register. */
{ "acr1", ACR1 }, /* Access Control Unit 1. */
{ "acr2", ACR2 }, /* Access Control Unit 2. */
{ "acr3", ACR3 }, /* Access Control Unit 3. */
+ { "acr4", ACR4 }, /* Access Control Unit 4. */
+ { "acr5", ACR5 }, /* Access Control Unit 5. */
+ { "acr6", ACR6 }, /* Access Control Unit 6. */
+ { "acr7", ACR7 }, /* Access Control Unit 7. */
{ "tc", TC }, /* MMU Translation Control Register. */
{ "tcr", TC },
{ "mbar2", MBAR2 }, /* mcf5249 registers. */
+ { "rgpiobar", RGPIOBAR }, /* mcf54418 registers. */
+
{ "cac", CAC }, /* fido registers. */
- { "mbb", MBB }, /* fido registers. */
+ { "mbb", MBO }, /* fido registers (obsolete). */
+ { "mbo", MBO }, /* fido registers. */
/* End of control registers. */
{ "ac", AC },
for (n = 1; n < the_ins.nfrag; n++)
wid += 2 * (the_ins.numo - the_ins.fragb[n - 1].fragoff);
/* frag_var part. */
- wid += 10;
+ wid += FRAG_VAR_SIZE;
/* Make sure the whole insn fits in one chunk, in particular that
the var part is attached, as we access one byte before the
variable frag for byte branches. */
the_ins.reloc[m].pic_reloc));
fixP->fx_pcrel_adjust = the_ins.reloc[m].pcrel_fix;
}
- (void) frag_var (rs_machine_dependent, 10, 0,
+ (void) frag_var (rs_machine_dependent, FRAG_VAR_SIZE, 0,
(relax_substateT) (the_ins.fragb[n].fragty),
the_ins.fragb[n].fadd, the_ins.fragb[n].foff, to_beg_P);
}
obstack_begin (&robyn, 4000);
for (i = 0; i < m68k_numopcodes; i++)
{
- hack = slak = (struct m68k_incant *) obstack_alloc (&robyn, sizeof (struct m68k_incant));
+ hack = slak = obstack_alloc (&robyn, sizeof (struct m68k_incant));
do
{
ins = m68k_sorted_opcodes[i];
{
const char *name = m68k_opcode_aliases[i].primary;
const char *alias = m68k_opcode_aliases[i].alias;
- PTR val = hash_find (op_hash, name);
+ void *val = hash_find (op_hash, name);
if (!val)
as_fatal (_("Internal Error: Can't find %s in hash table"), name);
{
const char *name = mri_aliases[i].primary;
const char *alias = mri_aliases[i].alias;
- PTR val = hash_find (op_hash, name);
+ void *val = hash_find (op_hash, name);
if (!val)
as_fatal (_("Internal Error: Can't find %s in hash table"), name);
}
}
-/* Equal to MAX_PRECISION in atof-ieee.c. */
-#define MAX_LITTLENUMS 6
-
-/* Turn a string in input_line_pointer into a floating point constant
- of type TYPE, and store the appropriate bytes in *LITP. The number
- of LITTLENUMS emitted is stored in *SIZEP. An error message is
- returned, or NULL on OK. */
-
char *
md_atof (int type, char *litP, int *sizeP)
{
- int prec;
- LITTLENUM_TYPE words[MAX_LITTLENUMS];
- LITTLENUM_TYPE *wordP;
- char *t;
-
- switch (type)
- {
- case 'f':
- case 'F':
- case 's':
- case 'S':
- prec = 2;
- break;
-
- case 'd':
- case 'D':
- case 'r':
- case 'R':
- prec = 4;
- break;
-
- case 'x':
- case 'X':
- prec = 6;
- break;
-
- case 'p':
- case 'P':
- prec = 6;
- break;
-
- default:
- *sizeP = 0;
- return _("Bad call to MD_ATOF()");
- }
- t = atof_ieee (input_line_pointer, type, words);
- if (t)
- input_line_pointer = t;
-
- *sizeP = prec * sizeof (LITTLENUM_TYPE);
- for (wordP = words; prec--;)
- {
- md_number_to_chars (litP, (long) (*wordP++), sizeof (LITTLENUM_TYPE));
- litP += sizeof (LITTLENUM_TYPE);
- }
- return 0;
+ return ieee_md_atof (type, litP, sizeP, TRUE);
}
void
&& !S_IS_DEFINED (fixP->fx_addsy)
&& !S_IS_WEAK (fixP->fx_addsy))
S_SET_WEAK (fixP->fx_addsy);
+
+ switch (fixP->fx_r_type)
+ {
+ case BFD_RELOC_68K_TLS_GD32:
+ case BFD_RELOC_68K_TLS_GD16:
+ case BFD_RELOC_68K_TLS_GD8:
+ case BFD_RELOC_68K_TLS_LDM32:
+ case BFD_RELOC_68K_TLS_LDM16:
+ case BFD_RELOC_68K_TLS_LDM8:
+ case BFD_RELOC_68K_TLS_LDO32:
+ case BFD_RELOC_68K_TLS_LDO16:
+ case BFD_RELOC_68K_TLS_LDO8:
+ case BFD_RELOC_68K_TLS_IE32:
+ case BFD_RELOC_68K_TLS_IE16:
+ case BFD_RELOC_68K_TLS_IE8:
+ case BFD_RELOC_68K_TLS_LE32:
+ case BFD_RELOC_68K_TLS_LE16:
+ case BFD_RELOC_68K_TLS_LE8:
+ S_SET_THREAD_LOCAL (fixP->fx_addsy);
+ break;
+
+ default:
+ break;
+ }
+
return;
}
#elif defined(OBJ_AOUT)
case TAB (BRABSJUNC, BYTE):
case TAB (BRABSJCOND, BYTE):
case TAB (BRANCHBW, BYTE):
+ case TAB (BRANCHBWPL, BYTE):
know (issbyte (disp));
if (disp == 0)
as_bad_where (fragP->fr_file, fragP->fr_line,
case TAB (BRABSJUNC, SHORT):
case TAB (BRABSJCOND, SHORT):
case TAB (BRANCHBW, SHORT):
+ case TAB (BRANCHBWPL, SHORT):
fragP->fr_opcode[1] = 0x00;
fixP = fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol,
fragP->fr_offset, 1, RELAX_RELOC_PC16);
fragP->fr_offset, 1, RELAX_RELOC_PC32);
fragP->fr_fix += 4;
break;
+ case TAB (BRANCHBWPL, LONG):
+ /* Here we are converting an unconditional branch into a pair of
+ conditional branches, in order to get the range. */
+ fragP->fr_opcode[0] = 0x66; /* bne */
+ fragP->fr_opcode[1] = 0xFF;
+ fixP = fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol,
+ fragP->fr_offset, 1, RELAX_RELOC_PC32);
+ fixP->fx_file = fragP->fr_file;
+ fixP->fx_line = fragP->fr_line;
+ fragP->fr_fix += 4; /* Skip first offset */
+ buffer_address += 4;
+ *buffer_address++ = 0x67; /* beq */
+ *buffer_address++ = 0xff;
+ fragP->fr_fix += 2; /* Skip second branch opcode */
+ fixP = fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol,
+ fragP->fr_offset, 1, RELAX_RELOC_PC32);
+ fragP->fr_fix += 4;
+ break;
case TAB (BRABSJUNC, LONG):
if (fragP->fr_opcode[0] == 0x61) /* jbsr */
{
fragP->fr_fix += 4;
break;
case TAB (PCINDEX, BYTE):
- assert (fragP->fr_fix >= 2);
+ gas_assert (fragP->fr_fix >= 2);
buffer_address[-2] &= ~1;
fixP = fix_new (fragP, fragP->fr_fix - 1, 1, fragP->fr_symbol,
fragP->fr_offset, 1, RELAX_RELOC_PC8);
fixP->fx_pcrel_adjust = 1;
break;
case TAB (PCINDEX, SHORT):
- assert (fragP->fr_fix >= 2);
+ gas_assert (fragP->fr_fix >= 2);
buffer_address[-2] |= 0x1;
buffer_address[-1] = 0x20;
fixP = fix_new (fragP, (int) (fragP->fr_fix), 2, fragP->fr_symbol,
fragP->fr_fix += 2;
break;
case TAB (PCINDEX, LONG):
- assert (fragP->fr_fix >= 2);
+ gas_assert (fragP->fr_fix >= 2);
buffer_address[-2] |= 0x1;
buffer_address[-1] = 0x30;
fixP = fix_new (fragP, (int) (fragP->fr_fix), 4, fragP->fr_symbol,
break;
case TAB (ABSTOPCREL, LONG):
if (flag_keep_pcrel)
- as_fatal (_("Conversion of PC relative displacement to absolute"));
+ as_bad_where (fragP->fr_file, fragP->fr_line,
+ _("Conversion of PC relative displacement to absolute"));
/* The thing to do here is force it to ABSOLUTE LONG, since
ABSTOPCREL is really trying to shorten an ABSOLUTE address anyway. */
if ((fragP->fr_opcode[1] & 0x3F) != 0x3A)
switch (fragP->fr_subtype)
{
case TAB (BRANCHBWL, SZ_UNDEF):
+ case TAB (BRANCHBWPL, SZ_UNDEF):
case TAB (BRABSJUNC, SZ_UNDEF):
case TAB (BRABSJCOND, SZ_UNDEF):
{
case MCC ('g', 't'): return MCC ('l', 't');
case MCC ('l', 'e'): return MCC ('g', 'e');
/* Issue a warning for conditions we can not swap. */
- case MCC ('n', 'e'): return MCC ('n', 'e'); // no problem here
- case MCC ('e', 'q'): return MCC ('e', 'q'); // also no problem
+ case MCC ('n', 'e'): return MCC ('n', 'e'); /* no problem here */
+ case MCC ('e', 'q'): return MCC ('e', 'q'); /* also no problem */
case MCC ('v', 'c'):
case MCC ('v', 's'):
default :
return 0;
}
-/* Set the cpu, issuing errors if it is unrecognized, or invalid */
+/* Set the cpu, issuing errors if it is unrecognized. */
static int
m68k_set_cpu (char const *name, int allow_m, int silent)
as_bad (_("cpu `%s' unrecognized"), name);
return 0;
}
-
- if (selected_cpu && selected_cpu != cpu)
- {
- as_bad (_("already selected `%s' processor"),
- selected_cpu->name);
- return 0;
- }
selected_cpu = cpu;
return 1;
}
-/* Set the architecture, issuing errors if it is unrecognized, or invalid */
+/* Set the architecture, issuing errors if it is unrecognized. */
static int
m68k_set_arch (char const *name, int allow_m, int silent)
as_bad (_("architecture `%s' unrecognized"), name);
return 0;
}
-
- if (selected_arch && selected_arch != arch)
- {
- as_bad (_("already selected `%s' architecture"),
- selected_arch->name);
- return 0;
- }
-
selected_arch = arch;
return 1;
}
}
if (negated)
- not_current_architecture |= ext->arch;
+ not_current_architecture |= (ext->control_regs
+ ? *(unsigned *)ext->control_regs: ext->arch);
else
current_architecture |= ext->arch;
return 1;
{
const char *default_cpu = TARGET_CPU;
int i;
- unsigned int default_arch;
/* Get the canonical name for the default target CPU. */
if (*default_cpu == 'm')
{
if (strcasecmp (default_cpu, m68k_cpus[i].name) == 0)
{
- default_arch = m68k_cpus[i].arch;
while (m68k_cpus[i].alias > 0)
i--;
while (m68k_cpus[i].alias < 0)
{
if (i)
fprintf (stream, " | ");
- fprintf (stream, m68k_archs[i].name);
+ fprintf (stream, "%s", m68k_archs[i].name);
}
fprintf (stream, "\n");
{
if (i)
fprintf (stream, " | ");
- fprintf (stream, m68k_cpus[i].name);
+ fprintf (stream, "%s", m68k_cpus[i].name);
}
fprintf (stream, _("\n"));
}
}
elf_elfheader (stdoutput)->e_flags |= flags;
}
+
+/* Parse @TLSLDO and return the desired relocation. */
+static bfd_reloc_code_real_type
+m68k_elf_suffix (char **str_p, expressionS *exp_p)
+{
+ char ident[20];
+ char *str = *str_p;
+ char *str2;
+ int ch;
+ int len;
+
+ if (*str++ != '@')
+ return BFD_RELOC_UNUSED;
+
+ for (ch = *str, str2 = ident;
+ (str2 < ident + sizeof (ident) - 1
+ && (ISALNUM (ch) || ch == '@'));
+ ch = *++str)
+ {
+ *str2++ = ch;
+ }
+
+ *str2 = '\0';
+ len = str2 - ident;
+
+ if (strncmp (ident, "TLSLDO", 6) == 0
+ && len == 6)
+ {
+ /* Now check for identifier@suffix+constant. */
+ if (*str == '-' || *str == '+')
+ {
+ char *orig_line = input_line_pointer;
+ expressionS new_exp;
+
+ input_line_pointer = str;
+ expression (&new_exp);
+ if (new_exp.X_op == O_constant)
+ {
+ exp_p->X_add_number += new_exp.X_add_number;
+ str = input_line_pointer;
+ }
+
+ if (&input_line_pointer != str_p)
+ input_line_pointer = orig_line;
+ }
+ *str_p = str;
+
+ return BFD_RELOC_68K_TLS_LDO32;
+ }
+
+ return BFD_RELOC_UNUSED;
+}
+
+/* Handles .long <tls_symbol>+0x8000 debug info.
+ Clobbers input_line_pointer, checks end-of-line.
+ Adapted from tc-ppc.c:ppc_elf_cons. */
+static void
+m68k_elf_cons (int nbytes /* 4=.long */)
+{
+ if (is_it_end_of_statement ())
+ {
+ demand_empty_rest_of_line ();
+ return;
+ }
+
+ do
+ {
+ expressionS exp;
+ bfd_reloc_code_real_type reloc;
+
+ expression (&exp);
+ if (exp.X_op == O_symbol
+ && *input_line_pointer == '@'
+ && (reloc = m68k_elf_suffix (&input_line_pointer,
+ &exp)) != BFD_RELOC_UNUSED)
+ {
+ reloc_howto_type *reloc_howto;
+ int size;
+
+ reloc_howto = bfd_reloc_type_lookup (stdoutput, reloc);
+ size = bfd_get_reloc_size (reloc_howto);
+
+ if (size > nbytes)
+ {
+ as_bad (_("%s relocations do not fit in %d bytes\n"),
+ reloc_howto->name, nbytes);
+ }
+ else
+ {
+ char *p;
+ int offset;
+
+ p = frag_more (nbytes);
+ offset = 0;
+ if (target_big_endian)
+ offset = nbytes - size;
+ fix_new_exp (frag_now, p - frag_now->fr_literal + offset, size,
+ &exp, 0, reloc);
+ }
+ }
+ else
+ emit_expr (&exp, (unsigned int) nbytes);
+ }
+ while (*input_line_pointer++ == ',');
+
+ /* Put terminator back into stream. */
+ input_line_pointer--;
+ demand_empty_rest_of_line ();
+}
#endif
int