* elfxx-mips.h (_bfd_mips_elf_insn32): New prototype.
	* elfxx-mips.c (mips_elf_link_hash_table): Add insn32 member.
	(STUB_MOVE32_MICROMIPS, STUB_JALR32_MICROMIPS): New macros.
	(MICROMIPS_INSN32_FUNCTION_STUB_NORMAL_SIZE): Likewise.
	(MICROMIPS_INSN32_FUNCTION_STUB_BIG_SIZE): Likewise.
	(micromips_insn32_o32_exec_plt0_entry): New variable.
	(micromips_insn32_o32_exec_plt_entry): Likewise.
	(_bfd_mips_elf_adjust_dynamic_symbol): Handle insn32 mode.
	(mips_elf_estimate_stub_size): Likewise.
	(_bfd_mips_elf_size_dynamic_sections): Likewise.
	(_bfd_mips_elf_finish_dynamic_symbol): Likewise.
	(mips_finish_exec_plt): Likewise.
	(_bfd_mips_elf_relax_section): Likewise.
	(_bfd_mips_elf_insn32): New function.
	(_bfd_mips_elf_get_synthetic_symtab): Handle insn32 PLT.

	gas/
	* config/tc-mips.c (mips_set_options): Add insn32 member.
	(mips_opts): Initialize it.
	(NOP_INSN, NOP_INSN_SIZE): Handle insn32 mode.
	(options): Add OPTION_INSN32 and OPTION_NO_INSN32 enum values.
	(md_longopts): Add "minsn32" and "mno-insn32" options.
	(is_size_valid): Handle insn32 mode.
	(md_assemble): Pass instruction string down to macro.
	(brk_fmt): Add second dimension and insn32 mode initializers.
	(mfhl_fmt): Likewise.
	(BRK_FMT, MFHL_FMT): Handle insn32 mode.
	(macro_build) <'c'>: Handle microMIPS 32-bit BREAK encoding.
	(macro_build_jalr, move_register): Handle insn32 mode.
	(macro_build_branch_rs): Likewise.
	(macro): Handle insn32 mode.
	<M_JRADDIUSP>, <M_JRC>, <M_MOVEP>: New cases.
	(mips_ip): Handle insn32 mode.
	(md_parse_option): Handle OPTION_INSN32 and OPTION_NO_INSN32.
	(s_mipsset): Handle "insn32" and "noinsn32" pseudo-ops.
	(mips_handle_align): Handle insn32 mode.
	(md_show_usage): Add -minsn32 and -mno-insn32.

	* doc/as.texinfo (Target MIPS options): Add -minsn32 and
	-mno-insn32 options.
	(-minsn32, -mno-insn32): New options.
	* doc/c-mips.texi (MIPS Opts): Add -minsn32 and -mno-insn32
	options.
	(MIPS assembly options): New node.  Document .set insn32 and
	.set noinsn32.
	(MIPS-Dependent): List the new node.

	gas/testsuite/
	* gas/mips/micromips-insn32.d: New test.
	* gas/mips/micromips-noinsn32.d: Likewise.
	* gas/mips/micromips.l: Rename to...
	* gas/mips/micromips-warn.l: ... this.
	* gas/mips/micromips.d: Update accordingly.
	* gas/mips/micromips-trap.d: Likewise.
	* gas/mips/micromips.l: New list test.
	* gas/mips/micromips.s: Add conditionals.
	* gas/mips/mips.exp: Run the new tests.

	include/opcode/
	* mips.h: Add M_JRADDIUSP, M_JRC and M_MOVEP anonymous enum
	values.

	ld/
	* emultempl/mipself.em (insn32): New variable.
	(mips_create_output_section_statements): Handle insn32 mode.
	(PARSE_AND_LIST_PROLOGUE): New macro.
	(PARSE_AND_LIST_LONGOPTS): Likewise.
	(PARSE_AND_LIST_OPTIONS): Likewise.

	* gen-doc.texi: Set MIPS.
	* ld.texinfo: Likewise.
	(Options specific to MIPS targets): New section.
	(ld and MIPS family): New node.
	(Top, Machine Dependent): List the new node.

	opcodes/
	* micromips-opc.c (micromips_opcodes): Add "jraddiusp", "jrc"
	and "movep" macros.
This commit is contained in:
Maciej W. Rozycki 2013-06-25 18:02:34 +00:00
parent 6e2048d3e3
commit 833794fc12
24 changed files with 16401 additions and 86 deletions

View File

@ -1,3 +1,22 @@
2013-06-25 Maciej W. Rozycki <macro@codesourcery.com>
Paul Brook <paul@codesourcery.com>
* elfxx-mips.h (_bfd_mips_elf_insn32): New prototype.
* elfxx-mips.c (mips_elf_link_hash_table): Add insn32 member.
(STUB_MOVE32_MICROMIPS, STUB_JALR32_MICROMIPS): New macros.
(MICROMIPS_INSN32_FUNCTION_STUB_NORMAL_SIZE): Likewise.
(MICROMIPS_INSN32_FUNCTION_STUB_BIG_SIZE): Likewise.
(micromips_insn32_o32_exec_plt0_entry): New variable.
(micromips_insn32_o32_exec_plt_entry): Likewise.
(_bfd_mips_elf_adjust_dynamic_symbol): Handle insn32 mode.
(mips_elf_estimate_stub_size): Likewise.
(_bfd_mips_elf_size_dynamic_sections): Likewise.
(_bfd_mips_elf_finish_dynamic_symbol): Likewise.
(mips_finish_exec_plt): Likewise.
(_bfd_mips_elf_relax_section): Likewise.
(_bfd_mips_elf_insn32): New function.
(_bfd_mips_elf_get_synthetic_symtab): Handle insn32 PLT.
2013-06-24 Maciej W. Rozycki <macro@codesourcery.com>
* elfxx-mips.h (_bfd_mips_elf_get_synthetic_symtab): New

View File

@ -437,6 +437,9 @@ struct mips_elf_link_hash_table
/* True if we can generate copy relocs and PLTs. */
bfd_boolean use_plts_and_copy_relocs;
/* True if we can only use 32-bit microMIPS instructions. */
bfd_boolean insn32;
/* True if we're generating code for VxWorks. */
bfd_boolean is_vxworks;
@ -904,9 +907,14 @@ static bfd *reldyn_sorting_bfd;
? 0xdf3c8010 /* ld t9,0x8010(gp) */ \
: 0xff3c8010) /* lw t9,0x8010(gp) */
#define STUB_MOVE_MICROMIPS 0x0dff /* move t7,ra */
#define STUB_MOVE32_MICROMIPS(abfd) \
(ABI_64_P (abfd) \
? 0x581f7950 /* daddu t7,ra,zero */ \
: 0x001f7950) /* addu t7,ra,zero */
#define STUB_LUI_MICROMIPS(VAL) \
(0x41b80000 + (VAL)) /* lui t8,VAL */
#define STUB_JALR_MICROMIPS 0x45d9 /* jalr t9 */
#define STUB_JALR32_MICROMIPS 0x03f90f3c /* jalr ra,t9 */
#define STUB_ORI_MICROMIPS(VAL) \
(0x53180000 + (VAL)) /* ori t8,t8,VAL */
#define STUB_LI16U_MICROMIPS(VAL) \
@ -920,6 +928,8 @@ static bfd *reldyn_sorting_bfd;
#define MIPS_FUNCTION_STUB_BIG_SIZE 20
#define MICROMIPS_FUNCTION_STUB_NORMAL_SIZE 12
#define MICROMIPS_FUNCTION_STUB_BIG_SIZE 16
#define MICROMIPS_INSN32_FUNCTION_STUB_NORMAL_SIZE 16
#define MICROMIPS_INSN32_FUNCTION_STUB_BIG_SIZE 20
/* The name of the dynamic interpreter. This is put in the .interp
section. */
@ -1050,6 +1060,20 @@ static const bfd_vma micromips_o32_exec_plt0_entry[] =
0x0c00 /* nop */
};
/* The format of the microMIPS first PLT entry in an O32 executable
in the insn32 mode. */
static const bfd_vma micromips_insn32_o32_exec_plt0_entry[] =
{
0x41bc, 0x0000, /* lui $28, %hi(&GOTPLT[0]) */
0xff3c, 0x0000, /* lw $25, %lo(&GOTPLT[0])($28) */
0x339c, 0x0000, /* addiu $28, $28, %lo(&GOTPLT[0]) */
0x0398, 0xc1d0, /* subu $24, $24, $28 */
0x001f, 0x7950, /* move $15, $31 */
0x0318, 0x1040, /* srl $24, $24, 2 */
0x03f9, 0x0f3c, /* jalr $25 */
0x3318, 0xfffe /* subu $24, $24, 2 */
};
/* The format of subsequent standard PLT entries. */
static const bfd_vma mips_exec_plt_entry[] =
{
@ -1083,6 +1107,15 @@ static const bfd_vma micromips_o32_exec_plt_entry[] =
0x0f02 /* move $24, $2 */
};
/* The format of subsequent microMIPS o32 PLT entries in the insn32 mode. */
static const bfd_vma micromips_insn32_o32_exec_plt_entry[] =
{
0x41af, 0x0000, /* lui $15, %hi(.got.plt entry) */
0xff2f, 0x0000, /* lw $25, %lo(.got.plt entry)($15) */
0x0019, 0x0f3c, /* jr $25 */
0x330f, 0x0000 /* addiu $24, $15, %lo(.got.plt entry) */
};
/* The format of the first PLT entry in a VxWorks executable. */
static const bfd_vma mips_vxworks_exec_plt0_entry[] =
{
@ -8802,19 +8835,26 @@ _bfd_mips_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
else if (newabi_p)
htab->plt_mips_entry_size
= 4 * ARRAY_SIZE (mips_exec_plt_entry);
else if (micromips_p)
else if (!micromips_p)
{
htab->plt_mips_entry_size
= 4 * ARRAY_SIZE (mips_exec_plt_entry);
htab->plt_comp_entry_size
= 2 * ARRAY_SIZE (micromips_o32_exec_plt_entry);
= 2 * ARRAY_SIZE (mips16_o32_exec_plt_entry);
}
else if (htab->insn32)
{
htab->plt_mips_entry_size
= 4 * ARRAY_SIZE (mips_exec_plt_entry);
htab->plt_comp_entry_size
= 2 * ARRAY_SIZE (micromips_insn32_o32_exec_plt_entry);
}
else
{
htab->plt_mips_entry_size
= 4 * ARRAY_SIZE (mips_exec_plt_entry);
htab->plt_comp_entry_size
= 2 * ARRAY_SIZE (mips16_o32_exec_plt_entry);
= 2 * ARRAY_SIZE (micromips_o32_exec_plt_entry);
}
}
@ -9128,15 +9168,19 @@ mips_elf_estimate_stub_size (bfd *output_bfd, struct bfd_link_info *info)
from using microMIPS code here, so for the sake of pure-microMIPS
binaries we prefer it whenever there's any microMIPS code in
output produced at all. This has a benefit of stubs being
shorter by 4 bytes each too. */
if (MICROMIPS_P (output_bfd))
htab->function_stub_size = (dynsymcount > 0x10000
? MICROMIPS_FUNCTION_STUB_BIG_SIZE
: MICROMIPS_FUNCTION_STUB_NORMAL_SIZE);
else
shorter by 4 bytes each too, unless in the insn32 mode. */
if (!MICROMIPS_P (output_bfd))
htab->function_stub_size = (dynsymcount > 0x10000
? MIPS_FUNCTION_STUB_BIG_SIZE
: MIPS_FUNCTION_STUB_NORMAL_SIZE);
else if (htab->insn32)
htab->function_stub_size = (dynsymcount > 0x10000
? MICROMIPS_INSN32_FUNCTION_STUB_BIG_SIZE
: MICROMIPS_INSN32_FUNCTION_STUB_NORMAL_SIZE);
else
htab->function_stub_size = (dynsymcount > 0x10000
? MICROMIPS_FUNCTION_STUB_BIG_SIZE
: MICROMIPS_FUNCTION_STUB_NORMAL_SIZE);
htab->sstubs->size = htab->lazy_stub_count * htab->function_stub_size;
}
@ -9341,6 +9385,8 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd,
size = 4 * ARRAY_SIZE (mips_n32_exec_plt0_entry);
else if (!micromips_p)
size = 4 * ARRAY_SIZE (mips_o32_exec_plt0_entry);
else if (htab->insn32)
size = 2 * ARRAY_SIZE (micromips_insn32_o32_exec_plt0_entry);
else
size = 2 * ARRAY_SIZE (micromips_o32_exec_plt0_entry);
@ -10293,7 +10339,32 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd *output_bfd,
loc = htab->splt->contents + plt_offset;
/* Fill in the PLT entry itself. */
if (MICROMIPS_P (output_bfd))
if (!MICROMIPS_P (output_bfd))
{
const bfd_vma *plt_entry = mips16_o32_exec_plt_entry;
bfd_put_16 (output_bfd, plt_entry[0], loc);
bfd_put_16 (output_bfd, plt_entry[1], loc + 2);
bfd_put_16 (output_bfd, plt_entry[2], loc + 4);
bfd_put_16 (output_bfd, plt_entry[3], loc + 6);
bfd_put_16 (output_bfd, plt_entry[4], loc + 8);
bfd_put_16 (output_bfd, plt_entry[5], loc + 10);
bfd_put_32 (output_bfd, got_address, loc + 12);
}
else if (htab->insn32)
{
const bfd_vma *plt_entry = micromips_insn32_o32_exec_plt_entry;
bfd_put_16 (output_bfd, plt_entry[0], loc);
bfd_put_16 (output_bfd, got_address_high, loc + 2);
bfd_put_16 (output_bfd, plt_entry[2], loc + 4);
bfd_put_16 (output_bfd, got_address_low, loc + 6);
bfd_put_16 (output_bfd, plt_entry[4], loc + 8);
bfd_put_16 (output_bfd, plt_entry[5], loc + 10);
bfd_put_16 (output_bfd, plt_entry[6], loc + 12);
bfd_put_16 (output_bfd, got_address_low, loc + 14);
}
else
{
const bfd_vma *plt_entry = micromips_o32_exec_plt_entry;
bfd_signed_vma gotpc_offset;
@ -10326,18 +10397,6 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd *output_bfd,
bfd_put_16 (output_bfd, plt_entry[4], loc + 8);
bfd_put_16 (output_bfd, plt_entry[5], loc + 10);
}
else
{
const bfd_vma *plt_entry = mips16_o32_exec_plt_entry;
bfd_put_16 (output_bfd, plt_entry[0], loc);
bfd_put_16 (output_bfd, plt_entry[1], loc + 2);
bfd_put_16 (output_bfd, plt_entry[2], loc + 4);
bfd_put_16 (output_bfd, plt_entry[3], loc + 6);
bfd_put_16 (output_bfd, plt_entry[4], loc + 8);
bfd_put_16 (output_bfd, plt_entry[5], loc + 10);
bfd_put_32 (output_bfd, got_address, loc + 12);
}
}
/* Emit an R_MIPS_JUMP_SLOT relocation against the .got.plt entry. */
@ -10369,10 +10428,12 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd *output_bfd,
bfd_vma isa_bit = micromips_p;
bfd_vma stub_big_size;
if (micromips_p)
stub_big_size = MICROMIPS_FUNCTION_STUB_BIG_SIZE;
else
if (!micromips_p)
stub_big_size = MIPS_FUNCTION_STUB_BIG_SIZE;
else if (htab->insn32)
stub_big_size = MICROMIPS_INSN32_FUNCTION_STUB_BIG_SIZE;
else
stub_big_size = MICROMIPS_FUNCTION_STUB_BIG_SIZE;
/* This symbol has a stub. Set it up. */
@ -10393,8 +10454,18 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd *output_bfd,
bfd_put_micromips_32 (output_bfd, STUB_LW_MICROMIPS (output_bfd),
stub + idx);
idx += 4;
bfd_put_16 (output_bfd, STUB_MOVE_MICROMIPS, stub + idx);
idx += 2;
if (htab->insn32)
{
bfd_put_micromips_32 (output_bfd,
STUB_MOVE32_MICROMIPS (output_bfd),
stub + idx);
idx += 4;
}
else
{
bfd_put_16 (output_bfd, STUB_MOVE_MICROMIPS, stub + idx);
idx += 2;
}
if (stub_size == stub_big_size)
{
long dynindx_hi = (h->dynindx >> 16) & 0x7fff;
@ -10404,8 +10475,17 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd *output_bfd,
stub + idx);
idx += 4;
}
bfd_put_16 (output_bfd, STUB_JALR_MICROMIPS, stub + idx);
idx += 2;
if (htab->insn32)
{
bfd_put_micromips_32 (output_bfd, STUB_JALR32_MICROMIPS,
stub + idx);
idx += 4;
}
else
{
bfd_put_16 (output_bfd, STUB_JALR_MICROMIPS, stub + idx);
idx += 2;
}
/* If a large stub is not required and sign extension is not a
problem, then use legacy code in the stub. */
@ -10828,10 +10908,12 @@ mips_finish_exec_plt (bfd *output_bfd, struct bfd_link_info *info)
plt_entry = mips_n64_exec_plt0_entry;
else if (ABI_N32_P (output_bfd))
plt_entry = mips_n32_exec_plt0_entry;
else if (htab->plt_header_is_comp)
plt_entry = micromips_o32_exec_plt0_entry;
else
else if (!htab->plt_header_is_comp)
plt_entry = mips_o32_exec_plt0_entry;
else if (htab->insn32)
plt_entry = micromips_insn32_o32_exec_plt0_entry;
else
plt_entry = micromips_o32_exec_plt0_entry;
/* Calculate the value of .got.plt. */
gotplt_value = (htab->sgotplt->output_section->vma
@ -10876,6 +10958,19 @@ mips_finish_exec_plt (bfd *output_bfd, struct bfd_link_info *info)
for (i = 2; i < ARRAY_SIZE (micromips_o32_exec_plt0_entry); i++)
bfd_put_16 (output_bfd, plt_entry[i], loc + (i * 2));
}
else if (plt_entry == micromips_insn32_o32_exec_plt0_entry)
{
size_t i;
bfd_put_16 (output_bfd, plt_entry[0], loc);
bfd_put_16 (output_bfd, gotplt_value_high, loc + 2);
bfd_put_16 (output_bfd, plt_entry[2], loc + 4);
bfd_put_16 (output_bfd, gotplt_value_low, loc + 6);
bfd_put_16 (output_bfd, plt_entry[4], loc + 8);
bfd_put_16 (output_bfd, gotplt_value_low, loc + 10);
for (i = 6; i < ARRAY_SIZE (micromips_insn32_o32_exec_plt0_entry); i++)
bfd_put_16 (output_bfd, plt_entry[i], loc + (i * 2));
}
else
{
bfd_put_32 (output_bfd, plt_entry[0] | gotplt_value_high, loc);
@ -12929,6 +13024,7 @@ _bfd_mips_elf_relax_section (bfd *abfd, asection *sec,
struct bfd_link_info *link_info,
bfd_boolean *again)
{
bfd_boolean insn32 = mips_elf_hash_table (link_info)->insn32;
Elf_Internal_Shdr *symtab_hdr;
Elf_Internal_Rela *internal_relocs;
Elf_Internal_Rela *irel, *irelend;
@ -13211,7 +13307,13 @@ _bfd_mips_elf_relax_section (bfd *abfd, asection *sec,
&& irel->r_offset + 5 < sec->size
&& ((fndopc = find_match (opcode, bz_rs_insns_32)) >= 0
|| (fndopc = find_match (opcode, bz_rt_insns_32)) >= 0)
&& MATCH (bfd_get_16 (abfd, ptr + 4), nop_insn_16))
&& ((!insn32
&& (delcnt = MATCH (bfd_get_16 (abfd, ptr + 4),
nop_insn_16) ? 2 : 0))
|| (irel->r_offset + 7 < sec->size
&& (delcnt = MATCH (bfd_get_micromips_32 (abfd,
ptr + 4),
nop_insn_32) ? 4 : 0))))
{
unsigned long reg;
@ -13224,15 +13326,15 @@ _bfd_mips_elf_relax_section (bfd *abfd, asection *sec,
bfd_put_micromips_32 (abfd, opcode, ptr);
/* Delete the 16-bit delay slot NOP: two bytes from
irel->offset + 4. */
delcnt = 2;
/* Delete the delay slot NOP: two or four bytes from
irel->offset + 4; delcnt has already been set above. */
deloff = 4;
}
/* R_MICROMIPS_PC16_S1 relaxation to R_MICROMIPS_PC10_S1. We need
to check the distance from the next instruction, so subtract 2. */
else if (r_type == R_MICROMIPS_PC16_S1
else if (!insn32
&& r_type == R_MICROMIPS_PC16_S1
&& IS_BITSIZE (pcrval - 2, 11)
&& find_match (opcode, b_insns_32) >= 0)
{
@ -13252,7 +13354,8 @@ _bfd_mips_elf_relax_section (bfd *abfd, asection *sec,
/* R_MICROMIPS_PC16_S1 relaxation to R_MICROMIPS_PC7_S1. We need
to check the distance from the next instruction, so subtract 2. */
else if (r_type == R_MICROMIPS_PC16_S1
else if (!insn32
&& r_type == R_MICROMIPS_PC16_S1
&& IS_BITSIZE (pcrval - 2, 8)
&& (((fndopc = find_match (opcode, bz_rs_insns_32)) >= 0
&& OP16_VALID_REG (OP32_SREG (opcode)))
@ -13279,7 +13382,8 @@ _bfd_mips_elf_relax_section (bfd *abfd, asection *sec,
}
/* R_MICROMIPS_26_S1 -- JAL to JALS relaxation for microMIPS targets. */
else if (r_type == R_MICROMIPS_26_S1
else if (!insn32
&& r_type == R_MICROMIPS_26_S1
&& target_is_micromips_code_p
&& irel->r_offset + 7 < sec->size
&& MATCH (opcode, jal_insn_32_bd32))
@ -13437,6 +13541,15 @@ _bfd_mips_elf_use_plts_and_copy_relocs (struct bfd_link_info *info)
{
mips_elf_hash_table (info)->use_plts_and_copy_relocs = TRUE;
}
/* A function that the linker calls to select between all or only
32-bit microMIPS instructions. */
void
_bfd_mips_elf_insn32 (struct bfd_link_info *info, bfd_boolean on)
{
mips_elf_hash_table (info)->insn32 = on;
}
/* We need to use a special link routine to handle the .reginfo and
the .mdebug sections. We need to merge all instances of these
@ -14999,6 +15112,13 @@ _bfd_mips_elf_get_synthetic_symtab (bfd *abfd,
plt0_size = 2 * ARRAY_SIZE (micromips_o32_exec_plt0_entry);
other = STO_MICROMIPS;
}
else if (opcode == 0x0398c1d0)
{
if (!micromips_p)
return -1;
plt0_size = 2 * ARRAY_SIZE (micromips_insn32_o32_exec_plt0_entry);
other = STO_MICROMIPS;
}
else
{
plt0_size = 4 * ARRAY_SIZE (mips_o32_exec_plt0_entry);
@ -15042,7 +15162,7 @@ _bfd_mips_elf_get_synthetic_symtab (bfd *abfd,
suffix = m16suffix;
other = STO_MIPS16;
}
/* Likewise the expected microMIPS instruction. */
/* Likewise the expected microMIPS instruction (no insn32 mode). */
else if (opcode == 0xff220000)
{
if (!micromips_p)
@ -15058,6 +15178,19 @@ _bfd_mips_elf_get_synthetic_symtab (bfd *abfd,
suffix = microsuffix;
other = STO_MICROMIPS;
}
/* Likewise the expected microMIPS instruction (insn32 mode). */
else if ((opcode & 0xffff0000) == 0xff2f0000)
{
gotplt_hi = bfd_get_16 (abfd, plt_data + plt_offset + 2) & 0xffff;
gotplt_lo = bfd_get_16 (abfd, plt_data + plt_offset + 6) & 0xffff;
gotplt_hi = ((gotplt_hi ^ 0x8000) - 0x8000) << 16;
gotplt_lo = (gotplt_lo ^ 0x8000) - 0x8000;
gotplt_addr = gotplt_hi + gotplt_lo;
entry_size = 2 * ARRAY_SIZE (micromips_insn32_o32_exec_plt_entry);
suffixlen = sizeof (microsuffix);
suffix = microsuffix;
other = STO_MICROMIPS;
}
/* Otherwise assume standard MIPS code. */
else
{

View File

@ -147,6 +147,8 @@ extern bfd_boolean _bfd_mips_elf_ignore_undef_symbol
(struct elf_link_hash_entry *);
extern void _bfd_mips_elf_use_plts_and_copy_relocs
(struct bfd_link_info *);
extern void _bfd_mips_elf_insn32
(struct bfd_link_info *, bfd_boolean);
extern bfd_boolean _bfd_mips_elf_init_stubs
(struct bfd_link_info *,
asection *(*) (const char *, asection *, asection *));

View File

@ -1,3 +1,35 @@
2013-06-25 Maciej W. Rozycki <macro@codesourcery.com>
* config/tc-mips.c (mips_set_options): Add insn32 member.
(mips_opts): Initialize it.
(NOP_INSN, NOP_INSN_SIZE): Handle insn32 mode.
(options): Add OPTION_INSN32 and OPTION_NO_INSN32 enum values.
(md_longopts): Add "minsn32" and "mno-insn32" options.
(is_size_valid): Handle insn32 mode.
(md_assemble): Pass instruction string down to macro.
(brk_fmt): Add second dimension and insn32 mode initializers.
(mfhl_fmt): Likewise.
(BRK_FMT, MFHL_FMT): Handle insn32 mode.
(macro_build) <'c'>: Handle microMIPS 32-bit BREAK encoding.
(macro_build_jalr, move_register): Handle insn32 mode.
(macro_build_branch_rs): Likewise.
(macro): Handle insn32 mode.
<M_JRADDIUSP>, <M_JRC>, <M_MOVEP>: New cases.
(mips_ip): Handle insn32 mode.
(md_parse_option): Handle OPTION_INSN32 and OPTION_NO_INSN32.
(s_mipsset): Handle "insn32" and "noinsn32" pseudo-ops.
(mips_handle_align): Handle insn32 mode.
(md_show_usage): Add -minsn32 and -mno-insn32.
* doc/as.texinfo (Target MIPS options): Add -minsn32 and
-mno-insn32 options.
(-minsn32, -mno-insn32): New options.
* doc/c-mips.texi (MIPS Opts): Add -minsn32 and -mno-insn32
options.
(MIPS assembly options): New node. Document .set insn32 and
.set noinsn32.
(MIPS-Dependent): List the new node.
2013-06-25 Nick Clifton <nickc@redhat.com>
* config/tc-msp430.c (msp430_srcoperand): Do not allow the use of

View File

@ -231,6 +231,10 @@ struct mips_set_options
/* Non-zero if we should not autoextend mips16 instructions.
Changed by `.set autoextend' and `.set noautoextend'. */
int noautoextend;
/* True if we should only emit 32-bit microMIPS instructions.
Changed by `.set insn32' and `.set noinsn32', and the -minsn32
and -mno-insn32 command line options. */
bfd_boolean insn32;
/* Restrict general purpose registers and floating point registers
to 32 bit. This is initially determined when -mgp32 or -mfp32
is passed but can changed if the assembler code uses .set mipsN. */
@ -272,8 +276,8 @@ static struct mips_set_options mips_opts =
{
/* isa */ ISA_UNKNOWN, /* ase */ 0, /* mips16 */ -1, /* micromips */ -1,
/* noreorder */ 0, /* at */ ATREG, /* warn_about_macros */ 0,
/* nomove */ 0, /* nobopt */ 0, /* noautoextend */ 0, /* gp32 */ 0,
/* fp32 */ 0, /* arch */ CPU_UNKNOWN, /* sym32 */ FALSE,
/* nomove */ 0, /* nobopt */ 0, /* noautoextend */ 0, /* insn32 */ FALSE,
/* gp32 */ 0, /* fp32 */ 0, /* arch */ CPU_UNKNOWN, /* sym32 */ FALSE,
/* soft_float */ FALSE, /* single_float */ FALSE
};
@ -686,11 +690,18 @@ static struct mips_cl_insn micromips_nop16_insn;
static struct mips_cl_insn micromips_nop32_insn;
/* The appropriate nop for the current mode. */
#define NOP_INSN (mips_opts.mips16 ? &mips16_nop_insn \
: (mips_opts.micromips ? &micromips_nop16_insn : &nop_insn))
#define NOP_INSN (mips_opts.mips16 \
? &mips16_nop_insn \
: (mips_opts.micromips \
? (mips_opts.insn32 \
? &micromips_nop32_insn \
: &micromips_nop16_insn) \
: &nop_insn))
/* The size of NOP_INSN in bytes. */
#define NOP_INSN_SIZE (HAVE_CODE_COMPRESSION ? 2 : 4)
#define NOP_INSN_SIZE ((mips_opts.mips16 \
|| (mips_opts.micromips && !mips_opts.insn32)) \
? 2 : 4)
/* If this is set, it points to a frag holding nop instructions which
were inserted before the start of a noreorder section. If those
@ -1276,7 +1287,7 @@ static void mips16_macro_build
static void load_register (int, expressionS *, int);
static void macro_start (void);
static void macro_end (void);
static void macro (struct mips_cl_insn * ip);
static void macro (struct mips_cl_insn *ip, char *str);
static void mips16_macro (struct mips_cl_insn * ip);
static void mips_ip (char *str, struct mips_cl_insn * ip);
static void mips16_ip (char *str, struct mips_cl_insn * ip);
@ -1418,6 +1429,8 @@ enum options
OPTION_GP64,
OPTION_RELAX_BRANCH,
OPTION_NO_RELAX_BRANCH,
OPTION_INSN32,
OPTION_NO_INSN32,
OPTION_MSHARED,
OPTION_MNO_SHARED,
OPTION_MSYM32,
@ -1524,6 +1537,8 @@ struct option md_longopts[] =
{"mgp64", no_argument, NULL, OPTION_GP64},
{"relax-branch", no_argument, NULL, OPTION_RELAX_BRANCH},
{"no-relax-branch", no_argument, NULL, OPTION_NO_RELAX_BRANCH},
{"minsn32", no_argument, NULL, OPTION_INSN32},
{"mno-insn32", no_argument, NULL, OPTION_NO_INSN32},
{"mshared", no_argument, NULL, OPTION_MSHARED},
{"mno-shared", no_argument, NULL, OPTION_MNO_SHARED},
{"msym32", no_argument, NULL, OPTION_MSYM32},
@ -2636,6 +2651,13 @@ is_size_valid (const struct mips_opcode *mo)
if (!mips_opts.micromips)
return TRUE;
if (mips_opts.insn32)
{
if (mo->pinfo != INSN_MACRO && micromips_insn_length (mo) != 4)
return FALSE;
if ((mo->pinfo2 & INSN2_BRANCH_DELAY_16BIT) != 0)
return FALSE;
}
if (!forced_insn_length)
return TRUE;
if (mo->pinfo == INSN_MACRO)
@ -2966,7 +2988,7 @@ md_assemble (char *str)
if (mips_opts.mips16)
mips16_macro (&insn);
else
macro (&insn);
macro (&insn, str);
macro_end ();
}
else
@ -5209,21 +5231,21 @@ macro_end (void)
/* Instruction operand formats used in macros that vary between
standard MIPS and microMIPS code. */
static const char * const brk_fmt[2] = { "c", "mF" };
static const char * const brk_fmt[2][2] = { { "c", "c" }, { "mF", "c" } };
static const char * const cop12_fmt[2] = { "E,o(b)", "E,~(b)" };
static const char * const jalr_fmt[2] = { "d,s", "t,s" };
static const char * const lui_fmt[2] = { "t,u", "s,u" };
static const char * const mem12_fmt[2] = { "t,o(b)", "t,~(b)" };
static const char * const mfhl_fmt[2] = { "d", "mj" };
static const char * const mfhl_fmt[2][2] = { { "d", "d" }, { "mj", "s" } };
static const char * const shft_fmt[2] = { "d,w,<", "t,r,<" };
static const char * const trap_fmt[2] = { "s,t,q", "s,t,|" };
#define BRK_FMT (brk_fmt[mips_opts.micromips])
#define BRK_FMT (brk_fmt[mips_opts.micromips][mips_opts.insn32])
#define COP12_FMT (cop12_fmt[mips_opts.micromips])
#define JALR_FMT (jalr_fmt[mips_opts.micromips])
#define LUI_FMT (lui_fmt[mips_opts.micromips])
#define MEM12_FMT (mem12_fmt[mips_opts.micromips])
#define MFHL_FMT (mfhl_fmt[mips_opts.micromips])
#define MFHL_FMT (mfhl_fmt[mips_opts.micromips][mips_opts.insn32])
#define SHFT_FMT (shft_fmt[mips_opts.micromips])
#define TRAP_FMT (trap_fmt[mips_opts.micromips])
@ -5382,8 +5404,7 @@ macro_build (expressionS *ep, const char *name, const char *fmt, ...)
continue;
case 'c':
gas_assert (!mips_opts.micromips);
INSERT_OPERAND (0, CODE, insn, va_arg (args, int));
INSERT_OPERAND (mips_opts.micromips, CODE, insn, va_arg (args, int));
continue;
case 'W':
@ -5750,8 +5771,10 @@ macro_build_jalr (expressionS *ep, int cprestore)
}
if (mips_opts.micromips)
{
jalr = mips_opts.noreorder && !cprestore ? "jalr" : "jalrs";
jalr = ((mips_opts.noreorder && !cprestore) || mips_opts.insn32
? "jalr" : "jalrs");
if (MIPS_JALR_HINT_P (ep)
|| mips_opts.insn32
|| (history[0].insn_mo->pinfo2 & INSN2_BRANCH_DELAY_32BIT))
macro_build (NULL, jalr, "t,s", RA, PIC_CALL_REG);
else
@ -6432,6 +6455,7 @@ move_register (int dest, int source)
/* Prefer to use a 16-bit microMIPS instruction unless the previous
instruction specifically requires a 32-bit one. */
if (mips_opts.micromips
&& !mips_opts.insn32
&& !(history[0].insn_mo->pinfo2 & INSN2_BRANCH_DELAY_32BIT))
macro_build (NULL, "move", "mp,mj", dest, source);
else
@ -6628,7 +6652,7 @@ macro_build_branch_rs (int type, expressionS *ep, unsigned int sreg)
break;
case M_BGEZALL:
gas_assert (mips_opts.micromips);
br = "bgezals";
br = mips_opts.insn32 ? "bgezal" : "bgezals";
brneg = "bltz";
call = 1;
break;
@ -6655,7 +6679,7 @@ macro_build_branch_rs (int type, expressionS *ep, unsigned int sreg)
break;
case M_BLTZALL:
gas_assert (mips_opts.micromips);
br = "bltzals";
br = mips_opts.insn32 ? "bltzal" : "bltzals";
brneg = "bgez";
call = 1;
break;
@ -6727,7 +6751,7 @@ macro_build_branch_rsrt (int type, expressionS *ep,
* we're missing.
*/
static void
macro (struct mips_cl_insn *ip)
macro (struct mips_cl_insn *ip, char *str)
{
unsigned int treg, sreg, dreg, breg;
unsigned int tempreg;
@ -8149,6 +8173,11 @@ macro (struct mips_cl_insn *ip)
/* Fall through. */
case M_JALS_2:
gas_assert (mips_opts.micromips);
if (mips_opts.insn32)
{
as_bad (_("Opcode not supported in the `insn32' mode `%s'"), str);
break;
}
jals = 1;
goto jal;
case M_JAL_1:
@ -8160,6 +8189,7 @@ macro (struct mips_cl_insn *ip)
{
s = jals ? "jalrs" : "jalr";
if (mips_opts.micromips
&& !mips_opts.insn32
&& dreg == RA
&& !(history[0].insn_mo->pinfo2 & INSN2_BRANCH_DELAY_32BIT))
macro_build (NULL, s, "mj", sreg);
@ -8174,9 +8204,12 @@ macro (struct mips_cl_insn *ip)
if (sreg != PIC_CALL_REG)
as_warn (_("MIPS PIC call to register other than $25"));
s = (mips_opts.micromips && (!mips_opts.noreorder || cprestore)
s = ((mips_opts.micromips
&& !mips_opts.insn32
&& (!mips_opts.noreorder || cprestore))
? "jalrs" : "jalr");
if (mips_opts.micromips
&& !mips_opts.insn32
&& dreg == RA
&& !(history[0].insn_mo->pinfo2 & INSN2_BRANCH_DELAY_32BIT))
macro_build (NULL, s, "mj", sreg);
@ -8215,6 +8248,11 @@ macro (struct mips_cl_insn *ip)
case M_JALS_A:
gas_assert (mips_opts.micromips);
if (mips_opts.insn32)
{
as_bad (_("Opcode not supported in the `insn32' mode `%s'"), str);
break;
}
jals = 1;
/* Fall through. */
case M_JAL_A:
@ -9227,6 +9265,24 @@ macro (struct mips_cl_insn *ip)
break;
case M_JRADDIUSP:
gas_assert (mips_opts.micromips);
gas_assert (mips_opts.insn32);
start_noreorder ();
macro_build (NULL, "jr", "s", RA);
expr1.X_add_number = EXTRACT_OPERAND (1, IMMP, *ip) << 2;
macro_build (&expr1, "addiu", "t,r,j", SP, SP, BFD_RELOC_LO16);
end_noreorder ();
break;
case M_JRC:
gas_assert (mips_opts.micromips);
gas_assert (mips_opts.insn32);
macro_build (NULL, "jr", "s", sreg);
if (mips_opts.noreorder)
macro_build (NULL, "nop", "");
break;
case M_LI:
case M_LI_S:
load_register (treg, &imm_expr, 0);
@ -9784,6 +9840,17 @@ macro (struct mips_cl_insn *ip)
move_register (dreg, sreg);
break;
case M_MOVEP:
gas_assert (mips_opts.micromips);
gas_assert (mips_opts.insn32);
dreg = micromips_to_32_reg_h_map[EXTRACT_OPERAND (1, MH, *ip)];
breg = micromips_to_32_reg_i_map[EXTRACT_OPERAND (1, MI, *ip)];
sreg = micromips_to_32_reg_m_map[EXTRACT_OPERAND (1, MM, *ip)];
treg = micromips_to_32_reg_n_map[EXTRACT_OPERAND (1, MN, *ip)];
move_register (dreg, sreg);
move_register (breg, treg);
break;
case M_DMUL:
dbl = 1;
case M_MUL:
@ -11343,6 +11410,8 @@ mips_ip (char *str, struct mips_cl_insn *ip)
sprintf (buf, _("Opcode not supported on this processor: %s (%s)"),
mips_cpu_info_from_arch (mips_opts.arch)->name,
mips_cpu_info_from_isa (mips_opts.isa)->name);
else if (mips_opts.insn32)
sprintf (buf, _("Opcode not supported in the `insn32' mode"));
else
sprintf (buf, _("Unrecognized %u-bit version of microMIPS opcode"),
8 * forced_insn_length);
@ -15135,6 +15204,14 @@ md_parse_option (int c, char *arg)
mips_relax_branch = 0;
break;
case OPTION_INSN32:
mips_opts.insn32 = TRUE;
break;
case OPTION_NO_INSN32:
mips_opts.insn32 = FALSE;
break;
case OPTION_MSHARED:
mips_in_shared = TRUE;
break;
@ -16547,6 +16624,10 @@ s_mipsset (int x ATTRIBUTE_UNUSED)
mips_opts.noautoextend = 0;
else if (strcmp (name, "noautoextend") == 0)
mips_opts.noautoextend = 1;
else if (strcmp (name, "insn32") == 0)
mips_opts.insn32 = TRUE;
else if (strcmp (name, "noinsn32") == 0)
mips_opts.insn32 = FALSE;
else if (strcmp (name, "push") == 0)
{
struct mips_option_stack *s;
@ -18854,7 +18935,7 @@ mips_handle_align (fragS *fragp)
*p++ = '\0';
/* Fall through. */
case 2:
if (nop_opcode == NOP_OPCODE_MICROMIPS)
if (nop_opcode == NOP_OPCODE_MICROMIPS && !mips_opts.insn32)
{
p = write_compressed_insn (p, micromips_nop16_insn.insn_opcode, 2);
break;
@ -19580,6 +19661,9 @@ MIPS options:\n\
-mvirt generate Virtualization instructions\n\
-mno-virt do not generate Virtualization instructions\n"));
fprintf (stream, _("\
-minsn32 only generate 32-bit microMIPS instructions\n\
-mno-insn32 generate all microMIPS instructions\n"));
fprintf (stream, _("\
-mfix-loongson2f-jump work around Loongson2F JUMP instructions\n\
-mfix-loongson2f-nop work around Loongson2F NOP errata\n\
-mfix-vr4120 work around certain VR4120 errata\n\

View File

@ -412,6 +412,7 @@ gcc(1), ld(1), and the Info entries for @file{binutils} and @file{ld}.
[@b{-mdspr2}] [@b{-mno-dspr2}]
[@b{-mmt}] [@b{-mno-mt}]
[@b{-mmcu}] [@b{-mno-mcu}]
[@b{-minsn32}] [@b{-mno-insn32}]
[@b{-mfix7000}] [@b{-mno-fix7000}]
[@b{-mfix-vr4120}] [@b{-mno-fix-vr4120}]
[@b{-mfix-vr4130}] [@b{-mno-fix-vr4130}]
@ -1341,6 +1342,16 @@ Generate code for the MCU Application Specific Extension.
This tells the assembler to accept MCU instructions.
@samp{-mno-mcu} turns off this option.
@item -minsn32
@itemx -mno-insn32
Only use 32-bit instruction encodings when generating code for the
microMIPS processor. This option inhibits the use of any 16-bit
instructions. This is equivalent to putting @code{.set insn32} at
the start of the assembly file. @samp{-mno-insn32} turns off this
option. This is equivalent to putting @code{.set noinsn32} at the
start of the assembly file. By default @samp{-mno-insn32} is
selected, allowing all instructions to be used.
@item --construct-floats
@itemx --no-construct-floats
The @samp{--no-construct-floats} option disables the construction of

View File

@ -27,6 +27,7 @@ Assembly Language Programming'' in the same work.
* MIPS Symbol Sizes:: Directives to override the size of symbols
* MIPS Small Data:: Controlling the use of small data accesses
* MIPS ISA:: Directives to override the ISA level
* MIPS assembly options:: Directives to control code generation
* MIPS autoextend:: Directives for extending MIPS 16 bit instructions
* MIPS insn:: Directive to mark data as an instruction
* MIPS Option Stack:: Directives to save and restore options
@ -186,6 +187,16 @@ Generate code for the Virtualization Application Specific Extension.
This tells the assembler to accept Virtualization instructions.
@samp{-mno-virt} turns off this option.
@item -minsn32
@itemx -mno-insn32
Only use 32-bit instruction encodings when generating code for the
microMIPS processor. This option inhibits the use of any 16-bit
instructions. This is equivalent to putting @code{.set insn32} at
the start of the assembly file. @samp{-mno-insn32} turns off this
option. This is equivalent to putting @code{.set noinsn32} at the
start of the assembly file. By default @samp{-mno-insn32} is
selected, allowing all instructions to be used.
@item -mfix7000
@itemx -mno-fix7000
Cause nops to be inserted if the read of the destination register
@ -649,6 +660,20 @@ in which it will assemble instructions for the microMIPS processor. Use
Traditional MIPS assemblers do not support this directive.
@node MIPS assembly options
@section Directives to control code generation
@cindex MIPS 32-bit microMIPS instruction generation override
@kindex @code{.set insn32}
@kindex @code{.set noinsn32}
The directive @code{.set insn32} makes the assembler only use 32-bit
instruction encodings when generating code for the microMIPS processor.
This directive inhibits the use of any 16-bit instructions from that
point on in the assembly. The @code{.set noinsn32} directive allows
16-bit instructions to be accepted.
Traditional MIPS assemblers do not support this directive.
@node MIPS autoextend
@section Directives for extending MIPS 16 bit instructions

View File

@ -1,3 +1,15 @@
2013-06-25 Maciej W. Rozycki <macro@codesourcery.com>
* gas/mips/micromips-insn32.d: New test.
* gas/mips/micromips-noinsn32.d: Likewise.
* gas/mips/micromips.l: Rename to...
* gas/mips/micromips-warn.l: ... this.
* gas/mips/micromips.d: Update accordingly.
* gas/mips/micromips-trap.d: Likewise.
* gas/mips/micromips.l: New list test.
* gas/mips/micromips.s: Add conditionals.
* gas/mips/mips.exp: Run the new tests.
2013-06-24 Roland McGrath <mcgrathr@google.com>
* gas/arm/macro-vld1.s: Add a case with whitespace before '}'.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
#objdump: -dr --show-raw-insn
#name: microMIPS for MIPS32r2 (w/traps)
#as: -mips32r2 -32 -trap -mfp64 -EB
#stderr: micromips.l
#stderr: micromips-warn.l
#source: micromips.s
.*: +file format .*mips.*

View File

@ -0,0 +1,27 @@
.*: Assembler messages:
.*:578: Warning: Divide by zero.
.*:581: Warning: Divide by zero.
.*:594: Warning: Divide by zero.
.*:1559: Warning: Divide by zero.
.*:1562: Warning: Divide by zero.
.*:1575: Warning: Divide by zero.
.*:2622: Warning: Branch bge is always true
.*:2625: Warning: Branch bgeu is always true
.*:2634: Warning: Branch bgeu is always true
.*:2709: Warning: Branch ble is always true
.*:2724: Warning: Branch bleu is always true
.*:2730: Warning: Branch bleu is always true
.*:2733: Warning: Branch bleu is always true
.*:2832: Warning: Branch bgel is always true
.*:2835: Warning: Branch bgeul is always true
.*:2844: Warning: Branch bgeul is always true
.*:2919: Warning: Branch blel is always true
.*:2934: Warning: Branch bleul is always true
.*:2940: Warning: Branch bleul is always true
.*:2943: Warning: Branch bleul is always true
.*:4759: Warning: Divide by zero.
.*:4762: Warning: Divide by zero.
.*:4775: Warning: Divide by zero.
.*:5180: Warning: Divide by zero.
.*:5190: Warning: Divide by zero.
.*:5200: Warning: Divide by zero.

View File

@ -1,7 +1,7 @@
#objdump: -dr --show-raw-insn
#name: microMIPS for MIPS32r2
#as: -mips32r2 -32 -mfp64 -EB
#stderr: micromips.l
#stderr: micromips-warn.l
#source: micromips.s
.*: +file format .*mips.*

View File

@ -1,27 +1,107 @@
.*: Assembler messages:
.*:560: Warning: Divide by zero.
.*:563: Warning: Divide by zero.
.*:576: Warning: Divide by zero.
.*:1541: Warning: Divide by zero.
.*:1544: Warning: Divide by zero.
.*:1557: Warning: Divide by zero.
.*:2604: Warning: Branch bge is always true
.*:2607: Warning: Branch bgeu is always true
.*:2616: Warning: Branch bgeu is always true
.*:2691: Warning: Branch ble is always true
.*:2706: Warning: Branch bleu is always true
.*:2712: Warning: Branch bleu is always true
.*:2715: Warning: Branch bleu is always true
.*:2814: Warning: Branch bgel is always true
.*:2817: Warning: Branch bgeul is always true
.*:2826: Warning: Branch bgeul is always true
.*:2901: Warning: Branch blel is always true
.*:2916: Warning: Branch bleul is always true
.*:2922: Warning: Branch bleul is always true
.*:2925: Warning: Branch bleul is always true
.*:4739: Warning: Divide by zero.
.*:4742: Warning: Divide by zero.
.*:4755: Warning: Divide by zero.
.*:5160: Warning: Divide by zero.
.*:5170: Warning: Divide by zero.
.*:39: Error: Opcode not supported in the `insn32' mode `nop16'
.*:98: Error: Opcode not supported in the `insn32' mode `move16 \$2,\$22'
.*:99: Error: Opcode not supported in the `insn32' mode `move16 \$22,\$2'
.*:106: Error: Opcode not supported in the `insn32' mode `b16 test'
.*:111: Error: Opcode not supported in the `insn32' mode `b16 1f'
.*:117: Error: Opcode not supported in the `insn32' mode `b16 1b'
.*:277: Error: Opcode not supported in the `insn32' mode `and16 \$2,\$2,\$3'
.*:315: Error: Opcode not supported in the `insn32' mode `andi16 \$7,65535'
.*:387: Error: Opcode not supported in the `insn32' mode `beqz16 \$16,test2'
.*:475: Error: Opcode not supported in the `insn32' mode `bnez16 \$16,test3'
.*:578: Warning: Divide by zero.
.*:581: Warning: Divide by zero.
.*:594: Warning: Divide by zero.
.*:1559: Warning: Divide by zero.
.*:1562: Warning: Divide by zero.
.*:1575: Warning: Divide by zero.
.*:2622: Warning: Branch bge is always true
.*:2625: Warning: Branch bgeu is always true
.*:2634: Warning: Branch bgeu is always true
.*:2709: Warning: Branch ble is always true
.*:2724: Warning: Branch bleu is always true
.*:2730: Warning: Branch bleu is always true
.*:2733: Warning: Branch bleu is always true
.*:2832: Warning: Branch bgel is always true
.*:2835: Warning: Branch bgeul is always true
.*:2844: Warning: Branch bgeul is always true
.*:2919: Warning: Branch blel is always true
.*:2934: Warning: Branch bleul is always true
.*:2940: Warning: Branch bleul is always true
.*:2943: Warning: Branch bleul is always true
.*:3010: Error: Opcode not supported in the `insn32' mode `addiur1sp \$2,0'
.*:3011: Error: Opcode not supported in the `insn32' mode `addiur1sp \$2,1<<2'
.*:3012: Error: Opcode not supported in the `insn32' mode `addiur1sp \$2,2<<2'
.*:3013: Error: Opcode not supported in the `insn32' mode `addiur1sp \$2,3<<2'
.*:3014: Error: Opcode not supported in the `insn32' mode `addiur1sp \$2,4<<2'
.*:3015: Error: Opcode not supported in the `insn32' mode `addiur1sp \$2,63<<2'
.*:3016: Error: Opcode not supported in the `insn32' mode `addiur1sp \$3,63<<2'
.*:3017: Error: Opcode not supported in the `insn32' mode `addiur1sp \$4,63<<2'
.*:3018: Error: Opcode not supported in the `insn32' mode `addiur1sp \$5,63<<2'
.*:3019: Error: Opcode not supported in the `insn32' mode `addiur1sp \$6,63<<2'
.*:3020: Error: Opcode not supported in the `insn32' mode `addiur1sp \$7,63<<2'
.*:3021: Error: Opcode not supported in the `insn32' mode `addiur1sp \$16,63<<2'
.*:3022: Error: Opcode not supported in the `insn32' mode `addiur1sp \$17,63<<2'
.*:3024: Error: Opcode not supported in the `insn32' mode `addiur2 \$2,\$2,-1'
.*:3025: Error: Opcode not supported in the `insn32' mode `addiur2 \$2,\$3,-1'
.*:3026: Error: Opcode not supported in the `insn32' mode `addiur2 \$2,\$4,-1'
.*:3027: Error: Opcode not supported in the `insn32' mode `addiur2 \$2,\$5,-1'
.*:3028: Error: Opcode not supported in the `insn32' mode `addiur2 \$2,\$6,-1'
.*:3029: Error: Opcode not supported in the `insn32' mode `addiur2 \$2,\$7,-1'
.*:3030: Error: Opcode not supported in the `insn32' mode `addiur2 \$2,\$16,-1'
.*:3031: Error: Opcode not supported in the `insn32' mode `addiur2 \$2,\$17,-1'
.*:3032: Error: Opcode not supported in the `insn32' mode `addiur2 \$3,\$17,-1'
.*:3033: Error: Opcode not supported in the `insn32' mode `addiur2 \$4,\$17,-1'
.*:3034: Error: Opcode not supported in the `insn32' mode `addiur2 \$5,\$17,-1'
.*:3035: Error: Opcode not supported in the `insn32' mode `addiur2 \$6,\$17,-1'
.*:3036: Error: Opcode not supported in the `insn32' mode `addiur2 \$7,\$17,-1'
.*:3037: Error: Opcode not supported in the `insn32' mode `addiur2 \$16,\$17,-1'
.*:3038: Error: Opcode not supported in the `insn32' mode `addiur2 \$17,\$17,-1'
.*:3039: Error: Opcode not supported in the `insn32' mode `addiur2 \$17,\$17,1'
.*:3040: Error: Opcode not supported in the `insn32' mode `addiur2 \$17,\$17,4'
.*:3041: Error: Opcode not supported in the `insn32' mode `addiur2 \$17,\$17,8'
.*:3042: Error: Opcode not supported in the `insn32' mode `addiur2 \$17,\$17,12'
.*:3043: Error: Opcode not supported in the `insn32' mode `addiur2 \$17,\$17,16'
.*:3044: Error: Opcode not supported in the `insn32' mode `addiur2 \$17,\$17,20'
.*:3045: Error: Opcode not supported in the `insn32' mode `addiur2 \$17,\$17,24'
.*:3047: Error: Opcode not supported in the `insn32' mode `addiusp 2<<2'
.*:3048: Error: Opcode not supported in the `insn32' mode `addiusp 3<<2'
.*:3049: Error: Opcode not supported in the `insn32' mode `addiusp 254<<2'
.*:3050: Error: Opcode not supported in the `insn32' mode `addiusp 255<<2'
.*:3051: Error: Opcode not supported in the `insn32' mode `addiusp 256<<2'
.*:3052: Error: Opcode not supported in the `insn32' mode `addiusp 257<<2'
.*:3053: Error: Opcode not supported in the `insn32' mode `addiusp -3<<2'
.*:3054: Error: Opcode not supported in the `insn32' mode `addiusp -4<<2'
.*:3055: Error: Opcode not supported in the `insn32' mode `addiusp -255<<2'
.*:3056: Error: Opcode not supported in the `insn32' mode `addiusp -256<<2'
.*:3057: Error: Opcode not supported in the `insn32' mode `addiusp -257<<2'
.*:3058: Error: Opcode not supported in the `insn32' mode `addiusp -258<<2'
.*:3060: Error: Opcode not supported in the `insn32' mode `addius5 \$0,0'
.*:3061: Error: Opcode not supported in the `insn32' mode `addius5 \$2,0'
.*:3062: Error: Opcode not supported in the `insn32' mode `addius5 \$3,0'
.*:3063: Error: Opcode not supported in the `insn32' mode `addius5 \$30,0'
.*:3064: Error: Opcode not supported in the `insn32' mode `addius5 \$31,0'
.*:3065: Error: Opcode not supported in the `insn32' mode `addius5 \$31,1'
.*:3066: Error: Opcode not supported in the `insn32' mode `addius5 \$31,2'
.*:3067: Error: Opcode not supported in the `insn32' mode `addius5 \$31,3'
.*:3068: Error: Opcode not supported in the `insn32' mode `addius5 \$31,7'
.*:3069: Error: Opcode not supported in the `insn32' mode `addius5 \$31,-6'
.*:3070: Error: Opcode not supported in the `insn32' mode `addius5 \$31,-7'
.*:3071: Error: Opcode not supported in the `insn32' mode `addius5 \$31,-8'
.*:4759: Warning: Divide by zero.
.*:4762: Warning: Divide by zero.
.*:4775: Warning: Divide by zero.
.*:5180: Warning: Divide by zero.
.*:5190: Warning: Divide by zero.
.*:5200: Warning: Divide by zero.
.*:5568: Error: Opcode not supported in the `insn32' mode `jalr16 \$2'
.*:5572: Error: Opcode not supported in the `insn32' mode `jr16 \$2'
.*:5579: Error: Opcode not supported in the `insn32' mode `jals test_delay_slot'
.*:5580: Error: Opcode not supported in the `insn32' mode `jalrs16 \$2'
.*:5581: Error: Opcode not supported in the `insn32' mode `jalrs32 \$2'
.*:5582: Error: Opcode not supported in the `insn32' mode `jrs \$2'
.*:5583: Error: Opcode not supported in the `insn32' mode `jalrs\.hb \$2'
.*:5584: Error: Opcode not supported in the `insn32' mode `jrs\.hb \$2'
.*:5665: Error: Opcode not supported in the `insn32' mode `bals test_spec107'
.*:5667: Error: Opcode not supported in the `insn32' mode `bgezals \$2,test_spec107'
.*:5669: Error: Opcode not supported in the `insn32' mode `bltzals \$2,test_spec107'

View File

@ -35,7 +35,9 @@ test:
pref 3, -32768($2)
nop
.ifndef insn32
nop16
.endif
nop32
ssnop
ehb
@ -92,20 +94,28 @@ test:
move $0, $31
move $22, $2
.ifndef insn32
move16 $2, $22
move16 $22, $2
.endif
move32 $2, $22
move32 $22, $2
b test
.ifndef insn32
b16 test
.endif
b32 test
b 1f
.ifndef insn32
b16 1f
.endif
b32 1f
1:
b 1b
.ifndef insn32
b16 1b
.endif
b32 1b
abs $2, $3
@ -263,7 +273,9 @@ test:
and $2, $3
and $2, $2, $3
and $2, $3, $2
.ifndef insn32
and16 $2, $2, $3
.endif
and32 $2, $2, $3
andi $2,$2,1
@ -299,7 +311,9 @@ test:
andi $7,$7,65535
andi $7,65535
.ifndef insn32
andi16 $7,65535
.endif
andi32 $7,65535
and32 $2, $3, $4
@ -369,7 +383,9 @@ test2:
beq $0, $16, test2
beq $0, $17, test2
.ifndef insn32
beqz16 $16, test2
.endif
beqz32 $16, test2
beqz $17, test2
beqz32 $17, test2
@ -455,7 +471,9 @@ test2:
bne $0, $16, test3
bne $0, $17, test3
.ifndef insn32
bnez16 $16, test3
.endif
bnez32 $16, test3
bnez $17, test2
bnez32 $17, test2
@ -2988,6 +3006,7 @@ test3:
bnel $9, 1, test
addu $3, $4, $5
.ifndef insn32
addiur1sp $2, 0
addiur1sp $2, 1<<2
addiur1sp $2, 2<<2
@ -3050,6 +3069,7 @@ test3:
addius5 $31, -6
addius5 $31, -7
addius5 $31, -8
.endif
sd $3, 4
sd $3, 4($0)
@ -5544,19 +5564,25 @@ test_delay_slot:
bltzall $3, test_delay_slot
jal test_delay_slot
jalx test_delay_slot
.ifndef insn32
jalr16 $2
.endif
jalr32 $2
.ifndef insn32
jr16 $2
.endif
jr32 $2
jalr.hb $2
jr.hb $2
.ifndef insn32
jals test_delay_slot
jalrs16 $2
jalrs32 $2
jrs $2
jalrs.hb $2
jrs.hb $2
.endif
.end test_delay_slot
@ -5635,12 +5661,14 @@ test_spec107:
movep $4, $7, $20, $18
movep $4, $7, $20, $19
movep $4, $7, $20, $20
.ifndef insn32
bals test_spec107
nop
bgezals $2, test_spec107
nop
bltzals $2, test_spec107
nop
.endif
bal test_spec107
nop
bgezal $2, test_spec107

View File

@ -1074,6 +1074,10 @@ if { [istarget mips*-*-vxworks*] } {
run_dump_test "micromips"
run_dump_test "micromips-trap"
run_dump_test "micromips-insn32"
run_dump_test "micromips-noinsn32"
run_list_test "micromips" "-mips32r2 -32 -mfp64 -minsn32" \
"microMIPS for MIPS32r2 (instructions invalid in insn32 mode)"
run_list_test "micromips-size-0" \
"-32 -march=mips64 -mmicromips" "microMIPS instruction size 0"
run_dump_test "micromips-size-1"

View File

@ -1,3 +1,8 @@
2013-06-25 Maciej W. Rozycki <macro@codesourcery.com>
* mips.h: Add M_JRADDIUSP, M_JRC and M_MOVEP anonymous enum
values.
2013-06-23 Richard Sandiford <rdsandiford@googlemail.com>
* mips.h: Fix comment typo: "G" is _RS rather than _RD for microMIPS.

View File

@ -1064,6 +1064,8 @@ enum
M_JALS_1,
M_JALS_2,
M_JALS_A,
M_JRADDIUSP,
M_JRC,
M_L_DOB,
M_L_DAB,
M_LA_AB,
@ -1148,6 +1150,7 @@ enum
M_MSGWAIT,
M_MSGWAIT_T,
M_MOVE,
M_MOVEP,
M_MUL,
M_MUL_I,
M_MULO,

View File

@ -1,3 +1,17 @@
2013-06-25 Maciej W. Rozycki <macro@codesourcery.com>
* emultempl/mipself.em (insn32): New variable.
(mips_create_output_section_statements): Handle insn32 mode.
(PARSE_AND_LIST_PROLOGUE): New macro.
(PARSE_AND_LIST_LONGOPTS): Likewise.
(PARSE_AND_LIST_OPTIONS): Likewise.
* gen-doc.texi: Set MIPS.
* ld.texinfo: Likewise.
(Options specific to MIPS targets): New section.
(ld and MIPS family): New node.
(Top, Machine Dependent): List the new node.
2013-06-24 Maciej W. Rozycki <macro@codesourcery.com>
* emulparams/elf32btsmip.sh: Arrange for .got.plt to be placed

View File

@ -33,6 +33,8 @@ fragment <<EOF
static lang_input_statement_type *stub_file;
static bfd *stub_bfd;
static bfd_boolean insn32;
static void
mips_after_parse (void)
{
@ -199,6 +201,12 @@ mips_add_stub_section (const char *stub_sec_name, asection *input_section,
static void
mips_create_output_section_statements (void)
{
struct elf_link_hash_table *htab;
htab = elf_hash_table (&link_info);
if (is_elf_hash_table (htab) && is_mips_elf (link_info.output_bfd))
_bfd_mips_elf_insn32 (&link_info, insn32);
if (is_mips_elf (link_info.output_bfd))
_bfd_mips_elf_init_stubs (&link_info, mips_add_stub_section);
}
@ -241,6 +249,38 @@ mips_lang_for_each_input_file (void (*func) (lang_input_statement_type *))
EOF
# Define some shell vars to insert bits of code into the standard elf
# parse_args and list_options functions.
#
PARSE_AND_LIST_PROLOGUE='
#define OPTION_INSN32 301
#define OPTION_NO_INSN32 (OPTION_INSN32 + 1)
'
PARSE_AND_LIST_LONGOPTS='
{ "insn32", no_argument, NULL, OPTION_INSN32 },
{ "no-insn32", no_argument, NULL, OPTION_NO_INSN32 },
'
PARSE_AND_LIST_OPTIONS='
fprintf (file, _("\
--insn32 Only generate 32-bit microMIPS instructions\n"
));
fprintf (file, _("\
--no-insn32 Generate all microMIPS instructions\n"
));
'
PARSE_AND_LIST_ARGS_CASES='
case OPTION_INSN32:
insn32 = TRUE;
break;
case OPTION_NO_INSN32:
insn32 = FALSE;
break;
'
LDEMUL_AFTER_PARSE=mips_after_parse
LDEMUL_BEFORE_ALLOCATION=mips_before_allocation
LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS=mips_create_output_section_statements

View File

@ -14,6 +14,7 @@
@set I960
@set M68HC11
@set M68K
@set MIPS
@set MMIX
@set MSP430
@set POWERPC

View File

@ -26,6 +26,7 @@
@set I960
@set M68HC11
@set M68K
@set MIPS
@set MMIX
@set MSP430
@set POWERPC
@ -146,6 +147,9 @@ in the section entitled ``GNU Free Documentation License''.
@ifset M68K
* M68K:: ld and Motorola 68K family
@end ifset
@ifset MIPS
* MIPS:: ld and MIPS family
@end ifset
@ifset POWERPC
* PowerPC ELF32:: ld and PowerPC 32-bit ELF Support
@end ifset
@ -2732,6 +2736,32 @@ Info entry for @file{ld}.
@c man end
@end ifset
@ifset MIPS
@subsection Options specific to MIPS targets
@c man begin OPTIONS
The following options are supported to control microMIPS instruction
generation when linking for MIPS targets.
@table @gcctabopt
@kindex --insn32
@item --insn32
@kindex --no-insn32
@itemx --no-insn32
These options control the choice of microMIPS instructions used in code
generated by the linker, such as that in the PLT or lazy binding stubs,
or in relaxation. If @samp{--insn32} is used, then the linker only uses
32-bit instruction encodings. By default or if @samp{--no-insn32} is
used, all instruction encodings are used, including 16-bit ones where
possible.
@end table
@c man end
@end ifset
@ifset UsesEnvVars
@node Environment
@section Environment Variables
@ -6033,6 +6063,9 @@ functionality are not listed.
@ifset M68K
* M68K:: @command{ld} and the Motorola 68K family
@end ifset
@ifset MIPS
* MIPS:: @command{ld} and the MIPS family
@end ifset
@ifset MMIX
* MMIX:: @command{ld} and MMIX
@end ifset
@ -6531,6 +6564,29 @@ files might access different GOTs. Not all environments support such GOTs.
@end ifclear
@end ifset
@ifset MIPS
@ifclear GENERIC
@raisesections
@end ifclear
@node MIPS
@section @command{ld} and the MIPS family
@cindex MIPS microMIPS instruction choice selection
@kindex --insn32
@kindex --no-insn32
The @samp{--insn32} and @samp{--no-insn32} options control the choice of
microMIPS instructions used in code generated by the linker, such as that
in the PLT or lazy binding stubs, or in relaxation. If @samp{--insn32} is
used, then the linker only uses 32-bit instruction encodings. By default
or if @samp{--no-insn32} is used, all instruction encodings are used,
including 16-bit ones where possible.
@ifclear GENERIC
@lowersections
@end ifclear
@end ifset
@ifset MMIX
@ifclear GENERIC
@raisesections

View File

@ -1,3 +1,8 @@
2013-06-25 Maciej W. Rozycki <macro@codesourcery.com>
* micromips-opc.c (micromips_opcodes): Add "jraddiusp", "jrc"
and "movep" macros.
2013-06-24 Maciej W. Rozycki <macro@codesourcery.com>
* mips-dis.c (is_mips16_plt_tail): New function.

View File

@ -548,7 +548,13 @@ const struct mips_opcode micromips_opcodes[] =
{"jr", "s", 0x00000f3c, 0xffe0ffff, UBD|RD_s, BD32, I1 }, /* jalr */
{"jrs", "s", 0x00004f3c, 0xffe0ffff, UBD|RD_s, BD16, I1 }, /* jalrs */
{"jraddiusp", "mP", 0x4700, 0xffe0, NODS, UBR|RD_31|WR_sp|RD_sp, I1 },
/* This macro is after the real instruction so that it only matches with
-minsn32. */
{"jraddiusp", "mP", 0, (int) M_JRADDIUSP, INSN_MACRO, 0, I1 },
{"jrc", "mj", 0x45a0, 0xffe0, NODS, UBR|RD_mj, I1 },
/* This macro is after the real instruction so that it only matches with
-minsn32. */
{"jrc", "s", 0, (int) M_JRC, INSN_MACRO, 0, I1 },
{"jr.hb", "s", 0x00001f3c, 0xffe0ffff, UBD|RD_s, BD32, I1 }, /* jalr.hb */
{"jrs.hb", "s", 0x00005f3c, 0xffe0ffff, UBD|RD_s, BD16, I1 }, /* jalrs.hb */
{"j", "mj", 0x4580, 0xffe0, UBD, RD_mj, I1 }, /* jr */
@ -704,6 +710,9 @@ const struct mips_opcode micromips_opcodes[] =
{"mov.s", "T,S", 0x5400007b, 0xfc00ffff, WR_T|RD_S|FP_S, 0, I1 },
{"mov.ps", "T,S", 0x5400407b, 0xfc00ffff, WR_T|RD_S|FP_D, 0, I1 },
{"movep", "mh,mi,mm,mn", 0x8400, 0xfc01, NODS, WR_mhi|RD_mmn, I1 },
/* This macro is after the real instruction so that it only matches with
-minsn32. */
{"movep", "mh,mi,mm,mn", 0, (int) M_MOVEP, INSN_MACRO, 0, I1 },
{"movf", "t,s,M", 0x5400017b, 0xfc001fff, WR_t|RD_s|RD_CC|FP_S|FP_D, 0, I1 },
{"movf.d", "T,S,M", 0x54000220, 0xfc001fff, WR_T|RD_S|RD_CC|FP_D, 0, I1 },
{"movf.s", "T,S,M", 0x54000020, 0xfc001fff, WR_T|RD_S|RD_CC|FP_S, 0, I1 },