ARMAsmBackend.cpp revision fa1f74470a51a57b7b8feb4c4ba18501c3f2709a
1d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim//===-- ARMAsmBackend.cpp - ARM Assembler Backend -------------------------===// 2d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim// 3d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim// The LLVM Compiler Infrastructure 4d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim// 5d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim// This file is distributed under the University of Illinois Open Source 6d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim// License. See LICENSE.TXT for details. 7d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim// 8d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim//===----------------------------------------------------------------------===// 9d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim 10d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach#include "MCTargetDesc/ARMMCTargetDesc.h" 11be74029f44c32efc09274a16cbff588ad10dc5eaEvan Cheng#include "MCTargetDesc/ARMBaseInfo.h" 12be74029f44c32efc09274a16cbff588ad10dc5eaEvan Cheng#include "MCTargetDesc/ARMFixupKinds.h" 13ee04a6d3a40c3017124e3fd89a0db473a2824498Evan Cheng#include "MCTargetDesc/ARMAddressingModes.h" 14d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim#include "llvm/ADT/Twine.h" 15d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim#include "llvm/MC/MCAssembler.h" 165be6d2af38c29e3653998978345220974cc40c01Jim Grosbach#include "llvm/MC/MCDirectives.h" 17285b3e5b61af15f11e59a7700375aefa2a326bd8Rafael Espindola#include "llvm/MC/MCELFObjectWriter.h" 18d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim#include "llvm/MC/MCExpr.h" 19aa4b7dd13ba83152473950d7014a29686dc7eef6Daniel Dunbar#include "llvm/MC/MCMachObjectWriter.h" 20d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim#include "llvm/MC/MCObjectWriter.h" 21d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim#include "llvm/MC/MCSectionELF.h" 22d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim#include "llvm/MC/MCSectionMachO.h" 2378c10eeaa57d1c6c4b7781d3c0bcb0cfbbc43b5cEvan Cheng#include "llvm/MC/MCAsmBackend.h" 24d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach#include "llvm/MC/MCSubtargetInfo.h" 259b5b125c34b47e0e7eef2548acee8bf1448c4b71Jim Grosbach#include "llvm/MC/MCValue.h" 2636d76a8dbc87b62de82a4a8c0d7cb4bb2a202934Daniel Dunbar#include "llvm/Object/MachOFormat.h" 27eecb858ca86fa949c06f819d6127e2ac68d165c8Wesley Peck#include "llvm/Support/ELF.h" 28d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim#include "llvm/Support/ErrorHandling.h" 29d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim#include "llvm/Support/raw_ostream.h" 30d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kimusing namespace llvm; 31d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim 32d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kimnamespace { 336024c97ffa15766bc0f200ffd309d9e017ae0d4bRafael Espindolaclass ARMELFObjectWriter : public MCELFObjectTargetWriter { 346024c97ffa15766bc0f200ffd309d9e017ae0d4bRafael Espindolapublic: 35dc9a8a378daf432d8dcfc178507afe149706f9a6Rafael Espindola ARMELFObjectWriter(uint8_t OSABI) 36dc9a8a378daf432d8dcfc178507afe149706f9a6Rafael Espindola : MCELFObjectTargetWriter(/*Is64Bit*/ false, OSABI, ELF::EM_ARM, 37bff66a86e6e44dc7424cd2d7719ac80630b3a5f8Rafael Espindola /*HasRelocationAddend*/ false) {} 386024c97ffa15766bc0f200ffd309d9e017ae0d4bRafael Espindola}; 396024c97ffa15766bc0f200ffd309d9e017ae0d4bRafael Espindola 4078c10eeaa57d1c6c4b7781d3c0bcb0cfbbc43b5cEvan Chengclass ARMAsmBackend : public MCAsmBackend { 41d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach const MCSubtargetInfo* STI; 425be6d2af38c29e3653998978345220974cc40c01Jim Grosbach bool isThumbMode; // Currently emitting Thumb code. 43d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kimpublic: 44d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach ARMAsmBackend(const Target &T, const StringRef TT) 45d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach : MCAsmBackend(), STI(ARM_MC::createARMMCSubtargetInfo(TT, "", "")), 46b9d3ff872908bcf648b826c1c48db2cacd813b95Jim Grosbach isThumbMode(TT.startswith("thumb")) {} 47d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach 48d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach ~ARMAsmBackend() { 49d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach delete STI; 50d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach } 51d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim 522761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar unsigned getNumFixupKinds() const { return ARM::NumTargetFixupKinds; } 532761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar 54d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach bool hasNOP() const { 55d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach return (STI->getFeatureBits() & ARM::HasV6T2Ops) != 0; 56d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach } 57d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach 582761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const { 592761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar const static MCFixupKindInfo Infos[ARM::NumTargetFixupKinds] = { 602761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar// This table *must* be in the order that the fixup_* kinds are defined in 612761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar// ARMFixupKinds.h. 622761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar// 632761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar// Name Offset (bits) Size (bits) Flags 642abba8496cb394af53b531e95067d5cae78bb9eeJim Grosbach{ "fixup_arm_ldst_pcrel_12", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, 652761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar{ "fixup_t2_ldst_pcrel_12", 0, 32, MCFixupKindInfo::FKF_IsPCRel | 662761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, 672f196747f15240691bd4e622f7995edfedf90f61Jim Grosbach{ "fixup_arm_pcrel_10_unscaled", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, 68681460f954e9c13ffd2f02f27bba048ccf90abafJim Grosbach{ "fixup_arm_pcrel_10", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, 692761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar{ "fixup_t2_pcrel_10", 0, 32, MCFixupKindInfo::FKF_IsPCRel | 702761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, 712761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar{ "fixup_thumb_adr_pcrel_10",0, 8, MCFixupKindInfo::FKF_IsPCRel | 722761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, 732abba8496cb394af53b531e95067d5cae78bb9eeJim Grosbach{ "fixup_arm_adr_pcrel_12", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, 742761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar{ "fixup_t2_adr_pcrel_12", 0, 32, MCFixupKindInfo::FKF_IsPCRel | 752761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, 76685c350ae76b588e1f00c01a511fe8bd57f18394Jason W Kim{ "fixup_arm_condbranch", 0, 24, MCFixupKindInfo::FKF_IsPCRel }, 77685c350ae76b588e1f00c01a511fe8bd57f18394Jason W Kim{ "fixup_arm_uncondbranch", 0, 24, MCFixupKindInfo::FKF_IsPCRel }, 782761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar{ "fixup_t2_condbranch", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, 792761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar{ "fixup_t2_uncondbranch", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, 802761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar{ "fixup_arm_thumb_br", 0, 16, MCFixupKindInfo::FKF_IsPCRel }, 817b25ecf6adbf3c4709c48033acfeb6ebbb4452abJim Grosbach{ "fixup_arm_bl", 0, 24, MCFixupKindInfo::FKF_IsPCRel }, 827b25ecf6adbf3c4709c48033acfeb6ebbb4452abJim Grosbach{ "fixup_arm_blx", 0, 24, MCFixupKindInfo::FKF_IsPCRel }, 832761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar{ "fixup_arm_thumb_bl", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, 8490b5a08e1ffc4a1c18f7fa964ca561fa4b03c314Jim Grosbach{ "fixup_arm_thumb_blx", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, 852761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar{ "fixup_arm_thumb_cb", 0, 16, MCFixupKindInfo::FKF_IsPCRel }, 8667b95f902a51b591b6178e370d23ffaca841275dJim Grosbach{ "fixup_arm_thumb_cp", 0, 8, MCFixupKindInfo::FKF_IsPCRel }, 87fea51fc007598176d48fb7319a9bf471efb93127Eric Christopher{ "fixup_arm_thumb_bcc", 0, 8, MCFixupKindInfo::FKF_IsPCRel }, 88f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng// movw / movt: 16-bits immediate but scattered into two chunks 0 - 12, 16 - 19. 89f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng{ "fixup_arm_movt_hi16", 0, 20, 0 }, 90f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng{ "fixup_arm_movw_lo16", 0, 20, 0 }, 91f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng{ "fixup_t2_movt_hi16", 0, 20, 0 }, 92f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng{ "fixup_t2_movw_lo16", 0, 20, 0 }, 93f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng{ "fixup_arm_movt_hi16_pcrel", 0, 20, MCFixupKindInfo::FKF_IsPCRel }, 94f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng{ "fixup_arm_movw_lo16_pcrel", 0, 20, MCFixupKindInfo::FKF_IsPCRel }, 95f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng{ "fixup_t2_movt_hi16_pcrel", 0, 20, MCFixupKindInfo::FKF_IsPCRel }, 96f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng{ "fixup_t2_movw_lo16_pcrel", 0, 20, MCFixupKindInfo::FKF_IsPCRel }, 972761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar }; 982761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar 992761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar if (Kind < FirstTargetFixupKind) 10078c10eeaa57d1c6c4b7781d3c0bcb0cfbbc43b5cEvan Cheng return MCAsmBackend::getFixupKindInfo(Kind); 1012761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar 1022761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() && 1032761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar "Invalid kind!"); 1042761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar return Infos[Kind - FirstTargetFixupKind]; 1052761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar } 1062761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar 1079b5b125c34b47e0e7eef2548acee8bf1448c4b71Jim Grosbach /// processFixupValue - Target hook to process the literal value of a fixup 1089b5b125c34b47e0e7eef2548acee8bf1448c4b71Jim Grosbach /// if necessary. 1099b5b125c34b47e0e7eef2548acee8bf1448c4b71Jim Grosbach void processFixupValue(const MCAssembler &Asm, const MCAsmLayout &Layout, 1109b5b125c34b47e0e7eef2548acee8bf1448c4b71Jim Grosbach const MCFixup &Fixup, const MCFragment *DF, 1117b25ecf6adbf3c4709c48033acfeb6ebbb4452abJim Grosbach MCValue &Target, uint64_t &Value, 1127b25ecf6adbf3c4709c48033acfeb6ebbb4452abJim Grosbach bool &IsResolved) { 1137b25ecf6adbf3c4709c48033acfeb6ebbb4452abJim Grosbach const MCSymbolRefExpr *A = Target.getSymA(); 1149b5b125c34b47e0e7eef2548acee8bf1448c4b71Jim Grosbach // Some fixups to thumb function symbols need the low bit (thumb bit) 1159b5b125c34b47e0e7eef2548acee8bf1448c4b71Jim Grosbach // twiddled. 1165a7efa7f134dd6f8f927c162d9f4062eaa3eb4acJim Grosbach if ((unsigned)Fixup.getKind() != ARM::fixup_arm_ldst_pcrel_12 && 1175a7efa7f134dd6f8f927c162d9f4062eaa3eb4acJim Grosbach (unsigned)Fixup.getKind() != ARM::fixup_t2_ldst_pcrel_12 && 1185a7efa7f134dd6f8f927c162d9f4062eaa3eb4acJim Grosbach (unsigned)Fixup.getKind() != ARM::fixup_arm_thumb_cp) { 1197b25ecf6adbf3c4709c48033acfeb6ebbb4452abJim Grosbach if (A) { 1205a7efa7f134dd6f8f927c162d9f4062eaa3eb4acJim Grosbach const MCSymbol &Sym = A->getSymbol().AliasedSymbol(); 1215a7efa7f134dd6f8f927c162d9f4062eaa3eb4acJim Grosbach if (Asm.isThumbFunc(&Sym)) 1225a7efa7f134dd6f8f927c162d9f4062eaa3eb4acJim Grosbach Value |= 1; 1235a7efa7f134dd6f8f927c162d9f4062eaa3eb4acJim Grosbach } 1249b5b125c34b47e0e7eef2548acee8bf1448c4b71Jim Grosbach } 1257b25ecf6adbf3c4709c48033acfeb6ebbb4452abJim Grosbach // We must always generate a relocation for BL/BLX instructions if we have 1267b25ecf6adbf3c4709c48033acfeb6ebbb4452abJim Grosbach // a symbol to reference, as the linker relies on knowing the destination 1277b25ecf6adbf3c4709c48033acfeb6ebbb4452abJim Grosbach // symbol's thumb-ness to get interworking right. 1287b25ecf6adbf3c4709c48033acfeb6ebbb4452abJim Grosbach if (A && ((unsigned)Fixup.getKind() == ARM::fixup_arm_thumb_blx || 1297b25ecf6adbf3c4709c48033acfeb6ebbb4452abJim Grosbach (unsigned)Fixup.getKind() == ARM::fixup_arm_thumb_bl || 1307b25ecf6adbf3c4709c48033acfeb6ebbb4452abJim Grosbach (unsigned)Fixup.getKind() == ARM::fixup_arm_blx || 1317b25ecf6adbf3c4709c48033acfeb6ebbb4452abJim Grosbach (unsigned)Fixup.getKind() == ARM::fixup_arm_bl)) 1327b25ecf6adbf3c4709c48033acfeb6ebbb4452abJim Grosbach IsResolved = false; 1339b5b125c34b47e0e7eef2548acee8bf1448c4b71Jim Grosbach } 1349b5b125c34b47e0e7eef2548acee8bf1448c4b71Jim Grosbach 135ec3433852dd11e8ff60c9610b4c84468e5935f2bJim Grosbach bool mayNeedRelaxation(const MCInst &Inst) const; 136d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim 137370b78d795154899a22ca2b4674e890661ff1d59Jim Grosbach bool fixupNeedsRelaxation(const MCFixup &Fixup, 138370b78d795154899a22ca2b4674e890661ff1d59Jim Grosbach uint64_t Value, 139370b78d795154899a22ca2b4674e890661ff1d59Jim Grosbach const MCInstFragment *DF, 140370b78d795154899a22ca2b4674e890661ff1d59Jim Grosbach const MCAsmLayout &Layout) const; 141370b78d795154899a22ca2b4674e890661ff1d59Jim Grosbach 142ec3433852dd11e8ff60c9610b4c84468e5935f2bJim Grosbach void relaxInstruction(const MCInst &Inst, MCInst &Res) const; 143d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim 144ec3433852dd11e8ff60c9610b4c84468e5935f2bJim Grosbach bool writeNopData(uint64_t Count, MCObjectWriter *OW) const; 1453787a40e038d6444a1b0e93f1cdc55fb006a5392Jim Grosbach 146ec3433852dd11e8ff60c9610b4c84468e5935f2bJim Grosbach void handleAssemblerFlag(MCAssemblerFlag Flag) { 1475be6d2af38c29e3653998978345220974cc40c01Jim Grosbach switch (Flag) { 1485be6d2af38c29e3653998978345220974cc40c01Jim Grosbach default: break; 1495be6d2af38c29e3653998978345220974cc40c01Jim Grosbach case MCAF_Code16: 1505be6d2af38c29e3653998978345220974cc40c01Jim Grosbach setIsThumb(true); 1515be6d2af38c29e3653998978345220974cc40c01Jim Grosbach break; 1525be6d2af38c29e3653998978345220974cc40c01Jim Grosbach case MCAF_Code32: 1535be6d2af38c29e3653998978345220974cc40c01Jim Grosbach setIsThumb(false); 1545be6d2af38c29e3653998978345220974cc40c01Jim Grosbach break; 1555be6d2af38c29e3653998978345220974cc40c01Jim Grosbach } 1563787a40e038d6444a1b0e93f1cdc55fb006a5392Jim Grosbach } 1575be6d2af38c29e3653998978345220974cc40c01Jim Grosbach 1585be6d2af38c29e3653998978345220974cc40c01Jim Grosbach unsigned getPointerSize() const { return 4; } 1595be6d2af38c29e3653998978345220974cc40c01Jim Grosbach bool isThumb() const { return isThumbMode; } 1605be6d2af38c29e3653998978345220974cc40c01Jim Grosbach void setIsThumb(bool it) { isThumbMode = it; } 161d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim}; 162b75c651e22a63907b727664f044283bf9c9fb885Chris Lattner} // end anonymous namespace 163d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim 164f503ef6800fcbda99d6ae581ee8cfe3204becb3cJim Grosbachstatic unsigned getRelaxedOpcode(unsigned Op) { 165f503ef6800fcbda99d6ae581ee8cfe3204becb3cJim Grosbach switch (Op) { 166f503ef6800fcbda99d6ae581ee8cfe3204becb3cJim Grosbach default: return Op; 167256ba4f42a16da2b3ffc757aa7bf191890765580Jim Grosbach case ARM::tBcc: return ARM::t2Bcc; 168256ba4f42a16da2b3ffc757aa7bf191890765580Jim Grosbach case ARM::tLDRpciASM: return ARM::t2LDRpci; 1699363c58dc2473a6470d3e7037afe8a215bee7e3eJim Grosbach case ARM::tADR: return ARM::t2ADR; 170fa1f74470a51a57b7b8feb4c4ba18501c3f2709aJim Grosbach case ARM::tB: return ARM::t2B; 171f503ef6800fcbda99d6ae581ee8cfe3204becb3cJim Grosbach } 172f503ef6800fcbda99d6ae581ee8cfe3204becb3cJim Grosbach} 173f503ef6800fcbda99d6ae581ee8cfe3204becb3cJim Grosbach 174ec3433852dd11e8ff60c9610b4c84468e5935f2bJim Grosbachbool ARMAsmBackend::mayNeedRelaxation(const MCInst &Inst) const { 175f503ef6800fcbda99d6ae581ee8cfe3204becb3cJim Grosbach if (getRelaxedOpcode(Inst.getOpcode()) != Inst.getOpcode()) 176f503ef6800fcbda99d6ae581ee8cfe3204becb3cJim Grosbach return true; 177d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim return false; 178d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim} 179d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim 180370b78d795154899a22ca2b4674e890661ff1d59Jim Grosbachbool ARMAsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup, 181370b78d795154899a22ca2b4674e890661ff1d59Jim Grosbach uint64_t Value, 182370b78d795154899a22ca2b4674e890661ff1d59Jim Grosbach const MCInstFragment *DF, 183370b78d795154899a22ca2b4674e890661ff1d59Jim Grosbach const MCAsmLayout &Layout) const { 184e545ee20f1b6ea6c03919cc9bc1a4a059c2f03b6Benjamin Kramer switch ((unsigned)Fixup.getKind()) { 185fa1f74470a51a57b7b8feb4c4ba18501c3f2709aJim Grosbach case ARM::fixup_arm_thumb_br: { 186fa1f74470a51a57b7b8feb4c4ba18501c3f2709aJim Grosbach // Relaxing tB to t2B. tB has a signed 12-bit displacement with the 187fa1f74470a51a57b7b8feb4c4ba18501c3f2709aJim Grosbach // low bit being an implied zero. There's an implied +4 offset for the 188fa1f74470a51a57b7b8feb4c4ba18501c3f2709aJim Grosbach // branch, so we adjust the other way here to determine what's 189fa1f74470a51a57b7b8feb4c4ba18501c3f2709aJim Grosbach // encodable. 190fa1f74470a51a57b7b8feb4c4ba18501c3f2709aJim Grosbach // 191fa1f74470a51a57b7b8feb4c4ba18501c3f2709aJim Grosbach // Relax if the value is too big for a (signed) i8. 192fa1f74470a51a57b7b8feb4c4ba18501c3f2709aJim Grosbach int64_t Offset = int64_t(Value) - 4; 193fa1f74470a51a57b7b8feb4c4ba18501c3f2709aJim Grosbach return Offset > 2046 || Offset < -2048; 194fa1f74470a51a57b7b8feb4c4ba18501c3f2709aJim Grosbach } 195256ba4f42a16da2b3ffc757aa7bf191890765580Jim Grosbach case ARM::fixup_arm_thumb_bcc: { 196256ba4f42a16da2b3ffc757aa7bf191890765580Jim Grosbach // Relaxing tBcc to t2Bcc. tBcc has a signed 9-bit displacement with the 197256ba4f42a16da2b3ffc757aa7bf191890765580Jim Grosbach // low bit being an implied zero. There's an implied +4 offset for the 198256ba4f42a16da2b3ffc757aa7bf191890765580Jim Grosbach // branch, so we adjust the other way here to determine what's 199256ba4f42a16da2b3ffc757aa7bf191890765580Jim Grosbach // encodable. 200256ba4f42a16da2b3ffc757aa7bf191890765580Jim Grosbach // 201256ba4f42a16da2b3ffc757aa7bf191890765580Jim Grosbach // Relax if the value is too big for a (signed) i8. 202256ba4f42a16da2b3ffc757aa7bf191890765580Jim Grosbach int64_t Offset = int64_t(Value) - 4; 203256ba4f42a16da2b3ffc757aa7bf191890765580Jim Grosbach return Offset > 254 || Offset < -256; 204256ba4f42a16da2b3ffc757aa7bf191890765580Jim Grosbach } 2059363c58dc2473a6470d3e7037afe8a215bee7e3eJim Grosbach case ARM::fixup_thumb_adr_pcrel_10: 206256ba4f42a16da2b3ffc757aa7bf191890765580Jim Grosbach case ARM::fixup_arm_thumb_cp: { 207d26bad079d6977309699e0bc9203451904acbd86Jim Grosbach // If the immediate is negative, greater than 1020, or not a multiple 208d26bad079d6977309699e0bc9203451904acbd86Jim Grosbach // of four, the wide version of the instruction must be used. 209256ba4f42a16da2b3ffc757aa7bf191890765580Jim Grosbach int64_t Offset = int64_t(Value) - 4; 210d26bad079d6977309699e0bc9203451904acbd86Jim Grosbach return Offset > 1020 || Offset < 0 || Offset & 3; 211256ba4f42a16da2b3ffc757aa7bf191890765580Jim Grosbach } 212256ba4f42a16da2b3ffc757aa7bf191890765580Jim Grosbach } 213e545ee20f1b6ea6c03919cc9bc1a4a059c2f03b6Benjamin Kramer llvm_unreachable("Unexpected fixup kind in fixupNeedsRelaxation()!"); 214370b78d795154899a22ca2b4674e890661ff1d59Jim Grosbach} 215370b78d795154899a22ca2b4674e890661ff1d59Jim Grosbach 216ec3433852dd11e8ff60c9610b4c84468e5935f2bJim Grosbachvoid ARMAsmBackend::relaxInstruction(const MCInst &Inst, MCInst &Res) const { 217f503ef6800fcbda99d6ae581ee8cfe3204becb3cJim Grosbach unsigned RelaxedOp = getRelaxedOpcode(Inst.getOpcode()); 218f503ef6800fcbda99d6ae581ee8cfe3204becb3cJim Grosbach 219f503ef6800fcbda99d6ae581ee8cfe3204becb3cJim Grosbach // Sanity check w/ diagnostic if we get here w/ a bogus instruction. 220f503ef6800fcbda99d6ae581ee8cfe3204becb3cJim Grosbach if (RelaxedOp == Inst.getOpcode()) { 221f503ef6800fcbda99d6ae581ee8cfe3204becb3cJim Grosbach SmallString<256> Tmp; 222f503ef6800fcbda99d6ae581ee8cfe3204becb3cJim Grosbach raw_svector_ostream OS(Tmp); 223f503ef6800fcbda99d6ae581ee8cfe3204becb3cJim Grosbach Inst.dump_pretty(OS); 224f503ef6800fcbda99d6ae581ee8cfe3204becb3cJim Grosbach OS << "\n"; 225f503ef6800fcbda99d6ae581ee8cfe3204becb3cJim Grosbach report_fatal_error("unexpected instruction to relax: " + OS.str()); 226f503ef6800fcbda99d6ae581ee8cfe3204becb3cJim Grosbach } 227f503ef6800fcbda99d6ae581ee8cfe3204becb3cJim Grosbach 228f503ef6800fcbda99d6ae581ee8cfe3204becb3cJim Grosbach // The instructions we're relaxing have (so far) the same operands. 229f503ef6800fcbda99d6ae581ee8cfe3204becb3cJim Grosbach // We just need to update to the proper opcode. 230f503ef6800fcbda99d6ae581ee8cfe3204becb3cJim Grosbach Res = Inst; 231f503ef6800fcbda99d6ae581ee8cfe3204becb3cJim Grosbach Res.setOpcode(RelaxedOp); 232d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim} 233d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim 234ec3433852dd11e8ff60c9610b4c84468e5935f2bJim Grosbachbool ARMAsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW) const { 235d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach const uint16_t Thumb1_16bitNopEncoding = 0x46c0; // using MOV r8,r8 236d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach const uint16_t Thumb2_16bitNopEncoding = 0xbf00; // NOP 237d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach const uint32_t ARMv4_NopEncoding = 0xe1a0000; // using MOV r0,r0 238b84acd24687c721e3da46bb56a94d393bc5a8cbcJim Grosbach const uint32_t ARMv6T2_NopEncoding = 0xe320f000; // NOP 2395be6d2af38c29e3653998978345220974cc40c01Jim Grosbach if (isThumb()) { 240d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach const uint16_t nopEncoding = hasNOP() ? Thumb2_16bitNopEncoding 241d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach : Thumb1_16bitNopEncoding; 242a3dbd3a2444f2531763ba05b64a30932542a631fJim Grosbach uint64_t NumNops = Count / 2; 243a3dbd3a2444f2531763ba05b64a30932542a631fJim Grosbach for (uint64_t i = 0; i != NumNops; ++i) 244d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach OW->Write16(nopEncoding); 245a3dbd3a2444f2531763ba05b64a30932542a631fJim Grosbach if (Count & 1) 246a3dbd3a2444f2531763ba05b64a30932542a631fJim Grosbach OW->Write8(0); 2475be6d2af38c29e3653998978345220974cc40c01Jim Grosbach return true; 2485be6d2af38c29e3653998978345220974cc40c01Jim Grosbach } 2495be6d2af38c29e3653998978345220974cc40c01Jim Grosbach // ARM mode 250d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach const uint32_t nopEncoding = hasNOP() ? ARMv6T2_NopEncoding 251d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach : ARMv4_NopEncoding; 252a3dbd3a2444f2531763ba05b64a30932542a631fJim Grosbach uint64_t NumNops = Count / 4; 253a3dbd3a2444f2531763ba05b64a30932542a631fJim Grosbach for (uint64_t i = 0; i != NumNops; ++i) 254d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach OW->Write32(nopEncoding); 255d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach // FIXME: should this function return false when unable to write exactly 256d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach // 'Count' bytes with NOP encodings? 257a3dbd3a2444f2531763ba05b64a30932542a631fJim Grosbach switch (Count % 4) { 258a3dbd3a2444f2531763ba05b64a30932542a631fJim Grosbach default: break; // No leftover bytes to write 259a3dbd3a2444f2531763ba05b64a30932542a631fJim Grosbach case 1: OW->Write8(0); break; 260a3dbd3a2444f2531763ba05b64a30932542a631fJim Grosbach case 2: OW->Write16(0); break; 261a3dbd3a2444f2531763ba05b64a30932542a631fJim Grosbach case 3: OW->Write16(0); OW->Write8(0xa0); break; 262a3dbd3a2444f2531763ba05b64a30932542a631fJim Grosbach } 263a3dbd3a2444f2531763ba05b64a30932542a631fJim Grosbach 264cecbc3d28277ff4916326311cbf87335ed05d106Rafael Espindola return true; 26587dc3aa2d87871f1affc6f3f2fa587c7b6725d83Jim Grosbach} 266d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim 2670c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kimstatic unsigned adjustFixupValue(unsigned Kind, uint64_t Value) { 2680c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim switch (Kind) { 2690c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim default: 2700c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim llvm_unreachable("Unknown fixup kind!"); 2716ec6eeb692fa11b569af8b69b2bb11cc84f04926Jim Grosbach case FK_Data_1: 2726ec6eeb692fa11b569af8b69b2bb11cc84f04926Jim Grosbach case FK_Data_2: 2730c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim case FK_Data_4: 2742ccf148fbaaf9ea15233d7ef09e31ca0fa6ee3beJason W Kim return Value; 2750c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim case ARM::fixup_arm_movt_hi16: 276f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng Value >>= 16; 277f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng // Fallthrough 278f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng case ARM::fixup_arm_movw_lo16: 279861b9c6a397f2ed4b5601cacbc9121d0b07d1f65Jason W Kim case ARM::fixup_arm_movt_hi16_pcrel: 28086a97f2e4d0cde5e992f52ac287da0de687e0110Jason W Kim case ARM::fixup_arm_movw_lo16_pcrel: { 2812ccf148fbaaf9ea15233d7ef09e31ca0fa6ee3beJason W Kim unsigned Hi4 = (Value & 0xF000) >> 12; 2822ccf148fbaaf9ea15233d7ef09e31ca0fa6ee3beJason W Kim unsigned Lo12 = Value & 0x0FFF; 2832ccf148fbaaf9ea15233d7ef09e31ca0fa6ee3beJason W Kim // inst{19-16} = Hi4; 2842ccf148fbaaf9ea15233d7ef09e31ca0fa6ee3beJason W Kim // inst{11-0} = Lo12; 2852ccf148fbaaf9ea15233d7ef09e31ca0fa6ee3beJason W Kim Value = (Hi4 << 16) | (Lo12); 2860c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim return Value; 2872ccf148fbaaf9ea15233d7ef09e31ca0fa6ee3beJason W Kim } 288f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng case ARM::fixup_t2_movt_hi16: 289f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng Value >>= 16; 290f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng // Fallthrough 291f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng case ARM::fixup_t2_movw_lo16: 2928b45456700f1e156b0a14000124f274dfac86f14Jim Grosbach case ARM::fixup_t2_movt_hi16_pcrel: //FIXME: Shouldn't this be shifted like 2938b45456700f1e156b0a14000124f274dfac86f14Jim Grosbach // the other hi16 fixup? 294f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng case ARM::fixup_t2_movw_lo16_pcrel: { 295f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng unsigned Hi4 = (Value & 0xF000) >> 12; 296f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng unsigned i = (Value & 0x800) >> 11; 297f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng unsigned Mid3 = (Value & 0x700) >> 8; 298f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng unsigned Lo8 = Value & 0x0FF; 299f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng // inst{19-16} = Hi4; 300f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng // inst{26} = i; 301f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng // inst{14-12} = Mid3; 302f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng // inst{7-0} = Lo8; 303f391e9f696183a8dfb6b0d1e791687a520552f85Jim Grosbach Value = (Hi4 << 16) | (i << 26) | (Mid3 << 12) | (Lo8); 304f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng uint64_t swapped = (Value & 0xFFFF0000) >> 16; 305f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng swapped |= (Value & 0x0000FFFF) << 16; 306f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng return swapped; 307f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng } 308d7b3f5870d9d04351d9cd363d9d6af01482a2eb8Owen Anderson case ARM::fixup_arm_ldst_pcrel_12: 3090c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim // ARM PC-relative values are offset by 8. 31005018c2f2872a05b1a2fff1a9934621ba1f38084Owen Anderson Value -= 4; 311fe7fac74b4edaf9cc04460fc21aa949e5533aea2Owen Anderson // FALLTHROUGH 312d7b3f5870d9d04351d9cd363d9d6af01482a2eb8Owen Anderson case ARM::fixup_t2_ldst_pcrel_12: { 313d7b3f5870d9d04351d9cd363d9d6af01482a2eb8Owen Anderson // Offset by 4, adjusted by two due to the half-word ordering of thumb. 31405018c2f2872a05b1a2fff1a9934621ba1f38084Owen Anderson Value -= 4; 315d7b3f5870d9d04351d9cd363d9d6af01482a2eb8Owen Anderson bool isAdd = true; 3160c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim if ((int64_t)Value < 0) { 3170c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim Value = -Value; 3180c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim isAdd = false; 3190c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim } 3200c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim assert ((Value < 4096) && "Out of range pc-relative fixup value!"); 3210c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim Value |= isAdd << 23; 3227e294cfcf97cd7b94bf5c4de0f214480ec13adadJim Grosbach 323d7b3f5870d9d04351d9cd363d9d6af01482a2eb8Owen Anderson // Same addressing mode as fixup_arm_pcrel_10, 324d7b3f5870d9d04351d9cd363d9d6af01482a2eb8Owen Anderson // but with 16-bit halfwords swapped. 325d7b3f5870d9d04351d9cd363d9d6af01482a2eb8Owen Anderson if (Kind == ARM::fixup_t2_ldst_pcrel_12) { 326d7b3f5870d9d04351d9cd363d9d6af01482a2eb8Owen Anderson uint64_t swapped = (Value & 0xFFFF0000) >> 16; 327d7b3f5870d9d04351d9cd363d9d6af01482a2eb8Owen Anderson swapped |= (Value & 0x0000FFFF) << 16; 328d7b3f5870d9d04351d9cd363d9d6af01482a2eb8Owen Anderson return swapped; 329d7b3f5870d9d04351d9cd363d9d6af01482a2eb8Owen Anderson } 3307e294cfcf97cd7b94bf5c4de0f214480ec13adadJim Grosbach 3310c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim return Value; 3320c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim } 333d40963c4065432ec7e47879d3ca665a54ee903b6Jim Grosbach case ARM::fixup_thumb_adr_pcrel_10: 334d40963c4065432ec7e47879d3ca665a54ee903b6Jim Grosbach return ((Value - 4) >> 2) & 0xff; 335dff84b03258514463ede477af38f1246b95b0cd0Jim Grosbach case ARM::fixup_arm_adr_pcrel_12: { 336dff84b03258514463ede477af38f1246b95b0cd0Jim Grosbach // ARM PC-relative values are offset by 8. 337dff84b03258514463ede477af38f1246b95b0cd0Jim Grosbach Value -= 8; 338dff84b03258514463ede477af38f1246b95b0cd0Jim Grosbach unsigned opc = 4; // bits {24-21}. Default to add: 0b0100 339dff84b03258514463ede477af38f1246b95b0cd0Jim Grosbach if ((int64_t)Value < 0) { 340dff84b03258514463ede477af38f1246b95b0cd0Jim Grosbach Value = -Value; 341dff84b03258514463ede477af38f1246b95b0cd0Jim Grosbach opc = 2; // 0b0010 342dff84b03258514463ede477af38f1246b95b0cd0Jim Grosbach } 343dff84b03258514463ede477af38f1246b95b0cd0Jim Grosbach assert(ARM_AM::getSOImmVal(Value) != -1 && 344dff84b03258514463ede477af38f1246b95b0cd0Jim Grosbach "Out of range pc-relative fixup value!"); 345dff84b03258514463ede477af38f1246b95b0cd0Jim Grosbach // Encode the immediate and shift the opcode into place. 346dff84b03258514463ede477af38f1246b95b0cd0Jim Grosbach return ARM_AM::getSOImmVal(Value) | (opc << 21); 347dff84b03258514463ede477af38f1246b95b0cd0Jim Grosbach } 348e8eb1ea6acd54538b42491b95d8fc6281d4b5710Jim Grosbach 349a838a25d59838adfa91463f6a918ae3adeb352c1Owen Anderson case ARM::fixup_t2_adr_pcrel_12: { 350a838a25d59838adfa91463f6a918ae3adeb352c1Owen Anderson Value -= 4; 351a838a25d59838adfa91463f6a918ae3adeb352c1Owen Anderson unsigned opc = 0; 352a838a25d59838adfa91463f6a918ae3adeb352c1Owen Anderson if ((int64_t)Value < 0) { 353a838a25d59838adfa91463f6a918ae3adeb352c1Owen Anderson Value = -Value; 354a838a25d59838adfa91463f6a918ae3adeb352c1Owen Anderson opc = 5; 355a838a25d59838adfa91463f6a918ae3adeb352c1Owen Anderson } 356a838a25d59838adfa91463f6a918ae3adeb352c1Owen Anderson 357a838a25d59838adfa91463f6a918ae3adeb352c1Owen Anderson uint32_t out = (opc << 21); 358741ad15e26d1717433f326743800f30c63c6a9c1Owen Anderson out |= (Value & 0x800) << 15; 359a838a25d59838adfa91463f6a918ae3adeb352c1Owen Anderson out |= (Value & 0x700) << 4; 360a838a25d59838adfa91463f6a918ae3adeb352c1Owen Anderson out |= (Value & 0x0FF); 361e8eb1ea6acd54538b42491b95d8fc6281d4b5710Jim Grosbach 362a838a25d59838adfa91463f6a918ae3adeb352c1Owen Anderson uint64_t swapped = (out & 0xFFFF0000) >> 16; 363a838a25d59838adfa91463f6a918ae3adeb352c1Owen Anderson swapped |= (out & 0x0000FFFF) << 16; 364a838a25d59838adfa91463f6a918ae3adeb352c1Owen Anderson return swapped; 365a838a25d59838adfa91463f6a918ae3adeb352c1Owen Anderson } 366e8eb1ea6acd54538b42491b95d8fc6281d4b5710Jim Grosbach 367685c350ae76b588e1f00c01a511fe8bd57f18394Jason W Kim case ARM::fixup_arm_condbranch: 368685c350ae76b588e1f00c01a511fe8bd57f18394Jason W Kim case ARM::fixup_arm_uncondbranch: 3697b25ecf6adbf3c4709c48033acfeb6ebbb4452abJim Grosbach case ARM::fixup_arm_bl: 3707b25ecf6adbf3c4709c48033acfeb6ebbb4452abJim Grosbach case ARM::fixup_arm_blx: 3710c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim // These values don't encode the low two bits since they're always zero. 3720c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim // Offset by 8 just as above. 373662a816e89a9d77bf75e1328b09cf9235b4682aaJim Grosbach return 0xffffff & ((Value - 8) >> 2); 374c266600bec4b5ba0ee93ffdfeaafcab8f1295145Owen Anderson case ARM::fixup_t2_uncondbranch: { 37563ee22065dc4e8af7f4bf99c25b82da132700267Owen Anderson Value = Value - 4; 376fb20d890756b75d6ccfa7ab17f170a877d425dc6Owen Anderson Value >>= 1; // Low bit is not encoded. 3777e294cfcf97cd7b94bf5c4de0f214480ec13adadJim Grosbach 37856a2535474dd4482c432b3c75c3dab4b2f3dd1e2Jim Grosbach uint32_t out = 0; 379c266600bec4b5ba0ee93ffdfeaafcab8f1295145Owen Anderson bool I = Value & 0x800000; 380c266600bec4b5ba0ee93ffdfeaafcab8f1295145Owen Anderson bool J1 = Value & 0x400000; 381c266600bec4b5ba0ee93ffdfeaafcab8f1295145Owen Anderson bool J2 = Value & 0x200000; 382c266600bec4b5ba0ee93ffdfeaafcab8f1295145Owen Anderson J1 ^= I; 383c266600bec4b5ba0ee93ffdfeaafcab8f1295145Owen Anderson J2 ^= I; 384e8eb1ea6acd54538b42491b95d8fc6281d4b5710Jim Grosbach 385c266600bec4b5ba0ee93ffdfeaafcab8f1295145Owen Anderson out |= I << 26; // S bit 386c266600bec4b5ba0ee93ffdfeaafcab8f1295145Owen Anderson out |= !J1 << 13; // J1 bit 387c266600bec4b5ba0ee93ffdfeaafcab8f1295145Owen Anderson out |= !J2 << 11; // J2 bit 388c266600bec4b5ba0ee93ffdfeaafcab8f1295145Owen Anderson out |= (Value & 0x1FF800) << 5; // imm6 field 389c266600bec4b5ba0ee93ffdfeaafcab8f1295145Owen Anderson out |= (Value & 0x0007FF); // imm11 field 390e8eb1ea6acd54538b42491b95d8fc6281d4b5710Jim Grosbach 391c266600bec4b5ba0ee93ffdfeaafcab8f1295145Owen Anderson uint64_t swapped = (out & 0xFFFF0000) >> 16; 392c266600bec4b5ba0ee93ffdfeaafcab8f1295145Owen Anderson swapped |= (out & 0x0000FFFF) << 16; 393c266600bec4b5ba0ee93ffdfeaafcab8f1295145Owen Anderson return swapped; 394c266600bec4b5ba0ee93ffdfeaafcab8f1295145Owen Anderson } 395c266600bec4b5ba0ee93ffdfeaafcab8f1295145Owen Anderson case ARM::fixup_t2_condbranch: { 396c266600bec4b5ba0ee93ffdfeaafcab8f1295145Owen Anderson Value = Value - 4; 397c266600bec4b5ba0ee93ffdfeaafcab8f1295145Owen Anderson Value >>= 1; // Low bit is not encoded. 398e8eb1ea6acd54538b42491b95d8fc6281d4b5710Jim Grosbach 399c266600bec4b5ba0ee93ffdfeaafcab8f1295145Owen Anderson uint64_t out = 0; 4008f0794331765661f92cf074f638acb1ea927bb5dOwen Anderson out |= (Value & 0x80000) << 7; // S bit 4018f0794331765661f92cf074f638acb1ea927bb5dOwen Anderson out |= (Value & 0x40000) >> 7; // J2 bit 4028f0794331765661f92cf074f638acb1ea927bb5dOwen Anderson out |= (Value & 0x20000) >> 4; // J1 bit 4038f0794331765661f92cf074f638acb1ea927bb5dOwen Anderson out |= (Value & 0x1F800) << 5; // imm6 field 4048f0794331765661f92cf074f638acb1ea927bb5dOwen Anderson out |= (Value & 0x007FF); // imm11 field 4057e294cfcf97cd7b94bf5c4de0f214480ec13adadJim Grosbach 40656a2535474dd4482c432b3c75c3dab4b2f3dd1e2Jim Grosbach uint32_t swapped = (out & 0xFFFF0000) >> 16; 407fb20d890756b75d6ccfa7ab17f170a877d425dc6Owen Anderson swapped |= (out & 0x0000FFFF) << 16; 408fb20d890756b75d6ccfa7ab17f170a877d425dc6Owen Anderson return swapped; 409fb20d890756b75d6ccfa7ab17f170a877d425dc6Owen Anderson } 410662a816e89a9d77bf75e1328b09cf9235b4682aaJim Grosbach case ARM::fixup_arm_thumb_bl: { 411662a816e89a9d77bf75e1328b09cf9235b4682aaJim Grosbach // The value doesn't encode the low bit (always zero) and is offset by 412662a816e89a9d77bf75e1328b09cf9235b4682aaJim Grosbach // four. The value is encoded into disjoint bit positions in the destination 413662a816e89a9d77bf75e1328b09cf9235b4682aaJim Grosbach // opcode. x = unchanged, I = immediate value bit, S = sign extension bit 4147e294cfcf97cd7b94bf5c4de0f214480ec13adadJim Grosbach // 41509aa3f0ef35d9241c92439d74b8d5e9a81d814c2Bill Wendling // BL: xxxxxSIIIIIIIIII xxxxxIIIIIIIIIII 4167e294cfcf97cd7b94bf5c4de0f214480ec13adadJim Grosbach // 417662a816e89a9d77bf75e1328b09cf9235b4682aaJim Grosbach // Note that the halfwords are stored high first, low second; so we need 418662a816e89a9d77bf75e1328b09cf9235b4682aaJim Grosbach // to transpose the fixup value here to map properly. 419298c8e12ea063f7522c59d2a297b47a879b6ed55Rafael Espindola unsigned isNeg = (int64_t(Value - 4) < 0) ? 1 : 0; 420797b7aab35d815a48f58ce7f7b0b8d0fe06c92afBill Wendling uint32_t Binary = 0; 421797b7aab35d815a48f58ce7f7b0b8d0fe06c92afBill Wendling Value = 0x3fffff & ((Value - 4) >> 1); 422797b7aab35d815a48f58ce7f7b0b8d0fe06c92afBill Wendling Binary = (Value & 0x7ff) << 16; // Low imm11 value. 423797b7aab35d815a48f58ce7f7b0b8d0fe06c92afBill Wendling Binary |= (Value & 0x1ffc00) >> 11; // High imm10 value. 424797b7aab35d815a48f58ce7f7b0b8d0fe06c92afBill Wendling Binary |= isNeg << 10; // Sign bit. 42509aa3f0ef35d9241c92439d74b8d5e9a81d814c2Bill Wendling return Binary; 42609aa3f0ef35d9241c92439d74b8d5e9a81d814c2Bill Wendling } 42709aa3f0ef35d9241c92439d74b8d5e9a81d814c2Bill Wendling case ARM::fixup_arm_thumb_blx: { 42809aa3f0ef35d9241c92439d74b8d5e9a81d814c2Bill Wendling // The value doesn't encode the low two bits (always zero) and is offset by 42909aa3f0ef35d9241c92439d74b8d5e9a81d814c2Bill Wendling // four (see fixup_arm_thumb_cp). The value is encoded into disjoint bit 43009aa3f0ef35d9241c92439d74b8d5e9a81d814c2Bill Wendling // positions in the destination opcode. x = unchanged, I = immediate value 43109aa3f0ef35d9241c92439d74b8d5e9a81d814c2Bill Wendling // bit, S = sign extension bit, 0 = zero. 4327e294cfcf97cd7b94bf5c4de0f214480ec13adadJim Grosbach // 43309aa3f0ef35d9241c92439d74b8d5e9a81d814c2Bill Wendling // BLX: xxxxxSIIIIIIIIII xxxxxIIIIIIIIII0 4347e294cfcf97cd7b94bf5c4de0f214480ec13adadJim Grosbach // 43509aa3f0ef35d9241c92439d74b8d5e9a81d814c2Bill Wendling // Note that the halfwords are stored high first, low second; so we need 43609aa3f0ef35d9241c92439d74b8d5e9a81d814c2Bill Wendling // to transpose the fixup value here to map properly. 437298c8e12ea063f7522c59d2a297b47a879b6ed55Rafael Espindola unsigned isNeg = (int64_t(Value-4) < 0) ? 1 : 0; 438797b7aab35d815a48f58ce7f7b0b8d0fe06c92afBill Wendling uint32_t Binary = 0; 439797b7aab35d815a48f58ce7f7b0b8d0fe06c92afBill Wendling Value = 0xfffff & ((Value - 2) >> 2); 440797b7aab35d815a48f58ce7f7b0b8d0fe06c92afBill Wendling Binary = (Value & 0x3ff) << 17; // Low imm10L value. 441797b7aab35d815a48f58ce7f7b0b8d0fe06c92afBill Wendling Binary |= (Value & 0xffc00) >> 10; // High imm10H value. 442797b7aab35d815a48f58ce7f7b0b8d0fe06c92afBill Wendling Binary |= isNeg << 10; // Sign bit. 443662a816e89a9d77bf75e1328b09cf9235b4682aaJim Grosbach return Binary; 444662a816e89a9d77bf75e1328b09cf9235b4682aaJim Grosbach } 445b8958b031ec5163261f490f131780c5dc3d823d6Bill Wendling case ARM::fixup_arm_thumb_cp: 4460c2c217244573cdfb4be8b7fa62670412b4c1e71Jim Grosbach // Offset by 4, and don't encode the low two bits. Two bytes of that 4470c2c217244573cdfb4be8b7fa62670412b4c1e71Jim Grosbach // 'off by 4' is implicitly handled by the half-word ordering of the 4480c2c217244573cdfb4be8b7fa62670412b4c1e71Jim Grosbach // Thumb encoding, so we only need to adjust by 2 here. 4490c2c217244573cdfb4be8b7fa62670412b4c1e71Jim Grosbach return ((Value - 2) >> 2) & 0xff; 450b492a7c2134d3886f545f1b5ea55115d71529a10Jim Grosbach case ARM::fixup_arm_thumb_cb: { 451dff2f7151f695b86db8c4b0c6604463bdb8a63eaBill Wendling // Offset by 4 and don't encode the lower bit, which is always 0. 452dff2f7151f695b86db8c4b0c6604463bdb8a63eaBill Wendling uint32_t Binary = (Value - 4) >> 1; 45386abd48fd01080f08eec1b46f92c90308b03bfd4Owen Anderson return ((Binary & 0x20) << 4) | ((Binary & 0x1f) << 3); 454dff2f7151f695b86db8c4b0c6604463bdb8a63eaBill Wendling } 455e246717c3a36a913fd4200776ed621649bb2b624Jim Grosbach case ARM::fixup_arm_thumb_br: 456e246717c3a36a913fd4200776ed621649bb2b624Jim Grosbach // Offset by 4 and don't encode the lower bit, which is always 0. 457e246717c3a36a913fd4200776ed621649bb2b624Jim Grosbach return ((Value - 4) >> 1) & 0x7ff; 45801086451393ef33e82b6fad623989dd97dd70edfJim Grosbach case ARM::fixup_arm_thumb_bcc: 45901086451393ef33e82b6fad623989dd97dd70edfJim Grosbach // Offset by 4 and don't encode the lower bit, which is always 0. 46001086451393ef33e82b6fad623989dd97dd70edfJim Grosbach return ((Value - 4) >> 1) & 0xff; 4612f196747f15240691bd4e622f7995edfedf90f61Jim Grosbach case ARM::fixup_arm_pcrel_10_unscaled: { 4622f196747f15240691bd4e622f7995edfedf90f61Jim Grosbach Value = Value - 8; // ARM fixups offset by an additional word and don't 4632f196747f15240691bd4e622f7995edfedf90f61Jim Grosbach // need to adjust for the half-word ordering. 4642f196747f15240691bd4e622f7995edfedf90f61Jim Grosbach bool isAdd = true; 4652f196747f15240691bd4e622f7995edfedf90f61Jim Grosbach if ((int64_t)Value < 0) { 4662f196747f15240691bd4e622f7995edfedf90f61Jim Grosbach Value = -Value; 4672f196747f15240691bd4e622f7995edfedf90f61Jim Grosbach isAdd = false; 4682f196747f15240691bd4e622f7995edfedf90f61Jim Grosbach } 4692f196747f15240691bd4e622f7995edfedf90f61Jim Grosbach assert ((Value < 256) && "Out of range pc-relative fixup value!"); 4702f196747f15240691bd4e622f7995edfedf90f61Jim Grosbach return Value | (isAdd << 23); 4712f196747f15240691bd4e622f7995edfedf90f61Jim Grosbach } 4720c2c217244573cdfb4be8b7fa62670412b4c1e71Jim Grosbach case ARM::fixup_arm_pcrel_10: 473e2e0f58809374265bd75edeefae8817e7ade62b4Owen Anderson Value = Value - 4; // ARM fixups offset by an additional word and don't 4740c2c217244573cdfb4be8b7fa62670412b4c1e71Jim Grosbach // need to adjust for the half-word ordering. 4750c2c217244573cdfb4be8b7fa62670412b4c1e71Jim Grosbach // Fall through. 4760c2c217244573cdfb4be8b7fa62670412b4c1e71Jim Grosbach case ARM::fixup_t2_pcrel_10: { 4770c2c217244573cdfb4be8b7fa62670412b4c1e71Jim Grosbach // Offset by 4, adjusted by two due to the half-word ordering of thumb. 478e2e0f58809374265bd75edeefae8817e7ade62b4Owen Anderson Value = Value - 4; 4790c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim bool isAdd = true; 4800c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim if ((int64_t)Value < 0) { 4810c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim Value = -Value; 4820c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim isAdd = false; 4830c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim } 4840c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim // These values don't encode the low two bits since they're always zero. 4850c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim Value >>= 2; 4860c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim assert ((Value < 256) && "Out of range pc-relative fixup value!"); 4870c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim Value |= isAdd << 23; 4880c2c217244573cdfb4be8b7fa62670412b4c1e71Jim Grosbach 4892f196747f15240691bd4e622f7995edfedf90f61Jim Grosbach // Same addressing mode as fixup_arm_pcrel_10, but with 16-bit halfwords 4902f196747f15240691bd4e622f7995edfedf90f61Jim Grosbach // swapped. 491d8e351b96f5fd7007fbdd636acaa1fc9f6e18f3cOwen Anderson if (Kind == ARM::fixup_t2_pcrel_10) { 49256a2535474dd4482c432b3c75c3dab4b2f3dd1e2Jim Grosbach uint32_t swapped = (Value & 0xFFFF0000) >> 16; 493255eafbd498e7d41ceef45ee0ad13bfde573ff82Owen Anderson swapped |= (Value & 0x0000FFFF) << 16; 494d8e351b96f5fd7007fbdd636acaa1fc9f6e18f3cOwen Anderson return swapped; 495d8e351b96f5fd7007fbdd636acaa1fc9f6e18f3cOwen Anderson } 4960c2c217244573cdfb4be8b7fa62670412b4c1e71Jim Grosbach 4970c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim return Value; 4980c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim } 4990c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim } 5000c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim} 5010c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim 502d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kimnamespace { 50352e635ea3512cfcd03587201b20100074e5b6ac9Bill Wendling 504d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim// FIXME: This should be in a separate file. 505d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim// ELF is an ELF of course... 506d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kimclass ELFARMAsmBackend : public ARMAsmBackend { 507d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kimpublic: 508dc9a8a378daf432d8dcfc178507afe149706f9a6Rafael Espindola uint8_t OSABI; 509d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach ELFARMAsmBackend(const Target &T, const StringRef TT, 510dc9a8a378daf432d8dcfc178507afe149706f9a6Rafael Espindola uint8_t _OSABI) 511dc9a8a378daf432d8dcfc178507afe149706f9a6Rafael Espindola : ARMAsmBackend(T, TT), OSABI(_OSABI) { } 512d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim 513ec3433852dd11e8ff60c9610b4c84468e5935f2bJim Grosbach void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, 514d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim uint64_t Value) const; 515d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim 516d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim MCObjectWriter *createObjectWriter(raw_ostream &OS) const { 51769bbda03918a18bd4477bb254d51346ee3033567Rafael Espindola return createARMELFObjectWriter(OS, OSABI); 518d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim } 519d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim}; 520d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim 52152e635ea3512cfcd03587201b20100074e5b6ac9Bill Wendling// FIXME: Raise this to share code between Darwin and ELF. 522ec3433852dd11e8ff60c9610b4c84468e5935f2bJim Grosbachvoid ELFARMAsmBackend::applyFixup(const MCFixup &Fixup, char *Data, 523179821ac1f282ef6f8d24d5ea346028aee8ba4c7Rafael Espindola unsigned DataSize, uint64_t Value) const { 52452e635ea3512cfcd03587201b20100074e5b6ac9Bill Wendling unsigned NumBytes = 4; // FIXME: 2 for Thumb 52585fed5e0c5bc010f967948a4af6b425a5a2f2bd0Jason W Kim Value = adjustFixupValue(Fixup.getKind(), Value); 526d832fa053b86f42a5bc1e55e979b61c1115a8053Bill Wendling if (!Value) return; // Doesn't change encoding. 52785fed5e0c5bc010f967948a4af6b425a5a2f2bd0Jason W Kim 52852e635ea3512cfcd03587201b20100074e5b6ac9Bill Wendling unsigned Offset = Fixup.getOffset(); 52952e635ea3512cfcd03587201b20100074e5b6ac9Bill Wendling 53052e635ea3512cfcd03587201b20100074e5b6ac9Bill Wendling // For each byte of the fragment that the fixup touches, mask in the bits from 53152e635ea3512cfcd03587201b20100074e5b6ac9Bill Wendling // the fixup value. The Value has been "split up" into the appropriate 53252e635ea3512cfcd03587201b20100074e5b6ac9Bill Wendling // bitfields above. 53352e635ea3512cfcd03587201b20100074e5b6ac9Bill Wendling for (unsigned i = 0; i != NumBytes; ++i) 53452e635ea3512cfcd03587201b20100074e5b6ac9Bill Wendling Data[Offset + i] |= uint8_t((Value >> (i * 8)) & 0xff); 535d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim} 536d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim 537d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim// FIXME: This should be in a separate file. 538d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kimclass DarwinARMAsmBackend : public ARMAsmBackend { 539d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kimpublic: 5401721324d97e2b05c9276ffe116dfb6c808521c2bOwen Anderson const object::mach::CPUSubtypeARM Subtype; 541d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach DarwinARMAsmBackend(const Target &T, const StringRef TT, 542d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach object::mach::CPUSubtypeARM st) 543d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach : ARMAsmBackend(T, TT), Subtype(st) { } 544d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim 545d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim MCObjectWriter *createObjectWriter(raw_ostream &OS) const { 5462fc689888623743502b62e979767dd5c71e692bbJim Grosbach return createARMMachObjectWriter(OS, /*Is64Bit=*/false, 5472fc689888623743502b62e979767dd5c71e692bbJim Grosbach object::mach::CTM_ARM, 5482fc689888623743502b62e979767dd5c71e692bbJim Grosbach Subtype); 549d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim } 550d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim 551ec3433852dd11e8ff60c9610b4c84468e5935f2bJim Grosbach void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, 5521721324d97e2b05c9276ffe116dfb6c808521c2bOwen Anderson uint64_t Value) const; 5531721324d97e2b05c9276ffe116dfb6c808521c2bOwen Anderson 554d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim virtual bool doesSectionRequireSymbols(const MCSection &Section) const { 555d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim return false; 556d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim } 557d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim}; 558d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim 559d832fa053b86f42a5bc1e55e979b61c1115a8053Bill Wendling/// getFixupKindNumBytes - The number of bytes the fixup may change. 560c466b937dbdbaabeef0097fe340de1b8f49a3508Jim Grosbachstatic unsigned getFixupKindNumBytes(unsigned Kind) { 561679cbd3b215b1769a6035e334f9009aeeb940dddJim Grosbach switch (Kind) { 562662a816e89a9d77bf75e1328b09cf9235b4682aaJim Grosbach default: 563662a816e89a9d77bf75e1328b09cf9235b4682aaJim Grosbach llvm_unreachable("Unknown fixup kind!"); 564b8958b031ec5163261f490f131780c5dc3d823d6Bill Wendling 5656ec6eeb692fa11b569af8b69b2bb11cc84f04926Jim Grosbach case FK_Data_1: 56601086451393ef33e82b6fad623989dd97dd70edfJim Grosbach case ARM::fixup_arm_thumb_bcc: 567b8958b031ec5163261f490f131780c5dc3d823d6Bill Wendling case ARM::fixup_arm_thumb_cp: 568d40963c4065432ec7e47879d3ca665a54ee903b6Jim Grosbach case ARM::fixup_thumb_adr_pcrel_10: 569b8958b031ec5163261f490f131780c5dc3d823d6Bill Wendling return 1; 570b8958b031ec5163261f490f131780c5dc3d823d6Bill Wendling 5716ec6eeb692fa11b569af8b69b2bb11cc84f04926Jim Grosbach case FK_Data_2: 572e246717c3a36a913fd4200776ed621649bb2b624Jim Grosbach case ARM::fixup_arm_thumb_br: 573b492a7c2134d3886f545f1b5ea55115d71529a10Jim Grosbach case ARM::fixup_arm_thumb_cb: 574dff2f7151f695b86db8c4b0c6604463bdb8a63eaBill Wendling return 2; 575dff2f7151f695b86db8c4b0c6604463bdb8a63eaBill Wendling 5762f196747f15240691bd4e622f7995edfedf90f61Jim Grosbach case ARM::fixup_arm_pcrel_10_unscaled: 577662a816e89a9d77bf75e1328b09cf9235b4682aaJim Grosbach case ARM::fixup_arm_ldst_pcrel_12: 578662a816e89a9d77bf75e1328b09cf9235b4682aaJim Grosbach case ARM::fixup_arm_pcrel_10: 579662a816e89a9d77bf75e1328b09cf9235b4682aaJim Grosbach case ARM::fixup_arm_adr_pcrel_12: 5807b25ecf6adbf3c4709c48033acfeb6ebbb4452abJim Grosbach case ARM::fixup_arm_bl: 5817b25ecf6adbf3c4709c48033acfeb6ebbb4452abJim Grosbach case ARM::fixup_arm_blx: 582685c350ae76b588e1f00c01a511fe8bd57f18394Jason W Kim case ARM::fixup_arm_condbranch: 583685c350ae76b588e1f00c01a511fe8bd57f18394Jason W Kim case ARM::fixup_arm_uncondbranch: 584662a816e89a9d77bf75e1328b09cf9235b4682aaJim Grosbach return 3; 585b8958b031ec5163261f490f131780c5dc3d823d6Bill Wendling 586b8958b031ec5163261f490f131780c5dc3d823d6Bill Wendling case FK_Data_4: 587d7b3f5870d9d04351d9cd363d9d6af01482a2eb8Owen Anderson case ARM::fixup_t2_ldst_pcrel_12: 588c266600bec4b5ba0ee93ffdfeaafcab8f1295145Owen Anderson case ARM::fixup_t2_condbranch: 589c266600bec4b5ba0ee93ffdfeaafcab8f1295145Owen Anderson case ARM::fixup_t2_uncondbranch: 590d8e351b96f5fd7007fbdd636acaa1fc9f6e18f3cOwen Anderson case ARM::fixup_t2_pcrel_10: 591a838a25d59838adfa91463f6a918ae3adeb352c1Owen Anderson case ARM::fixup_t2_adr_pcrel_12: 592662a816e89a9d77bf75e1328b09cf9235b4682aaJim Grosbach case ARM::fixup_arm_thumb_bl: 59309aa3f0ef35d9241c92439d74b8d5e9a81d814c2Bill Wendling case ARM::fixup_arm_thumb_blx: 594f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng case ARM::fixup_arm_movt_hi16: 595f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng case ARM::fixup_arm_movw_lo16: 596f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng case ARM::fixup_arm_movt_hi16_pcrel: 597f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng case ARM::fixup_arm_movw_lo16_pcrel: 598f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng case ARM::fixup_t2_movt_hi16: 599f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng case ARM::fixup_t2_movw_lo16: 600f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng case ARM::fixup_t2_movt_hi16_pcrel: 601f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng case ARM::fixup_t2_movw_lo16_pcrel: 602662a816e89a9d77bf75e1328b09cf9235b4682aaJim Grosbach return 4; 603679cbd3b215b1769a6035e334f9009aeeb940dddJim Grosbach } 604679cbd3b215b1769a6035e334f9009aeeb940dddJim Grosbach} 605679cbd3b215b1769a6035e334f9009aeeb940dddJim Grosbach 606ec3433852dd11e8ff60c9610b4c84468e5935f2bJim Grosbachvoid DarwinARMAsmBackend::applyFixup(const MCFixup &Fixup, char *Data, 607179821ac1f282ef6f8d24d5ea346028aee8ba4c7Rafael Espindola unsigned DataSize, uint64_t Value) const { 608c466b937dbdbaabeef0097fe340de1b8f49a3508Jim Grosbach unsigned NumBytes = getFixupKindNumBytes(Fixup.getKind()); 609679cbd3b215b1769a6035e334f9009aeeb940dddJim Grosbach Value = adjustFixupValue(Fixup.getKind(), Value); 610d832fa053b86f42a5bc1e55e979b61c1115a8053Bill Wendling if (!Value) return; // Doesn't change encoding. 611d832fa053b86f42a5bc1e55e979b61c1115a8053Bill Wendling 612d832fa053b86f42a5bc1e55e979b61c1115a8053Bill Wendling unsigned Offset = Fixup.getOffset(); 613d832fa053b86f42a5bc1e55e979b61c1115a8053Bill Wendling assert(Offset + NumBytes <= DataSize && "Invalid fixup offset!"); 614679cbd3b215b1769a6035e334f9009aeeb940dddJim Grosbach 615679cbd3b215b1769a6035e334f9009aeeb940dddJim Grosbach // For each byte of the fragment that the fixup touches, mask in the 616679cbd3b215b1769a6035e334f9009aeeb940dddJim Grosbach // bits from the fixup value. 617679cbd3b215b1769a6035e334f9009aeeb940dddJim Grosbach for (unsigned i = 0; i != NumBytes; ++i) 618d832fa053b86f42a5bc1e55e979b61c1115a8053Bill Wendling Data[Offset + i] |= uint8_t((Value >> (i * 8)) & 0xff); 619d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim} 62052e635ea3512cfcd03587201b20100074e5b6ac9Bill Wendling 621f73fd7278f2bebd435c84c55a79db8ccb07d3534Jim Grosbach} // end anonymous namespace 622d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim 62378c10eeaa57d1c6c4b7781d3c0bcb0cfbbc43b5cEvan ChengMCAsmBackend *llvm::createARMAsmBackend(const Target &T, StringRef TT) { 6241721324d97e2b05c9276ffe116dfb6c808521c2bOwen Anderson Triple TheTriple(TT); 625912225e18559a73228099330a4c253fdccf9fa3dDaniel Dunbar 626912225e18559a73228099330a4c253fdccf9fa3dDaniel Dunbar if (TheTriple.isOSDarwin()) { 627a6eb2562b62fc293295f2fede2608753563e7005Evan Cheng if (TheTriple.getArchName() == "armv4t" || 628a6eb2562b62fc293295f2fede2608753563e7005Evan Cheng TheTriple.getArchName() == "thumbv4t") 629d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach return new DarwinARMAsmBackend(T, TT, object::mach::CSARM_V4T); 630a6eb2562b62fc293295f2fede2608753563e7005Evan Cheng else if (TheTriple.getArchName() == "armv5e" || 631a6eb2562b62fc293295f2fede2608753563e7005Evan Cheng TheTriple.getArchName() == "thumbv5e") 632d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach return new DarwinARMAsmBackend(T, TT, object::mach::CSARM_V5TEJ); 633a6eb2562b62fc293295f2fede2608753563e7005Evan Cheng else if (TheTriple.getArchName() == "armv6" || 6341721324d97e2b05c9276ffe116dfb6c808521c2bOwen Anderson TheTriple.getArchName() == "thumbv6") 635d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach return new DarwinARMAsmBackend(T, TT, object::mach::CSARM_V6); 636d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach return new DarwinARMAsmBackend(T, TT, object::mach::CSARM_V7); 6371721324d97e2b05c9276ffe116dfb6c808521c2bOwen Anderson } 638912225e18559a73228099330a4c253fdccf9fa3dDaniel Dunbar 639912225e18559a73228099330a4c253fdccf9fa3dDaniel Dunbar if (TheTriple.isOSWindows()) 640d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim assert(0 && "Windows not supported on ARM"); 641912225e18559a73228099330a4c253fdccf9fa3dDaniel Dunbar 642dc9a8a378daf432d8dcfc178507afe149706f9a6Rafael Espindola uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(Triple(TT).getOS()); 643dc9a8a378daf432d8dcfc178507afe149706f9a6Rafael Espindola return new ELFARMAsmBackend(T, TT, OSABI); 644d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim} 645