/* Clear combination ASE flags, which need to be recalculated based on
updated regular ASE settings. */
- opts->ase &= ~(ASE_MIPS16E2_MT | ASE_XPA_VIRT);
+ opts->ase &= ~(ASE_MIPS16E2_MT | ASE_XPA_VIRT | ASE_EVA_R6);
if (enabled_p)
opts->ase |= ase->flags;
mask |= ASE_MIPS16E2_MT;
}
+ /* The EVA Extension has instructions which are only valid when the R6 ISA
+ is enabled. This sets the ASE_EVA_R6 flag when both EVA and R6 ISA are
+ present. */
+ if (((opts->ase & ASE_EVA) != 0) && ISA_IS_R6 (opts->isa))
+ {
+ opts->ase |= ASE_EVA_R6;
+ mask |= ASE_EVA_R6;
+ }
+
return mask;
}
if (strncmp (TARGET_OS, "elf", 3) != 0
&& strncmp (TARGET_OS, "vxworks", 7) != 0)
{
- (void) bfd_set_section_alignment (stdoutput, text_section, 4);
- (void) bfd_set_section_alignment (stdoutput, data_section, 4);
- (void) bfd_set_section_alignment (stdoutput, bss_section, 4);
+ bfd_set_section_alignment (text_section, 4);
+ bfd_set_section_alignment (data_section, 4);
+ bfd_set_section_alignment (bss_section, 4);
}
/* Create a .reginfo section for register masks and a .mdebug
{
sec = subseg_new (".reginfo", (subsegT) 0);
- bfd_set_section_flags (stdoutput, sec, flags);
- bfd_set_section_alignment (stdoutput, sec, HAVE_NEWABI ? 3 : 2);
+ bfd_set_section_flags (sec, flags);
+ bfd_set_section_alignment (sec, HAVE_NEWABI ? 3 : 2);
mips_regmask_frag = frag_more (sizeof (Elf32_External_RegInfo));
}
/* The 64-bit ABI uses a .MIPS.options section rather than
.reginfo section. */
sec = subseg_new (".MIPS.options", (subsegT) 0);
- bfd_set_section_flags (stdoutput, sec, flags);
- bfd_set_section_alignment (stdoutput, sec, 3);
+ bfd_set_section_flags (sec, flags);
+ bfd_set_section_alignment (sec, 3);
/* Set up the option header. */
{
}
sec = subseg_new (".MIPS.abiflags", (subsegT) 0);
- bfd_set_section_flags (stdoutput, sec,
+ bfd_set_section_flags (sec,
SEC_READONLY | SEC_DATA | SEC_ALLOC | SEC_LOAD);
- bfd_set_section_alignment (stdoutput, sec, 3);
+ bfd_set_section_alignment (sec, 3);
mips_flags_frag = frag_more (sizeof (Elf_External_ABIFlags_v0));
if (ECOFF_DEBUGGING)
{
sec = subseg_new (".mdebug", (subsegT) 0);
- (void) bfd_set_section_flags (stdoutput, sec,
- SEC_HAS_CONTENTS | SEC_READONLY);
- (void) bfd_set_section_alignment (stdoutput, sec, 2);
+ bfd_set_section_flags (sec, SEC_HAS_CONTENTS | SEC_READONLY);
+ bfd_set_section_alignment (sec, 2);
}
else if (mips_flag_pdr)
{
pdr_seg = subseg_new (".pdr", (subsegT) 0);
- (void) bfd_set_section_flags (stdoutput, pdr_seg,
- SEC_READONLY | SEC_RELOC
- | SEC_DEBUGGING);
- (void) bfd_set_section_alignment (stdoutput, pdr_seg, 2);
+ bfd_set_section_flags (pdr_seg,
+ SEC_READONLY | SEC_RELOC | SEC_DEBUGGING);
+ bfd_set_section_alignment (pdr_seg, 2);
}
subseg_set (seg, subseg);
gas_assert (S_GET_SEGMENT (l->label) == now_seg);
symbol_set_frag (l->label, frag_now);
val = (valueT) frag_now_fix ();
- /* MIPS16/microMIPS text labels are stored as odd. */
+ /* MIPS16/microMIPS text labels are stored as odd.
+ We just carry the ISA mode bit forward. */
if (text_p && HAVE_CODE_COMPRESSION)
- ++val;
+ val |= (S_GET_VALUE (l->label) & 0x1);
S_SET_VALUE (l->label, val);
}
}
if (symseg != from_seg && !S_IS_LOCAL (sym))
{
- if ((bfd_get_section_flags (stdoutput, symseg) & SEC_LINK_ONCE))
+ if ((bfd_section_flags (symseg) & SEC_LINK_ONCE))
linkonce = TRUE;
/* The GNU toolchain uses an extension for ELF: a section
beginning with the magic string .gnu.linkonce is a
return FALSE;
if (regno == 0)
- return FALSE;
+ {
+ set_insn_error (arg->argnum, _("the source register must not be $0"));
+ return FALSE;
+ }
arg->last_regno = regno;
insn_insert_operand (arg->insn, operand, regno);
}
new_seg = subseg_new (newname, (subsegT) 0);
- bfd_set_section_flags (stdoutput, new_seg,
+ bfd_set_section_flags (new_seg,
SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_DATA);
frag_align (length == 4 ? 2 : 3, 0, 0);
if (strncmp (TARGET_OS, "elf", 3) != 0)
int imm = 0;
int ust = 0;
int lp = 0;
+ int ll_sc_paired = 0;
bfd_boolean large_offset;
int off;
int hold_mips_optimize;
case M_ADD_I:
s = "addi";
s2 = "add";
- goto do_addi;
+ if (ISA_IS_R6 (mips_opts.isa))
+ goto do_addi_i;
+ else
+ goto do_addi;
case M_ADDU_I:
s = "addiu";
s2 = "addu";
dbl = 1;
s = "daddi";
s2 = "dadd";
- if (!mips_opts.micromips)
+ if (!mips_opts.micromips && !ISA_IS_R6 (mips_opts.isa))
goto do_addi;
if (imm_expr.X_add_number >= -0x200
- && imm_expr.X_add_number < 0x200)
+ && imm_expr.X_add_number < 0x200
+ && !ISA_IS_R6 (mips_opts.isa))
{
macro_build (NULL, s, "t,r,.", op[0], op[1],
(int) imm_expr.X_add_number);
offbits = 12;
lp = 1;
goto ld;
+ case M_LLDP_AB:
+ case M_LLWP_AB:
+ case M_LLWPE_AB:
+ s = ip->insn_mo->name;
+ fmt = "t,d,s";
+ ll_sc_paired = 1;
+ offbits = 0;
+ goto ld;
case M_LWM_AB:
gas_assert (mips_opts.micromips);
s = "lwm";
goto ld_st;
ld:
- /* We don't want to use $0 as tempreg. */
- if (op[2] == op[0] + lp || op[0] + lp == ZERO)
- goto ld_st;
+ /* Try to use one the the load registers to compute the base address.
+ We don't want to use $0 as tempreg. */
+ if (ll_sc_paired)
+ {
+ if ((op[0] == ZERO && op[3] == op[1])
+ || (op[1] == ZERO && op[3] == op[0])
+ || (op[0] == ZERO && op[1] == ZERO))
+ goto ld_st;
+ else if (op[0] != op[3] && op[0] != ZERO)
+ tempreg = op[0];
+ else
+ tempreg = op[1];
+ }
else
- tempreg = op[0] + lp;
+ {
+ if (op[2] == op[0] + lp || op[0] + lp == ZERO)
+ goto ld_st;
+ else
+ tempreg = op[0] + lp;
+ }
goto ld_noat;
case M_SB_AB:
: ISA_IS_R6 (mips_opts.isa) ? 9
: 16);
goto ld_st;
+ case M_SCDP_AB:
+ case M_SCWP_AB:
+ case M_SCWPE_AB:
+ s = ip->insn_mo->name;
+ fmt = "t,d,s";
+ ll_sc_paired = 1;
+ offbits = 0;
+ goto ld_st;
case M_CACHE_AB:
s = "cache";
fmt = (mips_opts.micromips ? "k,~(b)"
ld_st:
tempreg = AT;
ld_noat:
- breg = op[2];
+ breg = ll_sc_paired ? op[3] : op[2];
if (small_offset_p (0, align, 16))
{
/* The first case exists for M_LD_AB and M_SD_AB, which are
else if (small_offset_p (0, align, offbits))
{
if (offbits == 0)
- macro_build (NULL, s, fmt, op[0], breg);
+ {
+ if (ll_sc_paired)
+ macro_build (NULL, s, fmt, op[0], op[1], breg);
+ else
+ macro_build (NULL, s, fmt, op[0], breg);
+ }
else
macro_build (NULL, s, fmt, op[0],
(int) offset_expr.X_add_number, breg);
tempreg, breg, -1, offset_reloc[0],
offset_reloc[1], offset_reloc[2]);
if (offbits == 0)
- macro_build (NULL, s, fmt, op[0], tempreg);
+ {
+ if (ll_sc_paired)
+ macro_build (NULL, s, fmt, op[0], op[1], tempreg);
+ else
+ macro_build (NULL, s, fmt, op[0], tempreg);
+ }
else
macro_build (NULL, s, fmt, op[0], 0, tempreg);
}
if (offset_expr.X_add_number != 0)
macro_build (&offset_expr, ADDRESS_ADDI_INSN,
"t,r,j", tempreg, tempreg, BFD_RELOC_LO16);
- macro_build (NULL, s, fmt, op[0], tempreg);
+ if (ll_sc_paired)
+ macro_build (NULL, s, fmt, op[0], op[1], tempreg);
+ else
+ macro_build (NULL, s, fmt, op[0], tempreg);
}
else if (offbits == 16)
macro_build (&offset_expr, s, fmt, op[0], BFD_RELOC_LO16, tempreg);
macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t",
tempreg, tempreg, breg);
if (offbits == 0)
- macro_build (NULL, s, fmt, op[0], tempreg);
+ {
+ if (ll_sc_paired)
+ macro_build (NULL, s, fmt, op[0], op[1], tempreg);
+ else
+ macro_build (NULL, s, fmt, op[0], tempreg);
+ }
else
macro_build (NULL, s, fmt, op[0], 0, tempreg);
}
OFFSET_EXPR. */
if (imm_expr.X_op == O_constant)
{
- used_at = 1;
- load_register (AT, &imm_expr, FPR_SIZE == 64);
+ tempreg = ZERO;
+ if (((FPR_SIZE == 64 && GPR_SIZE == 64)
+ || !ISA_HAS_MXHC1 (mips_opts.isa))
+ && imm_expr.X_add_number != 0)
+ {
+ used_at = 1;
+ tempreg = AT;
+ load_register (AT, &imm_expr, FPR_SIZE == 64);
+ }
if (FPR_SIZE == 64 && GPR_SIZE == 64)
- macro_build (NULL, "dmtc1", "t,S", AT, op[0]);
+ macro_build (NULL, "dmtc1", "t,S", tempreg, op[0]);
else
{
- if (ISA_HAS_MXHC1 (mips_opts.isa))
- macro_build (NULL, "mthc1", "t,G", AT, op[0]);
- else if (FPR_SIZE != 32)
- as_bad (_("Unable to generate `%s' compliant code "
- "without mthc1"),
- (FPR_SIZE == 64) ? "fp64" : "fpxx");
- else
- macro_build (NULL, "mtc1", "t,G", AT, op[0] + 1);
+ if (!ISA_HAS_MXHC1 (mips_opts.isa))
+ {
+ if (FPR_SIZE != 32)
+ as_bad (_("Unable to generate `%s' compliant code "
+ "without mthc1"),
+ (FPR_SIZE == 64) ? "fp64" : "fpxx");
+ else
+ macro_build (NULL, "mtc1", "t,G", tempreg, op[0] + 1);
+ }
if (offset_expr.X_op == O_absent)
macro_build (NULL, "mtc1", "t,G", 0, op[0]);
else
load_register (AT, &offset_expr, 0);
macro_build (NULL, "mtc1", "t,G", AT, op[0]);
}
+ if (ISA_HAS_MXHC1 (mips_opts.isa))
+ {
+ if (imm_expr.X_add_number != 0)
+ {
+ used_at = 1;
+ tempreg = AT;
+ load_register (AT, &imm_expr, 0);
+ }
+ macro_build (NULL, "mthc1", "t,G", tempreg, op[0]);
+ }
}
break;
}
case M_SUB_I:
s = "addi";
s2 = "sub";
- goto do_subi;
+ if (ISA_IS_R6 (mips_opts.isa))
+ goto do_subi_i;
+ else
+ goto do_subi;
case M_SUBU_I:
s = "addiu";
s2 = "subu";
dbl = 1;
s = "daddi";
s2 = "dsub";
- if (!mips_opts.micromips)
+ if (!mips_opts.micromips && !ISA_IS_R6 (mips_opts.isa))
goto do_subi;
if (imm_expr.X_add_number > -0x200
- && imm_expr.X_add_number <= 0x200)
+ && imm_expr.X_add_number <= 0x200
+ && !ISA_IS_R6 (mips_opts.isa))
{
macro_build (NULL, s, "t,r,.", op[0], op[1],
(int) -imm_expr.X_add_number);
opend = dot != NULL ? dot - name : length;
if (opend >= 3 && name[opend - 2] == '1' && name[opend - 1] == '6')
suffix = 2;
- else if (name[opend - 2] == '3' && name[opend - 1] == '2')
+ else if (opend >= 2 && name[opend - 2] == '3' && name[opend - 1] == '2')
suffix = 4;
else
suffix = 0;
file_mips_opts.isa = arch_info->isa;
file_mips_opts.init_ase = arch_info->ase;
+ /* The EVA Extension has instructions which are only valid when the R6 ISA
+ is enabled. This sets the ASE_EVA_R6 flag when both EVA and R6 ISA are
+ present. */
+ if (((file_mips_opts.ase & ASE_EVA) != 0) && ISA_IS_R6 (file_mips_opts.isa))
+ file_mips_opts.ase |= ASE_EVA_R6;
+
/* Set up initial mips_opts state. */
mips_opts = file_mips_opts;
return (val & 0x3) != isa_bit;
}
+/* Calculate the relocation target by masking off ISA mode bit before
+ combining symbol and addend. */
+
+static valueT
+fix_bad_misaligned_address (fixS *fixP)
+{
+ valueT val;
+ valueT off;
+ unsigned isa_mode;
+ gas_assert (fixP != NULL && fixP->fx_addsy != NULL);
+ val = S_GET_VALUE (fixP->fx_addsy);
+ off = fixP->fx_offset;
+ isa_mode = (ELF_ST_IS_COMPRESSED (S_GET_OTHER (fixP->fx_addsy))
+ ? 1 : 0);
+
+ return ((val & ~isa_mode) + off);
+}
+
/* Make the necessary checks on a regular MIPS branch pointed to by FIXP
and its calculated value VAL. */
else if (fix_bad_misaligned_branch_p (fixP))
as_bad_where (fixP->fx_file, fixP->fx_line,
_("branch to misaligned address (0x%lx)"),
- (long) (S_GET_VALUE (fixP->fx_addsy) + fixP->fx_offset));
+ (long) fix_bad_misaligned_address (fixP));
else if (HAVE_IN_PLACE_ADDENDS && (fixP->fx_offset & 0x3) != 0)
as_bad_where (fixP->fx_file, fixP->fx_line,
_("cannot encode misaligned addend "
else if (fix_bad_misaligned_jump_p (fixP, shift))
as_bad_where (fixP->fx_file, fixP->fx_line,
_("jump to misaligned address (0x%lx)"),
- (long) (S_GET_VALUE (fixP->fx_addsy)
- + fixP->fx_offset));
+ (long) fix_bad_misaligned_address (fixP));
else if (HAVE_IN_PLACE_ADDENDS
&& (fixP->fx_offset & ((1 << shift) - 1)) != 0)
as_bad_where (fixP->fx_file, fixP->fx_line,
&& fixP->fx_done
&& fixP->fx_frag->fr_address >= text_section->vma
&& (fixP->fx_frag->fr_address
- < text_section->vma + bfd_get_section_size (text_section))
+ < text_section->vma + bfd_section_size (text_section))
&& ((insn & 0xffff0000) == 0x10000000 /* beq $0,$0 */
|| (insn & 0xffff0000) == 0x04010000 /* bgez $0 */
|| (insn & 0xffff0000) == 0x04110000)) /* bgezal $0 */
&& (fixP->fx_offset & 0x1) != 0)
as_bad_where (fixP->fx_file, fixP->fx_line,
_("branch to misaligned address (0x%lx)"),
- (long) (S_GET_VALUE (fixP->fx_addsy) + fixP->fx_offset));
+ (long) fix_bad_misaligned_address (fixP));
else if (HAVE_IN_PLACE_ADDENDS && (fixP->fx_offset & 0x1) != 0)
as_bad_where (fixP->fx_file, fixP->fx_line,
_("cannot encode misaligned addend "
else
frag_align (to, fill ? *fill : 0, 0);
record_alignment (now_seg, to);
- mips_move_labels (labels, FALSE);
+ mips_move_labels (labels, subseg_text_p (now_seg));
}
/* Align to a given power of two. .align 0 turns off the automatic
case 'r':
seg = subseg_new (RDATA_SECTION_NAME,
(subsegT) get_absolute_expression ());
- bfd_set_section_flags (stdoutput, seg, (SEC_ALLOC | SEC_LOAD
- | SEC_READONLY | SEC_RELOC
- | SEC_DATA));
+ bfd_set_section_flags (seg, (SEC_ALLOC | SEC_LOAD | SEC_READONLY
+ | SEC_RELOC | SEC_DATA));
if (strncmp (TARGET_OS, "elf", 3) != 0)
record_alignment (seg, 4);
demand_empty_rest_of_line ();
case 's':
seg = subseg_new (".sdata", (subsegT) get_absolute_expression ());
- bfd_set_section_flags (stdoutput, seg,
+ bfd_set_section_flags (seg,
SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA);
if (strncmp (TARGET_OS, "elf", 3) != 0)
record_alignment (seg, 4);
case 'B':
seg = subseg_new (".sbss", (subsegT) get_absolute_expression ());
- bfd_set_section_flags (stdoutput, seg, SEC_ALLOC);
+ bfd_set_section_flags (seg, SEC_ALLOC);
if (strncmp (TARGET_OS, "elf", 3) != 0)
record_alignment (seg, 4);
demand_empty_rest_of_line ();
char *name;
int c;
symbolS *symbolP;
- flagword flag;
do
{
*input_line_pointer = c;
SKIP_WHITESPACE_AFTER_NAME ();
- /* On Irix 5, every global symbol that is not explicitly labelled as
- being a function is apparently labelled as being an object. */
- flag = BSF_OBJECT;
-
if (!is_end_of_line[(unsigned char) *input_line_pointer]
&& (*input_line_pointer != ','))
{
(void) restore_line_pointer (c);
if (sec != NULL && (sec->flags & SEC_CODE) != 0)
- flag = BSF_FUNCTION;
+ symbol_get_bfdsym (symbolP)->flags |= BSF_FUNCTION;
}
- symbol_get_bfdsym (symbolP)->flags |= flag;
-
c = *input_line_pointer;
if (c == ',')
{
demand_empty_rest_of_line ();
}
+#ifdef TE_IRIX
+/* The Irix 5 and 6 assemblers set the type of any common symbol and
+ any undefined non-function symbol to STT_OBJECT. We try to be
+ compatible, since newer Irix 5 and 6 linkers care. */
+
+void
+mips_frob_symbol (symbolS *symp ATTRIBUTE_UNUSED)
+{
+ /* This late in assembly we can set BSF_OBJECT indiscriminately
+ and let elf.c:swap_out_syms sort out the symbol type. */
+ flagword *flags = &symbol_get_bfdsym (symp)->flags;
+ if ((*flags & (BSF_GLOBAL | BSF_WEAK)) != 0
+ || !S_IS_DEFINED (symp))
+ *flags |= BSF_OBJECT;
+}
+#endif
+
static void
s_option (int x ATTRIBUTE_UNUSED)
{
valueT
md_section_align (asection *seg, valueT addr)
{
- int align = bfd_get_section_alignment (stdoutput, seg);
+ int align = bfd_section_alignment (seg);
/* We don't need to align ELF sections to the full alignment.
However, Irix 5 may prefer that we align them at least to a 16
else if ((fragp->fr_offset & 0x1) != 0)
as_bad_where (fragp->fr_file, fragp->fr_line,
_("branch to misaligned address (0x%lx)"),
- (long) val);
+ (long) (resolve_symbol_value (fragp->fr_symbol)
+ + (fragp->fr_offset & ~1)));
}
val = mips16_pcrel_val (fragp, pcrel_op, val, 0);
relax_substateT subtype = fragp->fr_subtype;
bfd_boolean second_longer = (subtype & RELAX_SECOND_LONGER) != 0;
bfd_boolean use_second = (subtype & RELAX_USE_SECOND) != 0;
- int first, second;
+ unsigned int first, second;
fixS *fixp;
first = RELAX_FIRST (subtype);
sequence instead. */
while (fixp
&& fixp->fx_frag == fragp
- && fixp->fx_where < fragp->fr_fix - second)
+ && fixp->fx_where + second < fragp->fr_fix)
{
if (subtype & RELAX_USE_SECOND)
fixp->fx_done = 1;
else
p = NULL;
- if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) == 0)
+ if ((bfd_section_flags (now_seg) & SEC_CODE) == 0)
as_warn (_(".end not in text section"));
if (!cur_proc_ptr)
|| *input_line_pointer == '-')
get_number ();
- if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) == 0)
+ if ((bfd_section_flags (now_seg) & SEC_CODE) == 0)
as_warn (_(".ent or .aent not in text section"));
if (!aent && cur_proc_ptr)
{ "xlp", 0, 0, ISA_MIPS64R2, CPU_XLR },
/* MIPS 64 Release 6. */
- { "i6400", 0, ASE_MSA, ISA_MIPS64R6, CPU_MIPS64R6},
+ { "i6400", 0, ASE_VIRT | ASE_MSA, ISA_MIPS64R6, CPU_MIPS64R6},
+ { "i6500", 0, ASE_VIRT | ASE_MSA | ASE_CRC | ASE_GINV,
+ ISA_MIPS64R6, CPU_MIPS64R6},
{ "p6600", 0, ASE_VIRT | ASE_MSA, ISA_MIPS64R6, CPU_MIPS64R6},
/* End marker. */