@@ -309,7 +309,7 @@ class PPC64R2SaveStub final : public Thunk {
309
309
}
310
310
return true ;
311
311
}
312
- uint32_t size () override { return getMayUseShortThunk () ? 8 : 20 ; }
312
+ uint32_t size () override { return getMayUseShortThunk () ? 8 : 32 ; }
313
313
void writeTo (uint8_t *buf) override ;
314
314
void addSymbols (ThunkSection &isec) override ;
315
315
@@ -330,7 +330,7 @@ class PPC64R2SaveStub final : public Thunk {
330
330
class PPC64R12SetupStub final : public Thunk {
331
331
public:
332
332
PPC64R12SetupStub (Symbol &dest) : Thunk(dest, 0 ) { alignment = 16 ; }
333
- uint32_t size () override { return 16 ; }
333
+ uint32_t size () override { return 32 ; }
334
334
void writeTo (uint8_t *buf) override ;
335
335
void addSymbols (ThunkSection &isec) override ;
336
336
};
@@ -345,7 +345,7 @@ class PPC64R12SetupStub final : public Thunk {
345
345
class PPC64PCRelPLTStub final : public Thunk {
346
346
public:
347
347
PPC64PCRelPLTStub (Symbol &dest) : Thunk(dest, 0 ) { alignment = 16 ; }
348
- uint32_t size () override { return 16 ; }
348
+ uint32_t size () override { return 32 ; }
349
349
void writeTo (uint8_t *buf) override ;
350
350
void addSymbols (ThunkSection &isec) override ;
351
351
bool isCompatibleWith (const InputSection &isec,
@@ -362,7 +362,7 @@ class PPC64PCRelPLTStub final : public Thunk {
362
362
// used.
363
363
class PPC64LongBranchThunk : public Thunk {
364
364
public:
365
- uint32_t size () override { return 16 ; }
365
+ uint32_t size () override { return 32 ; }
366
366
void writeTo (uint8_t *buf) override ;
367
367
void addSymbols (ThunkSection &isec) override ;
368
368
bool isCompatibleWith (const InputSection &isec,
@@ -406,7 +406,7 @@ class PPC64PCRelLongBranchThunk final : public Thunk {
406
406
: Thunk(dest, addend) {
407
407
alignment = 16 ;
408
408
}
409
- uint32_t size () override { return 16 ; }
409
+ uint32_t size () override { return 32 ; }
410
410
void writeTo (uint8_t *buf) override ;
411
411
void addSymbols (ThunkSection &isec) override ;
412
412
bool isCompatibleWith (const InputSection &isec,
@@ -922,17 +922,34 @@ bool PPC64PltCallStub::isCompatibleWith(const InputSection &isec,
922
922
923
923
void PPC64R2SaveStub::writeTo (uint8_t *buf) {
924
924
const int64_t offset = computeOffset ();
925
- write32 (buf + 0 , 0xf8410018 ); // std r2,24(r1)
925
+ write32 (buf + 0 , 0xf8410018 ); // std r2,24(r1)
926
926
// The branch offset needs to fit in 26 bits.
927
927
if (getMayUseShortThunk ()) {
928
928
write32 (buf + 4 , 0x48000000 | (offset & 0x03fffffc )); // b <offset>
929
929
} else if (isInt<34 >(offset)) {
930
- const uint64_t paddi = PADDI_R12_NO_DISP |
931
- (((offset >> 16 ) & 0x3ffff ) << 32 ) |
932
- (offset & 0xffff );
933
- writePrefixedInstruction (buf + 4 , paddi); // paddi r12, 0, func@pcrel, 1
934
- write32 (buf + 12 , MTCTR_R12); // mtctr r12
935
- write32 (buf + 16 , BCTR); // bctr
930
+ int nextInstOffset;
931
+ if (!config->Power10Stub ) {
932
+ uint64_t tocOffset = destination.getVA () - getPPC64TocBase ();
933
+ if (tocOffset >> 16 > 0 ) {
934
+ const uint64_t addi = ADDI_R12_TO_R12_NO_DISP | (tocOffset & 0xffff );
935
+ const uint64_t addis = ADDIS_R12_TO_R2_NO_DISP | ((tocOffset >> 16 ) & 0xffff );
936
+ write32 (buf + 4 , addis); // addis r12, r2 , top of offset
937
+ write32 (buf + 8 , addi); // addi r12, r12, bottom of offset
938
+ nextInstOffset = 12 ;
939
+ } else {
940
+ const uint64_t addi = ADDI_R12_TO_R2_NO_DISP | (tocOffset & 0xffff );
941
+ write32 (buf + 4 , addi); // addi r12, r2, offset
942
+ nextInstOffset = 8 ;
943
+ }
944
+ } else {
945
+ const uint64_t paddi = PADDI_R12_NO_DISP |
946
+ (((offset >> 16 ) & 0x3ffff ) << 32 ) |
947
+ (offset & 0xffff );
948
+ writePrefixedInstruction (buf + 4 , paddi); // paddi r12, 0, func@pcrel, 1
949
+ nextInstOffset = 12 ;
950
+ }
951
+ write32 (buf + nextInstOffset, MTCTR_R12); // mtctr r12
952
+ write32 (buf + nextInstOffset + 4 , BCTR); // bctr
936
953
} else {
937
954
in.ppc64LongBranchTarget ->addEntry (&destination, addend);
938
955
const int64_t offsetFromTOC =
@@ -952,12 +969,25 @@ void PPC64R12SetupStub::writeTo(uint8_t *buf) {
952
969
int64_t offset = destination.getVA () - getThunkTargetSym ()->getVA ();
953
970
if (!isInt<34 >(offset))
954
971
reportRangeError (buf, offset, 34 , destination, " R12 setup stub offset" );
955
- uint64_t paddi = PADDI_R12_NO_DISP | (((offset >> 16 ) & 0x3ffff ) << 32 ) |
956
- (offset & 0xffff );
957
972
958
- writePrefixedInstruction (buf + 0 , paddi); // paddi r12, 0, func@pcrel, 1
959
- write32 (buf + 8 , MTCTR_R12); // mtctr r12
960
- write32 (buf + 12 , BCTR); // bctr
973
+ int nextInstOffset;
974
+ if (!config->Power10Stub ) {
975
+ uint32_t off = destination.getVA (addend) - getThunkTargetSym ()->getVA () - 8 ;
976
+ write32 (buf + 0 , 0x7c0802a6 ); // mflr r12
977
+ write32 (buf + 4 , 0x429f0005 ); // bcl 20,31,.+4
978
+ write32 (buf + 8 , 0x7d6802a6 ); // mflr r11
979
+ write32 (buf + 12 , 0x7d8803a6 ); // mtlr r12
980
+ write32 (buf + 16 , 0x3d8b0000 | computeHiBits (off));// addis r12,r11,off@ha
981
+ write32 (buf + 20 , 0x398c0000 | (off & 0xffff )); // addi r12,r12,off@l
982
+ nextInstOffset = 24 ;
983
+ } else {
984
+ uint64_t paddi = PADDI_R12_NO_DISP | (((offset >> 16 ) & 0x3ffff ) << 32 ) |
985
+ (offset & 0xffff );
986
+ writePrefixedInstruction (buf + 0 , paddi); // paddi r12, 0, func@pcrel, 1
987
+ nextInstOffset = 8 ;
988
+ }
989
+ write32 (buf + nextInstOffset, MTCTR_R12); // mtctr r12
990
+ write32 (buf + nextInstOffset + 4 , BCTR); // bctr
961
991
}
962
992
963
993
void PPC64R12SetupStub::addSymbols (ThunkSection &isec) {
@@ -966,16 +996,29 @@ void PPC64R12SetupStub::addSymbols(ThunkSection &isec) {
966
996
}
967
997
968
998
void PPC64PCRelPLTStub::writeTo (uint8_t *buf) {
999
+ int nextInstOffset = 0 ;
969
1000
int64_t offset = destination.getGotPltVA () - getThunkTargetSym ()->getVA ();
970
- if (!isInt<34 >(offset))
971
- reportRangeError (buf, offset, 34 , destination,
972
- " PC-relative PLT stub offset" );
973
- uint64_t pld =
974
- PLD_R12_NO_DISP | (((offset >> 16 ) & 0x3ffff ) << 32 ) | (offset & 0xffff );
975
1001
976
- writePrefixedInstruction (buf + 0 , pld); // pld r12, func@plt@pcrel
977
- write32 (buf + 8 , MTCTR_R12); // mtctr r12
978
- write32 (buf + 12 , BCTR); // bctr
1002
+ if (config->Power10Stub ) {
1003
+ if (!isInt<34 >(offset))
1004
+ reportRangeError (buf, offset, 34 , destination,
1005
+ " PC-relative PLT stub offset" );
1006
+ const uint64_t pld = PLD_R12_NO_DISP | (((offset >> 16 ) & 0x3ffff ) << 32 ) |
1007
+ (offset & 0xffff );
1008
+ writePrefixedInstruction (buf + 0 , pld); // pld r12, func@plt@pcrel
1009
+ nextInstOffset = 8 ;
1010
+ } else {
1011
+ uint32_t off = destination.getVA (addend) - getThunkTargetSym ()->getVA () - 8 ;
1012
+ write32 (buf + 0 , 0x7c0802a6 ); // mflr r12
1013
+ write32 (buf + 4 , 0x429f0005 ); // bcl 20,31,.+4
1014
+ write32 (buf + 8 , 0x7d6802a6 ); // mflr r11
1015
+ write32 (buf + 12 , 0x7d8803a6 ); // mtlr r12
1016
+ write32 (buf + 16 , 0x3d8b0000 | computeHiBits (off)); // addis r12,r11,off@ha
1017
+ write32 (buf + 20 , 0x398c0000 | (off & 0xffff )); // addi r12,r12,off@l
1018
+ nextInstOffset = 24 ;
1019
+ }
1020
+ write32 (buf + nextInstOffset, MTCTR_R12); // mtctr r12
1021
+ write32 (buf + nextInstOffset + 4 , BCTR); // bctr
979
1022
}
980
1023
981
1024
void PPC64PCRelPLTStub::addSymbols (ThunkSection &isec) {
@@ -1009,12 +1052,25 @@ void PPC64PCRelLongBranchThunk::writeTo(uint8_t *buf) {
1009
1052
if (!isInt<34 >(offset))
1010
1053
reportRangeError (buf, offset, 34 , destination,
1011
1054
" PC-relative long branch stub offset" );
1012
- uint64_t paddi = PADDI_R12_NO_DISP | (((offset >> 16 ) & 0x3ffff ) << 32 ) |
1013
- (offset & 0xffff );
1014
1055
1015
- writePrefixedInstruction (buf + 0 , paddi); // paddi r12, 0, func@pcrel, 1
1016
- write32 (buf + 8 , MTCTR_R12); // mtctr r12
1017
- write32 (buf + 12 , BCTR); // bctr
1056
+ int nextInstOffset;
1057
+ if (!config->Power10Stub ) {
1058
+ uint32_t off = destination.getVA (addend) - getThunkTargetSym ()->getVA () - 8 ;
1059
+ write32 (buf + 0 , 0x7c0802a6 ); // mflr r12
1060
+ write32 (buf + 4 , 0x429f0005 ); // bcl 20,31,.+4
1061
+ write32 (buf + 8 , 0x7d6802a6 ); // mflr r11
1062
+ write32 (buf + 12 , 0x7d8803a6 ); // mtlr r12
1063
+ write32 (buf + 16 , 0x3d8b0000 | computeHiBits (off)); // addis r12,r11,off@ha
1064
+ write32 (buf + 20 , 0x398c0000 | (off & 0xffff )); // addi r12,r12,off@l
1065
+ nextInstOffset = 24 ;
1066
+ } else {
1067
+ uint64_t paddi = PADDI_R12_NO_DISP | (((offset >> 16 ) & 0x3ffff ) << 32 ) |
1068
+ (offset & 0xffff );
1069
+ writePrefixedInstruction (buf + 0 , paddi); // paddi r12, 0, func@pcrel, 1
1070
+ nextInstOffset = 8 ;
1071
+ }
1072
+ write32 (buf + nextInstOffset, MTCTR_R12); // mtctr r12
1073
+ write32 (buf + nextInstOffset + 4 , BCTR); // bctr
1018
1074
}
1019
1075
1020
1076
void PPC64PCRelLongBranchThunk::addSymbols (ThunkSection &isec) {
0 commit comments