]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
PR 19977: MIPS: Add missing pairing for REL PCHI/PCLO relocations
authorMaciej W. Rozycki <macro@orcam.me.uk>
Sat, 12 Jul 2025 00:25:53 +0000 (01:25 +0100)
committerMaciej W. Rozycki <macro@orcam.me.uk>
Sat, 12 Jul 2025 00:25:53 +0000 (01:25 +0100)
Just as with all HI/LO 16-bit partial relocations the newly-introduced
MIPSr6 PC-relative R_MIPS_PCHI16 and R_MIPS_PCLO16 relocations require
pairing for correct borrow propagation from the low part to the high
part with REL targets, another case for PR 19977.

Unlike with absolute relocation, there is a complication here in that
both parts represent a calculation that is relative to the PC at the
individual relocation's location rather than both referring to the
location of the R_MIPS_PCHI16 relocation, normally applied to an AUIPC
instruction, the location of which is used for the run-time calculation
executed by hardware.

To take this semantics into account, the addend of the R_MIPS_PCLO16
relocation matching a given R_MIPS_PCHI16 relocation is expected to be
adjusted in the source assembly file for the distance between the two
relocations in a single pair, so that once both relocations have been
calculated by the linker, the expression calculated at run time is such
as if the combined 32-bit immediate was added at the location of the
AUIPC instruction.

So for matching R_MIPS_PCHI16 and R_MIPS_PCLO16 relocations into pairs
GAS needs to check for the distance between the two relocations to be
equal to the difference between the addends supplied, and then the
linker has to subtract the low part of the distance between the two
relocations from the low part in calculating the high part, so as to
factor in any borrow.

A further complication is that `_bfd_mips_elf_lo16_reloc' handler is
supplied with the addend differently depending on whether it has been
called by GAS via `bfd_install_relocation', or by the generic linker via
`bfd_perform_relocation'.  In the former case the addend is supplied
with the relocation itself while in the latter one it comes from the
field being relocated.

We currently ignore the addend supplied with the relocation and it works
for calculating absolute high-part relocations, because the same addend
has been previously supplied with them when `_bfd_mips_elf_hi16_reloc'
was called, however this approach does not work for the PC-relative case
because as noted above the low-part addend is different and we need to
consistently apply the distance adjustment both with GAS and LD.

Since the supplied addend and one retrieved from field being relocated
won't ever be both nonzero, just use the sum of the two values.

The low-part addend in `mips_elf_add_lo16_rel_addend' always comes from
the field being relocated, so there's no complication there, we just
need to apply the same adjustment.

New linker test cases verify that the same ultimate machine code is
produced both for ELF and S-record output formats, ensuring that the
both the MIPS/ELF linker and the generic linker behave in the correct
way, consistent with each other.

17 files changed:
bfd/elf32-mips.c
bfd/elf64-mips.c
bfd/elfn32-mips.c
bfd/elfxx-mips.c
gas/config/tc-mips.c
gas/testsuite/gas/mips/mips.exp
gas/testsuite/gas/mips/pcrel-hilo-64.d [new file with mode: 0644]
gas/testsuite/gas/mips/pcrel-hilo-addend.d [new file with mode: 0644]
gas/testsuite/gas/mips/pcrel-hilo-match.d [new file with mode: 0644]
gas/testsuite/gas/mips/pcrel-hilo-match.s [new file with mode: 0644]
gas/testsuite/gas/mips/pcrel-hilo-n32.d [new file with mode: 0644]
gas/testsuite/gas/mips/pcrel-hilo.d [new file with mode: 0644]
gas/testsuite/gas/mips/pcrel-hilo.s [new file with mode: 0644]
ld/testsuite/ld-mips-elf/mips-elf.exp
ld/testsuite/ld-mips-elf/pcrel-hilo-srec.d [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pcrel-hilo.d [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pcrel-hilo.ld [new file with mode: 0644]

index 6fe93a893e8dee28672eabe1ef8fd4a3dc1b8cbd..45856b14af0fd3c3e067c389064b41fe4d2e3e01 100644 (file)
@@ -789,7 +789,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] =
         true,                  /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        _bfd_mips_elf_generic_reloc,   /* special_function */
+        _bfd_mips_elf_hi16_reloc, /* special_function */
         "R_MIPS_PCHI16",       /* name */
         true,                  /* partial_inplace */
         0x0000ffff,            /* src_mask */
@@ -803,7 +803,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] =
         true,                  /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        _bfd_mips_elf_generic_reloc,   /* special_function */
+        _bfd_mips_elf_lo16_reloc, /* special_function */
         "R_MIPS_PCLO16",       /* name */
         true,                  /* partial_inplace */
         0x0000ffff,            /* src_mask */
index 5b5521079e1b51d0b0f3a90bc706f4596e8f1f63..29dcadd3230bc42a25d0b6ab6b16067273afef0a 100644 (file)
@@ -868,7 +868,7 @@ static reloc_howto_type mips_elf64_howto_table_rel[] =
         true,                  /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        _bfd_mips_elf_generic_reloc,   /* special_function */
+        _bfd_mips_elf_hi16_reloc, /* special_function */
         "R_MIPS_PCHI16",       /* name */
         true,                  /* partial_inplace */
         0x0000ffff,            /* src_mask */
@@ -882,7 +882,7 @@ static reloc_howto_type mips_elf64_howto_table_rel[] =
         true,                  /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        _bfd_mips_elf_generic_reloc,   /* special_function */
+        _bfd_mips_elf_lo16_reloc, /* special_function */
         "R_MIPS_PCLO16",       /* name */
         true,                  /* partial_inplace */
         0x0000ffff,            /* src_mask */
index e457bfc984913dcdcb43f8affef54f63bb01b42d..d72e2f5236a025462e632c4da63f5f85603519a1 100644 (file)
@@ -847,7 +847,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] =
         true,                  /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        _bfd_mips_elf_generic_reloc,   /* special_function */
+        _bfd_mips_elf_hi16_reloc, /* special_function */
         "R_MIPS_PCHI16",       /* name */
         true,                  /* partial_inplace */
         0x0000ffff,            /* src_mask */
@@ -861,7 +861,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] =
         true,                  /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        _bfd_mips_elf_generic_reloc,   /* special_function */
+        _bfd_mips_elf_lo16_reloc, /* special_function */
         "R_MIPS_PCLO16",       /* name */
         true,                  /* partial_inplace */
         0x0000ffff,            /* src_mask */
index 6f323289ad613948d8208909ebabe1342b398ea5..7d1dff1d7212f4eafd69b77869a87f85be05bde9 100644 (file)
@@ -2600,20 +2600,22 @@ _bfd_mips_elf_lo16_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
      extended.  For example, an addend of 0x38000 would have 0x0004 in
      the high part and 0x8000 (=0xff..f8000) in the low part.
      To extract the actual addend, calculate
-     ((hi & 0xffff) << 16) + ((lo & 0xffff) ^ 0x8000) - 0x8000.
-     We will be applying (symbol + addend) & 0xffff to the low insn,
-     and we want to apply (symbol + addend + 0x8000) >> 16 to the
-     high insn (the +0x8000 adjusting for when the applied low part is
-     negative).  */
+     ((hi & 0xffff) << 16) + ((lo & 0xffff) ^ 0x8000) - 0x8000.  */
   vallo = _bfd_mips_elf_sign_extend (bfd_get_32 (abfd, location) & 0xffff, 16);
   _bfd_mips_elf_reloc_shuffle (abfd, reloc_entry->howto->type, false,
                               location);
+  /* Add in the separate addend, if any.  Since we are REL here this
+     will have been set and the in-place addend cleared if we have
+     been called from GAS via `bfd_install_relocation'.  */
+  vallo += reloc_entry->addend;
 
   tdata = mips_elf_tdata (abfd);
   while (tdata->mips_hi16_list != NULL)
     {
       bfd_reloc_status_type ret;
       struct mips_hi16 *hi;
+      bfd_vma addhi;
+      bfd_vma addlo;
 
       hi = tdata->mips_hi16_list;
 
@@ -2629,7 +2631,19 @@ _bfd_mips_elf_lo16_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
       else if (hi->rel.howto->type == R_MICROMIPS_GOT16)
        hi->rel.howto = MIPS_ELF_RTYPE_TO_HOWTO (abfd, R_MICROMIPS_HI16, false);
 
-      hi->rel.addend += vallo;
+      /* We will be applying (symbol + addend) & 0xffff to the low insn,
+        and we want to apply (symbol + addend + 0x8000) >> 16 to the
+        high insn (the +0x8000 adjusting for when the applied low part is
+        negative).  */
+      addhi = (hi->rel.addend + 0x8000) & ~(bfd_vma) 0xffff;
+      addlo = vallo;
+
+      /* For a PC-relative relocation the PCLO16 part of the addend
+        is relative to its PC and not ours, so we need to adjust it.  */
+      if (hi->rel.howto->type == R_MIPS_PCHI16)
+       addlo -= reloc_entry->address - hi->rel.address;
+
+      hi->rel.addend = addhi + _bfd_mips_elf_sign_extend (addlo & 0xffff, 16);
 
       ret = _bfd_mips_elf_generic_reloc (abfd, &hi->rel, symbol, hi->data,
                                         hi->input_section, output_bfd,
@@ -8334,6 +8348,10 @@ mips_elf_add_lo16_rel_addend (bfd *abfd,
                                contents);
 
   l <<= lo16_howto->rightshift;
+  /* For a PC-relative relocation the PCLO16 part of the addend
+     is relative to its PC and not ours, so we need to adjust it.  */
+  if (r_type == R_MIPS_PCHI16)
+    l = (l - (lo16_relocation->r_offset - rel->r_offset)) & 0xffff;
   l = _bfd_mips_elf_sign_extend (l, 16);
 
   *addend <<= 16;
index 9134cef96beede4a20cac705ff5e3adde1f727a6..7d0d855911540a7585356d0ad0fa8d62804a7408 100644 (file)
@@ -4328,14 +4328,16 @@ got16_reloc_p (bfd_reloc_code_real_type reloc)
 static inline bool
 hi16_reloc_p (bfd_reloc_code_real_type reloc)
 {
-  return (reloc == BFD_RELOC_HI16_S || reloc == BFD_RELOC_MIPS16_HI16_S
+  return (reloc == BFD_RELOC_HI16_S || reloc == BFD_RELOC_HI16_S_PCREL
+         || reloc == BFD_RELOC_MIPS16_HI16_S
          || reloc == BFD_RELOC_MICROMIPS_HI16_S);
 }
 
 static inline bool
 lo16_reloc_p (bfd_reloc_code_real_type reloc)
 {
-  return (reloc == BFD_RELOC_LO16 || reloc == BFD_RELOC_MIPS16_LO16
+  return (reloc == BFD_RELOC_LO16 || reloc == BFD_RELOC_LO16_PCREL
+         || reloc == BFD_RELOC_MIPS16_LO16
          || reloc == BFD_RELOC_MICROMIPS_LO16);
 }
 
@@ -4402,8 +4404,9 @@ static inline bfd_reloc_code_real_type
 matching_lo_reloc (bfd_reloc_code_real_type reloc)
 {
   return (mips16_reloc_p (reloc) ? BFD_RELOC_MIPS16_LO16
-         : (micromips_reloc_p (reloc) ? BFD_RELOC_MICROMIPS_LO16
-            : BFD_RELOC_LO16));
+         : micromips_reloc_p (reloc) ? BFD_RELOC_MICROMIPS_LO16
+         : reloc == BFD_RELOC_HI16_S_PCREL ? BFD_RELOC_LO16_PCREL
+         : BFD_RELOC_LO16);
 }
 
 /* Return true if the given fixup is followed by a matching R_MIPS_LO16
@@ -4415,7 +4418,12 @@ fixup_has_matching_lo_p (fixS *fixp)
   return (fixp->fx_next != NULL
          && fixp->fx_next->fx_r_type == matching_lo_reloc (fixp->fx_r_type)
          && fixp->fx_addsy == fixp->fx_next->fx_addsy
-         && fixp->fx_offset == fixp->fx_next->fx_offset);
+         && (fixp->fx_r_type == BFD_RELOC_HI16_S_PCREL
+             ? (fixp->fx_next->fx_offset - fixp->fx_offset
+                == ((fixp->fx_next->fx_frag->fr_address
+                       + fixp->fx_next->fx_where)
+                    - (fixp->fx_frag->fr_address + fixp->fx_where)))
+             : fixp->fx_offset == fixp->fx_next->fx_offset));
 }
 
 /* Move all labels in LABELS to the current insertion point.  TEXT_P
@@ -15413,6 +15421,13 @@ mips_frob_file_before_adjust (void)
    if the user knows that adding 2 to "foo" will not induce a carry to
    the high 16 bits.
 
+   A %pcrel_lo() expression matches a %pcrel_hi() expression if:
+
+      (a) it refers to the same symbol; and
+      (b) the offset applied in the %pcrel_lo() expression equals
+         the offset applied in the %pcrel_hi() expression plus the
+         distance from the location of %pcrel_hi() to %pcrel_lo().
+
    When several %lo()s match a particular %got() or %hi(), we use the
    following rules to distinguish them:
 
@@ -15484,9 +15499,14 @@ mips_frob_file (void)
 
          if ((*pos)->fx_r_type == looking_for_rtype
              && symbol_same_p ((*pos)->fx_addsy, l->fixp->fx_addsy)
-             && (*pos)->fx_offset >= l->fixp->fx_offset
+             && (l->fixp->fx_r_type == BFD_RELOC_HI16_S_PCREL
+                 ? ((*pos)->fx_offset - l->fixp->fx_offset
+                    == (((*pos)->fx_frag->fr_address + (*pos)->fx_where)
+                        - (l->fixp->fx_frag->fr_address + l->fixp->fx_where)))
+                 : (*pos)->fx_offset >= l->fixp->fx_offset)
              && (lo_pos == NULL
-                 || (*pos)->fx_offset < (*lo_pos)->fx_offset
+                 || (l->fixp->fx_r_type != BFD_RELOC_HI16_S_PCREL
+                     && (*pos)->fx_offset < (*lo_pos)->fx_offset)
                  || (!matched_lo_p
                      && (*pos)->fx_offset == (*lo_pos)->fx_offset)))
            lo_pos = pos;
@@ -15497,15 +15517,20 @@ mips_frob_file (void)
 
       /* If we found a match, remove the high-part relocation from its
         current position and insert it before the low-part relocation.
-        Make the offsets match so that fixup_has_matching_lo_p()
-        will return true.
+
+        For absolute relocations make the offsets match so that
+        fixup_has_matching_lo_p() will return true.  For PC-relative
+        relocations the distance between the offsets is retained
+        according to expectations in `fixup_has_matching_lo_p',
+        `_bfd_mips_elf_lo16_reloc' and `mips_elf_add_lo16_rel_addend'.
 
         We don't warn about unmatched high-part relocations since some
         versions of gcc have been known to emit dead "lui ...%hi(...)"
         instructions.  */
       if (lo_pos != NULL)
        {
-         l->fixp->fx_offset = (*lo_pos)->fx_offset;
+         if (l->fixp->fx_r_type != BFD_RELOC_HI16_S_PCREL)
+           l->fixp->fx_offset = (*lo_pos)->fx_offset;
          if (l->fixp->fx_next != *lo_pos)
            {
              *hi_pos = l->fixp->fx_next;
index 1a766ffc821c2ae7cde9c17ff006ca6344d8bc1b..73ea41d59c60ec1ebab6fe7bb4210e569c653e15 100644 (file)
@@ -1724,6 +1724,13 @@ if { [istarget mips*-*-vxworks*] } {
        run_dump_test "pcrel-4-n32"
        run_dump_test "pcrel-4-64"
     }
+    run_dump_test "pcrel-hilo-match"
+    run_dump_test "pcrel-hilo-addend"
+    run_dump_test "pcrel-hilo"
+    if $has_newabi {
+       run_dump_test "pcrel-hilo-n32"
+       run_dump_test "pcrel-hilo-64"
+    }
 
     run_dump_test "pcrel-reloc-1"
     run_dump_test "pcrel-reloc-1-r6"
diff --git a/gas/testsuite/gas/mips/pcrel-hilo-64.d b/gas/testsuite/gas/mips/pcrel-hilo-64.d
new file mode 100644 (file)
index 0000000..92c697f
--- /dev/null
@@ -0,0 +1,79 @@
+#readelf: -r
+#name: MIPSr6 PCHI16/PCLO16 relocations (n64)
+#as: -mabi=64 -march=mips64r6 -mno-pdr
+#source: pcrel-hilo.s
+
+Relocation section '\.rela\.text' at offset .+ contains 24 entries:
+  Offset          Info           Type           Sym\. Value    Sym\. Name \+ Addend
+000000000000  000800000040 R_MIPS_PCHI16     0000000000000000 bar \+ 7fec
+                    Type2: R_MIPS_NONE      
+                    Type3: R_MIPS_NONE      
+000000000004  000900000005 R_MIPS_HI16       0000000000000000 baz \+ 0
+                    Type2: R_MIPS_NONE      
+                    Type3: R_MIPS_NONE      
+000000000008  000800000040 R_MIPS_PCHI16     0000000000000000 bar \+ 7ff8
+                    Type2: R_MIPS_NONE      
+                    Type3: R_MIPS_NONE      
+00000000000c  000800000040 R_MIPS_PCHI16     0000000000000000 bar \+ fff0
+                    Type2: R_MIPS_NONE      
+                    Type3: R_MIPS_NONE      
+000000000010  000800000041 R_MIPS_PCLO16     0000000000000000 bar \+ 7ffc
+                    Type2: R_MIPS_NONE      
+                    Type3: R_MIPS_NONE      
+000000000014  000900000006 R_MIPS_LO16       0000000000000000 baz \+ 0
+                    Type2: R_MIPS_NONE      
+                    Type3: R_MIPS_NONE      
+000000000018  000800000041 R_MIPS_PCLO16     0000000000000000 bar \+ 8008
+                    Type2: R_MIPS_NONE      
+                    Type3: R_MIPS_NONE      
+00000000001c  000800000041 R_MIPS_PCLO16     0000000000000000 bar \+ 10000
+                    Type2: R_MIPS_NONE      
+                    Type3: R_MIPS_NONE      
+000000000020  000800000040 R_MIPS_PCHI16     0000000000000000 bar \+ 800c
+                    Type2: R_MIPS_NONE      
+                    Type3: R_MIPS_NONE      
+000000000024  000900000005 R_MIPS_HI16       0000000000000000 baz \+ 0
+                    Type2: R_MIPS_NONE      
+                    Type3: R_MIPS_NONE      
+000000000028  000800000040 R_MIPS_PCHI16     0000000000000000 bar \+ 8018
+                    Type2: R_MIPS_NONE      
+                    Type3: R_MIPS_NONE      
+00000000002c  000800000040 R_MIPS_PCHI16     0000000000000000 bar \+ 10010
+                    Type2: R_MIPS_NONE      
+                    Type3: R_MIPS_NONE      
+000000030030  000800000041 R_MIPS_PCLO16     0000000000000000 bar \+ 3801c
+                    Type2: R_MIPS_NONE      
+                    Type3: R_MIPS_NONE      
+000000030034  000900000006 R_MIPS_LO16       0000000000000000 baz \+ 0
+                    Type2: R_MIPS_NONE      
+                    Type3: R_MIPS_NONE      
+000000030038  000800000041 R_MIPS_PCLO16     0000000000000000 bar \+ 38028
+                    Type2: R_MIPS_NONE      
+                    Type3: R_MIPS_NONE      
+00000003003c  000800000041 R_MIPS_PCLO16     0000000000000000 bar \+ 40020
+                    Type2: R_MIPS_NONE      
+                    Type3: R_MIPS_NONE      
+000000030040  000800000041 R_MIPS_PCLO16     0000000000000000 bar \+ 3802c
+                    Type2: R_MIPS_NONE      
+                    Type3: R_MIPS_NONE      
+000000030044  000900000006 R_MIPS_LO16       0000000000000000 baz \+ 0
+                    Type2: R_MIPS_NONE      
+                    Type3: R_MIPS_NONE      
+000000030048  000800000041 R_MIPS_PCLO16     0000000000000000 bar \+ 38038
+                    Type2: R_MIPS_NONE      
+                    Type3: R_MIPS_NONE      
+00000003004c  000800000041 R_MIPS_PCLO16     0000000000000000 bar \+ 40030
+                    Type2: R_MIPS_NONE      
+                    Type3: R_MIPS_NONE      
+000000030050  000800000040 R_MIPS_PCHI16     0000000000000000 bar \+ 3803c
+                    Type2: R_MIPS_NONE      
+                    Type3: R_MIPS_NONE      
+000000030054  000900000005 R_MIPS_HI16       0000000000000000 baz \+ 0
+                    Type2: R_MIPS_NONE      
+                    Type3: R_MIPS_NONE      
+000000030058  000800000040 R_MIPS_PCHI16     0000000000000000 bar \+ 38048
+                    Type2: R_MIPS_NONE      
+                    Type3: R_MIPS_NONE      
+00000003005c  000800000040 R_MIPS_PCHI16     0000000000000000 bar \+ 40040
+                    Type2: R_MIPS_NONE      
+                    Type3: R_MIPS_NONE      
diff --git a/gas/testsuite/gas/mips/pcrel-hilo-addend.d b/gas/testsuite/gas/mips/pcrel-hilo-addend.d
new file mode 100644 (file)
index 0000000..296101c
--- /dev/null
@@ -0,0 +1,63 @@
+#objdump: -dr --prefix-addresses --show-raw-insn
+#name: MIPSr6 PCHI16/PCLO16 in-place addends (o32)
+#as: -mabi=32 -mno-pdr
+#source: pcrel-hilo.s
+
+.*: +file format .*mips.*
+
+Disassembly of section \.text:
+00000000 <[^>]*> ec9e0000      auipc   a0,0x0
+                       0: R_MIPS_PCHI16        bar
+00000004 <[^>]*> 3c050000      lui     a1,0x0
+                       4: R_MIPS_HI16  baz
+00000008 <[^>]*> ecde0000      auipc   a2,0x0
+                       8: R_MIPS_PCHI16        bar
+0000000c <[^>]*> ecfe0001      auipc   a3,0x1
+                       c: R_MIPS_PCHI16        bar
+00000010 <[^>]*> 24847ffc      addiu   a0,a0,32764
+                       10: R_MIPS_PCLO16       bar
+00000014 <[^>]*> 24a50000      addiu   a1,a1,0
+                       14: R_MIPS_LO16 baz
+00000018 <[^>]*> 24c68008      addiu   a2,a2,-32760
+                       18: R_MIPS_PCLO16       bar
+0000001c <[^>]*> 24e70000      addiu   a3,a3,0
+                       1c: R_MIPS_PCLO16       bar
+00000020 <[^>]*> ec9e0001      auipc   a0,0x1
+                       20: R_MIPS_PCHI16       bar
+00000024 <[^>]*> 3c050000      lui     a1,0x0
+                       24: R_MIPS_HI16 baz
+00000028 <[^>]*> ecde0001      auipc   a2,0x1
+                       28: R_MIPS_PCHI16       bar
+0000002c <[^>]*> ecfe0001      auipc   a3,0x1
+                       2c: R_MIPS_PCHI16       bar
+       \.\.\.
+00030030 <[^>]*> 2484801c      addiu   a0,a0,-32740
+                       30030: R_MIPS_PCLO16    bar
+00030034 <[^>]*> 24a50000      addiu   a1,a1,0
+                       30034: R_MIPS_LO16      baz
+00030038 <[^>]*> 24c68028      addiu   a2,a2,-32728
+                       30038: R_MIPS_PCLO16    bar
+0003003c <[^>]*> 24e70020      addiu   a3,a3,32
+                       3003c: R_MIPS_PCLO16    bar
+00030040 <[^>]*> 2410802c      li      s0,-32724
+                       30040: R_MIPS_PCLO16    bar
+00030044 <[^>]*> 24110000      li      s1,0
+                       30044: R_MIPS_LO16      baz
+00030048 <[^>]*> 24128038      li      s2,-32712
+                       30048: R_MIPS_PCLO16    bar
+0003004c <[^>]*> 24130030      li      s3,48
+                       3004c: R_MIPS_PCLO16    bar
+00030050 <[^>]*> ec9e0004      auipc   a0,0x4
+                       30050: R_MIPS_PCHI16    bar
+00030054 <[^>]*> 3c050000      lui     a1,0x0
+                       30054: R_MIPS_HI16      baz
+00030058 <[^>]*> ecde0004      auipc   a2,0x4
+                       30058: R_MIPS_PCHI16    bar
+0003005c <[^>]*> ecfe0004      auipc   a3,0x4
+                       3005c: R_MIPS_PCHI16    bar
+00030060 <[^>]*> 00902021      addu    a0,a0,s0
+00030064 <[^>]*> 00b12821      addu    a1,a1,s1
+00030068 <[^>]*> 00d23021      addu    a2,a2,s2
+0003006c <[^>]*> 00f33821      addu    a3,a3,s3
+00030070 <[^>]*> d81f0000      jrc     ra
+       \.\.\.
diff --git a/gas/testsuite/gas/mips/pcrel-hilo-match.d b/gas/testsuite/gas/mips/pcrel-hilo-match.d
new file mode 100644 (file)
index 0000000..5ff66c2
--- /dev/null
@@ -0,0 +1,28 @@
+#objdump: -r
+#as: -mabi=32 -mno-pdr
+#name: MIPS pcrel-hilo-match
+
+.*: +file format .*mips.*
+
+RELOCATION RECORDS FOR \[\.text\]:
+OFFSET +TYPE +VALUE
+00000010 R_MIPS_PCHI16     var4
+00000018 R_MIPS_PCLO16     var4
+00000008 R_MIPS_PCHI16     __var1
+00000020 R_MIPS_PCLO16     __var1
+0000001c R_MIPS_PCHI16     .sbss
+0000002c R_MIPS_PCLO16     .sbss
+00000028 R_MIPS_PCHI16     __var3
+00000034 R_MIPS_PCLO16     __var3
+00000030 R_MIPS_PCHI16     func4
+00000038 R_MIPS_PCLO16     func4
+00000024 R_MIPS_PCHI16     hilo_match
+0000003c R_MIPS_PCLO16     hilo_match
+00000040 R_MIPS_PCHI16     .bss
+00000048 R_MIPS_PCLO16     .bss
+00000044 R_MIPS_PCHI16     .bss
+0000004c R_MIPS_PCLO16     .bss
+00000050 R_MIPS_PCHI16     hilo_match
+00000058 R_MIPS_PCLO16     hilo_match
+00000054 R_MIPS_PCHI16     func3
+0000005c R_MIPS_PCLO16     func3
diff --git a/gas/testsuite/gas/mips/pcrel-hilo-match.s b/gas/testsuite/gas/mips/pcrel-hilo-match.s
new file mode 100644 (file)
index 0000000..dfc8a80
--- /dev/null
@@ -0,0 +1,81 @@
+       .module mips64r6
+
+       .align  2
+       .globl  _pinit
+       .ent    _pinit
+_pinit:
+       lw      $3,8($23)
+       li      $5,1
+10:    auipc   $2,%pcrel_hi(__var1)
+       ori     $3,$3,0x1
+11:    auipc   $4,%pcrel_hi(var4)
+       sw      $3,8($23)
+12:    addiu   $4,$4,%pcrel_lo(var4 + (12b - 11b))
+13:    auipc   $3,%pcrel_hi(var5)
+14:    sw      $5,%pcrel_lo(__var1 + (14b - 10b))($2)
+15:    auipc   $19,%pcrel_hi(hilo_match)
+16:    auipc   $2,%pcrel_hi(__var3)
+17:    sw      $5,%pcrel_lo(var5 + (17b - 13b))($3)
+18:    auipc   $25,%pcrel_hi(func4)
+19:    sw      $5,%pcrel_lo(__var3 + (19b - 16b))($2)
+20:    jialc   $25,%pcrel_lo(func4 + (20b - 18b))
+21:    lw      $17,%pcrel_lo(hilo_match + (21b - 15b))($19)
+22:    auipc   $2,%pcrel_hi(var6)
+23:    auipc   $3,%pcrel_hi(var6+704)
+24:    addiu   $16,$2,%pcrel_lo(var6 + (24b - 22b))
+25:    addiu   $18,$3,%pcrel_lo(var6+704 + (25b - 23b))
+26:    auipc   $19,%pcrel_hi(hilo_match)
+28:    auipc   $25,%pcrel_hi(func3)
+27:    sw      $2,%pcrel_lo(hilo_match + (27b - 26b))($19)
+29:    jialc   $25,%pcrel_lo(func3 + (29b - 28b))
+       .end    _pinit
+       .size   _pinit, .-_pinit
+
+       .align  2
+       .weak   __var3
+       .section        .sbss,"aw",@nobits
+       .align  2
+       .type   __var3, @object
+       .size   __var3, 4
+__var3:
+       .space  4
+       .weak   __var1
+       .align  2
+       .type   __var1, @object
+       .size   __var1, 4
+__var1:
+       .space  4
+       .data
+       .align  2
+       .weak   __hilo_match
+       .align  2
+       .type   __hilo_match, @object
+       .size   __hilo_match, 4
+__hilo_match:
+       .space  4
+       .data
+       .align  2
+       .align  2
+       .type   var2, @object
+       .size   var2, 32
+var2:
+       .word   0
+       .word   -1
+       .word   0
+       .byte   0
+       .byte   0
+       .byte   0
+       .byte   0
+       .word   0
+       .word   0
+       .half   0
+       .space  6
+       .align  2
+       .rdata
+       .align  2
+       .space  8
+       .local  var5
+       .comm   var5,4,4
+       .align  2
+       .local  var6
+       .comm   var6,704,4
diff --git a/gas/testsuite/gas/mips/pcrel-hilo-n32.d b/gas/testsuite/gas/mips/pcrel-hilo-n32.d
new file mode 100644 (file)
index 0000000..aed204a
--- /dev/null
@@ -0,0 +1,31 @@
+#readelf: -r
+#name: MIPSr6 PCHI16/PCLO16 relocations (n32)
+#as: -mabi=n32 -march=mips64r6 -mno-pdr
+#source: pcrel-hilo.s
+
+Relocation section '\.rela\.text' at offset .+ contains 24 entries:
+ Offset     Info    Type            Sym\.Value  Sym\. Name \+ Addend
+00000000  00000840 R_MIPS_PCHI16     00000000   bar \+ 7fec
+00000004  00000905 R_MIPS_HI16       00000000   baz \+ 0
+00000008  00000840 R_MIPS_PCHI16     00000000   bar \+ 7ff8
+0000000c  00000840 R_MIPS_PCHI16     00000000   bar \+ fff0
+00000010  00000841 R_MIPS_PCLO16     00000000   bar \+ 7ffc
+00000014  00000906 R_MIPS_LO16       00000000   baz \+ 0
+00000018  00000841 R_MIPS_PCLO16     00000000   bar \+ 8008
+0000001c  00000841 R_MIPS_PCLO16     00000000   bar \+ 10000
+00000020  00000840 R_MIPS_PCHI16     00000000   bar \+ 800c
+00000024  00000905 R_MIPS_HI16       00000000   baz \+ 0
+00000028  00000840 R_MIPS_PCHI16     00000000   bar \+ 8018
+0000002c  00000840 R_MIPS_PCHI16     00000000   bar \+ 10010
+00030030  00000841 R_MIPS_PCLO16     00000000   bar \+ 3801c
+00030034  00000906 R_MIPS_LO16       00000000   baz \+ 0
+00030038  00000841 R_MIPS_PCLO16     00000000   bar \+ 38028
+0003003c  00000841 R_MIPS_PCLO16     00000000   bar \+ 40020
+00030040  00000841 R_MIPS_PCLO16     00000000   bar \+ 3802c
+00030044  00000906 R_MIPS_LO16       00000000   baz \+ 0
+00030048  00000841 R_MIPS_PCLO16     00000000   bar \+ 38038
+0003004c  00000841 R_MIPS_PCLO16     00000000   bar \+ 40030
+00030050  00000840 R_MIPS_PCHI16     00000000   bar \+ 3803c
+00030054  00000905 R_MIPS_HI16       00000000   baz \+ 0
+00030058  00000840 R_MIPS_PCHI16     00000000   bar \+ 38048
+0003005c  00000840 R_MIPS_PCHI16     00000000   bar \+ 40040
diff --git a/gas/testsuite/gas/mips/pcrel-hilo.d b/gas/testsuite/gas/mips/pcrel-hilo.d
new file mode 100644 (file)
index 0000000..a96e4f2
--- /dev/null
@@ -0,0 +1,30 @@
+#readelf: -r
+#name: MIPSr6 PCHI16/PCLO16 relocations (o32)
+#as: -mabi=32 -mno-pdr
+
+Relocation section '\.rel\.text' at offset .+ contains 24 entries:
+ Offset     Info    Type            Sym\.Value  Sym\. Name
+00030050  00000840 R_MIPS_PCHI16     00000000   bar
+00000000  00000840 R_MIPS_PCHI16     00000000   bar
+00000010  00000841 R_MIPS_PCLO16     00000000   bar
+00000004  00000905 R_MIPS_HI16       00000000   baz
+00000014  00000906 R_MIPS_LO16       00000000   baz
+00030058  00000840 R_MIPS_PCHI16     00000000   bar
+00000028  00000840 R_MIPS_PCHI16     00000000   bar
+00000008  00000840 R_MIPS_PCHI16     00000000   bar
+00000018  00000841 R_MIPS_PCLO16     00000000   bar
+0003005c  00000840 R_MIPS_PCHI16     00000000   bar
+0000002c  00000840 R_MIPS_PCHI16     00000000   bar
+0000000c  00000840 R_MIPS_PCHI16     00000000   bar
+0000001c  00000841 R_MIPS_PCLO16     00000000   bar
+00000020  00000840 R_MIPS_PCHI16     00000000   bar
+00030030  00000841 R_MIPS_PCLO16     00000000   bar
+00000024  00000905 R_MIPS_HI16       00000000   baz
+00030034  00000906 R_MIPS_LO16       00000000   baz
+00030038  00000841 R_MIPS_PCLO16     00000000   bar
+0003003c  00000841 R_MIPS_PCLO16     00000000   bar
+00030040  00000841 R_MIPS_PCLO16     00000000   bar
+00030054  00000905 R_MIPS_HI16       00000000   baz
+00030044  00000906 R_MIPS_LO16       00000000   baz
+00030048  00000841 R_MIPS_PCLO16     00000000   bar
+0003004c  00000841 R_MIPS_PCLO16     00000000   bar
diff --git a/gas/testsuite/gas/mips/pcrel-hilo.s b/gas/testsuite/gas/mips/pcrel-hilo.s
new file mode 100644 (file)
index 0000000..4a8278f
--- /dev/null
@@ -0,0 +1,48 @@
+       .module mips64r6
+
+       .text
+       .align  16
+       .globl  foo
+       .ent    foo
+foo:
+0:     auipc   $4, %pcrel_hi(bar + 0x7fec)
+1:     lui     $5, %hi(baz)
+2:     auipc   $6, %pcrel_hi(bar + 0x7ff8)
+3:     auipc   $7, %pcrel_hi(bar + 0xfff0)
+4:     addiu   $4, %pcrel_lo(bar + 0x7fec + (4b - 0b))
+5:     addiu   $5, %lo(baz)
+6:     addiu   $6, %pcrel_lo(bar + 0x7ff8 + (6b - 2b))
+7:     addiu   $7, %pcrel_lo(bar + 0xfff0 + (7b - 3b))
+10:    auipc   $4, %pcrel_hi(bar + 0x800c)
+11:    lui     $5, %hi(baz)
+12:    auipc   $6, %pcrel_hi(bar + 0x8018)
+13:    auipc   $7, %pcrel_hi(bar + 0x10010)
+       .rept   49152
+       nop
+       .endr
+14:    addiu   $4, %pcrel_lo(bar + 0x800c + (14b - 10b))
+15:    addiu   $5, %lo(baz)
+16:    addiu   $6, %pcrel_lo(bar + 0x8018 + (16b - 12b))
+17:    addiu   $7, %pcrel_lo(bar + 0x10010 + (17b - 13b))
+24:    addiu   $16, $0, %pcrel_lo(bar + 0x3803c + (24b - 20f))
+25:    addiu   $17, $0, %lo(baz)
+26:    addiu   $18, $0, %pcrel_lo(bar + 0x38048 + (26b - 22f))
+27:    addiu   $19, $0, %pcrel_lo(bar + 0x40040 + (27b - 23f))
+20:    auipc   $4, %pcrel_hi(bar + 0x3803c)
+21:    lui     $5, %hi(baz)
+22:    auipc   $6, %pcrel_hi(bar + 0x38048)
+23:    auipc   $7, %pcrel_hi(bar + 0x40040)
+       addu    $4, $4, $16
+       addu    $5, $5, $17
+       addu    $6, $6, $18
+       addu    $7, $7, $19
+       jrc     $31
+       .end    foo
+
+       .data
+       .align  16
+       .globl  bar
+       .type   bar, @object
+bar:
+       .space  0x18000
+       .size   bar, . - bar
index e95f1e739cdc905b05b4b90c7c18ba4f43faeca5..6fc960dfc10bc1ec163d588b1fdaf1c5ef278daf 100644 (file)
@@ -855,6 +855,17 @@ run_dump_test_n32 "micromips-hilo-srec" \
 run_dump_test_n64 "micromips-hilo-srec-n64" \
        [list noarch \
              [list objdump [expr { [istarget *el-*-*] ? "-EL" : "-EB" }]]]
+run_dump_test_o32 "pcrel-hilo"
+run_dump_test_n32 "pcrel-hilo" [list [list name (n32)]]
+run_dump_test_n64 "pcrel-hilo" [list [list name (n64)]]
+run_dump_test_o32 "pcrel-hilo-srec" \
+       [list [list objdump [expr { [istarget *el-*-*] ? "-EL" : "-EB" }]]]
+run_dump_test_n32 "pcrel-hilo-srec" \
+       [list [list name (n32)] \
+             [list objdump [expr { [istarget *el-*-*] ? "-EL" : "-EB" }]]]
+run_dump_test_n64 "pcrel-hilo-srec" \
+       [list [list name (n64)] \
+             [list objdump [expr { [istarget *el-*-*] ? "-EL" : "-EB" }]]]
 
 if { $linux_gnu } {
     run_dump_test_n32 "textrel-1"
diff --git a/ld/testsuite/ld-mips-elf/pcrel-hilo-srec.d b/ld/testsuite/ld-mips-elf/pcrel-hilo-srec.d
new file mode 100644 (file)
index 0000000..e9b0956
--- /dev/null
@@ -0,0 +1,6 @@
+#name: MIPSr6 PCHI16/PCLO16 relocations srec
+#as: -mno-pdr
+#ld: -e 0 --defsym=baz=0xfedcba98 -T pcrel-hilo.ld --oformat=srec
+#objdump: -m mips:isa64r6 -D -j .sec1
+#source: ../../../gas/testsuite/gas/mips/pcrel-hilo.s
+#dump: pcrel-hilo.d
diff --git a/ld/testsuite/ld-mips-elf/pcrel-hilo.d b/ld/testsuite/ld-mips-elf/pcrel-hilo.d
new file mode 100644 (file)
index 0000000..ae5d052
--- /dev/null
@@ -0,0 +1,42 @@
+#name: MIPSr6 PCHI16/PCLO16 relocations
+#as: -mno-pdr
+#ld: -e 0 --defsym=baz=0xfedcba98 -T pcrel-hilo.ld
+#objdump: -m mips:isa64r6 -d
+#source: ../../../gas/testsuite/gas/mips/pcrel-hilo.s
+
+.*: +file format (?:.*mips.*|srec)
+
+Disassembly of section \.(?:text|sec1):
+
+0*10000000 <[^>]*>:
+ *10000000:    ec9e2456        auipc   a0,0x2456
+ *10000004:    3c05fedd        lui     a1,0xfedd
+ *10000008:    ecde2456        auipc   a2,0x2456
+ *1000000c:    ecfe2457        auipc   a3,0x2457
+ *10000010:    24847fec        addiu   a0,a0,32748
+ *10000014:    24a5ba98        addiu   a1,a1,-17768
+ *10000018:    24c67ff0        addiu   a2,a2,32752
+ *1000001c:    24e7ffe4        addiu   a3,a3,-28
+ *10000020:    ec9e2456        auipc   a0,0x2456
+ *10000024:    3c05fedd        lui     a1,0xfedd
+ *10000028:    ecde2456        auipc   a2,0x2456
+ *1000002c:    ecfe2457        auipc   a3,0x2457
+       \.\.\.
+ *10030030:    24847fec        addiu   a0,a0,32748
+ *10030034:    24a5ba98        addiu   a1,a1,-17768
+ *10030038:    24c67ff0        addiu   a2,a2,32752
+ *1003003c:    24e7ffe4        addiu   a3,a3,-28
+ *10030040:    24107fec        li      s0,32748
+ *10030044:    2411ba98        li      s1,-17768
+ *10030048:    24127ff0        li      s2,32752
+ *1003004c:    2413ffe4        li      s3,-28
+ *10030050:    ec9e2456        auipc   a0,0x2456
+ *10030054:    3c05fedd        lui     a1,0xfedd
+ *10030058:    ecde2456        auipc   a2,0x2456
+ *1003005c:    ecfe2457        auipc   a3,0x2457
+ *10030060:    00902021        addu    a0,a0,s0
+ *10030064:    00b12821        addu    a1,a1,s1
+ *10030068:    00d23021        addu    a2,a2,s2
+ *1003006c:    00f33821        addu    a3,a3,s3
+ *10030070:    d81f0000        jrc     ra
+       \.\.\.
diff --git a/ld/testsuite/ld-mips-elf/pcrel-hilo.ld b/ld/testsuite/ld-mips-elf/pcrel-hilo.ld
new file mode 100644 (file)
index 0000000..77d361d
--- /dev/null
@@ -0,0 +1,14 @@
+MEMORY
+{
+  text (rx) : ORIGIN = 0x10000000, LENGTH = 0x40000
+  data (w) : ORIGIN = 0x34560000, LENGTH = 0x40000
+}
+SECTIONS
+{
+  .text : { *(.text) } >text
+  .data : { *(.data) } >data
+  .symtab : { *(.symtab) }
+  .strtab : { *(.strtab) }
+  .shstrtab : { *(.shstrtab) }
+  /DISCARD/ : { *(*) }
+}