X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gas%2Fconfig%2Ftc-mips.c;h=5c3da07c8b72d7be45932eee7c3c5b1481d3a9cd;hb=94f592af1baedbbe3957436c713fd58c02d55ef9;hp=847ee2c839443f1f571644216243d6ce967e024a;hpb=2e4acd247eb79f179e4c084a74ea1100f7cc34b7;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c index 847ee2c839..5c3da07c8b 100644 --- a/gas/config/tc-mips.c +++ b/gas/config/tc-mips.c @@ -113,6 +113,20 @@ extern int target_big_endian; ? ".rodata" \ : (abort (), "")) +/* The ABI to use. */ +enum mips_abi_level +{ + NO_ABI = 0, + O32_ABI, + O64_ABI, + N32_ABI, + N64_ABI, + EABI_ABI +}; + +/* MIPS ABI we are using for this output file. */ +static enum mips_abi_level file_mips_abi = NO_ABI; + /* This is the set of options which may be modified by the .set pseudo-op. We use a struct so that .set push and .set pop are more reliable. */ @@ -149,15 +163,29 @@ struct mips_set_options /* Non-zero if we should not autoextend mips16 instructions. Changed by `.set autoextend' and `.set noautoextend'. */ int noautoextend; + /* Restrict general purpose registers and floating point registers + to 32 bit. This is initially determined when -mgp32 or -mfp32 + is passed but can changed if the assembler code uses .set mipsN. */ + int gp32; + int fp32; + /* The ABI currently in use. This is changed by .set mipsN to loosen + restrictions and doesn't affect the whole file. */ + enum mips_abi_level abi; }; +/* True if -mgp32 was passed. */ +static int file_mips_gp32 = 0; + +/* True if -mfp32 was passed. */ +static int file_mips_fp32 = 0; + /* This is the struct we use to hold the current set of options. Note 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 = { - ISA_UNKNOWN, -1, 0, 0, 0, 0, 0, 0 + ISA_UNKNOWN, -1, 0, 0, 0, 0, 0, 0, 0, 0, NO_ABI }; /* These variables are filled in with the masks of registers used. @@ -179,19 +207,6 @@ static int mips_arch = CPU_UNKNOWN; are optimizing. */ static int mips_tune = CPU_UNKNOWN; -/* The ABI to use. */ -enum mips_abi_level -{ - NO_ABI = 0, - O32_ABI, - O64_ABI, - N32_ABI, - N64_ABI, - EABI_ABI -}; - -static enum mips_abi_level mips_abi = NO_ABI; - /* Whether we should mark the file EABI64 or EABI32. */ static int mips_eabi64 = 0; @@ -199,12 +214,6 @@ static int mips_eabi64 = 0; mips3 or greater, then mark the object file 32BITMODE. */ static int mips_32bitmode = 0; -/* True if -mgp32 was passed. */ -static int mips_gp32 = 0; - -/* True if -mfp32 was passed. */ -static int mips_fp32 = 0; - /* Some ISA's have delay slots for instructions which read or write from a coprocessor (eg. mips1-mips3); some don't (eg mips4). Return true if instructions marked INSN_LOAD_COPROC_DELAY, @@ -228,28 +237,29 @@ static int mips_fp32 = 0; ) #define HAVE_32BIT_GPRS \ - (mips_gp32 \ - || mips_abi == O32_ABI \ + (mips_opts.gp32 \ + || mips_opts.abi == O32_ABI \ || ! ISA_HAS_64BIT_REGS (mips_opts.isa)) #define HAVE_32BIT_FPRS \ - (mips_fp32 \ - || mips_abi == O32_ABI \ + (mips_opts.fp32 \ + || mips_opts.abi == O32_ABI \ || ! ISA_HAS_64BIT_REGS (mips_opts.isa)) #define HAVE_64BIT_GPRS (! HAVE_32BIT_GPRS) #define HAVE_64BIT_FPRS (! HAVE_32BIT_FPRS) -#define HAVE_NEWABI (mips_abi == N32_ABI || mips_abi == N64_ABI) +#define HAVE_NEWABI (mips_opts.abi == N32_ABI || mips_opts.abi == N64_ABI) -#define HAVE_64BIT_OBJECTS (mips_abi == N64_ABI) +#define HAVE_64BIT_OBJECTS (mips_opts.abi == N64_ABI) /* We can only have 64bit addresses if the object file format supports it. */ -#define HAVE_32BIT_ADDRESSES \ - (HAVE_32BIT_GPRS \ - || bfd_arch_bits_per_address (stdoutput) == 32 \ - || ! HAVE_64BIT_OBJECTS) +#define HAVE_32BIT_ADDRESSES \ + (HAVE_32BIT_GPRS \ + || ((bfd_arch_bits_per_address (stdoutput) == 32 \ + || ! HAVE_64BIT_OBJECTS) \ + && mips_pic != EMBEDDED_PIC)) #define HAVE_64BIT_ADDRESSES (! HAVE_32BIT_ADDRESSES) @@ -258,6 +268,7 @@ static int mips_fp32 = 0; require nops to be inserted. */ #define hilo_interlocks (mips_arch == CPU_R4010 \ + || mips_arch == CPU_SB1 \ ) /* Whether the processor uses hardware interlocks to protect reads @@ -270,6 +281,7 @@ static int mips_fp32 = 0; (co-processor) interlocks. */ /* Itbl support may require additional care here. */ #define cop_interlocks (mips_arch == CPU_R4300 \ + || mips_arch == CPU_SB1 \ ) /* Is this a mfhi or mflo instruction? */ @@ -685,7 +697,9 @@ static void mips16_immed PARAMS ((char *, unsigned int, int, offsetT, boolean, static int my_getSmallParser PARAMS ((char **, unsigned int *, int *)); static int my_getSmallExpression PARAMS ((expressionS *, char *)); static void my_getExpression PARAMS ((expressionS *, char *)); +#ifdef OBJ_ELF static int support_64bit_objects PARAMS((void)); +#endif static symbolS *get_symbol PARAMS ((void)); static void mips_align PARAMS ((int to, int fill, symbolS *label)); static void s_align PARAMS ((int)); @@ -1120,7 +1134,7 @@ md_begin () to change the ISA with directives. This isn't really the best, but then neither is basing the abi on the isa. */ if (ISA_HAS_64BIT_REGS (mips_opts.isa) - && mips_abi == EABI_ABI) + && mips_opts.abi == EABI_ABI) mips_eabi64 = 1; /* If they asked for mips1 or mips2 and a cpu that is @@ -1134,6 +1148,9 @@ md_begin () as_warn (_("Could not set architecture and machine")); file_mips_isa = mips_opts.isa; + file_mips_abi = mips_opts.abi; + mips_opts.gp32 = file_mips_gp32; + mips_opts.fp32 = file_mips_fp32; op_hash = hash_new (); @@ -1372,12 +1389,11 @@ md_assemble (str) else { if (imm_expr.X_op != O_absent) - append_insn ((char *) NULL, &insn, &imm_expr, imm_reloc, - imm_unmatched_hi); + append_insn (NULL, &insn, &imm_expr, imm_reloc, imm_unmatched_hi); else if (offset_expr.X_op != O_absent) - append_insn ((char *) NULL, &insn, &offset_expr, offset_reloc, false); + append_insn (NULL, &insn, &offset_expr, offset_reloc, false); else - append_insn ((char *) NULL, &insn, NULL, unused_reloc, false); + append_insn (NULL, &insn, NULL, unused_reloc, false); } } @@ -1891,8 +1907,7 @@ append_insn (place, ip, address_expr, reloc_type, unmatched_hi) & INSN_UNCOND_BRANCH_DELAY), (*prev_insn_reloc_type == BFD_RELOC_MIPS16_JMP)), - make_expr_symbol (address_expr), (offsetT) 0, - (char *) NULL); + make_expr_symbol (address_expr), 0, NULL); } else if (place != NULL) f = place; @@ -3041,9 +3056,9 @@ mips16_macro_build (place, counter, ep, name, fmt, args) *r = BFD_RELOC_UNUSED + c; else { - mips16_immed ((char *) NULL, 0, c, ep->X_add_number, false, - false, false, &insn.insn_opcode, - &insn.use_extend, &insn.extend); + mips16_immed (NULL, 0, c, ep->X_add_number, false, false, + false, &insn.insn_opcode, &insn.use_extend, + &insn.extend); ep = NULL; *r = BFD_RELOC_UNUSED; } @@ -3151,7 +3166,7 @@ set_at (counter, reg, unsignedp) else { load_register (counter, AT, &imm_expr, 0); - macro_build ((char *) NULL, counter, NULL, + macro_build ((char *) NULL, counter, (expressionS *) NULL, unsignedp ? "sltu" : "slt", "d,v,t", AT, reg, AT); } @@ -3399,7 +3414,7 @@ load_register (counter, reg, ep, dbl) macro_build ((char *) NULL, counter, &tmp, "ori", "t,r,i", reg, 0, (int) BFD_RELOC_LO16); - macro_build ((char *) NULL, counter, NULL, + macro_build ((char *) NULL, counter, (expressionS *) NULL, (shift >= 32) ? "dsll32" : "dsll", "d,w,<", reg, reg, (shift >= 32) ? shift - 32 : shift); @@ -3454,12 +3469,12 @@ load_register (counter, reg, ep, dbl) if (bit != 0) { bit += shift; - macro_build ((char *) NULL, counter, NULL, + macro_build ((char *) NULL, counter, (expressionS *) NULL, (bit >= 32) ? "dsll32" : "dsll", "d,w,<", reg, reg, (bit >= 32) ? bit - 32 : bit); } - macro_build ((char *) NULL, counter, NULL, + macro_build ((char *) NULL, counter, (expressionS *) NULL, (shift >= 32) ? "dsrl32" : "dsrl", "d,w,<", reg, reg, (shift >= 32) ? shift - 32 : shift); @@ -3478,8 +3493,8 @@ load_register (counter, reg, ep, dbl) { if (freg != 0) { - macro_build ((char *) NULL, counter, NULL, "dsll32", "d,w,<", reg, - freg, 0); + macro_build ((char *) NULL, counter, (expressionS *) NULL, + "dsll32", "d,w,<", reg, freg, 0); freg = reg; } } @@ -3548,7 +3563,7 @@ load_address (counter, reg, ep, dbl, used_at) lui $reg, (BFD_RELOC_HI16_S) addiu $reg,$reg, (BFD_RELOC_LO16) If we have an addend, we always use the latter form. - + With 64bit address space and a usable $at we want lui $reg, (BFD_RELOC_MIPS_HIGHEST) lui $at, (BFD_RELOC_HI16_S) @@ -3556,7 +3571,7 @@ load_address (counter, reg, ep, dbl, used_at) daddiu $at, (BFD_RELOC_LO16) dsll32 $reg,0 dadd $reg,$reg,$at - + If $at is already in use, we use an path which is suboptimal on superscalar processors. lui $reg, (BFD_RELOC_MIPS_HIGHEST) @@ -3583,10 +3598,10 @@ load_address (counter, reg, ep, dbl, used_at) reg, reg, (int) BFD_RELOC_MIPS_HIGHER); macro_build (p, counter, ep, "daddiu", "t,r,j", AT, AT, (int) BFD_RELOC_LO16); - macro_build (p, counter, NULL, "dsll32", "d,w,<", - reg, reg, 0); - macro_build (p, counter, NULL, "dadd", "d,v,t", - reg, reg, AT); + macro_build (p, counter, (expressionS *) NULL, "dsll32", + "d,w,<", reg, reg, 0); + macro_build (p, counter, (expressionS *) NULL, "dadd", + "d,v,t", reg, reg, AT); *used_at = 1; } else @@ -3595,12 +3610,12 @@ load_address (counter, reg, ep, dbl, used_at) reg, (int) BFD_RELOC_MIPS_HIGHEST); macro_build (p, counter, ep, "daddiu", "t,r,j", reg, reg, (int) BFD_RELOC_MIPS_HIGHER); - macro_build (p, counter, NULL, "dsll", "d,w,<", - reg, reg, 16); + macro_build (p, counter, (expressionS *) NULL, "dsll", + "d,w,<", reg, reg, 16); macro_build (p, counter, ep, "daddiu", "t,r,j", reg, reg, (int) BFD_RELOC_HI16_S); - macro_build (p, counter, NULL, "dsll", "d,w,<", - reg, reg, 16); + macro_build (p, counter, (expressionS *) NULL, "dsll", + "d,w,<", reg, reg, 16); macro_build (p, counter, ep, "daddiu", "t,r,j", reg, reg, (int) BFD_RELOC_LO16); } @@ -3819,10 +3834,11 @@ macro (ip) expr1.X_add_number = 8; macro_build ((char *) NULL, &icnt, &expr1, "bgez", "s,p", sreg); if (dreg == sreg) - macro_build ((char *) NULL, &icnt, NULL, "nop", "", 0); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "nop", "", + 0); else move_register (&icnt, dreg, sreg); - macro_build ((char *) NULL, &icnt, NULL, + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, dbl ? "dsub" : "sub", "d,v,t", dreg, 0, sreg); --mips_opts.noreorder; @@ -3855,7 +3871,8 @@ macro (ip) return; } load_register (&icnt, AT, &imm_expr, dbl); - macro_build ((char *) NULL, &icnt, NULL, s2, "d,v,t", treg, sreg, AT); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, s2, "d,v,t", + treg, sreg, AT); break; case M_AND_I: @@ -3885,14 +3902,15 @@ macro (ip) { macro_build ((char *) NULL, &icnt, &imm_expr, "ori", "t,r,i", treg, sreg, (int) BFD_RELOC_LO16); - macro_build ((char *) NULL, &icnt, NULL, "nor", "d,v,t", - treg, treg, 0); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "nor", + "d,v,t", treg, treg, 0); } return; } load_register (&icnt, AT, &imm_expr, HAVE_64BIT_GPRS); - macro_build ((char *) NULL, &icnt, NULL, s2, "d,v,t", treg, sreg, AT); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, s2, "d,v,t", + treg, sreg, AT); break; case M_BEQ_I: @@ -3925,18 +3943,17 @@ macro (ip) if (treg == 0) { macro_build ((char *) NULL, &icnt, &offset_expr, - likely ? "bgezl" : "bgez", - "s,p", sreg); + likely ? "bgezl" : "bgez", "s,p", sreg); return; } if (sreg == 0) { macro_build ((char *) NULL, &icnt, &offset_expr, - likely ? "blezl" : "blez", - "s,p", treg); + likely ? "blezl" : "blez", "s,p", treg); return; } - macro_build ((char *) NULL, &icnt, NULL, "slt", "d,v,t", AT, sreg, treg); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "slt", "d,v,t", + AT, sreg, treg); macro_build ((char *) NULL, &icnt, &offset_expr, likely ? "beql" : "beq", "s,t,p", AT, 0); break; @@ -3964,7 +3981,8 @@ macro (ip) if (warn_nops) as_warn (_("Branch %s is always false (nop)"), ip->insn_mo->name); - macro_build ((char *) NULL, &icnt, NULL, "nop", "", 0); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "nop", + "", 0); } else { @@ -4031,8 +4049,8 @@ macro (ip) likely ? "beql" : "beq", "s,t,p", 0, treg); return; } - macro_build ((char *) NULL, &icnt, NULL, "sltu", "d,v,t", AT, sreg, - treg); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "sltu", + "d,v,t", AT, sreg, treg); macro_build ((char *) NULL, &icnt, &offset_expr, likely ? "beql" : "beq", "s,t,p", AT, 0); break; @@ -4081,7 +4099,8 @@ macro (ip) likely ? "bltzl" : "bltz", "s,p", treg); return; } - macro_build ((char *) NULL, &icnt, NULL, "slt", "d,v,t", AT, treg, sreg); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "slt", "d,v,t", + AT, treg, sreg); macro_build ((char *) NULL, &icnt, &offset_expr, likely ? "bnel" : "bne", "s,t,p", AT, 0); break; @@ -4097,8 +4116,8 @@ macro (ip) } if (sreg == 0) goto do_false; - macro_build ((char *) NULL, &icnt, NULL, "sltu", "d,v,t", AT, treg, - sreg); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "sltu", + "d,v,t", AT, treg, sreg); macro_build ((char *) NULL, &icnt, &offset_expr, likely ? "bnel" : "bne", "s,t,p", AT, 0); break; @@ -4118,7 +4137,8 @@ macro (ip) likely ? "bgezl" : "bgez", "s,p", treg); return; } - macro_build ((char *) NULL, &icnt, NULL, "slt", "d,v,t", AT, treg, sreg); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "slt", "d,v,t", + AT, treg, sreg); macro_build ((char *) NULL, &icnt, &offset_expr, likely ? "beql" : "beq", "s,t,p", AT, 0); break; @@ -4174,8 +4194,8 @@ macro (ip) } if (sreg == 0) goto do_true; - macro_build ((char *) NULL, &icnt, NULL, "sltu", "d,v,t", AT, treg, - sreg); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "sltu", + "d,v,t", AT, treg, sreg); macro_build ((char *) NULL, &icnt, &offset_expr, likely ? "beql" : "beq", "s,t,p", AT, 0); break; @@ -4225,7 +4245,8 @@ macro (ip) likely ? "bgtzl" : "bgtz", "s,p", treg); return; } - macro_build ((char *) NULL, &icnt, NULL, "slt", "d,v,t", AT, sreg, treg); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "slt", "d,v,t", + AT, sreg, treg); macro_build ((char *) NULL, &icnt, &offset_expr, likely ? "bnel" : "bne", "s,t,p", AT, 0); break; @@ -4241,7 +4262,8 @@ macro (ip) likely ? "bnel" : "bne", "s,t,p", 0, treg); return; } - macro_build ((char *) NULL, &icnt, NULL, "sltu", "d,v,t", AT, sreg, + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "sltu", + "d,v,t", AT, sreg, treg); macro_build ((char *) NULL, &icnt, &offset_expr, likely ? "bnel" : "bne", "s,t,p", AT, 0); @@ -4261,9 +4283,11 @@ macro (ip) { as_warn (_("Divide by zero.")); if (mips_trap) - macro_build ((char *) NULL, &icnt, NULL, "teq", "s,t", 0, 0); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "teq", + "s,t", 0, 0); else - macro_build ((char *) NULL, &icnt, NULL, "break", "c", 7); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "break", + "c", 7); return; } @@ -4272,17 +4296,19 @@ macro (ip) mips_any_noreorder = 1; if (mips_trap) { - macro_build ((char *) NULL, &icnt, NULL, "teq", "s,t", treg, 0); - macro_build ((char *) NULL, &icnt, NULL, + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "teq", + "s,t", treg, 0); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, dbl ? "ddiv" : "div", "z,s,t", sreg, treg); } else { expr1.X_add_number = 8; macro_build ((char *) NULL, &icnt, &expr1, "bne", "s,t,p", treg, 0); - macro_build ((char *) NULL, &icnt, NULL, + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, dbl ? "ddiv" : "div", "z,s,t", sreg, treg); - macro_build ((char *) NULL, &icnt, NULL, "break", "c", 7); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "break", + "c", 7); } expr1.X_add_number = -1; macro_build ((char *) NULL, &icnt, &expr1, @@ -4295,8 +4321,8 @@ macro (ip) expr1.X_add_number = 1; macro_build ((char *) NULL, &icnt, &expr1, "daddiu", "t,r,j", AT, 0, (int) BFD_RELOC_LO16); - macro_build ((char *) NULL, &icnt, NULL, "dsll32", "d,w,<", AT, AT, - 31); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "dsll32", + "d,w,<", AT, AT, 31); } else { @@ -4306,7 +4332,8 @@ macro (ip) } if (mips_trap) { - macro_build ((char *) NULL, &icnt, NULL, "teq", "s,t", sreg, AT); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "teq", + "s,t", sreg, AT); /* We want to close the noreorder block as soon as possible, so that later insns are available for delay slot filling. */ --mips_opts.noreorder; @@ -4315,15 +4342,17 @@ macro (ip) { expr1.X_add_number = 8; macro_build ((char *) NULL, &icnt, &expr1, "bne", "s,t,p", sreg, AT); - macro_build ((char *) NULL, &icnt, NULL, "nop", "", 0); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "nop", "", + 0); /* 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", 6); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "break", + "c", 6); } - macro_build ((char *) NULL, &icnt, NULL, s, "d", dreg); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, s, "d", dreg); break; case M_DIV_3I: @@ -4366,9 +4395,11 @@ macro (ip) { as_warn (_("Divide by zero.")); if (mips_trap) - macro_build ((char *) NULL, &icnt, NULL, "teq", "s,t", 0, 0); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "teq", + "s,t", 0, 0); else - macro_build ((char *) NULL, &icnt, NULL, "break", "c", 7); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "break", + "c", 7); return; } if (imm_expr.X_op == O_constant && imm_expr.X_add_number == 1) @@ -4385,8 +4416,8 @@ macro (ip) { if (strcmp (s2, "mflo") == 0) { - macro_build ((char *) NULL, &icnt, NULL, dbl ? "dneg" : "neg", - "d,w", dreg, sreg); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, + dbl ? "dneg" : "neg", "d,w", dreg, sreg); } else move_register (&icnt, dreg, 0); @@ -4394,8 +4425,9 @@ macro (ip) } load_register (&icnt, AT, &imm_expr, dbl); - macro_build ((char *) NULL, &icnt, NULL, s, "z,s,t", sreg, AT); - macro_build ((char *) NULL, &icnt, NULL, s2, "d", dreg); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, s, "z,s,t", + sreg, AT); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, s2, "d", dreg); break; case M_DIVU_3: @@ -4419,8 +4451,10 @@ macro (ip) mips_any_noreorder = 1; if (mips_trap) { - macro_build ((char *) NULL, &icnt, NULL, "teq", "s,t", treg, 0); - macro_build ((char *) NULL, &icnt, NULL, s, "z,s,t", sreg, treg); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "teq", + "s,t", treg, 0); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, s, "z,s,t", + sreg, treg); /* We want to close the noreorder block as soon as possible, so that later insns are available for delay slot filling. */ --mips_opts.noreorder; @@ -4429,14 +4463,16 @@ macro (ip) { expr1.X_add_number = 8; macro_build ((char *) NULL, &icnt, &expr1, "bne", "s,t,p", treg, 0); - macro_build ((char *) NULL, &icnt, NULL, s, "z,s,t", sreg, treg); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, s, "z,s,t", + sreg, treg); /* 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, (expressionS *) NULL, "break", + "c", 7); } - macro_build ((char *) NULL, &icnt, NULL, s2, "d", dreg); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, s2, "d", dreg); return; case M_DLA_AB: @@ -4445,9 +4481,21 @@ macro (ip) /* Load the address of a symbol into a register. If breg is not zero, we then add a base register to it. */ + if (treg == breg) + { + tempreg = AT; + used_at = 1; + } + else + { + tempreg = treg; + used_at = 0; + } + /* When generating embedded PIC code, we permit expressions of the form - la $4,foo-bar + la $treg,foo-bar + la $treg,foo-bar($breg) where bar is an address in the current section. These are used when getting the addresses of functions. We don't permit X_add_number to be non-zero, because if the symbol is @@ -4462,16 +4510,30 @@ macro (ip) (symbol_get_value_expression (offset_expr.X_op_symbol) ->X_add_symbol) == now_seg))) - && breg == 0 && (offset_expr.X_add_number == 0 || OUTPUT_FLAVOR == bfd_target_elf_flavour)) { - macro_build ((char *) NULL, &icnt, &offset_expr, "lui", "t,u", - treg, (int) BFD_RELOC_PCREL_HI16_S); + if (breg == 0) + { + tempreg = treg; + used_at = 0; + macro_build ((char *) NULL, &icnt, &offset_expr, "lui", "t,u", + tempreg, (int) BFD_RELOC_PCREL_HI16_S); + } + else + { + macro_build ((char *) NULL, &icnt, &offset_expr, "lui", "t,u", + tempreg, (int) BFD_RELOC_PCREL_HI16_S); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, + HAVE_32BIT_ADDRESSES ? "addu" : "daddu", + "d,v,t", tempreg, tempreg, breg); + } macro_build ((char *) NULL, &icnt, &offset_expr, HAVE_32BIT_ADDRESSES ? "addiu" : "daddiu", - "t,r,j", treg, treg, (int) BFD_RELOC_PCREL_LO16); - return; + "t,r,j", treg, tempreg, (int) BFD_RELOC_PCREL_LO16); + if (! used_at) + return; + break; } if (offset_expr.X_op != O_symbol @@ -4481,17 +4543,6 @@ macro (ip) offset_expr.X_op = O_constant; } - if (treg == breg) - { - tempreg = AT; - used_at = 1; - } - else - { - tempreg = treg; - used_at = 0; - } - if (offset_expr.X_op == O_constant) load_register (&icnt, tempreg, &offset_expr, dbl); else if (mips_pic == NO_PIC) @@ -4503,7 +4554,7 @@ macro (ip) addiu $tempreg,$tempreg, (BFD_RELOC_LO16) If we have a constant, we need two instructions anyhow, so we may as well always use the latter form. - + With 64bit address space and a usable $at we want lui $tempreg, (BFD_RELOC_MIPS_HIGHEST) lui $at, (BFD_RELOC_HI16_S) @@ -4511,7 +4562,7 @@ macro (ip) daddiu $at, (BFD_RELOC_LO16) dsll32 $tempreg,0 dadd $tempreg,$tempreg,$at - + If $at is already in use, we use an path which is suboptimal on superscalar processors. lui $tempreg, (BFD_RELOC_MIPS_HIGHEST) @@ -4537,9 +4588,9 @@ macro (ip) tempreg, tempreg, (int) BFD_RELOC_MIPS_HIGHER); macro_build (p, &icnt, &offset_expr, "daddiu", "t,r,j", AT, AT, (int) BFD_RELOC_LO16); - macro_build (p, &icnt, NULL, "dsll32", "d,w,<", - tempreg, tempreg, 0); - macro_build (p, &icnt, NULL, "dadd", "d,v,t", + macro_build (p, &icnt, (expressionS *) NULL, "dsll32", + "d,w,<", tempreg, tempreg, 0); + macro_build (p, &icnt, (expressionS *) NULL, "dadd", "d,v,t", tempreg, tempreg, AT); used_at = 1; } @@ -4549,11 +4600,11 @@ macro (ip) tempreg, (int) BFD_RELOC_MIPS_HIGHEST); macro_build (p, &icnt, &offset_expr, "daddiu", "t,r,j", tempreg, tempreg, (int) BFD_RELOC_MIPS_HIGHER); - macro_build (p, &icnt, NULL, "dsll", "d,w,<", + macro_build (p, &icnt, (expressionS *) NULL, "dsll", "d,w,<", tempreg, tempreg, 16); macro_build (p, &icnt, &offset_expr, "daddiu", "t,r,j", tempreg, tempreg, (int) BFD_RELOC_HI16_S); - macro_build (p, &icnt, NULL, "dsll", "d,w,<", + macro_build (p, &icnt, (expressionS *) NULL, "dsll", "d,w,<", tempreg, tempreg, 16); macro_build (p, &icnt, &offset_expr, "daddiu", "t,r,j", tempreg, tempreg, (int) BFD_RELOC_LO16); @@ -4619,8 +4670,7 @@ macro (ip) 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", + macro_build ((char *) NULL, &icnt, &offset_expr, dbl ? "ld" : "lw", "t,o(b)", tempreg, lw_reloc_type, GP); if (expr1.X_add_number == 0) { @@ -4642,8 +4692,7 @@ macro (ip) (breg == 0 ? mips_opts.warn_about_macros : 0)), - offset_expr.X_add_symbol, (offsetT) 0, - (char *) NULL); + offset_expr.X_add_symbol, 0, NULL); if (breg == 0) { macro_build (p, &icnt, (expressionS *) NULL, "nop", ""); @@ -4664,10 +4713,9 @@ macro (ip) macro_build ((char *) NULL, &icnt, &expr1, HAVE_32BIT_ADDRESSES ? "addiu" : "daddiu", "t,r,j", tempreg, tempreg, (int) BFD_RELOC_LO16); - (void) frag_var (rs_machine_dependent, 0, 0, - RELAX_ENCODE (0, 0, -12, -4, 0, 0), - offset_expr.X_add_symbol, (offsetT) 0, - (char *) NULL); + frag_var (rs_machine_dependent, 0, 0, + RELAX_ENCODE (0, 0, -12, -4, 0, 0), + offset_expr.X_add_symbol, 0, NULL); } else { @@ -4698,7 +4746,7 @@ macro (ip) inserting an unnecessary nop after the lw. */ hold_mips_optimize = mips_optimize; mips_optimize = 2; - macro_build_lui ((char *) NULL, &icnt, &expr1, AT); + macro_build_lui (NULL, &icnt, &expr1, AT); mips_optimize = hold_mips_optimize; macro_build ((char *) NULL, &icnt, &expr1, @@ -4707,10 +4755,9 @@ macro (ip) macro_build ((char *) NULL, &icnt, (expressionS *) NULL, HAVE_32BIT_ADDRESSES ? "addu" : "daddu", "d,v,t", tempreg, tempreg, AT); - (void) frag_var (rs_machine_dependent, 0, 0, - RELAX_ENCODE (0, 0, -16 + off1, -8, 0, 0), - offset_expr.X_add_symbol, (offsetT) 0, - (char *) NULL); + frag_var (rs_machine_dependent, 0, 0, + RELAX_ENCODE (0, 0, -16 + off1, -8, 0, 0), + offset_expr.X_add_symbol, 0, NULL); used_at = 1; } } @@ -4802,8 +4849,7 @@ macro (ip) (breg == 0 ? mips_opts.warn_about_macros : 0)), - offset_expr.X_add_symbol, (offsetT) 0, - (char *) NULL); + offset_expr.X_add_symbol, 0, NULL); } else if (expr1.X_add_number >= -0x8000 && expr1.X_add_number < 0x8000) @@ -4819,8 +4865,7 @@ macro (ip) (breg == 0 ? mips_opts.warn_about_macros : 0)), - offset_expr.X_add_symbol, (offsetT) 0, - (char *) NULL); + offset_expr.X_add_symbol, 0, NULL); } else { @@ -4854,7 +4899,7 @@ macro (ip) inserting an unnecessary nop after the lw. */ hold_mips_optimize = mips_optimize; mips_optimize = 2; - macro_build_lui ((char *) NULL, &icnt, &expr1, AT); + macro_build_lui (NULL, &icnt, &expr1, AT); mips_optimize = hold_mips_optimize; macro_build ((char *) NULL, &icnt, &expr1, @@ -4870,8 +4915,7 @@ macro (ip) (breg == 0 ? mips_opts.warn_about_macros : 0)), - offset_expr.X_add_symbol, (offsetT) 0, - (char *) NULL); + offset_expr.X_add_symbol, 0, NULL); used_at = 1; } @@ -5039,8 +5083,7 @@ macro (ip) "nop", ""); p = frag_var (rs_machine_dependent, 4, 0, RELAX_ENCODE (0, 4, -8, 0, 0, 0), - offset_expr.X_add_symbol, (offsetT) 0, - (char *) NULL); + offset_expr.X_add_symbol, 0, NULL); } else { @@ -5064,8 +5107,7 @@ macro (ip) p = frag_var (rs_machine_dependent, 12 + gpdel, 0, RELAX_ENCODE (16, 12 + gpdel, gpdel, 8 + gpdel, 0, 0), - offset_expr.X_add_symbol, (offsetT) 0, - (char *) NULL); + offset_expr.X_add_symbol, 0, NULL); if (gpdel > 0) { macro_build (p, &icnt, (expressionS *) NULL, "nop", ""); @@ -5287,6 +5329,46 @@ macro (ip) else fmt = "t,o(b)"; + /* For embedded PIC, we allow loads where the offset is calculated + by subtracting a symbol in the current segment from an unknown + symbol, relative to a base register, e.g.: + $treg, -($breg) + This is used by the compiler for switch statements. */ + if (mips_pic == EMBEDDED_PIC + && offset_expr.X_op == O_subtract + && (symbol_constant_p (offset_expr.X_op_symbol) + ? S_GET_SEGMENT (offset_expr.X_op_symbol) == now_seg + : (symbol_equated_p (offset_expr.X_op_symbol) + && (S_GET_SEGMENT + (symbol_get_value_expression (offset_expr.X_op_symbol) + ->X_add_symbol) + == now_seg))) + && breg != 0 + && (offset_expr.X_add_number == 0 + || OUTPUT_FLAVOR == bfd_target_elf_flavour)) + { + /* For this case, we output the instructions: + lui $tempreg, (BFD_RELOC_PCREL_HI16_S) + addiu $tempreg,$tempreg,$breg + $treg,($tempreg) (BFD_RELOC_PCREL_LO16) + If the relocation would fit entirely in 16 bits, it would be + nice to emit: + $treg,($breg) (BFD_RELOC_PCREL_LO16) + instead, but that seems quite difficult. */ + macro_build ((char *) NULL, &icnt, &offset_expr, "lui", "t,u", + tempreg, (int) BFD_RELOC_PCREL_HI16_S); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, + ((bfd_arch_bits_per_address (stdoutput) == 32 + || ! ISA_HAS_64BIT_REGS (mips_opts.isa)) + ? "addu" : "daddu"), + "d,v,t", tempreg, tempreg, breg); + macro_build ((char *) NULL, &icnt, &offset_expr, s, fmt, treg, + (int) BFD_RELOC_PCREL_LO16, tempreg); + if (! used_at) + return; + break; + } + if (offset_expr.X_op != O_constant && offset_expr.X_op != O_symbol) { @@ -5317,7 +5399,7 @@ macro (ip) addu $tempreg,$tempreg,$breg $treg,($tempreg) (BFD_RELOC_LO16) With a constant we always use the latter case. - + With 64bit address space and no base register and $at usable, we want lui $tempreg, (BFD_RELOC_MIPS_HIGHEST) @@ -5368,12 +5450,12 @@ macro (ip) macro_build (p, &icnt, &offset_expr, "daddiu", "t,r,j", tempreg, tempreg, (int) BFD_RELOC_MIPS_HIGHER); if (breg != 0) - macro_build (p, &icnt, NULL, "daddu", "d,v,t", - AT, AT, breg); - macro_build (p, &icnt, NULL, "dsll32", "d,w,<", - tempreg, tempreg, 0); - macro_build (p, &icnt, NULL, "daddu", "d,v,t", - tempreg, tempreg, AT); + macro_build (p, &icnt, (expressionS *) NULL, "daddu", + "d,v,t", AT, AT, breg); + macro_build (p, &icnt, (expressionS *) NULL, "dsll32", + "d,w,<", tempreg, tempreg, 0); + macro_build (p, &icnt, (expressionS *) NULL, "daddu", + "d,v,t", tempreg, tempreg, AT); macro_build (p, &icnt, &offset_expr, s, fmt, treg, (int) BFD_RELOC_LO16, tempreg); used_at = 1; @@ -5384,22 +5466,22 @@ macro (ip) tempreg, (int) BFD_RELOC_MIPS_HIGHEST); macro_build (p, &icnt, &offset_expr, "daddiu", "t,r,j", tempreg, tempreg, (int) BFD_RELOC_MIPS_HIGHER); - macro_build (p, &icnt, NULL, "dsll", "d,w,<", - tempreg, tempreg, 16); + macro_build (p, &icnt, (expressionS *) NULL, "dsll", + "d,w,<", tempreg, tempreg, 16); macro_build (p, &icnt, &offset_expr, "daddiu", "t,r,j", tempreg, tempreg, (int) BFD_RELOC_HI16_S); - macro_build (p, &icnt, NULL, "dsll", "d,w,<", - tempreg, tempreg, 16); + macro_build (p, &icnt, (expressionS *) NULL, "dsll", + "d,w,<", tempreg, tempreg, 16); if (breg != 0) - macro_build (p, &icnt, NULL, "daddu", "d,v,t", - tempreg, tempreg, breg); + macro_build (p, &icnt, (expressionS *) NULL, "daddu", + "d,v,t", tempreg, tempreg, breg); macro_build (p, &icnt, &offset_expr, s, fmt, treg, (int) BFD_RELOC_LO16, tempreg); } return; } - + if (breg == 0) { if ((valueT) offset_expr.X_add_number > MAX_GPREL_OFFSET @@ -5485,8 +5567,7 @@ macro (ip) macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "nop", ""); p = frag_var (rs_machine_dependent, 4, 0, RELAX_ENCODE (0, 4, -8, 0, 0, 0), - offset_expr.X_add_symbol, (offsetT) 0, - (char *) NULL); + offset_expr.X_add_symbol, 0, NULL); macro_build (p, &icnt, &offset_expr, HAVE_32BIT_ADDRESSES ? "addiu" : "daddiu", "t,r,j", tempreg, tempreg, (int) BFD_RELOC_LO16); @@ -5539,7 +5620,7 @@ macro (ip) tempreg); p = frag_var (rs_machine_dependent, 12 + gpdel, 0, RELAX_ENCODE (12, 12 + gpdel, gpdel, 8 + gpdel, 0, 0), - offset_expr.X_add_symbol, (offsetT) 0, (char *) NULL); + offset_expr.X_add_symbol, 0, NULL); if (gpdel > 0) { macro_build (p, &icnt, (expressionS *) NULL, "nop", ""); @@ -5891,6 +5972,11 @@ macro (ip) fmt = "t,o(b)"; ldd_std: + /* We do _not_ bother to allow embedded PIC (symbol-local_symbol) + loads for the case of doing a pair of loads to simulate an 'ld'. + This is not currently done by the compiler, and assembly coders + writing embedded-pic code can cope. */ + if (offset_expr.X_op != O_symbol && offset_expr.X_op != O_constant) { @@ -6071,8 +6157,7 @@ macro (ip) (void) frag_var (rs_machine_dependent, 0, 0, RELAX_ENCODE (0, 0, -16 - off, -8, 1, 0), - offset_expr.X_add_symbol, (offsetT) 0, - (char *) NULL); + offset_expr.X_add_symbol, 0, NULL); } else if (mips_pic == SVR4_PIC) { @@ -6141,8 +6226,7 @@ macro (ip) p = frag_var (rs_machine_dependent, 16 + gpdel + off, 0, RELAX_ENCODE (24 + off, 16 + gpdel + off, gpdel, 8 + gpdel + off, 1, 0), - offset_expr.X_add_symbol, (offsetT) 0, - (char *) NULL); + offset_expr.X_add_symbol, 0, NULL); if (gpdel > 0) { macro_build (p, &icnt, (expressionS *) NULL, "nop", ""); @@ -6339,10 +6423,10 @@ macro2 (ip) case M_DMUL: dbl = 1; case M_MUL: - macro_build ((char *) NULL, &icnt, NULL, - dbl ? "dmultu" : "multu", - "s,t", sreg, treg); - macro_build ((char *) NULL, &icnt, NULL, "mflo", "d", dreg); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, + dbl ? "dmultu" : "multu", "s,t", sreg, treg); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "mflo", "d", + dreg); return; case M_DMUL_I: @@ -6352,9 +6436,10 @@ macro2 (ip) not trying to be that fancy. GCC should do this for us anyway. */ load_register (&icnt, AT, &imm_expr, dbl); - macro_build ((char *) NULL, &icnt, NULL, + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, dbl ? "dmult" : "mult", "s,t", sreg, AT); - macro_build ((char *) NULL, &icnt, NULL, "mflo", "d", dreg); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "mflo", "d", + dreg); break; case M_DMULO_I: @@ -6372,23 +6457,29 @@ macro2 (ip) mips_any_noreorder = 1; if (imm) load_register (&icnt, AT, &imm_expr, dbl); - macro_build ((char *) NULL, &icnt, NULL, + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, dbl ? "dmult" : "mult", "s,t", sreg, imm ? AT : treg); - macro_build ((char *) NULL, &icnt, NULL, "mflo", "d", dreg); - macro_build ((char *) NULL, &icnt, NULL, + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "mflo", "d", + dreg); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, dbl ? "dsra32" : "sra", "d,w,<", dreg, dreg, 31); - macro_build ((char *) NULL, &icnt, NULL, "mfhi", "d", AT); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "mfhi", "d", + AT); if (mips_trap) - macro_build ((char *) NULL, &icnt, NULL, "tne", "s,t", dreg, AT); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "tne", "s,t", + dreg, AT); else { 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, &expr1, "beq", "s,t,p", dreg, + AT); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "nop", "", + 0); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "break", + "c", 6); } --mips_opts.noreorder; - macro_build ((char *) NULL, &icnt, NULL, "mflo", "d", dreg); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "mflo", "d", dreg); break; case M_DMULOU_I: @@ -6406,57 +6497,70 @@ macro2 (ip) mips_any_noreorder = 1; if (imm) load_register (&icnt, AT, &imm_expr, dbl); - macro_build ((char *) NULL, &icnt, NULL, + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, dbl ? "dmultu" : "multu", "s,t", sreg, imm ? AT : treg); - macro_build ((char *) NULL, &icnt, NULL, "mfhi", "d", AT); - macro_build ((char *) NULL, &icnt, NULL, "mflo", "d", dreg); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "mfhi", "d", + AT); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "mflo", "d", + dreg); if (mips_trap) - macro_build ((char *) NULL, &icnt, NULL, "tne", "s,t", AT, 0); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "tne", "s,t", + AT, 0); else { 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, (expressionS *) NULL, "nop", "", + 0); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "break", + "c", 6); } --mips_opts.noreorder; break; case M_ROL: - macro_build ((char *) NULL, &icnt, NULL, "subu", "d,v,t", AT, 0, treg); - macro_build ((char *) NULL, &icnt, NULL, "srlv", "d,t,s", AT, sreg, AT); - macro_build ((char *) NULL, &icnt, NULL, "sllv", "d,t,s", dreg, sreg, - treg); - macro_build ((char *) NULL, &icnt, NULL, "or", "d,v,t", dreg, dreg, AT); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "subu", + "d,v,t", AT, 0, treg); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "srlv", + "d,t,s", AT, sreg, AT); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "sllv", + "d,t,s", dreg, sreg, treg); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "or", + "d,v,t", dreg, dreg, AT); break; case M_ROL_I: if (imm_expr.X_op != O_constant) as_bad (_("rotate count too large")); - macro_build ((char *) NULL, &icnt, NULL, "sll", "d,w,<", AT, sreg, - (int) (imm_expr.X_add_number & 0x1f)); - macro_build ((char *) NULL, &icnt, NULL, "srl", "d,w,<", dreg, sreg, - (int) ((0 - imm_expr.X_add_number) & 0x1f)); - macro_build ((char *) NULL, &icnt, NULL, "or", "d,v,t", dreg, dreg, AT); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "sll", "d,w,<", + AT, sreg, (int) (imm_expr.X_add_number & 0x1f)); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "srl", "d,w,<", + dreg, sreg, (int) ((0 - imm_expr.X_add_number) & 0x1f)); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "or", "d,v,t", + dreg, dreg, AT); break; case M_ROR: - macro_build ((char *) NULL, &icnt, NULL, "subu", "d,v,t", AT, 0, treg); - macro_build ((char *) NULL, &icnt, NULL, "sllv", "d,t,s", AT, sreg, AT); - macro_build ((char *) NULL, &icnt, NULL, "srlv", "d,t,s", dreg, sreg, - treg); - macro_build ((char *) NULL, &icnt, NULL, "or", "d,v,t", dreg, dreg, AT); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "subu", + "d,v,t", AT, 0, treg); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "sllv", + "d,t,s", AT, sreg, AT); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "srlv", + "d,t,s", dreg, sreg, treg); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "or", + "d,v,t", dreg, dreg, AT); break; case M_ROR_I: if (imm_expr.X_op != O_constant) as_bad (_("rotate count too large")); - macro_build ((char *) NULL, &icnt, NULL, "srl", "d,w,<", AT, sreg, - (int) (imm_expr.X_add_number & 0x1f)); - macro_build ((char *) NULL, &icnt, NULL, "sll", "d,w,<", dreg, sreg, - (int) ((0 - imm_expr.X_add_number) & 0x1f)); - macro_build ((char *) NULL, &icnt, NULL, "or", "d,v,t", dreg, dreg, AT); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "srl", "d,w,<", + AT, sreg, (int) (imm_expr.X_add_number & 0x1f)); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "sll", "d,w,<", + dreg, sreg, (int) ((0 - imm_expr.X_add_number) & 0x1f)); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "or", "d,v,t", + dreg, dreg, AT); break; case M_S_DOB: @@ -6486,8 +6590,8 @@ macro2 (ip) sreg, (int) BFD_RELOC_LO16); else { - macro_build ((char *) NULL, &icnt, NULL, "xor", "d,v,t", dreg, - sreg, treg); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "xor", + "d,v,t", dreg, sreg, treg); macro_build ((char *) NULL, &icnt, &expr1, "sltiu", "t,r,j", dreg, dreg, (int) BFD_RELOC_LO16); } @@ -6529,8 +6633,8 @@ macro2 (ip) else { load_register (&icnt, AT, &imm_expr, 0); - macro_build ((char *) NULL, &icnt, NULL, "xor", "d,v,t", dreg, - sreg, AT); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "xor", + "d,v,t", dreg, sreg, AT); used_at = 1; } macro_build ((char *) NULL, &icnt, &expr1, "sltiu", "t,r,j", dreg, dreg, @@ -6545,7 +6649,8 @@ macro2 (ip) case M_SGEU: s = "sltu"; sge: - macro_build ((char *) NULL, &icnt, NULL, s, "d,v,t", dreg, sreg, treg); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, s, "d,v,t", + dreg, sreg, treg); macro_build ((char *) NULL, &icnt, &expr1, "xori", "t,r,i", dreg, dreg, (int) BFD_RELOC_LO16); return; @@ -6564,9 +6669,9 @@ macro2 (ip) else { load_register (&icnt, AT, &imm_expr, 0); - macro_build ((char *) NULL, &icnt, NULL, - mask == M_SGE_I ? "slt" : "sltu", - "d,v,t", dreg, sreg, AT); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, + mask == M_SGE_I ? "slt" : "sltu", "d,v,t", dreg, sreg, + AT); used_at = 1; } macro_build ((char *) NULL, &icnt, &expr1, "xori", "t,r,i", dreg, dreg, @@ -6581,7 +6686,8 @@ macro2 (ip) case M_SGTU: s = "sltu"; sgt: - macro_build ((char *) NULL, &icnt, NULL, s, "d,v,t", dreg, treg, sreg); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, s, "d,v,t", + dreg, treg, sreg); return; case M_SGT_I: /* sreg > I <==> I < sreg */ @@ -6591,28 +6697,31 @@ macro2 (ip) s = "sltu"; sgti: load_register (&icnt, AT, &imm_expr, 0); - macro_build ((char *) NULL, &icnt, NULL, s, "d,v,t", dreg, AT, sreg); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, s, "d,v,t", + dreg, AT, sreg); break; - case M_SLE: /* sreg <= treg <==> treg >= sreg <==> not (treg < sreg) */ + case M_SLE: /* sreg <= treg <==> treg >= sreg <==> not (treg < sreg) */ s = "slt"; goto sle; case M_SLEU: s = "sltu"; sle: - macro_build ((char *) NULL, &icnt, NULL, s, "d,v,t", dreg, treg, sreg); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, s, "d,v,t", + dreg, treg, sreg); macro_build ((char *) NULL, &icnt, &expr1, "xori", "t,r,i", dreg, dreg, (int) BFD_RELOC_LO16); return; - case M_SLE_I: /* sreg <= I <==> I >= sreg <==> not (I < sreg) */ + case M_SLE_I: /* sreg <= I <==> I >= sreg <==> not (I < sreg) */ s = "slt"; goto slei; case M_SLEU_I: s = "sltu"; slei: load_register (&icnt, AT, &imm_expr, 0); - macro_build ((char *) NULL, &icnt, NULL, s, "d,v,t", dreg, AT, sreg); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, s, "d,v,t", + dreg, AT, sreg); macro_build ((char *) NULL, &icnt, &expr1, "xori", "t,r,i", dreg, dreg, (int) BFD_RELOC_LO16); break; @@ -6627,7 +6736,8 @@ macro2 (ip) return; } load_register (&icnt, AT, &imm_expr, 0); - macro_build ((char *) NULL, &icnt, NULL, "slt", "d,v,t", dreg, sreg, AT); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "slt", "d,v,t", + dreg, sreg, AT); break; case M_SLTU_I: @@ -6640,31 +6750,31 @@ macro2 (ip) return; } load_register (&icnt, AT, &imm_expr, 0); - macro_build ((char *) NULL, &icnt, NULL, "sltu", "d,v,t", dreg, sreg, - AT); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "sltu", + "d,v,t", dreg, sreg, AT); break; case M_SNE: if (sreg == 0) - macro_build ((char *) NULL, &icnt, NULL, "sltu", "d,v,t", dreg, 0, - treg); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "sltu", + "d,v,t", dreg, 0, treg); else if (treg == 0) - macro_build ((char *) NULL, &icnt, NULL, "sltu", "d,v,t", dreg, 0, - sreg); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "sltu", + "d,v,t", dreg, 0, sreg); else { - macro_build ((char *) NULL, &icnt, NULL, "xor", "d,v,t", dreg, - sreg, treg); - macro_build ((char *) NULL, &icnt, NULL, "sltu", "d,v,t", dreg, 0, - dreg); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "xor", + "d,v,t", dreg, sreg, treg); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "sltu", + "d,v,t", dreg, 0, dreg); } return; case M_SNE_I: if (imm_expr.X_op == O_constant && imm_expr.X_add_number == 0) { - macro_build ((char *) NULL, &icnt, NULL, "sltu", "d,v,t", dreg, 0, - sreg); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "sltu", + "d,v,t", dreg, 0, sreg); return; } if (sreg == 0) @@ -6697,11 +6807,12 @@ macro2 (ip) else { load_register (&icnt, AT, &imm_expr, 0); - macro_build ((char *) NULL, &icnt, NULL, "xor", "d,v,t", dreg, - sreg, AT); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "xor", + "d,v,t", dreg, sreg, AT); used_at = 1; } - macro_build ((char *) NULL, &icnt, NULL, "sltu", "d,v,t", dreg, 0, dreg); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "sltu", + "d,v,t", dreg, 0, dreg); if (used_at) break; return; @@ -6720,7 +6831,7 @@ macro2 (ip) return; } load_register (&icnt, AT, &imm_expr, dbl); - macro_build ((char *) NULL, &icnt, NULL, + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, dbl ? "dsub" : "sub", "d,v,t", dreg, sreg, AT); break; @@ -6738,7 +6849,7 @@ macro2 (ip) return; } load_register (&icnt, AT, &imm_expr, dbl); - macro_build ((char *) NULL, &icnt, NULL, + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, dbl ? "dsubu" : "subu", "d,v,t", dreg, sreg, AT); break; @@ -6761,7 +6872,8 @@ macro2 (ip) s = "tne"; trap: load_register (&icnt, AT, &imm_expr, 0); - macro_build ((char *) NULL, &icnt, NULL, s, "s,t", sreg, AT); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, s, "s,t", sreg, + AT); break; case M_TRUNCWS: @@ -6777,21 +6889,25 @@ macro2 (ip) mips_emit_delays (true); ++mips_opts.noreorder; mips_any_noreorder = 1; - macro_build ((char *) NULL, &icnt, NULL, "cfc1", "t,G", treg, 31); - macro_build ((char *) NULL, &icnt, NULL, "cfc1", "t,G", treg, 31); - macro_build ((char *) NULL, &icnt, NULL, "nop", ""); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "cfc1", "t,G", + treg, 31); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "cfc1", "t,G", + treg, 31); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "nop", ""); expr1.X_add_number = 3; macro_build ((char *) NULL, &icnt, &expr1, "ori", "t,r,i", AT, treg, (int) BFD_RELOC_LO16); expr1.X_add_number = 2; macro_build ((char *) NULL, &icnt, &expr1, "xori", "t,r,i", AT, AT, (int) BFD_RELOC_LO16); - macro_build ((char *) NULL, &icnt, NULL, "ctc1", "t,G", AT, 31); - macro_build ((char *) NULL, &icnt, NULL, "nop", ""); - macro_build ((char *) NULL, &icnt, NULL, + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "ctc1", "t,G", + AT, 31); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "nop", ""); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, mask == M_TRUNCWD ? "cvt.w.d" : "cvt.w.s", "D,S", dreg, sreg); - macro_build ((char *) NULL, &icnt, NULL, "ctc1", "t,G", treg, 31); - macro_build ((char *) NULL, &icnt, NULL, "nop", ""); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "ctc1", "t,G", + treg, 31); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "nop", ""); --mips_opts.noreorder; break; @@ -6814,8 +6930,10 @@ macro2 (ip) offset_expr.X_add_number += 1; macro_build ((char *) NULL, &icnt, &offset_expr, "lbu", "t,o(b)", AT, (int) BFD_RELOC_LO16, breg); - macro_build ((char *) NULL, &icnt, NULL, "sll", "d,w,<", treg, treg, 8); - macro_build ((char *) NULL, &icnt, NULL, "or", "d,v,t", treg, treg, AT); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "sll", "d,w,<", + treg, treg, 8); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "or", "d,v,t", + treg, treg, AT); break; case M_ULD: @@ -6891,10 +7009,10 @@ macro2 (ip) expr1.X_add_number = 0; macro_build ((char *) NULL, &icnt, &expr1, "lbu", "t,o(b)", AT, (int) BFD_RELOC_LO16, AT); - macro_build ((char *) NULL, &icnt, NULL, "sll", "d,w,<", treg, - treg, 8); - macro_build ((char *) NULL, &icnt, NULL, "or", "d,v,t", treg, - treg, AT); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "sll", "d,w,<", + treg, treg, 8); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "or", "d,v,t", + treg, treg, AT); break; case M_USH: @@ -6904,7 +7022,8 @@ macro2 (ip) offset_expr.X_add_number += 1; macro_build ((char *) NULL, &icnt, &offset_expr, "sb", "t,o(b)", treg, (int) BFD_RELOC_LO16, breg); - macro_build ((char *) NULL, &icnt, NULL, "srl", "d,w,<", AT, treg, 8); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "srl", "d,w,<", + AT, treg, 8); if (target_big_endian) offset_expr.X_add_number -= 1; else @@ -6978,8 +7097,8 @@ macro2 (ip) expr1.X_add_number = 0; macro_build ((char *) NULL, &icnt, &expr1, "sb", "t,o(b)", treg, (int) BFD_RELOC_LO16, AT); - macro_build ((char *) NULL, &icnt, NULL, "srl", "d,w,<", treg, - treg, 8); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "srl", "d,w,<", + treg, treg, 8); if (! target_big_endian) expr1.X_add_number = 1; else @@ -6992,10 +7111,10 @@ macro2 (ip) expr1.X_add_number = 1; macro_build ((char *) NULL, &icnt, &expr1, "lbu", "t,o(b)", AT, (int) BFD_RELOC_LO16, AT); - macro_build ((char *) NULL, &icnt, NULL, "sll", "d,w,<", treg, - treg, 8); - macro_build ((char *) NULL, &icnt, NULL, "or", "d,v,t", treg, - treg, AT); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "sll", "d,w,<", + treg, treg, 8); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "or", "d,v,t", + treg, treg, AT); break; default: @@ -7054,19 +7173,20 @@ mips16_macro (ip) mips_emit_delays (true); ++mips_opts.noreorder; mips_any_noreorder = 1; - macro_build ((char *) NULL, &icnt, NULL, + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, dbl ? "ddiv" : "div", "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, (expressionS *) 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, but I don't see how to do the comparisons without a temporary register. */ --mips_opts.noreorder; - macro_build ((char *) NULL, &icnt, NULL, s, "x", zreg); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, s, "x", zreg); break; case M_DIVU_3: @@ -7088,20 +7208,23 @@ mips16_macro (ip) mips_emit_delays (true); ++mips_opts.noreorder; mips_any_noreorder = 1; - macro_build ((char *) NULL, &icnt, NULL, s, "0,x,y", xreg, yreg); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, s, "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, (expressionS *) NULL, "break", + "6", 7); --mips_opts.noreorder; - macro_build ((char *) NULL, &icnt, NULL, s2, "x", zreg); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, s2, "x", zreg); break; case M_DMUL: dbl = 1; case M_MUL: - macro_build ((char *) NULL, &icnt, NULL, + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, dbl ? "dmultu" : "multu", "x,y", xreg, yreg); - macro_build ((char *) NULL, &icnt, NULL, "mflo", "x", zreg); + macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "mflo", "x", + zreg); return; case M_DSUBU_I: @@ -8214,23 +8337,11 @@ mips_ip (str, ip) /* If this value won't fit into a 16 bit offset, then go find a macro that will generate the 32 bit offset - code pattern. As a special hack, we accept the - difference of two local symbols as a constant. This - is required to suppose embedded PIC switches, which - use an instruction which looks like - lw $4,$L12-$LS12($4) - The problem with handling this in a more general - fashion is that the macro function doesn't expect to - see anything which can be handled in a single - constant instruction. */ + code pattern. */ if (c == S_EX_NONE && (offset_expr.X_op != O_constant || offset_expr.X_add_number >= 0x8000 - || offset_expr.X_add_number < -0x8000) - && (mips_pic != EMBEDDED_PIC - || offset_expr.X_op != O_subtract - || (S_GET_SEGMENT (offset_expr.X_add_symbol) - != S_GET_SEGMENT (offset_expr.X_op_symbol)))) + || offset_expr.X_add_number < -0x8000)) break; if (c == S_EX_HI) @@ -8263,14 +8374,14 @@ mips_ip (str, ip) if (imm_expr.X_op == O_constant) imm_expr.X_add_number = (imm_expr.X_add_number >> 16) & 0xffff; -#ifdef OBJ_ELF - else if (c == S_EX_HIGHEST) - *imm_reloc = BFD_RELOC_MIPS_HIGHEST; else if (c == S_EX_HI) { *imm_reloc = BFD_RELOC_HI16_S; imm_unmatched_hi = true; } +#ifdef OBJ_ELF + else if (c == S_EX_HIGHEST) + *imm_reloc = BFD_RELOC_MIPS_HIGHEST; else if (c == S_EX_GP_REL) { /* This occurs in NewABI only. */ @@ -8479,8 +8590,7 @@ mips16_ip (str, ip) && *imm_reloc > BFD_RELOC_UNUSED && insn->pinfo != INSN_MACRO) { - mips16_immed ((char *) NULL, 0, - *imm_reloc - BFD_RELOC_UNUSED, + mips16_immed (NULL, 0, *imm_reloc - BFD_RELOC_UNUSED, imm_expr.X_add_number, true, mips16_small, mips16_ext, &ip->insn_opcode, &ip->use_extend, &ip->extend); @@ -9166,9 +9276,9 @@ my_getSmallParser (str, len, nestlevel) *str = b; goto percent_op; } - else - /* Some other expression in the braces. */ - *len = strcspn (*str, ")") + 1; + + /* Some other expression in the braces. */ + *len = strcspn (*str, ")") + 1; } /* Check for percent_op. */ else if (*str[0] == '%') @@ -9222,7 +9332,7 @@ my_getSmallExpression (ep, str) /* Don't update oldstr if the last call had nested percent_op's. */ if (! oldstr) oldstr = str; - + do { oldc = c; @@ -9378,6 +9488,7 @@ md_number_to_chars (buf, val, n) number_to_chars_littleendian (buf, val, n); } +#ifdef OBJ_ELF static int support_64bit_objects(void) { const char **list, **l; @@ -9396,6 +9507,7 @@ static int support_64bit_objects(void) free (list); return (*l != NULL); } +#endif /* OBJ_ELF */ CONST char *md_shortopts = "nO::g::G:"; @@ -9410,83 +9522,82 @@ struct option md_longopts[] = {"mips3", no_argument, NULL, OPTION_MIPS3}, #define OPTION_MIPS4 (OPTION_MD_BASE + 4) {"mips4", no_argument, NULL, OPTION_MIPS4}, -#define OPTION_MCPU (OPTION_MD_BASE + 5) - {"mcpu", required_argument, NULL, OPTION_MCPU}, -#define OPTION_MEMBEDDED_PIC (OPTION_MD_BASE + 6) +#define OPTION_MIPS5 (OPTION_MD_BASE + 5) + {"mips5", no_argument, NULL, OPTION_MIPS5}, +#define OPTION_MIPS32 (OPTION_MD_BASE + 6) + {"mips32", no_argument, NULL, OPTION_MIPS32}, +#define OPTION_MIPS64 (OPTION_MD_BASE + 7) + {"mips64", no_argument, NULL, OPTION_MIPS64}, +#define OPTION_MEMBEDDED_PIC (OPTION_MD_BASE + 8) {"membedded-pic", no_argument, NULL, OPTION_MEMBEDDED_PIC}, -#define OPTION_TRAP (OPTION_MD_BASE + 7) +#define OPTION_TRAP (OPTION_MD_BASE + 9) {"trap", no_argument, NULL, OPTION_TRAP}, {"no-break", no_argument, NULL, OPTION_TRAP}, -#define OPTION_BREAK (OPTION_MD_BASE + 8) +#define OPTION_BREAK (OPTION_MD_BASE + 10) {"break", no_argument, NULL, OPTION_BREAK}, {"no-trap", no_argument, NULL, OPTION_BREAK}, -#define OPTION_EB (OPTION_MD_BASE + 9) +#define OPTION_EB (OPTION_MD_BASE + 11) {"EB", no_argument, NULL, OPTION_EB}, -#define OPTION_EL (OPTION_MD_BASE + 10) +#define OPTION_EL (OPTION_MD_BASE + 12) {"EL", no_argument, NULL, OPTION_EL}, -#define OPTION_M4650 (OPTION_MD_BASE + 11) - {"m4650", no_argument, NULL, OPTION_M4650}, -#define OPTION_NO_M4650 (OPTION_MD_BASE + 12) - {"no-m4650", no_argument, NULL, OPTION_NO_M4650}, -#define OPTION_M4010 (OPTION_MD_BASE + 13) - {"m4010", no_argument, NULL, OPTION_M4010}, -#define OPTION_NO_M4010 (OPTION_MD_BASE + 14) - {"no-m4010", no_argument, NULL, OPTION_NO_M4010}, -#define OPTION_M4100 (OPTION_MD_BASE + 15) - {"m4100", no_argument, NULL, OPTION_M4100}, -#define OPTION_NO_M4100 (OPTION_MD_BASE + 16) - {"no-m4100", no_argument, NULL, OPTION_NO_M4100}, -#define OPTION_MIPS16 (OPTION_MD_BASE + 17) +#define OPTION_MIPS16 (OPTION_MD_BASE + 13) {"mips16", no_argument, NULL, OPTION_MIPS16}, -#define OPTION_NO_MIPS16 (OPTION_MD_BASE + 18) +#define OPTION_NO_MIPS16 (OPTION_MD_BASE + 14) {"no-mips16", no_argument, NULL, OPTION_NO_MIPS16}, -#define OPTION_M3900 (OPTION_MD_BASE + 19) - {"m3900", no_argument, NULL, OPTION_M3900}, -#define OPTION_NO_M3900 (OPTION_MD_BASE + 20) - {"no-m3900", no_argument, NULL, OPTION_NO_M3900}, -#define OPTION_MABI (OPTION_MD_BASE + 21) - {"mabi", required_argument, NULL, OPTION_MABI}, -#define OPTION_M7000_HILO_FIX (OPTION_MD_BASE + 22) +#define OPTION_M7000_HILO_FIX (OPTION_MD_BASE + 15) {"mfix7000", no_argument, NULL, OPTION_M7000_HILO_FIX}, -#define OPTION_NO_M7000_HILO_FIX (OPTION_MD_BASE + 23) +#define OPTION_NO_M7000_HILO_FIX (OPTION_MD_BASE + 16) {"no-fix-7000", no_argument, NULL, OPTION_NO_M7000_HILO_FIX}, -#define OPTION_GP32 (OPTION_MD_BASE + 24) +#define OPTION_FP32 (OPTION_MD_BASE + 17) + {"mfp32", no_argument, NULL, OPTION_FP32}, +#define OPTION_GP32 (OPTION_MD_BASE + 18) {"mgp32", no_argument, NULL, OPTION_GP32}, -#define OPTION_GP64 (OPTION_MD_BASE + 25) - {"mgp64", no_argument, NULL, OPTION_GP64}, -#define OPTION_CONSTRUCT_FLOATS (OPTION_MD_BASE + 26) +#define OPTION_CONSTRUCT_FLOATS (OPTION_MD_BASE + 19) {"construct-floats", no_argument, NULL, OPTION_CONSTRUCT_FLOATS}, -#define OPTION_NO_CONSTRUCT_FLOATS (OPTION_MD_BASE + 27) +#define OPTION_NO_CONSTRUCT_FLOATS (OPTION_MD_BASE + 20) {"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_MIPS5 (OPTION_MD_BASE + 29) - {"mips5", no_argument, NULL, OPTION_MIPS5}, -#define OPTION_MIPS64 (OPTION_MD_BASE + 30) - {"mips64", no_argument, NULL, OPTION_MIPS64}, -#define OPTION_MARCH (OPTION_MD_BASE + 31) +#define OPTION_MARCH (OPTION_MD_BASE + 21) {"march", required_argument, NULL, OPTION_MARCH}, -#define OPTION_MTUNE (OPTION_MD_BASE + 32) +#define OPTION_MTUNE (OPTION_MD_BASE + 22) {"mtune", required_argument, NULL, OPTION_MTUNE}, -#define OPTION_FP32 (OPTION_MD_BASE + 33) - {"mfp32", no_argument, NULL, OPTION_FP32}, +#define OPTION_MCPU (OPTION_MD_BASE + 23) + {"mcpu", required_argument, NULL, OPTION_MCPU}, +#define OPTION_M4650 (OPTION_MD_BASE + 24) + {"m4650", no_argument, NULL, OPTION_M4650}, +#define OPTION_NO_M4650 (OPTION_MD_BASE + 25) + {"no-m4650", no_argument, NULL, OPTION_NO_M4650}, +#define OPTION_M4010 (OPTION_MD_BASE + 26) + {"m4010", no_argument, NULL, OPTION_M4010}, +#define OPTION_NO_M4010 (OPTION_MD_BASE + 27) + {"no-m4010", no_argument, NULL, OPTION_NO_M4010}, +#define OPTION_M4100 (OPTION_MD_BASE + 28) + {"m4100", no_argument, NULL, OPTION_M4100}, +#define OPTION_NO_M4100 (OPTION_MD_BASE + 29) + {"no-m4100", no_argument, NULL, OPTION_NO_M4100}, +#define OPTION_M3900 (OPTION_MD_BASE + 30) + {"m3900", no_argument, NULL, OPTION_M3900}, +#define OPTION_NO_M3900 (OPTION_MD_BASE + 31) + {"no-m3900", no_argument, NULL, OPTION_NO_M3900}, +#define OPTION_GP64 (OPTION_MD_BASE + 32) + {"mgp64", no_argument, NULL, OPTION_GP64}, #ifdef OBJ_ELF -#define OPTION_ELF_BASE (OPTION_MD_BASE + 35) +#define OPTION_ELF_BASE (OPTION_MD_BASE + 33) #define OPTION_CALL_SHARED (OPTION_ELF_BASE + 0) -#define OPTION_NON_SHARED (OPTION_ELF_BASE + 1) -#define OPTION_XGOT (OPTION_ELF_BASE + 2) -#define OPTION_32 (OPTION_ELF_BASE + 3) -#define OPTION_N32 (OPTION_ELF_BASE + 4) -#define OPTION_64 (OPTION_ELF_BASE + 5) {"KPIC", no_argument, NULL, OPTION_CALL_SHARED}, {"call_shared", no_argument, NULL, OPTION_CALL_SHARED}, +#define OPTION_NON_SHARED (OPTION_ELF_BASE + 1) {"non_shared", no_argument, NULL, OPTION_NON_SHARED}, +#define OPTION_XGOT (OPTION_ELF_BASE + 2) {"xgot", no_argument, NULL, OPTION_XGOT}, +#define OPTION_MABI (OPTION_ELF_BASE + 3) + {"mabi", required_argument, NULL, OPTION_MABI}, +#define OPTION_32 (OPTION_ELF_BASE + 4) {"32", no_argument, NULL, OPTION_32}, +#define OPTION_N32 (OPTION_ELF_BASE + 5) {"n32", no_argument, NULL, OPTION_N32}, +#define OPTION_64 (OPTION_ELF_BASE + 6) {"64", no_argument, NULL, OPTION_64}, -#endif - +#endif /* OBJ_ELF */ {NULL, no_argument, NULL, 0} }; size_t md_longopts_size = sizeof (md_longopts); @@ -9751,55 +9862,57 @@ md_parse_option (c, arg) /* The -32 and -64 options tell the assembler to output the 32 bit or the 64 bit MIPS ELF format. */ case OPTION_32: - mips_abi = O32_ABI; + mips_opts.abi = O32_ABI; break; case OPTION_N32: - mips_abi = N32_ABI; + mips_opts.abi = N32_ABI; break; case OPTION_64: - mips_abi = N64_ABI; + mips_opts.abi = N64_ABI; if (! support_64bit_objects()) as_fatal (_("No compiled in support for 64 bit object file format")); break; +#endif /* OBJ_ELF */ case OPTION_GP32: - mips_gp32 = 1; - if (mips_abi != O32_ABI) - mips_abi = NO_ABI; + file_mips_gp32 = 1; + if (mips_opts.abi != O32_ABI) + mips_opts.abi = NO_ABI; break; case OPTION_GP64: - mips_gp32 = 0; - if (mips_abi == O32_ABI) - mips_abi = NO_ABI; + file_mips_gp32 = 0; + if (mips_opts.abi == O32_ABI) + mips_opts.abi = NO_ABI; break; case OPTION_FP32: - mips_fp32 = 1; - if (mips_abi != O32_ABI) - mips_abi = NO_ABI; + file_mips_fp32 = 1; + if (mips_opts.abi != O32_ABI) + mips_opts.abi = NO_ABI; break; +#ifdef OBJ_ELF case OPTION_MABI: if (strcmp (arg, "32") == 0) - mips_abi = O32_ABI; + mips_opts.abi = O32_ABI; else if (strcmp (arg, "o64") == 0) - mips_abi = O64_ABI; + mips_opts.abi = O64_ABI; else if (strcmp (arg, "n32") == 0) - mips_abi = N32_ABI; + mips_opts.abi = N32_ABI; else if (strcmp (arg, "64") == 0) { - mips_abi = N64_ABI; + mips_opts.abi = N64_ABI; if (! support_64bit_objects()) as_fatal (_("No compiled in support for 64 bit object file " "format")); } else if (strcmp (arg, "eabi") == 0) - mips_abi = EABI_ABI; + mips_opts.abi = EABI_ABI; else - mips_abi = NO_ABI; + mips_opts.abi = NO_ABI; break; #endif /* OBJ_ELF */ @@ -9981,7 +10094,7 @@ mips_frob_file_before_adjust () } /* Sort any unmatched HI16_S relocs so that they immediately precede - the corresponding LO reloc. This is called before md_apply_fix and + the corresponding LO reloc. This is called before md_apply_fix3 and tc_gen_reloc. Unmatched HI16_S relocs can only be generated by explicit use of the %hi modifier. */ @@ -10098,13 +10211,6 @@ mips_force_relocation (fixp) || fixp->fx_r_type == BFD_RELOC_LO16)) return 1; - if (HAVE_NEWABI - && S_GET_SEGMENT (fixp->fx_addsy) == bfd_abs_section_ptr - && (fixp->fx_r_type == BFD_RELOC_MIPS_SUB - || fixp->fx_r_type == BFD_RELOC_HI16_S - || fixp->fx_r_type == BFD_RELOC_LO16)) - return 1; - return (mips_pic == EMBEDDED_PIC && (fixp->fx_pcrel || SWITCH_TABLE (fixp) @@ -10114,10 +10220,11 @@ mips_force_relocation (fixp) /* Apply a fixup to the object file. */ -int -md_apply_fix (fixP, valueP) +void +md_apply_fix3 (fixP, valP, seg) fixS *fixP; - valueT *valueP; + valueT * valP; + segT seg ATTRIBUTE_UNUSED; { unsigned char *buf; long insn; @@ -10130,7 +10237,7 @@ md_apply_fix (fixP, valueP) || fixP->fx_r_type == BFD_RELOC_HI16_S || fixP->fx_r_type == BFD_RELOC_LO16 || fixP->fx_r_type == BFD_RELOC_GPREL16 - || fixP->fx_r_type == BFD_RELOC_MIPS_LITERAL + || fixP->fx_r_type == BFD_RELOC_MIPS_LITERAL || fixP->fx_r_type == BFD_RELOC_GPREL32 || fixP->fx_r_type == BFD_RELOC_64 || fixP->fx_r_type == BFD_RELOC_CTOR @@ -10143,7 +10250,7 @@ md_apply_fix (fixP, valueP) || fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY); - value = *valueP; + value = * valP; /* If we aren't adjusting this fixup to be against the section symbol, we need to adjust the value. */ @@ -10164,6 +10271,7 @@ md_apply_fix (fixP, valueP) { valueT symval = S_GET_VALUE (fixP->fx_addsy); + value -= symval; if (value != 0 && ! fixP->fx_pcrel @@ -10231,7 +10339,7 @@ md_apply_fix (fixP, valueP) } #endif - fixP->fx_addnumber = value; /* Remember value for tc_gen_reloc */ + fixP->fx_addnumber = value; /* Remember value for tc_gen_reloc. */ if (fixP->fx_addsy == NULL && ! fixP->fx_pcrel) fixP->fx_done = 1; @@ -10471,8 +10579,6 @@ md_apply_fix (fixP, valueP) default: internalError (); } - - return 1; } #if 0 @@ -10961,10 +11067,6 @@ s_mipsset (x) else if (strncmp (name, "mips", 4) == 0) { int isa; - static int saved_mips_gp32; - static int saved_mips_fp32; - static enum mips_abi_level saved_mips_abi; - static int is_saved; /* Permit the user to change the ISA on the fly. Needless to say, misuse can cause serious problems. */ @@ -10972,41 +11074,28 @@ s_mipsset (x) switch (isa) { case 0: - mips_gp32 = saved_mips_gp32; - mips_fp32 = saved_mips_fp32; - mips_abi = saved_mips_abi; - is_saved = 0; + mips_opts.gp32 = file_mips_gp32; + mips_opts.fp32 = file_mips_fp32; + mips_opts.abi = file_mips_abi; break; case 1: case 2: case 32: - if (! is_saved) - { - saved_mips_gp32 = mips_gp32; - saved_mips_fp32 = mips_fp32; - saved_mips_abi = mips_abi; - } - mips_gp32 = 1; - mips_fp32 = 1; - is_saved = 1; + mips_opts.gp32 = 1; + mips_opts.fp32 = 1; break; case 3: case 4: case 5: case 64: - if (! is_saved) - { - saved_mips_gp32 = mips_gp32; - saved_mips_fp32 = mips_fp32; - saved_mips_abi = mips_abi; - } - mips_gp32 = 0; - mips_fp32 = 0; - mips_abi = NO_ABI; - is_saved = 1; + /* Loosen ABI register width restriction. */ + if (mips_opts.abi == O32_ABI) + mips_opts.abi = NO_ABI; + mips_opts.gp32 = 0; + mips_opts.fp32 = 0; break; default: - as_bad (_("unknown ISA level")); + as_bad (_("unknown ISA level %s"), name + 4); break; } @@ -11020,7 +11109,7 @@ s_mipsset (x) case 5: mips_opts.isa = ISA_MIPS5; break; case 32: mips_opts.isa = ISA_MIPS32; break; case 64: mips_opts.isa = ISA_MIPS64; break; - default: as_bad (_("unknown ISA level")); break; + default: as_bad (_("unknown ISA level %s"), name + 4); break; } } else if (strcmp (name, "autoextend") == 0) @@ -11127,7 +11216,7 @@ s_cpload (ignore) /* In ELF, this symbol is implicitly an STT_OBJECT symbol. */ symbol_get_bfdsym (ex.X_add_symbol)->flags |= BSF_OBJECT; - macro_build_lui ((char *) NULL, &icnt, &ex, GP); + macro_build_lui (NULL, &icnt, &ex, GP); macro_build ((char *) NULL, &icnt, &ex, "addiu", "t,r,j", GP, GP, (int) BFD_RELOC_LO16); @@ -11286,7 +11375,7 @@ s_cprestore (ignore) /* Handle the .cpreturn pseudo-op defined for NewABI PIC code. If an offset was given in the preceeding .gpsetup, it results in: ld $gp, offset($sp) - + If a register $reg2 was given there, it results in: daddiu $gp, $gp, $reg2 */ @@ -12195,7 +12284,7 @@ mips_relax_frag (fragp, stretch) if (! RELAX_MIPS16_P (fragp->fr_subtype)) return 0; - if (mips16_extended_frag (fragp, (asection *) NULL, stretch)) + if (mips16_extended_frag (fragp, NULL, stretch)) { if (RELAX_MIPS16_EXTENDED (fragp->fr_subtype)) return 0; @@ -12433,20 +12522,20 @@ mips_elf_final_processing () elf_elfheader (stdoutput)->e_flags |= EF_MIPS_PIC; /* Set the MIPS ELF ABI flags. */ - if (mips_abi == NO_ABI) + if (file_mips_abi == NO_ABI) ; - else if (mips_abi == O32_ABI) + else if (file_mips_abi == O32_ABI) elf_elfheader (stdoutput)->e_flags |= E_MIPS_ABI_O32; - else if (mips_abi == O64_ABI) + else if (file_mips_abi == O64_ABI) elf_elfheader (stdoutput)->e_flags |= E_MIPS_ABI_O64; - else if (mips_abi == EABI_ABI) + else if (file_mips_abi == EABI_ABI) { if (mips_eabi64) elf_elfheader (stdoutput)->e_flags |= E_MIPS_ABI_EABI64; else elf_elfheader (stdoutput)->e_flags |= E_MIPS_ABI_EABI32; } - else if (mips_abi == N32_ABI) + else if (file_mips_abi == N32_ABI) elf_elfheader (stdoutput)->e_flags |= EF_MIPS_ABI2; /* Nothing to do for "64". */