Lines Matching +full:10 +full:g +full:- +full:support
1 //===--------- aarch32.cpp - Generic JITLink arm/thumb utilities ----------===//
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
11 //===----------------------------------------------------------------------===//
20 #include "llvm/Support/Endian.h"
21 #include "llvm/Support/ManagedStatic.h"
22 #include "llvm/Support/MathExtras.h"
35 /// Encode 22-bit immediate value for branch instructions without J1J2 range
38 /// 00000:Imm11H:Imm11L:0 -> [ 00000:Imm11H, 00000:Imm11L ]
48 /// Decode 22-bit immediate value for branch instructions without J1J2 range
51 /// [ 00000:Imm11H, 00000:Imm11L ] -> 00000:Imm11H:Imm11L:0
60 /// Encode 25-bit immediate value for branch instructions with J1J2 range
63 /// S:I1:I2:Imm10:Imm11:0 -> [ 00000:S:Imm10, 00:J1:0:J2:Imm11 ]
67 uint32_t J1 = (((~(Value >> 10)) ^ (Value >> 11)) & 0x2000);
74 /// Decode 25-bit immediate value for branch instructions with J1J2 range
77 /// [ 00000:S:Imm10, 00:J1:0:J2:Imm11] -> S:I1:I2:Imm10:Imm11:0
81 uint32_t I1 = ~((Lo ^ (Hi << 3)) << 10) & 0x00800000;
88 /// Encode 26-bit immediate value for branch instructions
91 /// Imm24:00 -> 00000000:Imm24
97 /// Decode 26-bit immediate value for branch instructions
100 /// 00000000:Imm24 -> Imm24:00
106 /// Encode 16-bit immediate value for move instruction formats MOVT T1 and
109 /// Imm4:Imm1:Imm3:Imm8 -> [ 00000:i:000000:Imm4, 0:Imm3:0000:Imm8 ]
116 return HalfWords{Imm1 << 10 | Imm4, Imm3 << 12 | Imm8};
119 /// Decode 16-bit immediate value from move instruction formats MOVT T1 and
122 /// [ 00000:i:000000:Imm4, 0:Imm3:0000:Imm8 ] -> Imm4:Imm1:Imm3:Imm8
126 uint32_t Imm1 = (Hi >> 10) & 0x01;
130 assert(Imm16 <= 0xffff && "Decoded value out-of-range");
136 /// Rd4 -> [0000000000000000, 0000:Rd4:00000000]
145 /// [0000000000000000, 0000:Rd4:00000000] -> Rd4
152 /// Encode 16-bit immediate value for move instruction formats MOVT A1 and
155 /// Imm4:Imm12 -> 000000000000:Imm4:0000:Imm12
163 /// Decode 16-bit immediate value for move instruction formats MOVT A1 and
166 /// 000000000000:Imm4:0000:Imm12 -> Imm4:Imm12
177 /// Rd4 -> 0000000000000000:Rd4:000000000000
187 /// 0000000000000000:Rd4:000000000000 -> Rd4
196 /// 32-bit Thumb instructions are stored as two little-endian halfwords.
202 : Hi{*reinterpret_cast<support::ulittle16_t *>(FixupPtr)},
203 Lo{*reinterpret_cast<support::ulittle16_t *>(FixupPtr + 2)} {}
205 support::ulittle16_t &Hi; // First halfword
206 support::ulittle16_t &Lo; // Second halfword
210 /// Create a read-only reference to a Thumb32 fixup.
212 : Hi{*reinterpret_cast<const support::ulittle16_t *>(FixupPtr)},
213 Lo{*reinterpret_cast<const support::ulittle16_t *>(FixupPtr + 2)} {}
215 /// Create a read-only Thumb32 fixup from a writeable one.
219 const support::ulittle16_t &Hi; // First halfword
220 const support::ulittle16_t &Lo; // Second halfword
225 : Wd{*reinterpret_cast<support::ulittle32_t *>(FixupPtr)} {}
227 support::ulittle32_t &Wd;
232 : Wd{*reinterpret_cast<const support::ulittle32_t *>(FixupPtr)} {}
236 const support::ulittle32_t &Wd;
239 Error makeUnexpectedOpcodeError(const LinkGraph &G, const ThumbRelocation &R,
244 G.getEdgeKindName(Kind)));
247 Error makeUnexpectedOpcodeError(const LinkGraph &G, const ArmRelocation &R,
251 static_cast<uint32_t>(R.Wd), G.getEdgeKindName(Kind)));
301 Entry->checkOpcode = checkOpcodeArm<K>;
303 Entry->checkOpcode = checkOpcodeThumb<K>;
315 static Error checkOpcode(LinkGraph &G, const ArmRelocation &R,
319 const FixupInfoBase *Entry = DynFixupInfos->getEntry(Kind);
323 return makeUnexpectedOpcodeError(G, R, Kind);
328 static Error checkOpcode(LinkGraph &G, const ThumbRelocation &R,
332 const FixupInfoBase *Entry = DynFixupInfos->getEntry(Kind);
336 return makeUnexpectedOpcodeError(G, R, Kind);
342 return DynFixupInfos->getEntry(K);
390 Expected<int64_t> readAddendData(LinkGraph &G, Block &B, Edge::OffsetT Offset,
392 endianness Endian = G.getEndianness();
400 return SignExtend64<32>(support::endian::read32(FixupPtr, Endian));
402 return SignExtend64<31>(support::endian::read32(FixupPtr, Endian));
405 "In graph " + G.getName() + ", section " + B.getSection().getName() +
407 G.getEdgeKindName(Kind));
411 Expected<int64_t> readAddendArm(LinkGraph &G, Block &B, Edge::OffsetT Offset,
414 if (Error Err = checkOpcode(G, R, Kind))
428 "In graph " + G.getName() + ", section " + B.getSection().getName() +
430 G.getEdgeKindName(Kind));
434 Expected<int64_t> readAddendThumb(LinkGraph &G, Block &B, Edge::OffsetT Offset,
437 if (Error Err = checkOpcode(G, R, Kind))
459 "In graph " + G.getName() + ", section " + B.getSection().getName() +
461 G.getEdgeKindName(Kind));
465 Error applyFixupData(LinkGraph &G, Block &B, const Edge &E) {
466 using namespace support;
478 // R_ARM_ABS16) and write the full 32-bit result (except R_ARM_PREL31).
481 int64_t Value = TargetAddress - FixupAddress + Addend;
483 return makeTargetOutOfRangeError(G, B, E);
484 if (LLVM_LIKELY(G.getEndianness() == endianness::little))
493 return makeTargetOutOfRangeError(G, B, E);
494 if (LLVM_LIKELY(G.getEndianness() == endianness::little))
501 int64_t Value = TargetAddress - FixupAddress + Addend;
503 return makeTargetOutOfRangeError(G, B, E);
504 if (LLVM_LIKELY(G.getEndianness() == endianness::little)) {
517 "In graph " + G.getName() + ", section " + B.getSection().getName() +
519 G.getEdgeKindName(E.getKind()));
523 Error applyFixupArm(LinkGraph &G, Block &B, const Edge &E) {
526 if (Error Err = checkOpcode(G, R, Kind))
539 StringRef(G.getEdgeKindName(Kind)));
541 int64_t Value = TargetAddress - FixupAddress + Addend;
544 return makeTargetOutOfRangeError(G, B, E);
554 StringRef(G.getEdgeKindName(Kind)));
556 int64_t Value = TargetAddress - FixupAddress + Addend;
564 // Change opcode BL -> BLX
568 // Change opcode BLX -> BL
574 return makeTargetOutOfRangeError(G, B, E);
591 "In graph " + G.getName() + ", section " + B.getSection().getName() +
593 G.getEdgeKindName(E.getKind()));
597 Error applyFixupThumb(LinkGraph &G, Block &B, const Edge &E,
602 if (Error Err = checkOpcode(G, R, Kind))
615 StringRef(G.getEdgeKindName(Kind)));
617 int64_t Value = TargetAddress - FixupAddress + Addend;
620 return makeTargetOutOfRangeError(G, B, E);
624 return makeTargetOutOfRangeError(G, B, E);
632 int64_t Value = TargetAddress - FixupAddress + Addend;
640 // Change opcode BL -> BLX and fix range value: account for 4-byte
641 // aligned destination while instruction may only be 2-byte aligned
646 // Change opcode BLX -> BL
653 return makeTargetOutOfRangeError(G, B, E);
657 return makeTargetOutOfRangeError(G, B, E);
678 uint16_t Value = ((TargetAddress + Addend - FixupAddress) & 0xffff);
683 uint16_t Value = (((TargetAddress + Addend - FixupAddress) >> 16) & 0xffff);
690 "In graph " + G.getName() + ", section " + B.getSection().getName() +
692 G.getEdgeKindName(E.getKind()));
703 /// Create a new node in the link-graph for the given pointer value.
705 static Block &allocPointer(LinkGraph &G, Section &S,
707 static_assert(Size == 4, "Pointers are 32-bit");
710 return G.createContentBlock(S, Init, orc::ExecutorAddr(), Alignment, 0);
713 Symbol &GOTBuilder::createEntry(LinkGraph &G, Symbol &Target) {
715 GOTSection = &G.createSection(getSectionName(), orc::MemProt::Read);
716 Block &B = allocPointer(G, *GOTSection, GOTEntryInit);
719 return G.addAnonymousSymbol(B, 0, B.getSize(), false, false);
722 bool GOTBuilder::visitEdge(LinkGraph &G, Block *B, Edge &E) {
732 LLVM_DEBUG(dbgs() << " Transforming " << G.getEdgeKindName(E.getKind())
733 << " edge at " << B->getFixupAddress(E) << " ("
734 << B->getAddress() << " + "
736 << G.getEdgeKindName(KindToSet) << "\n");
738 E.setTarget(getEntryForTarget(G, E.getTarget()));
744 0xfd, 0xe7, // b #-6 ; Arm recommended sequence to follow bx pc
745 0x04, 0xf0, 0x1f, 0xe5, // ldr pc, [pc,#-4] ; L1
750 0x00, 0xc0, 0x00, 0xe3, // movw r12, #0x0000 ; lower 16-bit
751 0x00, 0xc0, 0x40, 0xe3, // movt r12, #0x0000 ; upper 16-bit
756 0x40, 0xf2, 0x00, 0x0c, // movw r12, #0x0000 ; lower 16-bit
757 0xc0, 0xf2, 0x00, 0x0c, // movt r12, #0x0000 ; upper 16-bit
761 /// Create a new node in the link-graph for the given stub template.
763 static Block &allocStub(LinkGraph &G, Section &S, const uint8_t (&Code)[Size]) {
766 return G.createContentBlock(S, Template, orc::ExecutorAddr(), Alignment, 0);
769 static Block &createStubPrev7(LinkGraph &G, Section &S, Symbol &Target) {
770 Block &B = allocStub(G, S, ArmThumbv5LdrPc);
775 static Block &createStubThumbv7(LinkGraph &G, Section &S, Symbol &Target) {
776 Block &B = allocStub(G, S, Thumbv7ABS);
788 static Block &createStubArmv7(LinkGraph &G, Section &S, Symbol &Target) {
789 Block &B = allocStub(G, S, Armv7ABS);
835 Symbol *StubsManager_prev7::getOrCreateSlotEntrypoint(LinkGraph &G,
842 &G.addAnonymousSymbol(*Slot.B, ThumbEntrypointOffset, 4, true, false);
843 Slot.ThumbEntry->setTargetFlags(ThumbSymbol);
847 &G.addAnonymousSymbol(*Slot.B, ArmEntrypointOffset, 8, true, false);
851 bool StubsManager_prev7::visitEdge(LinkGraph &G, Block *B, Edge &E) {
861 StubsSection = &G.createSection(getSectionName(),
865 << StubsSection->getName() << "\n";
867 Slot->B = &createStubPrev7(G, *StubsSection, Target);
874 Symbol *StubEntrypoint = getOrCreateSlotEntrypoint(G, *Slot, UseThumb);
879 << StubEntrypoint->getBlock().getSection().getName() << "\n";
886 bool StubsManager_v7::visitEdge(LinkGraph &G, Block *B, Edge &E) {
894 << " stub for " << G.getEdgeKindName(E.getKind())
895 << " edge at " << B->getFixupAddress(E) << " ("
896 << B->getAddress() << " + "
905 StubsSection = &G.createSection(getSectionName(),
907 Block &B = MakeThumb ? createStubThumbv7(G, *StubsSection, Target)
908 : createStubArmv7(G, *StubsSection, Target);
909 StubSymbol = &G.addAnonymousSymbol(B, 0, B.getSize(), true, false);
911 StubSymbol->setTargetFlags(ThumbSymbol);
915 << Target.getName() << " in " << StubsSection->getName() << ": "
920 assert(MakeThumb == (StubSymbol->getTargetFlags() & ThumbSymbol) &&
925 << StubSymbol->getBlock().getSection().getName() << "\n";