Coverage Report

Created: 2017-10-03 07:32

/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/tools/lld/ELF/Arch/ARM.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- ARM.cpp ------------------------------------------------------------===//
2
//
3
//                             The LLVM Linker
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 "Error.h"
11
#include "InputFiles.h"
12
#include "Symbols.h"
13
#include "SyntheticSections.h"
14
#include "Target.h"
15
#include "Thunks.h"
16
#include "llvm/Object/ELF.h"
17
#include "llvm/Support/Endian.h"
18
19
using namespace llvm;
20
using namespace llvm::support::endian;
21
using namespace llvm::ELF;
22
using namespace lld;
23
using namespace lld::elf;
24
25
namespace {
26
class ARM final : public TargetInfo {
27
public:
28
  ARM();
29
  RelExpr getRelExpr(uint32_t Type, const SymbolBody &S, const InputFile &File,
30
                     const uint8_t *Loc) const override;
31
  bool isPicRel(uint32_t Type) const override;
32
  uint32_t getDynRel(uint32_t Type) const override;
33
  int64_t getImplicitAddend(const uint8_t *Buf, uint32_t Type) const override;
34
  void writeGotPlt(uint8_t *Buf, const SymbolBody &S) const override;
35
  void writeIgotPlt(uint8_t *Buf, const SymbolBody &S) const override;
36
  void writePltHeader(uint8_t *Buf) const override;
37
  void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr,
38
                int32_t Index, unsigned RelOff) const override;
39
  void addPltSymbols(InputSectionBase *IS, uint64_t Off) const override;
40
  void addPltHeaderSymbols(InputSectionBase *ISD) const override;
41
  bool needsThunk(RelExpr Expr, uint32_t RelocType, const InputFile *File,
42
                  const SymbolBody &S) const override;
43
  bool inBranchRange(uint32_t RelocType, uint64_t Src,
44
                     uint64_t Dst) const override;
45
  void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const override;
46
};
47
} // namespace
48
49
82
ARM::ARM() {
50
82
  CopyRel = R_ARM_COPY;
51
82
  RelativeRel = R_ARM_RELATIVE;
52
82
  IRelativeRel = R_ARM_IRELATIVE;
53
82
  GotRel = R_ARM_GLOB_DAT;
54
82
  PltRel = R_ARM_JUMP_SLOT;
55
82
  TlsGotRel = R_ARM_TLS_TPOFF32;
56
82
  TlsModuleIndexRel = R_ARM_TLS_DTPMOD32;
57
82
  TlsOffsetRel = R_ARM_TLS_DTPOFF32;
58
82
  GotEntrySize = 4;
59
82
  GotPltEntrySize = 4;
60
82
  PltEntrySize = 16;
61
82
  PltHeaderSize = 20;
62
82
  TrapInstr = 0xd4d4d4d4;
63
82
  // ARM uses Variant 1 TLS
64
82
  TcbSize = 8;
65
82
  NeedsThunks = true;
66
82
}
67
68
RelExpr ARM::getRelExpr(uint32_t Type, const SymbolBody &S,
69
330
                        const InputFile &File, const uint8_t *Loc) const {
70
330
  switch (Type) {
71
37
  default:
72
37
    return R_ABS;
73
4
  case R_ARM_THM_JUMP11:
74
4
    return R_PC;
75
211
  case R_ARM_CALL:
76
211
  case R_ARM_JUMP24:
77
211
  case R_ARM_PC24:
78
211
  case R_ARM_PLT32:
79
211
  case R_ARM_PREL31:
80
211
  case R_ARM_THM_JUMP19:
81
211
  case R_ARM_THM_JUMP24:
82
211
  case R_ARM_THM_CALL:
83
211
    return R_PLT_PC;
84
3
  case R_ARM_GOTOFF32:
85
3
    // (S + A) - GOT_ORG
86
3
    return R_GOTREL;
87
5
  case R_ARM_GOT_BREL:
88
5
    // GOT(S) + A - GOT_ORG
89
5
    return R_GOT_OFF;
90
6
  case R_ARM_GOT_PREL:
91
6
  case R_ARM_TLS_IE32:
92
6
    // GOT(S) + A - P
93
6
    return R_GOT_PC;
94
4
  case R_ARM_SBREL32:
95
4
    return R_ARM_SBREL;
96
4
  case R_ARM_TARGET1:
97
4
    return Config->Target1Rel ? 
R_PC2
:
R_ABS2
;
98
4
  case R_ARM_TARGET2:
99
4
    if (Config->Target2 == Target2Policy::Rel)
100
1
      return R_PC;
101
3
    
if (3
Config->Target2 == Target2Policy::Abs3
)
102
1
      return R_ABS;
103
2
    return R_GOT_PC;
104
13
  case R_ARM_TLS_GD32:
105
13
    return R_TLSGD_PC;
106
2
  case R_ARM_TLS_LDM32:
107
2
    return R_TLSLD_PC;
108
0
  case R_ARM_BASE_PREL:
109
0
    // B(S) + A - P
110
0
    // FIXME: currently B(S) assumed to be .got, this may not hold for all
111
0
    // platforms.
112
0
    return R_GOTONLY_PC;
113
27
  case R_ARM_MOVW_PREL_NC:
114
27
  case R_ARM_MOVT_PREL:
115
27
  case R_ARM_REL32:
116
27
  case R_ARM_THM_MOVW_PREL_NC:
117
27
  case R_ARM_THM_MOVT_PREL:
118
27
    return R_PC;
119
7
  case R_ARM_NONE:
120
7
    return R_NONE;
121
3
  case R_ARM_TLS_LE32:
122
3
    return R_TLS;
123
0
  }
124
0
}
125
126
1
bool ARM::isPicRel(uint32_t Type) const {
127
0
  return (Type == R_ARM_TARGET1 && !Config->Target1Rel) ||
128
1
         (Type == R_ARM_ABS32);
129
1
}
130
131
1
uint32_t ARM::getDynRel(uint32_t Type) const {
132
1
  if (
Type == R_ARM_TARGET1 && 1
!Config->Target1Rel0
)
133
0
    return R_ARM_ABS32;
134
1
  
if (1
Type == R_ARM_ABS321
)
135
1
    return Type;
136
0
  // Keep it going with a dummy value so that we can find more reloc errors.
137
0
  return R_ARM_ABS32;
138
0
}
139
140
27
void ARM::writeGotPlt(uint8_t *Buf, const SymbolBody &) const {
141
27
  write32le(Buf, InX::Plt->getVA());
142
27
}
143
144
6
void ARM::writeIgotPlt(uint8_t *Buf, const SymbolBody &S) const {
145
6
  // An ARM entry is the address of the ifunc resolver function.
146
6
  write32le(Buf, S.getVA());
147
6
}
148
149
13
void ARM::writePltHeader(uint8_t *Buf) const {
150
13
  const uint8_t PltData[] = {
151
13
      0x04, 0xe0, 0x2d, 0xe5, //     str lr, [sp,#-4]!
152
13
      0x04, 0xe0, 0x9f, 0xe5, //     ldr lr, L2
153
13
      0x0e, 0xe0, 0x8f, 0xe0, // L1: add lr, pc, lr
154
13
      0x08, 0xf0, 0xbe, 0xe5, //     ldr pc, [lr, #8]
155
13
      0x00, 0x00, 0x00, 0x00, // L2: .word   &(.got.plt) - L1 - 8
156
13
  };
157
13
  memcpy(Buf, PltData, sizeof(PltData));
158
13
  uint64_t GotPlt = InX::GotPlt->getVA();
159
13
  uint64_t L1 = InX::Plt->getVA() + 8;
160
13
  write32le(Buf + 16, GotPlt - L1 - 8);
161
13
}
162
163
13
void ARM::addPltHeaderSymbols(InputSectionBase *ISD) const {
164
13
  auto *IS = cast<InputSection>(ISD);
165
13
  addSyntheticLocal("$a", STT_NOTYPE, 0, 0, IS);
166
13
  addSyntheticLocal("$d", STT_NOTYPE, 16, 0, IS);
167
13
}
168
169
void ARM::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr,
170
                   uint64_t PltEntryAddr, int32_t Index,
171
33
                   unsigned RelOff) const {
172
33
  // FIXME: Using simple code sequence with simple relocations.
173
33
  // There is a more optimal sequence but it requires support for the group
174
33
  // relocations. See ELF for the ARM Architecture Appendix A.3
175
33
  const uint8_t PltData[] = {
176
33
      0x04, 0xc0, 0x9f, 0xe5, //     ldr ip, L2
177
33
      0x0f, 0xc0, 0x8c, 0xe0, // L1: add ip, ip, pc
178
33
      0x00, 0xf0, 0x9c, 0xe5, //     ldr pc, [ip]
179
33
      0x00, 0x00, 0x00, 0x00, // L2: .word   Offset(&(.plt.got) - L1 - 8
180
33
  };
181
33
  memcpy(Buf, PltData, sizeof(PltData));
182
33
  uint64_t L1 = PltEntryAddr + 4;
183
33
  write32le(Buf + 12, GotPltEntryAddr - L1 - 8);
184
33
}
185
186
33
void ARM::addPltSymbols(InputSectionBase *ISD, uint64_t Off) const {
187
33
  auto *IS = cast<InputSection>(ISD);
188
33
  addSyntheticLocal("$a", STT_NOTYPE, Off, 0, IS);
189
33
  addSyntheticLocal("$d", STT_NOTYPE, Off + 12, 0, IS);
190
33
}
191
192
bool ARM::needsThunk(RelExpr Expr, uint32_t RelocType, const InputFile *File,
193
291
                     const SymbolBody &S) const {
194
291
  // If S is an undefined weak symbol in an executable we don't need a Thunk.
195
291
  // In a DSO calls to undefined symbols, including weak ones get PLT entries
196
291
  // which may need a thunk.
197
291
  if (
S.isUndefWeak() && 291
!Config->Shared16
)
198
15
    return false;
199
276
  // A state change from ARM to Thumb and vice versa must go through an
200
276
  // interworking thunk if the relocation type is not R_ARM_CALL or
201
276
  // R_ARM_THM_CALL.
202
276
  switch (RelocType) {
203
51
  case R_ARM_PC24:
204
51
  case R_ARM_PLT32:
205
51
  case R_ARM_JUMP24:
206
51
    // Source is ARM, all PLT entries are ARM so no interworking required.
207
51
    // Otherwise we need to interwork if Symbol has bit 0 set (Thumb).
208
51
    if (
Expr == R_PC && 51
((S.getVA() & 1) == 1)33
)
209
11
      return true;
210
40
    break;
211
33
  case R_ARM_THM_JUMP19:
212
33
  case R_ARM_THM_JUMP24:
213
33
    // Source is Thumb, all PLT entries are ARM so interworking is required.
214
33
    // Otherwise we need to interwork if Symbol has bit 0 clear (ARM).
215
33
    if (
Expr == R_PLT_PC || 33
((S.getVA() & 1) == 0)24
)
216
25
      return true;
217
8
    break;
218
240
  }
219
240
  return false;
220
240
}
221
222
0
bool ARM::inBranchRange(uint32_t RelocType, uint64_t Src, uint64_t Dst) const {
223
0
  uint64_t Range;
224
0
  uint64_t InstrSize;
225
0
226
0
  switch (RelocType) {
227
0
  case R_ARM_PC24:
228
0
  case R_ARM_PLT32:
229
0
  case R_ARM_JUMP24:
230
0
  case R_ARM_CALL:
231
0
    Range = 0x2000000;
232
0
    InstrSize = 4;
233
0
    break;
234
0
  case R_ARM_THM_JUMP19:
235
0
    Range = 0x100000;
236
0
    InstrSize = 2;
237
0
    break;
238
0
  case R_ARM_THM_JUMP24:
239
0
  case R_ARM_THM_CALL:
240
0
    Range = 0x1000000;
241
0
    InstrSize = 2;
242
0
    break;
243
0
  default:
244
0
    return true;
245
0
  }
246
0
  // PC at Src is 2 instructions ahead, immediate of branch is signed
247
0
  
if (0
Src > Dst0
)
248
0
    Range -= 2 * InstrSize;
249
0
  else
250
0
    Range += InstrSize;
251
0
252
0
  if ((Dst & 0x1) == 0)
253
0
    // Destination is ARM, if ARM caller then Src is already 4-byte aligned.
254
0
    // If Thumb Caller (BLX) the Src address has bottom 2 bits cleared to ensure
255
0
    // destination will be 4 byte aligned.
256
0
    Src &= ~0x3;
257
0
  else
258
0
    // Bit 0 == 1 denotes Thumb state, it is not part of the range
259
0
    Dst &= ~0x1;
260
0
261
0
  uint64_t Distance = (Src > Dst) ? 
Src - Dst0
:
Dst - Src0
;
262
0
  return Distance <= Range;
263
0
}
264
265
418
void ARM::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const {
266
418
  switch (Type) {
267
70
  case R_ARM_ABS32:
268
70
  case R_ARM_BASE_PREL:
269
70
  case R_ARM_GLOB_DAT:
270
70
  case R_ARM_GOTOFF32:
271
70
  case R_ARM_GOT_BREL:
272
70
  case R_ARM_GOT_PREL:
273
70
  case R_ARM_REL32:
274
70
  case R_ARM_RELATIVE:
275
70
  case R_ARM_SBREL32:
276
70
  case R_ARM_TARGET1:
277
70
  case R_ARM_TARGET2:
278
70
  case R_ARM_TLS_GD32:
279
70
  case R_ARM_TLS_IE32:
280
70
  case R_ARM_TLS_LDM32:
281
70
  case R_ARM_TLS_LDO32:
282
70
  case R_ARM_TLS_LE32:
283
70
  case R_ARM_TLS_TPOFF32:
284
70
  case R_ARM_TLS_DTPOFF32:
285
70
    write32le(Loc, Val);
286
70
    break;
287
6
  case R_ARM_TLS_DTPMOD32:
288
6
    write32le(Loc, 1);
289
6
    break;
290
82
  case R_ARM_PREL31:
291
82
    checkInt<31>(Loc, Val, Type);
292
82
    write32le(Loc, (read32le(Loc) & 0x80000000) | (Val & ~0x80000000));
293
82
    break;
294
53
  case R_ARM_CALL:
295
53
    // R_ARM_CALL is used for BL and BLX instructions, depending on the
296
53
    // value of bit 0 of Val, we must select a BL or BLX instruction
297
53
    if (
Val & 153
) {
298
16
      // If bit 0 of Val is 1 the target is Thumb, we must select a BLX.
299
16
      // The BLX encoding is 0xfa:H:imm24 where Val = imm24:H:'1'
300
16
      checkInt<26>(Loc, Val, Type);
301
16
      write32le(Loc, 0xfa000000 |                    // opcode
302
16
                         ((Val & 2) << 23) |         // H
303
16
                         ((Val >> 2) & 0x00ffffff)); // imm24
304
16
      break;
305
16
    }
306
37
    
if (37
(read32le(Loc) & 0xfe000000) == 0xfa00000037
)
307
37
      // BLX (always unconditional) instruction to an ARM Target, select an
308
37
      // unconditional BL.
309
4
      write32le(Loc, 0xeb000000 | (read32le(Loc) & 0x00ffffff));
310
37
    // fall through as BL encoding is shared with B
311
37
    LLVM_FALLTHROUGH;
312
75
  case R_ARM_JUMP24:
313
75
  case R_ARM_PC24:
314
75
  case R_ARM_PLT32:
315
75
    checkInt<26>(Loc, Val, Type);
316
75
    write32le(Loc, (read32le(Loc) & ~0x00ffffff) | ((Val >> 2) & 0x00ffffff));
317
75
    break;
318
4
  case R_ARM_THM_JUMP11:
319
4
    checkInt<12>(Loc, Val, Type);
320
4
    write16le(Loc, (read32le(Loc) & 0xf800) | ((Val >> 1) & 0x07ff));
321
4
    break;
322
14
  case R_ARM_THM_JUMP19:
323
14
    // Encoding T3: Val = S:J2:J1:imm6:imm11:0
324
14
    checkInt<21>(Loc, Val, Type);
325
14
    write16le(Loc,
326
14
              (read16le(Loc) & 0xfbc0) |   // opcode cond
327
14
                  ((Val >> 10) & 0x0400) | // S
328
14
                  ((Val >> 12) & 0x003f)); // imm6
329
14
    write16le(Loc + 2,
330
14
              0x8000 |                    // opcode
331
14
                  ((Val >> 8) & 0x0800) | // J2
332
14
                  ((Val >> 5) & 0x2000) | // J1
333
14
                  ((Val >> 1) & 0x07ff)); // imm11
334
14
    break;
335
28
  case R_ARM_THM_CALL:
336
28
    // R_ARM_THM_CALL is used for BL and BLX instructions, depending on the
337
28
    // value of bit 0 of Val, we must select a BL or BLX instruction
338
28
    if (
(Val & 1) == 028
) {
339
15
      // Ensure BLX destination is 4-byte aligned. As BLX instruction may
340
15
      // only be two byte aligned. This must be done before overflow check
341
15
      Val = alignTo(Val, 4);
342
15
    }
343
28
    // Bit 12 is 0 for BLX, 1 for BL
344
28
    write16le(Loc + 2, (read16le(Loc + 2) & ~0x1000) | (Val & 1) << 12);
345
28
    // Fall through as rest of encoding is the same as B.W
346
28
    LLVM_FALLTHROUGH;
347
51
  case R_ARM_THM_JUMP24:
348
51
    // Encoding B  T4, BL T1, BLX T2: Val = S:I1:I2:imm10:imm11:0
349
51
    // FIXME: Use of I1 and I2 require v6T2ops
350
51
    checkInt<25>(Loc, Val, Type);
351
51
    write16le(Loc,
352
51
              0xf000 |                     // opcode
353
51
                  ((Val >> 14) & 0x0400) | // S
354
51
                  ((Val >> 12) & 0x03ff)); // imm10
355
51
    write16le(Loc + 2,
356
51
              (read16le(Loc + 2) & 0xd000) |                  // opcode
357
51
                  (((~(Val >> 10)) ^ (Val >> 11)) & 0x2000) | // J1
358
51
                  (((~(Val >> 11)) ^ (Val >> 13)) & 0x0800) | // J2
359
51
                  ((Val >> 1) & 0x07ff));                     // imm11
360
51
    break;
361
23
  case R_ARM_MOVW_ABS_NC:
362
23
  case R_ARM_MOVW_PREL_NC:
363
23
    write32le(Loc, (read32le(Loc) & ~0x000f0fff) | ((Val & 0xf000) << 4) |
364
23
                       (Val & 0x0fff));
365
23
    break;
366
23
  case R_ARM_MOVT_ABS:
367
23
  case R_ARM_MOVT_PREL:
368
23
    checkInt<32>(Loc, Val, Type);
369
23
    write32le(Loc, (read32le(Loc) & ~0x000f0fff) |
370
23
                       (((Val >> 16) & 0xf000) << 4) | ((Val >> 16) & 0xfff));
371
23
    break;
372
27
  case R_ARM_THM_MOVT_ABS:
373
27
  case R_ARM_THM_MOVT_PREL:
374
27
    // Encoding T1: A = imm4:i:imm3:imm8
375
27
    checkInt<32>(Loc, Val, Type);
376
27
    write16le(Loc,
377
27
              0xf2c0 |                     // opcode
378
27
                  ((Val >> 17) & 0x0400) | // i
379
27
                  ((Val >> 28) & 0x000f)); // imm4
380
27
    write16le(Loc + 2,
381
27
              (read16le(Loc + 2) & 0x8f00) | // opcode
382
27
                  ((Val >> 12) & 0x7000) |   // imm3
383
27
                  ((Val >> 16) & 0x00ff));   // imm8
384
27
    break;
385
27
  case R_ARM_THM_MOVW_ABS_NC:
386
27
  case R_ARM_THM_MOVW_PREL_NC:
387
27
    // Encoding T3: A = imm4:i:imm3:imm8
388
27
    write16le(Loc,
389
27
              0xf240 |                     // opcode
390
27
                  ((Val >> 1) & 0x0400) |  // i
391
27
                  ((Val >> 12) & 0x000f)); // imm4
392
27
    write16le(Loc + 2,
393
27
              (read16le(Loc + 2) & 0x8f00) | // opcode
394
27
                  ((Val << 4) & 0x7000) |    // imm3
395
27
                  (Val & 0x00ff));           // imm8
396
27
    break;
397
0
  default:
398
0
    error(getErrorLocation(Loc) + "unrecognized reloc " + Twine(Type));
399
418
  }
400
418
}
401
402
337
int64_t ARM::getImplicitAddend(const uint8_t *Buf, uint32_t Type) const {
403
337
  switch (Type) {
404
4
  default:
405
4
    return 0;
406
52
  case R_ARM_ABS32:
407
52
  case R_ARM_BASE_PREL:
408
52
  case R_ARM_GOTOFF32:
409
52
  case R_ARM_GOT_BREL:
410
52
  case R_ARM_GOT_PREL:
411
52
  case R_ARM_REL32:
412
52
  case R_ARM_TARGET1:
413
52
  case R_ARM_TARGET2:
414
52
  case R_ARM_TLS_GD32:
415
52
  case R_ARM_TLS_LDM32:
416
52
  case R_ARM_TLS_LDO32:
417
52
  case R_ARM_TLS_IE32:
418
52
  case R_ARM_TLS_LE32:
419
52
    return SignExtend64<32>(read32le(Buf));
420
71
  case R_ARM_PREL31:
421
71
    return SignExtend64<31>(read32le(Buf));
422
91
  case R_ARM_CALL:
423
91
  case R_ARM_JUMP24:
424
91
  case R_ARM_PC24:
425
91
  case R_ARM_PLT32:
426
91
    return SignExtend64<26>(read32le(Buf) << 2);
427
4
  case R_ARM_THM_JUMP11:
428
4
    return SignExtend64<12>(read16le(Buf) << 1);
429
14
  case R_ARM_THM_JUMP19: {
430
14
    // Encoding T3: A = S:J2:J1:imm10:imm6:0
431
14
    uint16_t Hi = read16le(Buf);
432
14
    uint16_t Lo = read16le(Buf + 2);
433
14
    return SignExtend64<20>(((Hi & 0x0400) << 10) | // S
434
14
                            ((Lo & 0x0800) << 8) |  // J2
435
14
                            ((Lo & 0x2000) << 5) |  // J1
436
14
                            ((Hi & 0x003f) << 12) | // imm6
437
14
                            ((Lo & 0x07ff) << 1));  // imm11:0
438
91
  }
439
51
  case R_ARM_THM_CALL:
440
51
  case R_ARM_THM_JUMP24: {
441
51
    // Encoding B T4, BL T1, BLX T2: A = S:I1:I2:imm10:imm11:0
442
51
    // I1 = NOT(J1 EOR S), I2 = NOT(J2 EOR S)
443
51
    // FIXME: I1 and I2 require v6T2ops
444
51
    uint16_t Hi = read16le(Buf);
445
51
    uint16_t Lo = read16le(Buf + 2);
446
51
    return SignExtend64<24>(((Hi & 0x0400) << 14) |                    // S
447
51
                            (~((Lo ^ (Hi << 3)) << 10) & 0x00800000) | // I1
448
51
                            (~((Lo ^ (Hi << 1)) << 11) & 0x00400000) | // I2
449
51
                            ((Hi & 0x003ff) << 12) |                   // imm0
450
51
                            ((Lo & 0x007ff) << 1)); // imm11:0
451
51
  }
452
51
  // ELF for the ARM Architecture 4.6.1.1 the implicit addend for MOVW and
453
51
  // MOVT is in the range -32768 <= A < 32768
454
28
  case R_ARM_MOVW_ABS_NC:
455
28
  case R_ARM_MOVT_ABS:
456
28
  case R_ARM_MOVW_PREL_NC:
457
28
  case R_ARM_MOVT_PREL: {
458
28
    uint64_t Val = read32le(Buf) & 0x000f0fff;
459
28
    return SignExtend64<16>(((Val & 0x000f0000) >> 4) | (Val & 0x00fff));
460
28
  }
461
22
  case R_ARM_THM_MOVW_ABS_NC:
462
22
  case R_ARM_THM_MOVT_ABS:
463
22
  case R_ARM_THM_MOVW_PREL_NC:
464
22
  case R_ARM_THM_MOVT_PREL: {
465
22
    // Encoding T3: A = imm4:i:imm3:imm8
466
22
    uint16_t Hi = read16le(Buf);
467
22
    uint16_t Lo = read16le(Buf + 2);
468
22
    return SignExtend64<16>(((Hi & 0x000f) << 12) | // imm4
469
22
                            ((Hi & 0x0400) << 1) |  // i
470
22
                            ((Lo & 0x7000) >> 4) |  // imm3
471
22
                            (Lo & 0x00ff));         // imm8
472
0
  }
473
337
  }
474
337
}
475
476
82
TargetInfo *elf::getARMTargetInfo() {
477
82
  static ARM Target;
478
82
  return &Target;
479
82
}