Lines Matching +full:armv4t +full:- +full:based

1 //===- Thunks.cpp --------------------------------------------------------===//
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===---------------------------------------------------------------------===//
13 // such as MIPS PIC and non-PIC or ARM non-Thumb and Thumb functions.
19 // i386 and x86-64 don't need thunks.
21 //===---------------------------------------------------------------------===//
122 // Base class for Thumb-2 thunks.
124 // This class is similar to ARMThunk, but it uses the Thumb-2 B.W instruction
188 // Implementations of Thunks for Arm v6-M. Only Thumb instructions are permitted
225 // ARMV5LongLdrPcThunk can be used for both Arm->Arm and Arm->Thumb calls. v4
226 // can also use this thunk, but only for Arm->Arm calls.
326 // microMIPS R2-R5 LA25 thunk
368 uint32_t size() override { return config->isPic ? 32 : 16; } in size()
376 // 1) Saving the toc-pointer to the stack.
426 return destination.getVA() - (getThunkTargetSym()->getVA() + 4); in computeOffset()
432 // use TOC (either non-preemptible with localentry>1 or preemptible), we need to
452 // larger than that we need to emit a long-branch thunk. The target address
453 // of the callee is stored in a table to be accessed TOC-relative. Since the
454 // call must be local (a non-local call will have a PltCallStub instead) the
456 // position-independent code a corresponding relative dynamic relocation is
476 in.ppc64LongBranchTarget->addEntry(&dest, addend)) { in PPC64PILongBranchThunk()
477 mainPart->relaDyn->addRelativeReloc( in PPC64PILongBranchThunk()
478 target->relativeRel, *in.ppc64LongBranchTarget, *index * UINT64_C(8), in PPC64PILongBranchThunk()
480 target->symbolicRel, R_ABS); in PPC64PILongBranchThunk()
489 in.ppc64LongBranchTarget->addEntry(&dest, addend); in PPC64PDLongBranchThunk()
504 d->value = d->value - offset + newOffset; in setOffset()
518 uint64_t p = getThunkTargetSym()->getVA(); in getMayUseShortThunk()
519 mayUseShortThunk = llvm::isInt<28>(s - p); in getMayUseShortThunk()
529 uint64_t p = getThunkTargetSym()->getVA(); in writeTo()
531 target->relocateNoSym(buf, R_AARCH64_CALL26, s - p); in writeTo()
544 target->relocateNoSym(buf + 8, R_AARCH64_ABS64, s); in writeLong()
556 // using the small code model, including pc-relative ones. At time of writing
567 uint64_t p = getThunkTargetSym()->getVA(); in writeLong()
569 target->relocateNoSym(buf, R_AARCH64_ADR_PREL_PG_HI21, in writeLong()
570 getAArch64Page(s) - getAArch64Page(p)); in writeLong()
571 target->relocateNoSym(buf + 4, R_AARCH64_ADD_ABS_LO12_NC, s); in writeLong()
596 uint64_t p = getThunkTargetSym()->getVA(); in getMayUseShortThunk()
597 int64_t offset = s - p - 8; in getMayUseShortThunk()
609 uint64_t p = getThunkTargetSym()->getVA(); in writeTo()
610 int64_t offset = s - p - 8; in writeTo()
612 target->relocateNoSym(buf, R_ARM_JUMP24, offset); in writeTo()
618 if (!config->armHasBlx && rel.type == R_ARM_THM_CALL) in isCompatibleWith()
632 if (!mayUseShortThunk || !config->armJ1J2BranchEncoding) in getMayUseShortThunk()
639 uint64_t p = getThunkTargetSym()->getVA() & ~1; in getMayUseShortThunk()
640 int64_t offset = s - p - 4; in getMayUseShortThunk()
652 uint64_t p = getThunkTargetSym()->getVA(); in writeTo()
653 int64_t offset = s - p - 4; in writeTo()
656 target->relocateNoSym(buf, R_ARM_THM_JUMP24, offset); in writeTo()
662 if (!config->armHasBlx && rel.type == R_ARM_CALL) in isCompatibleWith()
674 target->relocateNoSym(buf, R_ARM_MOVW_ABS_NC, s); in writeLong()
675 target->relocateNoSym(buf + 4, R_ARM_MOVT_ABS, s); in writeLong()
691 target->relocateNoSym(buf, R_ARM_THM_MOVW_ABS_NC, s); in writeLong()
692 target->relocateNoSym(buf + 4, R_ARM_THM_MOVT_ABS, s); in writeLong()
702 write32(buf + 0, 0xe30fcff0); // P: movw ip,:lower16:S - (P + (L1-P) + 8) in writeLong()
703 write32(buf + 4, 0xe340c000); // movt ip,:upper16:S - (P + (L1-P) + 8) in writeLong()
707 uint64_t p = getThunkTargetSym()->getVA(); in writeLong()
708 int64_t offset = s - p - 16; in writeLong()
709 target->relocateNoSym(buf, R_ARM_MOVW_PREL_NC, offset); in writeLong()
710 target->relocateNoSym(buf + 4, R_ARM_MOVT_PREL, offset); in writeLong()
720 write16(buf + 0, 0xf64f); // P: movw ip,:lower16:S - (P + (L1-P) + 4) in writeLong()
722 write16(buf + 4, 0xf2c0); // movt ip,:upper16:S - (P + (L1-P) + 4) in writeLong()
727 uint64_t p = getThunkTargetSym()->getVA() & ~0x1; in writeLong()
728 int64_t offset = s - p - 12; in writeLong()
729 target->relocateNoSym(buf, R_ARM_THM_MOVW_PREL_NC, offset); in writeLong()
730 target->relocateNoSym(buf + 4, R_ARM_THM_MOVT_PREL, offset); in writeLong()
740 // Most Thumb instructions cannot access the high registers r8 - r15. As the in writeLong()
750 target->relocateNoSym(buf + 8, R_ARM_ABS32, s); in writeLong()
762 // Most Thumb instructions cannot access the high registers r8 - r15. As the in writeLong()
777 target->relocateNoSym(buf + 2, R_ARM_THM_ALU_ABS_G3, s); in writeLong()
778 target->relocateNoSym(buf + 6, R_ARM_THM_ALU_ABS_G2_NC, s); in writeLong()
779 target->relocateNoSym(buf + 10, R_ARM_THM_ALU_ABS_G1_NC, s); in writeLong()
780 target->relocateNoSym(buf + 14, R_ARM_THM_ALU_ABS_G0_NC, s); in writeLong()
790 // Most Thumb instructions cannot access the high registers r8 - r15. As the in writeLong()
798 write16(buf + 10, 0x46c0); // nop ; pad to 4-byte boundary in writeLong()
799 write32(buf + 12, 0x00000000); // L2: .word S - (P + (L1 - P) + 4) in writeLong()
801 uint64_t p = getThunkTargetSym()->getVA() & ~0x1; in writeLong()
802 target->relocateNoSym(buf + 12, R_ARM_REL32, s - p - 12); in writeLong()
814 write32(buf + 0, 0xe51ff004); // ldr pc, [pc,#-4] ; L1 in writeLong()
816 target->relocateNoSym(buf + 4, R_ARM_ABS32, getARMThunkDestVA(destination)); in writeLong()
831 target->relocateNoSym(buf + 8, R_ARM_ABS32, getARMThunkDestVA(destination)); in writeLong()
844 write16(buf + 2, 0xe7fd); // b #-6 ; Arm recommended sequence to follow bx pc in writeLong()
845 write32(buf + 4, 0xe51ff004); // ldr pc, [pc, #-4] ; L1 in writeLong()
847 target->relocateNoSym(buf + 8, R_ARM_ABS32, getARMThunkDestVA(destination)); in writeLong()
861 write16(buf + 2, 0xe7fd); // b #-6 ; Arm recommended sequence to follow bx pc in writeLong()
865 target->relocateNoSym(buf + 12, R_ARM_ABS32, getARMThunkDestVA(destination)); in writeLong()
881 write32(buf + 12, 0x00000000); // L2: .word S - (P + (L1 - P) + 8) in writeLong()
883 uint64_t p = getThunkTargetSym()->getVA() & ~0x1; in writeLong()
884 target->relocateNoSym(buf + 12, R_ARM_REL32, s - p - 12); in writeLong()
898 write32(buf + 8, 0x00000000); // L2: .word S - (P + (L1 - P) + 8) in writeLong()
900 uint64_t p = getThunkTargetSym()->getVA() & ~0x1; in writeLong()
901 target->relocateNoSym(buf + 8, R_ARM_REL32, s - p - 12); in writeLong()
914 write16(buf + 2, 0xe7fd); // b #-6 ; Arm recommended sequence to follow bx pc in writeLong()
917 write32(buf + 12, 0x00000000); // L2: .word S - (P + (L1 - P) + 8) in writeLong()
919 uint64_t p = getThunkTargetSym()->getVA() & ~0x1; in writeLong()
920 target->relocateNoSym(buf + 12, R_ARM_REL32, s - p - 16); in writeLong()
934 write16(buf + 2, 0xe7fd); // b #-6 ; Arm recommended sequence to follow bx pc in writeLong()
938 write32(buf + 16, 0x00000000); // L2: .word S - (P + (L1 - P) + 8) in writeLong()
940 uint64_t p = getThunkTargetSym()->getVA() & ~0x1; in writeLong()
941 target->relocateNoSym(buf + 16, R_ARM_REL32, s - p - 16); in writeLong()
956 target->relocateNoSym(buf, R_AVR_CALL, destination.getVA()); in writeTo()
964 // Write MIPS LA25 thunk code to call PIC function from the non-PIC one.
971 target->relocateNoSym(buf, R_MIPS_HI16, s); in writeTo()
972 target->relocateNoSym(buf + 8, R_MIPS_LO16, s); in writeTo()
985 // Write microMIPS R2-R5 LA25 thunk code
986 // to call PIC function from the non-PIC one.
993 target->relocateNoSym(buf, R_MICROMIPS_HI16, s); in writeTo()
994 target->relocateNoSym(buf + 4, R_MICROMIPS_26_S1, s); in writeTo()
995 target->relocateNoSym(buf + 8, R_MICROMIPS_LO16, s); in writeTo()
1002 d->stOther |= STO_MIPS_MICROMIPS; in addSymbols()
1011 // to call PIC function from the non-PIC one.
1014 uint64_t p = getThunkTargetSym()->getVA(); in writeTo()
1018 target->relocateNoSym(buf, R_MICROMIPS_HI16, s); in writeTo()
1019 target->relocateNoSym(buf + 4, R_MICROMIPS_LO16, s); in writeTo()
1020 target->relocateNoSym(buf + 8, R_MICROMIPS_PC26_S1, s - p - 12); in writeTo()
1027 d->stOther |= STO_MIPS_MICROMIPS; in addSymbols()
1037 if (!config->isPic) { in writePPC32PltCallStub()
1049 offset = gotPltVA - in writePPC32PltCallStub()
1050 (in.ppc32Got2->getParent()->getVA() + in writePPC32PltCallStub()
1051 (file->ppc32Got2 ? file->ppc32Got2->outSecOff : 0) + addend); in writePPC32PltCallStub()
1055 offset = gotPltVA - in.got->getVA(); in writePPC32PltCallStub()
1079 if (!config->isPic) in addSymbols()
1091 return !config->isPic || (isec.file == file && rel.addend == addend); in isCompatibleWith()
1100 auto ha = [](uint32_t v) -> uint16_t { return (v + 0x8000) >> 16; }; in writeTo()
1101 auto lo = [](uint32_t v) -> uint16_t { return v; }; in writeTo()
1103 if (config->isPic) { in writeTo()
1104 uint32_t off = d - (getThunkTargetSym()->getVA() + 8); in writeTo()
1132 int64_t offset = destination.getGotPltVA() - getPPC64TocBase(); in writeTo()
1133 // Save the TOC pointer to the save-slot reserved in the call frame. in writeTo()
1141 s->setNeedsTocRestore(true); in addSymbols()
1142 s->file = destination.file; in addSymbols()
1158 uint64_t tocOffset = destination.getVA() - getPPC64TocBase(); in writeTo()
1174 in.ppc64LongBranchTarget->addEntry(&destination, addend); in writeTo()
1176 in.ppc64LongBranchTarget->getEntryVA(&destination, addend) - in writeTo()
1185 s->setNeedsTocRestore(true); in addSymbols()
1194 int64_t offset = (gotPlt ? destination.getGotPltVA() : destination.getVA()) - in writeTo()
1195 getThunkTargetSym()->getVA(); in writeTo()
1200 if (config->power10Stubs) { in writeTo()
1207 uint32_t off = offset - 8; in writeTo()
1236 int64_t offset = in.ppc64LongBranchTarget->getEntryVA(&destination, addend) - in writeTo()
1261 if (config->picThunk) in addThunkAArch64()
1266 // Creates a thunk for long branches or Thumb-ARM interworking.
1269 // - MOVT and MOVW instructions cannot be used.
1270 // - We can't rewrite BL in place to BLX. We will need thunks.
1272 // TODO: use B for short Thumb->Arm thunks instead of LDR (this doesn't work for
1273 // Arm->Thumb, as in Arm state no BX PC trick; it doesn't switch state).
1282 if (config->picThunk) { in addThunkArmv4()
1291 if (config->picThunk) { in addThunkArmv4()
1301 " not supported for Armv4 or Armv4T target"); in addThunkArmv4()
1304 // Creates a thunk for Thumb-ARM interworking compatible with Armv5 and Armv6.
1306 // - MOVT and MOVW instructions cannot be used
1307 // - Only Thumb relocation that can generate a Thunk is a BL, this can always
1316 if (config->picThunk) in addThunkArmv5v6()
1324 // Create a thunk for Thumb long branch on V6-M.
1325 // Arm Architecture v6-M only supports Thumb instructions. This means
1326 // - MOVT and MOVW instructions cannot be used.
1327 // - Only a limited number of instructions can access registers r8 and above
1328 // - No interworking support is needed (all Thumb).
1331 const bool isPureCode = isec.getParent()->flags & SHF_ARM_PURECODE; in addThunkV6M()
1336 if (config->isPic) { in addThunkV6M()
1341 " not supported for Armv6-M targets for position independent" in addThunkV6M()
1349 " not supported for Armv6-M targets"); in addThunkV6M()
1352 // Creates a thunk for Thumb-ARM interworking or branch range extension.
1355 // Decide which Thunk is needed based on: in addThunkArm()
1357 // - An Arm Thunk can only be used if Arm state is available. in addThunkArm()
1358 // - A Thumb Thunk can only be used if Thumb state is available. in addThunkArm()
1359 // - Can only use a Thunk if it uses instructions that the Target supports. in addThunkArm()
1361 // - Branch instructions cannot change state, can only select Thunk that in addThunkArm()
1363 // - Branch and link relocations can change state, can select Thunks from in addThunkArm()
1372 if (!config->armHasMovtMovw) { in addThunkArm()
1373 if (config->armJ1J2BranchEncoding) in addThunkArm()
1375 if (config->armHasBlx) in addThunkArm()
1385 if (config->picThunk) in addThunkArm()
1391 if (config->picThunk) in addThunkArm()
1434 getPPC64TargetInfo()->ppc64DynamicSectionOpt = 0x2; in addThunkPPC64()
1450 if (config->picThunk) in addThunkPPC64()
1460 switch (config->emachine) { in addThunk()