diff --git a/0001-LoongArch-sync-patch-from-binutils-upstream.patch b/0001-LoongArch-sync-patch-from-binutils-upstream.patch new file mode 100644 index 0000000000000000000000000000000000000000..fee4893f9ab6fe1da9fbe1f0fa59678cda84e6eb --- /dev/null +++ b/0001-LoongArch-sync-patch-from-binutils-upstream.patch @@ -0,0 +1,669 @@ +From 4aad447b3f699584594b0b7920b34636c6e18e93 Mon Sep 17 00:00:00 2001 +From: ticat_fp +Date: Wed, 28 Feb 2024 10:22:02 +0800 +Subject: [PATCH] LoongArch: sync patch from binutils upstream + +Signed-off-by: ticat_fp +--- + bfd/elfnn-loongarch.c | 54 ++++++++----- + bfd/elfxx-loongarch.c | 3 - + gas/config/loongarch-parse.y | 6 +- + gas/config/tc-loongarch.c | 6 +- + gas/testsuite/gas/loongarch/float_op.d | 4 + + gas/testsuite/gas/loongarch/float_op.s | 4 + + gas/testsuite/gas/loongarch/load_store_op.d | 42 ++++++++++ + gas/testsuite/gas/loongarch/load_store_op.s | 42 ++++++++++ + gas/testsuite/gas/loongarch/reloc_type.d | 3 + + gas/testsuite/gas/loongarch/reloc_type.l | 2 + + gas/testsuite/gas/loongarch/reloc_type.s | 3 + + gas/testsuite/gas/loongarch/vector.d | 8 ++ + gas/testsuite/gas/loongarch/vector.s | 8 ++ + ld/emultempl/loongarchelf.em | 20 ++++- + .../ld-loongarch-elf/relax-segment-max.s | 12 +++ + .../ld-loongarch-elf/relax-segment-min.s | 12 +++ + ld/testsuite/ld-loongarch-elf/relax-so.s | 4 + + ld/testsuite/ld-loongarch-elf/relax.exp | 80 +++++++++++++++++-- + opcodes/loongarch-opc.c | 54 +++++++++++++ + 19 files changed, 336 insertions(+), 31 deletions(-) + create mode 100644 gas/testsuite/gas/loongarch/reloc_type.d + create mode 100644 gas/testsuite/gas/loongarch/reloc_type.l + create mode 100644 gas/testsuite/gas/loongarch/reloc_type.s + create mode 100644 ld/testsuite/ld-loongarch-elf/relax-segment-max.s + create mode 100644 ld/testsuite/ld-loongarch-elf/relax-segment-min.s + create mode 100644 ld/testsuite/ld-loongarch-elf/relax-so.s + +diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c +index e9c408b2..db9f106a 100644 +--- a/bfd/elfnn-loongarch.c ++++ b/bfd/elfnn-loongarch.c +@@ -3738,15 +3738,33 @@ loongarch_relax_delete_bytes (bfd *abfd, + + /* Relax pcalau12i,addi.d => pcaddi. */ + static bool +-loongarch_relax_pcala_addi (bfd *abfd, asection *sec, +- Elf_Internal_Rela *rel_hi, bfd_vma symval) ++loongarch_relax_pcala_addi (bfd *abfd, asection *sec, asection *sym_sec, ++ Elf_Internal_Rela *rel_hi, bfd_vma symval, ++ struct bfd_link_info *info, bool *again) + { + bfd_byte *contents = elf_section_data (sec)->this_hdr.contents; + Elf_Internal_Rela *rel_lo = rel_hi + 2; + uint32_t pca = bfd_get (32, abfd, contents + rel_hi->r_offset); + uint32_t add = bfd_get (32, abfd, contents + rel_lo->r_offset); + uint32_t rd = pca & 0x1f; ++ ++ /* This section's output_offset need to subtract the bytes of instructions ++ relaxed by the previous sections, so it needs to be updated beforehand. ++ size_input_section already took care of updating it after relaxation, ++ so we additionally update once here. */ ++ sec->output_offset = sec->output_section->size; + bfd_vma pc = sec_addr (sec) + rel_hi->r_offset; ++ ++ /* If pc and symbol not in the same segment, add/sub segment alignment. ++ FIXME: if there are multiple readonly segments? */ ++ if (!(sym_sec->flags & SEC_READONLY)) ++ { ++ if (symval > pc) ++ pc -= info->maxpagesize; ++ else if (symval < pc) ++ pc += info->maxpagesize; ++ } ++ + const uint32_t addi_d = 0x02c00000; + const uint32_t pcaddi = 0x18000000; + +@@ -3765,14 +3783,18 @@ loongarch_relax_pcala_addi (bfd *abfd, asection *sec, + || ((bfd_signed_vma)(symval - pc) > (bfd_signed_vma)(int32_t)0x1ffffc)) + return false; + ++ /* Continue next relax trip. */ ++ *again = true; ++ + pca = pcaddi | rd; + bfd_put (32, abfd, pca, contents + rel_hi->r_offset); + + /* Adjust relocations. */ + rel_hi->r_info = ELFNN_R_INFO (ELFNN_R_SYM (rel_hi->r_info), + R_LARCH_PCREL20_S2); +- rel_lo->r_info = ELFNN_R_INFO (ELFNN_R_SYM (rel_hi->r_info), +- R_LARCH_DELETE); ++ rel_lo->r_info = ELFNN_R_INFO (0, R_LARCH_NONE); ++ ++ loongarch_relax_delete_bytes (abfd, sec, rel_lo->r_offset, 4, info); + + return true; + } +@@ -3884,7 +3906,6 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec, + || sec->sec_flg0 + || (sec->flags & SEC_RELOC) == 0 + || sec->reloc_count == 0 +- || elf_seg_map (info->output_bfd) == NULL + || (info->disable_target_specific_optimizations + && info->relax_pass == 0) + /* The exp_seg_relro_adjust is enum phase_enum (0x4), +@@ -3992,33 +4013,28 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec, + switch (ELFNN_R_TYPE (rel->r_info)) + { + case R_LARCH_ALIGN: +- if (2 == info->relax_pass) ++ if (1 == info->relax_pass) + loongarch_relax_align (abfd, sec, sym_sec, info, rel, symval); + break; + case R_LARCH_DELETE: +- if (info->relax_pass == 1) ++ if (1 == info->relax_pass) + { + loongarch_relax_delete_bytes (abfd, sec, rel->r_offset, 4, info); + rel->r_info = ELFNN_R_INFO (0, R_LARCH_NONE); + } + break; + case R_LARCH_PCALA_HI20: +- if (info->relax_pass == 0) +- { +- if (i + 4 > sec->reloc_count) +- break; +- loongarch_relax_pcala_addi (abfd, sec, rel, symval); +- } ++ if (0 == info->relax_pass && (i + 4) <= sec->reloc_count) ++ loongarch_relax_pcala_addi (abfd, sec, sym_sec, rel, symval, ++ info, again); + break; + case R_LARCH_GOT_PC_HI20: +- if (local_got) ++ if (local_got && 0 == info->relax_pass ++ && (i + 4) <= sec->reloc_count) + { +- if (i + 4 > sec->reloc_count) +- break; + if (loongarch_relax_pcala_ld (abfd, sec, rel)) +- { +- loongarch_relax_pcala_addi (abfd, sec, rel, symval); +- } ++ loongarch_relax_pcala_addi (abfd, sec, sym_sec, rel, symval, ++ info, again); + } + break; + default: +diff --git a/bfd/elfxx-loongarch.c b/bfd/elfxx-loongarch.c +index 2d299050..35676ead 100644 +--- a/bfd/elfxx-loongarch.c ++++ b/bfd/elfxx-loongarch.c +@@ -1629,9 +1629,6 @@ loongarch_larch_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, + return lht->bfd_type; + } + +- (*_bfd_error_handler) (_("%pB: unsupported relocation type name %s"), +- abfd, l_r_name); +- bfd_set_error (bfd_error_bad_value); + return BFD_RELOC_NONE; + } + +diff --git a/gas/config/loongarch-parse.y b/gas/config/loongarch-parse.y +index f4e1a63b..f786fdae 100644 +--- a/gas/config/loongarch-parse.y ++++ b/gas/config/loongarch-parse.y +@@ -132,7 +132,11 @@ reloc (const char *op_c_str, const char *id_c_str, offsetT addend) + if (0 == strcmp (op_c_str, "plt")) + btype = BFD_RELOC_LARCH_B26; + else +- btype = loongarch_larch_reloc_name_lookup (NULL, op_c_str); ++ { ++ btype = loongarch_larch_reloc_name_lookup (NULL, op_c_str); ++ if (btype == BFD_RELOC_NONE) ++ as_fatal (_("unsupported modifier %s"), op_c_str); ++ } + + if (id_c_str) + { +diff --git a/gas/config/tc-loongarch.c b/gas/config/tc-loongarch.c +index 2e8a259d..29a14e74 100644 +--- a/gas/config/tc-loongarch.c ++++ b/gas/config/tc-loongarch.c +@@ -882,8 +882,10 @@ check_this_insn_before_appending (struct loongarch_cl_insn *ip) + ip->reloc_num++; + } + else if (ip->insn->mask == 0xffff8000 +- /* amswap.w rd, rk, rj */ +- && ((ip->insn_bin & 0xfff00000) == 0x38600000 ++ /* amcas.b rd, rk, rj */ ++ && ((ip->insn_bin & 0xfff80000) == 0x38580000 ++ /* amswap.w rd, rk, rj */ ++ || (ip->insn_bin & 0xfff00000) == 0x38600000 + /* ammax_db.wu rd, rk, rj */ + || (ip->insn_bin & 0xffff0000) == 0x38700000 + /* ammin_db.wu rd, rk, rj */ +diff --git a/gas/testsuite/gas/loongarch/float_op.d b/gas/testsuite/gas/loongarch/float_op.d +index f9d3b89e..b09e7ba0 100644 +--- a/gas/testsuite/gas/loongarch/float_op.d ++++ b/gas/testsuite/gas/loongarch/float_op.d +@@ -83,3 +83,7 @@ Disassembly of section .text: + [ ]+124:[ ]+011d2820 [ ]+ffint.d.l[ ]+[ ]+\$fa0, \$fa1 + [ ]+128:[ ]+011e4420 [ ]+frint.s[ ]+[ ]+\$fa0, \$fa1 + [ ]+12c:[ ]+011e4820 [ ]+frint.d[ ]+[ ]+\$fa0, \$fa1 ++[ ]+130:[ ]+01147420 [ ]+frecipe.s[ ]+[ ]+\$fa0, \$fa1 ++[ ]+134:[ ]+01147820 [ ]+frecipe.d[ ]+[ ]+\$fa0, \$fa1 ++[ ]+138:[ ]+01148420 [ ]+frsqrte.s[ ]+[ ]+\$fa0, \$fa1 ++[ ]+13c:[ ]+01148820 [ ]+frsqrte.d[ ]+[ ]+\$fa0, \$fa1 +diff --git a/gas/testsuite/gas/loongarch/float_op.s b/gas/testsuite/gas/loongarch/float_op.s +index 2e3ec5b8..a83be3e3 100644 +--- a/gas/testsuite/gas/loongarch/float_op.s ++++ b/gas/testsuite/gas/loongarch/float_op.s +@@ -74,3 +74,7 @@ ffint.d.w $f0,$f1 + ffint.d.l $f0,$f1 + frint.s $f0,$f1 + frint.d $f0,$f1 ++frecipe.s $f0,$f1 ++frecipe.d $f0,$f1 ++frsqrte.s $f0,$f1 ++frsqrte.d $f0,$f1 +diff --git a/gas/testsuite/gas/loongarch/load_store_op.d b/gas/testsuite/gas/loongarch/load_store_op.d +index e1b4dea1..0ad83167 100644 +--- a/gas/testsuite/gas/loongarch/load_store_op.d ++++ b/gas/testsuite/gas/loongarch/load_store_op.d +@@ -176,3 +176,45 @@ Disassembly of section .text: + 298:[ ]+387e98a4 [ ]+stle.h[ ]+[ ]+\$a0, \$a1, \$a2 + 29c:[ ]+387f18a4 [ ]+stle.w[ ]+[ ]+\$a0, \$a1, \$a2 + 2a0:[ ]+387f98a4 [ ]+stle.d[ ]+[ ]+\$a0, \$a1, \$a2 ++ 2a4:[ ]+385714c4 [ ]+sc.q[ ]+[ ]+\$a0, \$a1, \$a2 ++ 2a8:[ ]+385714c4 [ ]+sc.q[ ]+[ ]+\$a0, \$a1, \$a2 ++ 2ac:[ ]+385780a4 [ ]+llacq.w[ ]+[ ]+\$a0, \$a1 ++ 2b0:[ ]+385780a4 [ ]+llacq.w[ ]+[ ]+\$a0, \$a1 ++ 2b4:[ ]+385784a4 [ ]+screl.w[ ]+[ ]+\$a0, \$a1 ++ 2b8:[ ]+385784a4 [ ]+screl.w[ ]+[ ]+\$a0, \$a1 ++ 2bc:[ ]+385788a4 [ ]+llacq.d[ ]+[ ]+\$a0, \$a1 ++ 2c0:[ ]+385788a4 [ ]+llacq.d[ ]+[ ]+\$a0, \$a1 ++ 2c4:[ ]+38578ca4 [ ]+screl.d[ ]+[ ]+\$a0, \$a1 ++ 2c8:[ ]+38578ca4 [ ]+screl.d[ ]+[ ]+\$a0, \$a1 ++ 2cc:[ ]+385814c4 [ ]+amcas.b[ ]+[ ]+\$a0, \$a1, \$a2 ++ 2d0:[ ]+385818a4 [ ]+amcas.b[ ]+[ ]+\$a0, \$a2, \$a1 ++ 2d4:[ ]+385894c4 [ ]+amcas.h[ ]+[ ]+\$a0, \$a1, \$a2 ++ 2d8:[ ]+385898a4 [ ]+amcas.h[ ]+[ ]+\$a0, \$a2, \$a1 ++ 2dc:[ ]+385914c4 [ ]+amcas.w[ ]+[ ]+\$a0, \$a1, \$a2 ++ 2e0:[ ]+385918a4 [ ]+amcas.w[ ]+[ ]+\$a0, \$a2, \$a1 ++ 2e4:[ ]+385994c4 [ ]+amcas.d[ ]+[ ]+\$a0, \$a1, \$a2 ++ 2e8:[ ]+385998a4 [ ]+amcas.d[ ]+[ ]+\$a0, \$a2, \$a1 ++ 2ec:[ ]+385a14c4 [ ]+amcas_db.b[ ]+[ ]+\$a0, \$a1, \$a2 ++ 2f0:[ ]+385a18a4 [ ]+amcas_db.b[ ]+[ ]+\$a0, \$a2, \$a1 ++ 2f4:[ ]+385a94c4 [ ]+amcas_db.h[ ]+[ ]+\$a0, \$a1, \$a2 ++ 2f8:[ ]+385a98a4 [ ]+amcas_db.h[ ]+[ ]+\$a0, \$a2, \$a1 ++ 2fc:[ ]+385b14c4 [ ]+amcas_db.w[ ]+[ ]+\$a0, \$a1, \$a2 ++ 300:[ ]+385b18a4 [ ]+amcas_db.w[ ]+[ ]+\$a0, \$a2, \$a1 ++ 304:[ ]+385b94c4 [ ]+amcas_db.d[ ]+[ ]+\$a0, \$a1, \$a2 ++ 308:[ ]+385b98a4 [ ]+amcas_db.d[ ]+[ ]+\$a0, \$a2, \$a1 ++ 30c:[ ]+385c14c4 [ ]+amswap.b[ ]+[ ]+\$a0, \$a1, \$a2 ++ 310:[ ]+385c18a4 [ ]+amswap.b[ ]+[ ]+\$a0, \$a2, \$a1 ++ 314:[ ]+385c94c4 [ ]+amswap.h[ ]+[ ]+\$a0, \$a1, \$a2 ++ 318:[ ]+385c98a4 [ ]+amswap.h[ ]+[ ]+\$a0, \$a2, \$a1 ++ 31c:[ ]+385d14c4 [ ]+amadd.b[ ]+[ ]+\$a0, \$a1, \$a2 ++ 320:[ ]+385d18a4 [ ]+amadd.b[ ]+[ ]+\$a0, \$a2, \$a1 ++ 324:[ ]+385d94c4 [ ]+amadd.h[ ]+[ ]+\$a0, \$a1, \$a2 ++ 328:[ ]+385d98a4 [ ]+amadd.h[ ]+[ ]+\$a0, \$a2, \$a1 ++ 32c:[ ]+385e14c4 [ ]+amswap_db.b[ ]+[ ]+\$a0, \$a1, \$a2 ++ 330:[ ]+385e18a4 [ ]+amswap_db.b[ ]+[ ]+\$a0, \$a2, \$a1 ++ 334:[ ]+385e94c4 [ ]+amswap_db.h[ ]+[ ]+\$a0, \$a1, \$a2 ++ 338:[ ]+385e98a4 [ ]+amswap_db.h[ ]+[ ]+\$a0, \$a2, \$a1 ++ 33c:[ ]+385f14c4 [ ]+amadd_db.b[ ]+[ ]+\$a0, \$a1, \$a2 ++ 340:[ ]+385f18a4 [ ]+amadd_db.b[ ]+[ ]+\$a0, \$a2, \$a1 ++ 344:[ ]+385f94c4 [ ]+amadd_db.h[ ]+[ ]+\$a0, \$a1, \$a2 ++ 348:[ ]+385f98a4 [ ]+amadd_db.h[ ]+[ ]+\$a0, \$a2, \$a1 +diff --git a/gas/testsuite/gas/loongarch/load_store_op.s b/gas/testsuite/gas/loongarch/load_store_op.s +index efbd124a..7912adb1 100644 +--- a/gas/testsuite/gas/loongarch/load_store_op.s ++++ b/gas/testsuite/gas/loongarch/load_store_op.s +@@ -167,3 +167,45 @@ stle.b $r4,$r5,$r6 + stle.h $r4,$r5,$r6 + stle.w $r4,$r5,$r6 + stle.d $r4,$r5,$r6 ++sc.q $r4,$r5,$r6,0 ++sc.q $r4,$r5,$r6 ++llacq.w $r4,$r5,0 ++llacq.w $r4,$r5 ++screl.w $r4,$r5,0 ++screl.w $r4,$r5 ++llacq.d $r4,$r5,0 ++llacq.d $r4,$r5 ++screl.d $r4,$r5,0 ++screl.d $r4,$r5 ++amcas.b $r4,$r5,$r6,0 ++amcas.b $r4,$r6,$r5 ++amcas.h $r4,$r5,$r6,0 ++amcas.h $r4,$r6,$r5 ++amcas.w $r4,$r5,$r6,0 ++amcas.w $r4,$r6,$r5 ++amcas.d $r4,$r5,$r6,0 ++amcas.d $r4,$r6,$r5 ++amcas_db.b $r4,$r5,$r6,0 ++amcas_db.b $r4,$r6,$r5 ++amcas_db.h $r4,$r5,$r6,0 ++amcas_db.h $r4,$r6,$r5 ++amcas_db.w $r4,$r5,$r6,0 ++amcas_db.w $r4,$r6,$r5 ++amcas_db.d $r4,$r5,$r6,0 ++amcas_db.d $r4,$r6,$r5 ++amswap.b $r4,$r5,$r6,0 ++amswap.b $r4,$r6,$r5 ++amswap.h $r4,$r5,$r6,0 ++amswap.h $r4,$r6,$r5 ++amadd.b $r4,$r5,$r6,0 ++amadd.b $r4,$r6,$r5 ++amadd.h $r4,$r5,$r6,0 ++amadd.h $r4,$r6,$r5 ++amswap_db.b $r4,$r5,$r6,0 ++amswap_db.b $r4,$r6,$r5 ++amswap_db.h $r4,$r5,$r6,0 ++amswap_db.h $r4,$r6,$r5 ++amadd_db.b $r4,$r5,$r6,0 ++amadd_db.b $r4,$r6,$r5 ++amadd_db.h $r4,$r5,$r6,0 ++amadd_db.h $r4,$r6,$r5 +diff --git a/gas/testsuite/gas/loongarch/reloc_type.d b/gas/testsuite/gas/loongarch/reloc_type.d +new file mode 100644 +index 00000000..0a8f7782 +--- /dev/null ++++ b/gas/testsuite/gas/loongarch/reloc_type.d +@@ -0,0 +1,3 @@ ++#as: ++#source: reloc_type.s ++#error_output: reloc_type.l +diff --git a/gas/testsuite/gas/loongarch/reloc_type.l b/gas/testsuite/gas/loongarch/reloc_type.l +new file mode 100644 +index 00000000..e981f6f2 +--- /dev/null ++++ b/gas/testsuite/gas/loongarch/reloc_type.l +@@ -0,0 +1,2 @@ ++.*Assembler messages: ++.*Fatal error: unsupported modifier (.*)$ +diff --git a/gas/testsuite/gas/loongarch/reloc_type.s b/gas/testsuite/gas/loongarch/reloc_type.s +new file mode 100644 +index 00000000..2ce27777 +--- /dev/null ++++ b/gas/testsuite/gas/loongarch/reloc_type.s +@@ -0,0 +1,3 @@ ++.L1: ++ nop ++ addi.d $a0,$a1,%reloc(x) +diff --git a/gas/testsuite/gas/loongarch/vector.d b/gas/testsuite/gas/loongarch/vector.d +index 1a092bca..4526b3d3 100644 +--- a/gas/testsuite/gas/loongarch/vector.d ++++ b/gas/testsuite/gas/loongarch/vector.d +@@ -1459,3 +1459,11 @@ Disassembly of section .text: + [ ]+16a0:[ ]+77e40420[ ]+xvpermi.w[ ]+\$xr0,[ ]+\$xr1,[ ]+0x1 + [ ]+16a4:[ ]+77e80420[ ]+xvpermi.d[ ]+\$xr0,[ ]+\$xr1,[ ]+0x1 + [ ]+16a8:[ ]+77ec0420[ ]+xvpermi.q[ ]+\$xr0,[ ]+\$xr1,[ ]+0x1 ++[ ]+16ac:[ ]+729d1420[ ]+vfrecipe.s[ ]+\$vr0,[ ]+\$vr1 ++[ ]+16b0:[ ]+729d1820[ ]+vfrecipe.d[ ]+\$vr0,[ ]+\$vr1 ++[ ]+16b4:[ ]+729d2420[ ]+vfrsqrte.s[ ]+\$vr0,[ ]+\$vr1 ++[ ]+16b8:[ ]+729d2820[ ]+vfrsqrte.d[ ]+\$vr0,[ ]+\$vr1 ++[ ]+16bc:[ ]+769d1420[ ]+xvfrecipe.s[ ]+\$xr0,[ ]+\$xr1 ++[ ]+16c0:[ ]+769d1820[ ]+xvfrecipe.d[ ]+\$xr0,[ ]+\$xr1 ++[ ]+16c4:[ ]+769d2420[ ]+xvfrsqrte.s[ ]+\$xr0,[ ]+\$xr1 ++[ ]+16c8:[ ]+769d2820[ ]+xvfrsqrte.d[ ]+\$xr0,[ ]+\$xr1 +diff --git a/gas/testsuite/gas/loongarch/vector.s b/gas/testsuite/gas/loongarch/vector.s +index fe0369e7..0283a4b4 100644 +--- a/gas/testsuite/gas/loongarch/vector.s ++++ b/gas/testsuite/gas/loongarch/vector.s +@@ -1449,3 +1449,11 @@ xvldi $xr0, 1 + xvpermi.w $xr0, $xr1, 1 + xvpermi.d $xr0, $xr1, 1 + xvpermi.q $xr0, $xr1, 1 ++vfrecipe.s $vr0, $vr1 ++vfrecipe.d $vr0, $vr1 ++vfrsqrte.s $vr0, $vr1 ++vfrsqrte.d $vr0, $vr1 ++xvfrecipe.s $xr0, $xr1 ++xvfrecipe.d $xr0, $xr1 ++xvfrsqrte.s $xr0, $xr1 ++xvfrsqrte.d $xr0, $xr1 +diff --git a/ld/emultempl/loongarchelf.em b/ld/emultempl/loongarchelf.em +index 4850feb8..99749894 100644 +--- a/ld/emultempl/loongarchelf.em ++++ b/ld/emultempl/loongarchelf.em +@@ -42,7 +42,7 @@ larch_elf_before_allocation (void) + ENABLE_RELAXATION; + } + +- link_info.relax_pass = 3; ++ link_info.relax_pass = 2; + } + + static void +@@ -62,6 +62,24 @@ gld${EMULATION_NAME}_after_allocation (void) + } + } + ++ /* The program header size of executable file may increase. */ ++ if (bfd_get_flavour (link_info.output_bfd) == bfd_target_elf_flavour ++ && !bfd_link_relocatable (&link_info)) ++ { ++ if (lang_phdr_list == NULL) ++ elf_seg_map (link_info.output_bfd) = NULL; ++ if (!_bfd_elf_map_sections_to_segments (link_info.output_bfd, ++ &link_info, ++ NULL)) ++ einfo (_("%F%P: map sections to segments failed: %E\n")); ++ } ++ ++ /* Adjust program header size and .eh_frame_hdr size before ++ lang_relax_sections. Without it, the vma of data segment may increase. */ ++ lang_do_assignments (lang_allocating_phase_enum); ++ lang_reset_memory_regions (); ++ lang_size_sections (NULL, true); ++ + enum phase_enum *phase = &(expld.dataseg.phase); + bfd_elf${ELFSIZE}_loongarch_set_data_segment_info (&link_info, (int *) phase); + /* gld${EMULATION_NAME}_map_segments (need_layout); */ +diff --git a/ld/testsuite/ld-loongarch-elf/relax-segment-max.s b/ld/testsuite/ld-loongarch-elf/relax-segment-max.s +new file mode 100644 +index 00000000..df15d4ca +--- /dev/null ++++ b/ld/testsuite/ld-loongarch-elf/relax-segment-max.s +@@ -0,0 +1,12 @@ ++# The .align may cause overflow because deleting nops. ++ .text # 0x120004000 ++ .align 3 ++ la.local $r12, .L1 ++ ++# .fill 0x1f7ffc # max fill without overflow, .data address is 0x120200000 ++# .fill 0x1f8000 # min fill with overflow, .data address is 0x120204000 ++ .fill 0x1fbff4 # max fill with overflow, .data address is 0x120204000 ++ ++ .data ++.L1: ++ .byte 2 +diff --git a/ld/testsuite/ld-loongarch-elf/relax-segment-min.s b/ld/testsuite/ld-loongarch-elf/relax-segment-min.s +new file mode 100644 +index 00000000..476b9fba +--- /dev/null ++++ b/ld/testsuite/ld-loongarch-elf/relax-segment-min.s +@@ -0,0 +1,12 @@ ++# The .align may cause overflow because deleting nops. ++ .text # 0x120004000 ++ .align 3 ++ la.local $r12, .L1 ++ ++# .fill 0x1f7ffc # max fill without overflow, .data address is 0x120200000 ++ .fill 0x1f8000 # min fill with overflow, .data address is 0x120204000 ++# .fill 0x1fbff4 # max fill with overflow, .data address is 0x120204000 ++ ++ .data ++.L1: ++ .byte 2 +diff --git a/ld/testsuite/ld-loongarch-elf/relax-so.s b/ld/testsuite/ld-loongarch-elf/relax-so.s +new file mode 100644 +index 00000000..01a404a8 +--- /dev/null ++++ b/ld/testsuite/ld-loongarch-elf/relax-so.s +@@ -0,0 +1,4 @@ ++.text ++.align 2 ++.L1: ++ la.local $r12, .L1 +diff --git a/ld/testsuite/ld-loongarch-elf/relax.exp b/ld/testsuite/ld-loongarch-elf/relax.exp +index 7ff876d7..24d79ed5 100644 +--- a/ld/testsuite/ld-loongarch-elf/relax.exp ++++ b/ld/testsuite/ld-loongarch-elf/relax.exp +@@ -22,7 +22,7 @@ + if [istarget loongarch64-*-*] { + + if [isbuild loongarch64-*-*] { +- set testname "loongarch relax build" ++ set testname "loongarch relax .exe build" + set pre_builds [list \ + [list \ + "$testname" \ +@@ -39,17 +39,87 @@ if [istarget loongarch64-*-*] { + if [file exist "tmpdir/relax"] { + set objdump_output [run_host_cmd "objdump" "-d tmpdir/relax"] + if { [ regexp ".*pcaddi.*pcaddi.*" $objdump_output] } { +- pass "loongarch relax" ++ pass "loongarch relax .exe" + } { +- fail "loongarch relax" ++ fail "loongarch relax .exe" + } + } ++ ++ set testname "loongarch ld --no-relax build" ++ set pre_builds [list \ ++ [list \ ++ "$testname" \ ++ "-Wl,--no-relax" \ ++ "" \ ++ {relax.s} \ ++ {} \ ++ "norelax" \ ++ ] \ ++ ] ++ ++ run_cc_link_tests $pre_builds ++ ++ if [file exist "tmpdir/norelax"] { ++ set objdump_output [run_host_cmd "objdump" "-d tmpdir/norelax"] ++ if { [ regexp ".*pcaddi.*" $objdump_output] } { ++ fail "loongarch ld --no-relax" ++ } { ++ pass "loongarch ld --no-relax" ++ } ++ } ++ ++ run_ld_link_tests \ ++ [list \ ++ [list \ ++ "loongarch relax .so build" \ ++ "-shared -e 0x0" "" \ ++ "" \ ++ {relax-so.s} \ ++ {} \ ++ "relax-so" \ ++ ] \ ++ ] ++ ++ if [file exist "tmpdir/relax-so"] { ++ set objdump_output [run_host_cmd "objdump" "-d tmpdir/relax-so"] ++ if { [ regexp ".*pcaddi.*" $objdump_output] } { ++ pass "loongarch relax .so" ++ } { ++ fail "loongarch relax .so" ++ } ++ } ++ ++ # If symbol in data segment, offset need to sub segment align to prevent ++ # overflow. ++ run_ld_link_tests \ ++ [list \ ++ [list \ ++ "loongarch relax segment alignment min" \ ++ "-e0 -Ttext 0x120004000 -pie -z relro" "" \ ++ "" \ ++ {relax-segment-min.s} \ ++ {} \ ++ "relax-segment-min" \ ++ ] \ ++ ] ++ ++ run_ld_link_tests \ ++ [list \ ++ [list \ ++ "loongarch relax segment alignment max" \ ++ "-e0 -Ttext 0x120004000 -pie -z relro" "" \ ++ "" \ ++ {relax-segment-max.s} \ ++ {} \ ++ "relax-segment-max" \ ++ ] \ ++ ] + } + + run_ld_link_tests \ + [list \ + [list \ +- "relax-align" \ ++ "loongarch relax-align" \ + "-e 0x0 -z relro" "" \ + "" \ + {relax-align.s} \ +@@ -64,7 +134,7 @@ if [istarget loongarch64-*-*] { + run_ld_link_tests \ + [list \ + [list \ +- "uleb128" \ ++ "loongarch uleb128" \ + "-e 0x0" "" \ + "" \ + {uleb128.s} \ +diff --git a/opcodes/loongarch-opc.c b/opcodes/loongarch-opc.c +index 2f02e33d..4a88c4d7 100644 +--- a/opcodes/loongarch-opc.c ++++ b/opcodes/loongarch-opc.c +@@ -482,6 +482,8 @@ static struct loongarch_opcode loongarch_single_float_opcodes[] = + { 0x01144400, 0xfffffc00, "fsqrt.s", "f0:5,f5:5", 0, 0, 0, 0 }, + { 0x01145400, 0xfffffc00, "frecip.s", "f0:5,f5:5", 0, 0, 0, 0 }, + { 0x01146400, 0xfffffc00, "frsqrt.s", "f0:5,f5:5", 0, 0, 0, 0 }, ++ { 0x01147400, 0xfffffc00, "frecipe.s", "f0:5,f5:5", 0, 0, 0, 0 }, ++ { 0x01148400, 0xfffffc00, "frsqrte.s", "f0:5,f5:5", 0, 0, 0, 0 }, + { 0x01149400, 0xfffffc00, "fmov.s", "f0:5,f5:5", 0, 0, 0, 0 }, + { 0x0114a400, 0xfffffc00, "movgr2fr.w", "f0:5,r5:5", 0, 0, 0, 0 }, + { 0x0114ac00, 0xfffffc00, "movgr2frh.w", "f0:5,r5:5", 0, 0, 0, 0 }, +@@ -528,6 +530,8 @@ static struct loongarch_opcode loongarch_double_float_opcodes[] = + { 0x01144800, 0xfffffc00, "fsqrt.d", "f0:5,f5:5", 0, 0, 0, 0 }, + { 0x01145800, 0xfffffc00, "frecip.d", "f0:5,f5:5", 0, 0, 0, 0 }, + { 0x01146800, 0xfffffc00, "frsqrt.d", "f0:5,f5:5", 0, 0, 0, 0 }, ++ { 0x01147800, 0xfffffc00, "frecipe.d", "f0:5,f5:5", 0, 0, 0, 0 }, ++ { 0x01148800, 0xfffffc00, "frsqrte.d", "f0:5,f5:5", 0, 0, 0, 0 }, + { 0x01149800, 0xfffffc00, "fmov.d", "f0:5,f5:5", 0, 0, 0, 0 }, + { 0x0114a800, 0xfffffc00, "movgr2fr.d", "f0:5,r5:5", 0, 0, 0, 0 }, + { 0x0114b800, 0xfffffc00, "movfr2gr.d", "r0:5,f5:5", 0, 0, 0, 0 }, +@@ -816,6 +820,48 @@ static struct loongarch_opcode loongarch_load_store_opcodes[] = + { 0x38240000, 0xffff8000, "ldx.hu", "r0:5,r5:5,r10:5", 0, 0, 0, 0 }, + { 0x38280000, 0xffff8000, "ldx.wu", "r0:5,r5:5,r10:5", 0, 0, 0, 0 }, + { 0x382c0000, 0xffff8000, "preldx", "u0:5,r5:5,r10:5", 0, 0, 0, 0 }, ++ { 0x0, 0x0, "sc.q", "r,r,r,u0:0", "sc.q %1,%2,%3", 0, 0, 0 }, ++ { 0x38570000, 0xffff8000, "sc.q", "r0:5,r10:5,r5:5", 0, 0, 0, 0 }, ++ { 0x0, 0x0, "llacq.w", "r,r,u0:0", "llacq.w %1,%2", 0, 0, 0 }, ++ { 0x38578000, 0xfffffc00, "llacq.w", "r0:5,r5:5", 0, 0, 0, 0 }, ++ { 0x0, 0x0, "screl.w", "r,r,u0:0", "screl.w %1,%2", 0, 0, 0 }, ++ { 0x38578400, 0xfffffc00, "screl.w", "r0:5,r5:5", 0, 0, 0, 0 }, ++ { 0x0, 0x0, "llacq.d", "r,r,u0:0", "llacq.d %1,%2", 0, 0, 0 }, ++ { 0x38578800, 0xfffffc00, "llacq.d", "r0:5,r5:5", 0, 0, 0, 0 }, ++ { 0x0, 0x0, "screl.d", "r,r,u0:0", "screl.d %1,%2", 0, 0, 0 }, ++ { 0x38578c00, 0xfffffc00, "screl.d", "r0:5,r5:5", 0, 0, 0, 0 }, ++ { 0x0, 0x0, "amcas.b", "r,r,r,u0:0", "amcas.b %1,%2,%3", 0, 0, 0 }, ++ { 0x38580000, 0xffff8000, "amcas.b", "r0:5,r10:5,r5:5", 0, 0, 0, 0 }, ++ { 0x0, 0x0, "amcas.h", "r,r,r,u0:0", "amcas.h %1,%2,%3", 0, 0, 0 }, ++ { 0x38588000, 0xffff8000, "amcas.h", "r0:5,r10:5,r5:5", 0, 0, 0, 0 }, ++ { 0x0, 0x0, "amcas.w", "r,r,r,u0:0", "amcas.w %1,%2,%3", 0, 0, 0 }, ++ { 0x38590000, 0xffff8000, "amcas.w", "r0:5,r10:5,r5:5", 0, 0, 0, 0 }, ++ { 0x0, 0x0, "amcas.d", "r,r,r,u0:0", "amcas.d %1,%2,%3", 0, 0, 0 }, ++ { 0x38598000, 0xffff8000, "amcas.d", "r0:5,r10:5,r5:5", 0, 0, 0, 0 }, ++ { 0x0, 0x0, "amcas_db.b", "r,r,r,u0:0", "amcas_db.b %1,%2,%3", 0, 0, 0 }, ++ { 0x385a0000, 0xffff8000, "amcas_db.b", "r0:5,r10:5,r5:5", 0, 0, 0, 0 }, ++ { 0x0, 0x0, "amcas_db.h", "r,r,r,u0:0", "amcas_db.h %1,%2,%3", 0, 0, 0 }, ++ { 0x385a8000, 0xffff8000, "amcas_db.h", "r0:5,r10:5,r5:5", 0, 0, 0, 0 }, ++ { 0x0, 0x0, "amcas_db.w", "r,r,r,u0:0", "amcas_db.w %1,%2,%3", 0, 0, 0 }, ++ { 0x385b0000, 0xffff8000, "amcas_db.w", "r0:5,r10:5,r5:5", 0, 0, 0, 0 }, ++ { 0x0, 0x0, "amcas_db.d", "r,r,r,u0:0", "amcas_db.d %1,%2,%3", 0, 0, 0 }, ++ { 0x385b8000, 0xffff8000, "amcas_db.d", "r0:5,r10:5,r5:5", 0, 0, 0, 0 }, ++ { 0x0, 0x0, "amswap.b", "r,r,r,u0:0", "amswap.b %1,%2,%3", 0, 0, 0 }, ++ { 0x385c0000, 0xffff8000, "amswap.b", "r0:5,r10:5,r5:5", 0, 0, 0, 0 }, ++ { 0x0, 0x0, "amswap.h", "r,r,r,u0:0", "amswap.h %1,%2,%3", 0, 0, 0 }, ++ { 0x385c8000, 0xffff8000, "amswap.h", "r0:5,r10:5,r5:5", 0, 0, 0, 0 }, ++ { 0x0, 0x0, "amadd.b", "r,r,r,u0:0", "amadd.b %1,%2,%3", 0, 0, 0 }, ++ { 0x385d0000, 0xffff8000, "amadd.b", "r0:5,r10:5,r5:5", 0, 0, 0, 0 }, ++ { 0x0, 0x0, "amadd.h", "r,r,r,u0:0", "amadd.h %1,%2,%3", 0, 0, 0 }, ++ { 0x385d8000, 0xffff8000, "amadd.h", "r0:5,r10:5,r5:5", 0, 0, 0, 0 }, ++ { 0x0, 0x0, "amswap_db.b", "r,r,r,u0:0", "amswap_db.b %1,%2,%3", 0, 0, 0 }, ++ { 0x385e0000, 0xffff8000, "amswap_db.b", "r0:5,r10:5,r5:5", 0, 0, 0, 0 }, ++ { 0x0, 0x0, "amswap_db.h", "r,r,r,u0:0", "amswap_db.h %1,%2,%3", 0, 0, 0 }, ++ { 0x385e8000, 0xffff8000, "amswap_db.h", "r0:5,r10:5,r5:5", 0, 0, 0, 0 }, ++ { 0x0, 0x0, "amadd_db.b", "r,r,r,u0:0", "amadd_db.b %1,%2,%3", 0, 0, 0 }, ++ { 0x385f0000, 0xffff8000, "amadd_db.b", "r0:5,r10:5,r5:5", 0, 0, 0, 0 }, ++ { 0x0, 0x0, "amadd_db.h", "r,r,r,u0:0", "amadd_db.h %1,%2,%3", 0, 0, 0 }, ++ { 0x385f8000, 0xffff8000, "amadd_db.h", "r0:5,r10:5,r5:5", 0, 0, 0, 0 }, + { 0x0, 0x0, "amswap.w", "r,r,r,u0:0", "amswap.w %1,%2,%3", 0, 0, 0 }, + { 0x38600000, 0xffff8000, "amswap.w", "r0:5,r10:5,r5:5", 0, 0, 0, 0 }, + { 0x0, 0x0, "amswap.d", "r,r,r,u0:0", "amswap.d %1,%2,%3", 0, 0, 0 }, +@@ -1382,6 +1428,10 @@ static struct loongarch_opcode loongarch_lsx_opcodes[] = + { 0x729cf800, 0xfffffc00, "vfrecip.d", "v0:5,v5:5", 0, 0, 0, 0}, + { 0x729d0400, 0xfffffc00, "vfrsqrt.s", "v0:5,v5:5", 0, 0, 0, 0}, + { 0x729d0800, 0xfffffc00, "vfrsqrt.d", "v0:5,v5:5", 0, 0, 0, 0}, ++ { 0x729d1400, 0xfffffc00, "vfrecipe.s", "v0:5,v5:5", 0, 0, 0, 0}, ++ { 0x729d1800, 0xfffffc00, "vfrecipe.d", "v0:5,v5:5", 0, 0, 0, 0}, ++ { 0x729d2400, 0xfffffc00, "vfrsqrte.s", "v0:5,v5:5", 0, 0, 0, 0}, ++ { 0x729d2800, 0xfffffc00, "vfrsqrte.d", "v0:5,v5:5", 0, 0, 0, 0}, + { 0x729d3400, 0xfffffc00, "vfrint.s", "v0:5,v5:5", 0, 0, 0, 0}, + { 0x729d3800, 0xfffffc00, "vfrint.d", "v0:5,v5:5", 0, 0, 0, 0}, + { 0x729d4400, 0xfffffc00, "vfrintrm.s", "v0:5,v5:5", 0, 0, 0, 0}, +@@ -2127,6 +2177,10 @@ static struct loongarch_opcode loongarch_lasx_opcodes[] = + { 0x769cf800, 0xfffffc00, "xvfrecip.d", "x0:5,x5:5", 0, 0, 0, 0}, + { 0x769d0400, 0xfffffc00, "xvfrsqrt.s", "x0:5,x5:5", 0, 0, 0, 0}, + { 0x769d0800, 0xfffffc00, "xvfrsqrt.d", "x0:5,x5:5", 0, 0, 0, 0}, ++ { 0x769d1400, 0xfffffc00, "xvfrecipe.s", "x0:5,x5:5", 0, 0, 0, 0}, ++ { 0x769d1800, 0xfffffc00, "xvfrecipe.d", "x0:5,x5:5", 0, 0, 0, 0}, ++ { 0x769d2400, 0xfffffc00, "xvfrsqrte.s", "x0:5,x5:5", 0, 0, 0, 0}, ++ { 0x769d2800, 0xfffffc00, "xvfrsqrte.d", "x0:5,x5:5", 0, 0, 0, 0}, + { 0x769d3400, 0xfffffc00, "xvfrint.s", "x0:5,x5:5", 0, 0, 0, 0}, + { 0x769d3800, 0xfffffc00, "xvfrint.d", "x0:5,x5:5", 0, 0, 0, 0}, + { 0x769d4400, 0xfffffc00, "xvfrintrm.s", "x0:5,x5:5", 0, 0, 0, 0}, +-- +2.33.0 + diff --git a/binutils.spec b/binutils.spec index 65281c749bfea05096e482ac3e268bc3eff76aa5..95dfb7ca621143d89c0e7f80f9877f6c075aefab 100644 --- a/binutils.spec +++ b/binutils.spec @@ -2,7 +2,7 @@ Summary: A GNU collection of binary utilities Name: binutils%{?_with_debug:-debug} Version: 2.41 -Release: 1 +Release: 2 License: GPL-3.0-or-later AND (GPL-3.0-or-later WITH Bison-exception-2.2) AND (LGPL-2.0-or-later WITH GCC-exception-2.0) AND BSD-3-Clause AND GFDL-1.3-or-later AND GPL-2.0-or-later AND LGPL-2.1-or-later AND LGPL-2.0-or-later URL: https://sourceware.org/binutils @@ -78,7 +78,7 @@ URL: https://sourceware.org/binutils #----End of Configure Options------------------------------------------------ # Note - in the future the gold linker may become deprecated. -%ifnarch riscv64 +%ifnarch riscv64 loongarch64 %bcond_without gold %else # RISC-V does not have ld.gold thus disable by default. @@ -217,6 +217,9 @@ Patch5007: binutils-update-linker-manual.patch # Lifetime: Fixed in 2.42 (maybe) Patch5008: binutils-gold-empty-dwp.patch +# Purpose: Fix R_LARCH_ALIGN. +# Lifetime: Permanent +Patch5009: 0001-LoongArch-sync-patch-from-binutils-upstream.patch #---------------------------------------------------------------------------- @@ -1256,6 +1259,9 @@ exit 0 #---------------------------------------------------------------------------- %changelog +* Wed Feb 28 2024 Peng Fan - 2.41-2 +- LoongArch: Fix R_LARCH_ALIGN + * Mon Feb 26 2024 eastb233 - 2.41-1 - Update binutils 2.41 - Reference: https://gitlab.com/redhat/centos-stream/rpms/binutils/-/tree/c10s