X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gas%2Fconfig%2Ftc-mips.c;h=15c4f871303c474ee38793cdcf23d236a0700fd9;hb=d1cf510e5e1ab5cb49de51ae96ef011ec0ab7510;hp=19490a86b408cada3cd34f54fb50a1d49a921e1e;hpb=82efde3a56791e66bb9f241341df3e8d6a18247e;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c index 19490a86b4..15c4f87130 100644 --- a/gas/config/tc-mips.c +++ b/gas/config/tc-mips.c @@ -1,5 +1,5 @@ /* 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. @@ -110,6 +110,7 @@ extern int target_big_endian; static int mips_64; /* The default target format to use. */ + const char * mips_target_format () { @@ -125,7 +126,8 @@ 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") @@ -187,10 +189,13 @@ struct mips_set_options }; /* 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 @@ -199,13 +204,13 @@ unsigned long mips_gprmask; 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; @@ -226,15 +231,17 @@ static int mips_gp32 = 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 @@ -270,7 +277,7 @@ static int mips_gp32 = 0; /* 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 @@ -584,8 +591,8 @@ static const unsigned int mips16_to_32_reg_map[] = | ((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) @@ -706,9 +713,24 @@ static void s_mips_stab PARAMS ((int)); 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)); /* Pseudo-op table. @@ -730,7 +752,7 @@ static int validate_mips_insn PARAMS ((const struct mips_opcode *)); 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'}, @@ -743,7 +765,7 @@ static const pseudo_typeS mips_pseudo_table[] = {"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'}, @@ -752,7 +774,7 @@ static const pseudo_typeS mips_pseudo_table[] = {"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}, @@ -774,9 +796,10 @@ static const pseudo_typeS mips_pseudo_table[] = { 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}, @@ -852,33 +875,34 @@ static boolean mips16_small, mips16_ext; 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 @@ -887,13 +911,14 @@ mips_cpu_to_str (cpu) 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 @@ -913,129 +938,51 @@ md_begin () 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. */ @@ -1046,7 +993,7 @@ md_begin () 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 @@ -1054,40 +1001,17 @@ md_begin () 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; @@ -1303,8 +1227,8 @@ md_assemble (str) 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) @@ -1536,7 +1460,7 @@ append_insn (place, ip, address_expr, reloc_type, unmatched_hi) 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, @@ -1548,8 +1472,8 @@ append_insn (place, ip, address_expr, reloc_type, unmatched_hi) 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 @@ -1614,7 +1538,7 @@ append_insn (place, ip, address_expr, reloc_type, unmatched_hi) (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; @@ -1628,9 +1552,8 @@ append_insn (place, ip, address_expr, reloc_type, unmatched_hi) 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; } @@ -1972,7 +1895,7 @@ append_insn (place, ip, address_expr, reloc_type, unmatched_hi) 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 { @@ -2083,7 +2006,7 @@ append_insn (place, ip, address_expr, reloc_type, unmatched_hi) && ! 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. */ @@ -2419,11 +2342,11 @@ mips_emit_delays (insns) && (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) @@ -2445,7 +2368,7 @@ mips_emit_delays (insns) && ((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; } @@ -2597,6 +2520,15 @@ macro_build (place, counter, ep, name, fmt, va_alist) 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; @@ -2617,6 +2549,10 @@ macro_build (place, counter, ep, name, fmt, va_alist) 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; @@ -3113,63 +3049,65 @@ load_register (counter, reg, ep, dbl) 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. */ @@ -3201,38 +3139,38 @@ load_register (counter, reg, ep, dbl) /* 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; } @@ -3250,13 +3188,13 @@ load_register (counter, reg, ep, dbl) 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) { @@ -3309,7 +3247,7 @@ load_address (counter, reg, ep) addiu $reg,$reg, (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 { @@ -3999,7 +3937,7 @@ macro (ip) 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; } @@ -4020,7 +3958,7 @@ macro (ip) 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, @@ -4059,7 +3997,7 @@ macro (ip) 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; @@ -4106,7 +4044,7 @@ macro (ip) 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) @@ -4177,7 +4115,7 @@ macro (ip) /* 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; @@ -4276,9 +4214,13 @@ macro (ip) } 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,($gp) (BFD_RELOC_MIPS_GOT16) + or if tempreg is PIC_CALL_REG + lw $tempreg,($gp) (BFD_RELOC_MIPS_CALL16) For a local symbol, we want lw $tempreg,($gp) (BFD_RELOC_MIPS_GOT16) nop @@ -4305,9 +4247,11 @@ macro (ip) 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; @@ -4413,12 +4357,18 @@ macro (ip) 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, (BFD_RELOC_MIPS_GOT_HI16) addu $tempreg,$tempreg,$gp lw $tempreg,($tempreg) (BFD_RELOC_MIPS_GOT_LO16) + or if tempreg is PIC_CALL_REG + lui $tempreg, (BFD_RELOC_MIPS_CALL_HI16) + addu $tempreg,$tempreg,$gp + lw $tempreg,($tempreg) (BFD_RELOC_MIPS_CALL_LO16) For a local symbol, we want lw $tempreg,($gp) (BFD_RELOC_MIPS_GOT16) nop @@ -4457,8 +4407,13 @@ macro (ip) 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)) @@ -4466,8 +4421,7 @@ macro (ip) "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; @@ -5408,7 +5362,7 @@ macro (ip) 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); @@ -5433,7 +5387,7 @@ macro (ip) 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); @@ -5460,7 +5414,7 @@ macro (ip) 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); @@ -5499,7 +5453,7 @@ macro (ip) } /* Itbl support may require additional care here. */ coproc = 1; - if (mips_opts.isa != 1) + if (mips_opts.isa != ISA_MIPS1) { s = "ldc1"; goto ld; @@ -5516,7 +5470,7 @@ macro (ip) return; } - if (mips_opts.isa != 1) + if (mips_opts.isa != ISA_MIPS1) { s = "sdc1"; goto st; @@ -5611,7 +5565,7 @@ macro (ip) 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); @@ -5621,7 +5575,7 @@ macro (ip) 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); @@ -5667,7 +5621,7 @@ macro (ip) 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); @@ -5675,7 +5629,7 @@ macro (ip) 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); @@ -5720,7 +5674,7 @@ macro (ip) || ! 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); @@ -5730,7 +5684,7 @@ macro (ip) 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); @@ -5794,7 +5748,7 @@ macro (ip) || ! 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); @@ -5804,7 +5758,7 @@ macro (ip) 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); @@ -5838,7 +5792,7 @@ macro (ip) "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); @@ -5849,7 +5803,7 @@ macro (ip) 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); @@ -5881,12 +5835,12 @@ macro (ip) 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); @@ -5961,13 +5915,13 @@ macro (ip) 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; } @@ -6064,7 +6018,7 @@ macro2 (ip) 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); @@ -6097,7 +6051,7 @@ macro2 (ip) 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; @@ -6144,7 +6098,7 @@ macro2 (ip) 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)", @@ -6453,7 +6407,7 @@ macro2 (ip) 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 */ @@ -6750,7 +6704,7 @@ mips16_macro (ip) "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, @@ -6976,7 +6930,7 @@ validate_mips_insn (opc) 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; @@ -6984,6 +6938,7 @@ validate_mips_insn (opc) 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; @@ -7002,7 +6957,6 @@ validate_mips_insn (opc) 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; @@ -7015,6 +6969,8 @@ validate_mips_insn (opc) 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); @@ -7128,11 +7084,12 @@ mips_ip (str, ip) 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; @@ -7268,62 +7225,55 @@ mips_ip (str, ip) 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 */ @@ -7336,6 +7286,7 @@ mips_ip (str, ip) 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] == '$') { @@ -7411,7 +7362,7 @@ mips_ip (str, ip) } else goto notreg; - } + } else goto notreg; } @@ -7450,6 +7401,10 @@ mips_ip (str, ip) 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': @@ -7802,8 +7757,8 @@ mips_ip (str, ip) { 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)) @@ -7835,8 +7790,8 @@ mips_ip (str, ip) 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) @@ -7873,8 +7828,8 @@ mips_ip (str, ip) || offset_expr.X_add_number < -0x8000) && (mips_pic != EMBEDDED_PIC || offset_expr.X_op != O_subtract - || (S_GET_SEGMENT (offset_expr.X_op_symbol) - != now_seg))) + || (S_GET_SEGMENT (offset_expr.X_add_symbol) + != S_GET_SEGMENT (offset_expr.X_op_symbol)))) break; if (c == 'h' || c == 'H') @@ -7947,7 +7902,7 @@ mips_ip (str, ip) 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')) @@ -8648,7 +8603,8 @@ mips16_immed (file, line, type, val, warn, small, ext, insn, use_extend, 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")); @@ -8951,9 +8907,10 @@ struct option md_longopts[] = {"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) @@ -9024,154 +8981,47 @@ md_parse_option (c, arg) 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; @@ -9197,13 +9047,6 @@ md_parse_option (c, arg) 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; @@ -9231,6 +9074,7 @@ md_parse_option (c, arg) 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. */ @@ -9264,6 +9108,7 @@ md_parse_option (c, arg) case OPTION_XGOT: mips_big_got = 1; break; +#endif /* OBJ_ELF */ case 'G': if (! USE_GLOBAL_POINTER_OPT) @@ -9281,6 +9126,7 @@ md_parse_option (c, arg) 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: @@ -9294,7 +9140,9 @@ md_parse_option (c, arg) 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")); @@ -9302,6 +9150,7 @@ md_parse_option (c, arg) mips_64 = 1; } break; +#endif /* OBJ_ELF */ case OPTION_GP32: mips_gp32 = 1; @@ -9316,21 +9165,25 @@ md_parse_option (c, arg) 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; @@ -9385,7 +9238,7 @@ md_show_usage (stream) { int column, first; - fprintf(stream, _("\ + fprintf (stream, _("\ MIPS options:\n\ -membedded-pic generate embedded position independent code\n\ -EB generate big endian output\n\ @@ -9393,11 +9246,14 @@ MIPS options:\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; @@ -9417,9 +9273,9 @@ MIPS options:\n\ 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, _("\ @@ -9436,19 +9292,16 @@ MIPS options:\n\ 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\ @@ -9462,7 +9315,7 @@ mips_init_after_args () { /* 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 @@ -9631,7 +9484,6 @@ mips_frob_file () 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; @@ -10428,12 +10280,18 @@ s_mipsset (x) /* 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; @@ -11094,7 +10952,6 @@ mips16_extended_frag (fragp, sec, stretch) 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; @@ -11146,18 +11003,18 @@ md_estimate_size_before_relax (fragp, segtype) /* 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 @@ -11500,7 +11357,7 @@ md_convert_frag (abfd, asec, fragp) 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) { @@ -11684,11 +11541,11 @@ mips_elf_final_processing () /* 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; @@ -11702,51 +11559,52 @@ mips_elf_final_processing () #endif /* OBJ_ELF || OBJ_MAYBE_ELF */ -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 @@ -11893,21 +11751,21 @@ s_mips_end (x) 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); } @@ -11981,7 +11839,7 @@ s_mips_frame (ignore) 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 (); @@ -12079,3 +11937,202 @@ s_loc (x) 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; +}