@@ -351,6 +351,47 @@ class AVRThunk : public Thunk {
351351 void addSymbols (ThunkSection &isec) override ;
352352};
353353
354+ static const uint32_t MASK_END_PACKET = 3 << 14 ;
355+ static const uint32_t END_OF_PACKET = 3 << 14 ;
356+ static const uint32_t END_OF_DUPLEX = 0 << 14 ;
357+
358+ static std::optional<int32_t > getRealAddend (const InputSection &isec,
359+ const Relocation &rel) {
360+ const ArrayRef<uint8_t > SectContents = isec.content ();
361+ if (SectContents.size () < sizeof (int32_t ))
362+ // FIXME: assert? emit a diagnostic?
363+ return std::nullopt ;
364+ int32_t offset = rel.offset ;
365+
366+ // Search as many as 4 instructions:
367+ for (int i = 0 ; i < 4 ; i++) {
368+ uint32_t instWord = 0 ;
369+ const ArrayRef<uint8_t > InstWordContents = SectContents.drop_front (offset);
370+ ::memcpy (&instWord, InstWordContents.data(), sizeof(instWord));
371+ if (((instWord & MASK_END_PACKET) == END_OF_PACKET) ||
372+ ((instWord & MASK_END_PACKET) == END_OF_DUPLEX))
373+ break ;
374+ offset += sizeof (instWord);
375+ }
376+ return offset - rel.offset ;
377+ }
378+ // Hexagon CPUs need thunks for <<FIXME TBD>>
379+ // when their destination is out of range [0, 0x_?].
380+ class HexagonThunk : public Thunk {
381+ public:
382+ HexagonThunk (Ctx &ctx, const InputSection &isec, Relocation &rel,
383+ Symbol &dest)
384+ : Thunk(ctx, dest, 0 ), RealAddend(getRealAddend(isec, rel)),
385+ RelOffset (rel.offset) {
386+ alignment = 4 ;
387+ }
388+ std::optional<int32_t > RealAddend;
389+ int32_t RelOffset;
390+ uint32_t size () override { return ctx.arg .isPic ? 12 : 8 ; }
391+ void writeTo (uint8_t *buf) override ;
392+ void addSymbols (ThunkSection &isec) override ;
393+ };
394+
354395// MIPS LA25 thunk
355396class MipsThunk final : public Thunk {
356397public:
@@ -1352,6 +1393,39 @@ bool PPC64LongBranchThunk::isCompatibleWith(const InputSection &isec,
13521393 return rel.type == R_PPC64_REL24 || rel.type == R_PPC64_REL14;
13531394}
13541395
1396+ // Hexagon Target Thunks
1397+ static uint64_t getHexagonThunkDestVA (const Symbol &s, int64_t a) {
1398+ uint64_t v = s.isInPlt () ? s.getPltVA () : s.getVA (a);
1399+ return SignExtend64<32 >(v); // FIXME: sign extend to 64-bit?
1400+ }
1401+
1402+ void HexagonThunk::writeTo (uint8_t *buf) {
1403+ uint64_t s = getHexagonThunkDestVA (destination, addend);
1404+ uint64_t p = getThunkTargetSym ()->getVA ();
1405+
1406+ if (ctx.arg .isPic ) {
1407+ write32 (buf + 0 , 0x00004000 ); // { immext(#0)
1408+ ctx.target ->relocateNoSym (buf, R_HEX_B32_PCREL_X, s - p);
1409+ write32 (buf + 4 , 0x6a49c00e ); // r14 = add(pc,##0) }
1410+ ctx.target ->relocateNoSym (buf + 4 , R_HEX_6_PCREL_X, s - p);
1411+
1412+ write32 (buf + 8 , 0x528ec000 ); // { jumpr r14 }
1413+ } else {
1414+ write32 (buf + 0 , 0x00004000 ); // { immext
1415+ ctx.target ->relocateNoSym (buf, R_HEX_B32_PCREL_X, s - p);
1416+ write32 (buf + 4 , 0x5800c000 ); // jump <> }
1417+ ctx.target ->relocateNoSym (buf + 4 , R_HEX_B22_PCREL_X, s - p);
1418+ }
1419+ }
1420+ void HexagonThunk::addSymbols (ThunkSection &isec) {
1421+ Symbol *enclosing = isec.getEnclosingSymbol (RelOffset);
1422+ StringRef src = enclosing ? enclosing->getName () : isec.name ;
1423+
1424+ addSymbol (saver ().save (" __trampoline_for_" + destination.getName () +
1425+ " _from_" + src),
1426+ STT_FUNC, 0 , isec);
1427+ }
1428+
13551429Thunk::Thunk (Ctx &ctx, Symbol &d, int64_t a)
13561430 : ctx(ctx), destination(d), addend(a), offset(0 ) {
13571431 destination.thunkAccessed = true ;
@@ -1513,6 +1587,27 @@ static Thunk *addThunkAVR(Ctx &ctx, RelType type, Symbol &s, int64_t a) {
15131587 }
15141588}
15151589
1590+ static Thunk *addThunkHexagon (Ctx &ctx, const InputSection &isec,
1591+ Relocation &rel, Symbol &s) {
1592+ switch (rel.type ) {
1593+ case R_HEX_B9_PCREL:
1594+ case R_HEX_B13_PCREL:
1595+ case R_HEX_B15_PCREL:
1596+ case R_HEX_B22_PCREL:
1597+ case R_HEX_PLT_B22_PCREL:
1598+ case R_HEX_GD_PLT_B22_PCREL:
1599+ #if 0
1600+ // FIXME: we don't need this for extended rels?
1601+ case R_HEX_B32_PCREL_X:
1602+ case R_HEX_6_PCREL_X:
1603+ case R_HEX_B22_PCREL_X:
1604+ #endif
1605+ return make<HexagonThunk>(ctx, isec, rel, s);
1606+ default :
1607+ fatal (" unrecognized relocation type " + toString (rel.type ));
1608+ }
1609+ }
1610+
15161611static Thunk *addThunkMips (Ctx &ctx, RelType type, Symbol &s) {
15171612 if ((s.stOther & STO_MIPS_MICROMIPS) && isMipsR6 ())
15181613 return make<MicroMipsR6Thunk>(ctx, s);
@@ -1578,8 +1673,11 @@ Thunk *elf::addThunk(Ctx &ctx, const InputSection &isec, Relocation &rel) {
15781673 return addThunkPPC32 (ctx, isec, rel, s);
15791674 case EM_PPC64:
15801675 return addThunkPPC64 (ctx, rel.type , s, a);
1676+ case EM_HEXAGON:
1677+ return addThunkHexagon (ctx, isec, rel, s);
15811678 default :
1582- llvm_unreachable (" add Thunk only supported for ARM, AVR, Mips and PowerPC" );
1679+ llvm_unreachable (
1680+ " add Thunk only supported for ARM, AVR, Hexagon, Mips and PowerPC" );
15831681 }
15841682}
15851683
0 commit comments