/src/keystone/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp
Line | Count | Source |
1 | | //===-- ARMAsmBackend.cpp - ARM Assembler Backend -------------------------===// |
2 | | // |
3 | | // The LLVM Compiler Infrastructure |
4 | | // |
5 | | // This file is distributed under the University of Illinois Open Source |
6 | | // License. See LICENSE.TXT for details. |
7 | | // |
8 | | //===----------------------------------------------------------------------===// |
9 | | |
10 | | #include "MCTargetDesc/ARMMCTargetDesc.h" |
11 | | #include "MCTargetDesc/ARMAddressingModes.h" |
12 | | #include "MCTargetDesc/ARMAsmBackend.h" |
13 | | #include "MCTargetDesc/ARMAsmBackendELF.h" |
14 | | #include "MCTargetDesc/ARMBaseInfo.h" |
15 | | #include "MCTargetDesc/ARMFixupKinds.h" |
16 | | #include "llvm/ADT/StringSwitch.h" |
17 | | #include "llvm/MC/MCAsmBackend.h" |
18 | | #include "llvm/MC/MCAssembler.h" |
19 | | #include "llvm/MC/MCContext.h" |
20 | | #include "llvm/MC/MCDirectives.h" |
21 | | #include "llvm/MC/MCELFObjectWriter.h" |
22 | | #include "llvm/MC/MCExpr.h" |
23 | | #include "llvm/MC/MCFixupKindInfo.h" |
24 | | #include "llvm/MC/MCObjectWriter.h" |
25 | | #include "llvm/MC/MCRegisterInfo.h" |
26 | | #include "llvm/MC/MCSectionELF.h" |
27 | | #include "llvm/MC/MCSectionMachO.h" |
28 | | #include "llvm/MC/MCSubtargetInfo.h" |
29 | | #include "llvm/MC/MCValue.h" |
30 | | #include "llvm/Support/Debug.h" |
31 | | #include "llvm/Support/ELF.h" |
32 | | #include "llvm/Support/ErrorHandling.h" |
33 | | #include "llvm/Support/Format.h" |
34 | | #include "llvm/Support/MachO.h" |
35 | | #include "llvm/Support/TargetParser.h" |
36 | | #include "llvm/Support/raw_ostream.h" |
37 | | |
38 | | #include <keystone/keystone.h> |
39 | | |
40 | | using namespace llvm_ks; |
41 | | |
42 | | namespace { |
43 | | class ARMELFObjectWriter : public MCELFObjectTargetWriter { |
44 | | public: |
45 | | ARMELFObjectWriter(uint8_t OSABI) |
46 | | : MCELFObjectTargetWriter(/*Is64Bit*/ false, OSABI, ELF::EM_ARM, |
47 | 0 | /*HasRelocationAddend*/ false) {} |
48 | | }; |
49 | | } // end anonymous namespace |
50 | | |
51 | 349k | const MCFixupKindInfo &ARMAsmBackend::getFixupKindInfo(MCFixupKind Kind) const { |
52 | 349k | const static MCFixupKindInfo InfosLE[ARM::NumTargetFixupKinds] = { |
53 | | // This table *must* be in the order that the fixup_* kinds are defined in |
54 | | // ARMFixupKinds.h. |
55 | | // |
56 | | // Name Offset (bits) Size (bits) Flags |
57 | 349k | {"fixup_arm_ldst_pcrel_12", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, |
58 | 349k | {"fixup_t2_ldst_pcrel_12", 0, 32, |
59 | 349k | MCFixupKindInfo::FKF_IsPCRel | |
60 | 349k | MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, |
61 | 349k | {"fixup_arm_pcrel_10_unscaled", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, |
62 | 349k | {"fixup_arm_pcrel_10", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, |
63 | 349k | {"fixup_t2_pcrel_10", 0, 32, |
64 | 349k | MCFixupKindInfo::FKF_IsPCRel | |
65 | 349k | MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, |
66 | 349k | {"fixup_arm_pcrel_9", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, |
67 | 349k | {"fixup_t2_pcrel_9", 0, 32, |
68 | 349k | MCFixupKindInfo::FKF_IsPCRel | |
69 | 349k | MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, |
70 | 349k | {"fixup_thumb_adr_pcrel_10", 0, 8, |
71 | 349k | MCFixupKindInfo::FKF_IsPCRel | |
72 | 349k | MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, |
73 | 349k | {"fixup_arm_adr_pcrel_12", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, |
74 | 349k | {"fixup_t2_adr_pcrel_12", 0, 32, |
75 | 349k | MCFixupKindInfo::FKF_IsPCRel | |
76 | 349k | MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, |
77 | 349k | {"fixup_arm_condbranch", 0, 24, MCFixupKindInfo::FKF_IsPCRel}, |
78 | 349k | {"fixup_arm_uncondbranch", 0, 24, MCFixupKindInfo::FKF_IsPCRel}, |
79 | 349k | {"fixup_t2_condbranch", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, |
80 | 349k | {"fixup_t2_uncondbranch", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, |
81 | 349k | {"fixup_arm_thumb_br", 0, 16, MCFixupKindInfo::FKF_IsPCRel}, |
82 | 349k | {"fixup_arm_uncondbl", 0, 24, MCFixupKindInfo::FKF_IsPCRel}, |
83 | 349k | {"fixup_arm_condbl", 0, 24, MCFixupKindInfo::FKF_IsPCRel}, |
84 | 349k | {"fixup_arm_blx", 0, 24, MCFixupKindInfo::FKF_IsPCRel}, |
85 | 349k | {"fixup_arm_thumb_bl", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, |
86 | 349k | {"fixup_arm_thumb_blx", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, |
87 | 349k | {"fixup_arm_thumb_cb", 0, 16, MCFixupKindInfo::FKF_IsPCRel}, |
88 | 349k | {"fixup_arm_thumb_cp", 0, 8, |
89 | 349k | MCFixupKindInfo::FKF_IsPCRel | |
90 | 349k | MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, |
91 | 349k | {"fixup_arm_thumb_bcc", 0, 8, MCFixupKindInfo::FKF_IsPCRel}, |
92 | | // movw / movt: 16-bits immediate but scattered into two chunks 0 - 12, 16 |
93 | | // - 19. |
94 | 349k | {"fixup_arm_movt_hi16", 0, 20, 0}, |
95 | 349k | {"fixup_arm_movw_lo16", 0, 20, 0}, |
96 | 349k | {"fixup_t2_movt_hi16", 0, 20, 0}, |
97 | 349k | {"fixup_t2_movw_lo16", 0, 20, 0}, |
98 | 349k | }; |
99 | 349k | const static MCFixupKindInfo InfosBE[ARM::NumTargetFixupKinds] = { |
100 | | // This table *must* be in the order that the fixup_* kinds are defined in |
101 | | // ARMFixupKinds.h. |
102 | | // |
103 | | // Name Offset (bits) Size (bits) Flags |
104 | 349k | {"fixup_arm_ldst_pcrel_12", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, |
105 | 349k | {"fixup_t2_ldst_pcrel_12", 0, 32, |
106 | 349k | MCFixupKindInfo::FKF_IsPCRel | |
107 | 349k | MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, |
108 | 349k | {"fixup_arm_pcrel_10_unscaled", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, |
109 | 349k | {"fixup_arm_pcrel_10", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, |
110 | 349k | {"fixup_t2_pcrel_10", 0, 32, |
111 | 349k | MCFixupKindInfo::FKF_IsPCRel | |
112 | 349k | MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, |
113 | 349k | {"fixup_arm_pcrel_9", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, |
114 | 349k | {"fixup_t2_pcrel_9", 0, 32, |
115 | 349k | MCFixupKindInfo::FKF_IsPCRel | |
116 | 349k | MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, |
117 | 349k | {"fixup_thumb_adr_pcrel_10", 8, 8, |
118 | 349k | MCFixupKindInfo::FKF_IsPCRel | |
119 | 349k | MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, |
120 | 349k | {"fixup_arm_adr_pcrel_12", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, |
121 | 349k | {"fixup_t2_adr_pcrel_12", 0, 32, |
122 | 349k | MCFixupKindInfo::FKF_IsPCRel | |
123 | 349k | MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, |
124 | 349k | {"fixup_arm_condbranch", 8, 24, MCFixupKindInfo::FKF_IsPCRel}, |
125 | 349k | {"fixup_arm_uncondbranch", 8, 24, MCFixupKindInfo::FKF_IsPCRel}, |
126 | 349k | {"fixup_t2_condbranch", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, |
127 | 349k | {"fixup_t2_uncondbranch", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, |
128 | 349k | {"fixup_arm_thumb_br", 0, 16, MCFixupKindInfo::FKF_IsPCRel}, |
129 | 349k | {"fixup_arm_uncondbl", 8, 24, MCFixupKindInfo::FKF_IsPCRel}, |
130 | 349k | {"fixup_arm_condbl", 8, 24, MCFixupKindInfo::FKF_IsPCRel}, |
131 | 349k | {"fixup_arm_blx", 8, 24, MCFixupKindInfo::FKF_IsPCRel}, |
132 | 349k | {"fixup_arm_thumb_bl", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, |
133 | 349k | {"fixup_arm_thumb_blx", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, |
134 | 349k | {"fixup_arm_thumb_cb", 0, 16, MCFixupKindInfo::FKF_IsPCRel}, |
135 | 349k | {"fixup_arm_thumb_cp", 8, 8, |
136 | 349k | MCFixupKindInfo::FKF_IsPCRel | |
137 | 349k | MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, |
138 | 349k | {"fixup_arm_thumb_bcc", 8, 8, MCFixupKindInfo::FKF_IsPCRel}, |
139 | | // movw / movt: 16-bits immediate but scattered into two chunks 0 - 12, 16 |
140 | | // - 19. |
141 | 349k | {"fixup_arm_movt_hi16", 12, 20, 0}, |
142 | 349k | {"fixup_arm_movw_lo16", 12, 20, 0}, |
143 | 349k | {"fixup_t2_movt_hi16", 12, 20, 0}, |
144 | 349k | {"fixup_t2_movw_lo16", 12, 20, 0}, |
145 | 349k | }; |
146 | | |
147 | 349k | if (Kind < FirstTargetFixupKind) |
148 | 271k | return MCAsmBackend::getFixupKindInfo(Kind); |
149 | | |
150 | 349k | assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() && |
151 | 78.3k | "Invalid kind!"); |
152 | 78.3k | return (IsLittleEndian ? InfosLE : InfosBE)[Kind - FirstTargetFixupKind]; |
153 | 78.3k | } |
154 | | |
155 | 8.87k | void ARMAsmBackend::handleAssemblerFlag(MCAssemblerFlag Flag) { |
156 | 8.87k | switch (Flag) { |
157 | 0 | default: |
158 | 0 | break; |
159 | 5.09k | case MCAF_Code16: |
160 | 5.09k | setIsThumb(true); |
161 | 5.09k | break; |
162 | 3.77k | case MCAF_Code32: |
163 | 3.77k | setIsThumb(false); |
164 | 3.77k | break; |
165 | 8.87k | } |
166 | 8.87k | } |
167 | | |
168 | 130k | unsigned ARMAsmBackend::getRelaxedOpcode(unsigned Op) const { |
169 | 130k | bool HasThumb2 = STI->getFeatureBits()[ARM::FeatureThumb2]; |
170 | 130k | bool HasV8MBaselineOps = STI->getFeatureBits()[ARM::HasV8MBaselineOps]; |
171 | | |
172 | 130k | switch (Op) { |
173 | 99.3k | default: |
174 | 99.3k | return Op; |
175 | 5.45k | case ARM::tBcc: |
176 | 5.45k | return HasThumb2 ? (unsigned)ARM::t2Bcc : Op; |
177 | 3.06k | case ARM::tLDRpci: |
178 | 3.06k | return HasThumb2 ? (unsigned)ARM::t2LDRpci : Op; |
179 | 1.74k | case ARM::tADR: |
180 | 1.74k | return HasThumb2 ? (unsigned)ARM::t2ADR : Op; |
181 | 20.0k | case ARM::tB: |
182 | 20.0k | return HasV8MBaselineOps ? (unsigned)ARM::t2B : Op; |
183 | 603 | case ARM::tCBZ: |
184 | 603 | return ARM::tHINT; |
185 | 103 | case ARM::tCBNZ: |
186 | 103 | return ARM::tHINT; |
187 | 130k | } |
188 | 130k | } |
189 | | |
190 | 128k | bool ARMAsmBackend::mayNeedRelaxation(const MCInst &Inst) const { |
191 | 128k | if (getRelaxedOpcode(Inst.getOpcode()) != Inst.getOpcode()) |
192 | 29.6k | return true; |
193 | 99.3k | return false; |
194 | 128k | } |
195 | | |
196 | | const char *ARMAsmBackend::reasonForFixupRelaxation(const MCFixup &Fixup, |
197 | 7.20k | uint64_t Value) const { |
198 | 7.20k | switch ((unsigned)Fixup.getKind()) { |
199 | 4.06k | case ARM::fixup_arm_thumb_br: { |
200 | | // Relaxing tB to t2B. tB has a signed 12-bit displacement with the |
201 | | // low bit being an implied zero. There's an implied +4 offset for the |
202 | | // branch, so we adjust the other way here to determine what's |
203 | | // encodable. |
204 | | // |
205 | | // Relax if the value is too big for a (signed) i8. |
206 | 4.06k | int64_t Offset = int64_t(Value) - 4; |
207 | 4.06k | if (Offset > 2046 || Offset < -2048) |
208 | 382 | return "out of range pc-relative fixup value"; |
209 | 3.68k | break; |
210 | 4.06k | } |
211 | 3.68k | case ARM::fixup_arm_thumb_bcc: { |
212 | | // Relaxing tBcc to t2Bcc. tBcc has a signed 9-bit displacement with the |
213 | | // low bit being an implied zero. There's an implied +4 offset for the |
214 | | // branch, so we adjust the other way here to determine what's |
215 | | // encodable. |
216 | | // |
217 | | // Relax if the value is too big for a (signed) i8. |
218 | 974 | int64_t Offset = int64_t(Value) - 4; |
219 | 974 | if (Offset > 254 || Offset < -256) |
220 | 333 | return "out of range pc-relative fixup value"; |
221 | 641 | break; |
222 | 974 | } |
223 | 648 | case ARM::fixup_thumb_adr_pcrel_10: |
224 | 1.89k | case ARM::fixup_arm_thumb_cp: { |
225 | | // If the immediate is negative, greater than 1020, or not a multiple |
226 | | // of four, the wide version of the instruction must be used. |
227 | 1.89k | int64_t Offset = int64_t(Value) - 4; |
228 | 1.89k | if (Offset & 3) |
229 | 133 | return "misaligned pc-relative fixup value"; |
230 | 1.75k | else if (Offset > 1020 || Offset < 0) |
231 | 241 | return "out of range pc-relative fixup value"; |
232 | 1.51k | break; |
233 | 1.89k | } |
234 | 1.51k | case ARM::fixup_arm_thumb_cb: { |
235 | | // If we have a Thumb CBZ or CBNZ instruction and its target is the next |
236 | | // instruction it is is actually out of range for the instruction. |
237 | | // It will be changed to a NOP. |
238 | 272 | int64_t Offset = (Value & ~1); |
239 | 272 | if (Offset == 2) |
240 | 0 | return "will be converted to nop"; |
241 | 272 | break; |
242 | 272 | } |
243 | 272 | default: |
244 | 0 | llvm_unreachable("Unexpected fixup kind in reasonForFixupRelaxation()!"); |
245 | 7.20k | } |
246 | 6.11k | return nullptr; |
247 | 7.20k | } |
248 | | |
249 | | bool ARMAsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value, |
250 | | const MCRelaxableFragment *DF, |
251 | 7.20k | const MCAsmLayout &Layout, unsigned &KsError) const { |
252 | 7.20k | return reasonForFixupRelaxation(Fixup, Value); |
253 | 7.20k | } |
254 | | |
255 | 1.43k | void ARMAsmBackend::relaxInstruction(const MCInst &Inst, MCInst &Res) const { |
256 | 1.43k | unsigned RelaxedOp = getRelaxedOpcode(Inst.getOpcode()); |
257 | | |
258 | | // Sanity check w/ diagnostic if we get here w/ a bogus instruction. |
259 | 1.43k | if (RelaxedOp == Inst.getOpcode()) { |
260 | 0 | SmallString<256> Tmp; |
261 | 0 | raw_svector_ostream OS(Tmp); |
262 | | //Inst.dump_pretty(OS); |
263 | | //OS << "\n"; |
264 | 0 | report_fatal_error("unexpected instruction to relax: " + OS.str()); |
265 | 0 | } |
266 | | |
267 | | // If we are changing Thumb CBZ or CBNZ instruction to a NOP, aka tHINT, we |
268 | | // have to change the operands too. |
269 | 1.43k | if ((Inst.getOpcode() == ARM::tCBZ || Inst.getOpcode() == ARM::tCBNZ) && |
270 | 17 | RelaxedOp == ARM::tHINT) { |
271 | 17 | Res.setOpcode(RelaxedOp); |
272 | 17 | Res.addOperand(MCOperand::createImm(0)); |
273 | 17 | Res.addOperand(MCOperand::createImm(14)); |
274 | 17 | Res.addOperand(MCOperand::createReg(0)); |
275 | 17 | return; |
276 | 17 | } |
277 | | |
278 | | // The rest of instructions we're relaxing have the same operands. |
279 | | // We just need to update to the proper opcode. |
280 | 1.42k | Res = Inst; |
281 | 1.42k | Res.setOpcode(RelaxedOp); |
282 | 1.42k | } |
283 | | |
284 | 10.9k | bool ARMAsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW) const { |
285 | 10.9k | const uint16_t Thumb1_16bitNopEncoding = 0x46c0; // using MOV r8,r8 |
286 | 10.9k | const uint16_t Thumb2_16bitNopEncoding = 0xbf00; // NOP |
287 | 10.9k | const uint32_t ARMv4_NopEncoding = 0xe1a00000; // using MOV r0,r0 |
288 | 10.9k | const uint32_t ARMv6T2_NopEncoding = 0xe320f000; // NOP |
289 | 10.9k | if (isThumb()) { |
290 | 5.57k | const uint16_t nopEncoding = |
291 | 5.57k | hasNOP() ? Thumb2_16bitNopEncoding : Thumb1_16bitNopEncoding; |
292 | 5.57k | uint64_t NumNops = Count / 2; |
293 | 67.4M | for (uint64_t i = 0; i != NumNops; ++i) |
294 | 67.4M | OW->write16(nopEncoding); |
295 | 5.57k | if (Count & 1) |
296 | 14 | OW->write8(0); |
297 | 5.57k | return true; |
298 | 5.57k | } |
299 | | // ARM mode |
300 | 5.35k | const uint32_t nopEncoding = |
301 | 5.35k | hasNOP() ? ARMv6T2_NopEncoding : ARMv4_NopEncoding; |
302 | 5.35k | uint64_t NumNops = Count / 4; |
303 | 45.3M | for (uint64_t i = 0; i != NumNops; ++i) |
304 | 45.3M | OW->write32(nopEncoding); |
305 | | // FIXME: should this function return false when unable to write exactly |
306 | | // 'Count' bytes with NOP encodings? |
307 | 5.35k | switch (Count % 4) { |
308 | 5.29k | default: |
309 | 5.29k | break; // No leftover bytes to write |
310 | 5.29k | case 1: |
311 | 4 | OW->write8(0); |
312 | 4 | break; |
313 | 44 | case 2: |
314 | 44 | OW->write16(0); |
315 | 44 | break; |
316 | 13 | case 3: |
317 | 13 | OW->write16(0); |
318 | 13 | OW->write8(0xa0); |
319 | 13 | break; |
320 | 5.35k | } |
321 | | |
322 | 5.35k | return true; |
323 | 5.35k | } |
324 | | |
325 | 6.30k | static uint32_t swapHalfWords(uint32_t Value, bool IsLittleEndian) { |
326 | 6.30k | if (IsLittleEndian) { |
327 | | // Note that the halfwords are stored high first and low second in thumb; |
328 | | // so we need to swap the fixup value here to map properly. |
329 | 4.05k | uint32_t Swapped = (Value & 0xFFFF0000) >> 16; |
330 | 4.05k | Swapped |= (Value & 0x0000FFFF) << 16; |
331 | 4.05k | return Swapped; |
332 | 4.05k | } else |
333 | 2.24k | return Value; |
334 | 6.30k | } |
335 | | |
336 | | static uint32_t joinHalfWords(uint32_t FirstHalf, uint32_t SecondHalf, |
337 | 3.56k | bool IsLittleEndian) { |
338 | 3.56k | uint32_t Value; |
339 | | |
340 | 3.56k | if (IsLittleEndian) { |
341 | 2.18k | Value = (SecondHalf & 0xFFFF) << 16; |
342 | 2.18k | Value |= (FirstHalf & 0xFFFF); |
343 | 2.18k | } else { |
344 | 1.38k | Value = (SecondHalf & 0xFFFF); |
345 | 1.38k | Value |= (FirstHalf & 0xFFFF) << 16; |
346 | 1.38k | } |
347 | | |
348 | 3.56k | return Value; |
349 | 3.56k | } |
350 | | |
351 | | unsigned ARMAsmBackend::adjustFixupValue(const MCFixup &Fixup, uint64_t Value, |
352 | | bool IsPCRel, MCContext *Ctx, |
353 | | bool IsLittleEndian, |
354 | | bool IsResolved) const |
355 | 224k | { |
356 | 224k | unsigned Kind = Fixup.getKind(); |
357 | 224k | switch (Kind) { |
358 | 0 | default: |
359 | 0 | llvm_unreachable("Unknown fixup kind!"); |
360 | 1.45k | case FK_Data_1: |
361 | 1.97k | case FK_Data_2: |
362 | 179k | case FK_Data_4: |
363 | 179k | return Value; |
364 | 0 | case FK_SecRel_2: |
365 | 0 | return Value; |
366 | 0 | case FK_SecRel_4: |
367 | 0 | return Value; |
368 | 0 | case ARM::fixup_arm_movt_hi16: |
369 | 0 | if (!IsPCRel) |
370 | 0 | Value >>= 16; |
371 | | // Fallthrough |
372 | 0 | case ARM::fixup_arm_movw_lo16: { |
373 | 0 | unsigned Hi4 = (Value & 0xF000) >> 12; |
374 | 0 | unsigned Lo12 = Value & 0x0FFF; |
375 | | // inst{19-16} = Hi4; |
376 | | // inst{11-0} = Lo12; |
377 | 0 | Value = (Hi4 << 16) | (Lo12); |
378 | 0 | return Value; |
379 | 0 | } |
380 | 0 | case ARM::fixup_t2_movt_hi16: |
381 | 0 | if (!IsPCRel) |
382 | 0 | Value >>= 16; |
383 | | // Fallthrough |
384 | 0 | case ARM::fixup_t2_movw_lo16: { |
385 | 0 | unsigned Hi4 = (Value & 0xF000) >> 12; |
386 | 0 | unsigned i = (Value & 0x800) >> 11; |
387 | 0 | unsigned Mid3 = (Value & 0x700) >> 8; |
388 | 0 | unsigned Lo8 = Value & 0x0FF; |
389 | | // inst{19-16} = Hi4; |
390 | | // inst{26} = i; |
391 | | // inst{14-12} = Mid3; |
392 | | // inst{7-0} = Lo8; |
393 | 0 | Value = (Hi4 << 16) | (i << 26) | (Mid3 << 12) | (Lo8); |
394 | 0 | return swapHalfWords(Value, IsLittleEndian); |
395 | 0 | } |
396 | 2.32k | case ARM::fixup_arm_ldst_pcrel_12: |
397 | | // ARM PC-relative values are offset by 8. |
398 | 2.32k | Value -= 4; |
399 | | // FALLTHROUGH |
400 | 5.50k | case ARM::fixup_t2_ldst_pcrel_12: { |
401 | | // Offset by 4, adjusted by two due to the half-word ordering of thumb. |
402 | 5.50k | Value -= 4; |
403 | 5.50k | bool isAdd = true; |
404 | 5.50k | if ((int64_t)Value < 0) { |
405 | 3.25k | Value = -Value; |
406 | 3.25k | isAdd = false; |
407 | 3.25k | } |
408 | 5.50k | if (Ctx && Value >= 4096) { |
409 | 283 | Ctx->reportError(Fixup.getLoc(), "out of range pc-relative fixup value"); |
410 | 283 | return 0; |
411 | 283 | } |
412 | 5.21k | Value |= isAdd << 23; |
413 | | |
414 | | // Same addressing mode as fixup_arm_pcrel_10, |
415 | | // but with 16-bit halfwords swapped. |
416 | 5.21k | if (Kind == ARM::fixup_t2_ldst_pcrel_12) |
417 | 2.95k | return swapHalfWords(Value, IsLittleEndian); |
418 | | |
419 | 2.26k | return Value; |
420 | 5.21k | } |
421 | 1.75k | case ARM::fixup_arm_adr_pcrel_12: { |
422 | | // ARM PC-relative values are offset by 8. |
423 | 1.75k | Value -= 8; |
424 | 1.75k | unsigned opc = 4; // bits {24-21}. Default to add: 0b0100 |
425 | 1.75k | if ((int64_t)Value < 0) { |
426 | 660 | Value = -Value; |
427 | 660 | opc = 2; // 0b0010 |
428 | 660 | } |
429 | 1.75k | if (Ctx && ARM_AM::getSOImmVal(Value) == -1) { |
430 | 448 | Ctx->reportError(Fixup.getLoc(), "out of range pc-relative fixup value"); |
431 | 448 | return 0; |
432 | 448 | } |
433 | | // Encode the immediate and shift the opcode into place. |
434 | 1.30k | return ARM_AM::getSOImmVal(Value) | (opc << 21); |
435 | 1.75k | } |
436 | | |
437 | 1.16k | case ARM::fixup_t2_adr_pcrel_12: { |
438 | 1.16k | Value -= 4; |
439 | 1.16k | unsigned opc = 0; |
440 | 1.16k | if ((int64_t)Value < 0) { |
441 | 470 | Value = -Value; |
442 | 470 | opc = 5; |
443 | 470 | } |
444 | | |
445 | 1.16k | uint32_t out = (opc << 21); |
446 | 1.16k | out |= (Value & 0x800) << 15; |
447 | 1.16k | out |= (Value & 0x700) << 4; |
448 | 1.16k | out |= (Value & 0x0FF); |
449 | | |
450 | 1.16k | return swapHalfWords(out, IsLittleEndian); |
451 | 1.75k | } |
452 | | |
453 | 2.70k | case ARM::fixup_arm_condbranch: |
454 | 8.59k | case ARM::fixup_arm_uncondbranch: |
455 | 11.7k | case ARM::fixup_arm_uncondbl: |
456 | 12.4k | case ARM::fixup_arm_condbl: |
457 | 12.8k | case ARM::fixup_arm_blx: |
458 | | // These values don't encode the low two bits since they're always zero. |
459 | | // Offset by 8 just as above. |
460 | 12.8k | if (const MCSymbolRefExpr *SRE = |
461 | 12.8k | dyn_cast<MCSymbolRefExpr>(Fixup.getValue())) |
462 | 8.42k | if (SRE->getKind() == MCSymbolRefExpr::VK_ARM_TLSCALL) |
463 | 0 | return 0; |
464 | 12.8k | return 0xffffff & ((Value - 8) >> 2); |
465 | 1.06k | case ARM::fixup_t2_uncondbranch: { |
466 | 1.06k | Value = Value - 4; |
467 | 1.06k | Value >>= 1; // Low bit is not encoded. |
468 | | |
469 | 1.06k | uint32_t out = 0; |
470 | 1.06k | bool I = Value & 0x800000; |
471 | 1.06k | bool J1 = Value & 0x400000; |
472 | 1.06k | bool J2 = Value & 0x200000; |
473 | 1.06k | J1 ^= I; |
474 | 1.06k | J2 ^= I; |
475 | | |
476 | 1.06k | out |= I << 26; // S bit |
477 | 1.06k | out |= !J1 << 13; // J1 bit |
478 | 1.06k | out |= !J2 << 11; // J2 bit |
479 | 1.06k | out |= (Value & 0x1FF800) << 5; // imm6 field |
480 | 1.06k | out |= (Value & 0x0007FF); // imm11 field |
481 | | |
482 | 1.06k | return swapHalfWords(out, IsLittleEndian); |
483 | 12.8k | } |
484 | 868 | case ARM::fixup_t2_condbranch: { |
485 | 868 | Value = Value - 4; |
486 | 868 | Value >>= 1; // Low bit is not encoded. |
487 | | |
488 | 868 | uint64_t out = 0; |
489 | 868 | out |= (Value & 0x80000) << 7; // S bit |
490 | 868 | out |= (Value & 0x40000) >> 7; // J2 bit |
491 | 868 | out |= (Value & 0x20000) >> 4; // J1 bit |
492 | 868 | out |= (Value & 0x1F800) << 5; // imm6 field |
493 | 868 | out |= (Value & 0x007FF); // imm11 field |
494 | | |
495 | 868 | return swapHalfWords(out, IsLittleEndian); |
496 | 12.8k | } |
497 | 3.16k | case ARM::fixup_arm_thumb_bl: { |
498 | | // The value doesn't encode the low bit (always zero) and is offset by |
499 | | // four. The 32-bit immediate value is encoded as |
500 | | // imm32 = SignExtend(S:I1:I2:imm10:imm11:0) |
501 | | // where I1 = NOT(J1 ^ S) and I2 = NOT(J2 ^ S). |
502 | | // The value is encoded into disjoint bit positions in the destination |
503 | | // opcode. x = unchanged, I = immediate value bit, S = sign extension bit, |
504 | | // J = either J1 or J2 bit |
505 | | // |
506 | | // BL: xxxxxSIIIIIIIIII xxJxJIIIIIIIIIII |
507 | | // |
508 | | // Note that the halfwords are stored high first, low second; so we need |
509 | | // to transpose the fixup value here to map properly. |
510 | 3.16k | uint32_t offset = (Value - 4) >> 1; |
511 | 3.16k | uint32_t signBit = (offset & 0x800000) >> 23; |
512 | 3.16k | uint32_t I1Bit = (offset & 0x400000) >> 22; |
513 | 3.16k | uint32_t J1Bit = (I1Bit ^ 0x1) ^ signBit; |
514 | 3.16k | uint32_t I2Bit = (offset & 0x200000) >> 21; |
515 | 3.16k | uint32_t J2Bit = (I2Bit ^ 0x1) ^ signBit; |
516 | 3.16k | uint32_t imm10Bits = (offset & 0x1FF800) >> 11; |
517 | 3.16k | uint32_t imm11Bits = (offset & 0x000007FF); |
518 | | |
519 | 3.16k | uint32_t FirstHalf = (((uint16_t)signBit << 10) | (uint16_t)imm10Bits); |
520 | 3.16k | uint32_t SecondHalf = (((uint16_t)J1Bit << 13) | ((uint16_t)J2Bit << 11) | |
521 | 3.16k | (uint16_t)imm11Bits); |
522 | 3.16k | return joinHalfWords(FirstHalf, SecondHalf, IsLittleEndian); |
523 | 12.8k | } |
524 | 402 | case ARM::fixup_arm_thumb_blx: { |
525 | | // The value doesn't encode the low two bits (always zero) and is offset by |
526 | | // four (see fixup_arm_thumb_cp). The 32-bit immediate value is encoded as |
527 | | // imm32 = SignExtend(S:I1:I2:imm10H:imm10L:00) |
528 | | // where I1 = NOT(J1 ^ S) and I2 = NOT(J2 ^ S). |
529 | | // The value is encoded into disjoint bit positions in the destination |
530 | | // opcode. x = unchanged, I = immediate value bit, S = sign extension bit, |
531 | | // J = either J1 or J2 bit, 0 = zero. |
532 | | // |
533 | | // BLX: xxxxxSIIIIIIIIII xxJxJIIIIIIIIII0 |
534 | | // |
535 | | // Note that the halfwords are stored high first, low second; so we need |
536 | | // to transpose the fixup value here to map properly. |
537 | 402 | uint32_t offset = (Value - 2) >> 2; |
538 | 402 | if (const MCSymbolRefExpr *SRE = |
539 | 402 | dyn_cast<MCSymbolRefExpr>(Fixup.getValue())) |
540 | 186 | if (SRE->getKind() == MCSymbolRefExpr::VK_ARM_TLSCALL) |
541 | 0 | offset = 0; |
542 | 402 | uint32_t signBit = (offset & 0x400000) >> 22; |
543 | 402 | uint32_t I1Bit = (offset & 0x200000) >> 21; |
544 | 402 | uint32_t J1Bit = (I1Bit ^ 0x1) ^ signBit; |
545 | 402 | uint32_t I2Bit = (offset & 0x100000) >> 20; |
546 | 402 | uint32_t J2Bit = (I2Bit ^ 0x1) ^ signBit; |
547 | 402 | uint32_t imm10HBits = (offset & 0xFFC00) >> 10; |
548 | 402 | uint32_t imm10LBits = (offset & 0x3FF); |
549 | | |
550 | 402 | uint32_t FirstHalf = (((uint16_t)signBit << 10) | (uint16_t)imm10HBits); |
551 | 402 | uint32_t SecondHalf = (((uint16_t)J1Bit << 13) | ((uint16_t)J2Bit << 11) | |
552 | 402 | ((uint16_t)imm10LBits) << 1); |
553 | 402 | return joinHalfWords(FirstHalf, SecondHalf, IsLittleEndian); |
554 | 12.8k | } |
555 | 886 | case ARM::fixup_thumb_adr_pcrel_10: |
556 | 4.06k | case ARM::fixup_arm_thumb_cp: |
557 | | // On CPUs supporting Thumb2, this will be relaxed to an ldr.w, otherwise we |
558 | | // could have an error on our hands. |
559 | 4.06k | if (Ctx && !STI->getFeatureBits()[ARM::FeatureThumb2] && IsResolved) { |
560 | 0 | const char *FixupDiagnostic = reasonForFixupRelaxation(Fixup, Value); |
561 | 0 | if (FixupDiagnostic) { |
562 | 0 | Ctx->reportError(Fixup.getLoc(), FixupDiagnostic); |
563 | 0 | return 0; |
564 | 0 | } |
565 | 0 | } |
566 | | // Offset by 4, and don't encode the low two bits. |
567 | 4.06k | return ((Value - 4) >> 2) & 0xff; |
568 | 597 | case ARM::fixup_arm_thumb_cb: { |
569 | | // Offset by 4 and don't encode the lower bit, which is always 0. |
570 | | // FIXME: diagnose if no Thumb2 |
571 | 597 | uint32_t Binary = (Value - 4) >> 1; |
572 | 597 | return ((Binary & 0x20) << 4) | ((Binary & 0x1f) << 3); |
573 | 4.06k | } |
574 | 8.50k | case ARM::fixup_arm_thumb_br: |
575 | | // Offset by 4 and don't encode the lower bit, which is always 0. |
576 | 8.50k | if (Ctx && !STI->getFeatureBits()[ARM::FeatureThumb2] && |
577 | 0 | !STI->getFeatureBits()[ARM::HasV8MBaselineOps]) { |
578 | 0 | const char *FixupDiagnostic = reasonForFixupRelaxation(Fixup, Value); |
579 | 0 | if (FixupDiagnostic) { |
580 | 0 | Ctx->reportError(Fixup.getLoc(), FixupDiagnostic); |
581 | 0 | return 0; |
582 | 0 | } |
583 | 0 | } |
584 | 8.50k | return ((Value - 4) >> 1) & 0x7ff; |
585 | 2.11k | case ARM::fixup_arm_thumb_bcc: |
586 | | // Offset by 4 and don't encode the lower bit, which is always 0. |
587 | 2.11k | if (Ctx && !STI->getFeatureBits()[ARM::FeatureThumb2]) { |
588 | 0 | const char *FixupDiagnostic = reasonForFixupRelaxation(Fixup, Value); |
589 | 0 | if (FixupDiagnostic) { |
590 | 0 | Ctx->reportError(Fixup.getLoc(), FixupDiagnostic); |
591 | 0 | return 0; |
592 | 0 | } |
593 | 0 | } |
594 | 2.11k | return ((Value - 4) >> 1) & 0xff; |
595 | 2.25k | case ARM::fixup_arm_pcrel_10_unscaled: { |
596 | 2.25k | Value = Value - 8; // ARM fixups offset by an additional word and don't |
597 | | // need to adjust for the half-word ordering. |
598 | 2.25k | bool isAdd = true; |
599 | 2.25k | if ((int64_t)Value < 0) { |
600 | 1.93k | Value = -Value; |
601 | 1.93k | isAdd = false; |
602 | 1.93k | } |
603 | | // The value has the low 4 bits encoded in [3:0] and the high 4 in [11:8]. |
604 | 2.25k | if (Ctx && Value >= 256) { |
605 | 734 | Ctx->reportError(Fixup.getLoc(), "out of range pc-relative fixup value"); |
606 | 734 | return 0; |
607 | 734 | } |
608 | 1.51k | Value = (Value & 0xf) | ((Value & 0xf0) << 4); |
609 | 1.51k | return Value | (isAdd << 23); |
610 | 2.25k | } |
611 | 568 | case ARM::fixup_arm_pcrel_10: |
612 | 568 | Value = Value - 4; // ARM fixups offset by an additional word and don't |
613 | | // need to adjust for the half-word ordering. |
614 | | // Fall through. |
615 | 984 | case ARM::fixup_t2_pcrel_10: { |
616 | | // Offset by 4, adjusted by two due to the half-word ordering of thumb. |
617 | 984 | Value = Value - 4; |
618 | 984 | bool isAdd = true; |
619 | 984 | if ((int64_t)Value < 0) { |
620 | 234 | Value = -Value; |
621 | 234 | isAdd = false; |
622 | 234 | } |
623 | | // These values don't encode the low two bits since they're always zero. |
624 | 984 | Value >>= 2; |
625 | 984 | if (Ctx && Value >= 256) { |
626 | 346 | Ctx->reportError(Fixup.getLoc(), "out of range pc-relative fixup value"); |
627 | 346 | return 0; |
628 | 346 | } |
629 | 638 | Value |= isAdd << 23; |
630 | | |
631 | | // Same addressing mode as fixup_arm_pcrel_10, but with 16-bit halfwords |
632 | | // swapped. |
633 | 638 | if (Kind == ARM::fixup_t2_pcrel_10) |
634 | 259 | return swapHalfWords(Value, IsLittleEndian); |
635 | | |
636 | 379 | return Value; |
637 | 638 | } |
638 | 0 | case ARM::fixup_arm_pcrel_9: |
639 | 0 | Value = Value - 4; // ARM fixups offset by an additional word and don't |
640 | | // need to adjust for the half-word ordering. |
641 | | // Fall through. |
642 | 0 | case ARM::fixup_t2_pcrel_9: { |
643 | | // Offset by 4, adjusted by two due to the half-word ordering of thumb. |
644 | 0 | Value = Value - 4; |
645 | 0 | bool isAdd = true; |
646 | 0 | if ((int64_t)Value < 0) { |
647 | 0 | Value = -Value; |
648 | 0 | isAdd = false; |
649 | 0 | } |
650 | | // These values don't encode the low bit since it's always zero. |
651 | 0 | if (Ctx && (Value & 1)) { |
652 | 0 | Ctx->reportError(Fixup.getLoc(), "invalid value for this fixup"); |
653 | 0 | return 0; |
654 | 0 | } |
655 | 0 | Value >>= 1; |
656 | 0 | if (Ctx && Value >= 256) { |
657 | 0 | Ctx->reportError(Fixup.getLoc(), "out of range pc-relative fixup value"); |
658 | 0 | return 0; |
659 | 0 | } |
660 | 0 | Value |= isAdd << 23; |
661 | | |
662 | | // Same addressing mode as fixup_arm_pcrel_9, but with 16-bit halfwords |
663 | | // swapped. |
664 | 0 | if (Kind == ARM::fixup_t2_pcrel_9) |
665 | 0 | return swapHalfWords(Value, IsLittleEndian); |
666 | | |
667 | 0 | return Value; |
668 | 0 | } |
669 | 224k | } |
670 | 224k | } |
671 | | |
672 | | void ARMAsmBackend::processFixupValue(const MCAssembler &Asm, |
673 | | const MCAsmLayout &Layout, |
674 | | const MCFixup &Fixup, |
675 | | const MCFragment *DF, |
676 | | const MCValue &Target, uint64_t &Value, |
677 | | bool &IsResolved) |
678 | 116k | { |
679 | 116k | const MCSymbolRefExpr *A = Target.getSymA(); |
680 | 116k | const MCSymbol *Sym = A ? &A->getSymbol() : nullptr; |
681 | | // Some fixups to thumb function symbols need the low bit (thumb bit) |
682 | | // twiddled. |
683 | 116k | if ((unsigned)Fixup.getKind() != ARM::fixup_arm_ldst_pcrel_12 && |
684 | 115k | (unsigned)Fixup.getKind() != ARM::fixup_t2_ldst_pcrel_12 && |
685 | 113k | (unsigned)Fixup.getKind() != ARM::fixup_arm_adr_pcrel_12 && |
686 | 112k | (unsigned)Fixup.getKind() != ARM::fixup_thumb_adr_pcrel_10 && |
687 | 111k | (unsigned)Fixup.getKind() != ARM::fixup_t2_adr_pcrel_12 && |
688 | 111k | (unsigned)Fixup.getKind() != ARM::fixup_arm_thumb_cp) { |
689 | 109k | if (Sym) { |
690 | 97.8k | if (Asm.isThumbFunc(Sym)) |
691 | 0 | Value |= 1; |
692 | 97.8k | } |
693 | 109k | } |
694 | 116k | if (IsResolved && (unsigned)Fixup.getKind() == ARM::fixup_arm_thumb_bl) { |
695 | 745 | assert(Sym && "How did we resolve this?"); |
696 | | |
697 | | // If the symbol is external the linker will handle it. |
698 | | // FIXME: Should we handle it as an optimization? |
699 | | |
700 | | // If the symbol is out of range, produce a relocation and hope the |
701 | | // linker can handle it. GNU AS produces an error in this case. |
702 | 745 | if (Sym->isExternal() || ((Value >= 0x400004) && (Value <= (uint64_t)(-0x400000)))) |
703 | 440 | IsResolved = false; |
704 | 745 | } |
705 | | // We must always generate a relocation for BL/BLX instructions if we have |
706 | | // a symbol to reference, as the linker relies on knowing the destination |
707 | | // symbol's thumb-ness to get interworking right. |
708 | 116k | if (A && ( |
709 | | // (unsigned)Fixup.getKind() == ARM::fixup_arm_thumb_blx || |
710 | | //(unsigned)Fixup.getKind() == ARM::fixup_arm_blx || |
711 | | //(unsigned)Fixup.getKind() == ARM::fixup_arm_uncondbl || |
712 | 102k | (unsigned)Fixup.getKind() == ARM::fixup_arm_condbl)) |
713 | 267 | IsResolved = false; |
714 | | |
715 | | // Try to get the encoded value for the fixup as-if we're mapping it into |
716 | | // the instruction. This allows adjustFixupValue() to issue a diagnostic |
717 | | // if the value aren't invalid. |
718 | 116k | (void)adjustFixupValue(Fixup, Value, false, &Asm.getContext(), |
719 | 116k | IsLittleEndian, IsResolved); |
720 | 116k | } |
721 | | |
722 | | /// getFixupKindNumBytes - The number of bytes the fixup may change. |
723 | 108k | static unsigned getFixupKindNumBytes(unsigned Kind) { |
724 | 108k | switch (Kind) { |
725 | 0 | default: |
726 | 0 | llvm_unreachable("Unknown fixup kind!"); |
727 | | |
728 | 728 | case FK_Data_1: |
729 | 1.25k | case ARM::fixup_arm_thumb_bcc: |
730 | 2.21k | case ARM::fixup_arm_thumb_cp: |
731 | 2.33k | case ARM::fixup_thumb_adr_pcrel_10: |
732 | 2.33k | return 1; |
733 | | |
734 | 257 | case FK_Data_2: |
735 | 2.35k | case ARM::fixup_arm_thumb_br: |
736 | 2.51k | case ARM::fixup_arm_thumb_cb: |
737 | 2.51k | return 2; |
738 | | |
739 | 1.12k | case ARM::fixup_arm_pcrel_10_unscaled: |
740 | 2.28k | case ARM::fixup_arm_ldst_pcrel_12: |
741 | 2.57k | case ARM::fixup_arm_pcrel_10: |
742 | 2.57k | case ARM::fixup_arm_pcrel_9: |
743 | 3.44k | case ARM::fixup_arm_adr_pcrel_12: |
744 | 5.04k | case ARM::fixup_arm_uncondbl: |
745 | 5.36k | case ARM::fixup_arm_condbl: |
746 | 5.55k | case ARM::fixup_arm_blx: |
747 | 6.90k | case ARM::fixup_arm_condbranch: |
748 | 9.84k | case ARM::fixup_arm_uncondbranch: |
749 | 9.84k | return 3; |
750 | | |
751 | 88.8k | case FK_Data_4: |
752 | 90.4k | case ARM::fixup_t2_ldst_pcrel_12: |
753 | 90.9k | case ARM::fixup_t2_condbranch: |
754 | 91.4k | case ARM::fixup_t2_uncondbranch: |
755 | 91.6k | case ARM::fixup_t2_pcrel_10: |
756 | 91.6k | case ARM::fixup_t2_pcrel_9: |
757 | 92.2k | case ARM::fixup_t2_adr_pcrel_12: |
758 | 93.8k | case ARM::fixup_arm_thumb_bl: |
759 | 94.0k | case ARM::fixup_arm_thumb_blx: |
760 | 94.0k | case ARM::fixup_arm_movt_hi16: |
761 | 94.0k | case ARM::fixup_arm_movw_lo16: |
762 | 94.0k | case ARM::fixup_t2_movt_hi16: |
763 | 94.0k | case ARM::fixup_t2_movw_lo16: |
764 | 94.0k | return 4; |
765 | | |
766 | 0 | case FK_SecRel_2: |
767 | 0 | return 2; |
768 | 0 | case FK_SecRel_4: |
769 | 0 | return 4; |
770 | 108k | } |
771 | 108k | } |
772 | | |
773 | | /// getFixupKindContainerSizeBytes - The number of bytes of the |
774 | | /// container involved in big endian. |
775 | 23.6k | static unsigned getFixupKindContainerSizeBytes(unsigned Kind) { |
776 | 23.6k | switch (Kind) { |
777 | 0 | default: |
778 | 0 | llvm_unreachable("Unknown fixup kind!"); |
779 | | |
780 | 78 | case FK_Data_1: |
781 | 78 | return 1; |
782 | 44 | case FK_Data_2: |
783 | 44 | return 2; |
784 | 15.6k | case FK_Data_4: |
785 | 15.6k | return 4; |
786 | | |
787 | 136 | case ARM::fixup_arm_thumb_bcc: |
788 | 196 | case ARM::fixup_arm_thumb_cp: |
789 | 272 | case ARM::fixup_thumb_adr_pcrel_10: |
790 | 1.36k | case ARM::fixup_arm_thumb_br: |
791 | 1.45k | case ARM::fixup_arm_thumb_cb: |
792 | | // Instruction size is 2 bytes. |
793 | 1.45k | return 2; |
794 | | |
795 | 186 | case ARM::fixup_arm_pcrel_10_unscaled: |
796 | 697 | case ARM::fixup_arm_ldst_pcrel_12: |
797 | 850 | case ARM::fixup_arm_pcrel_10: |
798 | 1.17k | case ARM::fixup_arm_adr_pcrel_12: |
799 | 1.92k | case ARM::fixup_arm_uncondbl: |
800 | 2.11k | case ARM::fixup_arm_condbl: |
801 | 2.22k | case ARM::fixup_arm_blx: |
802 | 2.84k | case ARM::fixup_arm_condbranch: |
803 | 4.51k | case ARM::fixup_arm_uncondbranch: |
804 | 5.28k | case ARM::fixup_t2_ldst_pcrel_12: |
805 | 5.36k | case ARM::fixup_t2_condbranch: |
806 | 5.46k | case ARM::fixup_t2_uncondbranch: |
807 | 5.50k | case ARM::fixup_t2_pcrel_10: |
808 | 5.66k | case ARM::fixup_t2_adr_pcrel_12: |
809 | 6.28k | case ARM::fixup_arm_thumb_bl: |
810 | 6.35k | case ARM::fixup_arm_thumb_blx: |
811 | 6.35k | case ARM::fixup_arm_movt_hi16: |
812 | 6.35k | case ARM::fixup_arm_movw_lo16: |
813 | 6.35k | case ARM::fixup_t2_movt_hi16: |
814 | 6.35k | case ARM::fixup_t2_movw_lo16: |
815 | | // Instruction size is 4 bytes. |
816 | 6.35k | return 4; |
817 | 23.6k | } |
818 | 23.6k | } |
819 | | |
820 | | void ARMAsmBackend::applyFixup(const MCFixup &Fixup, char *Data, |
821 | | unsigned DataSize, uint64_t Value, |
822 | | bool IsPCRel, unsigned int &KsError) const |
823 | 108k | { |
824 | 108k | unsigned NumBytes = getFixupKindNumBytes(Fixup.getKind()); |
825 | 108k | Value = |
826 | 108k | adjustFixupValue(Fixup, Value, IsPCRel, nullptr, IsLittleEndian, true); |
827 | 108k | if (!Value) |
828 | 4.42k | return; // Doesn't change encoding. |
829 | | |
830 | 104k | unsigned Offset = Fixup.getOffset(); |
831 | | //assert(Offset + NumBytes <= DataSize && "Invalid fixup offset!"); |
832 | 104k | if (Offset + NumBytes > DataSize) { |
833 | 0 | KsError = KS_ERR_ASM_FIXUP_INVALID; |
834 | 0 | return; |
835 | 0 | } |
836 | | |
837 | | // Used to point to big endian bytes. |
838 | 104k | unsigned FullSizeBytes; |
839 | 104k | if (!IsLittleEndian) { |
840 | 23.6k | FullSizeBytes = getFixupKindContainerSizeBytes(Fixup.getKind()); |
841 | | //assert((Offset + FullSizeBytes) <= DataSize && "Invalid fixup size!"); |
842 | | //assert(NumBytes <= FullSizeBytes && "Invalid fixup size!"); |
843 | 23.6k | if ((Offset + FullSizeBytes) > DataSize || |
844 | 23.6k | NumBytes > FullSizeBytes) { |
845 | 0 | KsError = KS_ERR_ASM_FIXUP_INVALID; |
846 | 0 | return; |
847 | 0 | } |
848 | 23.6k | } |
849 | | |
850 | | // For each byte of the fragment that the fixup touches, mask in the bits from |
851 | | // the fixup value. The Value has been "split up" into the appropriate |
852 | | // bitfields above. |
853 | 502k | for (unsigned i = 0; i != NumBytes; ++i) { |
854 | 397k | unsigned Idx = IsLittleEndian ? i : (FullSizeBytes - 1 - i); |
855 | 397k | Data[Offset + Idx] |= uint8_t((Value >> (i * 8)) & 0xff); |
856 | 397k | } |
857 | 104k | } |
858 | | |
859 | | namespace CU { |
860 | | |
861 | | /// \brief Compact unwind encoding values. |
862 | | enum CompactUnwindEncodings { |
863 | | UNWIND_ARM_MODE_MASK = 0x0F000000, |
864 | | UNWIND_ARM_MODE_FRAME = 0x01000000, |
865 | | UNWIND_ARM_MODE_FRAME_D = 0x02000000, |
866 | | UNWIND_ARM_MODE_DWARF = 0x04000000, |
867 | | |
868 | | UNWIND_ARM_FRAME_STACK_ADJUST_MASK = 0x00C00000, |
869 | | |
870 | | UNWIND_ARM_FRAME_FIRST_PUSH_R4 = 0x00000001, |
871 | | UNWIND_ARM_FRAME_FIRST_PUSH_R5 = 0x00000002, |
872 | | UNWIND_ARM_FRAME_FIRST_PUSH_R6 = 0x00000004, |
873 | | |
874 | | UNWIND_ARM_FRAME_SECOND_PUSH_R8 = 0x00000008, |
875 | | UNWIND_ARM_FRAME_SECOND_PUSH_R9 = 0x00000010, |
876 | | UNWIND_ARM_FRAME_SECOND_PUSH_R10 = 0x00000020, |
877 | | UNWIND_ARM_FRAME_SECOND_PUSH_R11 = 0x00000040, |
878 | | UNWIND_ARM_FRAME_SECOND_PUSH_R12 = 0x00000080, |
879 | | |
880 | | UNWIND_ARM_FRAME_D_REG_COUNT_MASK = 0x00000F00, |
881 | | |
882 | | UNWIND_ARM_DWARF_SECTION_OFFSET = 0x00FFFFFF |
883 | | }; |
884 | | |
885 | | } // end CU namespace |
886 | | |
887 | | MCAsmBackend *llvm_ks::createARMAsmBackend(const Target &T, |
888 | | const MCRegisterInfo &MRI, |
889 | | const Triple &TheTriple, StringRef CPU, |
890 | 60.6k | bool isLittle) { |
891 | 60.6k | switch (TheTriple.getObjectFormat()) { |
892 | 0 | default: |
893 | 0 | llvm_unreachable("unsupported object format"); |
894 | 60.6k | case Triple::ELF: |
895 | 60.6k | assert(TheTriple.isOSBinFormatELF() && "using ELF for non-ELF target"); |
896 | 60.6k | uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TheTriple.getOS()); |
897 | 60.6k | return new ARMAsmBackendELF(T, TheTriple, OSABI, isLittle); |
898 | 60.6k | } |
899 | 60.6k | } |
900 | | |
901 | | MCAsmBackend *llvm_ks::createARMLEAsmBackend(const Target &T, |
902 | | const MCRegisterInfo &MRI, |
903 | 18.1k | const Triple &TT, StringRef CPU) { |
904 | 18.1k | return createARMAsmBackend(T, MRI, TT, CPU, true); |
905 | 18.1k | } |
906 | | |
907 | | MCAsmBackend *llvm_ks::createARMBEAsmBackend(const Target &T, |
908 | | const MCRegisterInfo &MRI, |
909 | 12.2k | const Triple &TT, StringRef CPU) { |
910 | 12.2k | return createARMAsmBackend(T, MRI, TT, CPU, false); |
911 | 12.2k | } |
912 | | |
913 | | MCAsmBackend *llvm_ks::createThumbLEAsmBackend(const Target &T, |
914 | | const MCRegisterInfo &MRI, |
915 | 16.0k | const Triple &TT, StringRef CPU) { |
916 | 16.0k | return createARMAsmBackend(T, MRI, TT, CPU, true); |
917 | 16.0k | } |
918 | | |
919 | | MCAsmBackend *llvm_ks::createThumbBEAsmBackend(const Target &T, |
920 | | const MCRegisterInfo &MRI, |
921 | 14.2k | const Triple &TT, StringRef CPU) { |
922 | 14.2k | return createARMAsmBackend(T, MRI, TT, CPU, false); |
923 | 14.2k | } |