X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gas%2Fconfig%2Ftc-mips.c;h=f58955c5232d99129a71b53f674189de4f55315d;hb=a4968f42e78972fa10b1a84a5e72afd4b65b0eca;hp=b596b8bb0b1f91a8a798833a3dce309be8c7de4a;hpb=325801bda4678d100721414300eb1170bfbc2e24;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c index b596b8bb0b..f58955c523 100644 --- a/gas/config/tc-mips.c +++ b/gas/config/tc-mips.c @@ -349,7 +349,7 @@ static int mips_32bitmode = 0; /* Likewise 64-bit registers. */ #define ABI_NEEDS_64BIT_REGS(ABI) \ - ((ABI) == N32_ABI \ + ((ABI) == N32_ABI \ || (ABI) == N64_ABI \ || (ABI) == O64_ABI) @@ -1017,7 +1017,7 @@ static int mips_relax_branch; /* Branch without likely bit. If label is out of range, we turn: - beq reg1, reg2, label + beq reg1, reg2, label delay slot into @@ -1410,6 +1410,8 @@ enum options OPTION_NO_SMARTMIPS, OPTION_DSPR2, OPTION_NO_DSPR2, + OPTION_DSPR3, + OPTION_NO_DSPR3, OPTION_EVA, OPTION_NO_EVA, OPTION_XPA, @@ -1522,6 +1524,8 @@ struct option md_longopts[] = {"mno-smartmips", no_argument, NULL, OPTION_NO_SMARTMIPS}, {"mdspr2", no_argument, NULL, OPTION_DSPR2}, {"mno-dspr2", no_argument, NULL, OPTION_NO_DSPR2}, + {"mdspr3", no_argument, NULL, OPTION_DSPR3}, + {"mno-dspr3", no_argument, NULL, OPTION_NO_DSPR3}, {"meva", no_argument, NULL, OPTION_EVA}, {"mno-eva", no_argument, NULL, OPTION_NO_EVA}, {"mmicromips", no_argument, NULL, OPTION_MICROMIPS}, @@ -1663,6 +1667,11 @@ static const struct mips_ase mips_ases[] = { 2, 2, 2, 2, -1 }, + { "dspr3", ASE_DSP | ASE_DSPR2 | ASE_DSPR3, 0, + OPTION_DSPR3, OPTION_NO_DSPR3, + 6, 6, -1, -1, + -1 }, + { "eva", ASE_EVA, 0, OPTION_EVA, OPTION_NO_EVA, 2, 2, 2, 2, @@ -1716,7 +1725,7 @@ static const struct mips_ase mips_ases[] = { /* Groups of ASE_* flags that represent different revisions of an ASE. */ static const unsigned int mips_ase_groups[] = { - ASE_DSP | ASE_DSPR2 + ASE_DSP | ASE_DSPR2 | ASE_DSPR3 }; /* Pseudo-op table. @@ -3601,21 +3610,20 @@ md_begin (void) for (i = 0; i < 32; i++) { - char regname[7]; + char regname[6]; /* R5900 VU0 floating-point register. */ - regname[sizeof (rename) - 1] = 0; - snprintf (regname, sizeof (regname) - 1, "$vf%d", i); + sprintf (regname, "$vf%d", i); symbol_table_insert (symbol_new (regname, reg_section, RTYPE_VF | i, &zero_address_frag)); /* R5900 VU0 integer register. */ - snprintf (regname, sizeof (regname) - 1, "$vi%d", i); + sprintf (regname, "$vi%d", i); symbol_table_insert (symbol_new (regname, reg_section, RTYPE_VI | i, &zero_address_frag)); /* MSA register. */ - snprintf (regname, sizeof (regname) - 1, "$w%d", i); + sprintf (regname, "$w%d", i); symbol_table_insert (symbol_new (regname, reg_section, RTYPE_MSA | i, &zero_address_frag)); } @@ -3850,7 +3858,7 @@ mips_check_options (struct mips_set_options *opts, bfd_boolean abi_checks) if (abi_checks && ABI_NEEDS_64BIT_REGS (mips_abi)) as_warn (_("`fp=32' used with a 64-bit ABI")); - if (ISA_IS_R6 (mips_opts.isa) && opts->single_float == 0) + if (ISA_IS_R6 (opts->isa) && opts->single_float == 0) as_bad (_("`fp=32' used with a MIPS R6 cpu")); break; default: @@ -3862,13 +3870,13 @@ mips_check_options (struct mips_set_options *opts, bfd_boolean abi_checks) as_bad (_("`nooddspreg` cannot be used with a 64-bit ABI")); if (opts->micromips == 1 && opts->mips16 == 1) - as_bad (_("`mips16' cannot be used with `micromips'")); - else if (ISA_IS_R6 (mips_opts.isa) + as_bad (_("`%s' cannot be used with `%s'"), "mips16", "micromips"); + else if (ISA_IS_R6 (opts->isa) && (opts->micromips == 1 || opts->mips16 == 1)) - as_fatal (_("`%s' can not be used with `%s'"), + as_fatal (_("`%s' cannot be used with `%s'"), opts->micromips ? "micromips" : "mips16", - mips_cpu_info_from_isa (mips_opts.isa)->name); + mips_cpu_info_from_isa (opts->isa)->name); if (ISA_IS_R6 (opts->isa) && mips_relax_branch) as_fatal (_("branch relaxation is not supported in `%s'"), @@ -6265,8 +6273,8 @@ nops_for_vr4130 (int ignore, const struct mips_cl_insn *hist, return 0; } -#define BASE_REG_EQ(INSN1, INSN2) \ - ((((INSN1) >> OP_SH_RS) & OP_MASK_RS) \ +#define BASE_REG_EQ(INSN1, INSN2) \ + ((((INSN1) >> OP_SH_RS) & OP_MASK_RS) \ == (((INSN2) >> OP_SH_RS) & OP_MASK_RS)) /* Return the minimum alignment for this store instruction. */ @@ -6733,11 +6741,11 @@ can_swap_branch_p (struct mips_cl_insn *ip, expressionS *address_expr, /* Parameter must be 16 bit. */ && (*reloc_type == BFD_RELOC_16_PCREL_S2) /* Branch to same segment. */ - && (S_GET_SEGMENT(address_expr->X_add_symbol) == now_seg) + && (S_GET_SEGMENT (address_expr->X_add_symbol) == now_seg) /* Branch to same code fragment. */ - && (symbol_get_frag(address_expr->X_add_symbol) == frag_now) + && (symbol_get_frag (address_expr->X_add_symbol) == frag_now) /* Can only calculate branch offset if value is known. */ - && symbol_constant_p(address_expr->X_add_symbol) + && symbol_constant_p (address_expr->X_add_symbol) /* Check if branch is really conditional. */ && !((ip->insn_opcode & 0xffff0000) == 0x10000000 /* beq $0,$0 */ || (ip->insn_opcode & 0xffff0000) == 0x04010000 /* bgez $0 */ @@ -6746,7 +6754,7 @@ can_swap_branch_p (struct mips_cl_insn *ip, expressionS *address_expr, int distance; /* Check if loop is shorter than 6 instructions including branch and delay slot. */ - distance = frag_now_fix() - S_GET_VALUE(address_expr->X_add_symbol); + distance = frag_now_fix () - S_GET_VALUE (address_expr->X_add_symbol); if (distance <= 20) { int i; @@ -6758,7 +6766,7 @@ can_swap_branch_p (struct mips_cl_insn *ip, expressionS *address_expr, for (i = 0; i < (distance / 4); i++) { if ((history[i].cleared_p) - || delayed_branch_p(&history[i])) + || delayed_branch_p (&history[i])) { rv = TRUE; break; @@ -7036,7 +7044,9 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr, { int shift; - shift = mips_opts.micromips ? 1 : 2; + /* Shift is 2, unusually, for microMIPS JALX. */ + shift = (mips_opts.micromips + && strcmp (ip->insn_mo->name, "jalx") != 0) ? 1 : 2; if ((address_expr->X_add_number & ((1 << shift) - 1)) != 0) as_bad (_("jump to misaligned address (0x%lx)"), (unsigned long) address_expr->X_add_number); @@ -11036,7 +11046,7 @@ macro (struct mips_cl_insn *ip, char *str) if (mips_opts.noreorder) macro_build (NULL, "nop", ""); expr1.X_add_number = mips_cprestore_offset; - macro_build_ldst_constoffset (&expr1, ADDRESS_LOAD_INSN, + macro_build_ldst_constoffset (&expr1, ADDRESS_LOAD_INSN, mips_gp_register, mips_frame_reg, HAVE_64BIT_ADDRESSES); @@ -11180,7 +11190,7 @@ macro (struct mips_cl_insn *ip, char *str) if (mips_opts.noreorder) macro_build (NULL, "nop", ""); expr1.X_add_number = mips_cprestore_offset; - macro_build_ldst_constoffset (&expr1, ADDRESS_LOAD_INSN, + macro_build_ldst_constoffset (&expr1, ADDRESS_LOAD_INSN, mips_gp_register, mips_frame_reg, HAVE_64BIT_ADDRESSES); @@ -12137,8 +12147,8 @@ macro (struct mips_cl_insn *ip, char *str) && offset_expr.X_add_number == 0); s = segment_name (S_GET_SEGMENT (offset_expr.X_add_symbol)); if (strcmp (s, ".lit8") == 0) - { - op[2] = mips_gp_register; + { + op[2] = mips_gp_register; offset_reloc[0] = BFD_RELOC_MIPS_LITERAL; offset_reloc[1] = BFD_RELOC_UNUSED; offset_reloc[2] = BFD_RELOC_UNUSED; @@ -12160,7 +12170,7 @@ macro (struct mips_cl_insn *ip, char *str) offset_reloc[0] = BFD_RELOC_LO16; offset_reloc[1] = BFD_RELOC_UNUSED; offset_reloc[2] = BFD_RELOC_UNUSED; - } + } align = 8; /* Fall through */ @@ -15472,20 +15482,22 @@ s_option (int x ATTRIBUTE_UNUSED) { /* FIXME: What does this mean? */ } - else if (strncmp (opt, "pic", 3) == 0) + else if (strncmp (opt, "pic", 3) == 0 && ISDIGIT (opt[3]) && opt[4] == '\0') { int i; i = atoi (opt + 3); - if (i == 0) + if (i != 0 && i != 2) + as_bad (_(".option pic%d not supported"), i); + else if (mips_pic == VXWORKS_PIC) + as_bad (_(".option pic%d not supported in VxWorks PIC mode"), i); + else if (i == 0) mips_pic = NO_PIC; else if (i == 2) { mips_pic = SVR4_PIC; mips_abicalls = TRUE; } - else - as_bad (_(".option pic%d not supported"), i); if (mips_pic == SVR4_PIC) { @@ -15512,10 +15524,29 @@ struct mips_option_stack static struct mips_option_stack *mips_opts_stack; -static bfd_boolean +/* Return status for .set/.module option handling. */ + +enum code_option_type +{ + /* Unrecognized option. */ + OPTION_TYPE_BAD = -1, + + /* Ordinary option. */ + OPTION_TYPE_NORMAL, + + /* ISA changing option. */ + OPTION_TYPE_ISA +}; + +/* Handle common .set/.module options. Return status indicating option + type. */ + +static enum code_option_type parse_code_option (char * name) { + bfd_boolean isa_set = FALSE; const struct mips_ase *ase; + if (strncmp (name, "at=", 3) == 0) { char *s = name + 3; @@ -15588,6 +15619,7 @@ parse_code_option (char * name) { mips_opts.arch = p->cpu; mips_opts.isa = p->isa; + isa_set = TRUE; } } else if (strncmp (name, "mips", 4) == 0) @@ -15601,6 +15633,7 @@ parse_code_option (char * name) { mips_opts.arch = p->cpu; mips_opts.isa = p->isa; + isa_set = TRUE; } } else @@ -15619,8 +15652,9 @@ parse_code_option (char * name) else if (strcmp (name, "nosym32") == 0) mips_opts.sym32 = FALSE; else - return FALSE; - return TRUE; + return OPTION_TYPE_BAD; + + return isa_set ? OPTION_TYPE_ISA : OPTION_TYPE_NORMAL; } /* Handle the .set pseudo-op. */ @@ -15628,8 +15662,8 @@ parse_code_option (char * name) static void s_mipsset (int x ATTRIBUTE_UNUSED) { + enum code_option_type type = OPTION_TYPE_NORMAL; char *name = input_line_pointer, ch; - int prev_isa = mips_opts.isa; file_mips_check_options (); @@ -15706,12 +15740,16 @@ s_mipsset (int x ATTRIBUTE_UNUSED) free (s); } } - else if (!parse_code_option (name)) - as_warn (_("tried to set unrecognized symbol: %s\n"), name); + else + { + type = parse_code_option (name); + if (type == OPTION_TYPE_BAD) + as_warn (_("tried to set unrecognized symbol: %s\n"), name); + } /* The use of .set [arch|cpu]= historically 'fixes' the width of gp and fp registers based on what is supported by the arch/cpu. */ - if (mips_opts.isa != prev_isa) + if (type == OPTION_TYPE_ISA) { switch (mips_opts.isa) { @@ -15778,7 +15816,7 @@ s_module (int ignore ATTRIBUTE_UNUSED) if (!file_mips_opts_checked) { - if (!parse_code_option (name)) + if (parse_code_option (name) == OPTION_TYPE_BAD) as_bad (_(".module used with unrecognized symbol: %s\n"), name); /* Update module level settings from mips_opts. */ @@ -16413,7 +16451,7 @@ s_nan (int ignore ATTRIBUTE_UNUSED) directive, such as in: foo: - .stabs ... + .stabs ... .set mips16 so the current mode wins. */ @@ -16796,6 +16834,7 @@ relaxed_branch_length (fragS *fragp, asection *sec, int update) if (fragp && S_IS_DEFINED (fragp->fr_symbol) + && !S_IS_WEAK (fragp->fr_symbol) && sec == S_GET_SEGMENT (fragp->fr_symbol)) { addressT addr; @@ -16809,12 +16848,9 @@ relaxed_branch_length (fragS *fragp, asection *sec, int update) toofar = val < - (0x8000 << 2) || val >= (0x8000 << 2); } - else if (fragp) - /* If the symbol is not defined or it's in a different segment, - assume the user knows what's going on and emit a short - branch. */ - toofar = FALSE; else + /* If the symbol is not defined or it's in a different segment, + we emit the long sequence. */ toofar = TRUE; if (fragp && update && toofar != RELAX_BRANCH_TOOFAR (fragp->fr_subtype)) @@ -16862,6 +16898,7 @@ relaxed_micromips_32bit_branch_length (fragS *fragp, asection *sec, int update) if (fragp && S_IS_DEFINED (fragp->fr_symbol) + && !S_IS_WEAK (fragp->fr_symbol) && sec == S_GET_SEGMENT (fragp->fr_symbol)) { addressT addr; @@ -16879,12 +16916,9 @@ relaxed_micromips_32bit_branch_length (fragS *fragp, asection *sec, int update) toofar = val < - (0x8000 << 1) || val >= (0x8000 << 1); } - else if (fragp) - /* If the symbol is not defined or it's in a different segment, - assume the user knows what's going on and emit a short - branch. */ - toofar = FALSE; else + /* If the symbol is not defined or it's in a different segment, + we emit the long sequence. */ toofar = TRUE; if (fragp && update @@ -16956,6 +16990,7 @@ relaxed_micromips_16bit_branch_length (fragS *fragp, asection *sec, int update) if (fragp && S_IS_DEFINED (fragp->fr_symbol) + && !S_IS_WEAK (fragp->fr_symbol) && sec == S_GET_SEGMENT (fragp->fr_symbol)) { addressT addr; @@ -17192,6 +17227,15 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp) Relocations want only the symbol offset. */ reloc->addend = fixp->fx_addnumber + reloc->address; } + else if (HAVE_IN_PLACE_ADDENDS + && fixp->fx_r_type == BFD_RELOC_MICROMIPS_JMP + && (read_compressed_insn (fixp->fx_frag->fr_literal + + fixp->fx_where, 4) >> 26) == 0x3c) + { + /* Shift is 2, unusually, for microMIPS JALX. Adjust the in-place + addend accordingly. */ + reloc->addend = fixp->fx_addnumber >> 1; + } else reloc->addend = fixp->fx_addnumber; @@ -17930,6 +17974,8 @@ mips_convert_ase_flags (int ase) ext_ases |= AFL_ASE_DSP; if (ase & ASE_DSPR2) ext_ases |= AFL_ASE_DSPR2; + if (ase & ASE_DSPR3) + ext_ases |= AFL_ASE_DSPR3; if (ase & ASE_EVA) ext_ases |= AFL_ASE_EVA; if (ase & ASE_MCU) @@ -18679,7 +18725,7 @@ static const struct mips_cpu_info mips_cpu_info_table[] = { "m5100", 0, ASE_MCU, ISA_MIPS32R5, CPU_MIPS32R5 }, { "m5101", 0, ASE_MCU, ISA_MIPS32R5, CPU_MIPS32R5 }, /* P5600 with EVA and Virtualization ASEs, other ASEs are optional. */ - { "p5600", 0, ASE_VIRT | ASE_EVA | ASE_XPA, ISA_MIPS32R5, CPU_MIPS32R5 }, + { "p5600", 0, ASE_VIRT | ASE_EVA | ASE_XPA, ISA_MIPS32R5, CPU_MIPS32R5 }, /* MIPS 64 */ { "5kc", 0, 0, ISA_MIPS64, CPU_MIPS64 }, @@ -18710,8 +18756,9 @@ static const struct mips_cpu_info mips_cpu_info_table[] = MIPS64R2 rather than MIPS64. */ { "xlp", 0, 0, ISA_MIPS64R2, CPU_XLR }, - /* i6400. */ + /* MIPS 64 Release 6 */ { "i6400", 0, ASE_MSA, ISA_MIPS64R6, CPU_MIPS64R6}, + { "p6600", 0, ASE_VIRT | ASE_MSA, ISA_MIPS64R6, CPU_MIPS64R6}, /* End marker */ { NULL, 0, 0, 0, 0 } @@ -18939,6 +18986,9 @@ MIPS options:\n\ -mdspr2 generate DSP R2 instructions\n\ -mno-dspr2 do not generate DSP R2 instructions\n")); fprintf (stream, _("\ +-mdspr3 generate DSP R3 instructions\n\ +-mno-dspr3 do not generate DSP R3 instructions\n")); + fprintf (stream, _("\ -mmt generate MT instructions\n\ -mno-mt do not generate MT instructions\n")); fprintf (stream, _("\