From 3734320dc054bd9f6632607e9e5c901c57450791 Mon Sep 17 00:00:00 2001 From: Matthew Fortune Date: Mon, 13 May 2019 17:03:19 -0700 Subject: [PATCH] [MIPS] Add generation of PLT entries with compact jumps for MIPS R6 Add a new option to get the linker to emit PLTs that use compact branches instead of delay slot branches. bfd/ * elfxx-mips.c (LA25_BC): New macro. (mips_elf_link_hash_table): New field. (STUB_JALRC): New macro. (mipsr6_o32_exec_plt0_entry_compact): New array. (mipsr6_n32_exec_plt0_entry_compact): Likewise. (mipsr6_n64_exec_plt0_entry_compact): Likewise. (mipsr6_exec_plt_entry_compact): Likewise. (mips_elf_create_la25_stub): Use BC instead of J for stubs when compact_branches is true. (_bfd_mips_elf_finish_dynamic_symbol): Choose the compact PLT for MIPSR6 with compact_branches. Do not reorder the compact branches PLT. Switch the lazy stub for MIPSR6 with compact_branches to use JALRC. (mips_finish_exec_plt): Choose the compact PLT0 for MIPSR6 when compact_branches is true. (_bfd_mips_elf_compact_branches): New function. * elfxx-mips.h (_bfd_mips_elf_compact_branches): New prototype. ld/ * emultempl/mipself.em (compact_branches): New static variable. (mips_create_output_section_statements): Call _bfd_mips_elf_compact_branches. (PARSE_AND_LIST_PROLOGUE): Add OPTION_COMPACT_BRANCHES and OPTION_NO_COMPACT_BRANCHES. (PARSE_AND_LIST_LONGOPTS): Add compact-branches, no-compact-branches. (PARSE_AND_LIST_OPTIONS): Add --compact-branches, --no-compact-branches. (PARSE_AND_LIST_ARGS_CASES): Handle the above. * ld.texinfo: Document --compact-branches, --no-compact-branches. * testsuite/ld-mips-elf/pic-and-nonpic-1-r6.dd: New test. * testsuite/ld-mips-elf/pic-and-nonpic-1-r6.nd: New test. * testsuite/ld-mips-elf/pic-and-nonpic-3a-r6.dd: New test. * testsuite/ld-mips-elf/pic-and-nonpic-3a-r6.gd: New test. * testsuite/ld-mips-elf/pic-and-nonpic-1a-r6.s: New test source. * testsuite/ld-mips-elf/pic-and-nonpic-3a-r6.s: New test source. * testsuite/ld-mips-elf/mips-elf.exp: Run the new tests. --- bfd/ChangeLog | 21 +++ bfd/elfxx-mips.c | 127 ++++++++++++++++-- bfd/elfxx-mips.h | 2 + ld/ChangeLog | 22 +++ ld/emultempl/mipself.em | 26 +++- ld/ld.texi | 7 + ld/testsuite/ld-mips-elf/mips-elf.exp | 13 ++ .../ld-mips-elf/pic-and-nonpic-1-r6.dd | 50 +++++++ .../ld-mips-elf/pic-and-nonpic-1-r6.nd | 9 ++ .../ld-mips-elf/pic-and-nonpic-1-r6.s | 0 .../ld-mips-elf/pic-and-nonpic-1a-r6.s | 28 ++++ .../ld-mips-elf/pic-and-nonpic-3a-r6.dd | 36 +++++ .../ld-mips-elf/pic-and-nonpic-3a-r6.gd | 21 +++ .../ld-mips-elf/pic-and-nonpic-3a-r6.s | 26 ++++ 14 files changed, 374 insertions(+), 14 deletions(-) create mode 100644 ld/testsuite/ld-mips-elf/pic-and-nonpic-1-r6.dd create mode 100644 ld/testsuite/ld-mips-elf/pic-and-nonpic-1-r6.nd create mode 100644 ld/testsuite/ld-mips-elf/pic-and-nonpic-1-r6.s create mode 100644 ld/testsuite/ld-mips-elf/pic-and-nonpic-1a-r6.s create mode 100644 ld/testsuite/ld-mips-elf/pic-and-nonpic-3a-r6.dd create mode 100644 ld/testsuite/ld-mips-elf/pic-and-nonpic-3a-r6.gd create mode 100644 ld/testsuite/ld-mips-elf/pic-and-nonpic-3a-r6.s diff --git a/bfd/ChangeLog b/bfd/ChangeLog index cbaeab63f29..deca7784d39 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,24 @@ +2019-05-21 Matthew Fortune + Faraz Shahbazker + + * elfxx-mips.c (LA25_BC): New macro. + (mips_elf_link_hash_table): New field. + (STUB_JALRC): New macro. + (mipsr6_o32_exec_plt0_entry_compact): New array. + (mipsr6_n32_exec_plt0_entry_compact): Likewise. + (mipsr6_n64_exec_plt0_entry_compact): Likewise. + (mipsr6_exec_plt_entry_compact): Likewise. + (mips_elf_create_la25_stub): Use BC instead of J for stubs + when compact_branches is true. + (_bfd_mips_elf_finish_dynamic_symbol): Choose the compact + PLT for MIPSR6 with compact_branches. Do not reorder the + compact branches PLT. Switch the lazy stub for MIPSR6 + with compact_branches to use JALRC. + (mips_finish_exec_plt): Choose the compact PLT0 for MIPSR6 + when compact_branches is true. + (_bfd_mips_elf_compact_branches): New function. + * elfxx-mips.h (_bfd_mips_elf_compact_branches): New prototype. + 2019-05-21 Tamar Christina PR ld/24373 diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c index 74dadf48f7d..8c1ad72aa83 100644 --- a/bfd/elfxx-mips.c +++ b/bfd/elfxx-mips.c @@ -292,6 +292,7 @@ struct mips_elf_la25_stub { #define LA25_LUI(VAL) (0x3c190000 | (VAL)) /* lui t9,VAL */ #define LA25_J(VAL) (0x08000000 | (((VAL) >> 2) & 0x3ffffff)) /* j VAL */ +#define LA25_BC(VAL) (0xc8000000 | (((VAL) >> 2) & 0x3ffffff)) /* bc VAL */ #define LA25_ADDIU(VAL) (0x27390000 | (VAL)) /* addiu t9,t9,VAL */ #define LA25_LUI_MICROMIPS(VAL) \ (0x41b90000 | (VAL)) /* lui t9,VAL */ @@ -449,6 +450,9 @@ struct mips_elf_link_hash_table /* True if we suppress checks for invalid branches between ISA modes. */ bfd_boolean ignore_branch_isa; + /* True if we are targetting R6 compact branches. */ + bfd_boolean compact_branches; + /* True if we're generating code for VxWorks. */ bfd_boolean is_vxworks; @@ -920,6 +924,7 @@ static bfd *reldyn_sorting_bfd; #define STUB_MOVE 0x03e07825 /* or t7,ra,zero */ #define STUB_LUI(VAL) (0x3c180000 + (VAL)) /* lui t8,VAL */ #define STUB_JALR 0x0320f809 /* jalr ra,t9 */ +#define STUB_JALRC 0xf8190000 /* jalrc ra,t9 */ #define STUB_ORI(VAL) (0x37180000 + (VAL)) /* ori t8,t8,VAL */ #define STUB_LI16U(VAL) (0x34180000 + (VAL)) /* ori t8,zero,VAL unsigned */ #define STUB_LI16S(abfd, VAL) \ @@ -1036,6 +1041,20 @@ static const bfd_vma mips_o32_exec_plt0_entry[] = 0x2718fffe /* subu $24, $24, 2 */ }; +/* The format of the first PLT entry in an O32 executable using compact + jumps. */ +static const bfd_vma mipsr6_o32_exec_plt0_entry_compact[] = +{ + 0x3c1c0000, /* lui $28, %hi(&GOTPLT[0]) */ + 0x8f990000, /* lw $25, %lo(&GOTPLT[0])($28) */ + 0x279c0000, /* addiu $28, $28, %lo(&GOTPLT[0]) */ + 0x031cc023, /* subu $24, $24, $28 */ + 0x03e07821, /* move $15, $31 # 32-bit move (addu) */ + 0x0018c082, /* srl $24, $24, 2 */ + 0x2718fffe, /* subu $24, $24, 2 */ + 0xf8190000 /* jalrc $25 */ +}; + /* The format of the first PLT entry in an N32 executable. Different because gp ($28) is not available; we use t2 ($14) instead. */ static const bfd_vma mips_n32_exec_plt0_entry[] = @@ -1050,6 +1069,21 @@ static const bfd_vma mips_n32_exec_plt0_entry[] = 0x2718fffe /* subu $24, $24, 2 */ }; +/* The format of the first PLT entry in an N32 executable using compact + jumps. Different because gp ($28) is not available; we use t2 ($14) + instead. */ +static const bfd_vma mipsr6_n32_exec_plt0_entry_compact[] = +{ + 0x3c0e0000, /* lui $14, %hi(&GOTPLT[0]) */ + 0x8dd90000, /* lw $25, %lo(&GOTPLT[0])($14) */ + 0x25ce0000, /* addiu $14, $14, %lo(&GOTPLT[0]) */ + 0x030ec023, /* subu $24, $24, $14 */ + 0x03e07821, /* move $15, $31 # 32-bit move (addu) */ + 0x0018c082, /* srl $24, $24, 2 */ + 0x2718fffe, /* subu $24, $24, 2 */ + 0xf8190000 /* jalrc $25 */ +}; + /* The format of the first PLT entry in an N64 executable. Different from N32 because of the increased size of GOT entries. */ static const bfd_vma mips_n64_exec_plt0_entry[] = @@ -1064,6 +1098,22 @@ static const bfd_vma mips_n64_exec_plt0_entry[] = 0x2718fffe /* subu $24, $24, 2 */ }; +/* The format of the first PLT entry in an N64 executable using compact + jumps. Different from N32 because of the increased size of GOT + entries. */ +static const bfd_vma mipsr6_n64_exec_plt0_entry_compact[] = +{ + 0x3c0e0000, /* lui $14, %hi(&GOTPLT[0]) */ + 0xddd90000, /* ld $25, %lo(&GOTPLT[0])($14) */ + 0x25ce0000, /* addiu $14, $14, %lo(&GOTPLT[0]) */ + 0x030ec023, /* subu $24, $24, $14 */ + 0x03e0782d, /* move $15, $31 # 64-bit move (daddu) */ + 0x0018c0c2, /* srl $24, $24, 3 */ + 0x2718fffe, /* subu $24, $24, 2 */ + 0xf8190000 /* jalrc $25 */ +}; + + /* The format of the microMIPS first PLT entry in an O32 executable. We rely on v0 ($2) rather than t8 ($24) to contain the address of the GOTPLT entry handled, so this stub may only be used when @@ -1106,9 +1156,6 @@ static const bfd_vma mips_exec_plt_entry[] = 0x03200008 /* jr $25 */ }; -/* In the following PLT entry the JR and ADDIU instructions will - be swapped in _bfd_mips_elf_finish_dynamic_symbol because - LOAD_INTERLOCKS_P will be true for MIPS R6. */ static const bfd_vma mipsr6_exec_plt_entry[] = { 0x3c0f0000, /* lui $15, %hi(.got.plt entry) */ @@ -1117,6 +1164,14 @@ static const bfd_vma mipsr6_exec_plt_entry[] = 0x03200009 /* jr $25 */ }; +static const bfd_vma mipsr6_exec_plt_entry_compact[] = +{ + 0x3c0f0000, /* lui $15, %hi(.got.plt entry) */ + 0x01f90000, /* l[wd] $25, %lo(.got.plt entry)($15) */ + 0x25f80000, /* addiu $24, $15, %lo(.got.plt entry) */ + 0xd8190000 /* jic $25, 0 */ +}; + /* The format of subsequent MIPS16 o32 PLT entries. We use v0 ($2) and v1 ($3) as temporaries because t8 ($24) and t9 ($25) are not directly addressable. */ @@ -10604,6 +10659,8 @@ mips_elf_create_la25_stub (void **slot, void *data) asection *s; bfd_byte *loc; bfd_vma offset, target, target_high, target_low; + bfd_vma branch_pc; + bfd_signed_vma pcrel_offset = 0; stub = (struct mips_elf_la25_stub *) *slot; hti = (struct mips_htab_traverse_info *) data; @@ -10627,6 +10684,12 @@ mips_elf_create_la25_stub (void **slot, void *data) /* Work out where in the section this stub should go. */ offset = stub->offset; + /* We add 8 here to account for the LUI/ADDIU instructions + before the branch instruction. This cannot be moved down to + where pcrel_offset is calculated as 's' is updated in + mips_elf_get_la25_target. */ + branch_pc = s->output_section->vma + s->output_offset + offset + 8; + /* Work out the target address. */ target = mips_elf_get_la25_target (stub, &s); target += s->output_section->vma + s->output_offset; @@ -10634,6 +10697,12 @@ mips_elf_create_la25_stub (void **slot, void *data) target_high = ((target + 0x8000) >> 16) & 0xffff; target_low = (target & 0xffff); + /* Calculate the PC of the compact branch instruction (for the case where + compact branches are used for either microMIPSR6 or MIPSR6 with + compact branches. Add 4-bytes to account for BC using the PC of the + next instruction as the base. */ + pcrel_offset = target - (branch_pc + 4); + if (stub->stub_section != htab->strampoline) { /* This is a simple LUI/ADDIU stub. Zero out the beginning @@ -10672,8 +10741,16 @@ mips_elf_create_la25_stub (void **slot, void *data) else { bfd_put_32 (hti->output_bfd, LA25_LUI (target_high), loc); - bfd_put_32 (hti->output_bfd, LA25_J (target), loc + 4); - bfd_put_32 (hti->output_bfd, LA25_ADDIU (target_low), loc + 8); + if (MIPSR6_P (hti->output_bfd) && htab->compact_branches) + { + bfd_put_32 (hti->output_bfd, LA25_ADDIU (target_low), loc + 4); + bfd_put_32 (hti->output_bfd, LA25_BC (pcrel_offset), loc + 8); + } + else + { + bfd_put_32 (hti->output_bfd, LA25_J (target), loc + 4); + bfd_put_32 (hti->output_bfd, LA25_ADDIU (target_low), loc + 8); + } bfd_put_32 (hti->output_bfd, 0, loc + 12); } } @@ -10830,14 +10907,16 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd *output_bfd, /* Fill in the PLT entry itself. */ if (MIPSR6_P (output_bfd)) - plt_entry = mipsr6_exec_plt_entry; + plt_entry = htab->compact_branches ? mipsr6_exec_plt_entry_compact + : mipsr6_exec_plt_entry; else plt_entry = mips_exec_plt_entry; bfd_put_32 (output_bfd, plt_entry[0] | got_address_high, loc); bfd_put_32 (output_bfd, plt_entry[1] | got_address_low | load, loc + 4); - if (! LOAD_INTERLOCKS_P (output_bfd)) + if (! LOAD_INTERLOCKS_P (output_bfd) + || (MIPSR6_P (output_bfd) && htab->compact_branches)) { bfd_put_32 (output_bfd, plt_entry[2] | got_address_low, loc + 8); bfd_put_32 (output_bfd, plt_entry[3], loc + 12); @@ -11041,8 +11120,12 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd *output_bfd, stub + idx); idx += 4; } - bfd_put_32 (output_bfd, STUB_JALR, stub + idx); - idx += 4; + + if (!(MIPSR6_P (output_bfd) && htab->compact_branches)) + { + bfd_put_32 (output_bfd, STUB_JALR, stub + idx); + idx += 4; + } /* If a large stub is not required and sign extension is not a problem, then use legacy code in the stub. */ @@ -11055,6 +11138,10 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd *output_bfd, else bfd_put_32 (output_bfd, STUB_LI16S (output_bfd, h->dynindx), stub + idx); + idx += 4; + + if (MIPSR6_P (output_bfd) && htab->compact_branches) + bfd_put_32 (output_bfd, STUB_JALRC, stub + idx); } BFD_ASSERT (h->plt.plist->stub_offset <= htab->sstubs->size); @@ -11428,11 +11515,17 @@ mips_finish_exec_plt (bfd *output_bfd, struct bfd_link_info *info) BFD_ASSERT (htab != NULL); if (ABI_64_P (output_bfd)) - plt_entry = mips_n64_exec_plt0_entry; + plt_entry = (htab->compact_branches + ? mipsr6_n64_exec_plt0_entry_compact + : mips_n64_exec_plt0_entry); else if (ABI_N32_P (output_bfd)) - plt_entry = mips_n32_exec_plt0_entry; + plt_entry = (htab->compact_branches + ? mipsr6_n32_exec_plt0_entry_compact + : mips_n32_exec_plt0_entry); else if (!htab->plt_header_is_comp) - plt_entry = mips_o32_exec_plt0_entry; + plt_entry = (htab->compact_branches + ? mipsr6_o32_exec_plt0_entry_compact + : mips_o32_exec_plt0_entry); else if (htab->insn32) plt_entry = micromips_insn32_o32_exec_plt0_entry; else @@ -14190,6 +14283,16 @@ _bfd_mips_elf_linker_flags (struct bfd_link_info *info, bfd_boolean insn32, mips_elf_hash_table (info)->ignore_branch_isa = ignore_branch_isa; mips_elf_hash_table (info)->gnu_target = gnu_target; } + +/* A function that the linker calls to enable use of compact branches in + linker generated code for MIPSR6. */ + +void +_bfd_mips_elf_compact_branches (struct bfd_link_info *info, bfd_boolean on) +{ + mips_elf_hash_table (info)->compact_branches = on; +} + /* Structure for saying that BFD machine EXTENSION extends BASE. */ diff --git a/bfd/elfxx-mips.h b/bfd/elfxx-mips.h index de2c0e54ac0..acd9d7913fa 100644 --- a/bfd/elfxx-mips.h +++ b/bfd/elfxx-mips.h @@ -150,6 +150,8 @@ extern void _bfd_mips_elf_use_plts_and_copy_relocs (struct bfd_link_info *); extern void _bfd_mips_elf_linker_flags (struct bfd_link_info *, bfd_boolean, bfd_boolean, bfd_boolean); +extern void _bfd_mips_elf_compact_branches + (struct bfd_link_info *, bfd_boolean); extern bfd_boolean _bfd_mips_elf_init_stubs (struct bfd_link_info *, asection *(*) (const char *, asection *, asection *)); diff --git a/ld/ChangeLog b/ld/ChangeLog index 05af3936820..6896a72be41 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,25 @@ +2019-05-21 Matthew Fortune + Faraz Shahbazker + + * emultempl/mipself.em (compact_branches): New static variable. + (mips_create_output_section_statements): Call + _bfd_mips_elf_compact_branches. + (PARSE_AND_LIST_PROLOGUE): Add OPTION_COMPACT_BRANCHES and + OPTION_NO_COMPACT_BRANCHES. + (PARSE_AND_LIST_LONGOPTS): Add compact-branches, + no-compact-branches. + (PARSE_AND_LIST_OPTIONS): Add --compact-branches, + --no-compact-branches. + (PARSE_AND_LIST_ARGS_CASES): Handle the above. + * ld.texinfo: Document --compact-branches, --no-compact-branches. + * testsuite/ld-mips-elf/pic-and-nonpic-1-r6.dd: New test. + * testsuite/ld-mips-elf/pic-and-nonpic-1-r6.nd: New test. + * testsuite/ld-mips-elf/pic-and-nonpic-3a-r6.dd: New test. + * testsuite/ld-mips-elf/pic-and-nonpic-3a-r6.gd: New test. + * testsuite/ld-mips-elf/pic-and-nonpic-1a-r6.s: New test source. + * testsuite/ld-mips-elf/pic-and-nonpic-3a-r6.s: New test source. + * testsuite/ld-mips-elf/mips-elf.exp: Run the new tests. + 2019-05-21 Andre Vieira * testsuite/ld-arm/arm-elf.exp: Add tests diff --git a/ld/emultempl/mipself.em b/ld/emultempl/mipself.em index d9eeef308ad..ec908d738dc 100644 --- a/ld/emultempl/mipself.em +++ b/ld/emultempl/mipself.em @@ -44,6 +44,7 @@ static bfd *stub_bfd; static bfd_boolean insn32; static bfd_boolean ignore_branch_isa; +static bfd_boolean compact_branches; static void mips_after_parse (void) @@ -216,7 +217,10 @@ mips_create_output_section_statements (void) ${gnu_target}); if (is_mips_elf (link_info.output_bfd)) - _bfd_mips_elf_init_stubs (&link_info, mips_add_stub_section); + { + _bfd_mips_elf_compact_branches (&link_info, compact_branches); + _bfd_mips_elf_init_stubs (&link_info, mips_add_stub_section); + } } /* This is called after we have merged the private data of the input bfds. */ @@ -269,7 +273,9 @@ enum OPTION_INSN32 = 301, OPTION_NO_INSN32, OPTION_IGNORE_BRANCH_ISA, - OPTION_NO_IGNORE_BRANCH_ISA + OPTION_NO_IGNORE_BRANCH_ISA, + OPTION_COMPACT_BRANCHES, + OPTION_NO_COMPACT_BRANCHES }; ' @@ -278,6 +284,8 @@ PARSE_AND_LIST_LONGOPTS=' { "no-insn32", no_argument, NULL, OPTION_NO_INSN32 }, { "ignore-branch-isa", no_argument, NULL, OPTION_IGNORE_BRANCH_ISA }, { "no-ignore-branch-isa", no_argument, NULL, OPTION_NO_IGNORE_BRANCH_ISA }, + { "compact-branches", no_argument, NULL, OPTION_COMPACT_BRANCHES }, + { "no-compact-branches", no_argument, NULL, OPTION_NO_COMPACT_BRANCHES }, ' PARSE_AND_LIST_OPTIONS=' @@ -295,6 +303,12 @@ PARSE_AND_LIST_OPTIONS=' --no-ignore-branch-isa Reject invalid branch relocations requiring\n\ an ISA mode switch\n" )); + fprintf (file, _("\ + --compact-branches Generate compact branches/jumps for MIPS R6\n" + )); + fprintf (file, _("\ + --no-compact-branches Generate delay slot branches/jumps for MIPS R6\n" + )); ' PARSE_AND_LIST_ARGS_CASES=' @@ -313,6 +327,14 @@ PARSE_AND_LIST_ARGS_CASES=' case OPTION_NO_IGNORE_BRANCH_ISA: ignore_branch_isa = FALSE; break; + + case OPTION_COMPACT_BRANCHES: + compact_branches = TRUE; + break; + + case OPTION_NO_COMPACT_BRANCHES: + compact_branches = FALSE; + break; ' LDEMUL_AFTER_PARSE=mips_after_parse diff --git a/ld/ld.texi b/ld/ld.texi index f47db75edc6..671a2a5dce7 100644 --- a/ld/ld.texi +++ b/ld/ld.texi @@ -3197,6 +3197,13 @@ calculated. By default or if @samp{--no-ignore-branch-isa} is used a check is made causing the loss of an ISA mode transition to produce an error. +@kindex --compact-branches +@item --compact-branches +@kindex --no-compact-branches +@item --compact-branches +These options control the generation of compact instructions by the linker +in the PLT entries for MIPS R6. + @end table @c man end diff --git a/ld/testsuite/ld-mips-elf/mips-elf.exp b/ld/testsuite/ld-mips-elf/mips-elf.exp index e2063e5cd0b..cbbd9add6af 100644 --- a/ld/testsuite/ld-mips-elf/mips-elf.exp +++ b/ld/testsuite/ld-mips-elf/mips-elf.exp @@ -523,6 +523,12 @@ if { $linux_gnu } { {{objdump -dr pic-and-nonpic-1.dd} {readelf --symbols pic-and-nonpic-1.nd}} "pic-and-nonpic-1-static1.o"} + {"PIC and non-PIC test 1 R6 compact branches (static 1)" + "-melf32btsmip -Tpic-and-nonpic-1.ld --compact-branches" "" + "-32 -EB -mips32r6" {pic-and-nonpic-1a-r6.s pic-and-nonpic-1b.s} + {{objdump -dr pic-and-nonpic-1-r6.dd} + {readelf --symbols pic-and-nonpic-1-r6.nd}} + "pic-and-nonpic-1-r6-static1.o"} {"PIC and non-PIC test 1 (static 2)" "-melf32btsmip -Tpic-and-nonpic-1.ld tmpdir/pic-and-nonpic-1-rel.o" "" "" {} @@ -586,6 +592,13 @@ if { $linux_gnu } { {readelf --symbols pic-and-nonpic-3b.nd} {readelf -d pic-and-nonpic-3b.ad}} "pic-and-nonpic-3b"} + {"PIC and non-PIC test 3 R6 compact branches (shared library)" + "-melf32btsmip -shared --compact-branches -Tpic-and-nonpic-3a.ld" "" + "-32 -EB -mips32r6" {pic-and-nonpic-3a-r6.s} + {{readelf --segments pic-and-nonpic-3a.sd} + {readelf -A pic-and-nonpic-3a-r6.gd} + {objdump -dr pic-and-nonpic-3a-r6.dd}} + "pic-and-nonpic-3a-r6.so"} } run_dump_test_o32 "pic-and-nonpic-3-error" {noarch {as -EB} {ld -EB}} run_ld_link_tests { diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-1-r6.dd b/ld/testsuite/ld-mips-elf/pic-and-nonpic-1-r6.dd new file mode 100644 index 00000000000..86ad7a9a302 --- /dev/null +++ b/ld/testsuite/ld-mips-elf/pic-and-nonpic-1-r6.dd @@ -0,0 +1,50 @@ + +.* + +Disassembly of section \.text: + +00041000 <\.pic\.f3>: + 41000: 3c190004 lui t9,0x4 + 41004: 27391060 addiu t9,t9,4192 + 41008: c8000015 bc 41060 + 4100c: 00000000 nop + +00041010 <\.pic\.f2>: + 41010: 3c190004 lui t9,0x4 + 41014: 2739104c addiu t9,t9,4172 + 41018: c800000c bc 4104c + \.\.\. + +00041028 <\.pic\.f1>: + 41028: 3c190004 lui t9,0x4 + 4102c: 27391030 addiu t9,t9,4144 + +00041030 : + 41030: 3c1c0002 lui gp,0x2 + 41034: 279c6fd0 addiu gp,gp,28624 + 41038: 0399e021 addu gp,gp,t9 + 4103c: 0c010418 jal 41060 + 41040: 00000000 nop + 41044: 03e00009 jr ra + 41048: 00000000 nop + +0004104c : + 4104c: 3c1c0002 lui gp,0x2 + 41050: 279c6fb4 addiu gp,gp,28596 + 41054: 0399e021 addu gp,gp,t9 + 41058: 03e00009 jr ra + 4105c: 00000000 nop + +00041060 : + 41060: 00021400 sll v0,v0,0x10 + 41064: 00431021 addu v0,v0,v1 + \.\.\. + +00041070 <__start>: + 41070: 0c01040a jal 41028 <\.pic\.f1> + 41074: 00000000 nop + 41078: 0c010404 jal 41010 <\.pic\.f2> + 4107c: 00000000 nop + 41080: 0c010400 jal 41000 <\.pic\.f3> + 41084: 00000000 nop + \.\.\. diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-1-r6.nd b/ld/testsuite/ld-mips-elf/pic-and-nonpic-1-r6.nd new file mode 100644 index 00000000000..5264505844b --- /dev/null +++ b/ld/testsuite/ld-mips-elf/pic-and-nonpic-1-r6.nd @@ -0,0 +1,9 @@ +#... +.*: 00041000 +16 +FUNC +LOCAL +DEFAULT .* \.pic\.f3 +.*: 00068000 +0 +NOTYPE +LOCAL +DEFAULT +ABS _gp +.*: 00041028 +8 +FUNC +LOCAL +DEFAULT .* \.pic\.f1 +.*: 00041010 +16 +FUNC +LOCAL +DEFAULT .* \.pic\.f2 +.*: 00041060 +8 +FUNC +GLOBAL +DEFAULT .* f3 +.*: 00041070 +24 +FUNC +GLOBAL +DEFAULT .* __start +.*: 0004104c +20 +FUNC +GLOBAL +DEFAULT .* f2 +.*: 00041030 +28 +FUNC +GLOBAL +DEFAULT .* f1 diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-1-r6.s b/ld/testsuite/ld-mips-elf/pic-and-nonpic-1-r6.s new file mode 100644 index 00000000000..e69de29bb2d diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-1a-r6.s b/ld/testsuite/ld-mips-elf/pic-and-nonpic-1a-r6.s new file mode 100644 index 00000000000..340004bca42 --- /dev/null +++ b/ld/testsuite/ld-mips-elf/pic-and-nonpic-1a-r6.s @@ -0,0 +1,28 @@ + .abicalls + .global f1 + .global f2 + .global f3 + .ent f1 +f1: + .set noreorder + .cpload $25 + .set reorder + .option pic0 + jal f3 + .option pic2 + jr $31 + .end f1 + + .ent f2 +f2: + .set noreorder + .cpload $25 + .set reorder + jr $31 + .end f2 + + .ent f3 +f3: + sll $2,16 + addu $2,$2,$3 + .end f3 diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-3a-r6.dd b/ld/testsuite/ld-mips-elf/pic-and-nonpic-3a-r6.dd new file mode 100644 index 00000000000..80dac37cb43 --- /dev/null +++ b/ld/testsuite/ld-mips-elf/pic-and-nonpic-3a-r6.dd @@ -0,0 +1,36 @@ +# GOT layout: +# +# -32752: lazy resolution function +# -32748: reserved for module pointer +# -32744: the GOT page entry +# -32740: foo's GOT entry +# -32736: ext's GOT entry + +.* + +Disassembly of section \.text: + +00000800 : + 800: 3c1c0001 lui gp,0x1 + 804: 279c7bf0 addiu gp,gp,31728 + 808: 0399e021 addu gp,gp,t9 + 80c: 8f99801c lw t9,-32740\(gp\) + 810: 8f828018 lw v0,-32744\(gp\) + 814: 24420000 addiu v0,v0,0 + 818: d8190000 jrc t9 + +0000081c : + 81c: 3c1c0001 lui gp,0x1 + 820: 279c7bd4 addiu gp,gp,31700 + 824: 0399e021 addu gp,gp,t9 + 828: 8f998020 lw t9,-32736\(gp\) + 82c: d8190000 jrc t9 +#... +Disassembly of section \.MIPS\.stubs: + +00000c00 <_MIPS_STUBS_>: + c00: 8f998010 lw t9,-32752\(gp\) + c04: 03e07825 move t7,ra + c08: 2418[0-9a-f]+ li t8,[0-9]+ + c0c: f8190000 jalrc t9 + \.\.\. diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-3a-r6.gd b/ld/testsuite/ld-mips-elf/pic-and-nonpic-3a-r6.gd new file mode 100644 index 00000000000..af046ee9d0e --- /dev/null +++ b/ld/testsuite/ld-mips-elf/pic-and-nonpic-3a-r6.gd @@ -0,0 +1,21 @@ + +Attribute Section: gnu +File Attributes + Tag_GNU_MIPS_ABI_FP: Hard float \(32-bit CPU, 64-bit FPU\) + +Primary GOT: + Canonical gp value: 000183f0 + + Reserved entries: + Address Access Initial Purpose + 00010400 -32752\(gp\) 00000000 Lazy resolver + 00010404 -32748\(gp\) 80000000 Module pointer \(GNU extension\) + + Local entries: + Address Access Initial + 00010408 -32744\(gp\) 00010000 + + Global entries: + Address Access Initial Sym\.Val\. Type Ndx Name + 0001040c -32740\(gp\) 00000800 00000800 FUNC 6 foo + 00010410 -32736\(gp\) 00000c00 00000c00 FUNC UND ext diff --git a/ld/testsuite/ld-mips-elf/pic-and-nonpic-3a-r6.s b/ld/testsuite/ld-mips-elf/pic-and-nonpic-3a-r6.s new file mode 100644 index 00000000000..fb8eb813dbb --- /dev/null +++ b/ld/testsuite/ld-mips-elf/pic-and-nonpic-3a-r6.s @@ -0,0 +1,26 @@ + .abicalls + .set nomips16 + .global foo + .ent foo +foo: + .set noreorder + .cpload $25 + .set reorder + lw $25,%call16(foo)($28) + lw $2,%got(data)($28) + addiu $2,$2,%lo(data) + jrc $25 + .end foo + + .global bar + .ent bar +bar: + .set noreorder + .cpload $25 + .set reorder + lw $25,%call16(ext)($28) + jrc $25 + .end bar + + .data +data: .word 0x12345678 -- 2.30.2