/* tc-mips.c -- assemble code for a MIPS chip.
- Copyright (C) 1993, 94, 95, 96, 97, 98, 1999, 2000
+ Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
Free Software Foundation, Inc.
Contributed by the OSF and Ralph Campbell.
Written by Keith Knowles and Ralph Campbell, working independently.
static int mips_64;
/* The default target format to use. */
+
const char *
mips_target_format ()
{
#ifdef TE_TMIPS
/* This is traditional mips */
return (target_big_endian
- ? "elf32-tradbigmips" : "elf32-tradlittlemips");
+ ? (mips_64 ? "elf64-tradbigmips" : "elf32-tradbigmips")
+ : (mips_64 ? "elf64-tradlittlemips" : "elf32-tradlittlemips"));
#else
return (target_big_endian
? (mips_64 ? "elf64-bigmips" : "elf32-bigmips")
};
/* This is the struct we use to hold the current set of options. Note
- that we must set the isa and mips16 fields to -1 to indicate that
- they have not been initialized. */
+ that we must set the isa field to ISA_UNKNOWN and the mips16 field to
+ -1 to indicate that they have not been initialized. */
-static struct mips_set_options mips_opts = { -1, -1, 0, 0, 0, 0, 0, 0 };
+static struct mips_set_options mips_opts =
+{
+ ISA_UNKNOWN, -1, 0, 0, 0, 0, 0, 0
+};
/* These variables are filled in with the masks of registers used.
The object format code reads them and puts them in the appropriate
unsigned long mips_cprmask[4];
/* MIPS ISA we are using for this output file. */
-static int file_mips_isa;
+static int file_mips_isa = ISA_UNKNOWN;
-/* The CPU type as a number: 2000, 3000, 4000, 4400, etc. */
-static int mips_cpu = -1;
+/* The CPU type we are using for this output file. */
+static int mips_cpu = CPU_UNKNOWN;
/* The argument of the -mabi= flag. */
-static char* mips_abi_string = 0;
+static char * mips_abi_string = 0;
/* Wether we should mark the file EABI64 or EABI32. */
static int mips_eabi64 = 0;
also assume that ISAs which don't have delays for these insns, don't
have delays for the INSN_LOAD_MEMORY_DELAY instructions either. */
#define ISA_HAS_COPROC_DELAYS(ISA) ( \
- (ISA) == 1 \
- || (ISA) == 2 \
- || (ISA) == 3 \
+ (ISA) == ISA_MIPS1 \
+ || (ISA) == ISA_MIPS2 \
+ || (ISA) == ISA_MIPS3 \
)
/* Return true if ISA supports 64 bit gp register instructions. */
#define ISA_HAS_64BIT_REGS(ISA) ( \
- (ISA) == 3 \
- || (ISA) == 4 \
+ (ISA) == ISA_MIPS3 \
+ || (ISA) == ISA_MIPS4 \
+ || (ISA) == ISA_MIPS5 \
+ || (ISA) == ISA_MIPS64 \
)
/* Whether the processor uses hardware interlocks to protect
/* Whether the processor uses hardware interlocks to protect reads
from the GPRs, and thus does not require nops to be inserted. */
#define gpr_interlocks \
- (mips_opts.isa != 1 \
+ (mips_opts.isa != ISA_MIPS1 \
|| mips_cpu == CPU_R3900)
/* As with other "interlocks" this is used by hardware that has FP
| ((warn) ? 1 : 0)))
#define RELAX_OLD(i) (((i) >> 23) & 0x7f)
#define RELAX_NEW(i) (((i) >> 16) & 0x7f)
-#define RELAX_RELOC1(i) ((bfd_vma)(((i) >> 9) & 0x7f) - 64)
-#define RELAX_RELOC2(i) ((bfd_vma)(((i) >> 2) & 0x7f) - 64)
+#define RELAX_RELOC1(i) ((bfd_vma) (((i) >> 9) & 0x7f) - 64)
+#define RELAX_RELOC2(i) ((bfd_vma) (((i) >> 2) & 0x7f) - 64)
#define RELAX_RELOC3(i) (((i) >> 1) & 1)
#define RELAX_WARN(i) ((i) & 1)
static void s_mips_weakext PARAMS ((int));
static void s_file PARAMS ((int));
static int mips16_extended_frag PARAMS ((fragS *, asection *, long));
-static char *mips_cpu_to_str PARAMS ((int));
-
+static const char *mips_isa_to_str PARAMS ((int));
+static const char *mips_cpu_to_str PARAMS ((int));
static int validate_mips_insn PARAMS ((const struct mips_opcode *));
+
+/* Table and functions used to map between CPU/ISA names, and
+ ISA levels, and CPU numbers. */
+
+struct mips_cpu_info
+{
+ const char *name; /* CPU or ISA name. */
+ int is_isa; /* Is this an ISA? (If 0, a CPU.) */
+ int isa; /* ISA level. */
+ int cpu; /* CPU number (default CPU if ISA). */
+};
+
+static const struct mips_cpu_info *mips_cpu_info_from_name PARAMS ((const char *));
+static const struct mips_cpu_info *mips_cpu_info_from_isa PARAMS ((int));
+static const struct mips_cpu_info *mips_cpu_info_from_cpu PARAMS ((int));
\f
/* Pseudo-op table.
static const pseudo_typeS mips_pseudo_table[] =
{
- /* MIPS specific pseudo-ops. */
+ /* MIPS specific pseudo-ops. */
{"option", s_option, 0},
{"set", s_mipsset, 0},
{"rdata", s_change_sec, 'r'},
{"cpadd", s_cpadd, 0},
{"insn", s_insn, 0},
- /* Relatively generic pseudo-ops that happen to be used on MIPS
+ /* Relatively generic pseudo-ops that happen to be used on MIPS
chips. */
{"asciiz", stringer, 1},
{"bss", s_change_sec, 'b'},
{"dword", s_cons, 3},
{"weakext", s_mips_weakext, 0},
- /* These pseudo-ops are defined in read.c, but must be overridden
+ /* These pseudo-ops are defined in read.c, but must be overridden
here for one reason or another. */
{"align", s_align, 0},
{"byte", s_cons, 0},
{ NULL, NULL, 0 },
};
-static const pseudo_typeS mips_nonecoff_pseudo_table[] = {
- /* These pseudo-ops should be defined by the object file format.
- However, a.out doesn't support them, so we have versions here. */
+static const pseudo_typeS mips_nonecoff_pseudo_table[] =
+{
+ /* These pseudo-ops should be defined by the object file format.
+ However, a.out doesn't support them, so we have versions here. */
{"aent", s_mips_ent, 1},
{"bgnb", s_ignore, 0},
{"end", s_mips_end, 0},
static segT pdr_seg;
#endif
-static char *
+static const char *
+mips_isa_to_str (isa)
+ int isa;
+{
+ const struct mips_cpu_info *ci;
+ static char s[20];
+
+ ci = mips_cpu_info_from_isa (isa);
+ if (ci != NULL)
+ return (ci->name);
+
+ sprintf (s, "ISA#%d", isa);
+ return s;
+}
+
+static const char *
mips_cpu_to_str (cpu)
int cpu;
{
+ const struct mips_cpu_info *ci;
static char s[16];
- switch (cpu)
- {
- case CPU_R2000: return "R2000";
- case CPU_R3000: return "R3000";
- case CPU_R3900: return "R3900";
- case CPU_R4000: return "R4000";
- case CPU_R4010: return "R4010";
- case CPU_VR4100: return "VR4100";
- case CPU_R4111: return "R4111";
- case CPU_R4300: return "R4300";
- case CPU_R4400: return "R4400";
- case CPU_R4600: return "R4600";
- case CPU_R4650: return "R4650";
- case CPU_R5000: return "R5000";
- case CPU_R6000: return "R6000";
- case CPU_R8000: return "R8000";
- case CPU_R10000: return "R10000";
- case CPU_4K: return "4K";
- default:
- sprintf (s, "%d", cpu);
- return s;
- }
+
+ ci = mips_cpu_info_from_cpu (cpu);
+ if (ci != NULL)
+ return (ci->name);
+
+ sprintf (s, "CPU#%d", cpu);
+ return s;
}
/* This function is called once, at assembler startup time. It should
void
md_begin ()
{
- boolean ok = false;
register const char *retval = NULL;
int i = 0;
const char *cpu;
char *a = NULL;
int broken = 0;
int mips_isa_from_cpu;
+ int target_cpu_had_mips16 = 0;
+ const struct mips_cpu_info *ci;
/* GP relative stuff not working for PE */
if (strncmp (TARGET_OS, "pe", 2) == 0
cpu = a;
}
- if (mips_cpu < 0)
+ if (strncmp (cpu, "mips16", sizeof "mips16" - 1) == 0)
{
- /* Set mips_cpu based on TARGET_CPU, unless TARGET_CPU is
- just the generic 'mips', in which case set mips_cpu based
- on the given ISA, if any. */
-
- if (strcmp (cpu, "mips") == 0)
- {
- if (mips_opts.isa < 0)
- mips_cpu = CPU_R3000;
-
- else if (mips_opts.isa == 2)
- mips_cpu = CPU_R6000;
-
- else if (mips_opts.isa == 3)
- mips_cpu = CPU_R4000;
-
- else if (mips_opts.isa == 4)
- mips_cpu = CPU_R8000;
-
- else
- mips_cpu = CPU_R3000;
- }
-
- else if (strcmp (cpu, "r3900") == 0
- || strcmp (cpu, "mipstx39") == 0
- )
- mips_cpu = CPU_R3900;
-
- else if (strcmp (cpu, "r6000") == 0
- || strcmp (cpu, "mips2") == 0)
- mips_cpu = CPU_R6000;
-
- else if (strcmp (cpu, "mips64") == 0
- || strcmp (cpu, "r4000") == 0
- || strcmp (cpu, "mips3") == 0)
- mips_cpu = CPU_R4000;
-
- else if (strcmp (cpu, "r4400") == 0)
- mips_cpu = CPU_R4400;
-
- else if (strcmp (cpu, "mips64orion") == 0
- || strcmp (cpu, "r4600") == 0)
- mips_cpu = CPU_R4600;
-
- else if (strcmp (cpu, "r4650") == 0)
- mips_cpu = CPU_R4650;
-
- else if (strcmp (cpu, "mips64vr4300") == 0)
- mips_cpu = CPU_R4300;
-
- else if (strcmp (cpu, "mips64vr4111") == 0)
- mips_cpu = CPU_R4111;
-
- else if (strcmp (cpu, "mips64vr4100") == 0)
- mips_cpu = CPU_VR4100;
-
- else if (strcmp (cpu, "r4010") == 0)
- mips_cpu = CPU_R4010;
-
- else if (strcmp (cpu, "4Kc") == 0
- || strcmp (cpu, "4Kp") == 0
- || strcmp (cpu, "4Km") == 0)
- mips_cpu = CPU_4K;
-
- else if (strcmp (cpu, "r5000") == 0
- || strcmp (cpu, "mips64vr5000") == 0)
- mips_cpu = CPU_R5000;
-
- else if (strcmp (cpu, "r8000") == 0
- || strcmp (cpu, "mips4") == 0)
- mips_cpu = CPU_R8000;
-
- else if (strcmp (cpu, "r10000") == 0)
- mips_cpu = CPU_R10000;
-
- else if (strcmp (cpu, "mips16") == 0)
- mips_cpu = 0; /* FIXME */
-
- else
- mips_cpu = CPU_R3000;
+ target_cpu_had_mips16 = 1;
+ cpu += sizeof "mips16" - 1;
}
- if (mips_cpu == CPU_R3000
- || mips_cpu == CPU_R3900)
- mips_isa_from_cpu = 1;
-
- else if (mips_cpu == CPU_R6000
- || mips_cpu == CPU_R4010)
- mips_isa_from_cpu = 2;
-
- else if (mips_cpu == CPU_R4000
- || mips_cpu == CPU_VR4100
- || mips_cpu == CPU_R4111
- || mips_cpu == CPU_R4400
- || mips_cpu == CPU_R4300
- || mips_cpu == CPU_R4600
- || mips_cpu == CPU_R4650)
- mips_isa_from_cpu = 3;
-
- else if (mips_cpu == CPU_R5000
- || mips_cpu == CPU_R8000
- || mips_cpu == CPU_R10000)
- mips_isa_from_cpu = 4;
-
- else
- mips_isa_from_cpu = -1;
+ if (mips_opts.mips16 < 0)
+ mips_opts.mips16 = target_cpu_had_mips16;
- if (mips_opts.isa == -1)
+ /* At this point, mips_cpu will either be CPU_UNKNOWN if no CPU was
+ specified on the command line, or some other value if one was.
+ Similarly, mips_opts.isa will be ISA_UNKNOWN if not specified on
+ the command line, or will be set otherwise if one was. */
+ if (mips_cpu != CPU_UNKNOWN && mips_opts.isa != ISA_UNKNOWN)
{
- if (mips_isa_from_cpu != -1)
- mips_opts.isa = mips_isa_from_cpu;
- else
- mips_opts.isa = 1;
+ /* We have it all. There's nothing to do. */
}
-
- if (mips_opts.mips16 < 0)
+ else if (mips_cpu != CPU_UNKNOWN && mips_opts.isa == ISA_UNKNOWN)
{
- if (strncmp (TARGET_CPU, "mips16", sizeof "mips16" - 1) == 0)
- mips_opts.mips16 = 1;
- else
- mips_opts.mips16 = 0;
+ /* We have CPU, we need ISA. */
+ ci = mips_cpu_info_from_cpu (mips_cpu);
+ assert (ci != NULL);
+ mips_opts.isa = ci->isa;
+ }
+ else if (mips_cpu == CPU_UNKNOWN && mips_opts.isa != ISA_UNKNOWN)
+ {
+ /* We have ISA, we need default CPU. */
+ ci = mips_cpu_info_from_isa (mips_opts.isa);
+ assert (ci != NULL);
+ mips_cpu = ci->cpu;
}
+ else
+ {
+ /* We need to set both ISA and CPU from target cpu. */
+ ci = mips_cpu_info_from_name (cpu);
+ if (ci == NULL)
+ ci = mips_cpu_info_from_cpu (CPU_R3000);
+ assert (ci != NULL);
+ mips_opts.isa = ci->isa;
+ mips_cpu = ci->cpu;
+ }
+
+ ci = mips_cpu_info_from_cpu (mips_cpu);
+ assert (ci != NULL);
+ mips_isa_from_cpu = ci->isa;
/* End of TARGET_CPU processing, get rid of malloced memory
if necessary. */
a = NULL;
}
- if (mips_opts.isa == 1 && mips_trap)
+ if (mips_opts.isa == ISA_MIPS1 && mips_trap)
as_bad (_("trap exception not supported at ISA 1"));
/* Set the EABI kind based on the ISA before the user gets
the best, but then neither is basing the abi on the isa. */
if (ISA_HAS_64BIT_REGS (mips_opts.isa)
&& mips_abi_string
- && 0 == strcmp (mips_abi_string,"eabi"))
+ && 0 == strcmp (mips_abi_string, "eabi"))
mips_eabi64 = 1;
- if (mips_cpu != 0 && mips_cpu != -1)
- {
- ok = bfd_set_arch_mach (stdoutput, bfd_arch_mips, mips_cpu);
+ /* If they asked for mips1 or mips2 and a cpu that is
+ mips3 or greater, then mark the object file 32BITMODE. */
+ if (mips_isa_from_cpu != ISA_UNKNOWN
+ && ! ISA_HAS_64BIT_REGS (mips_opts.isa)
+ && ISA_HAS_64BIT_REGS (mips_isa_from_cpu))
+ mips_32bitmode = 1;
- /* If they asked for mips1 or mips2 and a cpu that is
- mips3 or greater, then mark the object file 32BITMODE. */
- if (mips_isa_from_cpu != -1
- && ! ISA_HAS_64BIT_REGS (mips_opts.isa)
- && ISA_HAS_64BIT_REGS (mips_isa_from_cpu))
- mips_32bitmode = 1;
- }
- else
- {
- switch (mips_opts.isa)
- {
- case 1:
- ok = bfd_set_arch_mach (stdoutput, bfd_arch_mips, CPU_R3000);
- break;
- case 2:
- ok = bfd_set_arch_mach (stdoutput, bfd_arch_mips, CPU_R6000);
- break;
- case 3:
- ok = bfd_set_arch_mach (stdoutput, bfd_arch_mips, CPU_R4000);
- break;
- case 4:
- ok = bfd_set_arch_mach (stdoutput, bfd_arch_mips, CPU_R8000);
- break;
- }
- }
-
- if (! ok)
+ if (! bfd_set_arch_mach (stdoutput, bfd_arch_mips, mips_cpu))
as_warn (_("Could not set architecture and machine"));
file_mips_isa = mips_opts.isa;
else
{
mips_ip (str, &insn);
- DBG((_("returned from mips_ip(%s) insn_opcode = 0x%x\n"),
- str, insn.insn_opcode));
+ DBG ((_("returned from mips_ip(%s) insn_opcode = 0x%x\n"),
+ str, insn.insn_opcode));
}
if (insn_error)
delays delay the use of general register rt for one
instruction on the r3000. The r6000 and r4000 use
interlocks. */
- /* Itbl support may require additional care here. */
+ /* Itbl support may require additional care here. */
know (prev_pinfo & INSN_WRITE_GPR_T);
if (mips_optimize == 0
|| insn_uses_reg (ip,
else if (! mips_opts.mips16
&& ISA_HAS_COPROC_DELAYS (mips_opts.isa)
&& (((prev_pinfo & INSN_COPROC_MOVE_DELAY)
- && ! cop_interlocks)
- || (mips_opts.isa == 1
+ && ! cop_interlocks)
+ || (mips_opts.isa == ISA_MIPS1
&& (prev_pinfo & INSN_COPROC_MEMORY_DELAY))))
{
/* A generic coprocessor delay. The previous instruction
(this means it is a floating point comparison
instruction). If this instruction uses the condition
codes, we need to insert a single NOP. */
- /* Itbl support may require additional care here. */
+ /* Itbl support may require additional care here. */
if (mips_optimize == 0
|| (pinfo & INSN_READ_COND_CODE))
++nops;
else if (mips_7000_hilo_fix
&& MF_HILO_INSN (prev_pinfo)
&& insn_uses_reg (ip, ((prev_insn.insn_opcode >> OP_SH_RD)
- & OP_MASK_RD),
- MIPS_GR_REG))
-
+ & OP_MASK_RD),
+ MIPS_GR_REG))
{
nops += 2;
}
instruction. May want to add this support in the future. */
}
/* Never set the bit for $0, which is always zero. */
- mips_gprmask &=~ 1 << 0;
+ mips_gprmask &= ~1 << 0;
}
else
{
&& ! gpr_interlocks
&& (prev_pinfo & INSN_LOAD_MEMORY_DELAY))
|| (! mips_opts.mips16
- && mips_opts.isa == 1
+ && mips_opts.isa == ISA_MIPS1
/* Itbl support may require additional care here. */
&& (prev_pinfo & INSN_COPROC_MEMORY_DELAY))
/* We can not swap with a branch instruction. */
&& (prev_insn.insn_mo->pinfo
& INSN_LOAD_MEMORY_DELAY))
|| (! mips_opts.mips16
- && mips_opts.isa == 1
+ && mips_opts.isa == ISA_MIPS1
&& (prev_insn.insn_mo->pinfo
& INSN_COPROC_MEMORY_DELAY)))
{
- /* Itbl support may require additional care here. */
+ /* Itbl support may require additional care here. */
++nops;
if ((! mips_opts.mips16
&& ISA_HAS_COPROC_DELAYS (mips_opts.isa)
&& ((prev_prev_insn.insn_mo->pinfo & INSN_READ_HI)
|| (prev_prev_insn.insn_mo->pinfo & INSN_READ_LO))))
{
- /* Itbl support may require additional care here. */
+ /* Itbl support may require additional care here. */
if (! prev_prev_insn_unreordered)
++nops;
}
insn.insn_opcode |= va_arg (args, int) << 11;
continue;
+ case 'U':
+ {
+ int tmp = va_arg (args, int);
+
+ insn.insn_opcode |= tmp << 16;
+ insn.insn_opcode |= tmp << 11;
+ continue;
+ }
+
case 'V':
case 'S':
insn.insn_opcode |= va_arg (args, int) << 11;
insn.insn_opcode |= va_arg (args, int) << 6;
continue;
+ case 'J':
+ insn.insn_opcode |= va_arg (args, int) << 6;
+ continue;
+
case 'q':
insn.insn_opcode |= va_arg (args, int) << 6;
continue;
unsigned long hi, lo;
if (hi32.X_add_number == 0xffffffff)
- {
- if ((lo32.X_add_number & 0xffff8000) == 0xffff8000)
- {
- macro_build ((char *) NULL, counter, &lo32, "addiu", "t,r,j",
+ {
+ if ((lo32.X_add_number & 0xffff8000) == 0xffff8000)
+ {
+ macro_build ((char *) NULL, counter, &lo32, "addiu", "t,r,j",
reg, 0, (int) BFD_RELOC_LO16);
- return;
- }
- if (lo32.X_add_number & 0x80000000)
- {
- macro_build ((char *) NULL, counter, &lo32, "lui", "t,u", reg,
- (int) BFD_RELOC_HI16);
+ return;
+ }
+ if (lo32.X_add_number & 0x80000000)
+ {
+ macro_build ((char *) NULL, counter, &lo32, "lui", "t,u", reg,
+ (int) BFD_RELOC_HI16);
if (lo32.X_add_number & 0xffff)
macro_build ((char *) NULL, counter, &lo32, "ori", "t,r,i",
reg, reg, (int) BFD_RELOC_LO16);
- return;
- }
- }
+ return;
+ }
+ }
/* Check for 16bit shifted constant. We know that hi32 is
non-zero, so start the mask on the first bit of the hi32
value. */
shift = 17;
do
- {
- unsigned long himask, lomask;
-
- if (shift < 32)
- {
- himask = 0xffff >> (32 - shift);
- lomask = (0xffff << shift) & 0xffffffff;
- }
- else
- {
- himask = 0xffff << (shift - 32);
- lomask = 0;
- }
- if ((hi32.X_add_number & ~ (offsetT) himask) == 0
- && (lo32.X_add_number & ~ (offsetT) lomask) == 0)
- {
- expressionS tmp;
-
- tmp.X_op = O_constant;
- if (shift < 32)
- tmp.X_add_number = ((hi32.X_add_number << (32 - shift))
- | (lo32.X_add_number >> shift));
- else
- tmp.X_add_number = hi32.X_add_number >> (shift - 32);
- macro_build ((char *) NULL, counter, &tmp, "ori", "t,r,i", reg, 0,
- (int) BFD_RELOC_LO16);
- macro_build ((char *) NULL, counter, NULL,
- (shift >= 32) ? "dsll32" : "dsll",
- "d,w,<", reg, reg,
- (shift >= 32) ? shift - 32 : shift);
- return;
- }
- shift++;
- } while (shift <= (64 - 16));
+ {
+ unsigned long himask, lomask;
+
+ if (shift < 32)
+ {
+ himask = 0xffff >> (32 - shift);
+ lomask = (0xffff << shift) & 0xffffffff;
+ }
+ else
+ {
+ himask = 0xffff << (shift - 32);
+ lomask = 0;
+ }
+ if ((hi32.X_add_number & ~(offsetT) himask) == 0
+ && (lo32.X_add_number & ~(offsetT) lomask) == 0)
+ {
+ expressionS tmp;
+
+ tmp.X_op = O_constant;
+ if (shift < 32)
+ tmp.X_add_number = ((hi32.X_add_number << (32 - shift))
+ | (lo32.X_add_number >> shift));
+ else
+ tmp.X_add_number = hi32.X_add_number >> (shift - 32);
+ macro_build ((char *) NULL, counter, &tmp,
+ "ori", "t,r,i", reg, 0,
+ (int) BFD_RELOC_LO16);
+ macro_build ((char *) NULL, counter, NULL,
+ (shift >= 32) ? "dsll32" : "dsll",
+ "d,w,<", reg, reg,
+ (shift >= 32) ? shift - 32 : shift);
+ return;
+ }
+ shift++;
+ }
+ while (shift <= (64 - 16));
/* Find the bit number of the lowest one bit, and store the
shifted value in hi/lo. */
/* Optimize if the shifted value is a (power of 2) - 1. */
if ((hi == 0 && ((lo + 1) & lo) == 0)
|| (lo == 0xffffffff && ((hi + 1) & hi) == 0))
- {
- shift = COUNT_TOP_ZEROES ((unsigned int) hi32.X_add_number);
+ {
+ shift = COUNT_TOP_ZEROES ((unsigned int) hi32.X_add_number);
if (shift != 0)
- {
+ {
expressionS tmp;
/* This instruction will set the register to be all
ones. */
- tmp.X_op = O_constant;
- tmp.X_add_number = (offsetT) -1;
- macro_build ((char *) NULL, counter, &tmp, "addiu", "t,r,j",
+ tmp.X_op = O_constant;
+ tmp.X_add_number = (offsetT) -1;
+ macro_build ((char *) NULL, counter, &tmp, "addiu", "t,r,j",
reg, 0, (int) BFD_RELOC_LO16);
- if (bit != 0)
- {
- bit += shift;
- macro_build ((char *) NULL, counter, NULL,
- (bit >= 32) ? "dsll32" : "dsll",
- "d,w,<", reg, reg,
- (bit >= 32) ? bit - 32 : bit);
- }
- macro_build ((char *) NULL, counter, NULL,
+ if (bit != 0)
+ {
+ bit += shift;
+ macro_build ((char *) NULL, counter, NULL,
+ (bit >= 32) ? "dsll32" : "dsll",
+ "d,w,<", reg, reg,
+ (bit >= 32) ? bit - 32 : bit);
+ }
+ macro_build ((char *) NULL, counter, NULL,
(shift >= 32) ? "dsrl32" : "dsrl",
- "d,w,<", reg, reg,
+ "d,w,<", reg, reg,
(shift >= 32) ? shift - 32 : shift);
- return;
- }
- }
+ return;
+ }
+ }
/* Sign extend hi32 before calling load_register, because we can
generally get better code when we load a sign extended value. */
if ((hi32.X_add_number & 0x80000000) != 0)
- hi32.X_add_number |= ~ (offsetT) 0xffffffff;
+ hi32.X_add_number |= ~(offsetT) 0xffffffff;
load_register (counter, reg, &hi32, 0);
freg = reg;
}
expressionS mid16;
if ((freg == 0) && (lo32.X_add_number == 0xffffffff))
- {
+ {
macro_build ((char *) NULL, counter, &lo32, "lui", "t,u", reg,
(int) BFD_RELOC_HI16);
- macro_build ((char *) NULL, counter, NULL, "dsrl32", "d,w,<", reg,
- reg, 0);
- return;
- }
+ macro_build ((char *) NULL, counter, NULL, "dsrl32", "d,w,<", reg,
+ reg, 0);
+ return;
+ }
if (freg != 0)
{
addiu $reg,$reg,<sym> (BFD_RELOC_LO16)
If we have an addend, we always use the latter form. */
if ((valueT) ep->X_add_number >= MAX_GPREL_OFFSET
- || nopic_need_relax (ep->X_add_symbol, 1))
+ || nopic_need_relax (ep->X_add_symbol, 1))
p = NULL;
else
{
if (mips_trap)
macro_build ((char *) NULL, &icnt, NULL, "teq", "s,t", 0, 0);
else
- macro_build ((char *) NULL, &icnt, NULL, "break", "c", 7);
+ macro_build ((char *) NULL, &icnt, NULL, "break", "c", 7);
return;
}
macro_build ((char *) NULL, &icnt, NULL,
dbl ? "ddiv" : "div",
"z,s,t", sreg, treg);
- macro_build ((char *) NULL, &icnt, NULL, "break", "c", 7);
+ macro_build ((char *) NULL, &icnt, NULL, "break", "c", 7);
}
expr1.X_add_number = -1;
macro_build ((char *) NULL, &icnt, &expr1,
that later insns are available for delay slot filling. */
--mips_opts.noreorder;
- macro_build ((char *) NULL, &icnt, NULL, "break", "c", 6);
+ macro_build ((char *) NULL, &icnt, NULL, "break", "c", 6);
}
macro_build ((char *) NULL, &icnt, NULL, s, "d", dreg);
break;
if (mips_trap)
macro_build ((char *) NULL, &icnt, NULL, "teq", "s,t", 0, 0);
else
- macro_build ((char *) NULL, &icnt, NULL, "break", "c", 7);
+ macro_build ((char *) NULL, &icnt, NULL, "break", "c", 7);
return;
}
if (imm_expr.X_op == O_constant && imm_expr.X_add_number == 1)
/* We want to close the noreorder block as soon as possible, so
that later insns are available for delay slot filling. */
--mips_opts.noreorder;
- macro_build ((char *) NULL, &icnt, NULL, "break", "c", 7);
+ macro_build ((char *) NULL, &icnt, NULL, "break", "c", 7);
}
macro_build ((char *) NULL, &icnt, NULL, s2, "d", dreg);
return;
}
else if (mips_pic == SVR4_PIC && ! mips_big_got)
{
+ int lw_reloc_type = (int) BFD_RELOC_MIPS_GOT16;
+
/* If this is a reference to an external symbol, and there
is no constant, we want
lw $tempreg,<sym>($gp) (BFD_RELOC_MIPS_GOT16)
+ or if tempreg is PIC_CALL_REG
+ lw $tempreg,<sym>($gp) (BFD_RELOC_MIPS_CALL16)
For a local symbol, we want
lw $tempreg,<sym>($gp) (BFD_RELOC_MIPS_GOT16)
nop
expr1.X_add_number = offset_expr.X_add_number;
offset_expr.X_add_number = 0;
frag_grow (32);
+ if (expr1.X_add_number == 0 && tempreg == PIC_CALL_REG)
+ lw_reloc_type = (int) BFD_RELOC_MIPS_CALL16;
macro_build ((char *) NULL, &icnt, &offset_expr,
dbl ? "ld" : "lw",
- "t,o(b)", tempreg, (int) BFD_RELOC_MIPS_GOT16, GP);
+ "t,o(b)", tempreg, lw_reloc_type, GP);
if (expr1.X_add_number == 0)
{
int off;
else if (mips_pic == SVR4_PIC)
{
int gpdel;
+ int lui_reloc_type = (int) BFD_RELOC_MIPS_GOT_HI16;
+ int lw_reloc_type = (int) BFD_RELOC_MIPS_GOT_LO16;
/* This is the large GOT case. If this is a reference to an
external symbol, and there is no constant, we want
lui $tempreg,<sym> (BFD_RELOC_MIPS_GOT_HI16)
addu $tempreg,$tempreg,$gp
lw $tempreg,<sym>($tempreg) (BFD_RELOC_MIPS_GOT_LO16)
+ or if tempreg is PIC_CALL_REG
+ lui $tempreg,<sym> (BFD_RELOC_MIPS_CALL_HI16)
+ addu $tempreg,$tempreg,$gp
+ lw $tempreg,<sym>($tempreg) (BFD_RELOC_MIPS_CALL_LO16)
For a local symbol, we want
lw $tempreg,<sym>($gp) (BFD_RELOC_MIPS_GOT16)
nop
gpdel = 4;
else
gpdel = 0;
+ if (expr1.X_add_number == 0 && tempreg == PIC_CALL_REG)
+ {
+ lui_reloc_type = (int) BFD_RELOC_MIPS_CALL_HI16;
+ lw_reloc_type = (int) BFD_RELOC_MIPS_CALL_LO16;
+ }
macro_build ((char *) NULL, &icnt, &offset_expr, "lui", "t,u",
- tempreg, (int) BFD_RELOC_MIPS_GOT_HI16);
+ tempreg, lui_reloc_type);
macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
((bfd_arch_bits_per_address (stdoutput) == 32
|| ! ISA_HAS_64BIT_REGS (mips_opts.isa))
"d,v,t", tempreg, tempreg, GP);
macro_build ((char *) NULL, &icnt, &offset_expr,
dbl ? "ld" : "lw",
- "t,o(b)", tempreg, (int) BFD_RELOC_MIPS_GOT_LO16,
- tempreg);
+ "t,o(b)", tempreg, lw_reloc_type, tempreg);
if (expr1.X_add_number == 0)
{
int off;
s = segment_name (S_GET_SEGMENT (offset_expr.X_add_symbol));
if (strcmp (s, ".lit8") == 0)
{
- if (mips_opts.isa != 1)
+ if (mips_opts.isa != ISA_MIPS1)
{
macro_build ((char *) NULL, &icnt, &offset_expr, "ldc1",
"T,o(b)", treg, (int) BFD_RELOC_MIPS_LITERAL, GP);
macro_build_lui ((char *) NULL, &icnt, &offset_expr, AT);
}
- if (mips_opts.isa != 1)
+ if (mips_opts.isa != ISA_MIPS1)
{
macro_build ((char *) NULL, &icnt, &offset_expr, "ldc1",
"T,o(b)", treg, (int) BFD_RELOC_LO16, AT);
to adjust when loading from memory. */
r = BFD_RELOC_LO16;
dob:
- assert (mips_opts.isa == 1);
+ assert (mips_opts.isa == ISA_MIPS1);
macro_build ((char *) NULL, &icnt, &offset_expr, "lwc1", "T,o(b)",
target_big_endian ? treg + 1 : treg,
(int) r, breg);
}
/* Itbl support may require additional care here. */
coproc = 1;
- if (mips_opts.isa != 1)
+ if (mips_opts.isa != ISA_MIPS1)
{
s = "ldc1";
goto ld;
return;
}
- if (mips_opts.isa != 1)
+ if (mips_opts.isa != ISA_MIPS1)
{
s = "sdc1";
goto st;
used_at = 1;
}
- /* Itbl support may require additional care here. */
+ /* Itbl support may require additional care here. */
macro_build ((char *) NULL, &icnt, &offset_expr, s, fmt,
coproc ? treg + 1 : treg,
(int) BFD_RELOC_MIPS_GPREL, tempreg);
undesired nop. */
hold_mips_optimize = mips_optimize;
mips_optimize = 2;
- /* Itbl support may require additional care here. */
+ /* Itbl support may require additional care here. */
macro_build ((char *) NULL, &icnt, &offset_expr, s, fmt,
coproc ? treg : treg + 1,
(int) BFD_RELOC_MIPS_GPREL, tempreg);
if (p != NULL)
p += 4;
}
- /* Itbl support may require additional care here. */
+ /* Itbl support may require additional care here. */
macro_build (p, &icnt, &offset_expr, s, fmt,
coproc ? treg + 1 : treg,
(int) BFD_RELOC_LO16, AT);
p += 4;
/* FIXME: How do we handle overflow here? */
offset_expr.X_add_number += 4;
- /* Itbl support may require additional care here. */
+ /* Itbl support may require additional care here. */
macro_build (p, &icnt, &offset_expr, s, fmt,
coproc ? treg : treg + 1,
(int) BFD_RELOC_LO16, AT);
|| ! ISA_HAS_64BIT_REGS (mips_opts.isa))
? "addu" : "daddu"),
"d,v,t", AT, breg, AT);
- /* Itbl support may require additional care here. */
+ /* Itbl support may require additional care here. */
macro_build ((char *) NULL, &icnt, &expr1, s, fmt,
coproc ? treg + 1 : treg,
(int) BFD_RELOC_LO16, AT);
nop. */
hold_mips_optimize = mips_optimize;
mips_optimize = 2;
- /* Itbl support may require additional care here. */
+ /* Itbl support may require additional care here. */
macro_build ((char *) NULL, &icnt, &expr1, s, fmt,
coproc ? treg : treg + 1,
(int) BFD_RELOC_LO16, AT);
|| ! ISA_HAS_64BIT_REGS (mips_opts.isa))
? "addu" : "daddu"),
"d,v,t", AT, breg, AT);
- /* Itbl support may require additional care here. */
+ /* Itbl support may require additional care here. */
macro_build ((char *) NULL, &icnt, &expr1, s, fmt,
coproc ? treg + 1 : treg,
(int) BFD_RELOC_LO16, AT);
nop. */
hold_mips_optimize = mips_optimize;
mips_optimize = 2;
- /* Itbl support may require additional care here. */
+ /* Itbl support may require additional care here. */
macro_build ((char *) NULL, &icnt, &expr1, s, fmt,
coproc ? treg : treg + 1,
(int) BFD_RELOC_LO16, AT);
"d,v,t", AT, breg, AT);
p += 4;
}
- /* Itbl support may require additional care here. */
+ /* Itbl support may require additional care here. */
macro_build (p, &icnt, &expr1, s, fmt,
coproc ? treg + 1 : treg,
(int) BFD_RELOC_LO16, AT);
nop. */
hold_mips_optimize = mips_optimize;
mips_optimize = 2;
- /* Itbl support may require additional care here. */
+ /* Itbl support may require additional care here. */
macro_build (p, &icnt, &expr1, s, fmt,
coproc ? treg : treg + 1,
(int) BFD_RELOC_LO16, AT);
used_at = 1;
}
- /* Itbl support may require additional care here. */
+ /* Itbl support may require additional care here. */
macro_build ((char *) NULL, &icnt, &offset_expr, s, fmt,
coproc ? treg + 1 : treg,
(int) BFD_RELOC_MIPS_GPREL, tempreg);
offset_expr.X_add_number += 4;
- /* Itbl support may require additional care here. */
+ /* Itbl support may require additional care here. */
macro_build ((char *) NULL, &icnt, &offset_expr, s, fmt,
coproc ? treg : treg + 1,
(int) BFD_RELOC_MIPS_GPREL, tempreg);
Would it be more efficient to use mask (id) here? */
if (itbl_have_entries
&& (immed_expr = itbl_assemble (ip->insn_mo->name, "")))
- {
+ {
s = ip->insn_mo->name;
s2 = "cop3";
coproc = ITBL_DECODE_PNUM (immed_expr);;
macro_build ((char *) NULL, &icnt, &immed_expr, s, "C");
return;
- }
+ }
macro2 (ip);
return;
}
expr1.X_add_number = 8;
macro_build ((char *) NULL, &icnt, &expr1, "beq", "s,t,p", dreg, AT);
macro_build ((char *) NULL, &icnt, NULL, "nop", "", 0);
- macro_build ((char *) NULL, &icnt, NULL, "break", "c", 6);
+ macro_build ((char *) NULL, &icnt, NULL, "break", "c", 6);
}
--mips_opts.noreorder;
macro_build ((char *) NULL, &icnt, NULL, "mflo", "d", dreg);
expr1.X_add_number = 8;
macro_build ((char *) NULL, &icnt, &expr1, "beq", "s,t,p", AT, 0);
macro_build ((char *) NULL, &icnt, NULL, "nop", "", 0);
- macro_build ((char *) NULL, &icnt, NULL, "break", "c", 6);
+ macro_build ((char *) NULL, &icnt, NULL, "break", "c", 6);
}
--mips_opts.noreorder;
break;
as_bad (_("opcode not supported on this processor"));
return;
}
- assert (mips_opts.isa == 1);
+ assert (mips_opts.isa == ISA_MIPS1);
/* Even on a big endian machine $fn comes before $fn+1. We have
to adjust when storing to memory. */
macro_build ((char *) NULL, &icnt, &offset_expr, "swc1", "T,o(b)",
case M_TRUNCWS:
case M_TRUNCWD:
- assert (mips_opts.isa == 1);
+ assert (mips_opts.isa == ISA_MIPS1);
sreg = (ip->insn_opcode >> 11) & 0x1f; /* floating reg */
dreg = (ip->insn_opcode >> 06) & 0x1f; /* floating reg */
"0,x,y", xreg, yreg);
expr1.X_add_number = 2;
macro_build ((char *) NULL, &icnt, &expr1, "bnez", "x,p", yreg);
- macro_build ((char *) NULL, &icnt, NULL, "break", "6", 7);
+ macro_build ((char *) NULL, &icnt, NULL, "break", "6", 7);
/* FIXME: The normal code checks for of -1 / -0x80000000 here,
since that causes an overflow. We should do that as well,
case '<': USE_BITS (OP_MASK_SHAMT, OP_SH_SHAMT); break;
case '>': USE_BITS (OP_MASK_SHAMT, OP_SH_SHAMT); break;
case 'A': break;
- case 'B': USE_BITS (OP_MASK_SYSCALL, OP_SH_SYSCALL); break;
+ case 'B': USE_BITS (OP_MASK_CODE20, OP_SH_CODE20); break;
case 'C': USE_BITS (OP_MASK_COPZ, OP_SH_COPZ); break;
case 'D': USE_BITS (OP_MASK_FD, OP_SH_FD); break;
case 'E': USE_BITS (OP_MASK_RT, OP_SH_RT); break;
case 'G': USE_BITS (OP_MASK_RD, OP_SH_RD); break;
case 'H': USE_BITS (OP_MASK_SEL, OP_SH_SEL); break;
case 'I': break;
+ case 'J': USE_BITS (OP_MASK_CODE19, OP_SH_CODE19); break;
case 'L': break;
case 'M': USE_BITS (OP_MASK_CCC, OP_SH_CCC); break;
case 'N': USE_BITS (OP_MASK_BCC, OP_SH_BCC); break;
case 'j': USE_BITS (OP_MASK_DELTA, OP_SH_DELTA); break;
case 'k': USE_BITS (OP_MASK_CACHE, OP_SH_CACHE); break;
case 'l': break;
- case 'm': USE_BITS (OP_MASK_CODE20, OP_SH_CODE20); break;
case 'o': USE_BITS (OP_MASK_DELTA, OP_SH_DELTA); break;
case 'p': USE_BITS (OP_MASK_DELTA, OP_SH_DELTA); break;
case 'q': USE_BITS (OP_MASK_CODE2, OP_SH_CODE2); break;
case 'x': break;
case 'z': break;
case 'P': USE_BITS (OP_MASK_PERFREG, OP_SH_PERFREG); break;
+ case 'U': USE_BITS (OP_MASK_RD, OP_SH_RD);
+ USE_BITS (OP_MASK_RT, OP_SH_RT); break;
default:
as_bad (_("internal: bad mips opcode (unknown operand type `%c'): %s %s"),
c, opc->name, opc->args);
continue;
}
else
- {
+ {
static char buf[100];
sprintf (buf,
- _("opcode not supported on this processor: %s (MIPS%d)"),
- mips_cpu_to_str (mips_cpu), mips_opts.isa);
+ _("opcode not supported on this processor: %s (%s)"),
+ mips_cpu_to_str (mips_cpu),
+ mips_isa_to_str (mips_opts.isa));
insn_error = buf;
return;
s = expr_end;
continue;
- case 'm': /* Full 20 bit break code. */
+ case 'B': /* 20-bit syscall/break code. */
my_getExpression (&imm_expr, s);
-
check_absolute_expr (ip, &imm_expr);
-
if ((unsigned) imm_expr.X_add_number > 0xfffff)
+ as_warn (_("Illegal 20-bit code (%ld)"),
+ (long) imm_expr.X_add_number);
+ ip->insn_opcode |= imm_expr.X_add_number << 6;
+ imm_expr.X_op = O_absent;
+ s = expr_end;
+ continue;
+
+ case 'C': /* Coprocessor code */
+ my_getExpression (&imm_expr, s);
+ check_absolute_expr (ip, &imm_expr);
+ if ((unsigned long) imm_expr.X_add_number >= (1<<25))
{
- as_warn (_("Illegal break code (%ld)"),
+ as_warn (_("Coproccesor code > 25 bits (%ld)"),
(long) imm_expr.X_add_number);
- imm_expr.X_add_number &= 0xfffff;
+ imm_expr.X_add_number &= ((1<<25) - 1);
}
-
- ip->insn_opcode |= imm_expr.X_add_number << 6;
+ ip->insn_opcode |= imm_expr.X_add_number;
imm_expr.X_op = O_absent;
s = expr_end;
-
continue;
- case 'B': /* syscall code */
+ case 'J': /* 19-bit wait code. */
my_getExpression (&imm_expr, s);
check_absolute_expr (ip, &imm_expr);
- if ((unsigned) imm_expr.X_add_number > 0xfffff)
- as_warn (_("Illegal syscall code (%ld)"),
+ if ((unsigned) imm_expr.X_add_number > 0x7ffff)
+ as_warn (_("Illegal 19-bit code (%ld)"),
(long) imm_expr.X_add_number);
ip->insn_opcode |= imm_expr.X_add_number << 6;
imm_expr.X_op = O_absent;
s = expr_end;
continue;
- case 'C': /* Coprocessor code */
- my_getExpression (&imm_expr, s);
- check_absolute_expr (ip, &imm_expr);
- if ((unsigned long) imm_expr.X_add_number >= (1<<25))
- {
- as_warn (_("Coproccesor code > 25 bits (%ld)"),
- (long) imm_expr.X_add_number);
- imm_expr.X_add_number &= ((1<<25) - 1);
- }
- ip->insn_opcode |= imm_expr.X_add_number;
- imm_expr.X_op = O_absent;
- s = expr_end;
- continue;
-
case 'P': /* Performance register */
- my_getExpression (&imm_expr, s);
+ my_getExpression (&imm_expr, s);
check_absolute_expr (ip, &imm_expr);
- if (imm_expr.X_add_number != 0 && imm_expr.X_add_number != 1)
+ if (imm_expr.X_add_number != 0 && imm_expr.X_add_number != 1)
{
- as_warn (_("Invalidate performance regster (%ld)"),
+ as_warn (_("Invalidate performance regster (%ld)"),
(long) imm_expr.X_add_number);
- imm_expr.X_add_number &= 1;
+ imm_expr.X_add_number &= 1;
}
- ip->insn_opcode |= (imm_expr.X_add_number << 1);
- imm_expr.X_op = O_absent;
- s = expr_end;
- continue;
+ ip->insn_opcode |= (imm_expr.X_add_number << 1);
+ imm_expr.X_op = O_absent;
+ s = expr_end;
+ continue;
case 'b': /* base register */
case 'd': /* destination register */
case 'G': /* coprocessor destination register */
case 'x': /* ignore register name */
case 'z': /* must be zero register */
+ case 'U': /* destination register (clo/clz). */
s_reset = s;
if (s[0] == '$')
{
}
else
goto notreg;
- }
+ }
else
goto notreg;
}
case 'G':
ip->insn_opcode |= regno << 11;
break;
+ case 'U':
+ ip->insn_opcode |= regno << 11;
+ ip->insn_opcode |= regno << 16;
+ break;
case 'w':
case 't':
case 'E':
{
if ((c == '\0' && imm_expr.X_op != O_constant)
|| ((imm_expr.X_add_number < 0
- || imm_expr.X_add_number >= 0x10000)
- && imm_expr.X_op == O_constant))
+ || imm_expr.X_add_number >= 0x10000)
+ && imm_expr.X_op == O_constant))
{
if (insn + 1 < &mips_opcodes[NUMOPCODES] &&
!strcmp (insn->name, insn[1].name))
max = 0x10000;
if ((c == '\0' && imm_expr.X_op != O_constant)
|| ((imm_expr.X_add_number < -0x8000
- || imm_expr.X_add_number >= max)
- && imm_expr.X_op == O_constant)
+ || imm_expr.X_add_number >= max)
+ && imm_expr.X_op == O_constant)
|| (more
&& imm_expr.X_add_number < 0
&& ISA_HAS_64BIT_REGS (mips_opts.isa)
ip->insn_opcode |= regno << OP_SH_BCC;
else
ip->insn_opcode |= regno << OP_SH_CCC;
- continue;
+ continue;
case 'H':
if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X'))
needext = false;
if (warn && ext && ! needext)
- as_warn_where (file, line, _("extended operand requested but not required"));
+ as_warn_where (file, line,
+ _("extended operand requested but not required"));
if (small && needext)
as_bad_where (file, line, _("invalid unextended operand value"));
{"no-construct-floats", no_argument, NULL, OPTION_NO_CONSTRUCT_FLOATS},
#define OPTION_MIPS32 (OPTION_MD_BASE + 28)
{"mips32", no_argument, NULL, OPTION_MIPS32},
-#define OPTION_NO_MIPS32 (OPTION_MD_BASE + 29)
- {"no-mips32", no_argument, NULL, OPTION_NO_MIPS32},
-
+#define OPTION_MIPS5 (OPTION_MD_BASE + 29)
+ {"mips5", no_argument, NULL, OPTION_MIPS5},
+#define OPTION_MIPS64 (OPTION_MD_BASE + 30)
+ {"mips64", no_argument, NULL, OPTION_MIPS64},
#ifdef OBJ_ELF
#define OPTION_ELF_BASE (OPTION_MD_BASE + 35)
#define OPTION_CALL_SHARED (OPTION_ELF_BASE + 0)
break;
case OPTION_MIPS1:
- mips_opts.isa = 1;
+ mips_opts.isa = ISA_MIPS1;
break;
case OPTION_MIPS2:
- mips_opts.isa = 2;
+ mips_opts.isa = ISA_MIPS2;
break;
case OPTION_MIPS3:
- mips_opts.isa = 3;
+ mips_opts.isa = ISA_MIPS3;
break;
case OPTION_MIPS4:
- mips_opts.isa = 4;
+ mips_opts.isa = ISA_MIPS4;
+ break;
+
+ case OPTION_MIPS5:
+ mips_opts.isa = ISA_MIPS5;
+ break;
+
+ case OPTION_MIPS32:
+ mips_opts.isa = ISA_MIPS32;
+ break;
+
+ case OPTION_MIPS64:
+ mips_opts.isa = ISA_MIPS64;
break;
case OPTION_MCPU:
{
- char *p;
-
- /* Identify the processor type */
- p = arg;
- if (strcmp (p, "default") == 0
- || strcmp (p, "DEFAULT") == 0)
- mips_cpu = -1;
+ /* Identify the processor type. */
+ if (strcasecmp (arg, "default") == 0)
+ mips_cpu = CPU_UNKNOWN;
else
{
- int sv = 0;
-
- /* We need to cope with the various "vr" prefixes for the 4300
- processor. */
- if (*p == 'v' || *p == 'V')
- {
- sv = 1;
- p++;
- }
+ const struct mips_cpu_info *ci;
- if (*p == 'r' || *p == 'R')
- p++;
-
- mips_cpu = -1;
- switch (*p)
- {
- case '1':
- if (strcmp (p, "10000") == 0
- || strcmp (p, "10k") == 0
- || strcmp (p, "10K") == 0)
- mips_cpu = CPU_R10000;
- break;
-
- case '2':
- if (strcmp (p, "2000") == 0
- || strcmp (p, "2k") == 0
- || strcmp (p, "2K") == 0)
- mips_cpu = CPU_R2000;
- break;
-
- case '3':
- if (strcmp (p, "3000") == 0
- || strcmp (p, "3k") == 0
- || strcmp (p, "3K") == 0)
- mips_cpu = CPU_R3000;
- else if (strcmp (p, "3900") == 0)
- mips_cpu = CPU_R3900;
- break;
-
- case '4':
- if (strcmp (p, "4000") == 0
- || strcmp (p, "4k") == 0
- || strcmp (p, "4K") == 0)
- mips_cpu = CPU_R4000;
- else if (strcmp (p, "4100") == 0)
- mips_cpu = CPU_VR4100;
- else if (strcmp (p, "4111") == 0)
- mips_cpu = CPU_R4111;
- else if (strcmp (p, "4300") == 0)
- mips_cpu = CPU_R4300;
- else if (strcmp (p, "4400") == 0)
- mips_cpu = CPU_R4400;
- else if (strcmp (p, "4600") == 0)
- mips_cpu = CPU_R4600;
- else if (strcmp (p, "4650") == 0)
- mips_cpu = CPU_R4650;
- else if (strcmp (p, "4010") == 0)
- mips_cpu = CPU_R4010;
- else if (strcmp (p, "4Kc") == 0
- || strcmp (p, "4Kp") == 0
- || strcmp (p, "4Km") == 0)
- mips_cpu = CPU_MIPS32;
- break;
-
- case '5':
- if (strcmp (p, "5000") == 0
- || strcmp (p, "5k") == 0
- || strcmp (p, "5K") == 0)
- mips_cpu = CPU_R5000;
- break;
-
- case '6':
- if (strcmp (p, "6000") == 0
- || strcmp (p, "6k") == 0
- || strcmp (p, "6K") == 0)
- mips_cpu = CPU_R6000;
- break;
-
- case '8':
- if (strcmp (p, "8000") == 0
- || strcmp (p, "8k") == 0
- || strcmp (p, "8K") == 0)
- mips_cpu = CPU_R8000;
- break;
-
- case 'o':
- if (strcmp (p, "orion") == 0)
- mips_cpu = CPU_R4600;
- break;
-
- case 'm':
- case 'M':
- switch (atoi (p + 1))
- {
- case 5200:
- case 5230:
- case 5231:
- case 5261:
- case 5721:
- case 7000:
- mips_cpu = CPU_R5000;
- break;
- default:
- break;
- }
- }
-
- if (sv
- && (mips_cpu != CPU_R4300
- && mips_cpu != CPU_VR4100
- && mips_cpu != CPU_R4111
- && mips_cpu != CPU_R5000))
- {
- as_bad (_("ignoring invalid leading 'v' in -mcpu=%s switch"), arg);
- return 0;
- }
-
- if (mips_cpu == -1)
- {
- as_bad (_("invalid architecture -mcpu=%s"), arg);
- return 0;
- }
+ ci = mips_cpu_info_from_name (arg);
+ if (ci == NULL || ci->is_isa)
+ as_bad (_("invalid architecture -mcpu=%s"), arg);
+ else
+ mips_cpu = ci->cpu;
}
}
break;
case OPTION_NO_M4100:
break;
- case OPTION_MIPS32:
- mips_cpu = CPU_MIPS32;
- break;
-
- case OPTION_NO_MIPS32:
- break;
-
case OPTION_M3900:
mips_cpu = CPU_R3900;
break;
g_switch_value = 0x7fffffff;
break;
+#ifdef OBJ_ELF
/* When generating ELF code, we permit -KPIC and -call_shared to
select SVR4_PIC, and -non_shared to select no PIC. This is
intended to be compatible with Irix 5. */
case OPTION_XGOT:
mips_big_got = 1;
break;
+#endif /* OBJ_ELF */
case 'G':
if (! USE_GLOBAL_POINTER_OPT)
g_switch_seen = 1;
break;
+#ifdef OBJ_ELF
/* The -32 and -64 options tell the assembler to output the 32
bit or the 64 bit MIPS ELF format. */
case OPTION_32:
list = bfd_target_list ();
for (l = list; *l != NULL; l++)
if (strcmp (*l, "elf64-bigmips") == 0
- || strcmp (*l, "elf64-littlemips") == 0)
+ || strcmp (*l, "elf64-littlemips") == 0
+ || strcmp (*l, "elf64-tradbigmips") == 0
+ || strcmp (*l, "elf64-tradlittlemips") == 0)
break;
if (*l == NULL)
as_fatal (_("No compiled in support for 64 bit object file format"));
mips_64 = 1;
}
break;
+#endif /* OBJ_ELF */
case OPTION_GP32:
mips_gp32 = 1;
gcc, but to set this flag before gcc is built with such
multilibs will break too many systems. */
-/* mips_32bitmode = 1; */
+#if 0
+ mips_32bitmode = 1;
+#endif
break;
case OPTION_GP64:
mips_gp32 = 0;
mips_64 = 1;
-/* mips_32bitmode = 0; */
+#if 0
+ mips_32bitmode = 0;
+#endif
break;
case OPTION_MABI:
- if (strcmp (arg,"32") == 0
- || strcmp (arg,"n32") == 0
- || strcmp (arg,"64") == 0
- || strcmp (arg,"o64") == 0
- || strcmp (arg,"eabi") == 0)
+ if (strcmp (arg, "32") == 0
+ || strcmp (arg, "n32") == 0
+ || strcmp (arg, "64") == 0
+ || strcmp (arg, "o64") == 0
+ || strcmp (arg, "eabi") == 0)
mips_abi_string = arg;
break;
{
int column, first;
- fprintf(stream, _("\
+ fprintf (stream, _("\
MIPS options:\n\
-membedded-pic generate embedded position independent code\n\
-EB generate big endian output\n\
-g, -g2 do not remove uneeded NOPs or swap branches\n\
-G NUM allow referencing objects up to NUM bytes\n\
implicitly with the gp register [default 8]\n"));
- fprintf(stream, _("\
+ fprintf (stream, _("\
-mips1 generate MIPS ISA I instructions\n\
-mips2 generate MIPS ISA II instructions\n\
-mips3 generate MIPS ISA III instructions\n\
-mips4 generate MIPS ISA IV instructions\n\
+-mips5 generate MIPS ISA V instructions\n\
+-mips32 generate MIPS32 ISA instructions\n\
+-mips64 generate MIPS64 ISA instructions\n\
-mcpu=CPU generate code for CPU, where CPU is one of:\n"));
first = 1;
show (stream, "6000", &column, &first);
show (stream, "8000", &column, &first);
show (stream, "10000", &column, &first);
- show (stream, "4Kc", &column, &first);
- show (stream, "4Kp", &column, &first);
- show (stream, "4Km", &column, &first);
+ show (stream, "12000", &column, &first);
+ show (stream, "mips32-4k", &column, &first);
+ show (stream, "sb-1", &column, &first);
fputc ('\n', stream);
fprintf (stream, _("\
fputc ('\n', stream);
fprintf (stream, _("\
--mips32 generate MIPS32 instructions\n"));
-
- fprintf(stream, _("\
-mips16 generate mips16 instructions\n\
-no-mips16 do not generate mips16 instructions\n"));
- fprintf(stream, _("\
+ fprintf (stream, _("\
-O0 remove unneeded NOPs, do not swap branches\n\
-O remove unneeded NOPs and swap branches\n\
--[no-]construct-floats [dis]allow floating point values to be constructed\n\
--trap, --no-break trap exception on div by 0 and mult overflow\n\
--break, --no-trap break exception on div by 0 and mult overflow\n"));
#ifdef OBJ_ELF
- fprintf(stream, _("\
+ fprintf (stream, _("\
-KPIC, -call_shared generate SVR4 position independent code\n\
-non_shared do not generate position independent code\n\
-xgot assume a 32 bit GOT\n\
{
/* initialize opcodes */
bfd_mips_num_opcodes = bfd_mips_num_builtin_opcodes;
- mips_opcodes = (struct mips_opcode*) mips_builtin_opcodes;
+ mips_opcodes = (struct mips_opcode *) mips_builtin_opcodes;
}
long
relocations, in case the linker has to relax a call. We also need
to keep relocations for switch table entries. */
-/*ARGSUSED*/
int
mips_force_relocation (fixp)
fixS *fixp;
/* Permit the user to change the ISA on the fly. Needless to
say, misuse can cause serious problems. */
isa = atoi (name + 4);
- if (isa == 0)
- mips_opts.isa = file_mips_isa;
- else if (isa < 1 || isa > 4)
- as_bad (_("unknown ISA level"));
- else
- mips_opts.isa = isa;
+ switch (isa)
+ {
+ case 0: mips_opts.isa = file_mips_isa; break;
+ case 1: mips_opts.isa = ISA_MIPS1; break;
+ case 2: mips_opts.isa = ISA_MIPS2; break;
+ case 3: mips_opts.isa = ISA_MIPS3; break;
+ case 5: mips_opts.isa = ISA_MIPS5; break;
+ case 4: mips_opts.isa = ISA_MIPS4; break;
+ case 32: mips_opts.isa = ISA_MIPS32; break;
+ case 64: mips_opts.isa = ISA_MIPS64; break;
+ default: as_bad (_("unknown ISA level")); break;
+ }
}
else if (strcmp (name, "autoextend") == 0)
mips_opts.noautoextend = 0;
encoded in the subtype information. For the mips16, we have to
decide whether we are using an extended opcode or not. */
-/*ARGSUSED*/
int
md_estimate_size_before_relax (fragp, segtype)
fragS *fragp;
/* duplicate the test for LINK_ONCE sections as in adjust_reloc_syms */
if (symsec != segtype && ! S_IS_LOCAL (sym))
- {
- if ((bfd_get_section_flags (stdoutput, symsec) & SEC_LINK_ONCE)
- != 0)
- linkonce = true;
-
- /* The GNU toolchain uses an extension for ELF: a section
- beginning with the magic string .gnu.linkonce is a linkonce
- section. */
- if (strncmp (segment_name (symsec), ".gnu.linkonce",
- sizeof ".gnu.linkonce" - 1) == 0)
- linkonce = true;
- }
+ {
+ if ((bfd_get_section_flags (stdoutput, symsec) & SEC_LINK_ONCE)
+ != 0)
+ linkonce = true;
+
+ /* The GNU toolchain uses an extension for ELF: a section
+ beginning with the magic string .gnu.linkonce is a linkonce
+ section. */
+ if (strncmp (segment_name (symsec), ".gnu.linkonce",
+ sizeof ".gnu.linkonce" - 1) == 0)
+ linkonce = true;
+ }
/* This must duplicate the test in adjust_reloc_syms. */
change = (symsec != &bfd_und_section
ext = false;
}
- resolve_symbol_value (fragp->fr_symbol, 1);
+ resolve_symbol_value (fragp->fr_symbol);
val = S_GET_VALUE (fragp->fr_symbol);
if (op->pcrel)
{
/* Set the MIPS ELF ABI flags. */
if (mips_abi_string == 0)
;
- else if (strcmp (mips_abi_string,"32") == 0)
+ else if (strcmp (mips_abi_string, "32") == 0)
elf_elfheader (stdoutput)->e_flags |= E_MIPS_ABI_O32;
- else if (strcmp (mips_abi_string,"o64") == 0)
+ else if (strcmp (mips_abi_string, "o64") == 0)
elf_elfheader (stdoutput)->e_flags |= E_MIPS_ABI_O64;
- else if (strcmp (mips_abi_string,"eabi") == 0)
+ else if (strcmp (mips_abi_string, "eabi") == 0)
{
if (mips_eabi64)
elf_elfheader (stdoutput)->e_flags |= E_MIPS_ABI_EABI64;
#endif /* OBJ_ELF || OBJ_MAYBE_ELF */
\f
-typedef struct proc
- {
- symbolS *isym;
- unsigned long reg_mask;
- unsigned long reg_offset;
- unsigned long fpreg_mask;
- unsigned long fpreg_offset;
- unsigned long frame_offset;
- unsigned long frame_reg;
- unsigned long pc_reg;
- }
-procS;
+typedef struct proc {
+ symbolS *isym;
+ unsigned long reg_mask;
+ unsigned long reg_offset;
+ unsigned long fpreg_mask;
+ unsigned long fpreg_offset;
+ unsigned long frame_offset;
+ unsigned long frame_reg;
+ unsigned long pc_reg;
+} procS;
static procS cur_proc;
static procS *cur_proc_ptr;
static int numprocs;
-/* When we align code in the .text section of mips16, use the correct two
- byte nop pattern of 0x6500 (move $0,$0) */
+/* Fill in an rs_align_code fragment. */
-int
-mips_do_align (n, fill, len, max)
- int n;
- const char *fill;
- int len ATTRIBUTE_UNUSED;
- int max;
+void
+mips_handle_align (fragp)
+ fragS *fragp;
{
- if (fill == NULL
- && subseg_text_p (now_seg)
- && n > 1
- && mips_opts.mips16)
+ if (fragp->fr_type != rs_align_code)
+ return;
+
+ if (mips_opts.mips16)
{
static const unsigned char be_nop[] = { 0x65, 0x00 };
static const unsigned char le_nop[] = { 0x00, 0x65 };
- frag_align (1, 0, 0);
+ int bytes;
+ char *p;
- if (target_big_endian)
- frag_align_pattern (n, be_nop, 2, max);
- else
- frag_align_pattern (n, le_nop, 2, max);
- return 1;
+ bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix;
+ p = fragp->fr_literal + fragp->fr_fix;
+
+ if (bytes & 1)
+ {
+ *p++ = 0;
+ fragp->fr_fix += 1;
+ }
+
+ memcpy (p, (target_big_endian ? be_nop : le_nop), 2);
+ fragp->fr_var = 2;
}
- return 0;
+ /* For mips32, a nop is a zero, which we trivially get by doing nothing. */
}
static void
assert (pdr_seg);
subseg_set (pdr_seg, 0);
- /* Write the symbol */
+ /* Write the symbol. */
exp.X_op = O_symbol;
exp.X_add_symbol = p;
exp.X_add_number = 0;
emit_expr (&exp, 4);
- fragp = frag_more (7*4);
+ fragp = frag_more (7 * 4);
- md_number_to_chars (fragp, (valueT) cur_proc_ptr->reg_mask, 4);
- md_number_to_chars (fragp + 4, (valueT) cur_proc_ptr->reg_offset, 4);
- md_number_to_chars (fragp + 8, (valueT) cur_proc_ptr->fpreg_mask, 4);
- md_number_to_chars (fragp +12, (valueT) cur_proc_ptr->fpreg_offset, 4);
- md_number_to_chars (fragp +16, (valueT) cur_proc_ptr->frame_offset, 4);
- md_number_to_chars (fragp +20, (valueT) cur_proc_ptr->frame_reg, 4);
- md_number_to_chars (fragp +24, (valueT) cur_proc_ptr->pc_reg, 4);
+ md_number_to_chars (fragp, (valueT) cur_proc_ptr->reg_mask, 4);
+ md_number_to_chars (fragp + 4, (valueT) cur_proc_ptr->reg_offset, 4);
+ md_number_to_chars (fragp + 8, (valueT) cur_proc_ptr->fpreg_mask, 4);
+ md_number_to_chars (fragp + 12, (valueT) cur_proc_ptr->fpreg_offset, 4);
+ md_number_to_chars (fragp + 16, (valueT) cur_proc_ptr->frame_offset, 4);
+ md_number_to_chars (fragp + 20, (valueT) cur_proc_ptr->frame_reg, 4);
+ md_number_to_chars (fragp + 24, (valueT) cur_proc_ptr->pc_reg, 4);
subseg_set (saved_seg, saved_subseg);
}
long val;
- if (cur_proc_ptr == (procS *) NULL)
+ if (cur_proc_ptr == (procS *) NULL)
{
as_warn (_(".frame outside of .ent"));
demand_empty_rest_of_line ();
symbolP->sy_segment = now_seg;
}
#endif
+
+/* CPU name/ISA/number mapping table.
+
+ Entries are grouped by type. The first matching CPU or ISA entry
+ gets chosen by CPU or ISA, so it should be the 'canonical' name
+ for that type. Entries after that within the type are sorted
+ alphabetically.
+
+ Case is ignored in comparison, so put the canonical entry in the
+ appropriate case but everything else in lower case to ease eye pain. */
+static const struct mips_cpu_info mips_cpu_info_table[] =
+{
+ /* MIPS1 ISA */
+ { "MIPS1", 1, ISA_MIPS1, CPU_R3000, },
+ { "mips", 1, ISA_MIPS1, CPU_R3000, },
+
+ /* MIPS2 ISA */
+ { "MIPS2", 1, ISA_MIPS2, CPU_R6000, },
+
+ /* MIPS3 ISA */
+ { "MIPS3", 1, ISA_MIPS3, CPU_R4000, },
+
+ /* MIPS4 ISA */
+ { "MIPS4", 1, ISA_MIPS4, CPU_R8000, },
+
+ /* MIPS5 ISA */
+ { "MIPS5", 1, ISA_MIPS5, CPU_MIPS5, },
+ { "Generic-MIPS5", 0, ISA_MIPS5, CPU_MIPS5, },
+
+ /* MIPS32 ISA */
+ { "MIPS32", 1, ISA_MIPS32, CPU_MIPS32, },
+ { "Generic-MIPS32", 0, ISA_MIPS32, CPU_MIPS32, },
+
+#if 1
+ /* XXX for now, MIPS64 -> MIPS3 because of history */
+ { "MIPS64", 1, ISA_MIPS3, CPU_R4000 }, /* XXX! */
+#else
+ /* MIPS64 ISA */
+ { "MIPS64", 1, ISA_MIPS64, CPU_MIPS64 },
+#endif
+ { "mips64isa", 1, ISA_MIPS64, CPU_MIPS64 },
+ { "Generic-MIPS64", 0, ISA_MIPS64, CPU_MIPS64, },
+
+ /* R2000 CPU */
+ { "R2000", 0, ISA_MIPS1, CPU_R2000, },
+ { "2000", 0, ISA_MIPS1, CPU_R2000, },
+ { "2k", 0, ISA_MIPS1, CPU_R2000, },
+ { "r2k", 0, ISA_MIPS1, CPU_R2000, },
+
+ /* R3000 CPU */
+ { "R3000", 0, ISA_MIPS1, CPU_R3000, },
+ { "3000", 0, ISA_MIPS1, CPU_R3000, },
+ { "3k", 0, ISA_MIPS1, CPU_R3000, },
+ { "r3k", 0, ISA_MIPS1, CPU_R3000, },
+
+ /* TX3900 CPU */
+ { "R3900", 0, ISA_MIPS1, CPU_R3900, },
+ { "3900", 0, ISA_MIPS1, CPU_R3900, },
+ { "mipstx39", 0, ISA_MIPS1, CPU_R3900, },
+
+ /* R4000 CPU */
+ { "R4000", 0, ISA_MIPS3, CPU_R4000, },
+ { "4000", 0, ISA_MIPS3, CPU_R4000, },
+ { "4k", 0, ISA_MIPS3, CPU_R4000, }, /* beware */
+ { "r4k", 0, ISA_MIPS3, CPU_R4000, },
+
+ /* R4010 CPU */
+ { "R4010", 0, ISA_MIPS2, CPU_R4010, },
+ { "4010", 0, ISA_MIPS2, CPU_R4010, },
+
+ /* R4400 CPU */
+ { "R4400", 0, ISA_MIPS3, CPU_R4400, },
+ { "4400", 0, ISA_MIPS3, CPU_R4400, },
+
+ /* R4600 CPU */
+ { "R4600", 0, ISA_MIPS3, CPU_R4600, },
+ { "4600", 0, ISA_MIPS3, CPU_R4600, },
+ { "mips64orion", 0, ISA_MIPS3, CPU_R4600, },
+ { "orion", 0, ISA_MIPS3, CPU_R4600, },
+
+ /* R4650 CPU */
+ { "R4650", 0, ISA_MIPS3, CPU_R4650, },
+ { "4650", 0, ISA_MIPS3, CPU_R4650, },
+
+ /* R6000 CPU */
+ { "R6000", 0, ISA_MIPS2, CPU_R6000, },
+ { "6000", 0, ISA_MIPS2, CPU_R6000, },
+ { "6k", 0, ISA_MIPS2, CPU_R6000, },
+ { "r6k", 0, ISA_MIPS2, CPU_R6000, },
+
+ /* R8000 CPU */
+ { "R8000", 0, ISA_MIPS4, CPU_R8000, },
+ { "8000", 0, ISA_MIPS4, CPU_R8000, },
+ { "8k", 0, ISA_MIPS4, CPU_R8000, },
+ { "r8k", 0, ISA_MIPS4, CPU_R8000, },
+
+ /* R10000 CPU */
+ { "R10000", 0, ISA_MIPS4, CPU_R10000, },
+ { "10000", 0, ISA_MIPS4, CPU_R10000, },
+ { "10k", 0, ISA_MIPS4, CPU_R10000, },
+ { "r10k", 0, ISA_MIPS4, CPU_R10000, },
+
+ /* R12000 CPU */
+ { "R12000", 0, ISA_MIPS4, CPU_R12000, },
+ { "12000", 0, ISA_MIPS4, CPU_R12000, },
+ { "12k", 0, ISA_MIPS4, CPU_R12000, },
+ { "r12k", 0, ISA_MIPS4, CPU_R12000, },
+
+ /* VR4100 CPU */
+ { "VR4100", 0, ISA_MIPS3, CPU_VR4100, },
+ { "4100", 0, ISA_MIPS3, CPU_VR4100, },
+ { "mips64vr4100", 0, ISA_MIPS3, CPU_VR4100, },
+ { "r4100", 0, ISA_MIPS3, CPU_VR4100, },
+
+ /* VR4111 CPU */
+ { "VR4111", 0, ISA_MIPS3, CPU_R4111, },
+ { "4111", 0, ISA_MIPS3, CPU_R4111, },
+ { "mips64vr4111", 0, ISA_MIPS3, CPU_R4111, },
+ { "r4111", 0, ISA_MIPS3, CPU_R4111, },
+
+ /* VR4300 CPU */
+ { "VR4300", 0, ISA_MIPS3, CPU_R4300, },
+ { "4300", 0, ISA_MIPS3, CPU_R4300, },
+ { "mips64vr4300", 0, ISA_MIPS3, CPU_R4300, },
+ { "r4300", 0, ISA_MIPS3, CPU_R4300, },
+
+ /* VR5000 CPU */
+ { "VR5000", 0, ISA_MIPS4, CPU_R5000, },
+ { "5000", 0, ISA_MIPS4, CPU_R5000, },
+ { "5k", 0, ISA_MIPS4, CPU_R5000, },
+ { "mips64vr5000", 0, ISA_MIPS4, CPU_R5000, },
+ { "r5000", 0, ISA_MIPS4, CPU_R5000, },
+ { "r5200", 0, ISA_MIPS4, CPU_R5000, },
+ { "r5230", 0, ISA_MIPS4, CPU_R5000, },
+ { "r5231", 0, ISA_MIPS4, CPU_R5000, },
+ { "r5261", 0, ISA_MIPS4, CPU_R5000, },
+ { "r5721", 0, ISA_MIPS4, CPU_R5000, },
+ { "r5k", 0, ISA_MIPS4, CPU_R5000, },
+ { "r7000", 0, ISA_MIPS4, CPU_R5000, },
+
+ /* MIPS32 4K CPU */
+ { "MIPS32-4K", 0, ISA_MIPS32, CPU_MIPS32_4K, },
+ { "4kc", 0, ISA_MIPS32, CPU_MIPS32_4K, },
+ { "4km", 0, ISA_MIPS32, CPU_MIPS32_4K, },
+ { "4kp", 0, ISA_MIPS32, CPU_MIPS32_4K, },
+ { "mips32-4kc", 0, ISA_MIPS32, CPU_MIPS32_4K, },
+ { "mips32-4km", 0, ISA_MIPS32, CPU_MIPS32_4K, },
+ { "mips32-4kp", 0, ISA_MIPS32, CPU_MIPS32_4K, },
+
+ /* SiByte SB-1 CPU */
+ { "SB-1", 0, ISA_MIPS64, CPU_SB1, },
+ { "sb-1250", 0, ISA_MIPS64, CPU_SB1, },
+ { "sb1", 0, ISA_MIPS64, CPU_SB1, },
+ { "sb1250", 0, ISA_MIPS64, CPU_SB1, },
+
+ /* End marker. */
+ { NULL, 0, 0, 0, },
+};
+
+static const struct mips_cpu_info *
+mips_cpu_info_from_name (name)
+ const char *name;
+{
+ int i;
+
+ for (i = 0; mips_cpu_info_table[i].name != NULL; i++)
+ if (strcasecmp (name, mips_cpu_info_table[i].name) == 0)
+ return (&mips_cpu_info_table[i]);
+
+ return NULL;
+}
+
+static const struct mips_cpu_info *
+mips_cpu_info_from_isa (isa)
+ int isa;
+{
+ int i;
+
+ for (i = 0; mips_cpu_info_table[i].name != NULL; i++)
+ if (mips_cpu_info_table[i].is_isa
+ && isa == mips_cpu_info_table[i].isa)
+ return (&mips_cpu_info_table[i]);
+
+ return NULL;
+}
+
+static const struct mips_cpu_info *
+mips_cpu_info_from_cpu (cpu)
+ int cpu;
+{
+ int i;
+
+ for (i = 0; mips_cpu_info_table[i].name != NULL; i++)
+ if (!mips_cpu_info_table[i].is_isa
+ && cpu == mips_cpu_info_table[i].cpu)
+ return (&mips_cpu_info_table[i]);
+
+ return NULL;
+}