si->tc_segment_info_data.micromips = mips_opts.micromips;
}
+/* Read a standard MIPS instruction from BUF. */
+
+static unsigned long
+read_insn (char *buf)
+{
+ if (target_big_endian)
+ return bfd_getb32 ((bfd_byte *) buf);
+ else
+ return bfd_getl32 ((bfd_byte *) buf);
+}
+
+/* Write standard MIPS instruction INSN to BUF. Return a pointer to
+ the next byte. */
+
+static char *
+write_insn (char *buf, unsigned int insn)
+{
+ md_number_to_chars (buf, insn, 4);
+ return buf + 4;
+}
+
+/* Read a microMIPS or MIPS16 opcode from BUF, given that it
+ has length LENGTH. */
+
+static unsigned long
+read_compressed_insn (char *buf, unsigned int length)
+{
+ unsigned long insn;
+ unsigned int i;
+
+ insn = 0;
+ for (i = 0; i < length; i += 2)
+ {
+ insn <<= 16;
+ if (target_big_endian)
+ insn |= bfd_getb16 ((char *) buf);
+ else
+ insn |= bfd_getl16 ((char *) buf);
+ buf += 2;
+ }
+ return insn;
+}
+
/* Write microMIPS or MIPS16 instruction INSN to BUF, given that the
instruction is LENGTH bytes long. Return a pointer to the next byte. */
if (HAVE_CODE_COMPRESSION)
write_compressed_insn (f, insn->insn_opcode, insn_length (insn));
else
- md_number_to_chars (f, insn->insn_opcode, 4);
+ write_insn (f, insn->insn_opcode);
mips_record_compressed_mode ();
}
void
md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
{
- bfd_byte *buf;
+ char *buf;
long insn;
reloc_howto_type *howto;
|| fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY
|| fixP->fx_r_type == BFD_RELOC_MIPS_TLS_DTPREL64);
- buf = (bfd_byte *) (fixP->fx_frag->fr_literal + fixP->fx_where);
+ buf = fixP->fx_frag->fr_literal + fixP->fx_where;
gas_assert (!fixP->fx_pcrel || fixP->fx_r_type == BFD_RELOC_16_PCREL_S2
|| fixP->fx_r_type == BFD_RELOC_MICROMIPS_7_PCREL_S1
if (fixP->fx_done)
{
if (8 <= sizeof (valueT))
- md_number_to_chars ((char *) buf, *valP, 8);
+ md_number_to_chars (buf, *valP, 8);
else
{
valueT hiv;
hiv = 0xffffffff;
else
hiv = 0;
- md_number_to_chars ((char *)(buf + (target_big_endian ? 4 : 0)),
- *valP, 4);
- md_number_to_chars ((char *)(buf + (target_big_endian ? 0 : 4)),
- hiv, 4);
+ md_number_to_chars (buf + (target_big_endian ? 4 : 0), *valP, 4);
+ md_number_to_chars (buf + (target_big_endian ? 0 : 4), hiv, 4);
}
}
break;
value now. This can happen if we have a .word which is not
resolved when it appears but is later defined. */
if (fixP->fx_done)
- md_number_to_chars ((char *) buf, *valP, fixP->fx_size);
+ md_number_to_chars (buf, *valP, fixP->fx_size);
break;
case BFD_RELOC_LO16:
of endianness. */
if (target_big_endian || fixP->fx_r_type == BFD_RELOC_MICROMIPS_LO16)
buf += 2;
- md_number_to_chars ((char *) buf, *valP, 2);
+ md_number_to_chars (buf, *valP, 2);
}
break;
break;
/* Update old instruction data. */
- if (target_big_endian)
- insn = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
- else
- insn = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
+ insn = read_insn (buf);
if (*valP + 0x20000 <= 0x3ffff)
{
insn |= (*valP >> 2) & 0xffff;
- md_number_to_chars ((char *) buf, insn, 4);
+ write_insn (buf, insn);
}
else if (mips_pic == NO_PIC
&& fixP->fx_done
fixP->fx_done = 0;
fixP->fx_addsy = section_symbol (text_section);
*valP += md_pcrel_from (fixP);
- md_number_to_chars ((char *) buf, insn, 4);
+ write_insn (buf, insn);
}
else
{
{
if (RELAX_BRANCH_P (fragp->fr_subtype))
{
- bfd_byte *buf;
+ char *buf;
unsigned long insn;
expressionS exp;
fixS *fixp;
- buf = (bfd_byte *)fragp->fr_literal + fragp->fr_fix;
-
- if (target_big_endian)
- insn = bfd_getb32 (buf);
- else
- insn = bfd_getl32 (buf);
+ buf = fragp->fr_literal + fragp->fr_fix;
+ insn = read_insn (buf);
if (!RELAX_BRANCH_TOOFAR (fragp->fr_subtype))
{
exp.X_add_symbol = fragp->fr_symbol;
exp.X_add_number = fragp->fr_offset;
- fixp = fix_new_exp (fragp, buf - (bfd_byte *)fragp->fr_literal,
- 4, &exp, TRUE, BFD_RELOC_16_PCREL_S2);
+ fixp = fix_new_exp (fragp, buf - fragp->fr_literal, 4, &exp, TRUE,
+ BFD_RELOC_16_PCREL_S2);
fixp->fx_file = fragp->fr_file;
fixp->fx_line = fragp->fr_line;
- md_number_to_chars ((char *) buf, insn, 4);
- buf += 4;
+ buf = write_insn (buf, insn);
}
else
{
else
{
/* How many bytes in instructions we've already emitted? */
- i = buf - (bfd_byte *)fragp->fr_literal - fragp->fr_fix;
+ i = buf - fragp->fr_literal - fragp->fr_fix;
/* How many bytes in instructions from here to the end? */
i = fragp->fr_var - i;
}
i--;
insn |= i;
/* Branch over the jump. */
- md_number_to_chars ((char *) buf, insn, 4);
- buf += 4;
+ buf = write_insn (buf, insn);
/* nop */
- md_number_to_chars ((char *) buf, 0, 4);
- buf += 4;
+ buf = write_insn (buf, 0);
if (RELAX_BRANCH_LIKELY (fragp->fr_subtype))
{
/* Compute the PC offset from the current instruction to
the end of the variable frag. */
/* How many bytes in instructions we've already emitted? */
- i = buf - (bfd_byte *)fragp->fr_literal - fragp->fr_fix;
+ i = buf - fragp->fr_literal - fragp->fr_fix;
/* How many bytes in instructions from here to the end? */
i = fragp->fr_var - i;
/* Convert to instruction count. */
i >>= 2;
/* Don't decrement i, because we want to branch over the
delay slot. */
-
insn |= i;
- md_number_to_chars ((char *) buf, insn, 4);
- buf += 4;
- md_number_to_chars ((char *) buf, 0, 4);
- buf += 4;
+ buf = write_insn (buf, insn);
+ buf = write_insn (buf, 0);
}
uncond:
exp.X_add_symbol = fragp->fr_symbol;
exp.X_add_number = fragp->fr_offset;
- fixp = fix_new_exp (fragp, buf - (bfd_byte *)fragp->fr_literal,
- 4, &exp, FALSE, BFD_RELOC_MIPS_JMP);
+ fixp = fix_new_exp (fragp, buf - fragp->fr_literal, 4, &exp,
+ FALSE, BFD_RELOC_MIPS_JMP);
fixp->fx_file = fragp->fr_file;
fixp->fx_line = fragp->fr_line;
- md_number_to_chars ((char *) buf, insn, 4);
- buf += 4;
+ buf = write_insn (buf, insn);
}
else
{
exp.X_add_number = 0;
}
- fixp = fix_new_exp (fragp, buf - (bfd_byte *)fragp->fr_literal,
- 4, &exp, FALSE, BFD_RELOC_MIPS_GOT16);
+ fixp = fix_new_exp (fragp, buf - fragp->fr_literal, 4, &exp,
+ FALSE, BFD_RELOC_MIPS_GOT16);
fixp->fx_file = fragp->fr_file;
fixp->fx_line = fragp->fr_line;
- md_number_to_chars ((char *) buf, insn, 4);
- buf += 4;
+ buf = write_insn (buf, insn);
if (mips_opts.isa == ISA_MIPS1)
- {
- /* nop */
- md_number_to_chars ((char *) buf, 0, 4);
- buf += 4;
- }
+ /* nop */
+ buf = write_insn (buf, 0);
/* d/addiu $at, $at, <sym> R_MIPS_LO16 */
insn = HAVE_64BIT_ADDRESSES ? 0x64000000 : 0x24000000;
insn |= at << OP_SH_RS | at << OP_SH_RT;
- fixp = fix_new_exp (fragp, buf - (bfd_byte *)fragp->fr_literal,
- 4, &exp, FALSE, BFD_RELOC_LO16);
+ fixp = fix_new_exp (fragp, buf - fragp->fr_literal, 4, &exp,
+ FALSE, BFD_RELOC_LO16);
fixp->fx_file = fragp->fr_file;
fixp->fx_line = fragp->fr_line;
- md_number_to_chars ((char *) buf, insn, 4);
- buf += 4;
+ buf = write_insn (buf, insn);
/* j(al)r $at. */
if (RELAX_BRANCH_LINK (fragp->fr_subtype))
insn = 0x00000008;
insn |= at << OP_SH_RS;
- md_number_to_chars ((char *) buf, insn, 4);
- buf += 4;
+ buf = write_insn (buf, insn);
}
}
- gas_assert (buf == (bfd_byte *)fragp->fr_literal
- + fragp->fr_fix + fragp->fr_var);
-
fragp->fr_fix += fragp->fr_var;
-
+ gas_assert (buf == fragp->fr_literal + fragp->fr_fix);
return;
}
/* Relax microMIPS branches. */
if (RELAX_MICROMIPS_P (fragp->fr_subtype))
{
- bfd_byte *buf = (bfd_byte *) (fragp->fr_literal + fragp->fr_fix);
+ char *buf = fragp->fr_literal + fragp->fr_fix;
bfd_boolean compact = RELAX_MICROMIPS_COMPACT (fragp->fr_subtype);
bfd_boolean al = RELAX_MICROMIPS_LINK (fragp->fr_subtype);
int type = RELAX_MICROMIPS_TYPE (fragp->fr_subtype);
because if there is linker relaxation, we're going to
need the relocations. */
if (type == 'D')
- fixp = fix_new_exp (fragp,
- buf - (bfd_byte *) fragp->fr_literal,
- 2, &exp, TRUE,
+ fixp = fix_new_exp (fragp, buf - fragp->fr_literal, 2, &exp, TRUE,
BFD_RELOC_MICROMIPS_10_PCREL_S1);
else if (type == 'E')
- fixp = fix_new_exp (fragp,
- buf - (bfd_byte *) fragp->fr_literal,
- 2, &exp, TRUE,
+ fixp = fix_new_exp (fragp, buf - fragp->fr_literal, 2, &exp, TRUE,
BFD_RELOC_MICROMIPS_7_PCREL_S1);
else
abort ();
/* We generate a fixup instead of applying it right now,
because if there is linker relaxation, we're going to
need the relocations. */
- fixp = fix_new_exp (fragp, buf - (bfd_byte *) fragp->fr_literal,
- 4, &exp, TRUE, BFD_RELOC_MICROMIPS_16_PCREL_S1);
+ fixp = fix_new_exp (fragp, buf - fragp->fr_literal, 4, &exp, TRUE,
+ BFD_RELOC_MICROMIPS_16_PCREL_S1);
fixp->fx_file = fragp->fr_file;
fixp->fx_line = fragp->fr_line;
/* Relax 16-bit branches to 32-bit branches. */
if (type != 0)
{
- if (target_big_endian)
- insn = bfd_getb16 (buf);
- else
- insn = bfd_getl16 (buf);
+ insn = read_compressed_insn (buf, 2);
if ((insn & 0xfc00) == 0xcc00) /* b16 */
insn = 0x94000000; /* beq */
if (!RELAX_MICROMIPS_RELAX32 (fragp->fr_subtype)
|| !RELAX_MICROMIPS_TOOFAR32 (fragp->fr_subtype))
{
- md_number_to_chars ((char *) buf, insn >> 16, 2);
- buf += 2;
- md_number_to_chars ((char *) buf, insn & 0xffff, 2);
- buf += 2;
-
- gas_assert (buf == ((bfd_byte *) fragp->fr_literal
- + fragp->fr_fix));
+ buf = write_compressed_insn (buf, insn, 4);
+ gas_assert (buf == fragp->fr_literal + fragp->fr_fix);
return;
}
}
else
- {
- unsigned long next;
-
- if (target_big_endian)
- {
- insn = bfd_getb16 (buf);
- next = bfd_getb16 (buf + 2);
- }
- else
- {
- insn = bfd_getl16 (buf);
- next = bfd_getl16 (buf + 2);
- }
- insn = (insn << 16) | next;
- }
+ insn = read_compressed_insn (buf, 4);
/* Relax 32-bit branches to a sequence of instructions. */
as_warn_where (fragp->fr_file, fragp->fr_line,
#endif
/* Refer to it. */
- fixp = fix_new (fragp, buf - (bfd_byte *) fragp->fr_literal,
- 4, l, 0, TRUE, BFD_RELOC_MICROMIPS_16_PCREL_S1);
+ fixp = fix_new (fragp, buf - fragp->fr_literal, 4, l, 0, TRUE,
+ BFD_RELOC_MICROMIPS_16_PCREL_S1);
fixp->fx_file = fragp->fr_file;
fixp->fx_line = fragp->fr_line;
/* Branch over the jump. */
- md_number_to_chars ((char *) buf, insn >> 16, 2);
- buf += 2;
- md_number_to_chars ((char *) buf, insn & 0xffff, 2);
- buf += 2;
-
+ buf = write_compressed_insn (buf, insn, 4);
if (!compact)
- {
- /* nop */
- insn = 0x0c00;
- md_number_to_chars ((char *) buf, insn, 2);
- buf += 2;
- }
+ /* nop */
+ buf = write_compressed_insn (buf, 0x0c00, 2);
}
if (mips_pic == NO_PIC)
/* j/jal/jals <sym> R_MICROMIPS_26_S1 */
insn = al ? jal : 0xd4000000;
- fixp = fix_new_exp (fragp, buf - (bfd_byte *) fragp->fr_literal,
- 4, &exp, FALSE, BFD_RELOC_MICROMIPS_JMP);
+ fixp = fix_new_exp (fragp, buf - fragp->fr_literal, 4, &exp, FALSE,
+ BFD_RELOC_MICROMIPS_JMP);
fixp->fx_file = fragp->fr_file;
fixp->fx_line = fragp->fr_line;
- md_number_to_chars ((char *) buf, insn >> 16, 2);
- buf += 2;
- md_number_to_chars ((char *) buf, insn & 0xffff, 2);
- buf += 2;
-
+ buf = write_compressed_insn (buf, insn, 4);
if (compact)
- {
- /* nop */
- insn = 0x0c00;
- md_number_to_chars ((char *) buf, insn, 2);
- buf += 2;
- }
+ /* nop */
+ buf = write_compressed_insn (buf, 0x0c00, 2);
}
else
{
exp.X_add_number = 0;
}
- fixp = fix_new_exp (fragp, buf - (bfd_byte *) fragp->fr_literal,
- 4, &exp, FALSE, BFD_RELOC_MICROMIPS_GOT16);
+ fixp = fix_new_exp (fragp, buf - fragp->fr_literal, 4, &exp, FALSE,
+ BFD_RELOC_MICROMIPS_GOT16);
fixp->fx_file = fragp->fr_file;
fixp->fx_line = fragp->fr_line;
- md_number_to_chars ((char *) buf, insn >> 16, 2);
- buf += 2;
- md_number_to_chars ((char *) buf, insn & 0xffff, 2);
- buf += 2;
+ buf = write_compressed_insn (buf, insn, 4);
/* d/addiu $at, $at, <sym> R_MICROMIPS_LO16 */
insn = HAVE_64BIT_ADDRESSES ? 0x5c000000 : 0x30000000;
insn |= at << MICROMIPSOP_SH_RT | at << MICROMIPSOP_SH_RS;
- fixp = fix_new_exp (fragp, buf - (bfd_byte *) fragp->fr_literal,
- 4, &exp, FALSE, BFD_RELOC_MICROMIPS_LO16);
+ fixp = fix_new_exp (fragp, buf - fragp->fr_literal, 4, &exp, FALSE,
+ BFD_RELOC_MICROMIPS_LO16);
fixp->fx_file = fragp->fr_file;
fixp->fx_line = fragp->fr_line;
- md_number_to_chars ((char *) buf, insn >> 16, 2);
- buf += 2;
- md_number_to_chars ((char *) buf, insn & 0xffff, 2);
- buf += 2;
+ buf = write_compressed_insn (buf, insn, 4);
/* jr/jrc/jalr/jalrs $at */
insn = al ? jalr : jr;
insn |= at << MICROMIPSOP_SH_MJ;
- md_number_to_chars ((char *) buf, insn & 0xffff, 2);
- buf += 2;
+ buf = write_compressed_insn (buf, insn, 2);
}
- gas_assert (buf == (bfd_byte *) fragp->fr_literal + fragp->fr_fix);
+ gas_assert (buf == fragp->fr_literal + fragp->fr_fix);
return;
}
buf = fragp->fr_literal + fragp->fr_fix;
- if (target_big_endian)
- insn = bfd_getb16 ((bfd_byte *) buf);
- else
- insn = bfd_getl16 ((bfd_byte *) buf);
-
+ insn = read_compressed_insn (buf, 2);
if (ext)
insn |= MIPS16_EXTEND;
case 2:
if (nop_opcode == NOP_OPCODE_MICROMIPS)
{
- md_number_to_chars (p, micromips_nop16_insn.insn_opcode, 2);
- p += 2;
+ p = write_compressed_insn (p, micromips_nop16_insn.insn_opcode, 2);
break;
}
*p++ = '\0';