From: Ken Raeburn Date: Tue, 11 Apr 1995 01:29:49 +0000 (+0000) Subject: Fix for PR6697: X-Git-Url: http://drtracing.org/?a=commitdiff_plain;h=d8a1c247aef292a99c2a132bd7d9a950234c7c7e;p=deliverable%2Fbinutils-gdb.git Fix for PR6697: (nopic_need_relax): New static function, split out from md_estimate_size_before_relax. (md_estimate_size_before_relax): Call it. (load_address, macro): In NO_PIC branches, if nopic_need_relax returns nonzero, don't attempt GP optimization. --- diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c index f3677ec3a6..4fb2c0aeaf 100644 --- a/gas/config/tc-mips.c +++ b/gas/config/tc-mips.c @@ -168,6 +168,19 @@ static int g_switch_seen = 0; #define N_RMASK 0xc4 #define N_VFP 0xd4 +/* If we can determine in advance that GP optimization won't be + possible, we can skip the relaxation stuff that tries to produce + GP-relative references. This makes delay slot optimization work + better. + + This function can only provide a guess, but it seems to work for + gcc output. If it guesses wrong, the only loss should be in + efficiency; it shouldn't introduce any bugs. + + I don't know if a fix is needed for the SVR4_PIC mode. I've only + fixed it for the non-PIC mode. KR 95/04/07 */ +static int nopic_need_relax PARAMS ((symbolS *)); + /* handle of the OPCODE hash table */ static struct hash_control *op_hash = NULL; @@ -361,7 +374,7 @@ static void macro_build_lui PARAMS ((char *place, int *counter, static void set_at PARAMS ((int *counter, int reg, int unsignedp)); static void check_absolute_expr PARAMS ((struct mips_cl_insn * ip, expressionS *)); -static void load_register PARAMS ((int *counter, int reg, expressionS * ep)); +static void load_register PARAMS ((int *, int, expressionS *, int)); static void load_address PARAMS ((int *counter, int reg, expressionS *ep)); static void macro PARAMS ((struct mips_cl_insn * ip)); #ifdef LOSING_COMPILER @@ -580,6 +593,19 @@ md_begin () if (mips_4650 == -1) mips_4650 = 1; } + else if (strcmp (cpu, "r8000") == 0 + || strcmp (cpu, "mips4") == 0) + { + mips_isa = 4; + if (mips_cpu == -1) + mips_cpu = 8000; + } + else if (strcmp (cpu, "r10000") == 0) + { + mips_isa = 4; + if (mips_cpu == -1) + mips_cpu = 10000; + } else { mips_isa = 1; @@ -608,6 +634,9 @@ md_begin () case 3: ok = bfd_set_arch_mach (stdoutput, bfd_arch_mips, 4000); break; + case 4: + ok = bfd_set_arch_mach (stdoutput, bfd_arch_mips, 8000); + break; } if (! ok) as_warn ("Could not set architecture and machine"); @@ -831,9 +860,10 @@ append_insn (place, ip, address_expr, reloc_type) /* The previous insn might require a delay slot, depending upon the contents of the current insn. */ - if ((prev_pinfo & INSN_LOAD_COPROC_DELAY) - || (mips_isa < 2 - && (prev_pinfo & INSN_LOAD_MEMORY_DELAY))) + if (mips_isa < 4 + && ((prev_pinfo & INSN_LOAD_COPROC_DELAY) + || (mips_isa < 2 + && (prev_pinfo & INSN_LOAD_MEMORY_DELAY)))) { /* A load from a coprocessor or from memory. All load delays delay the use of general register rt for one @@ -847,9 +877,10 @@ append_insn (place, ip, address_expr, reloc_type) 0)) ++nops; } - else if ((prev_pinfo & INSN_COPROC_MOVE_DELAY) - || (mips_isa < 2 - && (prev_pinfo & INSN_COPROC_MEMORY_DELAY))) + else if (mips_isa < 4 + && ((prev_pinfo & INSN_COPROC_MOVE_DELAY) + || (mips_isa < 2 + && (prev_pinfo & INSN_COPROC_MEMORY_DELAY)))) { /* A generic coprocessor delay. The previous instruction modified a coprocessor general or control register. If @@ -899,7 +930,8 @@ append_insn (place, ip, address_expr, reloc_type) ++nops; } } - else if (prev_pinfo & INSN_WRITE_COND_CODE) + else if (mips_isa < 4 + && (prev_pinfo & INSN_WRITE_COND_CODE)) { /* The previous instruction sets the coprocessor condition codes, but does not require a general coprocessor delay @@ -940,7 +972,8 @@ append_insn (place, ip, address_expr, reloc_type) instruction, we must check for these cases compared to the instruction previous to the previous instruction. */ if (nops == 0 - && (((prev_prev_insn.insn_mo->pinfo & INSN_COPROC_MOVE_DELAY) + && ((mips_isa < 4 + && (prev_prev_insn.insn_mo->pinfo & INSN_COPROC_MOVE_DELAY) && (prev_prev_insn.insn_mo->pinfo & INSN_WRITE_COND_CODE) && (pinfo & INSN_READ_COND_CODE)) || ((prev_prev_insn.insn_mo->pinfo & INSN_READ_LO) @@ -1045,6 +1078,8 @@ append_insn (place, ip, address_expr, reloc_type) mips_cprmask[1] |= 1 << ((ip->insn_opcode >> OP_SH_FS) & OP_MASK_FS); if ((pinfo & (INSN_WRITE_FPR_T | INSN_READ_FPR_T)) != 0) mips_cprmask[1] |= 1 << ((ip->insn_opcode >> OP_SH_FT) & OP_MASK_FT); + if ((pinfo & INSN_READ_FPR_R) != 0) + mips_cprmask[1] |= 1 << ((ip->insn_opcode >> OP_SH_FR) & OP_MASK_FR); if (pinfo & INSN_COP) { /* We don't keep enough information to sort these cases out. */ @@ -1109,14 +1144,16 @@ append_insn (place, ip, address_expr, reloc_type) bc1t LABEL we can not swap, and I don't feel like handling that case. */ - || (pinfo & INSN_READ_COND_CODE) + || (mips_isa < 4 + && (pinfo & INSN_READ_COND_CODE)) /* We can not swap with an instruction that requires a delay slot, becase the target of the branch might interfere with that instruction. */ - || (prev_pinfo - & (INSN_LOAD_COPROC_DELAY - | INSN_COPROC_MOVE_DELAY - | INSN_WRITE_COND_CODE)) + || (mips_isa < 4 + && (prev_pinfo + & (INSN_LOAD_COPROC_DELAY + | INSN_COPROC_MOVE_DELAY + | INSN_WRITE_COND_CODE))) || (! mips_4650 && (prev_pinfo & (INSN_READ_LO @@ -1183,10 +1220,11 @@ append_insn (place, ip, address_expr, reloc_type) /* If the previous previous instruction has a load delay, and sets a register that the branch reads, we can not swap. */ - || (((prev_prev_insn.insn_mo->pinfo & INSN_LOAD_COPROC_DELAY) - || (mips_isa < 2 - && (prev_prev_insn.insn_mo->pinfo - & INSN_LOAD_MEMORY_DELAY))) + || (mips_isa < 4 + && ((prev_prev_insn.insn_mo->pinfo & INSN_LOAD_COPROC_DELAY) + || (mips_isa < 2 + && (prev_prev_insn.insn_mo->pinfo + & INSN_LOAD_MEMORY_DELAY))) && insn_uses_reg (ip, ((prev_prev_insn.insn_opcode >> OP_SH_RT) & OP_MASK_RT), @@ -1301,10 +1339,11 @@ mips_emit_delays () int nop; nop = 0; - if ((prev_insn.insn_mo->pinfo - & (INSN_LOAD_COPROC_DELAY - | INSN_COPROC_MOVE_DELAY - | INSN_WRITE_COND_CODE)) + if ((mips_isa < 4 + && (prev_insn.insn_mo->pinfo + & (INSN_LOAD_COPROC_DELAY + | INSN_COPROC_MOVE_DELAY + | INSN_WRITE_COND_CODE))) || (! mips_4650 && (prev_insn.insn_mo->pinfo & (INSN_READ_LO @@ -1315,13 +1354,15 @@ mips_emit_delays () | INSN_COPROC_MEMORY_DELAY)))) { nop = 1; - if ((prev_insn.insn_mo->pinfo & INSN_WRITE_COND_CODE) + if ((mips_isa < 4 + && (prev_insn.insn_mo->pinfo & INSN_WRITE_COND_CODE)) || (! mips_4650 && ((prev_insn.insn_mo->pinfo & INSN_READ_HI) || (prev_insn.insn_mo->pinfo & INSN_READ_LO)))) emit_nop (); } - else if ((prev_prev_insn.insn_mo->pinfo & INSN_WRITE_COND_CODE) + else if ((mips_isa < 4 + && (prev_prev_insn.insn_mo->pinfo & INSN_WRITE_COND_CODE)) || (! mips_4650 && ((prev_prev_insn.insn_mo->pinfo & INSN_READ_HI) || (prev_prev_insn.insn_mo->pinfo & INSN_READ_LO)))) @@ -1605,7 +1646,7 @@ set_at (counter, reg, unsignedp) "t,r,j", AT, reg, (int) BFD_RELOC_LO16); else { - load_register (counter, AT, &imm_expr); + load_register (counter, AT, &imm_expr, 0); macro_build ((char *) NULL, counter, NULL, unsignedp ? "sltu" : "slt", "d,v,t", AT, reg, AT); @@ -1628,18 +1669,24 @@ check_absolute_expr (ip, ex) * an absolute expression value into a register. */ static void -load_register (counter, reg, ep) +load_register (counter, reg, ep, dbl) int *counter; int reg; expressionS *ep; + int dbl; { - int shift; + int shift, freg; expressionS hi32, lo32, tmp; if (ep->X_op != O_big) { assert (ep->X_op == O_constant); - if (ep->X_add_number >= -0x8000 && ep->X_add_number < 0x8000) + if (ep->X_add_number < 0x8000 + && (ep->X_add_number >= 0 + || (ep->X_add_number >= -0x8000 + && (! dbl + || ! ep->X_unsigned + || sizeof (ep->X_add_number) > 4)))) { /* We can handle 16 bit signed values with an addiu to $zero. No need to ever use daddiu here, since $zero and @@ -1659,7 +1706,7 @@ load_register (counter, reg, ep) else if (((ep->X_add_number &~ (offsetT) 0x7fffffff) == 0 || ((ep->X_add_number &~ (offsetT) 0x7fffffff) == ~ (offsetT) 0x7fffffff)) - && (mips_isa < 3 + && (! dbl || ! ep->X_unsigned || sizeof (ep->X_add_number) > 4 || (ep->X_add_number & 0x80000000) == 0)) @@ -1721,25 +1768,42 @@ load_register (counter, reg, ep) hi32.X_add_number = generic_bignum[2] + (generic_bignum[3] << 16); } - load_register (counter, reg, &hi32); + if (hi32.X_add_number == 0) + freg = 0; + else + { + load_register (counter, reg, &hi32, 0); + freg = reg; + } if ((lo32.X_add_number & 0xffff0000) == 0) - macro_build ((char *) NULL, counter, NULL, "dsll32", "d,w,<", reg, - reg, 0); + { + if (freg != 0) + { + macro_build ((char *) NULL, counter, NULL, "dsll32", "d,w,<", reg, + freg, 0); + freg = reg; + } + } else { expressionS mid16; - macro_build ((char *) NULL, counter, NULL, "dsll", "d,w,<", reg, - reg, 16); + if (freg != 0) + { + macro_build ((char *) NULL, counter, NULL, "dsll", "d,w,<", reg, + freg, 16); + freg = reg; + } mid16 = lo32; mid16.X_add_number >>= 16; macro_build ((char *) NULL, counter, &mid16, "ori", "t,r,i", reg, - reg, (int) BFD_RELOC_LO16); + freg, (int) BFD_RELOC_LO16); macro_build ((char *) NULL, counter, NULL, "dsll", "d,w,<", reg, reg, 16); + freg = reg; } if ((lo32.X_add_number & 0xffff) != 0) - macro_build ((char *) NULL, counter, &lo32, "ori", "t,r,i", reg, reg, + macro_build ((char *) NULL, counter, &lo32, "ori", "t,r,i", reg, freg, (int) BFD_RELOC_LO16); } @@ -1762,7 +1826,7 @@ load_address (counter, reg, ep) if (ep->X_op == O_constant) { - load_register (counter, reg, ep); + load_register (counter, reg, ep, 0); return; } @@ -1774,7 +1838,7 @@ load_address (counter, reg, ep) lui $reg, (BFD_RELOC_HI16_S) addiu $reg,$reg, (BFD_RELOC_LO16) If we have an addend, we always use the latter form. */ - if (ep->X_add_number != 0) + if (ep->X_add_number != 0 || nopic_need_relax (ep->X_add_symbol)) p = NULL; else { @@ -1942,7 +2006,7 @@ macro (ip) (int) BFD_RELOC_LO16); return; } - load_register (&icnt, AT, &imm_expr); + load_register (&icnt, AT, &imm_expr, dbl); macro_build ((char *) NULL, &icnt, NULL, s2, "d,v,t", treg, sreg, AT); break; @@ -1977,7 +2041,7 @@ macro (ip) return; } - load_register (&icnt, AT, &imm_expr); + load_register (&icnt, AT, &imm_expr, 0); macro_build ((char *) NULL, &icnt, NULL, s2, "d,v,t", treg, sreg, AT); break; @@ -2001,7 +2065,7 @@ macro (ip) 0); return; } - load_register (&icnt, AT, &imm_expr); + load_register (&icnt, AT, &imm_expr, 0); macro_build ((char *) NULL, &icnt, &offset_expr, s, "s,t,p", sreg, AT); break; @@ -2478,7 +2542,7 @@ macro (ip) return; } - load_register (&icnt, AT, &imm_expr); + 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); break; @@ -2516,6 +2580,8 @@ macro (ip) macro_build ((char *) NULL, &icnt, NULL, s2, "d", dreg); return; + case M_DLA_AB: + dbl = 1; case M_LA_AB: /* Load the address of a symbol into a register. If breg is not zero, we then add a base register to it. */ @@ -2567,7 +2633,7 @@ macro (ip) } if (offset_expr.X_op == O_constant) - load_register (&icnt, tempreg, &offset_expr); + load_register (&icnt, tempreg, &offset_expr, dbl); else if (mips_pic == NO_PIC) { /* If this is a reference to an GP relative symbol, we want @@ -2577,7 +2643,8 @@ 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. */ - if (offset_expr.X_add_number != 0) + if (offset_expr.X_add_number != 0 + || nopic_need_relax (offset_expr.X_add_symbol)) p = NULL; else { @@ -2630,7 +2697,7 @@ macro (ip) offset_expr.X_add_number = 0; frag_grow (32); macro_build ((char *) NULL, &icnt, &offset_expr, - mips_isa < 3 ? "lw" : "ld", + dbl ? "ld" : "lw", "t,o(b)", tempreg, (int) BFD_RELOC_MIPS_GOT16, GP); if (expr1.X_add_number == 0) { @@ -3031,7 +3098,8 @@ macro (ip) With a constant we always use the latter case. */ if (breg == 0) { - if (offset_expr.X_add_number != 0) + if (offset_expr.X_add_number != 0 + || nopic_need_relax (offset_expr.X_add_symbol)) p = NULL; else { @@ -3054,7 +3122,8 @@ macro (ip) } else { - if (offset_expr.X_add_number != 0) + if (offset_expr.X_add_number != 0 + || nopic_need_relax (offset_expr.X_add_symbol)) p = NULL; else { @@ -3157,13 +3226,17 @@ macro (ip) case M_LI: case M_LI_S: - load_register (&icnt, treg, &imm_expr); + load_register (&icnt, treg, &imm_expr, 0); + return; + + case M_DLI: + load_register (&icnt, treg, &imm_expr, 1); return; case M_LI_SS: if (imm_expr.X_op == O_constant) { - load_register (&icnt, AT, &imm_expr); + load_register (&icnt, AT, &imm_expr, 0); macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "mtc1", "t,G", AT, treg); break; @@ -3390,7 +3463,8 @@ macro (ip) If there is a base register, we add it to $at after the lui instruction. If there is a constant, we always use the last case. */ - if (offset_expr.X_add_number != 0) + if (offset_expr.X_add_number != 0 + || nopic_need_relax (offset_expr.X_add_symbol)) { p = NULL; used_at = 1; @@ -3638,7 +3712,7 @@ macro2 (ip) /* The MIPS assembler some times generates shifts and adds. I'm not trying to be that fancy. GCC should do this for us anyway. */ - load_register (&icnt, AT, &imm_expr); + load_register (&icnt, AT, &imm_expr, dbl); macro_build ((char *) NULL, &icnt, NULL, dbl ? "dmult" : "mult", "s,t", sreg, AT); @@ -3787,7 +3861,7 @@ macro2 (ip) } else { - load_register (&icnt, AT, &imm_expr); + load_register (&icnt, AT, &imm_expr, 0); macro_build ((char *) NULL, &icnt, NULL, "xor", "d,v,t", dreg, sreg, AT); used_at = 1; @@ -3820,7 +3894,7 @@ macro2 (ip) } else { - load_register (&icnt, AT, &imm_expr); + 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); @@ -3847,7 +3921,7 @@ macro2 (ip) case M_SGTU_I: s = "sltu"; sgti: - load_register (&icnt, AT, &imm_expr); + load_register (&icnt, AT, &imm_expr, 0); macro_build ((char *) NULL, &icnt, NULL, s, "d,v,t", dreg, AT, sreg); break; @@ -3868,7 +3942,7 @@ macro2 (ip) case M_SLEU_I: s = "sltu"; slei: - load_register (&icnt, AT, &imm_expr); + 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, &expr1, "xori", "t,r,i", dreg, dreg, (int) BFD_RELOC_LO16); @@ -3881,7 +3955,7 @@ macro2 (ip) dreg, sreg, (int) BFD_RELOC_LO16); return; } - load_register (&icnt, AT, &imm_expr); + load_register (&icnt, AT, &imm_expr, 0); macro_build ((char *) NULL, &icnt, NULL, "slt", "d,v,t", dreg, sreg, AT); break; @@ -3892,7 +3966,7 @@ macro2 (ip) dreg, sreg, (int) BFD_RELOC_LO16); return; } - load_register (&icnt, AT, &imm_expr); + load_register (&icnt, AT, &imm_expr, 0); macro_build ((char *) NULL, &icnt, NULL, "sltu", "d,v,t", dreg, sreg, AT); break; @@ -3945,7 +4019,7 @@ macro2 (ip) } else { - load_register (&icnt, AT, &imm_expr); + load_register (&icnt, AT, &imm_expr, 0); macro_build ((char *) NULL, &icnt, NULL, "xor", "d,v,t", dreg, sreg, AT); used_at = 1; @@ -3966,7 +4040,7 @@ macro2 (ip) "t,r,j", dreg, sreg, (int) BFD_RELOC_LO16); return; } - load_register (&icnt, AT, &imm_expr); + load_register (&icnt, AT, &imm_expr, dbl); macro_build ((char *) NULL, &icnt, NULL, dbl ? "dsub" : "sub", "d,v,t", dreg, sreg, AT); @@ -3983,7 +4057,7 @@ macro2 (ip) "t,r,j", dreg, sreg, (int) BFD_RELOC_LO16); return; } - load_register (&icnt, AT, &imm_expr); + load_register (&icnt, AT, &imm_expr, dbl); macro_build ((char *) NULL, &icnt, NULL, dbl ? "dsubu" : "subu", "d,v,t", dreg, sreg, AT); @@ -4007,7 +4081,7 @@ macro2 (ip) case M_TNE_I: s = "tne"; trap: - load_register (&icnt, AT, &imm_expr); + load_register (&icnt, AT, &imm_expr, 0); macro_build ((char *) NULL, &icnt, NULL, s, "s,t", sreg, AT); break; @@ -4288,6 +4362,8 @@ mips_ip (str, ip) insn_isa = 2; else if ((insn->pinfo & INSN_ISA) == INSN_ISA3) insn_isa = 3; + else if ((insn->pinfo & INSN_ISA) == INSN_ISA4) + insn_isa = 4; else insn_isa = 1; @@ -4386,15 +4462,20 @@ mips_ip (str, ip) continue; case 'k': /* cache code */ + case 'h': /* prefx code */ my_getExpression (&imm_expr, s); check_absolute_expr (ip, &imm_expr); if ((unsigned long) imm_expr.X_add_number > 31) { - as_warn ("Invalid cahce opcode (%lu)", + as_warn ("Invalid value for `%s' (%lu)", + ip->insn_mo->name, (unsigned long) imm_expr.X_add_number); imm_expr.X_add_number &= 0x1f; } - ip->insn_opcode |= imm_expr.X_add_number << OP_SH_CACHE; + if (*args == 'k') + ip->insn_opcode |= imm_expr.X_add_number << OP_SH_CACHE; + else + ip->insn_opcode |= imm_expr.X_add_number << OP_SH_PREFX; imm_expr.X_op = O_absent; s = expr_end; continue; @@ -4569,6 +4650,7 @@ mips_ip (str, ip) case 'D': /* floating point destination register */ case 'S': /* floating point source register */ case 'T': /* floating point target register */ + case 'R': /* floating point source register */ case 'V': case 'W': s_reset = s; @@ -4620,6 +4702,10 @@ mips_ip (str, ip) case 'W': case 'T': ip->insn_opcode |= regno << 16; + break; + case 'R': + ip->insn_opcode |= regno << 21; + break; } lastregno = regno; continue; @@ -4837,7 +4923,12 @@ mips_ip (str, ip) max = 0x10000; if (imm_expr.X_op == O_big || imm_expr.X_add_number < -0x8000 - || imm_expr.X_add_number >= max) + || imm_expr.X_add_number >= max + || (more + && imm_expr.X_add_number < 0 + && mips_isa >= 3 + && imm_expr.X_unsigned + && sizeof (imm_expr.X_add_number) <= 4)) { if (more) break; @@ -4917,6 +5008,24 @@ mips_ip (str, ip) offset_reloc = BFD_RELOC_MIPS_JMP; continue; + case 'N': /* 3 bit branch condition code */ + case 'M': /* 3 bit compare condition code */ + my_getExpression (&imm_expr, s); + check_absolute_expr (ip, &imm_expr); + if ((unsigned long) imm_expr.X_add_number > 7) + { + as_warn ("Condition code > 7 (%ld)", + (long) imm_expr.X_add_number); + imm_expr.X_add_number &= 7; + } + if (*args == 'N') + ip->insn_opcode |= imm_expr.X_add_number << OP_SH_BCC; + else + ip->insn_opcode |= imm_expr.X_add_number << OP_SH_CCC; + imm_expr.X_op = O_absent; + s = expr_end; + continue; + default: fprintf (stderr, "bad char = '%c'\n", *args); internalError (); @@ -5131,30 +5240,32 @@ struct option md_longopts[] = { {"mips2", no_argument, NULL, OPTION_MIPS2}, #define OPTION_MIPS3 (OPTION_MD_BASE + 3) {"mips3", no_argument, NULL, OPTION_MIPS3}, -#define OPTION_MCPU (OPTION_MD_BASE + 4) +#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 + 5) +#define OPTION_MEMBEDDED_PIC (OPTION_MD_BASE + 6) {"membedded-pic", no_argument, NULL, OPTION_MEMBEDDED_PIC}, -#define OPTION_TRAP (OPTION_MD_BASE + 8) +#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 + 9) +#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 + 10) +#define OPTION_EB (OPTION_MD_BASE + 11) {"EB", no_argument, NULL, OPTION_EB}, -#define OPTION_EL (OPTION_MD_BASE + 11) +#define OPTION_EL (OPTION_MD_BASE + 12) {"EL", no_argument, NULL, OPTION_EL}, -#define OPTION_M4650 (OPTION_MD_BASE + 12) +#define OPTION_M4650 (OPTION_MD_BASE + 13) {"m4650", no_argument, NULL, OPTION_M4650}, -#define OPTION_NO_M4650 (OPTION_MD_BASE + 13) +#define OPTION_NO_M4650 (OPTION_MD_BASE + 14) {"no-m4650", no_argument, NULL, OPTION_NO_M4650}, #ifdef OBJ_ELF -#define OPTION_CALL_SHARED (OPTION_MD_BASE + 6) +#define OPTION_CALL_SHARED (OPTION_MD_BASE + 7) {"KPIC", no_argument, NULL, OPTION_CALL_SHARED}, {"call_shared", no_argument, NULL, OPTION_CALL_SHARED}, -#define OPTION_NON_SHARED (OPTION_MD_BASE + 7) +#define OPTION_NON_SHARED (OPTION_MD_BASE + 8) {"non_shared", no_argument, NULL, OPTION_NON_SHARED}, #endif @@ -5233,6 +5344,12 @@ md_parse_option (c, arg) mips_cpu = 4000; break; + case OPTION_MIPS4: + mips_isa = 4; + if (mips_cpu == -1) + mips_cpu = 8000; + break; + case OPTION_MCPU: { char *p; @@ -5250,6 +5367,13 @@ md_parse_option (c, arg) mips_cpu = -1; switch (*p) { + case '1': + if (strcmp (p, "10000") == 0 + || strcmp (p, "10k") == 0 + || strcmp (p, "10K") == 0) + mips_cpu = 10000; + break; + case '2': if (strcmp (p, "2000") == 0 || strcmp (p, "2k") == 0 @@ -5288,6 +5412,13 @@ md_parse_option (c, arg) mips_cpu = 6000; break; + case '8': + if (strcmp (p, "8000") == 0 + || strcmp (p, "8k") == 0 + || strcmp (p, "8K") == 0) + mips_cpu = 8000; + break; + case 'o': if (strcmp (p, "orion") == 0) mips_cpu = 4600; @@ -5378,6 +5509,9 @@ MIPS options:\n\ -mips1, -mcpu=r{2,3}000 generate code for r2000 and r3000\n\ -mips2, -mcpu=r6000 generate code for r6000\n\ -mips3, -mcpu=r4000 generate code for r4000\n\ +-mips4, -mcpu=r8000 generate code for r8000\n\ +-m4650 permit -m4650 instructions\n\ +-no-m4650 do not permit -m4650 instructions\n\ -O0 remove unneeded NOPs, do not swap branches\n\ -O remove unneeded NOPs and swap branches\n\ --trap, --no-break trap exception on div by 0 and mult overflow\n\ @@ -6124,7 +6258,7 @@ s_mipsset (x) isa = atoi (name + 4); if (isa == 0) mips_isa = file_mips_isa; - else if (isa < 1 || isa > 3) + else if (isa < 1 || isa > 4) as_bad ("unknown ISA level"); else mips_isa = isa; @@ -6368,6 +6502,61 @@ md_section_align (seg, addr) relaxing here, and the final size is encoded in the subtype information. */ +/* Utility routine, called from above as well. If called while the + input file is still being read, it's only an approximation. (For + example, a symbol may later become defined which appeared to be + undefined earlier.) */ +static int nopic_need_relax (sym) + symbolS *sym; +{ + if (sym == 0) + return 0; + +#ifdef GPOPT + { + const char *symname; + int change; + + /* Find out whether this symbol can be referenced off the GP + register. It can be if it is smaller than the -G size or if it + is in the .sdata or .sbss section. Certain symbols can not be + referenced off the GP, although it appears as though they can. */ + symname = S_GET_NAME (sym); + if (symname != (const char *) NULL + && (strcmp (symname, "eprol") == 0 + || strcmp (symname, "etext") == 0 + || strcmp (symname, "_gp") == 0 + || strcmp (symname, "edata") == 0 + || strcmp (symname, "_fbss") == 0 + || strcmp (symname, "_fdata") == 0 + || strcmp (symname, "_ftext") == 0 + || strcmp (symname, "end") == 0 + || strcmp (symname, "_gp_disp") == 0)) + change = 1; + else if (! S_IS_DEFINED (sym) + && ((sym->ecoff_extern_size != 0 + && sym->ecoff_extern_size <= g_switch_value) + || (S_GET_VALUE (sym) != 0 + && S_GET_VALUE (sym) <= g_switch_value))) + change = 0; + else + { + const char *segname; + + segname = segment_name (S_GET_SEGMENT (sym)); + assert (strcmp (segname, ".lit8") != 0 + && strcmp (segname, ".lit4") != 0); + change = (strcmp (segname, ".sdata") != 0 + && strcmp (segname, ".sbss") != 0); + } + return change; + } +#else /* ! defined (GPOPT) */ + /* We are not optimizing for the GP register. */ + return 1; +#endif /* ! defined (GPOPT) */ +} + /*ARGSUSED*/ int md_estimate_size_before_relax (fragp, segtype) @@ -6378,46 +6567,7 @@ md_estimate_size_before_relax (fragp, segtype) if (mips_pic == NO_PIC) { -#ifdef GPOPT - const char *symname; - - /* Find out whether this symbol can be referenced off the GP - register. It can be if it is smaller than the -G size or if - it is in the .sdata or .sbss section. Certain symbols can - not be referenced off the GP, although it appears as though - they can. */ - symname = S_GET_NAME (fragp->fr_symbol); - if (symname != (const char *) NULL - && (strcmp (symname, "eprol") == 0 - || strcmp (symname, "etext") == 0 - || strcmp (symname, "_gp") == 0 - || strcmp (symname, "edata") == 0 - || strcmp (symname, "_fbss") == 0 - || strcmp (symname, "_fdata") == 0 - || strcmp (symname, "_ftext") == 0 - || strcmp (symname, "end") == 0 - || strcmp (symname, "_gp_disp") == 0)) - change = 1; - else if (! S_IS_DEFINED (fragp->fr_symbol) - && ((fragp->fr_symbol->ecoff_extern_size != 0 - && fragp->fr_symbol->ecoff_extern_size <= g_switch_value) - || (S_GET_VALUE (fragp->fr_symbol) != 0 - && S_GET_VALUE (fragp->fr_symbol) <= g_switch_value))) - change = 0; - else - { - const char *segname; - - segname = segment_name (S_GET_SEGMENT (fragp->fr_symbol)); - assert (strcmp (segname, ".lit8") != 0 - && strcmp (segname, ".lit4") != 0); - change = (strcmp (segname, ".sdata") != 0 - && strcmp (segname, ".sbss") != 0); - } -#else /* ! defined (GPOPT) */ - /* We are not optimizing for the GP register. */ - change = 1; -#endif /* ! defined (GPOPT) */ + change = nopic_need_relax (fragp->fr_symbol); } else if (mips_pic == SVR4_PIC) {