[llvm] 3619279 - [PowerPC][PC Rel] Implement option to omit Power10 instructions from stubs

Albion Fung via llvm-commits llvm-commits at lists.llvm.org
Thu Mar 4 10:27:58 PST 2021


Author: Albion Fung
Date: 2021-03-04T13:27:46-05:00
New Revision: 36192790d84ba1c9a814df4024967685b0dc27c5

URL: https://github.com/llvm/llvm-project/commit/36192790d84ba1c9a814df4024967685b0dc27c5
DIFF: https://github.com/llvm/llvm-project/commit/36192790d84ba1c9a814df4024967685b0dc27c5.diff

LOG: [PowerPC][PC Rel] Implement option to omit Power10 instructions from stubs

Implemented the option to omit Power10 instructions from save stubs via the
option --no-power10-stubs or --power10-stubs=no on lld. --power10-stubs= will
override the other option. --power10-stubs=auto also exists to use the default
behaviour (ie allow Power10 instructions in stubs).

Differential Revision: https://reviews.llvm.org/D94627

Added: 
    

Modified: 
    lld/ELF/Config.h
    lld/ELF/Driver.cpp
    lld/ELF/Options.td
    lld/ELF/Thunks.cpp
    lld/ELF/Thunks.h
    lld/test/ELF/ppc64-call-reach.s
    lld/test/ELF/ppc64-long-branch-localentry-offset.s
    lld/test/ELF/ppc64-long-branch-pi.s
    lld/test/ELF/ppc64-long-branch-rel14.s
    lld/test/ELF/ppc64-long-branch.s
    lld/test/ELF/ppc64-pcrel-call-to-extern.s
    lld/test/ELF/ppc64-pcrel-call-to-toc.s
    lld/test/ELF/ppc64-plt-stub-compatible.s
    lld/test/ELF/ppc64-tls-pcrel-gd.s
    lld/test/ELF/ppc64-toc-call-to-pcrel-long-jump.s
    lld/test/ELF/ppc64-toc-call-to-pcrel.s
    llvm/include/llvm/Object/ELF.h

Removed: 
    


################################################################################
diff  --git a/lld/ELF/Config.h b/lld/ELF/Config.h
index 966bfd3bfad8..fcfe5f64c32f 100644
--- a/lld/ELF/Config.h
+++ b/lld/ELF/Config.h
@@ -253,6 +253,7 @@ struct Configuration {
   UnresolvedPolicy unresolvedSymbols;
   UnresolvedPolicy unresolvedSymbolsInShlib;
   Target2Policy target2;
+  bool Power10Stub;
   ARMVFPArgKind armVFPArgs = ARMVFPArgKind::Default;
   BuildIdKind buildId = BuildIdKind::None;
   SeparateSegmentKind zSeparate;

diff  --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index f9ff5d6a8c52..df9925d74f8a 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -761,6 +761,20 @@ static OrphanHandlingPolicy getOrphanHandling(opt::InputArgList &args) {
   return OrphanHandlingPolicy::Place;
 }
 
+// Parses --power10-stubs= flags, to disable or enable Power 10
+// instructions in stubs.
+static bool getP10StubOpt(opt::InputArgList &args) {
+
+  if (args.getLastArgValue(OPT_power10_stubs_eq)== "no")
+    return false;
+
+  if (!args.hasArg(OPT_power10_stubs_eq) &&
+      args.hasArg(OPT_no_power10_stubs))
+    return false;
+
+  return true;
+}
+
 // Parse --build-id or --build-id=<style>. We handle "tree" as a
 // synonym for "sha1" because all our hash functions including
 // -build-id=sha1 are actually tree hashes for performance reasons.
@@ -1126,6 +1140,7 @@ static void readConfigs(opt::InputArgList &args) {
   config->zText = getZFlag(args, "text", "notext", true);
   config->zWxneeded = hasZOption(args, "wxneeded");
   setUnresolvedSymbolPolicy(args);
+  config->Power10Stub = getP10StubOpt(args);
 
   if (opt::Arg *arg = args.getLastArg(OPT_eb, OPT_el)) {
     if (arg->getOption().matches(OPT_eb))

diff  --git a/lld/ELF/Options.td b/lld/ELF/Options.td
index e1eccdbada33..302afd2a4374 100644
--- a/lld/ELF/Options.td
+++ b/lld/ELF/Options.td
@@ -445,6 +445,17 @@ def verbose: F<"verbose">, HelpText<"Verbose mode">;
 
 def version: F<"version">, HelpText<"Display the version number and exit">;
 
+def power10_stubs: F<"power10-stubs">, HelpText<"Alias for --power10-stubs=auto">;
+
+def no_power10_stubs: F<"no-power10-stubs">, HelpText<"Alias for --power10-stubs=no">;
+
+def power10_stubs_eq:
+  J<"power10-stubs=">, HelpText<
+                     "Enables Power10 instructions in all stubs without options, "
+                     "options override previous flags."
+                     "auto: Allow Power10 instructions in stubs if applicable."
+                     "no:   No Power10 instructions in stubs.">;
+
 defm version_script: Eq<"version-script", "Read a version script">;
 
 defm warn_backrefs: BB<"warn-backrefs",

diff  --git a/lld/ELF/Thunks.cpp b/lld/ELF/Thunks.cpp
index 1fb3abaa60f5..331c5c89d501 100644
--- a/lld/ELF/Thunks.cpp
+++ b/lld/ELF/Thunks.cpp
@@ -309,7 +309,7 @@ class PPC64R2SaveStub final : public Thunk {
     }
     return true;
   }
-  uint32_t size() override { return getMayUseShortThunk() ? 8 : 20; }
+  uint32_t size() override { return getMayUseShortThunk() ? 8 : 32; }
   void writeTo(uint8_t *buf) override;
   void addSymbols(ThunkSection &isec) override;
 
@@ -330,7 +330,7 @@ class PPC64R2SaveStub final : public Thunk {
 class PPC64R12SetupStub final : public Thunk {
 public:
   PPC64R12SetupStub(Symbol &dest) : Thunk(dest, 0) { alignment = 16; }
-  uint32_t size() override { return 16; }
+  uint32_t size() override { return 32; }
   void writeTo(uint8_t *buf) override;
   void addSymbols(ThunkSection &isec) override;
 };
@@ -345,7 +345,7 @@ class PPC64R12SetupStub final : public Thunk {
 class PPC64PCRelPLTStub final : public Thunk {
 public:
   PPC64PCRelPLTStub(Symbol &dest) : Thunk(dest, 0) { alignment = 16; }
-  uint32_t size() override { return 16; }
+  uint32_t size() override { return 32; }
   void writeTo(uint8_t *buf) override;
   void addSymbols(ThunkSection &isec) override;
   bool isCompatibleWith(const InputSection &isec,
@@ -362,7 +362,7 @@ class PPC64PCRelPLTStub final : public Thunk {
 // used.
 class PPC64LongBranchThunk : public Thunk {
 public:
-  uint32_t size() override { return 16; }
+  uint32_t size() override { return 32; }
   void writeTo(uint8_t *buf) override;
   void addSymbols(ThunkSection &isec) override;
   bool isCompatibleWith(const InputSection &isec,
@@ -406,7 +406,7 @@ class PPC64PCRelLongBranchThunk final : public Thunk {
       : Thunk(dest, addend) {
     alignment = 16;
   }
-  uint32_t size() override { return 16; }
+  uint32_t size() override { return 32; }
   void writeTo(uint8_t *buf) override;
   void addSymbols(ThunkSection &isec) override;
   bool isCompatibleWith(const InputSection &isec,
@@ -922,17 +922,34 @@ bool PPC64PltCallStub::isCompatibleWith(const InputSection &isec,
 
 void PPC64R2SaveStub::writeTo(uint8_t *buf) {
   const int64_t offset = computeOffset();
-  write32(buf + 0, 0xf8410018);                         // std  r2,24(r1)
+  write32(buf + 0, 0xf8410018); // std  r2,24(r1)
   // The branch offset needs to fit in 26 bits.
   if (getMayUseShortThunk()) {
     write32(buf + 4, 0x48000000 | (offset & 0x03fffffc)); // b    <offset>
   } else if (isInt<34>(offset)) {
-    const uint64_t paddi = PADDI_R12_NO_DISP |
-                           (((offset >> 16) & 0x3ffff) << 32) |
-                           (offset & 0xffff);
-    writePrefixedInstruction(buf + 4, paddi); // paddi r12, 0, func at pcrel, 1
-    write32(buf + 12, MTCTR_R12);             // mtctr r12
-    write32(buf + 16, BCTR);                  // bctr
+    int nextInstOffset;
+    if (!config->Power10Stub) {
+      uint64_t tocOffset = destination.getVA() - getPPC64TocBase();
+      if (tocOffset >> 16 > 0) {
+        const uint64_t addi = ADDI_R12_TO_R12_NO_DISP | (tocOffset & 0xffff);
+        const uint64_t addis = ADDIS_R12_TO_R2_NO_DISP | ((tocOffset >> 16) & 0xffff);
+        write32(buf + 4, addis); // addis r12, r2 , top of offset
+        write32(buf + 8, addi);  // addi  r12, r12, bottom of offset
+        nextInstOffset = 12;
+      } else {
+        const uint64_t addi = ADDI_R12_TO_R2_NO_DISP | (tocOffset & 0xffff);
+        write32(buf + 4, addi); // addi r12, r2, offset
+        nextInstOffset = 8;
+      }
+    } else {
+      const uint64_t paddi = PADDI_R12_NO_DISP |
+                             (((offset >> 16) & 0x3ffff) << 32) |
+                             (offset & 0xffff);
+      writePrefixedInstruction(buf + 4, paddi); // paddi r12, 0, func at pcrel, 1
+      nextInstOffset = 12;
+    }
+    write32(buf + nextInstOffset, MTCTR_R12); // mtctr r12
+    write32(buf + nextInstOffset + 4, BCTR);  // bctr
   } else {
     in.ppc64LongBranchTarget->addEntry(&destination, addend);
     const int64_t offsetFromTOC =
@@ -952,12 +969,25 @@ void PPC64R12SetupStub::writeTo(uint8_t *buf) {
   int64_t offset = destination.getVA() - getThunkTargetSym()->getVA();
   if (!isInt<34>(offset))
     reportRangeError(buf, offset, 34, destination, "R12 setup stub offset");
-  uint64_t paddi = PADDI_R12_NO_DISP | (((offset >> 16) & 0x3ffff) << 32) |
-                   (offset & 0xffff);
 
-  writePrefixedInstruction(buf + 0, paddi); // paddi r12, 0, func at pcrel, 1
-  write32(buf + 8, MTCTR_R12);              // mtctr r12
-  write32(buf + 12, BCTR);                  // bctr
+  int nextInstOffset;
+  if (!config->Power10Stub) {
+    uint32_t off = destination.getVA(addend) - getThunkTargetSym()->getVA() - 8;
+    write32(buf + 0, 0x7c0802a6);                      // mflr r12
+    write32(buf + 4, 0x429f0005);                      // bcl 20,31,.+4
+    write32(buf + 8, 0x7d6802a6);                      // mflr r11
+    write32(buf + 12, 0x7d8803a6);                     // mtlr r12
+    write32(buf + 16, 0x3d8b0000 | computeHiBits(off));// addis r12,r11,off at ha
+    write32(buf + 20, 0x398c0000 | (off & 0xffff));    // addi r12,r12,off at l
+    nextInstOffset = 24;
+  } else {
+    uint64_t paddi = PADDI_R12_NO_DISP | (((offset >> 16) & 0x3ffff) << 32) |
+                     (offset & 0xffff);
+    writePrefixedInstruction(buf + 0, paddi); // paddi r12, 0, func at pcrel, 1
+    nextInstOffset = 8;
+  }
+  write32(buf + nextInstOffset, MTCTR_R12); // mtctr r12
+  write32(buf + nextInstOffset + 4, BCTR);  // bctr
 }
 
 void PPC64R12SetupStub::addSymbols(ThunkSection &isec) {
@@ -966,16 +996,29 @@ void PPC64R12SetupStub::addSymbols(ThunkSection &isec) {
 }
 
 void PPC64PCRelPLTStub::writeTo(uint8_t *buf) {
+  int nextInstOffset = 0;
   int64_t offset = destination.getGotPltVA() - getThunkTargetSym()->getVA();
-  if (!isInt<34>(offset))
-    reportRangeError(buf, offset, 34, destination,
-                     "PC-relative PLT stub offset");
-  uint64_t pld =
-      PLD_R12_NO_DISP | (((offset >> 16) & 0x3ffff) << 32) | (offset & 0xffff);
 
-  writePrefixedInstruction(buf + 0, pld); // pld r12, func at plt@pcrel
-  write32(buf + 8, MTCTR_R12);            // mtctr r12
-  write32(buf + 12, BCTR);                // bctr
+  if (config->Power10Stub) {
+    if (!isInt<34>(offset))
+      reportRangeError(buf, offset, 34, destination,
+                       "PC-relative PLT stub offset");
+    const uint64_t pld = PLD_R12_NO_DISP | (((offset >> 16) & 0x3ffff) << 32) |
+                   (offset & 0xffff);
+    writePrefixedInstruction(buf + 0, pld); // pld r12, func at plt@pcrel
+    nextInstOffset = 8;
+  } else {
+    uint32_t off = destination.getVA(addend) - getThunkTargetSym()->getVA() - 8;
+    write32(buf + 0, 0x7c0802a6);            // mflr r12
+    write32(buf + 4, 0x429f0005);            // bcl 20,31,.+4
+    write32(buf + 8, 0x7d6802a6);            // mflr r11
+    write32(buf + 12, 0x7d8803a6);           // mtlr r12
+    write32(buf + 16, 0x3d8b0000 | computeHiBits(off)); // addis r12,r11,off at ha
+    write32(buf + 20, 0x398c0000 | (off & 0xffff)); // addi r12,r12,off at l
+    nextInstOffset = 24;
+  }
+  write32(buf + nextInstOffset, MTCTR_R12); // mtctr r12
+  write32(buf + nextInstOffset + 4, BCTR);  // bctr
 }
 
 void PPC64PCRelPLTStub::addSymbols(ThunkSection &isec) {
@@ -1009,12 +1052,25 @@ void PPC64PCRelLongBranchThunk::writeTo(uint8_t *buf) {
   if (!isInt<34>(offset))
     reportRangeError(buf, offset, 34, destination,
                      "PC-relative long branch stub offset");
-  uint64_t paddi = PADDI_R12_NO_DISP | (((offset >> 16) & 0x3ffff) << 32) |
-                   (offset & 0xffff);
 
-  writePrefixedInstruction(buf + 0, paddi); // paddi r12, 0, func at pcrel, 1
-  write32(buf + 8, MTCTR_R12);              // mtctr r12
-  write32(buf + 12, BCTR);                  // bctr
+  int nextInstOffset;
+  if (!config->Power10Stub) {
+    uint32_t off = destination.getVA(addend) - getThunkTargetSym()->getVA() - 8;
+    write32(buf + 0, 0x7c0802a6);                      // mflr r12
+    write32(buf + 4, 0x429f0005);                      // bcl 20,31,.+4
+    write32(buf + 8, 0x7d6802a6);                      // mflr r11
+    write32(buf + 12, 0x7d8803a6);                     // mtlr r12
+    write32(buf + 16, 0x3d8b0000 | computeHiBits(off)); // addis r12,r11,off at ha
+    write32(buf + 20, 0x398c0000 | (off & 0xffff));    // addi r12,r12,off at l
+    nextInstOffset = 24;
+  } else {
+    uint64_t paddi = PADDI_R12_NO_DISP | (((offset >> 16) & 0x3ffff) << 32) |
+                     (offset & 0xffff);
+    writePrefixedInstruction(buf + 0, paddi); // paddi r12, 0, func at pcrel, 1
+    nextInstOffset = 8;
+  }
+  write32(buf + nextInstOffset, MTCTR_R12); // mtctr r12
+  write32(buf + nextInstOffset + 4, BCTR);  // bctr
 }
 
 void PPC64PCRelLongBranchThunk::addSymbols(ThunkSection &isec) {

diff  --git a/lld/ELF/Thunks.h b/lld/ELF/Thunks.h
index a8575b4cdb59..21e99a0a8e28 100644
--- a/lld/ELF/Thunks.h
+++ b/lld/ELF/Thunks.h
@@ -73,6 +73,10 @@ void writePPC32PltCallStub(uint8_t *buf, uint64_t gotPltVA,
                            const InputFile *file, int64_t addend);
 void writePPC64LoadAndBranch(uint8_t *buf, int64_t offset);
 
+static inline uint16_t computeHiBits(uint32_t toCompute) {
+  return (toCompute + 0x8000) >> 16;
+}
+
 } // namespace elf
 } // namespace lld
 

diff  --git a/lld/test/ELF/ppc64-call-reach.s b/lld/test/ELF/ppc64-call-reach.s
index fe4caab25bf0..c0018ad76e55 100644
--- a/lld/test/ELF/ppc64-call-reach.s
+++ b/lld/test/ELF/ppc64-call-reach.s
@@ -67,7 +67,7 @@ test:
 
 # THUNK-LABEL: <test>:
 # THUNK: 10010014:       bl 0x10010030
-# THUNK: 10010024:       b 0x10010040
+# THUNK: 10010024:       b 0x10010050
 
 # .branch_lt[0]
 # THUNK-LABEL: <__long_branch_callee>:
@@ -78,7 +78,7 @@ test:
 
 # .branch_lt[1]
 # THUNK-LABEL: <__long_branch_tail_callee>:
-# THUNK-NEXT: 10010040:       addis 12, 2, 1
+# THUNK-NEXT: 10010050:       addis 12, 2, 1
 # THUNK-NEXT:                 ld 12, -32752(12)
 # THUNK-NEXT:                 mtctr 12
 # THUNK-NEXT:                 bctr

diff  --git a/lld/test/ELF/ppc64-long-branch-localentry-offset.s b/lld/test/ELF/ppc64-long-branch-localentry-offset.s
index 9e631747e433..d58220c11e91 100644
--- a/lld/test/ELF/ppc64-long-branch-localentry-offset.s
+++ b/lld/test/ELF/ppc64-long-branch-localentry-offset.s
@@ -5,8 +5,8 @@
 # RUN: llvm-nm %t | FileCheck %s
 
 # CHECK-DAG: 0000000010010000 t __long_branch_callee
-# CHECK-DAG: 0000000010010010 T _start
-# CHECK-DAG: 0000000012010008 T callee
+# CHECK-DAG: 0000000010010020 T _start
+# CHECK-DAG: 0000000012010018 T callee
 
 # The bl instruction jumps to the local entry. The distance requires a long branch stub:
 # localentry(callee) - _start = 0x12010008+8 - 0x10010010 = 0x2000000

diff  --git a/lld/test/ELF/ppc64-long-branch-pi.s b/lld/test/ELF/ppc64-long-branch-pi.s
index 36f14f5cc319..0a62aada2a6f 100644
--- a/lld/test/ELF/ppc64-long-branch-pi.s
+++ b/lld/test/ELF/ppc64-long-branch-pi.s
@@ -14,26 +14,26 @@
 # RUN: llvm-objdump -d --no-show-raw-insn %t.so | FileCheck %s
 
 # SEC-PIE:    Name       Type     Address          Off     Size   ES Flg Lk Inf Al
-# SEC-PIE:    .got       PROGBITS 00000000020020f0 20120f0 000008 00  WA  0   0  8
-# SEC-PIE:    .branch_lt NOBITS   0000000002002100 2012100 000020 00  WA  0   0  8
+# SEC-PIE:    .got       PROGBITS 0000000002002100 2012100 000008 00  WA  0   0  8
+# SEC-PIE:    .branch_lt NOBITS   0000000002002110 2012110 000020 00  WA  0   0  8
 
 # SEC-SHARED: Name       Type     Address          Off     Size   ES Flg Lk Inf Al
-# SEC-SHARED: .got       PROGBITS 00000000020020d0 20120d0 000008 00  WA  0   0  8
-# SEC-SHARED: .branch_lt NOBITS   00000000020020e0 20120e0 000020 00  WA  0   0  8
+# SEC-SHARED: .got       PROGBITS 00000000020020e0 20120e0 000008 00  WA  0   0  8
+# SEC-SHARED: .branch_lt NOBITS   00000000020020f0 20120f0 000020 00  WA  0   0  8
 
 # RELOC:      .rela.dyn {
-# RELOC-NEXT:   0x20020F8 R_PPC64_RELATIVE - 0x8000
-# RELOC-NEXT:   0x2002100 R_PPC64_RELATIVE - 0x2002000
-# RELOC-NEXT:   0x2002108 R_PPC64_RELATIVE - 0x2002008
-# RELOC-NEXT:   0x2002110 R_PPC64_RELATIVE - 0x200200C
-# RELOC-NEXT:   0x2002118 R_PPC64_RELATIVE - 0x2000
+# RELOC-NEXT:   0x2002108 R_PPC64_RELATIVE - 0x8000
+# RELOC-NEXT:   0x2002110 R_PPC64_RELATIVE - 0x2002000
+# RELOC-NEXT:   0x2002118 R_PPC64_RELATIVE - 0x2002008
+# RELOC-NEXT:   0x2002120 R_PPC64_RELATIVE - 0x200200C
+# RELOC-NEXT:   0x2002128 R_PPC64_RELATIVE - 0x2000
 # RELOC-NEXT: }
 
 # CHECK:      <_start>:
 # CHECK-NEXT:     2000:       bl 0x2010
 # CHECK-NEXT:                 bl 0x2002000
-# CHECK-NEXT:                 bl 0x2020
 # CHECK-NEXT:                 bl 0x2030
+# CHECK-NEXT:                 bl 0x2050
 
 ## &.branch_lt[0] - .TOC. = .branch_lt - (.got+0x8000) = -32752
 # CHECK:      <__long_branch_>:
@@ -44,14 +44,14 @@
 
 ## &.branch_lt[1] - .TOC. = .branch_lt - (.got+0x8000) = -32744
 # CHECK:      <__long_branch_>:
-# CHECK-NEXT:     2020:       addis 12, 2, 0
+# CHECK-NEXT:     2030:       addis 12, 2, 0
 # CHECK-NEXT:                 ld 12, -32744(12)
 # CHECK-NEXT:                 mtctr 12
 # CHECK-NEXT:                 bctr
 
 ## &.branch_lt[2] - .TOC. = .branch_lt - (.got+0x8000) = -32736
 # CHECK:      <__long_branch_>:
-# CHECK-NEXT:     2030:       addis 12, 2, 0
+# CHECK-NEXT:     2050:       addis 12, 2, 0
 # CHECK-NEXT:                 ld 12, -32736(12)
 # CHECK-NEXT:                 mtctr 12
 # CHECK-NEXT:                 bctr

diff  --git a/lld/test/ELF/ppc64-long-branch-rel14.s b/lld/test/ELF/ppc64-long-branch-rel14.s
index 3332e4ec6d9e..722f3b6513bd 100644
--- a/lld/test/ELF/ppc64-long-branch-rel14.s
+++ b/lld/test/ELF/ppc64-long-branch-rel14.s
@@ -20,7 +20,7 @@
 # CHECK-NEXT:  2000: bt 2, 0x2020
 # CHECK-NEXT:        bt+ 2, 0x2020
 # CHECK-NEXT:        bf 2, 0xa004
-# CHECK-NEXT:        bt 2, 0x2030
+# CHECK-NEXT:        bt 2, 0x2040
 # CHECK-NEXT:        blr
 # CHECK-NEXT:        trap
 # CHECK-NEXT:        trap
@@ -31,10 +31,11 @@
 # CHECK-NEXT:        ld 12, {{.*}}(12)
 # CHECK-NEXT:        mtctr 12
 # CHECK-NEXT:        bctr
+# CHECK-NEXT:        ...
 # CHECK-EMPTY:
 
 # CHECK-NEXT: <__long_branch_>:
-# CHECK-NEXT:  2030: addis 12, 2, 0
+# CHECK-NEXT:  2040: addis 12, 2, 0
 # CHECK-NEXT:        ld 12, {{.*}}(12)
 # CHECK-NEXT:        mtctr 12
 # CHECK-NEXT:        bctr

diff  --git a/lld/test/ELF/ppc64-long-branch.s b/lld/test/ELF/ppc64-long-branch.s
index 7fa3c4b327fd..c937048e6ed8 100644
--- a/lld/test/ELF/ppc64-long-branch.s
+++ b/lld/test/ELF/ppc64-long-branch.s
@@ -19,16 +19,16 @@
 # RUN: llvm-nm --no-sort %t | FileCheck --check-prefix=NM %s
 
 # SEC: Name       Type     Address          Off     Size   ES Flg Lk Inf Al
-# SEC: .got       PROGBITS 0000000002002030 2002030 000008 00  WA  0   0  8
-# SEC: .branch_lt PROGBITS 0000000002002038 2002038 000018 00  WA  0   0  8
+# SEC: .got       PROGBITS 0000000002002040 2002040 000008 00  WA  0   0  8
+# SEC: .branch_lt PROGBITS 0000000002002048 2002048 000018 00  WA  0   0  8
 
 # SEC: There are no relocations in this file.
 
 ## high at localentry (high+8), .text_high+16 and .text_low+8
-# BRANCH-LE:      0x02002038 08200002 00000000 10200002 00000000
-# BRANCH-LE-NEXT: 0x02002048 08200000 00000000
-# BRANCH-BE:      0x02002038 00000000 02002008 00000000 02002010
-# BRANCH-BE-NEXT: 0x02002048 00000000 00002008
+# BRANCH-LE:      0x02002048 08200002 00000000 10200002 00000000
+# BRANCH-LE-NEXT: 0x02002058 08200000 00000000
+# BRANCH-BE:      0x02002048 00000000 02002008 00000000 02002010
+# BRANCH-BE-NEXT: 0x02002058 00000000 00002008
 
 # CHECK:      <_start>:
 # CHECK-NEXT:     2000:       bl 0x2020
@@ -45,7 +45,7 @@
 
 ## &.branch_lt[1] - .TOC. = .branch_lt - (.got+0x8000) = -32752
 # CHECK:      <__long_branch_>:
-# CHECK-NEXT:     2030:       addis 12, 2, 0
+# CHECK-NEXT:     2040:       addis 12, 2, 0
 # CHECK-NEXT:                 ld 12, -32752(12)
 # CHECK-NEXT:                 mtctr 12
 # CHECK-NEXT:                 bctr
@@ -64,7 +64,7 @@ blr
 # CHECK-EMPTY:
 # CHECK-NEXT: <high>:
 # CHECK-NEXT:  2002000:       addis 2, 12, 1
-# CHECK-NEXT:                 addi 2, 2, -32720
+# CHECK-NEXT:                 addi 2, 2, -32704
 # CHECK-NEXT:                 bl 0x2008
 # CHECK-NEXT:                 bl 0x2002020
 # CHECK:      <__long_branch_>:

diff  --git a/lld/test/ELF/ppc64-pcrel-call-to-extern.s b/lld/test/ELF/ppc64-pcrel-call-to-extern.s
index fa476b8884bd..500132fd88f5 100644
--- a/lld/test/ELF/ppc64-pcrel-call-to-extern.s
+++ b/lld/test/ELF/ppc64-pcrel-call-to-extern.s
@@ -23,6 +23,24 @@
 # RUN: llvm-readobj -r %t | FileCheck %s --check-prefix=REL
 # RUN: llvm-objdump -d --no-show-raw-insn --mcpu=pwr10 %t | FileCheck %s
 
+# RUN: llvm-mc -filetype=obj -triple=powerpc64le --defsym AUX=1 %s -o %t1.o
+# RUN: llvm-mc -filetype=obj -triple=powerpc64le %s -o %t2.o
+# RUN: ld.lld --shared %t2.o -o %t2.so
+# RUN: ld.lld -T %t.script %t1.o %t2.so -o %t --no-power10-stubs
+# RUN: llvm-readelf -s %t | FileCheck %s --check-prefix=SYMBOL-NOP10
+# RUN: llvm-readelf -S -d %t | FileCheck %s --check-prefix=SEC-NOP10
+# RUN: llvm-readobj -r %t | FileCheck %s --check-prefix=REL-NOP10
+# RUN: llvm-objdump -d --no-show-raw-insn --mcpu=pwr10 %t | FileCheck %s --check-prefix=CHECK-NOP10
+
+# RUN: llvm-mc -filetype=obj -triple=powerpc64 --defsym AUX=1 %s -o %t1.o
+# RUN: llvm-mc -filetype=obj -triple=powerpc64 %s -o %t2.o
+# RUN: ld.lld --shared %t2.o -o %t2.so
+# RUN: ld.lld -T %t.script %t1.o %t2.so -o %t --no-power10-stubs
+# RUN: llvm-readelf -s %t | FileCheck %s --check-prefix=SYMBOL-NOP10
+# RUN: llvm-readelf -S -d %t | FileCheck %s --check-prefix=SEC-NOP10
+# RUN: llvm-readobj -r %t | FileCheck %s --check-prefix=REL-NOP10
+# RUN: llvm-objdump -d --no-show-raw-insn --mcpu=pwr10 %t | FileCheck %s --check-prefix=CHECK-NOP10
+
 ## The test is created to check that when a function without TOC access an
 ## external function, a r12 setup stub is inserted.
 
@@ -35,56 +53,127 @@
 # SYMBOL:      2: 0000000010010000     0 NOTYPE  LOCAL  DEFAULT [<other: 0x20>]   6 caller1
 # SYMBOL-NEXT: 3: 0000000010020000     0 NOTYPE  LOCAL  DEFAULT [<other: 0x20>]   7 caller2
 # SYMBOL-NEXT: 4: 0000000010030000     0 NOTYPE  LOCAL  DEFAULT [<other: 0x20>]   8 caller3
-# SYMBOL:      6: 0000000010010010    16 FUNC    LOCAL  DEFAULT                  6 __plt_pcrel_callee_global_stother0
-# SYMBOL-NEXT: 7: 0000000010020010    16 FUNC    LOCAL  DEFAULT                  7 __plt_pcrel_callee_global_stother1
-# SYMBOL-NEXT: 8: 0000000010030010    16 FUNC    LOCAL  DEFAULT                  8 __plt_pcrel_callee_global_TOC
+# SYMBOL:      6: 0000000010010010    32 FUNC    LOCAL  DEFAULT                  6 __plt_pcrel_callee_global_stother0
+# SYMBOL-NEXT: 7: 0000000010020010    32 FUNC    LOCAL  DEFAULT                  7 __plt_pcrel_callee_global_stother1
+# SYMBOL-NEXT: 8: 0000000010030010    32 FUNC    LOCAL  DEFAULT                  8 __plt_pcrel_callee_global_TOC
 # SYMBOL-NEXT: 9: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT                UND callee_global_stother0
 # SYMBOL-NEXT: 10: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT [<other: 0x20>] UND callee_global_stother1
 # SYMBOL-NEXT: 11: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT [<other: 0x60>] UND callee_global_TOC
 
+# SYMBOL-NOP10: Symbol table '.symtab' contains 12 entries:
+# SYMBOL-NOP10:      2: 0000000010010000     0 NOTYPE  LOCAL  DEFAULT [<other: 0x20>]   6 caller1
+# SYMBOL-NOP10-NEXT: 3: 0000000010020000     0 NOTYPE  LOCAL  DEFAULT [<other: 0x20>]   7 caller2
+# SYMBOL-NOP10-NEXT: 4: 0000000010030000     0 NOTYPE  LOCAL  DEFAULT [<other: 0x20>]   8 caller3
+# SYMBOL-NOP10:      6: 0000000010010010    32 FUNC    LOCAL  DEFAULT                  6 __plt_pcrel_callee_global_stother0
+# SYMBOL-NOP10-NEXT: 7: 0000000010020010    32 FUNC    LOCAL  DEFAULT                  7 __plt_pcrel_callee_global_stother1
+# SYMBOL-NOP10-NEXT: 8: 0000000010030010    32 FUNC    LOCAL  DEFAULT                  8 __plt_pcrel_callee_global_TOC
+# SYMBOL-NOP10-NEXT: 9: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT                UND callee_global_stother0
+# SYMBOL-NOP10-NEXT: 10: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT [<other: 0x20>] UND callee_global_stother1
+# SYMBOL-NOP10-NEXT: 11: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT [<other: 0x60>] UND callee_global_TOC
+
 ## DT_PLTGOT points to .plt
-# SEC: .plt              NOBITS          0000000010030148 040148 000028 00  WA  0   0  8
-# SEC: 0x0000000000000003 (PLTGOT)      0x10030148
+# SEC: .plt              NOBITS          0000000010030158 040158 000028 00  WA  0   0  8
+# SEC-OG: .plt              NOBITS          0000000010030148 040148 000028 00  WA  0   0  8
+# SEC: 0x0000000000000003 (PLTGOT)      0x10030158
+# SEC-OG: 0x0000000000000003 (PLTGOT)      0x10030158
+
+## DT_PLTGOT points to .plt
+# SEC-NOP10: .plt              NOBITS          0000000010030158 040158 000028 00  WA  0   0  8
+# SEC-NOP10: 0x0000000000000003 (PLTGOT)      0x10030158
 
 ## The first 2 entries in the .plt are reserved for the dynamic linkers
 ## usage. The JMP_SLOT relocations are stored at .plt[2], .plt[3], .plt[4].
 ## Check that we emit 3 R_PPC64_JMP_SLOT in .rela.plt.
 # REL:      .rela.plt {
-# REL-NEXT:   0x10030158 R_PPC64_JMP_SLOT callee_global_stother0 0x0
-# REL-NEXT:   0x10030160 R_PPC64_JMP_SLOT callee_global_stother1 0x0
-# REL-NEXT:   0x10030168 R_PPC64_JMP_SLOT callee_global_TOC 0x0
+# REL-NEXT:   0x10030168 R_PPC64_JMP_SLOT callee_global_stother0 0x0
+# REL-NEXT-OG:   0x10030158 R_PPC64_JMP_SLOT callee_global_stother0 0x0
+# REL-NEXT:   0x10030170 R_PPC64_JMP_SLOT callee_global_stother1 0x0
+# REL-NEXT-OG:   0x10030160 R_PPC64_JMP_SLOT callee_global_stother1 0x0
+# REL-NEXT:   0x10030178 R_PPC64_JMP_SLOT callee_global_TOC 0x0
+# REL-NEXT-OG:   0x10030168 R_PPC64_JMP_SLOT callee_global_TOC 0x0
 # REL-NEXT: }
 
+# REL-NOP10:      .rela.plt {
+# REL-NOP10-NEXT:   0x10030168 R_PPC64_JMP_SLOT callee_global_stother0 0x0
+# REL-NOP10-NEXT:   0x10030170 R_PPC64_JMP_SLOT callee_global_stother1 0x0
+# REL-NOP10-NEXT:   0x10030178 R_PPC64_JMP_SLOT callee_global_TOC 0x0
+# REL-NOP10-NEXT: }
+
 # CHECK-LABEL: <caller1>:
 # CHECK:       10010000: bl 0x10010010
 # CHECK-NEXT:  10010004: blr
 
-## .plt[2] - 0x10010010 = 0x10030158 - 0x10010010 = 0x20148 = 131400
+# CHECK-NOP10-LABEL: <caller1>:
+# CHECK-NOP10:       10010000: bl 0x10010010
+# CHECK-NOP10-NEXT:  10010004: blr
+
+## .plt[2] - 0x10010010 = 0x10030168 - 0x10010010 = 0x20158 = 131416
 # CHECK-LABEL: <__plt_pcrel_callee_global_stother0>:
-# CHECK:       10010010: pld 12, 131400(0), 1
+# CHECK:       10010010: pld 12, 131416(0), 1
 # CHECK-NEXT:  10010018: mtctr 12
 # CHECK-NEXT:  1001001c: bctr
 
+## No P10; branch to next inst to get addr
+# CHECK-NOP10-LABEL: <__plt_pcrel_callee_global_stother0>:
+# CHECK-NOP10:       10010010: mflr 0
+# CHECK-NOP10-NEXT:  10010014: bcl 20, 31, 0x10010018
+# CHECK-NOP10:       10010018: mflr 11
+# CHECK-NOP10:       1001001c: mtlr 12
+# CHECK-NOP10:       10010020: addis 12, 11, -4097
+# CHECK-NOP10:       10010024: addi  12, 12, -24
+# CHECK-NOP10-NEXT:  10010028: mtctr 12
+# CHECK-NOP10-NEXT:  1001002c: bctr
+
 # CHECK-LABEL: <caller2>:
 # CHECK:       10020000: bl 0x10020010
 # CHECK-NEXT:  10020004: blr
 
-## .plt[3] - 0x10020010 = 0x10030160 - 0x10020010 = 0x10150 = 65872
+# CHECK-NOP10-LABEL: <caller2>:
+# CHECK-NOP10:       10020000: bl 0x10020010
+# CHECK-NOP10-NEXT:  10020004: blr
+
+## .plt[3] - 0x10020010 = 0x10030170 - 0x10020010 = 0x10160 = 65888
 # CHECK-LABEL: <__plt_pcrel_callee_global_stother1>:
-# CHECK:       10020010: pld 12, 65872(0), 1
+# CHECK:       10020010: pld 12, 65888(0), 1
 # CHECK-NEXT:  10020018: mtctr 12
 # CHECK-NEXT:  1002001c: bctr
 
+## no P10; branch to next inst to get addr
+# CHECK-NOP10-LABEL: <__plt_pcrel_callee_global_stother1>:
+# CHECK-NOP10:       10020010: mflr 0
+# CHECK-NOP10-NEXT:  10020014: bcl 20, 31, 0x10020018
+# CHECK-NOP10-NEXT:  10020018: mflr 11
+# CHECK-NOP10-NEXT:  1002001c: mtlr 12
+# CHECK-NOP10-NEXT:  10020020: addis 12, 11, -4098
+# CHECK-NOP10-NEXT:  10020024: addi 12, 12, -24
+# CHECK-NOP10-NEXT:  10020028: mtctr 12
+# CHECK-NOP10-NEXT:  1002002c: bctr
+
 # CHECK-LABEL: <caller3>:
 # CHECK:       10030000: bl 0x10030010
 # CHECK-NEXT:  10030004: blr
 
-## .plt[4] - 0x10030010 = 0x10030168 - 0x10030010 = 0x150 = 344
+# CHECK-NOP10-LABEL: <caller3>:
+# CHECK-NOP10:       10030000: bl 0x10030010
+# CHECK-NOP10-NEXT:  10030004: blr
+
+## .plt[4] - 0x10030010 = 0x10030178 - 0x10030010 = 0x168 = 360
 # CHECK-LABEL: <__plt_pcrel_callee_global_TOC>:
-# CHECK:       10030010: pld 12, 344(0), 1
+# CHECK:       10030010: pld 12, 360(0), 1
 # CHECK-NEXT:  10030018: mtctr 12
 # CHECK-NEXT:  1003001c: bctr
 
+## no P10; branch to next inst to get addr
+# CHECK-NOP10-LABEL: <__plt_pcrel_callee_global_TOC>:
+# CHECK-NOP10-NEXT:  10030010: mflr 0
+# CHECK-NOP10-NEXT:  10030014: bcl 20, 31, 0x10030018
+# CHECK-NOP10-NEXT:  10030018: mflr 11
+# CHECK-NOP10-NEXT:  1003001c: mtlr 12
+# CHECK-NOP10-NEXT:  10030020: addis 12, 11, -4099
+# CHECK-NOP10-NEXT:  10030024: addi 12, 12, -24
+# CHECK-NOP10-NEXT:  10030028: mtctr 12
+# CHECK-NOP10-NEXT:  1003002c: bctr
+
 .ifdef AUX
 .section .text_caller1, "ax", %progbits
 caller1:

diff  --git a/lld/test/ELF/ppc64-pcrel-call-to-toc.s b/lld/test/ELF/ppc64-pcrel-call-to-toc.s
index 8b61bf4827ba..15ef21ea5d42 100644
--- a/lld/test/ELF/ppc64-pcrel-call-to-toc.s
+++ b/lld/test/ELF/ppc64-pcrel-call-to-toc.s
@@ -15,13 +15,19 @@
 # RUN: llvm-readelf -s %t | FileCheck %s --check-prefix=SYMBOL
 # RUN: llvm-objdump -d --no-show-raw-insn --mcpu=pwr10 %t | FileCheck %s
 
+# RUN: llvm-mc -filetype=obj -triple=powerpc64le %s -o %t.o
+# RUN: ld.lld -T %t.script %t.o -o %t --no-power10-stubs
+# RUN: llvm-readelf -s %t | FileCheck %s --check-prefix=SYMBOL
+# RUN: llvm-objdump -d --no-show-raw-insn --mcpu=pwr10 %t \
+# RUN: | FileCheck %s --check-prefix=CHECK-NOP10
+
 ## When a function without TOC accesses a function using TOC, an r12 setup stub
 ## is inserted
 
 # SYMBOL:      1: 0000000010010000 0 NOTYPE LOCAL DEFAULT 1 func
 # SYMBOL-NEXT: 2: 0000000010020000 0 NOTYPE LOCAL DEFAULT [<other: 0x60>] 2 callee
 # SYMBOL:      4: 0000000010030000 0 NOTYPE LOCAL DEFAULT [<other: 0x20>] 3 caller
-# SYMBOL:      6: 0000000010030010 16 FUNC LOCAL DEFAULT 3 __gep_setup_callee
+# SYMBOL:      6: 0000000010030010 32 FUNC LOCAL DEFAULT 3 __gep_setup_callee
 
 # CHECK-LABEL: <func>:
 # CHECK-NEXT:  blr
@@ -29,7 +35,7 @@
 # CHECK-LABEL: <callee>:
 # CHECK:       bl 0x10010000
 # CHECK-NEXT:  addis 4, 2, -1
-# CHECK-NEXT:  lwz 4, 32744(4)
+# CHECK-NEXT:  lwz 4, 32728(4)
 # CHECK-NEXT:  blr
 
 # CHECK-LABEL: <caller>:
@@ -41,6 +47,16 @@
 # CHECK-NEXT:  mtctr 12
 # CHECK-NEXT:  bctr
 
+# CHECK-NOP10-LABEL: <__gep_setup_callee>:
+# CHECK-NOP10-NEXT:  mflr 0
+# CHECK-NOP10-NEXT:  bcl 20, 31, 0x10030018
+# CHECK-NOP10-NEXT:  mflr 11
+# CHECK-NOP10-NEXT:  mtlr 12
+# CHECK-NOP10-NEXT:  addis 12, 11, -1
+# CHECK-NOP10-NEXT:  addi 12, 12, -24
+# CHECK-NOP10-NEXT:  mtctr 12
+# CHECK-NOP10-NEXT:  bctr
+
 .section .text_func, "ax", %progbits
 func:
   blr

diff  --git a/lld/test/ELF/ppc64-plt-stub-compatible.s b/lld/test/ELF/ppc64-plt-stub-compatible.s
index c0ffb4154ccc..07773b645b3a 100644
--- a/lld/test/ELF/ppc64-plt-stub-compatible.s
+++ b/lld/test/ELF/ppc64-plt-stub-compatible.s
@@ -29,9 +29,9 @@ callee:
 
 # T2-LABEL: <p9codegen>:
 # T2-NEXT:    10010300: addis 2, 12, 1
-# T2-NEXT:    10010304: addi 2, 2, -32384
+# T2-NEXT:    10010304: addi 2, 2, -32368
 # T2-NEXT:    10010308: addis 4, 2, -1
-# T2-NEXT:    1001030c: lwa 3, 32428(4)
+# T2-NEXT:    1001030c: lwa 3, 32412(4)
 # T2-NEXT:    10010310: bl 0x10010330
 # T2-NEXT:    10010314: ld 2, 24(1)
 # T2-NEXT:    10010318: blr
@@ -49,7 +49,7 @@ callee:
 # T2-NEXT:    10010340: bctr
 
 # T2-LABEL: <__plt_pcrel_callee>:
-# T2-NEXT:    10010350: pld 12, 328(0), 1
+# T2-NEXT:    10010350: pld 12, 344(0), 1
 # T2-NEXT:    10010358: mtctr 12
 # T2-NEXT:    1001035c: bctr
 .ifdef T2
@@ -83,24 +83,24 @@ Global:
 
 # T3-LABEL: <p9codegen>:
 # T3-NEXT:    10010310: addis 2, 12, 1
-# T3-NEXT:    10010314: addi 2, 2, -32408
+# T3-NEXT:    10010314: addi 2, 2, -32392
 # T3-NEXT:    10010318: addis 4, 2, -1
-# T3-NEXT:    1001031c: lwa 3, 32436(4)
-# T3-NEXT:    10010320: bl 0x10010340
+# T3-NEXT:    1001031c: lwa 3, 32420(4)
+# T3-NEXT:    10010320: bl 0x10010350
 # T3-NEXT:    10010324: ld 2, 24(1)
 # T3-NEXT:    10010328: blr
 
 # T3-LABEL: <__plt_pcrel_callee>:
-# T3-NEXT:    10010330: pld 12, 352(0), 1
+# T3-NEXT:    10010330: pld 12, 368(0), 1
 # T3-NEXT:    10010338: mtctr 12
 # T3-NEXT:    1001033c: bctr
 
 # T3-LABEL: <__plt_callee>:
-# T3-NEXT:    10010340: std 2, 24(1)
-# T3-NEXT:    10010344: addis 12, 2, 0
-# T3-NEXT:    10010348: ld 12, -32744(12)
-# T3-NEXT:    1001034c: mtctr 12
-# T3-NEXT:    10010350: bctr
+# T3-NEXT:    10010350: std 2, 24(1)
+# T3-NEXT:    10010354: addis 12, 2, 0
+# T3-NEXT:    10010358: ld 12, -32744(12)
+# T3-NEXT:    1001035c: mtctr 12
+# T3-NEXT:    10010360: bctr
 .ifdef T3
 .section .text_start, "ax", %progbits
 p10codegen:

diff  --git a/lld/test/ELF/ppc64-tls-pcrel-gd.s b/lld/test/ELF/ppc64-tls-pcrel-gd.s
index 565f29ce0093..eb4f5ccfcf4c 100644
--- a/lld/test/ELF/ppc64-tls-pcrel-gd.s
+++ b/lld/test/ELF/ppc64-tls-pcrel-gd.s
@@ -42,10 +42,10 @@ y:
 #--- asm
 
 # GD-RELOC: Relocation section '.rela.dyn' at offset 0x100b8 contains 4 entries:
-# GD-RELOC: 0000000001001160  0000000100000044 R_PPC64_DTPMOD64       0000000000000000 x + 0
-# GD-RELOC: 0000000001001168  000000010000004e R_PPC64_DTPREL64       0000000000000000 x + 0
-# GD-RELOC: 0000000001001170  0000000300000044 R_PPC64_DTPMOD64       0000000000000000 y + 0
-# GD-RELOC: 0000000001001178  000000030000004e R_PPC64_DTPREL64       0000000000000000 y + 0
+# GD-RELOC: 0000000001001170  0000000100000044 R_PPC64_DTPMOD64       0000000000000000 x + 0
+# GD-RELOC: 0000000001001178  000000010000004e R_PPC64_DTPREL64       0000000000000000 x + 0
+# GD-RELOC: 0000000001001180  0000000300000044 R_PPC64_DTPMOD64       0000000000000000 y + 0
+# GD-RELOC: 0000000001001188  000000030000004e R_PPC64_DTPREL64       0000000000000000 y + 0
 
 # GD-SYM:   Symbol table '.dynsym' contains 4 entries:
 # GD-SYM:   0000000000000000     0 TLS     GLOBAL DEFAULT   UND x
@@ -68,9 +68,9 @@ y:
 # GDTOLE-SYM: 0000000000000004     0 TLS     GLOBAL DEFAULT     3 y
 
 # GD-LABEL: <GDTwoVal>:
-# GD-NEXT:    paddi 3, 0, 352, 1
+# GD-NEXT:    paddi 3, 0, 368, 1
 # GD-NEXT:    bl
-# GD-NEXT:    paddi 3, 0, 356, 1
+# GD-NEXT:    paddi 3, 0, 372, 1
 # GD-NEXT:    bl
 # GD-NEXT:    blr
 # GDTOIE-LABEL: <GDTwoVal>:

diff  --git a/lld/test/ELF/ppc64-toc-call-to-pcrel-long-jump.s b/lld/test/ELF/ppc64-toc-call-to-pcrel-long-jump.s
index 0cd8fd15fbaa..f8810130fa9c 100644
--- a/lld/test/ELF/ppc64-toc-call-to-pcrel-long-jump.s
+++ b/lld/test/ELF/ppc64-toc-call-to-pcrel-long-jump.s
@@ -11,15 +11,20 @@
 # RUN: llvm-objdump --mcpu=pwr10 --no-show-raw-insn -d %t_be | FileCheck %s
 # RUN: llvm-readelf -s %t_be | FileCheck %s --check-prefix=SYM
 
+# RUN: llvm-mc -filetype=obj -triple=powerpc64le %t/asm -o %t.o
+# RUN: ld.lld -T %t/lts %t.o -o %t_le --no-power10-stubs
+# RUN: llvm-objdump --mcpu=pwr10 --no-show-raw-insn -d %t_le | FileCheck %s --check-prefix=NoP10
+# RUN: llvm-readelf -s %t_le | FileCheck %s --check-prefix=SYM
+
 # SYM:      Symbol table '.symtab' contains 9 entries:
 # SYM:      1: 0000000010010000     0 NOTYPE  LOCAL  DEFAULT [<other: 0x20>]   1 callee
 # SYM-NEXT: 2: 0000000010020008     0 NOTYPE  LOCAL  DEFAULT                  2 caller_close
 # SYM-NEXT: 3: 0000000020020008     0 NOTYPE  LOCAL  DEFAULT [<other: 0x60>]   3 caller
 # SYM-NEXT: 4: 0000000520020008     0 NOTYPE  LOCAL  DEFAULT                  4 caller_far
-# SYM-NEXT: 5: 0000000520028038     0 NOTYPE  LOCAL  HIDDEN                   6 .TOC.
+# SYM-NEXT: 5: 0000000520028040     0 NOTYPE  LOCAL  HIDDEN                   6 .TOC.
 # SYM-NEXT: 6: 0000000010020020     8 FUNC    LOCAL  DEFAULT                  2 __toc_save_callee
-# SYM-NEXT: 7: 0000000020020020    20 FUNC    LOCAL  DEFAULT                  3 __toc_save_callee
-# SYM-NEXT: 8: 0000000520020020    20 FUNC    LOCAL  DEFAULT                  4 __toc_save_callee
+# SYM-NEXT: 7: 0000000020020020    32 FUNC    LOCAL  DEFAULT                  3 __toc_save_callee
+# SYM-NEXT: 8: 0000000520020020    32 FUNC    LOCAL  DEFAULT                  4 __toc_save_callee
 
 #--- lts
 PHDRS {
@@ -72,6 +77,17 @@ caller_close:
 # CHECK-NEXT:    paddi 12, 0, -268501028, 1
 # CHECK-NEXT:    mtctr 12
 # CHECK-NEXT:    bctr
+
+# NoP10-LABEL: <caller>:
+# NoP10:         bl 0x20020020
+# NoP10-NEXT:    ld 2, 24(1)
+# NoP10-NEXT:    blr
+# NoP10-LABEL: <__toc_save_callee>:
+# NoP10-NEXT:         std 2, 24(1)
+# NoP10-NEXT:    addis 12, 2, -4098
+# NoP10-NEXT:    addi 12, 12, 32704
+# NoP10-NEXT:    mtctr 12
+# NoP10-NEXT:    bctr
 .section .text_caller, "ax", %progbits
 .Lfunc_toc2:
   .quad .TOC.-.Lfunc_gep2

diff  --git a/lld/test/ELF/ppc64-toc-call-to-pcrel.s b/lld/test/ELF/ppc64-toc-call-to-pcrel.s
index 132f90fcc782..2013ba723d2b 100644
--- a/lld/test/ELF/ppc64-toc-call-to-pcrel.s
+++ b/lld/test/ELF/ppc64-toc-call-to-pcrel.s
@@ -14,6 +14,12 @@
 # RUN: llvm-readelf -s %t | FileCheck %s --check-prefix=SYMBOL
 # RUN: llvm-objdump -d --no-show-raw-insn --mcpu=future %t | FileCheck %s
 
+# RUN: llvm-mc -filetype=obj -triple=powerpc64 %s -o %t.o
+# RUN: ld.lld -T %t.script %t.o -o %t --no-power10-stubs
+# RUN: llvm-readelf -s %t | FileCheck %s --check-prefix=SYMBOL
+# RUN: llvm-objdump -d --no-show-raw-insn --mcpu=future %t \
+# RUN: | FileCheck %s
+
 # The point of this test is to make sure that when a function with TOC access
 # a local function with st_other=1, a TOC save stub is inserted.
 

diff  --git a/llvm/include/llvm/Object/ELF.h b/llvm/include/llvm/Object/ELF.h
index 447b4c25ce81..03e64e1d34dc 100644
--- a/llvm/include/llvm/Object/ELF.h
+++ b/llvm/include/llvm/Object/ELF.h
@@ -87,6 +87,9 @@ static inline Error createError(const Twine &Err) {
 
 enum PPCInstrMasks : uint64_t {
   PADDI_R12_NO_DISP = 0x0610000039800000,
+  ADDIS_R12_TO_R2_NO_DISP = 0x3D820000,
+  ADDI_R12_TO_R2_NO_DISP = 0x39820000,
+  ADDI_R12_TO_R12_NO_DISP = 0x398C0000,
   PLD_R12_NO_DISP = 0x04100000E5800000,
   MTCTR_R12 = 0x7D8903A6,
   BCTR = 0x4E800420,


        


More information about the llvm-commits mailing list