X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gas%2Fconfig%2Ftc-m68k.c;h=8d9d1fe327cb03ccdda8a1f78f328e254407ae9e;hb=1820262bc909121a408e030195789a70513b9139;hp=89c2df9c29807e89ebe0af2ad5f93babc8fe67da;hpb=6b6e92f432c86611c81a5da6880946bad25b59dc;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/config/tc-m68k.c b/gas/config/tc-m68k.c index 89c2df9c29..8d9d1fe327 100644 --- a/gas/config/tc-m68k.c +++ b/gas/config/tc-m68k.c @@ -1,12 +1,11 @@ /* tc-m68k.c -- Assemble for the m68k family - Copyright 1987, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. + Copyright (C) 1987-2019 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) + the Free Software Foundation; either version 3, or (at your option) any later version. GAS is distributed in the hope that it will be useful, @@ -16,8 +15,8 @@ You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to the Free - Software Foundation, 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. */ + Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA + 02110-1301, USA. */ #include "as.h" #include "safe-ctype.h" @@ -28,10 +27,9 @@ #include "opcode/m68k.h" #include "m68k-parse.h" - -#if defined (OBJ_ELF) #include "elf/m68k.h" -#endif + +static void m68k_elf_cons (int); /* This string holds the chars that always start a comment. If the pre-processor is disabled, these aren't very useful. The macro @@ -66,8 +64,6 @@ const char FLT_CHARS[] = "rRsSfFdDxXeEpP"; changed in read.c . Ideally it shouldn't have to know about it at all, but nothing is ideal around here. */ -const int md_reloc_size = 8; /* Size of relocation record. */ - /* Are we trying to generate PIC code? If so, absolute references ought to be made into linkage table references or pc-relative references. Not implemented. For ELF there are other means @@ -117,7 +113,7 @@ struct label_line { struct label_line *next; symbolS *label; - char *file; + const char *file; unsigned int line; int text; }; @@ -130,7 +126,10 @@ static struct label_line *labels; static struct label_line *current_label; -/* Its an arbitrary name: This means I don't approve of it. +/* Pointer to list holding the opcodes sorted by name. */ +static struct m68k_opcode const ** m68k_sorted_opcodes; + +/* It's an arbitrary name: This means I don't approve of it. See flames below. */ static struct obstack robyn; @@ -147,42 +146,192 @@ struct m68k_incant #define getone(x) ((((x)->m_opcode)>>16)&0xffff) #define gettwo(x) (((x)->m_opcode)&0xffff) -static const enum m68k_register m68000_control_regs[] = { 0 }; -static const enum m68k_register m68010_control_regs[] = { +static const enum m68k_register m68000_ctrl[] = { 0 }; +static const enum m68k_register m68010_ctrl[] = { SFC, DFC, USP, VBR, 0 }; -static const enum m68k_register m68020_control_regs[] = { +static const enum m68k_register m68020_ctrl[] = { SFC, DFC, USP, VBR, CACR, CAAR, MSP, ISP, 0 }; -static const enum m68k_register m68040_control_regs[] = { +static const enum m68k_register m68040_ctrl[] = { SFC, DFC, CACR, TC, ITT0, ITT1, DTT0, DTT1, USP, VBR, MSP, ISP, MMUSR, URP, SRP, 0 }; -static const enum m68k_register m68060_control_regs[] = { +static const enum m68k_register m68060_ctrl[] = { SFC, DFC, CACR, TC, ITT0, ITT1, DTT0, DTT1, BUSCR, USP, VBR, URP, SRP, PCR, 0 }; -static const enum m68k_register mcf_control_regs[] = { +static const enum m68k_register mcf_ctrl[] = { CACR, TC, ACR0, ACR1, ACR2, ACR3, VBR, ROMBAR, - RAMBAR0, RAMBAR1, MBAR, + RAMBAR0, RAMBAR1, RAMBAR, MBAR, + 0 +}; +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, + 0 +}; +static const enum m68k_register mcf5208_ctrl[] = { + CACR, ACR0, ACR1, VBR, RAMBAR, RAMBAR1, + 0 +}; +static const enum m68k_register mcf5210a_ctrl[] = { + VBR, CACR, ACR0, ACR1, ROMBAR, RAMBAR, RAMBAR1, MBAR, + 0 +}; +static const enum m68k_register mcf5213_ctrl[] = { + VBR, RAMBAR, RAMBAR1, FLASHBAR, + 0 +}; +static const enum m68k_register mcf5216_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, FLASHBAR, RAMBAR, RAMBAR1, + 0 +}; +static const enum m68k_register mcf52235_ctrl[] = { + 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 +}; +static const enum m68k_register mcf5249_ctrl[] = { + VBR, CACR, ACR0, ACR1, RAMBAR0, RAMBAR1, RAMBAR, MBAR, MBAR2, + 0 +}; +static const enum m68k_register mcf5250_ctrl[] = { + VBR, + 0 +}; +static const enum m68k_register mcf5253_ctrl[] = { + VBR, CACR, ACR0, ACR1, RAMBAR0, RAMBAR1, RAMBAR, MBAR, MBAR2, + 0 +}; +static const enum m68k_register mcf5271_ctrl[] = { + VBR, CACR, ACR0, ACR1, RAMBAR, RAMBAR1, + 0 +}; +static const enum m68k_register mcf5272_ctrl[] = { + VBR, CACR, ACR0, ACR1, ROMBAR, RAMBAR_ALT, RAMBAR0, MBAR, + 0 +}; +static const enum m68k_register mcf5275_ctrl[] = { + VBR, CACR, ACR0, ACR1, RAMBAR, RAMBAR1, + 0 +}; +static const enum m68k_register mcf5282_ctrl[] = { + 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[] = { + VBR, CACR, ACR0, ACR1, RAMBAR0, RAMBAR_ALT, MBAR, + 0 +}; +static const enum m68k_register mcf5329_ctrl[] = { + VBR, CACR, ACR0, ACR1, RAMBAR, RAMBAR1, 0 }; -static const enum m68k_register mcf528x_control_regs[] = { - CACR, ACR0, ACR1, VBR, FLASHBAR, RAMBAR, +static const enum m68k_register mcf5373_ctrl[] = { + VBR, CACR, ACR0, ACR1, RAMBAR, RAMBAR1, 0 }; -static const enum m68k_register mcfv4e_control_regs[] = { - CACR, TC, ITT0, ITT1, DTT0, DTT1, BUSCR, VBR, PC, ROMBAR, - ROMBAR1, RAMBAR0, RAMBAR1, MPCR, EDRAMBAR, SECMBAR, MBAR, MBAR0, MBAR1, +static const enum m68k_register mcfv4e_ctrl[] = { + CACR, ASID, ACR0, ACR1, ACR2, ACR3, MMUBAR, + VBR, PC, ROMBAR0, ROMBAR1, RAMBAR0, RAMBAR1, + MBAR, SECMBAR, + MPCR /* Multiprocessor Control register */, + EDRAMBAR /* Embedded DRAM Base Address Register */, + /* Permutation control registers. */ PCR1U0, PCR1L0, PCR1U1, PCR1L1, PCR2U0, PCR2L0, PCR2U1, PCR2L1, PCR3U0, PCR3L0, PCR3U1, PCR3L1, + /* Legacy names */ + TC /* ASID */, BUSCR /* MMUBAR */, + ITT0 /* ACR0 */, ITT1 /* ACR1 */, DTT0 /* ACR2 */, DTT1 /* ACR3 */, + MBAR1 /* MBAR */, MBAR2 /* SECMBAR */, MBAR0 /* SECMBAR */, + ROMBAR /* ROMBAR0 */, RAMBAR /* RAMBAR1 */, + 0 +}; +static const enum m68k_register mcf5407_ctrl[] = { + CACR, ASID, ACR0, ACR1, ACR2, ACR3, + VBR, PC, RAMBAR0, RAMBAR1, MBAR, + /* Legacy names */ + TC /* ASID */, + ITT0 /* ACR0 */, ITT1 /* ACR1 */, DTT0 /* ACR2 */, DTT1 /* ACR3 */, + 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, + /* Legacy names */ + TC /* ASID */, BUSCR /* MMUBAR */, + ITT0 /* ACR0 */, ITT1 /* ACR1 */, DTT0 /* ACR2 */, DTT1 /* ACR3 */, + RAMBAR /* RAMBAR1 */, + 0 +}; +static const enum m68k_register mcf5475_ctrl[] = { + CACR, ASID, ACR0, ACR1, ACR2, ACR3, MMUBAR, + VBR, PC, RAMBAR0, RAMBAR1, MBAR, + /* Legacy names */ + TC /* ASID */, BUSCR /* MMUBAR */, + ITT0 /* ACR0 */, ITT1 /* ACR1 */, DTT0 /* ACR2 */, DTT1 /* ACR3 */, + MBAR1 /* MBAR */, RAMBAR /* RAMBAR1 */, + 0 +}; +static const enum m68k_register mcf5485_ctrl[] = { + CACR, ASID, ACR0, ACR1, ACR2, ACR3, MMUBAR, + VBR, PC, RAMBAR0, RAMBAR1, MBAR, + /* Legacy names */ + TC /* ASID */, BUSCR /* MMUBAR */, + ITT0 /* ACR0 */, ITT1 /* ACR1 */, DTT0 /* ACR2 */, DTT1 /* ACR3 */, + MBAR1 /* MBAR */, RAMBAR /* RAMBAR1 */, + 0 +}; +static const enum m68k_register fido_ctrl[] = { + SFC, DFC, USP, VBR, CAC, MBO, 0 }; -#define cpu32_control_regs m68010_control_regs +#define cpu32_ctrl m68010_ctrl static const enum m68k_register *control_regs; @@ -211,7 +360,7 @@ struct m68k_it } fragb[4]; - int nrel; /* Num of reloc strucs in use. */ + int nrel; /* Num of reloc structs in use. */ struct { int n; @@ -226,23 +375,29 @@ struct m68k_it 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 | mcfisa_a)) +#define cpu_of_arch(x) ((x) & (m68000up | mcfisa_a | fido_a)) #define float_of_arch(x) ((x) & mfloat) #define mmu_of_arch(x) ((x) & mmmu) #define arch_coldfire_p(x) ((x) & mcfisa_a) #define arch_coldfire_fpu(x) ((x) & cfloat) /* Macros for determining if cpu supports a specific addressing mode. */ -#define HAVE_LONG_BRANCH(x) ((x) & (m68020|m68030|m68040|m68060|cpu32|mcfisa_b)) +#define HAVE_LONG_DISP(x) \ + ((x) & (m68020|m68030|m68040|m68060|cpu32|fido_a|mcfisa_b|mcfisa_c)) +#define HAVE_LONG_CALL(x) \ + ((x) & (m68020|m68030|m68040|m68060|cpu32|fido_a|mcfisa_b|mcfisa_c)) +#define HAVE_LONG_COND(x) \ + ((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. */ @@ -252,19 +407,12 @@ static struct m68k_it the_ins; /* The instruction being assembled. */ #define offs(ex) ((ex)->exp.X_add_number) /* Macros for adding things to the m68k_it struct. */ -#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)); +#define addword(w) (the_ins.opcode[the_ins.numo++] = (w)) /* Like addword, but goes BEFORE general operands. */ static void -insop (w, opcode) - int w; - const struct m68k_incant *opcode; +insop (int w, const struct m68k_incant *opcode) { int z; for (z = the_ins.numo; z > opcode->m_codenum; --z) @@ -280,23 +428,17 @@ insop (w, opcode) /* The numo+1 kludge is so we can hit the low order byte of the prev word. Blecch. */ static void -add_fix (width, exp, pc_rel, pc_fix) - int width; - struct m68k_exp *exp; - int pc_rel; - int pc_fix; +add_fix (int width, struct m68k_exp *exp, int pc_rel, int pc_fix) { - the_ins.reloc[the_ins.nrel].n = ((width == 'B' || width == '3') - ? (the_ins.numo*2-1) - : (((width)=='b') - ? (the_ins.numo*2+1) - : (the_ins.numo*2))); + 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.numo * 2)); 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; } @@ -311,10 +453,7 @@ add_fix (width, exp, pc_rel, pc_fix) ADD becomes the FR_SYMBOL field of the frag, and OFF the FR_OFFSET. */ static void -add_frag (add, off, type) - symbolS *add; - offsetT off; - int type; +add_frag (symbolS *add, offsetT off, int type) { the_ins.fragb[the_ins.nfrag].fragoff = the_ins.numo; the_ins.fragb[the_ins.nfrag].fadd = add; @@ -325,124 +464,276 @@ add_frag (add, off, type) #define isvar(ex) \ (op (ex) != O_constant && op (ex) != O_big) -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 install_operand PARAMS ((int mode, int val)); -static void s_bss PARAMS ((int)); -static void s_data1 PARAMS ((int)); -static void s_data2 PARAMS ((int)); -static void s_even PARAMS ((int)); -static void s_proc PARAMS ((int)); -static void mri_chip PARAMS ((void)); -static void s_chip PARAMS ((int)); -static void s_fopt PARAMS ((int)); -static void s_opt PARAMS ((int)); -static void s_reg PARAMS ((int)); -static void s_restore PARAMS ((int)); -static void s_save PARAMS ((int)); -static void s_mri_if PARAMS ((int)); -static void s_mri_else PARAMS ((int)); -static void s_mri_endi PARAMS ((int)); -static void s_mri_break PARAMS ((int)); -static void s_mri_next PARAMS ((int)); -static void s_mri_for PARAMS ((int)); -static void s_mri_endf PARAMS ((int)); -static void s_mri_repeat PARAMS ((int)); -static void s_mri_until PARAMS ((int)); -static void s_mri_while PARAMS ((int)); -static void s_mri_endw PARAMS ((int)); -static void md_convert_frag_1 PARAMS ((fragS *)); +static char *crack_operand (char *str, struct m68k_op *opP); +static int get_num (struct m68k_exp *exp, int ok); +static int reverse_16_bits (int in); +static int reverse_8_bits (int in); +static void install_gen_operand (int mode, int val); +static void install_operand (int mode, int val); +static void s_bss (int); +static void s_data1 (int); +static void s_data2 (int); +static void s_even (int); +static void s_proc (int); +static void s_chip (int); +static void s_fopt (int); +static void s_opt (int); +static void s_reg (int); +static void s_restore (int); +static void s_save (int); +static void s_mri_if (int); +static void s_mri_else (int); +static void s_mri_endi (int); +static void s_mri_break (int); +static void s_mri_next (int); +static void s_mri_for (int); +static void s_mri_endf (int); +static void s_mri_repeat (int); +static void s_mri_until (int); +static void s_mri_while (int); +static void s_mri_endw (int); +static void s_m68k_cpu (int); +static void s_m68k_arch (int); + +struct m68k_cpu +{ + unsigned long arch; /* Architecture features. */ + const enum m68k_register *control_regs; /* Control regs on chip */ + const char *name; /* Name */ + int alias; /* Alias for a canonical name. If 1, then + succeeds canonical name, if -1 then + succeeds canonical name, if <-1 ||>1 this is a + deprecated name, and the next/previous name + should be used. */ +}; +/* We hold flags for features explicitly enabled and explicitly + disabled. */ static int current_architecture; -static int current_chip; +static int not_current_architecture; +static const struct m68k_cpu *selected_arch; +static const struct m68k_cpu *selected_cpu; +static int initialized; -struct m68k_cpu - { - unsigned long arch; - unsigned long chip; - const char *name; - int alias; - }; +/* Architecture models. */ +static const struct m68k_cpu m68k_archs[] = +{ + {m68000, m68000_ctrl, "68000", 0}, + {m68010, m68010_ctrl, "68010", 0}, + {m68020|m68881|m68851, m68020_ctrl, "68020", 0}, + {m68030|m68881|m68851, m68020_ctrl, "68030", 0}, + {m68040, m68040_ctrl, "68040", 0}, + {m68060, m68060_ctrl, "68060", 0}, + {cpu32|m68881, cpu32_ctrl, "cpu32", 0}, + {fido_a, fido_ctrl, "fidoa", 0}, + {mcfisa_a|mcfhwdiv, NULL, "isaa", 0}, + {mcfisa_a|mcfhwdiv|mcfisa_aa|mcfusp, NULL, "isaaplus", 0}, + {mcfisa_a|mcfhwdiv|mcfisa_b|mcfusp, NULL, "isab", 0}, + {mcfisa_a|mcfhwdiv|mcfisa_c|mcfusp, NULL, "isac", 0}, + {mcfisa_a|mcfhwdiv|mcfisa_b|mcfmac|mcfusp, mcf_ctrl, "cfv4", 0}, + {mcfisa_a|mcfhwdiv|mcfisa_b|mcfemac|mcfusp|cfloat, mcfv4e_ctrl, "cfv4e", 0}, + {0,0,NULL, 0} +}; -static const struct m68k_cpu archs[] = - { - { m68000, m68000, "68000", 0 }, - { m68010, m68010, "68010", 0 }, - { m68020, m68020, "68020", 0 }, - { m68030, m68030, "68030", 0 }, - { m68040, m68040, "68040", 0 }, - { m68060, m68060, "68060", 0 }, - { cpu32, cpu32, "cpu32", 0 }, - { m68881, m68881, "68881", 0 }, - { m68851, m68851, "68851", 0 }, - { mcfisa_a, mcf5200, "5200", 0 }, - { mcfisa_a|mcfhwdiv|mcfmac, mcf5206e, "5206e", 0 }, - { mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp, mcf521x, "521x", 0 }, - { mcfisa_a|mcfhwdiv|mcfemac, mcf5249, "5249", 0 }, - { mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp, mcf528x, "528x", 0 }, - { mcfisa_a|mcfhwdiv|mcfmac, mcf5307, "5307", 0 }, - { mcfisa_a|mcfhwdiv|mcfisa_b|mcfmac, mcf5407, "5407", 0 }, - { mcfisa_a|mcfhwdiv|mcfisa_b|mcfemac|mcfusp|cfloat, mcf5470, "547x", 0 }, - { mcfisa_a|mcfhwdiv|mcfisa_b|mcfemac|mcfusp|cfloat, mcf5480, "548x", 0 }, - /* Aliases (effectively, so far as gas is concerned) for the above - cpus. */ - { m68020, m68020, "68k", 1 }, - { m68000, m68000, "68008", 1 }, - { m68000, m68000, "68302", 1 }, - { m68000, m68000, "68306", 1 }, - { m68000, m68000, "68307", 1 }, - { m68000, m68000, "68322", 1 }, - { m68000, m68000, "68356", 1 }, - { m68000, m68000, "68ec000", 1 }, - { m68000, m68000, "68hc000", 1 }, - { m68000, m68000, "68hc001", 1 }, - { m68020, m68020, "68ec020", 1 }, - { m68030, m68030, "68ec030", 1 }, - { m68040, m68040, "68ec040", 1 }, - { m68060, m68060, "68ec060", 1 }, - { cpu32, cpu32, "68330", 1 }, - { cpu32, cpu32, "68331", 1 }, - { cpu32, cpu32, "68332", 1 }, - { cpu32, cpu32, "68333", 1 }, - { cpu32, cpu32, "68334", 1 }, - { cpu32, cpu32, "68336", 1 }, - { cpu32, cpu32, "68340", 1 }, - { cpu32, cpu32, "68341", 1 }, - { cpu32, cpu32, "68349", 1 }, - { cpu32, cpu32, "68360", 1 }, - { m68881, m68881, "68882", 1 }, - { mcfisa_a, mcf5200, "5202", 1 }, - { mcfisa_a, mcf5200, "5204", 1 }, - { mcfisa_a, mcf5200, "5206", 1 }, - { mcfisa_a|mcfhwdiv|mcfisa_aa|mcfemac, mcf521x, "5214", 1 }, - { mcfisa_a|mcfhwdiv|mcfisa_aa|mcfemac, mcf521x, "5216", 1 }, - { mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac, mcf528x, "5280", 1 }, - { mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac, mcf528x, "5281", 1 }, - { mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac, mcf528x, "5282", 1 }, - { mcfisa_a|mcfhwdiv|mcfisa_b|mcfmac, mcf5407, "cfv4", 1 }, - { mcfisa_a|mcfhwdiv|mcfisa_b|mcfemac|mcfusp|cfloat, mcf5470, "5470", 1 }, - { mcfisa_a|mcfhwdiv|mcfisa_b|mcfemac|mcfusp|cfloat, mcf5470, "5471", 1 }, - { mcfisa_a|mcfhwdiv|mcfisa_b|mcfemac|mcfusp|cfloat, mcf5470, "5472", 1 }, - { mcfisa_a|mcfhwdiv|mcfisa_b|mcfemac|mcfusp|cfloat, mcf5470, "5473", 1 }, - { mcfisa_a|mcfhwdiv|mcfisa_b|mcfemac|mcfusp|cfloat, mcf5470, "5474", 1 }, - { mcfisa_a|mcfhwdiv|mcfisa_b|mcfemac|mcfusp|cfloat, mcf5470, "5475", 1 }, - { mcfisa_a|mcfhwdiv|mcfisa_b|mcfemac|mcfusp|cfloat, mcf5470, "5480", 1 }, - { mcfisa_a|mcfhwdiv|mcfisa_b|mcfemac|mcfusp|cfloat, mcf5470, "5481", 1 }, - { mcfisa_a|mcfhwdiv|mcfisa_b|mcfemac|mcfusp|cfloat, mcf5470, "5482", 1 }, - { mcfisa_a|mcfhwdiv|mcfisa_b|mcfemac|mcfusp|cfloat, mcf5470, "5483", 1 }, - { mcfisa_a|mcfhwdiv|mcfisa_b|mcfemac|mcfusp|cfloat, mcf5470, "5484", 1 }, - { mcfisa_a|mcfhwdiv|mcfisa_b|mcfemac|mcfusp|cfloat, mcf5470, "5485", 1 }, - { mcfisa_a|mcfhwdiv|mcfisa_b|mcfemac|mcfusp|cfloat, mcf5470, "cfv4e", 1 }, +/* 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, (void *)&no_mac, "mac", 1}, + {mcfemac, NULL, "emac", 1}, + + {0,NULL,NULL, 0} +}; + +/* Processor list */ +static const struct m68k_cpu m68k_cpus[] = +{ + {m68000, m68000_ctrl, "68000", 0}, + {m68000, m68000_ctrl, "68ec000", 1}, + {m68000, m68000_ctrl, "68hc000", 1}, + {m68000, m68000_ctrl, "68hc001", 1}, + {m68000, m68000_ctrl, "68008", 1}, + {m68000, m68000_ctrl, "68302", 1}, + {m68000, m68000_ctrl, "68306", 1}, + {m68000, m68000_ctrl, "68307", 1}, + {m68000, m68000_ctrl, "68322", 1}, + {m68000, m68000_ctrl, "68356", 1}, + {m68010, m68010_ctrl, "68010", 0}, + {m68020|m68881|m68851, m68020_ctrl, "68020", 0}, + {m68020|m68881|m68851, m68020_ctrl, "68k", 1}, + {m68020|m68881|m68851, m68020_ctrl, "68ec020", 1}, + {m68030|m68881|m68851, m68020_ctrl, "68030", 0}, + {m68030|m68881|m68851, m68020_ctrl, "68ec030", 1}, + {m68040, m68040_ctrl, "68040", 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, "68332", 1}, + {cpu32|m68881, cpu32_ctrl, "68333", 1}, + {cpu32|m68881, cpu32_ctrl, "68334", 1}, + {cpu32|m68881, cpu32_ctrl, "68336", 1}, + {cpu32|m68881, cpu32_ctrl, "68340", 1}, + {cpu32|m68881, cpu32_ctrl, "68341", 1}, + {cpu32|m68881, cpu32_ctrl, "68349", 1}, + {cpu32|m68881, cpu32_ctrl, "68360", 1}, + + {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, "51ag", 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|mcfmac, mcf51_ctrl, "51je", 1}, + {mcfisa_a|mcfisa_c|mcfusp|mcfemac, mcf51_ctrl, "51jf", 1}, + {mcfisa_a|mcfisa_c|mcfusp|mcfemac, mcf51_ctrl, "51jg", 1}, + {mcfisa_a|mcfisa_c|mcfusp, mcf51_ctrl, "51jm", 1}, + {mcfisa_a|mcfisa_c|mcfusp|mcfmac, mcf51_ctrl, "51mm", 1}, + {mcfisa_a|mcfisa_c|mcfusp, mcf51_ctrl, "51qe", 1}, + {mcfisa_a|mcfisa_c|mcfusp|mcfemac, mcf51_ctrl, "51qm", 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, "52230", -1}, + {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp, mcf52235_ctrl, "52233", -1}, + {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp, mcf52235_ctrl, "52234", -1}, + {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp, mcf52235_ctrl, "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|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp, mcf5235_ctrl, "5234", -1}, + {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp, mcf5235_ctrl, "5235", -1}, + {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp, mcf5235_ctrl, "523x", 0}, + + {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|mcfhwdiv|mcfmac, mcf5272_ctrl, "5272", 0}, + + {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp, mcf5275_ctrl, "5274", -1}, + {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp, mcf5275_ctrl, "5275", 0}, + + {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp, mcf5282_ctrl, "5280", -1}, + {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp, mcf5282_ctrl, "5281", -1}, + {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp, mcf5282_ctrl, "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_aa|mcfhwdiv|mcfemac|mcfusp, mcf5329_ctrl, "5328", -1}, + {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp, mcf5329_ctrl, "5329", -1}, + {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp, mcf5329_ctrl, "532x", 0}, + + {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp, mcf5373_ctrl, "5372", -1}, + {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp, mcf5373_ctrl, "5373", -1}, + {mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac|mcfusp, mcf5373_ctrl, "537x", 0}, + + {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}, + {mcfisa_a|mcfisa_c|mcfhwdiv|mcfemac|mcfusp, mcf54455_ctrl, "54453", -1}, + {mcfisa_a|mcfisa_c|mcfhwdiv|mcfemac|mcfusp, mcf54455_ctrl, "54454", -1}, + {mcfisa_a|mcfisa_c|mcfhwdiv|mcfemac|mcfusp, mcf54455_ctrl, "54455", 0}, + + {mcfisa_a|mcfisa_b|mcfhwdiv|mcfemac|mcfusp|cfloat, mcf5475_ctrl, "5470", -1}, + {mcfisa_a|mcfisa_b|mcfhwdiv|mcfemac|mcfusp|cfloat, mcf5475_ctrl, "5471", -1}, + {mcfisa_a|mcfisa_b|mcfhwdiv|mcfemac|mcfusp|cfloat, mcf5475_ctrl, "5472", -1}, + {mcfisa_a|mcfisa_b|mcfhwdiv|mcfemac|mcfusp|cfloat, mcf5475_ctrl, "5473", -1}, + {mcfisa_a|mcfisa_b|mcfhwdiv|mcfemac|mcfusp|cfloat, mcf5475_ctrl, "5474", -1}, + {mcfisa_a|mcfisa_b|mcfhwdiv|mcfemac|mcfusp|cfloat, mcf5475_ctrl, "5475", -1}, + {mcfisa_a|mcfisa_b|mcfhwdiv|mcfemac|mcfusp|cfloat, mcf5475_ctrl, "547x", 0}, + + {mcfisa_a|mcfisa_b|mcfhwdiv|mcfemac|mcfusp|cfloat, mcf5485_ctrl, "5480", -1}, + {mcfisa_a|mcfisa_b|mcfhwdiv|mcfemac|mcfusp|cfloat, mcf5485_ctrl, "5481", -1}, + {mcfisa_a|mcfisa_b|mcfhwdiv|mcfemac|mcfusp|cfloat, mcf5485_ctrl, "5482", -1}, + {mcfisa_a|mcfisa_b|mcfhwdiv|mcfemac|mcfusp|cfloat, mcf5485_ctrl, "5483", -1}, + {mcfisa_a|mcfisa_b|mcfhwdiv|mcfemac|mcfusp|cfloat, mcf5485_ctrl, "5484", -1}, + {mcfisa_a|mcfisa_b|mcfhwdiv|mcfemac|mcfusp|cfloat, mcf5485_ctrl, "5485", -1}, + {mcfisa_a|mcfisa_b|mcfhwdiv|mcfemac|mcfusp|cfloat, mcf5485_ctrl, "548x", 0}, + + {fido_a, fido_ctrl, "fidoa", 0}, + {fido_a, fido_ctrl, "fido", 1}, + + {0,NULL,NULL, 0} }; -static const int n_archs = sizeof (archs) / sizeof (archs[0]); +static const struct m68k_cpu *m68k_lookup_cpu +(const char *, const struct m68k_cpu *, int, int *); +static int m68k_set_arch (const char *, int, int); +static int m68k_set_cpu (const char *, int, int); +static int m68k_set_extension (const char *, int, int); +static void m68k_init_arch (void); /* This is the assembler relaxation table for m68k. m68k is a rich CISC architecture and we have a lot of relaxation modes. */ @@ -499,8 +790,14 @@ static const int n_archs = sizeof (archs) / sizeof (archs[0]); #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: @@ -560,6 +857,11 @@ relax_typeS md_relax_table[] = { 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 @@ -579,15 +881,15 @@ const pseudo_typeS md_pseudo_table[] = {"even", s_even, 0}, {"skip", s_space, 0}, {"proc", s_proc, 0}, -#if defined (TE_SUN3) || defined (OBJ_ELF) {"align", s_align_bytes, 0}, -#endif -#ifdef OBJ_ELF {"swbeg", s_ignore, 0}, -#endif + {"long", m68k_elf_cons, 4}, {"extend", float_cons, 'x'}, {"ldouble", float_cons, 'x'}, + {"arch", s_m68k_arch, 0}, + {"cpu", s_m68k_cpu, 0}, + /* The following pseudo-ops are supported for MRI compatibility. */ {"chip", s_chip, 0}, {"comline", s_space, 1}, @@ -632,12 +934,7 @@ const pseudo_typeS md_pseudo_table[] = }; /* The mote pseudo ops are put into the opcode table, since they - don't start with a . they look like opcodes to gas. - */ - -#ifdef M68KCOFF -extern void obj_coff_section PARAMS ((int)); -#endif + don't start with a . they look like opcodes to gas. */ const pseudo_typeS mote_pseudo_table[] = { @@ -653,28 +950,23 @@ 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}, -#endif {0, 0, 0} }; -#define issbyte(x) ((x)>=-128 && (x)<=127) -#define isubyte(x) ((x)>=0 && (x)<=255) -#define issword(x) ((x)>=-32768 && (x)<=32767) -#define isuword(x) ((x)>=0 && (x)<=65535) +/* Truncate and sign-extend at 32 bits, so that building on a 64-bit host + gives identical results to a 32-bit host. */ +#define TRUNC(X) ((valueT) (X) & 0xffffffff) +#define SEXT(X) ((TRUNC (X) ^ 0x80000000) - 0x80000000) -#define isbyte(x) ((x)>= -255 && (x)<=255) -#define isword(x) ((x)>=-65536 && (x)<=65535) -#define islong(x) (1) +#define issbyte(x) ((valueT) SEXT (x) + 0x80 < 0x100) +#define isubyte(x) ((valueT) TRUNC (x) < 0x100) +#define issword(x) ((valueT) SEXT (x) + 0x8000 < 0x10000) +#define isuword(x) ((valueT) TRUNC (x) < 0x10000) -extern char *input_line_pointer; +#define isbyte(x) ((valueT) SEXT (x) + 0xff < 0x1ff) +#define isword(x) ((valueT) SEXT (x) + 0xffff < 0x1ffff) +#define islong(x) (1) static char notend_table[256]; static char alt_notend_table[256]; @@ -683,135 +975,6 @@ static char alt_notend_table[256]; || (*s == ':' \ && alt_notend_table[(unsigned char) s[1]]))) -/* Return a human readable string holding the list of chips that are - valid for a particular architecture, suppressing aliases (unless - there is only one of them). */ - -static char * -find_cf_chip (int architecture) -{ - static char buf[1024]; - int i, j, n_chips, n_alias; - char *cp; - - strcpy (buf, " ("); - cp = buf + strlen (buf); - - for (i = 0, n_chips = 0, n_alias = 0; i < n_archs; ++i) - if (archs[i].arch & architecture) - { - n_chips++; - if (archs[i].alias) - n_alias++; - } - - if (n_chips == 0) - as_fatal (_("no matching ColdFire architectures found")); - - if (n_alias > 1) - n_chips -= n_alias; - - for (i = 0, j = 0; i < n_archs && j < n_chips; ++i) - if (archs[i].arch & architecture) - { - if (j) - { - if (((j == n_chips - 1) && !(n_alias > 1))|| ! n_alias) - { - if (n_chips == 2) - { - strncpy (cp, _(" or "), (sizeof (buf) - (cp - buf))); - cp += strlen (cp); - } - else - { - strncpy (cp, _(", or "), (sizeof (buf) - (cp - buf))); - cp += strlen (cp); - } - } - else - { - strncpy (cp, ", ", (sizeof (buf) - (cp - buf))); - cp += strlen (cp); - } - } - strncpy (cp, archs[i].name, (sizeof (buf) - (cp - buf))); - cp += strlen (cp); - j++; - } - - if (n_alias > 1) - { - strncpy (cp, _(", or aliases"), (sizeof (buf) - (cp - buf))); - cp += strlen (cp); - } - - strncpy (cp, ")", (sizeof (buf) - (cp - buf))); - - return buf; -} - -#if defined (M68KCOFF) && !defined (BFD_ASSEMBLER) - -#ifdef NO_PCREL_RELOCS - -int -make_pcrel_absolute (fixP, add_number) - fixS *fixP; - long *add_number; -{ - register unsigned char *opcode = fixP->fx_frag->fr_opcode; - - /* Rewrite the PC relative instructions to absolute address ones. - these are rumored to be faster, and the apollo linker refuses - to deal with the PC relative relocations. */ - if (opcode[0] == 0x60 && opcode[1] == 0xff) /* BRA -> JMP. */ - { - if (flag_keep_pcrel) - as_fatal (_("Tried to convert PC relative branch to absolute jump")); - opcode[0] = 0x4e; - opcode[1] = 0xf9; - } - else if (opcode[0] == 0x61 && opcode[1] == 0xff) /* BSR -> JSR. */ - { - if (flag_keep_pcrel) - as_fatal (_("Tried to convert PC relative BSR to absolute JSR")); - opcode[0] = 0x4e; - opcode[1] = 0xb9; - } - else - as_fatal (_("Unknown PC relative instruction")); - *add_number -= 4; - return 0; -} - -#endif /* NO_PCREL_RELOCS */ - -short -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 - : fixP->fx_size == 2 ? R_DIR16 - : R_DIR32); -#else - return (fixP->fx_pcrel ? - (fixP->fx_size == 1 ? R_PCRBYTE : - fixP->fx_size == 2 ? R_PCRWORD : - R_PCRLONG) : - (fixP->fx_size == 1 ? R_RELBYTE : - fixP->fx_size == 2 ? R_RELWORD : - R_RELLONG)); -#endif -} - -#endif - -#ifdef OBJ_ELF /* Return zero if the reference to SYMBOL from within the same segment may be relaxed. */ @@ -830,14 +993,8 @@ tc_coff_fix2rtype (fixP) 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; +get_reloc_code (int size, int pcrel, enum pic_relocation pic) { switch (pic) { @@ -889,6 +1046,66 @@ get_reloc_code (size, pcrel, pic) } 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) { @@ -940,8 +1157,7 @@ get_reloc_code (size, pcrel, pic) correctly, so in some cases we force the original symbol to be used. */ int -tc_m68k_fix_adjustable (fixP) - fixS *fixP; +tc_m68k_fix_adjustable (fixS *fixP) { /* Adjust_reloc_syms doesn't know about the GOT. */ switch (fixP->fx_r_type) @@ -958,6 +1174,21 @@ tc_m68k_fix_adjustable (fixP) 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: @@ -969,20 +1200,8 @@ tc_m68k_fix_adjustable (fixP) } } -#else /* !OBJ_ELF */ - -#define get_reloc_code(SIZE,PCREL,OTHER) NO_RELOC - -#define relaxable_symbol(symbol) 1 - -#endif /* OBJ_ELF */ - -#ifdef BFD_ASSEMBLER - arelent * -tc_gen_reloc (section, fixp) - asection *section ATTRIBUTE_UNUSED; - fixS *fixp; +tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp) { arelent *reloc; bfd_reloc_code_real_type code; @@ -1037,6 +1256,21 @@ tc_gen_reloc (section, fixp) 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, @@ -1064,35 +1298,24 @@ tc_gen_reloc (section, fixp) #undef F #undef MAP - reloc = (arelent *) xmalloc (sizeof (arelent)); - reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *)); + reloc = XNEW (arelent); + reloc->sym_ptr_ptr = XNEW (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 - /* Explicit sign extension in case char is - unsigned. */ - + ((fixp->fx_pcrel_adjust & 0xff) ^ 0x80) - 0x80 + + fixp->fx_pcrel_adjust + fixp->fx_addnumber + md_pcrel_from (fixp)); -#endif reloc->howto = bfd_reloc_type_lookup (stdoutput, code); - assert (reloc->howto != 0); + gas_assert (reloc->howto != 0); return reloc; } -#endif /* BFD_ASSEMBLER */ - /* Handle of the OPCODE hash table. NULL means any use before m68k_ip_begin() will crash. */ static struct hash_control *op_hash; @@ -1100,19 +1323,19 @@ static struct hash_control *op_hash; /* Assemble an m68k instruction. */ static void -m68k_ip (instring) - char *instring; +m68k_ip (char *instring) { - register char *p; - register struct m68k_op *opP; - register const struct m68k_incant *opcode; - register const char *s; - register int tmpreg = 0, baseo = 0, outro = 0, nextword; + char *p; + struct m68k_op *opP; + const struct m68k_incant *opcode; + const char *s; + int tmpreg = 0, baseo = 0, outro = 0, nextword; char *pdot, *pdotmove; enum m68k_size siz1, siz2; char c; int losing; int opsfound; + struct m68k_op operands_backup[6]; LITTLENUM_TYPE words[6]; LITTLENUM_TYPE *wordp; unsigned long ok_arch = 0; @@ -1176,7 +1399,7 @@ m68k_ip (instring) char *old = input_line_pointer; *old = '\n'; input_line_pointer = p; - /* Ahh - it's a motorola style psuedo op. */ + /* Ahh - it's a motorola style pseudo op. */ mote_pseudo_table[opcode->m_opnum].poc_handler (mote_pseudo_table[opcode->m_opnum].poc_val); input_line_pointer = old; @@ -1211,7 +1434,7 @@ m68k_ip (instring) opsfound = opP - &the_ins.operands[0]; /* This ugly hack is to support the floating pt opcodes in their - standard form. Essentially, we fake a first enty of type COP#1 */ + standard form. Essentially, we fake a first entry of type COP#1 */ if (opcode->m_operands[0] == 'I') { int n; @@ -1219,8 +1442,7 @@ m68k_ip (instring) for (n = opsfound; n > 0; --n) the_ins.operands[n] = the_ins.operands[n - 1]; - memset ((char *) (&the_ins.operands[0]), '\0', - sizeof (the_ins.operands[0])); + memset (&the_ins.operands[0], '\0', sizeof (the_ins.operands[0])); the_ins.operands[0].mode = CONTROL; the_ins.operands[0].reg = m68k_float_copnum; opsfound++; @@ -1238,7 +1460,15 @@ m68k_ip (instring) ++losing; else { - for (s = opcode->m_operands, opP = &the_ins.operands[0]; + int i; + + /* Make a copy of the operands of this insn so that + we can modify them safely, should we want to. */ + gas_assert (opsfound <= (int) ARRAY_SIZE (operands_backup)); + for (i = 0; i < opsfound; i++) + operands_backup[i] = the_ins.operands[i]; + + for (s = opcode->m_operands, opP = &operands_backup[0]; *s && !losing; s += 2, opP++) { @@ -1692,14 +1922,26 @@ m68k_ip (instring) case 'J': if (opP->mode != CONTROL || opP->reg < USP - || opP->reg > last_movec_reg) + || opP->reg > last_movec_reg + || !control_regs) losing++; else { const enum m68k_register *rp; + for (rp = control_regs; *rp; rp++) - if (*rp == opP->reg) - break; + { + if (*rp == opP->reg) + break; + /* In most CPUs RAMBAR refers to control reg + c05 (RAMBAR1), but a few CPUs have it + refer to c04 (RAMBAR0). */ + else if (*rp == RAMBAR_ALT && opP->reg == RAMBAR) + { + opP->reg = RAMBAR_ALT; + break; + } + } if (*rp == 0) losing++; } @@ -1792,8 +2034,7 @@ m68k_ip (instring) if (opP->mode != IMMED) losing++; else if (opP->disp.exp.X_op != O_constant - || opP->disp.exp.X_add_number < 1 - || opP->disp.exp.X_add_number > 8) + || TRUNC (opP->disp.exp.X_add_number) - 1 > 7) losing++; else if (! m68k_quick && (strncmp (instring, "add", 3) == 0 @@ -1839,8 +2080,7 @@ m68k_ip (instring) if (opP->mode != IMMED) losing++; else if (opP->disp.exp.X_op != O_constant - || opP->disp.exp.X_add_number < 0 - || opP->disp.exp.X_add_number > 7) + || TRUNC (opP->disp.exp.X_add_number) > 7) losing++; break; @@ -1853,9 +2093,24 @@ m68k_ip (instring) if (opP->mode != IMMED) losing++; else if (opP->disp.exp.X_op != O_constant - || opP->disp.exp.X_add_number < -1 - || opP->disp.exp.X_add_number > 7 - || opP->disp.exp.X_add_number == 0) + || (TRUNC (opP->disp.exp.X_add_number) != 0xffffffff + && TRUNC (opP->disp.exp.X_add_number) - 1 > 6)) + losing++; + break; + + case 'j': + if (opP->mode != IMMED) + losing++; + else if (opP->disp.exp.X_op != O_constant + || TRUNC (opP->disp.exp.X_add_number) - 1 > 7) + losing++; + break; + + case 'K': + if (opP->mode != IMMED) + losing++; + else if (opP->disp.exp.X_op != O_constant + || TRUNC (opP->disp.exp.X_add_number) > 511) losing++; break; @@ -1985,8 +2240,8 @@ m68k_ip (instring) case 'y': if (!(opP->mode == AINDR - || (opP->mode == DISP && !(opP->reg == PC || - opP->reg == ZPC)))) + || (opP->mode == DISP + && !(opP->reg == PC || opP->reg == ZPC)))) losing++; break; @@ -2002,6 +2257,12 @@ m68k_ip (instring) if (losing) break; } + + /* Since we have found the correct instruction, copy + in the modifications that we may have made. */ + if (!losing) + for (i = 0; i < opsfound; i++) + the_ins.operands[i] = operands_backup[i]; } if (!losing) @@ -2014,82 +2275,109 @@ m68k_ip (instring) if (ok_arch && !(ok_arch & current_architecture)) { - char buf[200], *cp; - - strncpy (buf, - _("invalid instruction for this architecture; needs "), sizeof (buf)); - cp = buf + strlen (buf); + const struct m68k_cpu *cpu; + int any = 0; + size_t space = 400; + char *buf = XNEWVEC (char, space + 1); + size_t len; + int paren = 1; + + 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. */ + buf[space] = 0; +#define APPEND(STRING) \ + (strncpy (buf, STRING, space), len = strlen (buf), buf += len, space -= len) + + APPEND (_("invalid instruction for this architecture; needs ")); switch (ok_arch) { case mcfisa_a: - strncpy (cp, _("ColdFire ISA_A"), (sizeof (buf) - (cp - buf))); - cp += strlen (cp); - strncpy (cp, find_cf_chip (ok_arch), (sizeof (buf) - (cp - buf))); - cp += strlen (cp); + APPEND ("ColdFire ISA_A"); break; case mcfhwdiv: - strncpy (cp, _("ColdFire hardware divide"), (sizeof (buf) - (cp - buf))); - cp += strlen (cp); - strncpy (cp, find_cf_chip (ok_arch), (sizeof (buf) - (cp - buf))); - cp += strlen (cp); + APPEND ("ColdFire "); + APPEND (_("hardware divide")); break; case mcfisa_aa: - strncpy (cp, _("ColdFire ISA_A+"), (sizeof (buf) - (cp - buf))); - cp += strlen (cp); - strncpy (cp, find_cf_chip (ok_arch), (sizeof (buf) - (cp - buf))); - cp += strlen (cp); + APPEND ("ColdFire ISA_A+"); break; case mcfisa_b: - strncpy (cp, _("ColdFire ISA_B"), (sizeof (buf) - (cp - buf))); - cp += strlen (cp); - strncpy (cp, find_cf_chip (ok_arch), (sizeof (buf) - (cp - buf))); - cp += strlen (cp); + APPEND ("ColdFire ISA_B"); + break; + case mcfisa_c: + APPEND ("ColdFire ISA_C"); break; case cfloat: - strncpy (cp, _("ColdFire fpu"), (sizeof (buf) - (cp - buf))); - cp += strlen (cp); - strncpy (cp, find_cf_chip (ok_arch), (sizeof (buf) - (cp - buf))); - cp += strlen (cp); + APPEND ("ColdFire fpu"); break; case mfloat: - strcpy (cp, _("fpu (68040, 68060 or 68881/68882)")); + APPEND ("M68K fpu"); break; case mmmu: - strcpy (cp, _("mmu (68030 or 68851)")); + APPEND ("M68K mmu"); break; case m68020up: - strcpy (cp, _("68020 or higher")); + APPEND ("68020 "); + APPEND (_("or higher")); break; case m68000up: - strcpy (cp, _("68000 or higher")); + APPEND ("68000 "); + APPEND (_("or higher")); break; case m68010up: - strcpy (cp, _("68010 or higher")); + APPEND ("68010 "); + APPEND (_("or higher")); break; default: + paren = 0; + } + if (paren) + APPEND (" ("); + + for (cpu = m68k_cpus; cpu->name; cpu++) + if (!cpu->alias && (cpu->arch & ok_arch)) { - int got_one = 0, idx; - - for (idx = 0; idx < n_archs; idx++) - { - if ((archs[idx].arch & ok_arch) - && ! archs[idx].alias) - { - if (got_one) - { - strcpy (cp, " or "); - cp += strlen (cp); - } - got_one = 1; - strcpy (cp, archs[idx].name); - cp += strlen (cp); - } - } + const struct m68k_cpu *alias; + int seen_master = 0; + + if (any) + APPEND (", "); + any = 0; + APPEND (cpu->name); + for (alias = cpu; alias != m68k_cpus; alias--) + if (alias[-1].alias >= 0) + break; + for (; !seen_master || alias->alias > 0; alias++) + { + if (!alias->alias) + seen_master = 1; + else + { + if (any) + APPEND (", "); + else + APPEND (" ["); + APPEND (alias->name); + any = 1; + } + } + if (any) + APPEND ("]"); + any = 1; } + if (paren) + APPEND (")"); +#undef APPEND + if (!space) + { + /* We ran out of space, so replace the end of the list + with ellipsis. */ + buf -= 4; + while (*buf != ' ') + buf--; + strcpy (buf, " ..."); } - cp = xmalloc (strlen (buf) + 1); - strcpy (cp, buf); - the_ins.error = cp; } else the_ins.error = _("operands mismatch"); @@ -2108,8 +2396,11 @@ m68k_ip (instring) 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! */ + Watch the first step; it's a big one! */ switch (s[0]) { @@ -2258,17 +2549,26 @@ m68k_ip (instring) nextword = get_num (&opP->disp, 90); + /* Convert mode 5 addressing with a zero offset into + mode 2 addressing to reduce the instruction size by a + word. */ + if (! isvar (&opP->disp) + && (nextword == 0) + && (opP->disp.size == SIZE_UNSPEC) + && (opP->reg >= ADDR0) + && (opP->reg <= ADDR7)) + { + tmpreg = 0x10 + opP->reg - ADDR; /* 2.areg */ + break; + } + if (opP->reg == PC && ! isvar (&opP->disp) && m68k_abspcadd) { opP->disp.exp.X_op = O_symbol; -#ifndef BFD_ASSEMBLER - opP->disp.exp.X_add_symbol = &abs_symbol; -#else opP->disp.exp.X_add_symbol = section_symbol (absolute_section); -#endif } /* Force into index mode. Hope this works. */ @@ -2300,12 +2600,9 @@ m68k_ip (instring) if (opP->reg == PC) { 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 - ) + || opP->disp.pic_reloc != pic_none) { addword (0x0170); add_fix ('l', &opP->disp, 1, 2); @@ -2313,7 +2610,7 @@ m68k_ip (instring) else { add_frag (adds (&opP->disp), - offs (&opP->disp), + SEXT (offs (&opP->disp)), TAB (PCREL1632, SZ_UNDEF)); break; } @@ -2424,7 +2721,7 @@ m68k_ip (instring) default: abort (); } - /* IF its simple, + /* IF it's simple, GET US OUT OF HERE! */ /* Must be INDEX, with an index register. Address @@ -2470,12 +2767,9 @@ m68k_ip (instring) && opP->reg == PC && isvar (&opP->disp) && subs (&opP->disp) == NULL -#ifdef OBJ_ELF /* If the displacement needs pic relocation it cannot be relaxed. */ - && opP->disp.pic_reloc == pic_none -#endif - ) + && opP->disp.pic_reloc == pic_none) { /* The code in md_convert_frag_1 needs to be able to adjust nextword. Call frag_grow @@ -2485,7 +2779,8 @@ m68k_ip (instring) frag_grow (14); nextword += baseo & 0xff; addword (nextword); - add_frag (adds (&opP->disp), offs (&opP->disp), + add_frag (adds (&opP->disp), + SEXT (offs (&opP->disp)), TAB (PCINDEX, SZ_UNDEF)); break; @@ -2618,21 +2913,19 @@ m68k_ip (instring) if (isvar (&opP->disp) && !subs (&opP->disp) && adds (&opP->disp) -#ifdef OBJ_ELF /* If the displacement needs pic relocation it cannot be relaxed. */ && opP->disp.pic_reloc == pic_none -#endif && !flag_long_jumps && !strchr ("~%&$?", s[0])) { tmpreg = 0x3A; /* 7.2 */ add_frag (adds (&opP->disp), - offs (&opP->disp), + SEXT (offs (&opP->disp)), TAB (ABSTOPCREL, SZ_UNDEF)); break; } - /* Fall through into long. */ + /* Fall through. */ case SIZE_LONG: if (isvar (&opP->disp)) add_fix ('l', &opP->disp, 0, 0); @@ -2738,6 +3031,7 @@ m68k_ip (instring) break; case '3': tmpreg &= 0xFF; + /* Fall through. */ case '8': case 'C': case 'j': @@ -2757,6 +3051,7 @@ m68k_ip (instring) case 'B': tmpreg = get_num (&opP->disp, 90); + switch (s[1]) { case 'B': @@ -2768,23 +3063,34 @@ m68k_ip (instring) break; case 'L': long_branch: - if (! HAVE_LONG_BRANCH (current_architecture)) - as_warn (_("Can't use long branches on 68000/68010/5200")); the_ins.opcode[0] |= 0xff; add_fix ('l', &opP->disp, 1, 0); addword (0); addword (0); break; - case 'g': - 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 + case 'g': /* Conditional branch */ + have_disp = HAVE_LONG_CALL (current_architecture); + goto var_branch; + + 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 */ + have_disp = HAVE_LONG_CALL (current_architecture); + + var_branch: + if (subs (&opP->disp) /* We can't relax it. */ + /* If the displacement needs pic relocation it cannot be + relaxed. */ + || opP->disp.pic_reloc != pic_none) + { + if (!have_disp) + as_warn (_("Can't use long branches on this architecture")); + goto long_branch; + } + /* This could either be a symbol, or an absolute address. If it's an absolute address, turn it into an absolute jump right here and keep it out of the @@ -2810,22 +3116,27 @@ m68k_ip (instring) /* Now we know it's going into the relaxer. Now figure out which mode. We try in this order of preference: long branch, absolute jump, byte/word branches only. */ - if (HAVE_LONG_BRANCH (current_architecture)) - add_frag (adds (&opP->disp), offs (&opP->disp), + if (have_disp) + add_frag (adds (&opP->disp), + SEXT (offs (&opP->disp)), TAB (BRANCHBWL, SZ_UNDEF)); else if (! flag_keep_pcrel) { if ((the_ins.opcode[0] == 0x6000) || (the_ins.opcode[0] == 0x6100)) - add_frag (adds (&opP->disp), offs (&opP->disp), + add_frag (adds (&opP->disp), + SEXT (offs (&opP->disp)), TAB (BRABSJUNC, SZ_UNDEF)); else - add_frag (adds (&opP->disp), offs (&opP->disp), + add_frag (adds (&opP->disp), + SEXT (offs (&opP->disp)), TAB (BRABSJCOND, SZ_UNDEF)); } else - add_frag (adds (&opP->disp), offs (&opP->disp), - TAB (BRANCHBW, SZ_UNDEF)); + add_frag (adds (&opP->disp), + SEXT (offs (&opP->disp)), + (use_pl ? TAB (BRANCHBWPL, SZ_UNDEF) + : TAB (BRANCHBW, SZ_UNDEF))); break; case 'w': if (isvar (&opP->disp)) @@ -2835,13 +3146,15 @@ m68k_ip (instring) jumps. */ if (((the_ins.opcode[0] & 0xf0f8) == 0x50c8) && (HAVE_LONG_BRANCH (current_architecture) - || (! flag_keep_pcrel))) + || ! flag_keep_pcrel)) { if (HAVE_LONG_BRANCH (current_architecture)) - add_frag (adds (&opP->disp), offs (&opP->disp), + add_frag (adds (&opP->disp), + SEXT (offs (&opP->disp)), TAB (DBCCLBR, SZ_UNDEF)); else - add_frag (adds (&opP->disp), offs (&opP->disp), + add_frag (adds (&opP->disp), + SEXT (offs (&opP->disp)), TAB (DBCCABSJ, SZ_UNDEF)); break; } @@ -2863,7 +3176,8 @@ m68k_ip (instring) addword (0); } else - add_frag (adds (&opP->disp), offs (&opP->disp), + add_frag (adds (&opP->disp), + SEXT (offs (&opP->disp)), TAB (FBRANCH, SZ_UNDEF)); break; default: @@ -2892,7 +3206,7 @@ m68k_ip (instring) case 'e': /* EMAC ACCx, reg/reg. */ install_operand (s[1], opP->reg - ACC); break; - + case 'E': /* Ignore it. */ break; @@ -2930,6 +3244,7 @@ m68k_ip (instring) tmpreg = 0x002; break; case TC: + case ASID: tmpreg = 0x003; break; case ACR0: @@ -2949,8 +3264,18 @@ m68k_ip (instring) tmpreg = 0x007; break; case BUSCR: + 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; @@ -2959,6 +3284,7 @@ m68k_ip (instring) tmpreg = 0x801; break; case CAAR: + case CPUCR: tmpreg = 0x802; break; case MSP: @@ -2980,6 +3306,7 @@ m68k_ip (instring) tmpreg = 0x808; break; case ROMBAR: + case ROMBAR0: tmpreg = 0xC00; break; case ROMBAR1: @@ -2987,6 +3314,7 @@ m68k_ip (instring) break; case FLASHBAR: case RAMBAR0: + case RAMBAR_ALT: tmpreg = 0xC04; break; case RAMBAR: @@ -3000,6 +3328,7 @@ m68k_ip (instring) tmpreg = 0xC0D; break; case MBAR0: + case MBAR2: case SECMBAR: tmpreg = 0xC0E; break; @@ -3043,6 +3372,12 @@ m68k_ip (instring) case PCR3U1: tmpreg = 0xD0F; break; + case CAC: + tmpreg = 0xFFE; + break; + case MBO: + tmpreg = 0xFFF; + break; default: abort (); } @@ -3306,18 +3641,25 @@ m68k_ip (instring) tmpreg = 0; install_operand (s[1], tmpreg); break; - default: + case 'j': + tmpreg = get_num (&opP->disp, 10); + install_operand (s[1], tmpreg - 1); + break; + case 'K': + tmpreg = get_num (&opP->disp, 65); + install_operand (s[1], tmpreg); + break; + default: abort (); } } - /* By the time whe get here (FINALLY) the_ins contains the complete + /* By the time when get here (FINALLY) the_ins contains the complete instruction, ready to be emitted. . . */ } static int -reverse_16_bits (in) - int in; +reverse_16_bits (int in) { int out = 0; int n; @@ -3336,8 +3678,7 @@ reverse_16_bits (in) } /* reverse_16_bits() */ static int -reverse_8_bits (in) - int in; +reverse_8_bits (int in) { int out = 0; int n; @@ -3355,10 +3696,9 @@ reverse_8_bits (in) 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 @@ -3366,9 +3706,7 @@ reverse_8_bits (in) ADD becomes the FR_SYMBOL field of the frag, and OFF the FR_OFFSET. */ static void -install_operand (mode, val) - int mode; - int val; +install_operand (int mode, int val) { switch (mode) { @@ -3378,6 +3716,9 @@ install_operand (mode, val) case 'd': the_ins.opcode[0] |= val << 9; break; + case 'E': + the_ins.opcode[1] |= val << 9; + break; case '1': the_ins.opcode[1] |= val << 12; break; @@ -3476,11 +3817,11 @@ install_operand (mode, val) case 'f': the_ins.opcode[0] |= ((val & 0x3) << 0); break; - case 'G': + case 'G': /* EMAC accumulator in a EMAC load instruction. */ the_ins.opcode[0] |= ((~val & 0x1) << 7); the_ins.opcode[1] |= ((val & 0x2) << (4 - 1)); break; - case 'H': + case 'H': /* EMAC accumulator in a EMAC non-load instruction. */ the_ins.opcode[0] |= ((val & 0x1) << 7); the_ins.opcode[1] |= ((val & 0x2) << (4 - 1)); break; @@ -3497,14 +3838,12 @@ install_operand (mode, val) } static void -install_gen_operand (mode, val) - int mode; - int val; +install_gen_operand (int mode, int val) { switch (mode) { case '/': /* Special for mask loads for mac/msac insns with - possible mask; trailing_ampersend set in bit 8. */ + possible mask; trailing_ampersand set in bit 8. */ the_ins.opcode[0] |= (val & 0x3f); the_ins.opcode[1] |= (((val & 0x100) >> 8) << 5); break; @@ -3534,13 +3873,11 @@ install_gen_operand (mode, val) then deal with the bitfield hack. */ static char * -crack_operand (str, opP) - register char *str; - register struct m68k_op *opP; +crack_operand (char *str, struct m68k_op *opP) { - register int parens; - register int c; - register char *beg_str; + int parens; + int c; + char *beg_str; int inquote = 0; if (!str) @@ -3606,9 +3943,7 @@ crack_operand (str, opP) */ static void -insert_reg (regname, regnum) - const char *regname; - int regnum; +insert_reg (const char *regname, int regnum) { char buf[100]; int i; @@ -3711,6 +4046,7 @@ static const struct init_entry init_table[] = { "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. */ @@ -3728,22 +4064,28 @@ static const struct init_entry init_table[] = { "dacr0", DTT0 }, /* Data Access Control Register 0. */ { "dacr1", DTT1 }, /* Data Access Control Register 0. */ - /* mcf5200 versions of same. The ColdFire programmer's reference + /* Coldfire versions of same. The ColdFire programmer's reference manual indicated that the order is 2,3,0,1, but Ken Rose says that 0,1,2,3 is the correct order. */ { "acr0", ACR0 }, /* Access Control Unit 0. */ { "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 }, + { "asid", ASID }, { "mmusr", MMUSR }, /* MMU Status Register. */ { "srp", SRP }, /* User Root Pointer. */ { "urp", URP }, /* Supervisor Root Pointer. */ { "buscr", BUSCR }, + { "mmubar", MMUBAR }, { "pcr", PCR }, { "rombar", ROMBAR }, /* ROM Base Address Register. */ @@ -3753,7 +4095,7 @@ static const struct init_entry init_table[] = { "mbar0", MBAR0 }, /* mcfv4e registers. */ { "mbar1", MBAR1 }, /* mcfv4e registers. */ - { "rombar0", ROMBAR }, /* mcfv4e registers. */ + { "rombar0", ROMBAR0 }, /* mcfv4e registers. */ { "rombar1", ROMBAR1 }, /* mcfv4e registers. */ { "mpcr", MPCR }, /* mcfv4e registers. */ { "edrambar", EDRAMBAR }, /* mcfv4e registers. */ @@ -3775,6 +4117,14 @@ static const struct init_entry init_table[] = { "flashbar", FLASHBAR }, /* mcf528x registers. */ { "rambar", RAMBAR }, /* mcf528x registers. */ + + { "mbar2", MBAR2 }, /* mcf5249 registers. */ + + { "rgpiobar", RGPIOBAR }, /* mcf54418 registers. */ + + { "cac", CAC }, /* fido registers. */ + { "mbb", MBO }, /* fido registers (obsolete). */ + { "mbo", MBO }, /* fido registers. */ /* End of control registers. */ { "ac", AC }, @@ -3874,23 +4224,15 @@ static const struct init_entry init_table[] = }; static void -init_regtable () +init_regtable (void) { int i; for (i = 0; init_table[i].name; i++) insert_reg (init_table[i].name, init_table[i].number); } -static int no_68851, no_68881; - -#ifdef OBJ_AOUT -/* a.out machine type. Default to 68020. */ -int m68k_aout_machtype = 2; -#endif - void -md_assemble (str) - char *str; +md_assemble (char *str) { const char *er; short *fromP; @@ -3900,6 +4242,17 @@ md_assemble (str) int shorts_this_frag; fixS *fixP; + if (!selected_cpu && !selected_arch) + { + /* We've not selected an architecture yet. Set the default + now. We do this lazily so that an initial .cpu or .arch directive + can specify. */ + if (!m68k_set_cpu (TARGET_CPU, 1, 1)) + as_bad (_("unrecognized default cpu `%s'"), TARGET_CPU); + } + if (!initialized) + m68k_init_arch (); + /* 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. */ @@ -3935,7 +4288,7 @@ md_assemble (str) } } - memset ((char *) (&the_ins), '\0', sizeof (the_ins)); + memset (&the_ins, '\0', sizeof (the_ins)); m68k_ip (str); er = the_ins.error; if (!er) @@ -3960,10 +4313,8 @@ md_assemble (str) current_label = NULL; } -#ifdef OBJ_ELF /* Tie dwarf2 debug info to the address at the start of the insn. */ dwarf2_emit_insn (0); -#endif if (the_ins.nfrag == 0) { @@ -3998,7 +4349,7 @@ md_assemble (str) 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 out width of %c in md_assemble()"), the_ins.reloc[m].wid); } @@ -4026,7 +4377,7 @@ md_assemble (str) 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. */ @@ -4074,15 +4425,16 @@ md_assemble (str) 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); } - n = (the_ins.numo - the_ins.fragb[n - 1].fragoff); + gas_assert (the_ins.nfrag >= 1); + n = the_ins.numo - the_ins.fragb[the_ins.nfrag - 1].fragoff; shorts_this_frag = 0; if (n) { - toP = frag_more (n * sizeof (short)); + toP = frag_more (n * 2); while (n--) { md_number_to_chars (toP, (long) (*fromP), 2); @@ -4113,13 +4465,40 @@ md_assemble (str) } } +/* Comparison function used by qsort to rank the opcode entries by name. */ + +static int +m68k_compare_opcode (const void * v1, const void * v2) +{ + struct m68k_opcode * op1, * op2; + int ret; + + if (v1 == v2) + return 0; + + op1 = *(struct m68k_opcode **) v1; + op2 = *(struct m68k_opcode **) v2; + + /* Compare the two names. If different, return the comparison. + If the same, return the order they are in the opcode table. */ + ret = strcmp (op1->name, op2->name); + if (ret) + return ret; + if (op1 < op2) + return -1; + return 1; +} + void -md_begin () +md_begin (void) { - /* - * md_begin -- set up hash tables with 68000 instructions. - * similar to what the vax assembler does. ---phr - */ + const struct m68k_opcode *ins; + struct m68k_incant *hack, *slak; + const char *retval = 0; /* Empty string, or error msg text. */ + int i; + + /* Set up hash tables with 68000 instructions. + similar to what the vax assembler does. */ /* RMS claims the thing to do is take the m68k-opcode.h table, and make a copy of it at runtime, adding in the information we want but isn't there. I think it'd be better to have an awk script hack the table @@ -4127,11 +4506,6 @@ md_begin () my lord ghod hath spoken, so we do it this way. Excuse the ugly var names. */ - const struct m68k_opcode *ins; - struct m68k_incant *hack, *slak; - const char *retval = 0; /* Empty string, or error msg text. */ - int i; - if (flag_mri) { flag_reg_prefix_optional = 1; @@ -4140,27 +4514,53 @@ md_begin () m68k_rel32 = 0; } + /* First sort the opcode table into alphabetical order to separate + the order that the assembler wants to see the opcodes from the + order that the disassembler wants to see them. */ + m68k_sorted_opcodes = XNEWVEC (const struct m68k_opcode *, m68k_numopcodes); + + for (i = m68k_numopcodes; i--;) + m68k_sorted_opcodes[i] = m68k_opcodes + i; + + qsort (m68k_sorted_opcodes, m68k_numopcodes, + sizeof (m68k_sorted_opcodes[0]), m68k_compare_opcode); + op_hash = hash_new (); 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 = XOBNEW (&robyn, struct m68k_incant); do { - ins = &m68k_opcodes[i]; - /* We *could* ignore insns that don't match our arch here - but just leaving them out of the hash. */ + ins = m68k_sorted_opcodes[i]; + + /* We must enter all insns into the table, because .arch and + .cpu directives can change things. */ slak->m_operands = ins->args; - slak->m_opnum = strlen (slak->m_operands) / 2; slak->m_arch = ins->arch; slak->m_opcode = ins->opcode; - /* This is kludgey. */ - slak->m_codenum = ((ins->match) & 0xffffL) ? 2 : 1; + + /* In most cases we can determine the number of opcode words + by checking the second word of the mask. Unfortunately + some instructions have 2 opcode words, but no fixed bits + in the second word. A leading dot in the operands + string also indicates 2 opcodes. */ + if (*slak->m_operands == '.') + { + slak->m_operands++; + slak->m_codenum = 2; + } + else if (ins->match & 0xffffL) + slak->m_codenum = 2; + else + slak->m_codenum = 1; + slak->m_opnum = strlen (slak->m_operands) / 2; + if (i + 1 != m68k_numopcodes - && !strcmp (ins->name, m68k_opcodes[i + 1].name)) + && !strcmp (ins->name, m68k_sorted_opcodes[i + 1]->name)) { - slak->m_next = (struct m68k_incant *) obstack_alloc (&robyn, sizeof (struct m68k_incant)); + slak->m_next = XOBNEW (&robyn, struct m68k_incant); i++; } else @@ -4178,7 +4578,8 @@ md_begin () { 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); retval = hash_insert (op_hash, alias, val); @@ -4216,7 +4617,8 @@ md_begin () { 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); retval = hash_jam (op_hash, alias, val); @@ -4230,6 +4632,7 @@ md_begin () notend_table[i] = 0; alt_notend_table[i] = 0; } + notend_table[','] = 1; notend_table['{'] = 1; notend_table['}'] = 1; @@ -4246,18 +4649,15 @@ md_begin () #endif /* We need to put '(' in alt_notend_table to handle - cas2 %d0:%d2,%d3:%d4,(%a0):(%a1) - */ + cas2 %d0:%d2,%d3:%d4,(%a0):(%a1) */ alt_notend_table['('] = 1; /* We need to put '@' in alt_notend_table to handle - cas2 %d0:%d2,%d3:%d4,@(%d0):@(%d1) - */ + cas2 %d0:%d2,%d3:%d4,@(%d0):@(%d1) */ alt_notend_table['@'] = 1; /* We need to put digits in alt_notend_table to handle - bfextu %d0{24:1},%d0 - */ + bfextu %d0{24:1},%d0 */ alt_notend_table['0'] = 1; alt_notend_table['1'] = 1; alt_notend_table['2'] = 1; @@ -4274,10 +4674,10 @@ md_begin () gas expects pseudo ops to start with a dot. */ { int n = 0; + while (mote_pseudo_table[n].poc_name) { - hack = (struct m68k_incant *) - obstack_alloc (&robyn, sizeof (struct m68k_incant)); + hack = XOBNEW (&robyn, struct m68k_incant); hash_insert (op_hash, mote_pseudo_table[n].poc_name, (char *) hack); hack->m_operands = 0; @@ -4289,155 +4689,34 @@ md_begin () 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 (current_chip) - { - case 0: - if (verbose) - as_warn (_("architecture not yet selected: defaulting to 68020")); - control_regs = m68020_control_regs; - break; - - 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: - case mcf5407: - control_regs = mcf_control_regs; - break; - case mcf528x: - case mcf521x: - control_regs = mcf528x_control_regs; - break; - case mcf5470: - case mcf5480: - control_regs = mcfv4e_control_regs; - break; - default: - abort (); - } } -void -m68k_init_after_args () -{ - if (cpu_of_arch (current_architecture) == 0) - { - int i; - const char *default_cpu = TARGET_CPU; - - if (*default_cpu == 'm') - default_cpu++; - for (i = 0; i < n_archs; i++) - if (strcasecmp (default_cpu, archs[i].name) == 0) - break; - if (i == n_archs) - { - as_bad (_("unrecognized default cpu `%s' ???"), TARGET_CPU); - current_architecture |= m68020; - } - else - current_architecture |= archs[i].arch; - } - /* Permit m68881 specification with all cpus; those that can't work - with a coprocessor could be doing emulation. */ - if (current_architecture & m68851) - { - if (current_architecture & m68040) - { - as_warn (_("68040 and 68851 specified; mmu instructions may assemble incorrectly")); - } - } - /* What other incompatibilities could we check for? */ - - /* Toss in some default assumptions about coprocessors. */ - if (!no_68881 - && (cpu_of_arch (current_architecture) - /* Can CPU32 have a 68881 coprocessor?? */ - & (m68020 | m68030 | cpu32))) - { - current_architecture |= m68881; - } - if (!no_68851 - && (cpu_of_arch (current_architecture) & m68020up) != 0 - && (cpu_of_arch (current_architecture) & m68040up) == 0) - { - current_architecture |= m68851; - } - if (no_68881 && (current_architecture & m68881)) - 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")); - -#ifdef OBJ_AOUT - /* Work out the magic number. This isn't very general. */ - if (current_architecture & m68000) - m68k_aout_machtype = 0; - else if (current_architecture & m68010) - m68k_aout_machtype = 1; - else if (current_architecture & m68020) - m68k_aout_machtype = 2; - else - m68k_aout_machtype = 2; -#endif - - /* Note which set of "movec" control registers is available. */ - select_control_regs (); - - if (cpu_of_arch (current_architecture) < m68020 - || arch_coldfire_p (current_architecture)) - md_relax_table[TAB (PCINDEX, BYTE)].rlx_more = 0; -} /* This is called when a label is defined. */ void -m68k_frob_label (sym) - symbolS *sym; +m68k_frob_label (symbolS *sym) { struct label_line *n; - n = (struct label_line *) xmalloc (sizeof *n); + n = XNEW (struct label_line); n->next = labels; n->label = sym; - as_where (&n->file, &n->line); + n->file = as_where (&n->line); n->text = 0; labels = n; current_label = n; + + dwarf2_emit_label (sym); } /* This is called when a value that is not an instruction is emitted. */ void -m68k_flush_pending_output () +m68k_flush_pending_output (void) { current_label = NULL; } @@ -4447,8 +4726,7 @@ m68k_flush_pending_output () odd location. */ void -m68k_frob_symbol (sym) - symbolS *sym; +m68k_frob_symbol (symbolS *sym) { if (S_GET_SEGMENT (sym) == reg_section && (int) S_GET_VALUE (sym) < 0) @@ -4478,8 +4756,7 @@ m68k_frob_symbol (sym) pseudo-op. */ void -m68k_mri_mode_change (on) - int on; +m68k_mri_mode_change (int on) { if (on) { @@ -4513,82 +4790,20 @@ m68k_mri_mode_change (on) } } -/* 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 (type, litP, sizeP) - char type; - char *litP; - int *sizeP; +const 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 -md_number_to_chars (buf, val, n) - char *buf; - valueT val; - int n; +md_number_to_chars (char *buf, valueT val, int n) { number_to_chars_bigendian (buf, val, n); } void -md_apply_fix3 (fixP, valP, seg) - fixS *fixP; - valueT *valP; - segT seg ATTRIBUTE_UNUSED; +md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) { offsetT val = *valP; addressT upper_limit; @@ -4600,12 +4815,11 @@ md_apply_fix3 (fixP, valP, seg) buf += fixP->fx_where; /* End ibm compiler workaround. */ - val = ((val & 0xffffffff) ^ 0x80000000) - 0x80000000; + val = SEXT (val); if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0) fixP->fx_done = 1; -#ifdef OBJ_ELF if (fixP->fx_addsy) { memset (buf, 0, fixP->fx_size); @@ -4615,15 +4829,37 @@ md_apply_fix3 (fixP, valP, seg) && !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; } -#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) { @@ -4669,7 +4905,8 @@ md_apply_fix3 (fixP, valP, seg) 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 %ld out of range"), (long)val); /* 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 @@ -4677,15 +4914,13 @@ md_apply_fix3 (fixP, valP, seg) 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_r_type == BFD_RELOC_8_PCREL) && 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")); } /* *fragP has been relaxed to its final size, and now needs to have @@ -4693,19 +4928,18 @@ md_apply_fix3 (fixP, valP, seg) MAGIC here. .. */ static void -md_convert_frag_1 (fragP) - register fragS *fragP; +md_convert_frag_1 (fragS *fragP) { long disp; - fixS *fixP; + fixS *fixP = NULL; /* Address in object code of the displacement. */ - register int object_address = fragP->fr_fix + fragP->fr_address; + int object_address = fragP->fr_fix + fragP->fr_address; /* Address in gas core of the place to store the displacement. */ /* This convinces the native rs6000 compiler to generate the code we want. */ - register char *buffer_address = fragP->fr_literal; + char *buffer_address = fragP->fr_literal; buffer_address += fragP->fr_fix; /* End ibm compiler workaround. */ @@ -4719,6 +4953,7 @@ md_convert_frag_1 (fragP) 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, @@ -4731,36 +4966,57 @@ md_convert_frag_1 (fragP) case TAB (BRABSJUNC, SHORT): case TAB (BRABSJCOND, SHORT): case TAB (BRANCHBW, SHORT): + case TAB (BRANCHBWPL, SHORT): fragP->fr_opcode[1] = 0x00; - fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol, fragP->fr_offset, - 1, RELAX_RELOC_PC16); + fixP = fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol, + fragP->fr_offset, 1, RELAX_RELOC_PC16); fragP->fr_fix += 2; break; case TAB (BRANCHBWL, LONG): fragP->fr_opcode[1] = (char) 0xFF; - fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol, fragP->fr_offset, - 1, RELAX_RELOC_PC32); + 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 (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 */ { if (flag_keep_pcrel) - as_fatal (_("Tried to convert PC relative BSR to absolute JSR")); + as_bad_where (fragP->fr_file, fragP->fr_line, + _("Conversion of PC relative BSR to absolute JSR")); fragP->fr_opcode[0] = 0x4E; fragP->fr_opcode[1] = (char) 0xB9; /* JSR with ABSL LONG operand. */ - fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol, fragP->fr_offset, - 0, RELAX_RELOC_ABS32); + fixP = fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol, + fragP->fr_offset, 0, RELAX_RELOC_ABS32); fragP->fr_fix += 4; } else if (fragP->fr_opcode[0] == 0x60) /* jbra */ { if (flag_keep_pcrel) - as_fatal (_("Tried to convert PC relative branch to absolute jump")); + as_bad_where (fragP->fr_file, fragP->fr_line, + _("Conversion of PC relative branch to absolute jump")); fragP->fr_opcode[0] = 0x4E; fragP->fr_opcode[1] = (char) 0xF9; /* JMP with ABSL LONG operand. */ - fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol, fragP->fr_offset, - 0, RELAX_RELOC_ABS32); + fixP = fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol, + fragP->fr_offset, 0, RELAX_RELOC_ABS32); fragP->fr_fix += 4; } else @@ -4772,7 +5028,8 @@ md_convert_frag_1 (fragP) break; case TAB (BRABSJCOND, LONG): if (flag_keep_pcrel) - as_fatal (_("Tried to convert PC relative conditional branch to absolute jump")); + as_bad_where (fragP->fr_file, fragP->fr_line, + _("Conversion of PC relative conditional branch to absolute jump")); /* Only Bcc 68000 instructions can come here Change bcc into b!cc/jmp absl long. */ @@ -4785,35 +5042,32 @@ md_convert_frag_1 (fragP) *buffer_address++ = 0x4e; /* put in jmp long (0x4ef9) */ *buffer_address++ = (char) 0xf9; fragP->fr_fix += 2; /* Account for jmp instruction. */ - fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol, - fragP->fr_offset, 0, RELAX_RELOC_ABS32); + fixP = fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol, + fragP->fr_offset, 0, RELAX_RELOC_ABS32); fragP->fr_fix += 4; break; case TAB (FBRANCH, SHORT): know ((fragP->fr_opcode[1] & 0x40) == 0); - fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol, fragP->fr_offset, - 1, RELAX_RELOC_PC16); + fixP = fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol, + fragP->fr_offset, 1, RELAX_RELOC_PC16); fragP->fr_fix += 2; break; case TAB (FBRANCH, LONG): fragP->fr_opcode[1] |= 0x40; /* Turn on LONG bit. */ - fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol, fragP->fr_offset, - 1, RELAX_RELOC_PC32); + 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 (DBCCLBR, SHORT): case TAB (DBCCABSJ, SHORT): - fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol, fragP->fr_offset, - 1, RELAX_RELOC_PC16); + fixP = fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol, + fragP->fr_offset, 1, RELAX_RELOC_PC16); fragP->fr_fix += 2; break; case TAB (DBCCLBR, LONG): /* Only DBcc instructions can come here. Change dbcc into dbcc/bral. JF: these used to be fr_opcode[2-7], but that's wrong. */ - if (flag_keep_pcrel) - as_fatal (_("Tried to convert DBcc to absolute jump")); - *buffer_address++ = 0x00; /* Branch offset = 4. */ *buffer_address++ = 0x04; *buffer_address++ = 0x60; /* Put in bra pc+6. */ @@ -4822,8 +5076,8 @@ md_convert_frag_1 (fragP) *buffer_address++ = (char) 0xff; fragP->fr_fix += 6; /* Account for bra/jmp instructions. */ - fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol, fragP->fr_offset, 1, - RELAX_RELOC_PC32); + 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 (DBCCABSJ, LONG): @@ -4831,7 +5085,8 @@ md_convert_frag_1 (fragP) Change dbcc into dbcc/jmp. JF: these used to be fr_opcode[2-7], but that's wrong. */ if (flag_keep_pcrel) - as_fatal (_("Tried to convert PC relative conditional branch to absolute jump")); + as_bad_where (fragP->fr_file, fragP->fr_line, + _("Conversion of PC relative conditional branch to absolute jump")); *buffer_address++ = 0x00; /* Branch offset = 4. */ *buffer_address++ = 0x04; @@ -4841,15 +5096,15 @@ md_convert_frag_1 (fragP) *buffer_address++ = (char) 0xf9; fragP->fr_fix += 6; /* Account for bra/jmp instructions. */ - fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol, fragP->fr_offset, 0, - RELAX_RELOC_ABS32); + fixP = fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol, + fragP->fr_offset, 0, RELAX_RELOC_ABS32); fragP->fr_fix += 4; break; case TAB (PCREL1632, SHORT): fragP->fr_opcode[1] &= ~0x3F; fragP->fr_opcode[1] |= 0x3A; /* 072 - mode 7.2 */ - fix_new (fragP, (int) (fragP->fr_fix), 2, fragP->fr_symbol, - fragP->fr_offset, 1, RELAX_RELOC_PC16); + fixP = fix_new (fragP, (int) (fragP->fr_fix), 2, fragP->fr_symbol, + fragP->fr_offset, 1, RELAX_RELOC_PC16); fragP->fr_fix += 2; break; case TAB (PCREL1632, LONG): @@ -4864,14 +5119,14 @@ md_convert_frag_1 (fragP) 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, @@ -4880,7 +5135,7 @@ md_convert_frag_1 (fragP) 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, @@ -4889,61 +5144,51 @@ md_convert_frag_1 (fragP) fragP->fr_fix += 4; break; case TAB (ABSTOPCREL, SHORT): - fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol, fragP->fr_offset, - 1, RELAX_RELOC_PC16); + fixP = fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol, + fragP->fr_offset, 1, RELAX_RELOC_PC16); fragP->fr_fix += 2; break; case TAB (ABSTOPCREL, LONG): if (flag_keep_pcrel) - as_fatal (_("Tried to convert PC relative conditional branch to absolute jump")); + 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) abort (); fragP->fr_opcode[1] &= ~0x3F; fragP->fr_opcode[1] |= 0x39; /* Mode 7.1 */ - fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol, fragP->fr_offset, - 0, RELAX_RELOC_ABS32); + fixP = fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol, + fragP->fr_offset, 0, RELAX_RELOC_ABS32); fragP->fr_fix += 4; break; } + if (fixP) + { + fixP->fx_file = fragP->fr_file; + fixP->fx_line = fragP->fr_line; + } } -#ifndef BFD_ASSEMBLER - -void -md_convert_frag (headers, sec, fragP) - object_headers *headers ATTRIBUTE_UNUSED; - segT sec ATTRIBUTE_UNUSED; - fragS *fragP; -{ - md_convert_frag_1 (fragP); -} - -#else - void -md_convert_frag (abfd, sec, fragP) - bfd *abfd ATTRIBUTE_UNUSED; - segT sec ATTRIBUTE_UNUSED; - fragS *fragP; +md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, + segT sec ATTRIBUTE_UNUSED, + fragS *fragP) { md_convert_frag_1 (fragP); } -#endif /* Force truly undefined symbols to their maximum size, and generally set up the frag list to be relaxed */ int -md_estimate_size_before_relax (fragP, segment) - register fragS *fragP; - segT segment; +md_estimate_size_before_relax (fragS *fragP, segT segment) { /* Handle SZ_UNDEF first, it can be changed to BYTE or SHORT. */ switch (fragP->fr_subtype) { case TAB (BRANCHBWL, SZ_UNDEF): + case TAB (BRANCHBWPL, SZ_UNDEF): case TAB (BRABSJUNC, SZ_UNDEF): case TAB (BRABSJCOND, SZ_UNDEF): { @@ -5063,80 +5308,14 @@ md_estimate_size_before_relax (fragP, segment) return md_relax_table[fragP->fr_subtype].rlx_length; } -#if defined(OBJ_AOUT) | defined(OBJ_BOUT) -/* the bit-field entries in the relocation_info struct plays hell - with the byte-order problems of cross-assembly. So as a hack, - I added this mach. dependent ri twiddler. Ugly, but it gets - you there. -KWK */ -/* on m68k: first 4 bytes are normal unsigned long, next three bytes - are symbolnum, most sig. byte first. Last byte is broken up with - bit 7 as pcrel, bits 6 & 5 as length, bit 4 as pcrel, and the lower - nibble as nuthin. (on Sun 3 at least) */ -/* Translate the internal relocation information into target-specific - format. */ -#ifdef comment -void -md_ri_to_chars (the_bytes, ri) - char *the_bytes; - struct reloc_info_generic *ri; -{ - /* This is easy. */ - md_number_to_chars (the_bytes, ri->r_address, 4); - /* Now the fun stuff. */ - the_bytes[4] = (ri->r_symbolnum >> 16) & 0x0ff; - the_bytes[5] = (ri->r_symbolnum >> 8) & 0x0ff; - the_bytes[6] = ri->r_symbolnum & 0x0ff; - the_bytes[7] = (((ri->r_pcrel << 7) & 0x80) | ((ri->r_length << 5) & 0x60) | - ((ri->r_extern << 4) & 0x10)); -} - -#endif - -#ifndef BFD_ASSEMBLER -void -tc_aout_fix_to_chars (where, fixP, segment_address_in_file) - char *where; - fixS *fixP; - relax_addressT segment_address_in_file; -{ - /* - * In: length of relocation (or of address) in chars: 1, 2 or 4. - * Out: GNU LD relocation length code: 0, 1, or 2. - */ - - static const unsigned char nbytes_r_length[] = {42, 0, 1, 42, 2}; - long r_symbolnum; - - know (fixP->fx_addsy != NULL); - - md_number_to_chars (where, - fixP->fx_frag->fr_address + fixP->fx_where - segment_address_in_file, - 4); - - r_symbolnum = (S_IS_DEFINED (fixP->fx_addsy) - ? S_GET_TYPE (fixP->fx_addsy) - : fixP->fx_addsy->sy_number); - - where[4] = (r_symbolnum >> 16) & 0x0ff; - where[5] = (r_symbolnum >> 8) & 0x0ff; - where[6] = r_symbolnum & 0x0ff; - where[7] = (((fixP->fx_pcrel << 7) & 0x80) | ((nbytes_r_length[fixP->fx_size] << 5) & 0x60) | - (((!S_IS_DEFINED (fixP->fx_addsy)) << 4) & 0x10)); -} -#endif - -#endif /* OBJ_AOUT or OBJ_BOUT */ - #ifndef WORKING_DOT_WORD -const int md_short_jump_size = 4; -const int md_long_jump_size = 6; +int md_short_jump_size = 4; +int md_long_jump_size = 6; void -md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol) - char *ptr; - addressT from_addr, to_addr; - fragS *frag ATTRIBUTE_UNUSED; - symbolS *to_symbol ATTRIBUTE_UNUSED; +md_create_short_jump (char *ptr, addressT from_addr, addressT to_addr, + fragS *frag ATTRIBUTE_UNUSED, + symbolS *to_symbol ATTRIBUTE_UNUSED) { valueT offset; @@ -5147,11 +5326,8 @@ md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol) } void -md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol) - char *ptr; - addressT from_addr, to_addr; - fragS *frag; - symbolS *to_symbol; +md_create_long_jump (char *ptr, addressT from_addr, addressT to_addr, + fragS *frag, symbolS *to_symbol) { valueT offset; @@ -5175,7 +5351,7 @@ md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol) #endif -/* Different values of OK tell what its OK to return. Things that +/* Different values of OK tell what it's OK to return. Things that aren't OK are an error (what a shock, no?) 0: Everything is OK @@ -5186,14 +5362,13 @@ md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol) 50: absolute 0:127 only 55: absolute -64:63 only 60: absolute -128:127 only + 65: absolute 0:511 only 70: absolute 0:4095 only 80: absolute -1, 1:7 only 90: No bignums. */ static int -get_num (exp, ok) - struct m68k_exp *exp; - int ok; +get_num (struct m68k_exp *exp, int ok) { if (exp->exp.X_op == O_absent) { @@ -5213,38 +5388,42 @@ get_num (exp, ok) switch (ok) { case 10: - if (offs (exp) < 1 || offs (exp) > 8) + if ((valueT) TRUNC (offs (exp)) - 1 > 7) { as_warn (_("expression out of range: defaulting to 1")); offs (exp) = 1; } break; case 20: - if (offs (exp) < 0 || offs (exp) > 7) + if ((valueT) TRUNC (offs (exp)) > 7) goto outrange; break; case 30: - if (offs (exp) < 0 || offs (exp) > 15) + if ((valueT) TRUNC (offs (exp)) > 15) goto outrange; break; case 40: - if (offs (exp) < 0 || offs (exp) > 32) + if ((valueT) TRUNC (offs (exp)) > 32) goto outrange; break; case 50: - if (offs (exp) < 0 || offs (exp) > 127) + if ((valueT) TRUNC (offs (exp)) > 127) goto outrange; break; case 55: - if (offs (exp) < -64 || offs (exp) > 63) + if ((valueT) SEXT (offs (exp)) + 64 > 127) goto outrange; break; case 60: - if (offs (exp) < -128 || offs (exp) > 127) + if ((valueT) SEXT (offs (exp)) + 128 > 255) + goto outrange; + break; + case 65: + if ((valueT) TRUNC (offs (exp)) > 511) goto outrange; break; case 70: - if (offs (exp) < 0 || offs (exp) > 4095) + if ((valueT) TRUNC (offs (exp)) > 4095) { outrange: as_warn (_("expression out of range: defaulting to 0")); @@ -5252,9 +5431,8 @@ get_num (exp, ok) } break; case 80: - if (offs (exp) < -1 - || offs (exp) > 7 - || offs (exp) == 0) + if ((valueT) TRUNC (offs (exp)) != 0xffffffff + && (valueT) TRUNC (offs (exp)) - 1 > 6) { as_warn (_("expression out of range: defaulting to 1")); offs (exp) = 1; @@ -5290,7 +5468,7 @@ get_num (exp, ok) subs (exp) = 0; offs (exp) = (ok == 10) ? 1 : 0; as_warn (_("Can't deal with expression; defaulting to %ld"), - offs (exp)); + (long) offs (exp)); } } else @@ -5302,7 +5480,7 @@ get_num (exp, ok) subs (exp) = 0; offs (exp) = (ok == 10) ? 1 : 0; as_warn (_("Can't deal with expression; defaulting to %ld"), - offs (exp)); + (long) offs (exp)); } } @@ -5330,24 +5508,21 @@ get_num (exp, ok) /* These are the back-ends for the various machine dependent pseudo-ops. */ static void -s_data1 (ignore) - int ignore ATTRIBUTE_UNUSED; +s_data1 (int ignore ATTRIBUTE_UNUSED) { subseg_set (data_section, 1); demand_empty_rest_of_line (); } static void -s_data2 (ignore) - int ignore ATTRIBUTE_UNUSED; +s_data2 (int ignore ATTRIBUTE_UNUSED) { subseg_set (data_section, 2); demand_empty_rest_of_line (); } static void -s_bss (ignore) - int ignore ATTRIBUTE_UNUSED; +s_bss (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. */ @@ -5357,11 +5532,10 @@ s_bss (ignore) } static void -s_even (ignore) - int ignore ATTRIBUTE_UNUSED; +s_even (int ignore ATTRIBUTE_UNUSED) { - register int temp; - register long temp_fill; + int temp; + long temp_fill; temp = 1; /* JF should be 2? */ temp_fill = get_absolute_expression (); @@ -5372,8 +5546,7 @@ s_even (ignore) } static void -s_proc (ignore) - int ignore ATTRIBUTE_UNUSED; +s_proc (int ignore ATTRIBUTE_UNUSED) { demand_empty_rest_of_line (); } @@ -5385,8 +5558,7 @@ s_proc (ignore) alignment is needed. */ int -m68k_conditional_pseudoop (pop) - pseudo_typeS *pop; +m68k_conditional_pseudoop (pseudo_typeS *pop) { return (pop->poc_handler == s_mri_if || pop->poc_handler == s_mri_else); @@ -5395,22 +5567,22 @@ m68k_conditional_pseudoop (pop) /* Handle an MRI style chip specification. */ static void -mri_chip () +mri_chip (void) { char *s; char c; int i; s = input_line_pointer; - /* We can't use get_symbol_end since the processor names are not proper + /* We can't use get_symbol_name 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) + for (i = 0; m68k_cpus[i].name; i++) + if (strcasecmp (s, m68k_cpus[i].name) == 0) break; - if (i >= n_archs) + if (!m68k_cpus[i].name) { as_bad (_("%s: unrecognized processor name"), s); *input_line_pointer = c; @@ -5423,14 +5595,14 @@ mri_chip () current_architecture = 0; else current_architecture &= m68881 | m68851; - current_architecture |= archs[i].arch; - current_chip |= archs[i].chip; + current_architecture |= m68k_cpus[i].arch & ~(m68881 | m68851); + control_regs = m68k_cpus[i].control_regs; while (*input_line_pointer == '/') { ++input_line_pointer; s = input_line_pointer; - /* We can't use get_symbol_end since the processor names are not + /* We can't use get_symbol_name since the processor names are not proper symbols. */ while (is_part_of_name (c = *input_line_pointer++)) ; @@ -5441,16 +5613,12 @@ mri_chip () 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 ATTRIBUTE_UNUSED; +s_chip (int ignore ATTRIBUTE_UNUSED) { char *stop = NULL; char stopc; @@ -5466,8 +5634,7 @@ s_chip (ignore) /* The MRI FOPT pseudo-op. */ static void -s_fopt (ignore) - int ignore ATTRIBUTE_UNUSED; +s_fopt (int ignore ATTRIBUTE_UNUSED) { SKIP_WHITESPACE (); @@ -5502,7 +5669,7 @@ struct opt_action /* If this is not NULL, just call this function. The first argument is the ARG field of this structure, the second argument is whether the option was negated. */ - void (*pfn) PARAMS ((int arg, int on)); + void (*pfn) (int arg, int on); /* If this is not NULL, and the PFN field is NULL, set the variable this points to. Set it to the ARG field if the option was not @@ -5520,11 +5687,11 @@ struct opt_action /* 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)); +static void skip_to_comma (int, int); +static void opt_nest (int, int); +static void opt_chip (int, int); +static void opt_list (int, int); +static void opt_list_symbols (int, int); static const struct opt_action opt_table[] = { @@ -5576,8 +5743,7 @@ static const struct opt_action opt_table[] = /* The MRI OPT pseudo-op. */ static void -s_opt (ignore) - int ignore ATTRIBUTE_UNUSED; +s_opt (int ignore ATTRIBUTE_UNUSED) { do { @@ -5601,8 +5767,7 @@ s_opt (ignore) t = 0; } - s = input_line_pointer; - c = get_symbol_end (); + c = get_symbol_name (&s); for (i = 0, o = opt_table; i < OPTCOUNT; i++, o++) { @@ -5612,14 +5777,14 @@ s_opt (ignore) { /* Restore input_line_pointer now in case the option takes arguments. */ - *input_line_pointer = c; + (void) restore_line_pointer (c); (*o->pfn) (o->arg, t); } else if (o->pvar != NULL) { if (! t && o->arg == o->notarg) as_bad (_("option `%s' may not be negated"), s); - *input_line_pointer = c; + restore_line_pointer (c); *o->pvar = t ? o->arg : o->notarg; } else @@ -5630,7 +5795,7 @@ s_opt (ignore) if (i >= OPTCOUNT) { as_bad (_("option `%s' not recognized"), s); - *input_line_pointer = c; + restore_line_pointer (c); } } while (*input_line_pointer++ == ','); @@ -5644,9 +5809,7 @@ s_opt (ignore) not support and which take arguments. */ static void -skip_to_comma (arg, on) - int arg ATTRIBUTE_UNUSED; - int on ATTRIBUTE_UNUSED; +skip_to_comma (int arg ATTRIBUTE_UNUSED, int on ATTRIBUTE_UNUSED) { while (*input_line_pointer != ',' && ! is_end_of_line[(unsigned char) *input_line_pointer]) @@ -5656,9 +5819,7 @@ skip_to_comma (arg, on) /* Handle the OPT NEST=depth option. */ static void -opt_nest (arg, on) - int arg ATTRIBUTE_UNUSED; - int on ATTRIBUTE_UNUSED; +opt_nest (int arg ATTRIBUTE_UNUSED, int on ATTRIBUTE_UNUSED) { if (*input_line_pointer != '=') { @@ -5673,9 +5834,7 @@ opt_nest (arg, on) /* Handle the OPT P=chip option. */ static void -opt_chip (arg, on) - int arg ATTRIBUTE_UNUSED; - int on ATTRIBUTE_UNUSED; +opt_chip (int arg ATTRIBUTE_UNUSED, int on ATTRIBUTE_UNUSED) { if (*input_line_pointer != '=') { @@ -5690,9 +5849,7 @@ opt_chip (arg, on) /* Handle the OPT S option. */ static void -opt_list (arg, on) - int arg ATTRIBUTE_UNUSED; - int on; +opt_list (int arg ATTRIBUTE_UNUSED, int on) { listing_list (on); } @@ -5700,9 +5857,7 @@ opt_list (arg, on) /* Handle the OPT T option. */ static void -opt_list_symbols (arg, on) - int arg ATTRIBUTE_UNUSED; - int on; +opt_list_symbols (int arg ATTRIBUTE_UNUSED, int on) { if (on) listing |= LISTING_SYMBOLS; @@ -5713,8 +5868,7 @@ opt_list_symbols (arg, on) /* Handle the MRI REG pseudo-op. */ static void -s_reg (ignore) - int ignore ATTRIBUTE_UNUSED; +s_reg (int ignore ATTRIBUTE_UNUSED) { char *s; int c; @@ -5803,7 +5957,7 @@ struct save_opts int keep_locals; int short_refs; int architecture; - int chip; + const enum m68k_register *control_regs; int quick; int rel32; int listing; @@ -5818,18 +5972,17 @@ static struct save_opts *save_stack; /* The MRI SAVE pseudo-op. */ static void -s_save (ignore) - int ignore ATTRIBUTE_UNUSED; +s_save (int ignore ATTRIBUTE_UNUSED) { struct save_opts *s; - s = (struct save_opts *) xmalloc (sizeof (struct save_opts)); + s = XNEW (struct save_opts); s->abspcadd = m68k_abspcadd; s->symbols_case_sensitive = symbols_case_sensitive; s->keep_locals = flag_keep_locals; s->short_refs = flag_short_refs; s->architecture = current_architecture; - s->chip = current_chip; + s->control_regs = control_regs; s->quick = m68k_quick; s->rel32 = m68k_rel32; s->listing = listing; @@ -5844,8 +5997,7 @@ s_save (ignore) /* The MRI RESTORE pseudo-op. */ static void -s_restore (ignore) - int ignore ATTRIBUTE_UNUSED; +s_restore (int ignore ATTRIBUTE_UNUSED) { struct save_opts *s; @@ -5864,7 +6016,7 @@ s_restore (ignore) flag_keep_locals = s->keep_locals; flag_short_refs = s->short_refs; current_architecture = s->architecture; - current_chip = s->chip; + control_regs = s->control_regs; m68k_quick = s->quick; m68k_rel32 = s->rel32; listing = s->listing; @@ -5923,29 +6075,10 @@ static struct mri_control_info *mri_control_stack; static int mri_control_index; -/* 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 *, 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, 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; +mri_assemble (char *str) { char *s; @@ -5959,11 +6092,11 @@ mri_assemble (str) /* Generate a new MRI label structured control directive label name. */ static char * -mri_control_label () +mri_control_label (void) { char *n; - n = (char *) xmalloc (20); + n = XNEWVEC (char, 20); sprintf (n, "%smc%d", FAKE_LABEL_NAME, mri_control_index); ++mri_control_index; return n; @@ -5972,12 +6105,11 @@ mri_control_label () /* Create a new MRI structured control directive. */ static struct mri_control_info * -push_mri_control (type) - enum mri_control_type type; +push_mri_control (enum mri_control_type type) { struct mri_control_info *n; - n = (struct mri_control_info *) xmalloc (sizeof (struct mri_control_info)); + n = XNEW (struct mri_control_info); n->type = type; n->else_seen = 0; @@ -5997,7 +6129,7 @@ push_mri_control (type) /* Pop off the stack of MRI structured control directives. */ static void -pop_mri_control () +pop_mri_control (void) { struct mri_control_info *n; @@ -6013,8 +6145,7 @@ pop_mri_control () /* Recognize a condition code in an MRI structured control expression. */ static int -parse_mri_condition (pcc) - int *pcc; +parse_mri_condition (int *pcc) { char c1, c2; @@ -6044,12 +6175,8 @@ parse_mri_condition (pcc) /* Parse a single operand in an MRI structured control expression. */ static int -parse_mri_control_operand (pcc, leftstart, leftstop, rightstart, rightstop) - int *pcc; - char **leftstart; - char **leftstop; - char **rightstart; - char **rightstop; +parse_mri_control_operand (int *pcc, char **leftstart, char **leftstop, + char **rightstart, char **rightstop) { char *s; @@ -6122,8 +6249,7 @@ parse_mri_control_operand (pcc, leftstart, leftstop, rightstart, rightstop) it generates the same result when the operands are swapped. */ static int -swap_mri_condition (cc) - int cc; +swap_mri_condition (int cc) { switch (cc) { @@ -6142,8 +6268,8 @@ swap_mri_condition (cc) 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 : @@ -6157,8 +6283,7 @@ swap_mri_condition (cc) /* Reverse the sense of a condition. */ static int -reverse_mri_condition (cc) - int cc; +reverse_mri_condition (int cc) { switch (cc) { @@ -6192,17 +6317,10 @@ reverse_mri_condition (cc) use for the branch. */ static void -build_mri_control_operand (qual, cc, leftstart, leftstop, rightstart, - rightstop, truelab, falselab, extent) - int qual; - int cc; - char *leftstart; - char *leftstop; - char *rightstart; - char *rightstop; - const char *truelab; - const char *falselab; - int extent; +build_mri_control_operand (int qual, int cc, char *leftstart, char *leftstop, + char *rightstart, char *rightstop, + const char *truelab, const char *falselab, + int extent) { char *buf; char *s; @@ -6235,20 +6353,20 @@ build_mri_control_operand (qual, cc, leftstart, leftstop, rightstart, { char *temp; - /* Correct conditional handling: - if #1 d0 then ;means if (1 < d0) - ... - endi + /* Correct conditional handling: + if #1 d0 then ;means if (1 < d0) + ... + endi - should assemble to: + should assemble to: - cmp #1,d0 if we do *not* swap the operands - bgt true we need the swapped condition! - ble false - true: - ... - false: - */ + cmp #1,d0 if we do *not* swap the operands + bgt true we need the swapped condition! + ble false + true: + ... + false: + */ temp = leftstart; leftstart = rightstart; rightstart = temp; @@ -6270,9 +6388,9 @@ build_mri_control_operand (qual, cc, leftstart, leftstop, rightstart, if (leftstart != NULL) { - buf = (char *) xmalloc (20 - + (leftstop - leftstart) - + (rightstop - rightstart)); + buf = XNEWVEC (char, (20 + + (leftstop - leftstart) + + (rightstop - rightstart))); s = buf; *s++ = 'c'; *s++ = 'm'; @@ -6290,7 +6408,7 @@ build_mri_control_operand (qual, cc, leftstart, leftstop, rightstart, free (buf); } - buf = (char *) xmalloc (20 + strlen (truelab)); + buf = XNEWVEC (char, 20 + strlen (truelab)); s = buf; *s++ = 'b'; *s++ = cc >> 8; @@ -6311,12 +6429,8 @@ build_mri_control_operand (qual, cc, leftstart, leftstop, rightstart, expression. EXTENT is the size to use for the branch. */ static void -parse_mri_control_expression (stop, qual, truelab, falselab, extent) - char *stop; - int qual; - const char *truelab; - const char *falselab; - int extent; +parse_mri_control_expression (char *stop, int qual, const char *truelab, + const char *falselab, int extent) { int c; int cc; @@ -6421,8 +6535,7 @@ parse_mri_control_expression (stop, qual, truelab, falselab, extent) on its operands. */ static void -s_mri_if (qual) - int qual; +s_mri_if (int qual) { char *s; int c; @@ -6436,12 +6549,12 @@ s_mri_if (qual) This is important when assembling: if d0 12(a0,d0*2) then if d0 #CONST*20 then. */ - while ( ! ( is_end_of_line[(unsigned char) *s] - || ( flag_mri - && *s == '*' - && ( s == input_line_pointer - || *(s-1) == ' ' - || *(s-1) == '\t')))) + while (! (is_end_of_line[(unsigned char) *s] + || (flag_mri + && *s == '*' + && (s == input_line_pointer + || *(s-1) == ' ' + || *(s-1) == '\t')))) ++s; --s; while (s > input_line_pointer && (*s == ' ' || *s == '\t')) @@ -6506,8 +6619,7 @@ s_mri_if (qual) it is a conditional else. */ static void -s_mri_else (qual) - int qual; +s_mri_else (int qual) { int c; char *buf; @@ -6545,7 +6657,7 @@ s_mri_else (qual) mri_control_stack->else_seen = 1; - buf = (char *) xmalloc (20 + strlen (mri_control_stack->bottom)); + buf = XNEWVEC (char, 20 + strlen (mri_control_stack->bottom)); q[0] = TOLOWER (qual); q[1] = '\0'; sprintf (buf, "bra%s %s", q, mri_control_stack->bottom); @@ -6566,8 +6678,7 @@ s_mri_else (qual) /* Handle the MRI ENDI pseudo-op. */ static void -s_mri_endi (ignore) - int ignore ATTRIBUTE_UNUSED; +s_mri_endi (int ignore ATTRIBUTE_UNUSED) { if (mri_control_stack == NULL || mri_control_stack->type != mri_if) @@ -6598,8 +6709,7 @@ s_mri_endi (ignore) /* Handle the MRI BREAK pseudo-op. */ static void -s_mri_break (extent) - int extent; +s_mri_break (int extent) { struct mri_control_info *n; char *buf; @@ -6618,7 +6728,7 @@ s_mri_break (extent) return; } - buf = (char *) xmalloc (20 + strlen (n->bottom)); + buf = XNEWVEC (char, 20 + strlen (n->bottom)); ex[0] = TOLOWER (extent); ex[1] = '\0'; sprintf (buf, "bra%s %s", ex, n->bottom); @@ -6637,8 +6747,7 @@ s_mri_break (extent) /* Handle the MRI NEXT pseudo-op. */ static void -s_mri_next (extent) - int extent; +s_mri_next (int extent) { struct mri_control_info *n; char *buf; @@ -6657,7 +6766,7 @@ s_mri_next (extent) return; } - buf = (char *) xmalloc (20 + strlen (n->next)); + buf = XNEWVEC (char, 20 + strlen (n->next)); ex[0] = TOLOWER (extent); ex[1] = '\0'; sprintf (buf, "bra%s %s", ex, n->next); @@ -6676,8 +6785,7 @@ s_mri_next (extent) /* Handle the MRI FOR pseudo-op. */ static void -s_mri_for (qual) - int qual; +s_mri_for (int qual) { const char *varstart, *varstop; const char *initstart, *initstop; @@ -6832,7 +6940,7 @@ s_mri_for (qual) /* We have fully parsed the FOR operands. Now build the loop. */ n = push_mri_control (mri_for); - buf = (char *) xmalloc (50 + (input_line_pointer - varstart)); + buf = XNEWVEC (char, 50 + (input_line_pointer - varstart)); /* Move init,var. */ s = buf; @@ -6908,8 +7016,7 @@ s_mri_for (qual) /* Handle the MRI ENDF pseudo-op. */ static void -s_mri_endf (ignore) - int ignore ATTRIBUTE_UNUSED; +s_mri_endf (int ignore ATTRIBUTE_UNUSED) { if (mri_control_stack == NULL || mri_control_stack->type != mri_for) @@ -6944,8 +7051,7 @@ s_mri_endf (ignore) /* Handle the MRI REPEAT pseudo-op. */ static void -s_mri_repeat (ignore) - int ignore ATTRIBUTE_UNUSED; +s_mri_repeat (int ignore ATTRIBUTE_UNUSED) { struct mri_control_info *n; @@ -6962,8 +7068,7 @@ s_mri_repeat (ignore) /* Handle the MRI UNTIL pseudo-op. */ static void -s_mri_until (qual) - int qual; +s_mri_until (int qual) { char *s; @@ -7001,8 +7106,7 @@ s_mri_until (qual) /* Handle the MRI WHILE pseudo-op. */ static void -s_mri_while (qual) - int qual; +s_mri_while (int qual) { char *s; @@ -7058,8 +7162,7 @@ s_mri_while (qual) /* Handle the MRI ENDW pseudo-op. */ static void -s_mri_endw (ignore) - int ignore ATTRIBUTE_UNUSED; +s_mri_endw (int ignore ATTRIBUTE_UNUSED) { char *buf; @@ -7071,7 +7174,7 @@ s_mri_endw (ignore) return; } - buf = (char *) xmalloc (20 + strlen (mri_control_stack->next)); + buf = XNEWVEC (char, 20 + strlen (mri_control_stack->next)); sprintf (buf, "bra %s", mri_control_stack->next); mri_assemble (buf); free (buf); @@ -7089,37 +7192,197 @@ s_mri_endw (ignore) demand_empty_rest_of_line (); } -/* - * md_parse_option - * Invocation line includes a switch not recognized by the base assembler. - * See if it's a processor-specific option. These are: - * - * -[A]m[c]68000, -[A]m[c]68008, -[A]m[c]68010, -[A]m[c]68020, -[A]m[c]68030, -[A]m[c]68040 - * -[A]m[c]68881, -[A]m[c]68882, -[A]m[c]68851 - * Select the architecture. Instructions or features not - * supported by the selected architecture cause fatal - * errors. More than one may be specified. The default is - * -m68020 -m68851 -m68881. Note that -m68008 is a synonym - * for -m68000, and -m68882 is a synonym for -m68881. - * -[A]m[c]no-68851, -[A]m[c]no-68881 - * Don't accept 688?1 instructions. (The "c" is kind of silly, - * so don't use or document it, but that's the way the parsing - * works). - * - * -pic Indicates PIC. - * -k Indicates PIC. (Sun 3 only.) - * --pcrel Never turn PC-relative branches into absolute jumps. - * - * --bitwise-or - * Permit `|' to be used in expressions. - * +/* Parse a .cpu directive. */ + +static void +s_m68k_cpu (int ignored ATTRIBUTE_UNUSED) +{ + char saved_char; + char *name; + + if (initialized) + { + as_bad (_("already assembled instructions")); + ignore_rest_of_line (); + return; + } + + name = input_line_pointer; + while (*input_line_pointer && !ISSPACE(*input_line_pointer)) + input_line_pointer++; + saved_char = *input_line_pointer; + *input_line_pointer = 0; + + m68k_set_cpu (name, 1, 0); + + *input_line_pointer = saved_char; + demand_empty_rest_of_line (); + return; +} + +/* Parse a .arch directive. */ + +static void +s_m68k_arch (int ignored ATTRIBUTE_UNUSED) +{ + char saved_char; + char *name; + + if (initialized) + { + as_bad (_("already assembled instructions")); + ignore_rest_of_line (); + return; + } + + name = input_line_pointer; + while (*input_line_pointer && *input_line_pointer != ',' + && !ISSPACE (*input_line_pointer)) + input_line_pointer++; + saved_char = *input_line_pointer; + *input_line_pointer = 0; + + if (m68k_set_arch (name, 1, 0)) + { + /* Scan extensions. */ + do + { + *input_line_pointer++ = saved_char; + if (!*input_line_pointer || ISSPACE (*input_line_pointer)) + break; + name = input_line_pointer; + while (*input_line_pointer && *input_line_pointer != ',' + && !ISSPACE (*input_line_pointer)) + input_line_pointer++; + saved_char = *input_line_pointer; + *input_line_pointer = 0; + } + while (m68k_set_extension (name, 1, 0)); + } + + *input_line_pointer = saved_char; + demand_empty_rest_of_line (); + return; +} + +/* Lookup a cpu name in TABLE and return the slot found. Return NULL + if none is found, the caller is responsible for emitting an error + message. If ALLOW_M is non-zero, we allow an initial 'm' on the + cpu name, if it begins with a '6' (possibly skipping an intervening + 'c'. We also allow a 'c' in the same place. if NEGATED is + non-zero, we accept a leading 'no-' and *NEGATED is set to true, if + the option is indeed negated. */ + +static const struct m68k_cpu * +m68k_lookup_cpu (const char *arg, const struct m68k_cpu *table, + int allow_m, int *negated) +{ + /* allow negated value? */ + if (negated) + { + *negated = 0; + + if (arg[0] == 'n' && arg[1] == 'o' && arg[2] == '-') + { + arg += 3; + *negated = 1; + } + } + + /* Remove 'm' or 'mc' prefix from 68k variants. */ + if (allow_m) + { + if (arg[0] == 'm') + { + if (arg[1] == '6') + arg += 1; + else if (arg[1] == 'c' && arg[2] == '6') + arg += 2; + } + } + else if (arg[0] == 'c' && arg[1] == '6') + arg += 1; + + for (; table->name; table++) + if (!strcmp (arg, table->name)) + { + if (table->alias < -1 || table->alias > 1) + as_bad (_("`%s' is deprecated, use `%s'"), + table->name, table[table->alias < 0 ? 1 : -1].name); + return table; + } + return 0; +} + +/* Set the cpu, issuing errors if it is unrecognized. */ + +static int +m68k_set_cpu (char const *name, int allow_m, int silent) +{ + const struct m68k_cpu *cpu; + + cpu = m68k_lookup_cpu (name, m68k_cpus, allow_m, NULL); + + if (!cpu) + { + if (!silent) + as_bad (_("cpu `%s' unrecognized"), name); + return 0; + } + selected_cpu = cpu; + return 1; +} + +/* Set the architecture, issuing errors if it is unrecognized. */ + +static int +m68k_set_arch (char const *name, int allow_m, int silent) +{ + const struct m68k_cpu *arch; + + arch = m68k_lookup_cpu (name, m68k_archs, allow_m, NULL); + + if (!arch) + { + if (!silent) + as_bad (_("architecture `%s' unrecognized"), name); + return 0; + } + selected_arch = arch; + return 1; +} + +/* Set the architecture extension, issuing errors if it is + unrecognized, or invalid */ + +static int +m68k_set_extension (char const *name, int allow_m, int silent) +{ + int negated; + const struct m68k_cpu *ext; + + ext = m68k_lookup_cpu (name, m68k_extensions, allow_m, &negated); + + if (!ext) + { + if (!silent) + as_bad (_("extension `%s' unrecognized"), name); + return 0; + } + + if (negated) + not_current_architecture |= (ext->control_regs + ? *(unsigned *)ext->control_regs: ext->arch); + else + current_architecture |= ext->arch; + return 1; +} + +/* md_parse_option + Invocation line includes a switch not recognized by the base assembler. */ -#ifdef OBJ_ELF const char *md_shortopts = "lSA:m:kQ:V"; -#else -const char *md_shortopts = "lSA:m:k"; -#endif struct option md_longopts[] = { #define OPTION_PIC (OPTION_MD_BASE) @@ -7144,9 +7407,7 @@ struct option md_longopts[] = { size_t md_longopts_size = sizeof (md_longopts); int -md_parse_option (c, arg) - int c; - char *arg; +md_parse_option (int c, const char *arg) { switch (c) { @@ -7165,83 +7426,6 @@ md_parse_option (c, arg) flag_keep_pcrel = 1; break; - case 'A': - if (*arg == 'm') - arg++; - /* Intentional fall-through. */ - case 'm': - - if (arg[0] == 'n' && arg[1] == 'o' && arg[2] == '-') - { - int i; - unsigned long arch; - const char *oarg = arg; - - arg += 3; - if (*arg == 'm') - { - arg++; - if (arg[0] == 'c' && arg[1] == '6') - arg++; - } - for (i = 0; i < n_archs; i++) - if (!strcmp (arg, archs[i].name)) - break; - if (i == n_archs) - { - unknown: - as_bad (_("unrecognized option `%s'"), oarg); - return 0; - } - arch = archs[i].arch; - if (arch == m68881) - no_68881 = 1; - else if (arch == m68851) - no_68851 = 1; - else - goto unknown; - } - else - { - int i; - - if (arg[0] == 'c' && arg[1] == '6') - arg++; - - for (i = 0; i < n_archs; i++) - if (!strcmp (arg, archs[i].name)) - { - unsigned long arch = archs[i].arch; - if (cpu_of_arch (arch)) - /* It's a cpu spec. */ - { - current_architecture &= ~m68000up; - current_architecture |= arch; - current_chip |= archs[i].chip; - } - else if (arch == m68881) - { - current_architecture |= m68881; - no_68881 = 0; - } - else if (arch == m68851) - { - current_architecture |= m68851; - no_68851 = 0; - } - else - /* ??? */ - abort (); - break; - } - if (i == n_archs) - { - as_bad (_("unrecognized architecture specification `%s'"), arg); - return 0; - } - } - break; - case OPTION_PIC: case 'k': flag_want_pic = 1; @@ -7267,7 +7451,7 @@ md_parse_option (c, arg) char *n, *t; const char *s; - n = (char *) xmalloc (strlen (m68k_comment_chars) + 1); + n = XNEWVEC (char, strlen (m68k_comment_chars) + 1); t = n; for (s = m68k_comment_chars; *s != '\0'; s++) if (*s != '|') @@ -7295,6 +7479,27 @@ md_parse_option (c, arg) m68k_rel32_from_cmdline = 1; break; + case 'A': +#if WARN_DEPRECATED + as_tsktsk (_ ("option `-A%s' is deprecated: use `-%s'", + arg, arg)); +#endif + /* Intentional fall-through. */ + case 'm': + if (!strncmp (arg, "arch=", 5)) + m68k_set_arch (arg + 5, 1, 0); + else if (!strncmp (arg, "cpu=", 4)) + m68k_set_cpu (arg + 4, 1, 0); + else if (m68k_set_extension (arg, 0, 1)) + ; + else if (m68k_set_arch (arg, 0, 1)) + ; + else if (m68k_set_cpu (arg, 0, 1)) + ; + else + return 0; + break; + default: return 0; } @@ -7302,61 +7507,135 @@ md_parse_option (c, arg) return 1; } +/* Setup tables from the selected arch and/or cpu */ + +static void +m68k_init_arch (void) +{ + if (not_current_architecture & current_architecture) + { + as_bad (_("architecture features both enabled and disabled")); + not_current_architecture &= ~current_architecture; + } + if (selected_arch) + { + current_architecture |= selected_arch->arch; + control_regs = selected_arch->control_regs; + } + else + current_architecture |= selected_cpu->arch; + + current_architecture &= ~not_current_architecture; + + if ((current_architecture & (cfloat | m68881)) == (cfloat | m68881)) + { + /* Determine which float is really meant. */ + if (current_architecture & (m68k_mask & ~m68881)) + current_architecture ^= cfloat; + else + current_architecture ^= m68881; + } + + if (selected_cpu) + { + control_regs = selected_cpu->control_regs; + if (current_architecture & ~selected_cpu->arch) + { + as_bad (_("selected processor does not have all features of selected architecture")); + current_architecture + = selected_cpu->arch & ~not_current_architecture; + } + } + + if ((current_architecture & m68k_mask) + && (current_architecture & ~m68k_mask)) + { + as_bad (_ ("m68k and cf features both selected")); + if (current_architecture & m68k_mask) + current_architecture &= m68k_mask; + else + current_architecture &= ~m68k_mask; + } + + /* Permit m68881 specification with all cpus; those that can't work + with a coprocessor could be doing emulation. */ + if (current_architecture & m68851) + { + if (current_architecture & m68040) + as_warn (_("68040 and 68851 specified; mmu instructions may assemble incorrectly")); + } + /* What other incompatibilities could we check for? */ + + if (cpu_of_arch (current_architecture) < m68020 + || arch_coldfire_p (current_architecture)) + md_relax_table[TAB (PCINDEX, BYTE)].rlx_more = 0; + + initialized = 1; +} + void -md_show_usage (stream) - FILE *stream; +md_show_usage (FILE *stream) { 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') default_cpu++; - for (i = 0; i < n_archs; i++) + for (i = 0; m68k_cpus[i].name; i++) { - if (strcasecmp (default_cpu, archs[i].name) == 0) + if (strcasecmp (default_cpu, m68k_cpus[i].name) == 0) { - default_arch = archs[i].arch; - for (i = 0; i < n_archs; i++) - { - if (archs[i].arch == default_arch - && !archs[i].alias) - { - default_cpu = archs[i].name; - break; - } - } + while (m68k_cpus[i].alias > 0) + i--; + while (m68k_cpus[i].alias < 0) + i++; + default_cpu = m68k_cpus[i].name; } } 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 | -mcpu32 |\n\ --m5200 | -m5202 | -m5204 | -m5206 | -m5206e | -m521x | -m5249 |\n\ --m528x | -m5307 | -m5407 | -m547x | -m548x | -mcfv4 | -mcfv4e\n\ - specify variant of 680X0 architecture [default %s]\n\ --m68881 | -m68882 | -mno-68881 | -mno-68882\n\ - target has/lacks floating-point coprocessor\n\ - [default yes for 68020, 68030, and cpu32]\n"), - default_cpu); +-march= set architecture\n\ +-mcpu= set cpu [default %s]\n\ +"), default_cpu); + for (i = 0; m68k_extensions[i].name; i++) + fprintf (stream, _("\ +-m[no-]%-16s enable/disable %s architecture extension\n\ +"), m68k_extensions[i].name, + m68k_extensions[i].alias > 0 ? " ColdFire" + : m68k_extensions[i].alias < 0 ? " m68k" : ""); + fprintf (stream, _("\ --m68851 | -mno-68851\n\ - target has/lacks memory-management unit coprocessor\n\ - [default yes for 68020 and up]\n\ +-l use 1 word for refs to undefined symbols [default 2]\n\ -pic, -k generate position independent code\n\ -S turn jbsr into jsr\n\ --pcrel never turn PC-relative branches into absolute jumps\n\ --register-prefix-optional\n\ recognize register names without prefix character\n\ ---bitwise-or do not treat `|' as a comment character\n")); - fprintf (stream, _("\ +--bitwise-or do not treat `|' as a comment character\n\ --base-size-default-16 base reg without size is 16 bits\n\ --base-size-default-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")); +--disp-size-default-32 displacement with unknown size is 32 bits (default)\n\ +")); + + fprintf (stream, _("Architecture variants are: ")); + for (i = 0; m68k_archs[i].name; i++) + { + if (i) + fprintf (stream, " | "); + fprintf (stream, "%s", m68k_archs[i].name); + } + fprintf (stream, "\n"); + + fprintf (stream, _("Processor variants are: ")); + for (i = 0; m68k_cpus[i].name; i++) + { + if (i) + fprintf (stream, " | "); + fprintf (stream, "%s", m68k_cpus[i].name); + } + fprintf (stream, _("\n")); } #ifdef TEST2 @@ -7364,7 +7643,7 @@ md_show_usage (stream) /* TEST2: Test md_assemble() */ /* Warning, this routine probably doesn't work anymore. */ int -main () +main (void) { struct m68k_it the_ins; char buf[120]; @@ -7405,21 +7684,27 @@ main () printf ("op%d Error %s in %s\n", n, the_ins.operands[n].error, buf); continue; } - printf ("mode %d, reg %d, ", the_ins.operands[n].mode, the_ins.operands[n].reg); + printf ("mode %d, reg %d, ", the_ins.operands[n].mode, + the_ins.operands[n].reg); if (the_ins.operands[n].b_const) - printf ("Constant: '%.*s', ", 1 + the_ins.operands[n].e_const - the_ins.operands[n].b_const, the_ins.operands[n].b_const); - printf ("ireg %d, isiz %d, imul %d, ", the_ins.operands[n].ireg, the_ins.operands[n].isiz, the_ins.operands[n].imul); + printf ("Constant: '%.*s', ", + 1 + the_ins.operands[n].e_const - the_ins.operands[n].b_const, + the_ins.operands[n].b_const); + printf ("ireg %d, isiz %d, imul %d, ", the_ins.operands[n].ireg, + the_ins.operands[n].isiz, the_ins.operands[n].imul); if (the_ins.operands[n].b_iadd) - printf ("Iadd: '%.*s',", 1 + the_ins.operands[n].e_iadd - the_ins.operands[n].b_iadd, the_ins.operands[n].b_iadd); - (void) putchar ('\n'); + printf ("Iadd: '%.*s',", + 1 + the_ins.operands[n].e_iadd - the_ins.operands[n].b_iadd, + the_ins.operands[n].b_iadd); + putchar ('\n'); } } m68k_ip_end (); return 0; } -is_label (str) - char *str; +int +is_label (char *str) { while (*str == ' ') str++; @@ -7452,32 +7737,15 @@ is_label (str) /* We have no need to default values of symbols. */ symbolS * -md_undefined_symbol (name) - char *name ATTRIBUTE_UNUSED; +md_undefined_symbol (char *name ATTRIBUTE_UNUSED) { return 0; } /* Round up a section size to the appropriate boundary. */ valueT -md_section_align (segment, size) - segT segment ATTRIBUTE_UNUSED; - valueT size; +md_section_align (segT segment ATTRIBUTE_UNUSED, valueT size) { -#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; } @@ -7486,60 +7754,203 @@ md_section_align (segment, size) word. The difference between the addresses of the offset and the first extension word is stored in fx_pcrel_adjust. */ long -md_pcrel_from (fixP) - fixS *fixP; +md_pcrel_from (fixS *fixP) { int adjust; - /* Because fx_pcrel_adjust is a char, and may be unsigned, we explicitly - sign extend the value here. */ - adjust = ((fixP->fx_pcrel_adjust & 0xff) ^ 0x80) - 0x80; + adjust = fixP->fx_pcrel_adjust; if (adjust == 64) adjust = -1; return fixP->fx_where + fixP->fx_frag->fr_address - adjust; } -#ifndef BFD_ASSEMBLER -#ifdef OBJ_COFF - void -tc_coff_symbol_emit_hook (ignore) - symbolS *ignore ATTRIBUTE_UNUSED; +m68k_elf_final_processing (void) { + unsigned flags = 0; + + if (arch_coldfire_fpu (current_architecture)) + flags |= EF_M68K_CFV4E; + /* Set file-specific flags if this is a cpu32 processor. */ + if (cpu_of_arch (current_architecture) & cpu32) + flags |= EF_M68K_CPU32; + else if (cpu_of_arch (current_architecture) & fido_a) + flags |= EF_M68K_FIDO; + else if ((cpu_of_arch (current_architecture) & m68000up) + && !(cpu_of_arch (current_architecture) & m68020up)) + flags |= EF_M68K_M68000; + + if (current_architecture & mcfisa_a) + { + static const unsigned isa_features[][2] = + { + {EF_M68K_CF_ISA_A_NODIV,mcfisa_a}, + {EF_M68K_CF_ISA_A, mcfisa_a|mcfhwdiv}, + {EF_M68K_CF_ISA_A_PLUS, mcfisa_a|mcfisa_aa|mcfhwdiv|mcfusp}, + {EF_M68K_CF_ISA_B_NOUSP,mcfisa_a|mcfisa_b|mcfhwdiv}, + {EF_M68K_CF_ISA_B, mcfisa_a|mcfisa_b|mcfhwdiv|mcfusp}, + {EF_M68K_CF_ISA_C, mcfisa_a|mcfisa_c|mcfhwdiv|mcfusp}, + {EF_M68K_CF_ISA_C_NODIV,mcfisa_a|mcfisa_c|mcfusp}, + {0,0}, + }; + static const unsigned mac_features[][2] = + { + {EF_M68K_CF_MAC, mcfmac}, + {EF_M68K_CF_EMAC, mcfemac}, + {0,0}, + }; + unsigned ix; + unsigned pattern; + + pattern = (current_architecture + & (mcfisa_a|mcfisa_aa|mcfisa_b|mcfisa_c|mcfhwdiv|mcfusp)); + for (ix = 0; isa_features[ix][1]; ix++) + { + if (pattern == isa_features[ix][1]) + { + flags |= isa_features[ix][0]; + break; + } + } + if (!isa_features[ix][1]) + { + cf_bad: + as_warn (_("Not a defined coldfire architecture")); + } + else + { + if (current_architecture & cfloat) + flags |= EF_M68K_CF_FLOAT | EF_M68K_CFV4E; + + pattern = current_architecture & (mcfmac|mcfemac); + if (pattern) + { + for (ix = 0; mac_features[ix][1]; ix++) + { + if (pattern == mac_features[ix][1]) + { + flags |= mac_features[ix][0]; + break; + } + } + if (!mac_features[ix][1]) + goto cf_bad; + } + } + } + elf_elfheader (stdoutput)->e_flags |= flags; } -int -tc_coff_sizemachdep (frag) - fragS *frag; +/* Parse @TLSLDO and return the desired relocation. */ +static bfd_reloc_code_real_type +m68k_elf_suffix (char **str_p, expressionS *exp_p) { - switch (frag->fr_subtype & 0x3) + 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) { - case BYTE: - return 1; - case SHORT: - return 2; - case LONG: - return 4; - default: - abort (); - return 0; + *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; } -#endif -#endif -#ifdef OBJ_ELF -void -m68k_elf_final_processing () +/* Handles .long +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 */) { - /* Set file-specific flags if this is a cpu32 processor. */ - if (cpu_of_arch (current_architecture) & cpu32) - elf_elfheader (stdoutput)->e_flags |= EF_CPU32; - else if ((cpu_of_arch (current_architecture) & m68000up) - && !(cpu_of_arch (current_architecture) & m68020up)) - elf_elfheader (stdoutput)->e_flags |= EF_M68000; + 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 (ngettext ("%s relocations do not fit in %u byte", + "%s relocations do not fit in %u bytes", + nbytes), + 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 tc_m68k_regname_to_dw2regnum (const char *regname) @@ -7571,3 +7982,17 @@ tc_m68k_frame_initial_instructions (void) cfi_add_CFA_def_cfa (sp_regno, -DWARF2_CIE_DATA_ALIGNMENT); cfi_add_CFA_offset (DWARF2_DEFAULT_RETURN_COLUMN, DWARF2_CIE_DATA_ALIGNMENT); } + +/* Check and emit error if broken-word handling has failed to fix up a + case-table. This is called from write.c, after doing everything it + knows about how to handle broken words. */ + +void +tc_m68k_check_adjusted_broken_word (offsetT new_offset, struct broken_word *brokwP) +{ + if (new_offset > 32767 || new_offset < -32768) + as_bad_where (brokwP->frag->fr_file, brokwP->frag->fr_line, + _("Adjusted signed .word (%#lx) overflows: `switch'-statement too large."), + (long) new_offset); +} +