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/ARMBaseInfo.h" 12 #include "MCTargetDesc/ARMFixupKinds.h" 13 #include "MCTargetDesc/ARMAddressingModes.h" 14 #include "llvm/ADT/Twine.h" 15 #include "llvm/MC/MCAssembler.h" 16 #include "llvm/MC/MCDirectives.h" 17 #include "llvm/MC/MCELFObjectWriter.h" 18 #include "llvm/MC/MCExpr.h" 19 #include "llvm/MC/MCMachObjectWriter.h" 20 #include "llvm/MC/MCObjectWriter.h" 21 #include "llvm/MC/MCSectionELF.h" 22 #include "llvm/MC/MCSectionMachO.h" 23 #include "llvm/MC/MCAsmBackend.h" 24 #include "llvm/MC/MCSubtargetInfo.h" 25 #include "llvm/Object/MachOFormat.h" 26 #include "llvm/Support/ELF.h" 27 #include "llvm/Support/ErrorHandling.h" 28 #include "llvm/Support/raw_ostream.h" 29 using namespace llvm; 30 31 namespace { 32 class ARMELFObjectWriter : public MCELFObjectTargetWriter { 33 public: 34 ARMELFObjectWriter(uint8_t OSABI) 35 : MCELFObjectTargetWriter(/*Is64Bit*/ false, OSABI, ELF::EM_ARM, 36 /*HasRelocationAddend*/ false) {} 37 }; 38 39 class ARMAsmBackend : public MCAsmBackend { 40 const MCSubtargetInfo* STI; 41 bool isThumbMode; // Currently emitting Thumb code. 42 public: 43 ARMAsmBackend(const Target &T, const StringRef TT) 44 : MCAsmBackend(), STI(ARM_MC::createARMMCSubtargetInfo(TT, "", "")), 45 isThumbMode(TT.startswith("thumb")) {} 46 47 ~ARMAsmBackend() { 48 delete STI; 49 } 50 51 unsigned getNumFixupKinds() const { return ARM::NumTargetFixupKinds; } 52 53 bool hasNOP() const { 54 return (STI->getFeatureBits() & ARM::HasV6T2Ops) != 0; 55 } 56 57 const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const { 58 const static MCFixupKindInfo Infos[ARM::NumTargetFixupKinds] = { 59 // This table *must* be in the order that the fixup_* kinds are defined in 60 // ARMFixupKinds.h. 61 // 62 // Name Offset (bits) Size (bits) Flags 63 { "fixup_arm_ldst_pcrel_12", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, 64 { "fixup_t2_ldst_pcrel_12", 0, 32, MCFixupKindInfo::FKF_IsPCRel | 65 MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, 66 { "fixup_arm_pcrel_10_unscaled", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, 67 { "fixup_arm_pcrel_10", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, 68 { "fixup_t2_pcrel_10", 0, 32, MCFixupKindInfo::FKF_IsPCRel | 69 MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, 70 { "fixup_thumb_adr_pcrel_10",0, 8, MCFixupKindInfo::FKF_IsPCRel | 71 MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, 72 { "fixup_arm_adr_pcrel_12", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, 73 { "fixup_t2_adr_pcrel_12", 0, 32, MCFixupKindInfo::FKF_IsPCRel | 74 MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, 75 { "fixup_arm_condbranch", 0, 24, MCFixupKindInfo::FKF_IsPCRel }, 76 { "fixup_arm_uncondbranch", 0, 24, MCFixupKindInfo::FKF_IsPCRel }, 77 { "fixup_t2_condbranch", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, 78 { "fixup_t2_uncondbranch", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, 79 { "fixup_arm_thumb_br", 0, 16, MCFixupKindInfo::FKF_IsPCRel }, 80 { "fixup_arm_thumb_bl", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, 81 { "fixup_arm_thumb_blx", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, 82 { "fixup_arm_thumb_cb", 0, 16, MCFixupKindInfo::FKF_IsPCRel }, 83 { "fixup_arm_thumb_cp", 0, 8, MCFixupKindInfo::FKF_IsPCRel }, 84 { "fixup_arm_thumb_bcc", 0, 8, MCFixupKindInfo::FKF_IsPCRel }, 85 // movw / movt: 16-bits immediate but scattered into two chunks 0 - 12, 16 - 19. 86 { "fixup_arm_movt_hi16", 0, 20, 0 }, 87 { "fixup_arm_movw_lo16", 0, 20, 0 }, 88 { "fixup_t2_movt_hi16", 0, 20, 0 }, 89 { "fixup_t2_movw_lo16", 0, 20, 0 }, 90 { "fixup_arm_movt_hi16_pcrel", 0, 20, MCFixupKindInfo::FKF_IsPCRel }, 91 { "fixup_arm_movw_lo16_pcrel", 0, 20, MCFixupKindInfo::FKF_IsPCRel }, 92 { "fixup_t2_movt_hi16_pcrel", 0, 20, MCFixupKindInfo::FKF_IsPCRel }, 93 { "fixup_t2_movw_lo16_pcrel", 0, 20, MCFixupKindInfo::FKF_IsPCRel }, 94 }; 95 96 if (Kind < FirstTargetFixupKind) 97 return MCAsmBackend::getFixupKindInfo(Kind); 98 99 assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() && 100 "Invalid kind!"); 101 return Infos[Kind - FirstTargetFixupKind]; 102 } 103 104 bool MayNeedRelaxation(const MCInst &Inst) const; 105 106 bool fixupNeedsRelaxation(const MCFixup &Fixup, 107 uint64_t Value, 108 const MCInstFragment *DF, 109 const MCAsmLayout &Layout) const; 110 111 void RelaxInstruction(const MCInst &Inst, MCInst &Res) const; 112 113 bool WriteNopData(uint64_t Count, MCObjectWriter *OW) const; 114 115 void HandleAssemblerFlag(MCAssemblerFlag Flag) { 116 switch (Flag) { 117 default: break; 118 case MCAF_Code16: 119 setIsThumb(true); 120 break; 121 case MCAF_Code32: 122 setIsThumb(false); 123 break; 124 } 125 } 126 127 unsigned getPointerSize() const { return 4; } 128 bool isThumb() const { return isThumbMode; } 129 void setIsThumb(bool it) { isThumbMode = it; } 130 }; 131 } // end anonymous namespace 132 133 static unsigned getRelaxedOpcode(unsigned Op) { 134 switch (Op) { 135 default: return Op; 136 case ARM::tBcc: return ARM::t2Bcc; 137 } 138 } 139 140 bool ARMAsmBackend::MayNeedRelaxation(const MCInst &Inst) const { 141 if (getRelaxedOpcode(Inst.getOpcode()) != Inst.getOpcode()) 142 return true; 143 return false; 144 } 145 146 bool ARMAsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup, 147 uint64_t Value, 148 const MCInstFragment *DF, 149 const MCAsmLayout &Layout) const { 150 // Relaxing tBcc to t2Bcc. tBcc has a signed 9-bit displacement with the 151 // low bit being an implied zero. There's an implied +4 offset for the 152 // branch, so we adjust the other way here to determine what's 153 // encodable. 154 // 155 // Relax if the value is too big for a (signed) i8. 156 int64_t Offset = int64_t(Value) - 4; 157 return Offset > 254 || Offset < -256; 158 } 159 160 void ARMAsmBackend::RelaxInstruction(const MCInst &Inst, MCInst &Res) const { 161 unsigned RelaxedOp = getRelaxedOpcode(Inst.getOpcode()); 162 163 // Sanity check w/ diagnostic if we get here w/ a bogus instruction. 164 if (RelaxedOp == Inst.getOpcode()) { 165 SmallString<256> Tmp; 166 raw_svector_ostream OS(Tmp); 167 Inst.dump_pretty(OS); 168 OS << "\n"; 169 report_fatal_error("unexpected instruction to relax: " + OS.str()); 170 } 171 172 // The instructions we're relaxing have (so far) the same operands. 173 // We just need to update to the proper opcode. 174 Res = Inst; 175 Res.setOpcode(RelaxedOp); 176 } 177 178 bool ARMAsmBackend::WriteNopData(uint64_t Count, MCObjectWriter *OW) const { 179 const uint16_t Thumb1_16bitNopEncoding = 0x46c0; // using MOV r8,r8 180 const uint16_t Thumb2_16bitNopEncoding = 0xbf00; // NOP 181 const uint32_t ARMv4_NopEncoding = 0xe1a0000; // using MOV r0,r0 182 const uint32_t ARMv6T2_NopEncoding = 0xe320f000; // NOP 183 if (isThumb()) { 184 const uint16_t nopEncoding = hasNOP() ? Thumb2_16bitNopEncoding 185 : Thumb1_16bitNopEncoding; 186 uint64_t NumNops = Count / 2; 187 for (uint64_t i = 0; i != NumNops; ++i) 188 OW->Write16(nopEncoding); 189 if (Count & 1) 190 OW->Write8(0); 191 return true; 192 } 193 // ARM mode 194 const uint32_t nopEncoding = hasNOP() ? ARMv6T2_NopEncoding 195 : ARMv4_NopEncoding; 196 uint64_t NumNops = Count / 4; 197 for (uint64_t i = 0; i != NumNops; ++i) 198 OW->Write32(nopEncoding); 199 // FIXME: should this function return false when unable to write exactly 200 // 'Count' bytes with NOP encodings? 201 switch (Count % 4) { 202 default: break; // No leftover bytes to write 203 case 1: OW->Write8(0); break; 204 case 2: OW->Write16(0); break; 205 case 3: OW->Write16(0); OW->Write8(0xa0); break; 206 } 207 208 return true; 209 } 210 211 static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) { 212 switch (Kind) { 213 default: 214 llvm_unreachable("Unknown fixup kind!"); 215 case FK_Data_1: 216 case FK_Data_2: 217 case FK_Data_4: 218 return Value; 219 case ARM::fixup_arm_movt_hi16: 220 Value >>= 16; 221 // Fallthrough 222 case ARM::fixup_arm_movw_lo16: 223 case ARM::fixup_arm_movt_hi16_pcrel: 224 case ARM::fixup_arm_movw_lo16_pcrel: { 225 unsigned Hi4 = (Value & 0xF000) >> 12; 226 unsigned Lo12 = Value & 0x0FFF; 227 // inst{19-16} = Hi4; 228 // inst{11-0} = Lo12; 229 Value = (Hi4 << 16) | (Lo12); 230 return Value; 231 } 232 case ARM::fixup_t2_movt_hi16: 233 Value >>= 16; 234 // Fallthrough 235 case ARM::fixup_t2_movw_lo16: 236 case ARM::fixup_t2_movt_hi16_pcrel: //FIXME: Shouldn't this be shifted like 237 // the other hi16 fixup? 238 case ARM::fixup_t2_movw_lo16_pcrel: { 239 unsigned Hi4 = (Value & 0xF000) >> 12; 240 unsigned i = (Value & 0x800) >> 11; 241 unsigned Mid3 = (Value & 0x700) >> 8; 242 unsigned Lo8 = Value & 0x0FF; 243 // inst{19-16} = Hi4; 244 // inst{26} = i; 245 // inst{14-12} = Mid3; 246 // inst{7-0} = Lo8; 247 Value = (Hi4 << 16) | (i << 26) | (Mid3 << 12) | (Lo8); 248 uint64_t swapped = (Value & 0xFFFF0000) >> 16; 249 swapped |= (Value & 0x0000FFFF) << 16; 250 return swapped; 251 } 252 case ARM::fixup_arm_ldst_pcrel_12: 253 // ARM PC-relative values are offset by 8. 254 Value -= 4; 255 // FALLTHROUGH 256 case ARM::fixup_t2_ldst_pcrel_12: { 257 // Offset by 4, adjusted by two due to the half-word ordering of thumb. 258 Value -= 4; 259 bool isAdd = true; 260 if ((int64_t)Value < 0) { 261 Value = -Value; 262 isAdd = false; 263 } 264 assert ((Value < 4096) && "Out of range pc-relative fixup value!"); 265 Value |= isAdd << 23; 266 267 // Same addressing mode as fixup_arm_pcrel_10, 268 // but with 16-bit halfwords swapped. 269 if (Kind == ARM::fixup_t2_ldst_pcrel_12) { 270 uint64_t swapped = (Value & 0xFFFF0000) >> 16; 271 swapped |= (Value & 0x0000FFFF) << 16; 272 return swapped; 273 } 274 275 return Value; 276 } 277 case ARM::fixup_thumb_adr_pcrel_10: 278 return ((Value - 4) >> 2) & 0xff; 279 case ARM::fixup_arm_adr_pcrel_12: { 280 // ARM PC-relative values are offset by 8. 281 Value -= 8; 282 unsigned opc = 4; // bits {24-21}. Default to add: 0b0100 283 if ((int64_t)Value < 0) { 284 Value = -Value; 285 opc = 2; // 0b0010 286 } 287 assert(ARM_AM::getSOImmVal(Value) != -1 && 288 "Out of range pc-relative fixup value!"); 289 // Encode the immediate and shift the opcode into place. 290 return ARM_AM::getSOImmVal(Value) | (opc << 21); 291 } 292 293 case ARM::fixup_t2_adr_pcrel_12: { 294 Value -= 4; 295 unsigned opc = 0; 296 if ((int64_t)Value < 0) { 297 Value = -Value; 298 opc = 5; 299 } 300 301 uint32_t out = (opc << 21); 302 out |= (Value & 0x800) << 15; 303 out |= (Value & 0x700) << 4; 304 out |= (Value & 0x0FF); 305 306 uint64_t swapped = (out & 0xFFFF0000) >> 16; 307 swapped |= (out & 0x0000FFFF) << 16; 308 return swapped; 309 } 310 311 case ARM::fixup_arm_condbranch: 312 case ARM::fixup_arm_uncondbranch: 313 // These values don't encode the low two bits since they're always zero. 314 // Offset by 8 just as above. 315 return 0xffffff & ((Value - 8) >> 2); 316 case ARM::fixup_t2_uncondbranch: { 317 Value = Value - 4; 318 Value >>= 1; // Low bit is not encoded. 319 320 uint32_t out = 0; 321 bool I = Value & 0x800000; 322 bool J1 = Value & 0x400000; 323 bool J2 = Value & 0x200000; 324 J1 ^= I; 325 J2 ^= I; 326 327 out |= I << 26; // S bit 328 out |= !J1 << 13; // J1 bit 329 out |= !J2 << 11; // J2 bit 330 out |= (Value & 0x1FF800) << 5; // imm6 field 331 out |= (Value & 0x0007FF); // imm11 field 332 333 uint64_t swapped = (out & 0xFFFF0000) >> 16; 334 swapped |= (out & 0x0000FFFF) << 16; 335 return swapped; 336 } 337 case ARM::fixup_t2_condbranch: { 338 Value = Value - 4; 339 Value >>= 1; // Low bit is not encoded. 340 341 uint64_t out = 0; 342 out |= (Value & 0x80000) << 7; // S bit 343 out |= (Value & 0x40000) >> 7; // J2 bit 344 out |= (Value & 0x20000) >> 4; // J1 bit 345 out |= (Value & 0x1F800) << 5; // imm6 field 346 out |= (Value & 0x007FF); // imm11 field 347 348 uint32_t swapped = (out & 0xFFFF0000) >> 16; 349 swapped |= (out & 0x0000FFFF) << 16; 350 return swapped; 351 } 352 case ARM::fixup_arm_thumb_bl: { 353 // The value doesn't encode the low bit (always zero) and is offset by 354 // four. The value is encoded into disjoint bit positions in the destination 355 // opcode. x = unchanged, I = immediate value bit, S = sign extension bit 356 // 357 // BL: xxxxxSIIIIIIIIII xxxxxIIIIIIIIIII 358 // 359 // Note that the halfwords are stored high first, low second; so we need 360 // to transpose the fixup value here to map properly. 361 unsigned isNeg = (int64_t(Value - 4) < 0) ? 1 : 0; 362 uint32_t Binary = 0; 363 Value = 0x3fffff & ((Value - 4) >> 1); 364 Binary = (Value & 0x7ff) << 16; // Low imm11 value. 365 Binary |= (Value & 0x1ffc00) >> 11; // High imm10 value. 366 Binary |= isNeg << 10; // Sign bit. 367 return Binary; 368 } 369 case ARM::fixup_arm_thumb_blx: { 370 // The value doesn't encode the low two bits (always zero) and is offset by 371 // four (see fixup_arm_thumb_cp). The value is encoded into disjoint bit 372 // positions in the destination opcode. x = unchanged, I = immediate value 373 // bit, S = sign extension bit, 0 = zero. 374 // 375 // BLX: xxxxxSIIIIIIIIII xxxxxIIIIIIIIII0 376 // 377 // Note that the halfwords are stored high first, low second; so we need 378 // to transpose the fixup value here to map properly. 379 unsigned isNeg = (int64_t(Value-4) < 0) ? 1 : 0; 380 uint32_t Binary = 0; 381 Value = 0xfffff & ((Value - 2) >> 2); 382 Binary = (Value & 0x3ff) << 17; // Low imm10L value. 383 Binary |= (Value & 0xffc00) >> 10; // High imm10H value. 384 Binary |= isNeg << 10; // Sign bit. 385 return Binary; 386 } 387 case ARM::fixup_arm_thumb_cp: 388 // Offset by 4, and don't encode the low two bits. Two bytes of that 389 // 'off by 4' is implicitly handled by the half-word ordering of the 390 // Thumb encoding, so we only need to adjust by 2 here. 391 return ((Value - 2) >> 2) & 0xff; 392 case ARM::fixup_arm_thumb_cb: { 393 // Offset by 4 and don't encode the lower bit, which is always 0. 394 uint32_t Binary = (Value - 4) >> 1; 395 return ((Binary & 0x20) << 4) | ((Binary & 0x1f) << 3); 396 } 397 case ARM::fixup_arm_thumb_br: 398 // Offset by 4 and don't encode the lower bit, which is always 0. 399 return ((Value - 4) >> 1) & 0x7ff; 400 case ARM::fixup_arm_thumb_bcc: 401 // Offset by 4 and don't encode the lower bit, which is always 0. 402 return ((Value - 4) >> 1) & 0xff; 403 case ARM::fixup_arm_pcrel_10_unscaled: { 404 Value = Value - 8; // ARM fixups offset by an additional word and don't 405 // need to adjust for the half-word ordering. 406 bool isAdd = true; 407 if ((int64_t)Value < 0) { 408 Value = -Value; 409 isAdd = false; 410 } 411 assert ((Value < 256) && "Out of range pc-relative fixup value!"); 412 return Value | (isAdd << 23); 413 } 414 case ARM::fixup_arm_pcrel_10: 415 Value = Value - 4; // ARM fixups offset by an additional word and don't 416 // need to adjust for the half-word ordering. 417 // Fall through. 418 case ARM::fixup_t2_pcrel_10: { 419 // Offset by 4, adjusted by two due to the half-word ordering of thumb. 420 Value = Value - 4; 421 bool isAdd = true; 422 if ((int64_t)Value < 0) { 423 Value = -Value; 424 isAdd = false; 425 } 426 // These values don't encode the low two bits since they're always zero. 427 Value >>= 2; 428 assert ((Value < 256) && "Out of range pc-relative fixup value!"); 429 Value |= isAdd << 23; 430 431 // Same addressing mode as fixup_arm_pcrel_10, but with 16-bit halfwords 432 // swapped. 433 if (Kind == ARM::fixup_t2_pcrel_10) { 434 uint32_t swapped = (Value & 0xFFFF0000) >> 16; 435 swapped |= (Value & 0x0000FFFF) << 16; 436 return swapped; 437 } 438 439 return Value; 440 } 441 } 442 } 443 444 namespace { 445 446 // FIXME: This should be in a separate file. 447 // ELF is an ELF of course... 448 class ELFARMAsmBackend : public ARMAsmBackend { 449 public: 450 uint8_t OSABI; 451 ELFARMAsmBackend(const Target &T, const StringRef TT, 452 uint8_t _OSABI) 453 : ARMAsmBackend(T, TT), OSABI(_OSABI) { } 454 455 void ApplyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, 456 uint64_t Value) const; 457 458 MCObjectWriter *createObjectWriter(raw_ostream &OS) const { 459 return createARMELFObjectWriter(OS, OSABI); 460 } 461 }; 462 463 // FIXME: Raise this to share code between Darwin and ELF. 464 void ELFARMAsmBackend::ApplyFixup(const MCFixup &Fixup, char *Data, 465 unsigned DataSize, uint64_t Value) const { 466 unsigned NumBytes = 4; // FIXME: 2 for Thumb 467 Value = adjustFixupValue(Fixup.getKind(), Value); 468 if (!Value) return; // Doesn't change encoding. 469 470 unsigned Offset = Fixup.getOffset(); 471 472 // For each byte of the fragment that the fixup touches, mask in the bits from 473 // the fixup value. The Value has been "split up" into the appropriate 474 // bitfields above. 475 for (unsigned i = 0; i != NumBytes; ++i) 476 Data[Offset + i] |= uint8_t((Value >> (i * 8)) & 0xff); 477 } 478 479 // FIXME: This should be in a separate file. 480 class DarwinARMAsmBackend : public ARMAsmBackend { 481 public: 482 const object::mach::CPUSubtypeARM Subtype; 483 DarwinARMAsmBackend(const Target &T, const StringRef TT, 484 object::mach::CPUSubtypeARM st) 485 : ARMAsmBackend(T, TT), Subtype(st) { } 486 487 MCObjectWriter *createObjectWriter(raw_ostream &OS) const { 488 return createARMMachObjectWriter(OS, /*Is64Bit=*/false, 489 object::mach::CTM_ARM, 490 Subtype); 491 } 492 493 void ApplyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, 494 uint64_t Value) const; 495 496 virtual bool doesSectionRequireSymbols(const MCSection &Section) const { 497 return false; 498 } 499 }; 500 501 /// getFixupKindNumBytes - The number of bytes the fixup may change. 502 static unsigned getFixupKindNumBytes(unsigned Kind) { 503 switch (Kind) { 504 default: 505 llvm_unreachable("Unknown fixup kind!"); 506 507 case FK_Data_1: 508 case ARM::fixup_arm_thumb_bcc: 509 case ARM::fixup_arm_thumb_cp: 510 case ARM::fixup_thumb_adr_pcrel_10: 511 return 1; 512 513 case FK_Data_2: 514 case ARM::fixup_arm_thumb_br: 515 case ARM::fixup_arm_thumb_cb: 516 return 2; 517 518 case ARM::fixup_arm_pcrel_10_unscaled: 519 case ARM::fixup_arm_ldst_pcrel_12: 520 case ARM::fixup_arm_pcrel_10: 521 case ARM::fixup_arm_adr_pcrel_12: 522 case ARM::fixup_arm_condbranch: 523 case ARM::fixup_arm_uncondbranch: 524 return 3; 525 526 case FK_Data_4: 527 case ARM::fixup_t2_ldst_pcrel_12: 528 case ARM::fixup_t2_condbranch: 529 case ARM::fixup_t2_uncondbranch: 530 case ARM::fixup_t2_pcrel_10: 531 case ARM::fixup_t2_adr_pcrel_12: 532 case ARM::fixup_arm_thumb_bl: 533 case ARM::fixup_arm_thumb_blx: 534 case ARM::fixup_arm_movt_hi16: 535 case ARM::fixup_arm_movw_lo16: 536 case ARM::fixup_arm_movt_hi16_pcrel: 537 case ARM::fixup_arm_movw_lo16_pcrel: 538 case ARM::fixup_t2_movt_hi16: 539 case ARM::fixup_t2_movw_lo16: 540 case ARM::fixup_t2_movt_hi16_pcrel: 541 case ARM::fixup_t2_movw_lo16_pcrel: 542 return 4; 543 } 544 } 545 546 void DarwinARMAsmBackend::ApplyFixup(const MCFixup &Fixup, char *Data, 547 unsigned DataSize, uint64_t Value) const { 548 unsigned NumBytes = getFixupKindNumBytes(Fixup.getKind()); 549 Value = adjustFixupValue(Fixup.getKind(), Value); 550 if (!Value) return; // Doesn't change encoding. 551 552 unsigned Offset = Fixup.getOffset(); 553 assert(Offset + NumBytes <= DataSize && "Invalid fixup offset!"); 554 555 // For each byte of the fragment that the fixup touches, mask in the 556 // bits from the fixup value. 557 for (unsigned i = 0; i != NumBytes; ++i) 558 Data[Offset + i] |= uint8_t((Value >> (i * 8)) & 0xff); 559 } 560 561 } // end anonymous namespace 562 563 MCAsmBackend *llvm::createARMAsmBackend(const Target &T, StringRef TT) { 564 Triple TheTriple(TT); 565 566 if (TheTriple.isOSDarwin()) { 567 if (TheTriple.getArchName() == "armv4t" || 568 TheTriple.getArchName() == "thumbv4t") 569 return new DarwinARMAsmBackend(T, TT, object::mach::CSARM_V4T); 570 else if (TheTriple.getArchName() == "armv5e" || 571 TheTriple.getArchName() == "thumbv5e") 572 return new DarwinARMAsmBackend(T, TT, object::mach::CSARM_V5TEJ); 573 else if (TheTriple.getArchName() == "armv6" || 574 TheTriple.getArchName() == "thumbv6") 575 return new DarwinARMAsmBackend(T, TT, object::mach::CSARM_V6); 576 return new DarwinARMAsmBackend(T, TT, object::mach::CSARM_V7); 577 } 578 579 if (TheTriple.isOSWindows()) 580 assert(0 && "Windows not supported on ARM"); 581 582 uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(Triple(TT).getOS()); 583 return new ELFARMAsmBackend(T, TT, OSABI); 584 } 585