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