/* Likewise 64-bit registers. */
#define ABI_NEEDS_64BIT_REGS(ABI) \
- ((ABI) == N32_ABI \
+ ((ABI) == N32_ABI \
|| (ABI) == N64_ABI \
|| (ABI) == O64_ABI)
/* Branch without likely bit. If label is out of range, we turn:
- beq reg1, reg2, label
+ beq reg1, reg2, label
delay slot
into
OPTION_NO_SMARTMIPS,
OPTION_DSPR2,
OPTION_NO_DSPR2,
+ OPTION_DSPR3,
+ OPTION_NO_DSPR3,
OPTION_EVA,
OPTION_NO_EVA,
OPTION_XPA,
{"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},
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,
/* 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
};
\f
/* Pseudo-op table.
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));
}
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:
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'"),
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. */
/* 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 */
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;
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;
{
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);
if (hi_fixup == 0
|| !fixup_has_matching_lo_p (hi_fixup->fixp))
{
- hi_fixup = ((struct mips_hi_fixup *)
- xmalloc (sizeof (struct mips_hi_fixup)));
+ hi_fixup = XNEW (struct mips_hi_fixup);
hi_fixup->next = mips_hi_fixup_list;
mips_hi_fixup_list = hi_fixup;
}
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);
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);
&& 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;
offset_reloc[0] = BFD_RELOC_LO16;
offset_reloc[1] = BFD_RELOC_UNUSED;
offset_reloc[2] = BFD_RELOC_UNUSED;
- }
+ }
align = 8;
/* Fall through */
{
/* 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)
{
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;
{
mips_opts.arch = p->cpu;
mips_opts.isa = p->isa;
+ isa_set = TRUE;
}
}
else if (strncmp (name, "mips", 4) == 0)
{
mips_opts.arch = p->cpu;
mips_opts.isa = p->isa;
+ isa_set = TRUE;
}
}
else
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. */
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 ();
{
struct mips_option_stack *s;
- s = (struct mips_option_stack *) xmalloc (sizeof *s);
+ s = XNEW (struct mips_option_stack);
s->next = mips_opts_stack;
s->options = mips_opts;
mips_opts_stack = s;
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)
{
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. */
directive, such as in:
foo:
- .stabs ...
+ .stabs ...
.set mips16
so the current mode wins. */
if (fragp
&& S_IS_DEFINED (fragp->fr_symbol)
+ && !S_IS_WEAK (fragp->fr_symbol)
&& sec == S_GET_SEGMENT (fragp->fr_symbol))
{
addressT addr;
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))
if (fragp
&& S_IS_DEFINED (fragp->fr_symbol)
+ && !S_IS_WEAK (fragp->fr_symbol)
&& sec == S_GET_SEGMENT (fragp->fr_symbol))
{
addressT addr;
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
if (fragp
&& S_IS_DEFINED (fragp->fr_symbol)
+ && !S_IS_WEAK (fragp->fr_symbol)
&& sec == S_GET_SEGMENT (fragp->fr_symbol))
{
addressT addr;
bfd_reloc_code_real_type code;
memset (retval, 0, sizeof(retval));
- reloc = retval[0] = (arelent *) xcalloc (1, sizeof (arelent));
- reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
+ reloc = retval[0] = XCNEW (arelent);
+ reloc->sym_ptr_ptr = XNEW (asymbol *);
*reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
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;
struct insn_label_list *l;
if (free_insn_labels == NULL)
- l = (struct insn_label_list *) xmalloc (sizeof *l);
+ l = XNEW (struct insn_label_list);
else
{
l = free_insn_labels;
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)
if (p && cur_proc_ptr)
{
OBJ_SYMFIELD_TYPE *obj = symbol_get_obj (p);
- expressionS *exp = xmalloc (sizeof (expressionS));
+ expressionS *exp = XNEW (expressionS);
obj->size = exp;
exp->X_op = O_subtract;
{ "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 },
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 }
-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, _("\