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" 11d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "MCTargetDesc/ARMAddressingModes.h" 12be74029f44c32efc09274a16cbff588ad10dc5eaEvan Cheng#include "MCTargetDesc/ARMBaseInfo.h" 13be74029f44c32efc09274a16cbff588ad10dc5eaEvan Cheng#include "MCTargetDesc/ARMFixupKinds.h" 1419d54337169ae4af2d44ae39664d0bac1ae0309cQuentin Colombet#include "llvm/ADT/StringSwitch.h" 15d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/MC/MCAsmBackend.h" 16d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim#include "llvm/MC/MCAssembler.h" 177a3afa91ad8f68428373948fc16375e99bff3c6fJim Grosbach#include "llvm/MC/MCContext.h" 185be6d2af38c29e3653998978345220974cc40c01Jim Grosbach#include "llvm/MC/MCDirectives.h" 19285b3e5b61af15f11e59a7700375aefa2a326bd8Rafael Espindola#include "llvm/MC/MCELFObjectWriter.h" 20d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim#include "llvm/MC/MCExpr.h" 21f1d0f7781e766df878bec4e7977fa3204374f394Craig Topper#include "llvm/MC/MCFixupKindInfo.h" 22aa4b7dd13ba83152473950d7014a29686dc7eef6Daniel Dunbar#include "llvm/MC/MCMachObjectWriter.h" 23d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim#include "llvm/MC/MCObjectWriter.h" 24d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim#include "llvm/MC/MCSectionELF.h" 25d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim#include "llvm/MC/MCSectionMachO.h" 26d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach#include "llvm/MC/MCSubtargetInfo.h" 279b5b125c34b47e0e7eef2548acee8bf1448c4b71Jim Grosbach#include "llvm/MC/MCValue.h" 28eecb858ca86fa949c06f819d6127e2ac68d165c8Wesley Peck#include "llvm/Support/ELF.h" 29d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim#include "llvm/Support/ErrorHandling.h" 305510728d28bb1ee04abc32da3d21b7df12948053Charles Davis#include "llvm/Support/MachO.h" 31d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim#include "llvm/Support/raw_ostream.h" 32d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kimusing namespace llvm; 33d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim 34d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kimnamespace { 356024c97ffa15766bc0f200ffd309d9e017ae0d4bRafael Espindolaclass ARMELFObjectWriter : public MCELFObjectTargetWriter { 366024c97ffa15766bc0f200ffd309d9e017ae0d4bRafael Espindolapublic: 37dc9a8a378daf432d8dcfc178507afe149706f9a6Rafael Espindola ARMELFObjectWriter(uint8_t OSABI) 38dc9a8a378daf432d8dcfc178507afe149706f9a6Rafael Espindola : MCELFObjectTargetWriter(/*Is64Bit*/ false, OSABI, ELF::EM_ARM, 39bff66a86e6e44dc7424cd2d7719ac80630b3a5f8Rafael Espindola /*HasRelocationAddend*/ false) {} 406024c97ffa15766bc0f200ffd309d9e017ae0d4bRafael Espindola}; 416024c97ffa15766bc0f200ffd309d9e017ae0d4bRafael Espindola 4278c10eeaa57d1c6c4b7781d3c0bcb0cfbbc43b5cEvan Chengclass ARMAsmBackend : public MCAsmBackend { 43d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach const MCSubtargetInfo* STI; 4436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines bool isThumbMode; // Currently emitting Thumb code. 4536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines bool IsLittleEndian; // Big or little endian. 46d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kimpublic: 4736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ARMAsmBackend(const Target &T, const StringRef TT, bool IsLittle) 48d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach : MCAsmBackend(), STI(ARM_MC::createARMMCSubtargetInfo(TT, "", "")), 4936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines isThumbMode(TT.startswith("thumb")), IsLittleEndian(IsLittle) {} 50d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach 51d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach ~ARMAsmBackend() { 52d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach delete STI; 53d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach } 54d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim 5536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines unsigned getNumFixupKinds() const override { 5636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return ARM::NumTargetFixupKinds; 5736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 582761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar 59d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach bool hasNOP() const { 60d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach return (STI->getFeatureBits() & ARM::HasV6T2Ops) != 0; 61d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach } 62d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach 6336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override { 6436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const static MCFixupKindInfo InfosLE[ARM::NumTargetFixupKinds] = { 652761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar// This table *must* be in the order that the fixup_* kinds are defined in 662761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar// ARMFixupKinds.h. 672761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar// 682761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar// Name Offset (bits) Size (bits) Flags 692abba8496cb394af53b531e95067d5cae78bb9eeJim Grosbach{ "fixup_arm_ldst_pcrel_12", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, 702761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar{ "fixup_t2_ldst_pcrel_12", 0, 32, MCFixupKindInfo::FKF_IsPCRel | 712761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, 722f196747f15240691bd4e622f7995edfedf90f61Jim Grosbach{ "fixup_arm_pcrel_10_unscaled", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, 73681460f954e9c13ffd2f02f27bba048ccf90abafJim Grosbach{ "fixup_arm_pcrel_10", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, 742761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar{ "fixup_t2_pcrel_10", 0, 32, MCFixupKindInfo::FKF_IsPCRel | 752761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, 762761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar{ "fixup_thumb_adr_pcrel_10",0, 8, MCFixupKindInfo::FKF_IsPCRel | 772761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, 782abba8496cb394af53b531e95067d5cae78bb9eeJim Grosbach{ "fixup_arm_adr_pcrel_12", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, 792761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar{ "fixup_t2_adr_pcrel_12", 0, 32, MCFixupKindInfo::FKF_IsPCRel | 802761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, 81685c350ae76b588e1f00c01a511fe8bd57f18394Jason W Kim{ "fixup_arm_condbranch", 0, 24, MCFixupKindInfo::FKF_IsPCRel }, 82685c350ae76b588e1f00c01a511fe8bd57f18394Jason W Kim{ "fixup_arm_uncondbranch", 0, 24, MCFixupKindInfo::FKF_IsPCRel }, 832761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar{ "fixup_t2_condbranch", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, 842761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar{ "fixup_t2_uncondbranch", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, 852761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar{ "fixup_arm_thumb_br", 0, 16, MCFixupKindInfo::FKF_IsPCRel }, 86cb0809b82b126e79b99755ae4fc3d9733faea038James Molloy{ "fixup_arm_uncondbl", 0, 24, MCFixupKindInfo::FKF_IsPCRel }, 87cb0809b82b126e79b99755ae4fc3d9733faea038James Molloy{ "fixup_arm_condbl", 0, 24, MCFixupKindInfo::FKF_IsPCRel }, 887b25ecf6adbf3c4709c48033acfeb6ebbb4452abJim Grosbach{ "fixup_arm_blx", 0, 24, MCFixupKindInfo::FKF_IsPCRel }, 892761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar{ "fixup_arm_thumb_bl", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, 9090b5a08e1ffc4a1c18f7fa964ca561fa4b03c314Jim Grosbach{ "fixup_arm_thumb_blx", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, 912761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar{ "fixup_arm_thumb_cb", 0, 16, MCFixupKindInfo::FKF_IsPCRel }, 929da7892fbe1c9e7c592c5928e36724a0e190a777Jim Grosbach{ "fixup_arm_thumb_cp", 0, 8, MCFixupKindInfo::FKF_IsPCRel | 939da7892fbe1c9e7c592c5928e36724a0e190a777Jim Grosbach MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, 94fea51fc007598176d48fb7319a9bf471efb93127Eric Christopher{ "fixup_arm_thumb_bcc", 0, 8, MCFixupKindInfo::FKF_IsPCRel }, 95f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng// movw / movt: 16-bits immediate but scattered into two chunks 0 - 12, 16 - 19. 96f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng{ "fixup_arm_movt_hi16", 0, 20, 0 }, 97f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng{ "fixup_arm_movw_lo16", 0, 20, 0 }, 98f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng{ "fixup_t2_movt_hi16", 0, 20, 0 }, 99f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng{ "fixup_t2_movw_lo16", 0, 20, 0 }, 10036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines }; 10136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const static MCFixupKindInfo InfosBE[ARM::NumTargetFixupKinds] = { 10236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// This table *must* be in the order that the fixup_* kinds are defined in 10336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// ARMFixupKinds.h. 10436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// 10536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// Name Offset (bits) Size (bits) Flags 10636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines{ "fixup_arm_ldst_pcrel_12", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, 10736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines{ "fixup_t2_ldst_pcrel_12", 0, 32, MCFixupKindInfo::FKF_IsPCRel | 10836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, 10936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines{ "fixup_arm_pcrel_10_unscaled", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, 11036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines{ "fixup_arm_pcrel_10", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, 11136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines{ "fixup_t2_pcrel_10", 0, 32, MCFixupKindInfo::FKF_IsPCRel | 11236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, 11336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines{ "fixup_thumb_adr_pcrel_10",8, 8, MCFixupKindInfo::FKF_IsPCRel | 11436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, 11536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines{ "fixup_arm_adr_pcrel_12", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, 11636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines{ "fixup_t2_adr_pcrel_12", 0, 32, MCFixupKindInfo::FKF_IsPCRel | 11736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, 11836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines{ "fixup_arm_condbranch", 8, 24, MCFixupKindInfo::FKF_IsPCRel }, 11936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines{ "fixup_arm_uncondbranch", 8, 24, MCFixupKindInfo::FKF_IsPCRel }, 12036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines{ "fixup_t2_condbranch", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, 12136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines{ "fixup_t2_uncondbranch", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, 12236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines{ "fixup_arm_thumb_br", 0, 16, MCFixupKindInfo::FKF_IsPCRel }, 12336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines{ "fixup_arm_uncondbl", 8, 24, MCFixupKindInfo::FKF_IsPCRel }, 12436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines{ "fixup_arm_condbl", 8, 24, MCFixupKindInfo::FKF_IsPCRel }, 12536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines{ "fixup_arm_blx", 8, 24, MCFixupKindInfo::FKF_IsPCRel }, 12636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines{ "fixup_arm_thumb_bl", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, 12736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines{ "fixup_arm_thumb_blx", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, 12836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines{ "fixup_arm_thumb_cb", 0, 16, MCFixupKindInfo::FKF_IsPCRel }, 12936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines{ "fixup_arm_thumb_cp", 8, 8, MCFixupKindInfo::FKF_IsPCRel | 13036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, 13136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines{ "fixup_arm_thumb_bcc", 8, 8, MCFixupKindInfo::FKF_IsPCRel }, 13236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// movw / movt: 16-bits immediate but scattered into two chunks 0 - 12, 16 - 19. 13336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines{ "fixup_arm_movt_hi16", 12, 20, 0 }, 13436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines{ "fixup_arm_movw_lo16", 12, 20, 0 }, 13536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines{ "fixup_t2_movt_hi16", 12, 20, 0 }, 13636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines{ "fixup_t2_movw_lo16", 12, 20, 0 }, 1372761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar }; 1382761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar 1392761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar if (Kind < FirstTargetFixupKind) 14078c10eeaa57d1c6c4b7781d3c0bcb0cfbbc43b5cEvan Cheng return MCAsmBackend::getFixupKindInfo(Kind); 1412761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar 1422761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() && 1432761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar "Invalid kind!"); 14436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return (IsLittleEndian ? InfosLE : InfosBE)[Kind - FirstTargetFixupKind]; 1452761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar } 1462761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar 1479b5b125c34b47e0e7eef2548acee8bf1448c4b71Jim Grosbach /// processFixupValue - Target hook to process the literal value of a fixup 1489b5b125c34b47e0e7eef2548acee8bf1448c4b71Jim Grosbach /// if necessary. 1499b5b125c34b47e0e7eef2548acee8bf1448c4b71Jim Grosbach void processFixupValue(const MCAssembler &Asm, const MCAsmLayout &Layout, 1509b5b125c34b47e0e7eef2548acee8bf1448c4b71Jim Grosbach const MCFixup &Fixup, const MCFragment *DF, 15136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const MCValue &Target, uint64_t &Value, 15236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines bool &IsResolved) override; 1539b5b125c34b47e0e7eef2548acee8bf1448c4b71Jim Grosbach 154cb4028b91d7c1b0163d1b6c85911668d3d19c75aBenjamin Kramer 155cb4028b91d7c1b0163d1b6c85911668d3d19c75aBenjamin Kramer void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, 15636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint64_t Value, bool IsPCRel) const override; 157cb4028b91d7c1b0163d1b6c85911668d3d19c75aBenjamin Kramer 15836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines bool mayNeedRelaxation(const MCInst &Inst) const override; 159d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim 16036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value, 161251040bc18eedfa56d01fe92836e55cfd8c5d990Eli Bendersky const MCRelaxableFragment *DF, 16236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const MCAsmLayout &Layout) const override; 163370b78d795154899a22ca2b4674e890661ff1d59Jim Grosbach 16436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines void relaxInstruction(const MCInst &Inst, MCInst &Res) const override; 165d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim 16636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override; 1673787a40e038d6444a1b0e93f1cdc55fb006a5392Jim Grosbach 16836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines void handleAssemblerFlag(MCAssemblerFlag Flag) override { 1695be6d2af38c29e3653998978345220974cc40c01Jim Grosbach switch (Flag) { 1705be6d2af38c29e3653998978345220974cc40c01Jim Grosbach default: break; 1715be6d2af38c29e3653998978345220974cc40c01Jim Grosbach case MCAF_Code16: 1725be6d2af38c29e3653998978345220974cc40c01Jim Grosbach setIsThumb(true); 1735be6d2af38c29e3653998978345220974cc40c01Jim Grosbach break; 1745be6d2af38c29e3653998978345220974cc40c01Jim Grosbach case MCAF_Code32: 1755be6d2af38c29e3653998978345220974cc40c01Jim Grosbach setIsThumb(false); 1765be6d2af38c29e3653998978345220974cc40c01Jim Grosbach break; 1775be6d2af38c29e3653998978345220974cc40c01Jim Grosbach } 1783787a40e038d6444a1b0e93f1cdc55fb006a5392Jim Grosbach } 1795be6d2af38c29e3653998978345220974cc40c01Jim Grosbach 1805be6d2af38c29e3653998978345220974cc40c01Jim Grosbach unsigned getPointerSize() const { return 4; } 1815be6d2af38c29e3653998978345220974cc40c01Jim Grosbach bool isThumb() const { return isThumbMode; } 1825be6d2af38c29e3653998978345220974cc40c01Jim Grosbach void setIsThumb(bool it) { isThumbMode = it; } 18336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines bool isLittle() const { return IsLittleEndian; } 184d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim}; 185b75c651e22a63907b727664f044283bf9c9fb885Chris Lattner} // end anonymous namespace 186d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim 187f503ef6800fcbda99d6ae581ee8cfe3204becb3cJim Grosbachstatic unsigned getRelaxedOpcode(unsigned Op) { 188f503ef6800fcbda99d6ae581ee8cfe3204becb3cJim Grosbach switch (Op) { 189f503ef6800fcbda99d6ae581ee8cfe3204becb3cJim Grosbach default: return Op; 190256ba4f42a16da2b3ffc757aa7bf191890765580Jim Grosbach case ARM::tBcc: return ARM::t2Bcc; 19102265382929b0275d7b7b334eab5e2fd34e1b9feMihai Popa case ARM::tLDRpci: return ARM::t2LDRpci; 1929363c58dc2473a6470d3e7037afe8a215bee7e3eJim Grosbach case ARM::tADR: return ARM::t2ADR; 193fa1f74470a51a57b7b8feb4c4ba18501c3f2709aJim Grosbach case ARM::tB: return ARM::t2B; 19436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case ARM::tCBZ: return ARM::tHINT; 19536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case ARM::tCBNZ: return ARM::tHINT; 196f503ef6800fcbda99d6ae581ee8cfe3204becb3cJim Grosbach } 197f503ef6800fcbda99d6ae581ee8cfe3204becb3cJim Grosbach} 198f503ef6800fcbda99d6ae581ee8cfe3204becb3cJim Grosbach 199ec3433852dd11e8ff60c9610b4c84468e5935f2bJim Grosbachbool ARMAsmBackend::mayNeedRelaxation(const MCInst &Inst) const { 200f503ef6800fcbda99d6ae581ee8cfe3204becb3cJim Grosbach if (getRelaxedOpcode(Inst.getOpcode()) != Inst.getOpcode()) 201f503ef6800fcbda99d6ae581ee8cfe3204becb3cJim Grosbach return true; 202d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim return false; 203d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim} 204d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim 205370b78d795154899a22ca2b4674e890661ff1d59Jim Grosbachbool ARMAsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup, 206370b78d795154899a22ca2b4674e890661ff1d59Jim Grosbach uint64_t Value, 207251040bc18eedfa56d01fe92836e55cfd8c5d990Eli Bendersky const MCRelaxableFragment *DF, 208370b78d795154899a22ca2b4674e890661ff1d59Jim Grosbach const MCAsmLayout &Layout) const { 209e545ee20f1b6ea6c03919cc9bc1a4a059c2f03b6Benjamin Kramer switch ((unsigned)Fixup.getKind()) { 210fa1f74470a51a57b7b8feb4c4ba18501c3f2709aJim Grosbach case ARM::fixup_arm_thumb_br: { 211fa1f74470a51a57b7b8feb4c4ba18501c3f2709aJim Grosbach // Relaxing tB to t2B. tB has a signed 12-bit displacement with the 212fa1f74470a51a57b7b8feb4c4ba18501c3f2709aJim Grosbach // low bit being an implied zero. There's an implied +4 offset for the 213fa1f74470a51a57b7b8feb4c4ba18501c3f2709aJim Grosbach // branch, so we adjust the other way here to determine what's 214fa1f74470a51a57b7b8feb4c4ba18501c3f2709aJim Grosbach // encodable. 215fa1f74470a51a57b7b8feb4c4ba18501c3f2709aJim Grosbach // 216fa1f74470a51a57b7b8feb4c4ba18501c3f2709aJim Grosbach // Relax if the value is too big for a (signed) i8. 217fa1f74470a51a57b7b8feb4c4ba18501c3f2709aJim Grosbach int64_t Offset = int64_t(Value) - 4; 218fa1f74470a51a57b7b8feb4c4ba18501c3f2709aJim Grosbach return Offset > 2046 || Offset < -2048; 219fa1f74470a51a57b7b8feb4c4ba18501c3f2709aJim Grosbach } 220256ba4f42a16da2b3ffc757aa7bf191890765580Jim Grosbach case ARM::fixup_arm_thumb_bcc: { 221256ba4f42a16da2b3ffc757aa7bf191890765580Jim Grosbach // Relaxing tBcc to t2Bcc. tBcc has a signed 9-bit displacement with the 222256ba4f42a16da2b3ffc757aa7bf191890765580Jim Grosbach // low bit being an implied zero. There's an implied +4 offset for the 223256ba4f42a16da2b3ffc757aa7bf191890765580Jim Grosbach // branch, so we adjust the other way here to determine what's 224256ba4f42a16da2b3ffc757aa7bf191890765580Jim Grosbach // encodable. 225256ba4f42a16da2b3ffc757aa7bf191890765580Jim Grosbach // 226256ba4f42a16da2b3ffc757aa7bf191890765580Jim Grosbach // Relax if the value is too big for a (signed) i8. 227256ba4f42a16da2b3ffc757aa7bf191890765580Jim Grosbach int64_t Offset = int64_t(Value) - 4; 228256ba4f42a16da2b3ffc757aa7bf191890765580Jim Grosbach return Offset > 254 || Offset < -256; 229256ba4f42a16da2b3ffc757aa7bf191890765580Jim Grosbach } 2309363c58dc2473a6470d3e7037afe8a215bee7e3eJim Grosbach case ARM::fixup_thumb_adr_pcrel_10: 231256ba4f42a16da2b3ffc757aa7bf191890765580Jim Grosbach case ARM::fixup_arm_thumb_cp: { 232d26bad079d6977309699e0bc9203451904acbd86Jim Grosbach // If the immediate is negative, greater than 1020, or not a multiple 233d26bad079d6977309699e0bc9203451904acbd86Jim Grosbach // of four, the wide version of the instruction must be used. 234256ba4f42a16da2b3ffc757aa7bf191890765580Jim Grosbach int64_t Offset = int64_t(Value) - 4; 235d26bad079d6977309699e0bc9203451904acbd86Jim Grosbach return Offset > 1020 || Offset < 0 || Offset & 3; 236256ba4f42a16da2b3ffc757aa7bf191890765580Jim Grosbach } 23736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case ARM::fixup_arm_thumb_cb: 23836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // If we have a Thumb CBZ or CBNZ instruction and its target is the next 23936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // instruction it is is actually out of range for the instruction. 24036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // It will be changed to a NOP. 24136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines int64_t Offset = (Value & ~1); 24236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return Offset == 2; 243256ba4f42a16da2b3ffc757aa7bf191890765580Jim Grosbach } 244e545ee20f1b6ea6c03919cc9bc1a4a059c2f03b6Benjamin Kramer llvm_unreachable("Unexpected fixup kind in fixupNeedsRelaxation()!"); 245370b78d795154899a22ca2b4674e890661ff1d59Jim Grosbach} 246370b78d795154899a22ca2b4674e890661ff1d59Jim Grosbach 247ec3433852dd11e8ff60c9610b4c84468e5935f2bJim Grosbachvoid ARMAsmBackend::relaxInstruction(const MCInst &Inst, MCInst &Res) const { 248f503ef6800fcbda99d6ae581ee8cfe3204becb3cJim Grosbach unsigned RelaxedOp = getRelaxedOpcode(Inst.getOpcode()); 249f503ef6800fcbda99d6ae581ee8cfe3204becb3cJim Grosbach 250f503ef6800fcbda99d6ae581ee8cfe3204becb3cJim Grosbach // Sanity check w/ diagnostic if we get here w/ a bogus instruction. 251f503ef6800fcbda99d6ae581ee8cfe3204becb3cJim Grosbach if (RelaxedOp == Inst.getOpcode()) { 252f503ef6800fcbda99d6ae581ee8cfe3204becb3cJim Grosbach SmallString<256> Tmp; 253f503ef6800fcbda99d6ae581ee8cfe3204becb3cJim Grosbach raw_svector_ostream OS(Tmp); 254f503ef6800fcbda99d6ae581ee8cfe3204becb3cJim Grosbach Inst.dump_pretty(OS); 255f503ef6800fcbda99d6ae581ee8cfe3204becb3cJim Grosbach OS << "\n"; 256f503ef6800fcbda99d6ae581ee8cfe3204becb3cJim Grosbach report_fatal_error("unexpected instruction to relax: " + OS.str()); 257f503ef6800fcbda99d6ae581ee8cfe3204becb3cJim Grosbach } 258f503ef6800fcbda99d6ae581ee8cfe3204becb3cJim Grosbach 25936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // If we are changing Thumb CBZ or CBNZ instruction to a NOP, aka tHINT, we 26036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // have to change the operands too. 26136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if ((Inst.getOpcode() == ARM::tCBZ || Inst.getOpcode() == ARM::tCBNZ) && 26236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines RelaxedOp == ARM::tHINT) { 26336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Res.setOpcode(RelaxedOp); 26436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Res.addOperand(MCOperand::CreateImm(0)); 26536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Res.addOperand(MCOperand::CreateImm(14)); 26636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Res.addOperand(MCOperand::CreateReg(0)); 26736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return; 26836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 26936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 27036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // The rest of instructions we're relaxing have the same operands. 271f503ef6800fcbda99d6ae581ee8cfe3204becb3cJim Grosbach // We just need to update to the proper opcode. 272f503ef6800fcbda99d6ae581ee8cfe3204becb3cJim Grosbach Res = Inst; 273f503ef6800fcbda99d6ae581ee8cfe3204becb3cJim Grosbach Res.setOpcode(RelaxedOp); 274d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim} 275d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim 276ec3433852dd11e8ff60c9610b4c84468e5935f2bJim Grosbachbool ARMAsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW) const { 277d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach const uint16_t Thumb1_16bitNopEncoding = 0x46c0; // using MOV r8,r8 278d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach const uint16_t Thumb2_16bitNopEncoding = 0xbf00; // NOP 279f2a1c83c86ceefb9a241aa728d1d1239a64b894eDavid Sehr const uint32_t ARMv4_NopEncoding = 0xe1a00000; // using MOV r0,r0 280b84acd24687c721e3da46bb56a94d393bc5a8cbcJim Grosbach const uint32_t ARMv6T2_NopEncoding = 0xe320f000; // NOP 2815be6d2af38c29e3653998978345220974cc40c01Jim Grosbach if (isThumb()) { 282d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach const uint16_t nopEncoding = hasNOP() ? Thumb2_16bitNopEncoding 283d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach : Thumb1_16bitNopEncoding; 284a3dbd3a2444f2531763ba05b64a30932542a631fJim Grosbach uint64_t NumNops = Count / 2; 285a3dbd3a2444f2531763ba05b64a30932542a631fJim Grosbach for (uint64_t i = 0; i != NumNops; ++i) 286d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach OW->Write16(nopEncoding); 287a3dbd3a2444f2531763ba05b64a30932542a631fJim Grosbach if (Count & 1) 288a3dbd3a2444f2531763ba05b64a30932542a631fJim Grosbach OW->Write8(0); 2895be6d2af38c29e3653998978345220974cc40c01Jim Grosbach return true; 2905be6d2af38c29e3653998978345220974cc40c01Jim Grosbach } 2915be6d2af38c29e3653998978345220974cc40c01Jim Grosbach // ARM mode 292d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach const uint32_t nopEncoding = hasNOP() ? ARMv6T2_NopEncoding 293d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach : ARMv4_NopEncoding; 294a3dbd3a2444f2531763ba05b64a30932542a631fJim Grosbach uint64_t NumNops = Count / 4; 295a3dbd3a2444f2531763ba05b64a30932542a631fJim Grosbach for (uint64_t i = 0; i != NumNops; ++i) 296d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach OW->Write32(nopEncoding); 297d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach // FIXME: should this function return false when unable to write exactly 298d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach // 'Count' bytes with NOP encodings? 299a3dbd3a2444f2531763ba05b64a30932542a631fJim Grosbach switch (Count % 4) { 300a3dbd3a2444f2531763ba05b64a30932542a631fJim Grosbach default: break; // No leftover bytes to write 301a3dbd3a2444f2531763ba05b64a30932542a631fJim Grosbach case 1: OW->Write8(0); break; 302a3dbd3a2444f2531763ba05b64a30932542a631fJim Grosbach case 2: OW->Write16(0); break; 303a3dbd3a2444f2531763ba05b64a30932542a631fJim Grosbach case 3: OW->Write16(0); OW->Write8(0xa0); break; 304a3dbd3a2444f2531763ba05b64a30932542a631fJim Grosbach } 305a3dbd3a2444f2531763ba05b64a30932542a631fJim Grosbach 306cecbc3d28277ff4916326311cbf87335ed05d106Rafael Espindola return true; 30787dc3aa2d87871f1affc6f3f2fa587c7b6725d83Jim Grosbach} 308d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim 309dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesstatic uint32_t swapHalfWords(uint32_t Value, bool IsLittleEndian) { 310dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines if (IsLittleEndian) { 311dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // Note that the halfwords are stored high first and low second in thumb; 312dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // so we need to swap the fixup value here to map properly. 313dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines uint32_t Swapped = (Value & 0xFFFF0000) >> 16; 314dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Swapped |= (Value & 0x0000FFFF) << 16; 315dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return Swapped; 316dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } 317dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines else 318dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return Value; 319dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines} 320dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 321dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesstatic uint32_t joinHalfWords(uint32_t FirstHalf, uint32_t SecondHalf, 322dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines bool IsLittleEndian) { 323dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines uint32_t Value; 324dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 325dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines if (IsLittleEndian) { 326dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Value = (SecondHalf & 0xFFFF) << 16; 327dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Value |= (FirstHalf & 0xFFFF); 328dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } else { 329dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Value = (SecondHalf & 0xFFFF); 330dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Value |= (FirstHalf & 0xFFFF) << 16; 331dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } 332dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 333dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return Value; 334dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines} 335dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 3367a3afa91ad8f68428373948fc16375e99bff3c6fJim Grosbachstatic unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value, 337dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines bool IsPCRel, MCContext *Ctx, 338dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines bool IsLittleEndian) { 3397a3afa91ad8f68428373948fc16375e99bff3c6fJim Grosbach unsigned Kind = Fixup.getKind(); 3400c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim switch (Kind) { 3410c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim default: 3420c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim llvm_unreachable("Unknown fixup kind!"); 3436ec6eeb692fa11b569af8b69b2bb11cc84f04926Jim Grosbach case FK_Data_1: 3446ec6eeb692fa11b569af8b69b2bb11cc84f04926Jim Grosbach case FK_Data_2: 3450c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim case FK_Data_4: 3462ccf148fbaaf9ea15233d7ef09e31ca0fa6ee3beJason W Kim return Value; 347dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines case FK_SecRel_2: 348dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return Value; 349dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines case FK_SecRel_4: 350dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return Value; 3510c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim case ARM::fixup_arm_movt_hi16: 35236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (!IsPCRel) 35336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Value >>= 16; 354f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng // Fallthrough 35536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case ARM::fixup_arm_movw_lo16: { 3562ccf148fbaaf9ea15233d7ef09e31ca0fa6ee3beJason W Kim unsigned Hi4 = (Value & 0xF000) >> 12; 3572ccf148fbaaf9ea15233d7ef09e31ca0fa6ee3beJason W Kim unsigned Lo12 = Value & 0x0FFF; 3582ccf148fbaaf9ea15233d7ef09e31ca0fa6ee3beJason W Kim // inst{19-16} = Hi4; 3592ccf148fbaaf9ea15233d7ef09e31ca0fa6ee3beJason W Kim // inst{11-0} = Lo12; 3602ccf148fbaaf9ea15233d7ef09e31ca0fa6ee3beJason W Kim Value = (Hi4 << 16) | (Lo12); 3610c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim return Value; 3622ccf148fbaaf9ea15233d7ef09e31ca0fa6ee3beJason W Kim } 363f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng case ARM::fixup_t2_movt_hi16: 36436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (!IsPCRel) 36536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Value >>= 16; 366f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng // Fallthrough 36736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case ARM::fixup_t2_movw_lo16: { 368f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng unsigned Hi4 = (Value & 0xF000) >> 12; 369f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng unsigned i = (Value & 0x800) >> 11; 370f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng unsigned Mid3 = (Value & 0x700) >> 8; 371f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng unsigned Lo8 = Value & 0x0FF; 372f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng // inst{19-16} = Hi4; 373f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng // inst{26} = i; 374f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng // inst{14-12} = Mid3; 375f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng // inst{7-0} = Lo8; 376f391e9f696183a8dfb6b0d1e791687a520552f85Jim Grosbach Value = (Hi4 << 16) | (i << 26) | (Mid3 << 12) | (Lo8); 377dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return swapHalfWords(Value, IsLittleEndian); 378f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng } 379d7b3f5870d9d04351d9cd363d9d6af01482a2eb8Owen Anderson case ARM::fixup_arm_ldst_pcrel_12: 3800c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim // ARM PC-relative values are offset by 8. 38105018c2f2872a05b1a2fff1a9934621ba1f38084Owen Anderson Value -= 4; 382fe7fac74b4edaf9cc04460fc21aa949e5533aea2Owen Anderson // FALLTHROUGH 383d7b3f5870d9d04351d9cd363d9d6af01482a2eb8Owen Anderson case ARM::fixup_t2_ldst_pcrel_12: { 384d7b3f5870d9d04351d9cd363d9d6af01482a2eb8Owen Anderson // Offset by 4, adjusted by two due to the half-word ordering of thumb. 38505018c2f2872a05b1a2fff1a9934621ba1f38084Owen Anderson Value -= 4; 386d7b3f5870d9d04351d9cd363d9d6af01482a2eb8Owen Anderson bool isAdd = true; 3870c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim if ((int64_t)Value < 0) { 3880c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim Value = -Value; 3890c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim isAdd = false; 3900c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim } 3917a3afa91ad8f68428373948fc16375e99bff3c6fJim Grosbach if (Ctx && Value >= 4096) 3927a3afa91ad8f68428373948fc16375e99bff3c6fJim Grosbach Ctx->FatalError(Fixup.getLoc(), "out of range pc-relative fixup value"); 3930c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim Value |= isAdd << 23; 3947e294cfcf97cd7b94bf5c4de0f214480ec13adadJim Grosbach 395d7b3f5870d9d04351d9cd363d9d6af01482a2eb8Owen Anderson // Same addressing mode as fixup_arm_pcrel_10, 396d7b3f5870d9d04351d9cd363d9d6af01482a2eb8Owen Anderson // but with 16-bit halfwords swapped. 397dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines if (Kind == ARM::fixup_t2_ldst_pcrel_12) 398dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return swapHalfWords(Value, IsLittleEndian); 3997e294cfcf97cd7b94bf5c4de0f214480ec13adadJim Grosbach 4000c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim return Value; 4010c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim } 402d40963c4065432ec7e47879d3ca665a54ee903b6Jim Grosbach case ARM::fixup_thumb_adr_pcrel_10: 403d40963c4065432ec7e47879d3ca665a54ee903b6Jim Grosbach return ((Value - 4) >> 2) & 0xff; 404dff84b03258514463ede477af38f1246b95b0cd0Jim Grosbach case ARM::fixup_arm_adr_pcrel_12: { 405dff84b03258514463ede477af38f1246b95b0cd0Jim Grosbach // ARM PC-relative values are offset by 8. 406dff84b03258514463ede477af38f1246b95b0cd0Jim Grosbach Value -= 8; 407dff84b03258514463ede477af38f1246b95b0cd0Jim Grosbach unsigned opc = 4; // bits {24-21}. Default to add: 0b0100 408dff84b03258514463ede477af38f1246b95b0cd0Jim Grosbach if ((int64_t)Value < 0) { 409dff84b03258514463ede477af38f1246b95b0cd0Jim Grosbach Value = -Value; 410dff84b03258514463ede477af38f1246b95b0cd0Jim Grosbach opc = 2; // 0b0010 411dff84b03258514463ede477af38f1246b95b0cd0Jim Grosbach } 4127a3afa91ad8f68428373948fc16375e99bff3c6fJim Grosbach if (Ctx && ARM_AM::getSOImmVal(Value) == -1) 4137a3afa91ad8f68428373948fc16375e99bff3c6fJim Grosbach Ctx->FatalError(Fixup.getLoc(), "out of range pc-relative fixup value"); 414dff84b03258514463ede477af38f1246b95b0cd0Jim Grosbach // Encode the immediate and shift the opcode into place. 415dff84b03258514463ede477af38f1246b95b0cd0Jim Grosbach return ARM_AM::getSOImmVal(Value) | (opc << 21); 416dff84b03258514463ede477af38f1246b95b0cd0Jim Grosbach } 417e8eb1ea6acd54538b42491b95d8fc6281d4b5710Jim Grosbach 418a838a25d59838adfa91463f6a918ae3adeb352c1Owen Anderson case ARM::fixup_t2_adr_pcrel_12: { 419a838a25d59838adfa91463f6a918ae3adeb352c1Owen Anderson Value -= 4; 420a838a25d59838adfa91463f6a918ae3adeb352c1Owen Anderson unsigned opc = 0; 421a838a25d59838adfa91463f6a918ae3adeb352c1Owen Anderson if ((int64_t)Value < 0) { 422a838a25d59838adfa91463f6a918ae3adeb352c1Owen Anderson Value = -Value; 423a838a25d59838adfa91463f6a918ae3adeb352c1Owen Anderson opc = 5; 424a838a25d59838adfa91463f6a918ae3adeb352c1Owen Anderson } 425a838a25d59838adfa91463f6a918ae3adeb352c1Owen Anderson 426a838a25d59838adfa91463f6a918ae3adeb352c1Owen Anderson uint32_t out = (opc << 21); 427741ad15e26d1717433f326743800f30c63c6a9c1Owen Anderson out |= (Value & 0x800) << 15; 428a838a25d59838adfa91463f6a918ae3adeb352c1Owen Anderson out |= (Value & 0x700) << 4; 429a838a25d59838adfa91463f6a918ae3adeb352c1Owen Anderson out |= (Value & 0x0FF); 430e8eb1ea6acd54538b42491b95d8fc6281d4b5710Jim Grosbach 431dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return swapHalfWords(out, IsLittleEndian); 432a838a25d59838adfa91463f6a918ae3adeb352c1Owen Anderson } 433e8eb1ea6acd54538b42491b95d8fc6281d4b5710Jim Grosbach 434685c350ae76b588e1f00c01a511fe8bd57f18394Jason W Kim case ARM::fixup_arm_condbranch: 435685c350ae76b588e1f00c01a511fe8bd57f18394Jason W Kim case ARM::fixup_arm_uncondbranch: 436cb0809b82b126e79b99755ae4fc3d9733faea038James Molloy case ARM::fixup_arm_uncondbl: 437cb0809b82b126e79b99755ae4fc3d9733faea038James Molloy case ARM::fixup_arm_condbl: 4387b25ecf6adbf3c4709c48033acfeb6ebbb4452abJim Grosbach case ARM::fixup_arm_blx: 4390c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim // These values don't encode the low two bits since they're always zero. 4400c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim // Offset by 8 just as above. 44136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (const MCSymbolRefExpr *SRE = dyn_cast<MCSymbolRefExpr>(Fixup.getValue())) 44236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (SRE->getKind() == MCSymbolRefExpr::VK_ARM_TLSCALL) 44336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return 0; 444662a816e89a9d77bf75e1328b09cf9235b4682aaJim Grosbach return 0xffffff & ((Value - 8) >> 2); 445c266600bec4b5ba0ee93ffdfeaafcab8f1295145Owen Anderson case ARM::fixup_t2_uncondbranch: { 44663ee22065dc4e8af7f4bf99c25b82da132700267Owen Anderson Value = Value - 4; 447fb20d890756b75d6ccfa7ab17f170a877d425dc6Owen Anderson Value >>= 1; // Low bit is not encoded. 4487e294cfcf97cd7b94bf5c4de0f214480ec13adadJim Grosbach 44956a2535474dd4482c432b3c75c3dab4b2f3dd1e2Jim Grosbach uint32_t out = 0; 450c266600bec4b5ba0ee93ffdfeaafcab8f1295145Owen Anderson bool I = Value & 0x800000; 451c266600bec4b5ba0ee93ffdfeaafcab8f1295145Owen Anderson bool J1 = Value & 0x400000; 452c266600bec4b5ba0ee93ffdfeaafcab8f1295145Owen Anderson bool J2 = Value & 0x200000; 453c266600bec4b5ba0ee93ffdfeaafcab8f1295145Owen Anderson J1 ^= I; 454c266600bec4b5ba0ee93ffdfeaafcab8f1295145Owen Anderson J2 ^= I; 455e8eb1ea6acd54538b42491b95d8fc6281d4b5710Jim Grosbach 456c266600bec4b5ba0ee93ffdfeaafcab8f1295145Owen Anderson out |= I << 26; // S bit 457c266600bec4b5ba0ee93ffdfeaafcab8f1295145Owen Anderson out |= !J1 << 13; // J1 bit 458c266600bec4b5ba0ee93ffdfeaafcab8f1295145Owen Anderson out |= !J2 << 11; // J2 bit 459c266600bec4b5ba0ee93ffdfeaafcab8f1295145Owen Anderson out |= (Value & 0x1FF800) << 5; // imm6 field 460c266600bec4b5ba0ee93ffdfeaafcab8f1295145Owen Anderson out |= (Value & 0x0007FF); // imm11 field 461e8eb1ea6acd54538b42491b95d8fc6281d4b5710Jim Grosbach 462dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return swapHalfWords(out, IsLittleEndian); 463c266600bec4b5ba0ee93ffdfeaafcab8f1295145Owen Anderson } 464c266600bec4b5ba0ee93ffdfeaafcab8f1295145Owen Anderson case ARM::fixup_t2_condbranch: { 465c266600bec4b5ba0ee93ffdfeaafcab8f1295145Owen Anderson Value = Value - 4; 466c266600bec4b5ba0ee93ffdfeaafcab8f1295145Owen Anderson Value >>= 1; // Low bit is not encoded. 467e8eb1ea6acd54538b42491b95d8fc6281d4b5710Jim Grosbach 468c266600bec4b5ba0ee93ffdfeaafcab8f1295145Owen Anderson uint64_t out = 0; 4698f0794331765661f92cf074f638acb1ea927bb5dOwen Anderson out |= (Value & 0x80000) << 7; // S bit 4708f0794331765661f92cf074f638acb1ea927bb5dOwen Anderson out |= (Value & 0x40000) >> 7; // J2 bit 4718f0794331765661f92cf074f638acb1ea927bb5dOwen Anderson out |= (Value & 0x20000) >> 4; // J1 bit 4728f0794331765661f92cf074f638acb1ea927bb5dOwen Anderson out |= (Value & 0x1F800) << 5; // imm6 field 4738f0794331765661f92cf074f638acb1ea927bb5dOwen Anderson out |= (Value & 0x007FF); // imm11 field 4747e294cfcf97cd7b94bf5c4de0f214480ec13adadJim Grosbach 475dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return swapHalfWords(out, IsLittleEndian); 476fb20d890756b75d6ccfa7ab17f170a877d425dc6Owen Anderson } 477662a816e89a9d77bf75e1328b09cf9235b4682aaJim Grosbach case ARM::fixup_arm_thumb_bl: { 47836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // The value doesn't encode the low bit (always zero) and is offset by 47936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // four. The 32-bit immediate value is encoded as 48036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // imm32 = SignExtend(S:I1:I2:imm10:imm11:0) 48136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // where I1 = NOT(J1 ^ S) and I2 = NOT(J2 ^ S). 48236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // The value is encoded into disjoint bit positions in the destination 48336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // opcode. x = unchanged, I = immediate value bit, S = sign extension bit, 48436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // J = either J1 or J2 bit 48536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // 48636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // BL: xxxxxSIIIIIIIIII xxJxJIIIIIIIIIII 48736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // 48836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // Note that the halfwords are stored high first, low second; so we need 48936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // to transpose the fixup value here to map properly. 49036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint32_t offset = (Value - 4) >> 1; 49136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint32_t signBit = (offset & 0x800000) >> 23; 49236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint32_t I1Bit = (offset & 0x400000) >> 22; 49336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint32_t J1Bit = (I1Bit ^ 0x1) ^ signBit; 49436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint32_t I2Bit = (offset & 0x200000) >> 21; 49536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint32_t J2Bit = (I2Bit ^ 0x1) ^ signBit; 49636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint32_t imm10Bits = (offset & 0x1FF800) >> 11; 49736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint32_t imm11Bits = (offset & 0x000007FF); 49836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 499dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines uint32_t FirstHalf = (((uint16_t)signBit << 10) | (uint16_t)imm10Bits); 500dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines uint32_t SecondHalf = (((uint16_t)J1Bit << 13) | ((uint16_t)J2Bit << 11) | 50136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines (uint16_t)imm11Bits); 502dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return joinHalfWords(FirstHalf, SecondHalf, IsLittleEndian); 50309aa3f0ef35d9241c92439d74b8d5e9a81d814c2Bill Wendling } 50409aa3f0ef35d9241c92439d74b8d5e9a81d814c2Bill Wendling case ARM::fixup_arm_thumb_blx: { 50536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // The value doesn't encode the low two bits (always zero) and is offset by 50636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // four (see fixup_arm_thumb_cp). The 32-bit immediate value is encoded as 50736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // imm32 = SignExtend(S:I1:I2:imm10H:imm10L:00) 50836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // where I1 = NOT(J1 ^ S) and I2 = NOT(J2 ^ S). 50936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // The value is encoded into disjoint bit positions in the destination 51036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // opcode. x = unchanged, I = immediate value bit, S = sign extension bit, 51136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // J = either J1 or J2 bit, 0 = zero. 51236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // 51336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // BLX: xxxxxSIIIIIIIIII xxJxJIIIIIIIIII0 51436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // 51536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // Note that the halfwords are stored high first, low second; so we need 51636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // to transpose the fixup value here to map properly. 51736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint32_t offset = (Value - 2) >> 2; 51836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (const MCSymbolRefExpr *SRE = dyn_cast<MCSymbolRefExpr>(Fixup.getValue())) 51936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (SRE->getKind() == MCSymbolRefExpr::VK_ARM_TLSCALL) 52036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines offset = 0; 52136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint32_t signBit = (offset & 0x400000) >> 22; 52236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint32_t I1Bit = (offset & 0x200000) >> 21; 52336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint32_t J1Bit = (I1Bit ^ 0x1) ^ signBit; 52436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint32_t I2Bit = (offset & 0x100000) >> 20; 52536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint32_t J2Bit = (I2Bit ^ 0x1) ^ signBit; 52636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint32_t imm10HBits = (offset & 0xFFC00) >> 10; 52736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint32_t imm10LBits = (offset & 0x3FF); 52836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 529dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines uint32_t FirstHalf = (((uint16_t)signBit << 10) | (uint16_t)imm10HBits); 530dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines uint32_t SecondHalf = (((uint16_t)J1Bit << 13) | ((uint16_t)J2Bit << 11) | 53136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ((uint16_t)imm10LBits) << 1); 532dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return joinHalfWords(FirstHalf, SecondHalf, IsLittleEndian); 533662a816e89a9d77bf75e1328b09cf9235b4682aaJim Grosbach } 534b8958b031ec5163261f490f131780c5dc3d823d6Bill Wendling case ARM::fixup_arm_thumb_cp: 5350c2c217244573cdfb4be8b7fa62670412b4c1e71Jim Grosbach // Offset by 4, and don't encode the low two bits. Two bytes of that 5360c2c217244573cdfb4be8b7fa62670412b4c1e71Jim Grosbach // 'off by 4' is implicitly handled by the half-word ordering of the 5370c2c217244573cdfb4be8b7fa62670412b4c1e71Jim Grosbach // Thumb encoding, so we only need to adjust by 2 here. 5380c2c217244573cdfb4be8b7fa62670412b4c1e71Jim Grosbach return ((Value - 2) >> 2) & 0xff; 539b492a7c2134d3886f545f1b5ea55115d71529a10Jim Grosbach case ARM::fixup_arm_thumb_cb: { 540dff2f7151f695b86db8c4b0c6604463bdb8a63eaBill Wendling // Offset by 4 and don't encode the lower bit, which is always 0. 541dff2f7151f695b86db8c4b0c6604463bdb8a63eaBill Wendling uint32_t Binary = (Value - 4) >> 1; 54286abd48fd01080f08eec1b46f92c90308b03bfd4Owen Anderson return ((Binary & 0x20) << 4) | ((Binary & 0x1f) << 3); 543dff2f7151f695b86db8c4b0c6604463bdb8a63eaBill Wendling } 544e246717c3a36a913fd4200776ed621649bb2b624Jim Grosbach case ARM::fixup_arm_thumb_br: 545e246717c3a36a913fd4200776ed621649bb2b624Jim Grosbach // Offset by 4 and don't encode the lower bit, which is always 0. 546e246717c3a36a913fd4200776ed621649bb2b624Jim Grosbach return ((Value - 4) >> 1) & 0x7ff; 54701086451393ef33e82b6fad623989dd97dd70edfJim Grosbach case ARM::fixup_arm_thumb_bcc: 54801086451393ef33e82b6fad623989dd97dd70edfJim Grosbach // Offset by 4 and don't encode the lower bit, which is always 0. 54901086451393ef33e82b6fad623989dd97dd70edfJim Grosbach return ((Value - 4) >> 1) & 0xff; 5502f196747f15240691bd4e622f7995edfedf90f61Jim Grosbach case ARM::fixup_arm_pcrel_10_unscaled: { 5512f196747f15240691bd4e622f7995edfedf90f61Jim Grosbach Value = Value - 8; // ARM fixups offset by an additional word and don't 5522f196747f15240691bd4e622f7995edfedf90f61Jim Grosbach // need to adjust for the half-word ordering. 5532f196747f15240691bd4e622f7995edfedf90f61Jim Grosbach bool isAdd = true; 5542f196747f15240691bd4e622f7995edfedf90f61Jim Grosbach if ((int64_t)Value < 0) { 5552f196747f15240691bd4e622f7995edfedf90f61Jim Grosbach Value = -Value; 5562f196747f15240691bd4e622f7995edfedf90f61Jim Grosbach isAdd = false; 5572f196747f15240691bd4e622f7995edfedf90f61Jim Grosbach } 558bf3c322640fdaf6e4a60a59ed8cb108a7f6685adJim Grosbach // The value has the low 4 bits encoded in [3:0] and the high 4 in [11:8]. 5597a3afa91ad8f68428373948fc16375e99bff3c6fJim Grosbach if (Ctx && Value >= 256) 5607a3afa91ad8f68428373948fc16375e99bff3c6fJim Grosbach Ctx->FatalError(Fixup.getLoc(), "out of range pc-relative fixup value"); 561bf3c322640fdaf6e4a60a59ed8cb108a7f6685adJim Grosbach Value = (Value & 0xf) | ((Value & 0xf0) << 4); 5622f196747f15240691bd4e622f7995edfedf90f61Jim Grosbach return Value | (isAdd << 23); 5632f196747f15240691bd4e622f7995edfedf90f61Jim Grosbach } 5640c2c217244573cdfb4be8b7fa62670412b4c1e71Jim Grosbach case ARM::fixup_arm_pcrel_10: 565e2e0f58809374265bd75edeefae8817e7ade62b4Owen Anderson Value = Value - 4; // ARM fixups offset by an additional word and don't 5660c2c217244573cdfb4be8b7fa62670412b4c1e71Jim Grosbach // need to adjust for the half-word ordering. 5670c2c217244573cdfb4be8b7fa62670412b4c1e71Jim Grosbach // Fall through. 5680c2c217244573cdfb4be8b7fa62670412b4c1e71Jim Grosbach case ARM::fixup_t2_pcrel_10: { 5690c2c217244573cdfb4be8b7fa62670412b4c1e71Jim Grosbach // Offset by 4, adjusted by two due to the half-word ordering of thumb. 570e2e0f58809374265bd75edeefae8817e7ade62b4Owen Anderson Value = Value - 4; 5710c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim bool isAdd = true; 5720c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim if ((int64_t)Value < 0) { 5730c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim Value = -Value; 5740c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim isAdd = false; 5750c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim } 5760c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim // These values don't encode the low two bits since they're always zero. 5770c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim Value >>= 2; 5787a3afa91ad8f68428373948fc16375e99bff3c6fJim Grosbach if (Ctx && Value >= 256) 5797a3afa91ad8f68428373948fc16375e99bff3c6fJim Grosbach Ctx->FatalError(Fixup.getLoc(), "out of range pc-relative fixup value"); 5800c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim Value |= isAdd << 23; 5810c2c217244573cdfb4be8b7fa62670412b4c1e71Jim Grosbach 5822f196747f15240691bd4e622f7995edfedf90f61Jim Grosbach // Same addressing mode as fixup_arm_pcrel_10, but with 16-bit halfwords 5832f196747f15240691bd4e622f7995edfedf90f61Jim Grosbach // swapped. 584dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines if (Kind == ARM::fixup_t2_pcrel_10) 585dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return swapHalfWords(Value, IsLittleEndian); 5860c2c217244573cdfb4be8b7fa62670412b4c1e71Jim Grosbach 5870c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim return Value; 5880c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim } 5890c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim } 5900c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim} 5910c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim 5927a3afa91ad8f68428373948fc16375e99bff3c6fJim Grosbachvoid ARMAsmBackend::processFixupValue(const MCAssembler &Asm, 5937a3afa91ad8f68428373948fc16375e99bff3c6fJim Grosbach const MCAsmLayout &Layout, 5947a3afa91ad8f68428373948fc16375e99bff3c6fJim Grosbach const MCFixup &Fixup, 5957a3afa91ad8f68428373948fc16375e99bff3c6fJim Grosbach const MCFragment *DF, 59636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const MCValue &Target, uint64_t &Value, 5977a3afa91ad8f68428373948fc16375e99bff3c6fJim Grosbach bool &IsResolved) { 5987a3afa91ad8f68428373948fc16375e99bff3c6fJim Grosbach const MCSymbolRefExpr *A = Target.getSymA(); 5997a3afa91ad8f68428373948fc16375e99bff3c6fJim Grosbach // Some fixups to thumb function symbols need the low bit (thumb bit) 6007a3afa91ad8f68428373948fc16375e99bff3c6fJim Grosbach // twiddled. 6017a3afa91ad8f68428373948fc16375e99bff3c6fJim Grosbach if ((unsigned)Fixup.getKind() != ARM::fixup_arm_ldst_pcrel_12 && 6027a3afa91ad8f68428373948fc16375e99bff3c6fJim Grosbach (unsigned)Fixup.getKind() != ARM::fixup_t2_ldst_pcrel_12 && 6037a3afa91ad8f68428373948fc16375e99bff3c6fJim Grosbach (unsigned)Fixup.getKind() != ARM::fixup_arm_adr_pcrel_12 && 6047a3afa91ad8f68428373948fc16375e99bff3c6fJim Grosbach (unsigned)Fixup.getKind() != ARM::fixup_thumb_adr_pcrel_10 && 6057a3afa91ad8f68428373948fc16375e99bff3c6fJim Grosbach (unsigned)Fixup.getKind() != ARM::fixup_t2_adr_pcrel_12 && 6067a3afa91ad8f68428373948fc16375e99bff3c6fJim Grosbach (unsigned)Fixup.getKind() != ARM::fixup_arm_thumb_cp) { 6077a3afa91ad8f68428373948fc16375e99bff3c6fJim Grosbach if (A) { 6087a3afa91ad8f68428373948fc16375e99bff3c6fJim Grosbach const MCSymbol &Sym = A->getSymbol().AliasedSymbol(); 6097a3afa91ad8f68428373948fc16375e99bff3c6fJim Grosbach if (Asm.isThumbFunc(&Sym)) 6107a3afa91ad8f68428373948fc16375e99bff3c6fJim Grosbach Value |= 1; 6117a3afa91ad8f68428373948fc16375e99bff3c6fJim Grosbach } 6127a3afa91ad8f68428373948fc16375e99bff3c6fJim Grosbach } 61336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // For Thumb1 BL instruction, it is possible to be a long jump between 61436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // the basic blocks of the same function. Thus, we would like to resolve 61536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // the offset when the destination has the same MCFragment. 61636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (A && (unsigned)Fixup.getKind() == ARM::fixup_arm_thumb_bl) { 61736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const MCSymbol &Sym = A->getSymbol().AliasedSymbol(); 618dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines const MCSymbolData &SymData = Asm.getSymbolData(Sym); 61936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines IsResolved = (SymData.getFragment() == DF); 62036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 6217a3afa91ad8f68428373948fc16375e99bff3c6fJim Grosbach // We must always generate a relocation for BL/BLX instructions if we have 6227a3afa91ad8f68428373948fc16375e99bff3c6fJim Grosbach // a symbol to reference, as the linker relies on knowing the destination 6237a3afa91ad8f68428373948fc16375e99bff3c6fJim Grosbach // symbol's thumb-ness to get interworking right. 6247a3afa91ad8f68428373948fc16375e99bff3c6fJim Grosbach if (A && ((unsigned)Fixup.getKind() == ARM::fixup_arm_thumb_blx || 6257a3afa91ad8f68428373948fc16375e99bff3c6fJim Grosbach (unsigned)Fixup.getKind() == ARM::fixup_arm_blx || 6267a3afa91ad8f68428373948fc16375e99bff3c6fJim Grosbach (unsigned)Fixup.getKind() == ARM::fixup_arm_uncondbl || 6277a3afa91ad8f68428373948fc16375e99bff3c6fJim Grosbach (unsigned)Fixup.getKind() == ARM::fixup_arm_condbl)) 6287a3afa91ad8f68428373948fc16375e99bff3c6fJim Grosbach IsResolved = false; 6297a3afa91ad8f68428373948fc16375e99bff3c6fJim Grosbach 6307a3afa91ad8f68428373948fc16375e99bff3c6fJim Grosbach // Try to get the encoded value for the fixup as-if we're mapping it into 6317a3afa91ad8f68428373948fc16375e99bff3c6fJim Grosbach // the instruction. This allows adjustFixupValue() to issue a diagnostic 6327a3afa91ad8f68428373948fc16375e99bff3c6fJim Grosbach // if the value aren't invalid. 633dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines (void)adjustFixupValue(Fixup, Value, false, &Asm.getContext(), 634dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines IsLittleEndian); 6357a3afa91ad8f68428373948fc16375e99bff3c6fJim Grosbach} 6367a3afa91ad8f68428373948fc16375e99bff3c6fJim Grosbach 637d832fa053b86f42a5bc1e55e979b61c1115a8053Bill Wendling/// getFixupKindNumBytes - The number of bytes the fixup may change. 638c466b937dbdbaabeef0097fe340de1b8f49a3508Jim Grosbachstatic unsigned getFixupKindNumBytes(unsigned Kind) { 639679cbd3b215b1769a6035e334f9009aeeb940dddJim Grosbach switch (Kind) { 640662a816e89a9d77bf75e1328b09cf9235b4682aaJim Grosbach default: 641662a816e89a9d77bf75e1328b09cf9235b4682aaJim Grosbach llvm_unreachable("Unknown fixup kind!"); 642b8958b031ec5163261f490f131780c5dc3d823d6Bill Wendling 6436ec6eeb692fa11b569af8b69b2bb11cc84f04926Jim Grosbach case FK_Data_1: 64401086451393ef33e82b6fad623989dd97dd70edfJim Grosbach case ARM::fixup_arm_thumb_bcc: 645b8958b031ec5163261f490f131780c5dc3d823d6Bill Wendling case ARM::fixup_arm_thumb_cp: 646d40963c4065432ec7e47879d3ca665a54ee903b6Jim Grosbach case ARM::fixup_thumb_adr_pcrel_10: 647b8958b031ec5163261f490f131780c5dc3d823d6Bill Wendling return 1; 648b8958b031ec5163261f490f131780c5dc3d823d6Bill Wendling 6496ec6eeb692fa11b569af8b69b2bb11cc84f04926Jim Grosbach case FK_Data_2: 650e246717c3a36a913fd4200776ed621649bb2b624Jim Grosbach case ARM::fixup_arm_thumb_br: 651b492a7c2134d3886f545f1b5ea55115d71529a10Jim Grosbach case ARM::fixup_arm_thumb_cb: 652dff2f7151f695b86db8c4b0c6604463bdb8a63eaBill Wendling return 2; 653dff2f7151f695b86db8c4b0c6604463bdb8a63eaBill Wendling 6542f196747f15240691bd4e622f7995edfedf90f61Jim Grosbach case ARM::fixup_arm_pcrel_10_unscaled: 655662a816e89a9d77bf75e1328b09cf9235b4682aaJim Grosbach case ARM::fixup_arm_ldst_pcrel_12: 656662a816e89a9d77bf75e1328b09cf9235b4682aaJim Grosbach case ARM::fixup_arm_pcrel_10: 657662a816e89a9d77bf75e1328b09cf9235b4682aaJim Grosbach case ARM::fixup_arm_adr_pcrel_12: 658cb0809b82b126e79b99755ae4fc3d9733faea038James Molloy case ARM::fixup_arm_uncondbl: 659cb0809b82b126e79b99755ae4fc3d9733faea038James Molloy case ARM::fixup_arm_condbl: 6607b25ecf6adbf3c4709c48033acfeb6ebbb4452abJim Grosbach case ARM::fixup_arm_blx: 661685c350ae76b588e1f00c01a511fe8bd57f18394Jason W Kim case ARM::fixup_arm_condbranch: 662685c350ae76b588e1f00c01a511fe8bd57f18394Jason W Kim case ARM::fixup_arm_uncondbranch: 663662a816e89a9d77bf75e1328b09cf9235b4682aaJim Grosbach return 3; 664b8958b031ec5163261f490f131780c5dc3d823d6Bill Wendling 665b8958b031ec5163261f490f131780c5dc3d823d6Bill Wendling case FK_Data_4: 666d7b3f5870d9d04351d9cd363d9d6af01482a2eb8Owen Anderson case ARM::fixup_t2_ldst_pcrel_12: 667c266600bec4b5ba0ee93ffdfeaafcab8f1295145Owen Anderson case ARM::fixup_t2_condbranch: 668c266600bec4b5ba0ee93ffdfeaafcab8f1295145Owen Anderson case ARM::fixup_t2_uncondbranch: 669d8e351b96f5fd7007fbdd636acaa1fc9f6e18f3cOwen Anderson case ARM::fixup_t2_pcrel_10: 670a838a25d59838adfa91463f6a918ae3adeb352c1Owen Anderson case ARM::fixup_t2_adr_pcrel_12: 671662a816e89a9d77bf75e1328b09cf9235b4682aaJim Grosbach case ARM::fixup_arm_thumb_bl: 67209aa3f0ef35d9241c92439d74b8d5e9a81d814c2Bill Wendling case ARM::fixup_arm_thumb_blx: 673f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng case ARM::fixup_arm_movt_hi16: 674f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng case ARM::fixup_arm_movw_lo16: 675f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng case ARM::fixup_t2_movt_hi16: 676f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng case ARM::fixup_t2_movw_lo16: 67736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return 4; 678dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 679dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines case FK_SecRel_2: 680dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return 2; 681dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines case FK_SecRel_4: 682dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return 4; 68336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 68436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 68536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 68636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// getFixupKindContainerSizeBytes - The number of bytes of the 68736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// container involved in big endian. 68836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesstatic unsigned getFixupKindContainerSizeBytes(unsigned Kind) { 68936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines switch (Kind) { 69036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines default: 69136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines llvm_unreachable("Unknown fixup kind!"); 69236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 69336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case FK_Data_1: 69436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return 1; 69536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case FK_Data_2: 69636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return 2; 69736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case FK_Data_4: 69836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return 4; 69936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 70036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case ARM::fixup_arm_thumb_bcc: 70136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case ARM::fixup_arm_thumb_cp: 70236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case ARM::fixup_thumb_adr_pcrel_10: 70336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case ARM::fixup_arm_thumb_br: 70436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case ARM::fixup_arm_thumb_cb: 70536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // Instruction size is 2 bytes. 70636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return 2; 70736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 70836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case ARM::fixup_arm_pcrel_10_unscaled: 70936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case ARM::fixup_arm_ldst_pcrel_12: 71036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case ARM::fixup_arm_pcrel_10: 71136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case ARM::fixup_arm_adr_pcrel_12: 71236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case ARM::fixup_arm_uncondbl: 71336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case ARM::fixup_arm_condbl: 71436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case ARM::fixup_arm_blx: 71536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case ARM::fixup_arm_condbranch: 71636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case ARM::fixup_arm_uncondbranch: 71736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case ARM::fixup_t2_ldst_pcrel_12: 71836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case ARM::fixup_t2_condbranch: 71936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case ARM::fixup_t2_uncondbranch: 72036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case ARM::fixup_t2_pcrel_10: 72136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case ARM::fixup_t2_adr_pcrel_12: 72236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case ARM::fixup_arm_thumb_bl: 72336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case ARM::fixup_arm_thumb_blx: 72436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case ARM::fixup_arm_movt_hi16: 72536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case ARM::fixup_arm_movw_lo16: 72636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case ARM::fixup_t2_movt_hi16: 72736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case ARM::fixup_t2_movw_lo16: 72836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // Instruction size is 4 bytes. 729662a816e89a9d77bf75e1328b09cf9235b4682aaJim Grosbach return 4; 730679cbd3b215b1769a6035e334f9009aeeb940dddJim Grosbach } 731679cbd3b215b1769a6035e334f9009aeeb940dddJim Grosbach} 732679cbd3b215b1769a6035e334f9009aeeb940dddJim Grosbach 733cb4028b91d7c1b0163d1b6c85911668d3d19c75aBenjamin Kramervoid ARMAsmBackend::applyFixup(const MCFixup &Fixup, char *Data, 73436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines unsigned DataSize, uint64_t Value, 73536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines bool IsPCRel) const { 736c466b937dbdbaabeef0097fe340de1b8f49a3508Jim Grosbach unsigned NumBytes = getFixupKindNumBytes(Fixup.getKind()); 737dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Value = adjustFixupValue(Fixup, Value, IsPCRel, nullptr, IsLittleEndian); 738d832fa053b86f42a5bc1e55e979b61c1115a8053Bill Wendling if (!Value) return; // Doesn't change encoding. 739d832fa053b86f42a5bc1e55e979b61c1115a8053Bill Wendling 740d832fa053b86f42a5bc1e55e979b61c1115a8053Bill Wendling unsigned Offset = Fixup.getOffset(); 741d832fa053b86f42a5bc1e55e979b61c1115a8053Bill Wendling assert(Offset + NumBytes <= DataSize && "Invalid fixup offset!"); 742679cbd3b215b1769a6035e334f9009aeeb940dddJim Grosbach 74336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // Used to point to big endian bytes. 74436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines unsigned FullSizeBytes; 745dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines if (!IsLittleEndian) { 74636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines FullSizeBytes = getFixupKindContainerSizeBytes(Fixup.getKind()); 747dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines assert((Offset + FullSizeBytes) <= DataSize && "Invalid fixup size!"); 748dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines assert(NumBytes <= FullSizeBytes && "Invalid fixup size!"); 749dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } 75036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 751cb4028b91d7c1b0163d1b6c85911668d3d19c75aBenjamin Kramer // For each byte of the fragment that the fixup touches, mask in the bits from 752cb4028b91d7c1b0163d1b6c85911668d3d19c75aBenjamin Kramer // the fixup value. The Value has been "split up" into the appropriate 753cb4028b91d7c1b0163d1b6c85911668d3d19c75aBenjamin Kramer // bitfields above. 75436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines for (unsigned i = 0; i != NumBytes; ++i) { 75536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines unsigned Idx = IsLittleEndian ? i : (FullSizeBytes - 1 - i); 75636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Data[Offset + Idx] |= uint8_t((Value >> (i * 8)) & 0xff); 75736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 758d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim} 75952e635ea3512cfcd03587201b20100074e5b6ac9Bill Wendling 760cb4028b91d7c1b0163d1b6c85911668d3d19c75aBenjamin Kramernamespace { 761dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines// FIXME: This should be in a separate file. 762dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesclass ARMWinCOFFAsmBackend : public ARMAsmBackend { 763dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinespublic: 764dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines ARMWinCOFFAsmBackend(const Target &T, const StringRef &Triple) 765dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines : ARMAsmBackend(T, Triple, true) { } 766dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines MCObjectWriter *createObjectWriter(raw_ostream &OS) const override { 767dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return createARMWinCOFFObjectWriter(OS, /*Is64Bit=*/false); 768dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } 769dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines}; 770cb4028b91d7c1b0163d1b6c85911668d3d19c75aBenjamin Kramer 771cb4028b91d7c1b0163d1b6c85911668d3d19c75aBenjamin Kramer// FIXME: This should be in a separate file. 772cb4028b91d7c1b0163d1b6c85911668d3d19c75aBenjamin Kramer// ELF is an ELF of course... 773cb4028b91d7c1b0163d1b6c85911668d3d19c75aBenjamin Kramerclass ELFARMAsmBackend : public ARMAsmBackend { 774cb4028b91d7c1b0163d1b6c85911668d3d19c75aBenjamin Kramerpublic: 775cb4028b91d7c1b0163d1b6c85911668d3d19c75aBenjamin Kramer uint8_t OSABI; 776cb4028b91d7c1b0163d1b6c85911668d3d19c75aBenjamin Kramer ELFARMAsmBackend(const Target &T, const StringRef TT, 77736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint8_t OSABI, bool IsLittle) 77836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines : ARMAsmBackend(T, TT, IsLittle), OSABI(OSABI) { } 779cb4028b91d7c1b0163d1b6c85911668d3d19c75aBenjamin Kramer 78036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines MCObjectWriter *createObjectWriter(raw_ostream &OS) const override { 78136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return createARMELFObjectWriter(OS, OSABI, isLittle()); 782cb4028b91d7c1b0163d1b6c85911668d3d19c75aBenjamin Kramer } 783cb4028b91d7c1b0163d1b6c85911668d3d19c75aBenjamin Kramer}; 784cb4028b91d7c1b0163d1b6c85911668d3d19c75aBenjamin Kramer 785cb4028b91d7c1b0163d1b6c85911668d3d19c75aBenjamin Kramer// FIXME: This should be in a separate file. 786cb4028b91d7c1b0163d1b6c85911668d3d19c75aBenjamin Kramerclass DarwinARMAsmBackend : public ARMAsmBackend { 787cb4028b91d7c1b0163d1b6c85911668d3d19c75aBenjamin Kramerpublic: 7885510728d28bb1ee04abc32da3d21b7df12948053Charles Davis const MachO::CPUSubTypeARM Subtype; 789cb4028b91d7c1b0163d1b6c85911668d3d19c75aBenjamin Kramer DarwinARMAsmBackend(const Target &T, const StringRef TT, 7905510728d28bb1ee04abc32da3d21b7df12948053Charles Davis MachO::CPUSubTypeARM st) 79136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines : ARMAsmBackend(T, TT, /* IsLittleEndian */ true), Subtype(st) { 792cb4028b91d7c1b0163d1b6c85911668d3d19c75aBenjamin Kramer HasDataInCodeSupport = true; 793cb4028b91d7c1b0163d1b6c85911668d3d19c75aBenjamin Kramer } 794cb4028b91d7c1b0163d1b6c85911668d3d19c75aBenjamin Kramer 79536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines MCObjectWriter *createObjectWriter(raw_ostream &OS) const override { 796cb4028b91d7c1b0163d1b6c85911668d3d19c75aBenjamin Kramer return createARMMachObjectWriter(OS, /*Is64Bit=*/false, 7975510728d28bb1ee04abc32da3d21b7df12948053Charles Davis MachO::CPU_TYPE_ARM, 798cb4028b91d7c1b0163d1b6c85911668d3d19c75aBenjamin Kramer Subtype); 799cb4028b91d7c1b0163d1b6c85911668d3d19c75aBenjamin Kramer } 800cb4028b91d7c1b0163d1b6c85911668d3d19c75aBenjamin Kramer}; 801cb4028b91d7c1b0163d1b6c85911668d3d19c75aBenjamin Kramer 802f73fd7278f2bebd435c84c55a79db8ccb07d3534Jim Grosbach} // end anonymous namespace 803d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim 804c3cee57f7d20f69a84fd88464ed8cf050e63c7adBill WendlingMCAsmBackend *llvm::createARMAsmBackend(const Target &T, 805c3cee57f7d20f69a84fd88464ed8cf050e63c7adBill Wendling const MCRegisterInfo &MRI, 80636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines StringRef TT, StringRef CPU, 80736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines bool isLittle) { 8081721324d97e2b05c9276ffe116dfb6c808521c2bOwen Anderson Triple TheTriple(TT); 809912225e18559a73228099330a4c253fdccf9fa3dDaniel Dunbar 810dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines switch (TheTriple.getObjectFormat()) { 811dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines default: llvm_unreachable("unsupported object format"); 812dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines case Triple::MachO: { 8135510728d28bb1ee04abc32da3d21b7df12948053Charles Davis MachO::CPUSubTypeARM CS = 8145510728d28bb1ee04abc32da3d21b7df12948053Charles Davis StringSwitch<MachO::CPUSubTypeARM>(TheTriple.getArchName()) 8155510728d28bb1ee04abc32da3d21b7df12948053Charles Davis .Cases("armv4t", "thumbv4t", MachO::CPU_SUBTYPE_ARM_V4T) 8165510728d28bb1ee04abc32da3d21b7df12948053Charles Davis .Cases("armv5e", "thumbv5e", MachO::CPU_SUBTYPE_ARM_V5TEJ) 8175510728d28bb1ee04abc32da3d21b7df12948053Charles Davis .Cases("armv6", "thumbv6", MachO::CPU_SUBTYPE_ARM_V6) 8185510728d28bb1ee04abc32da3d21b7df12948053Charles Davis .Cases("armv6m", "thumbv6m", MachO::CPU_SUBTYPE_ARM_V6M) 8195510728d28bb1ee04abc32da3d21b7df12948053Charles Davis .Cases("armv7em", "thumbv7em", MachO::CPU_SUBTYPE_ARM_V7EM) 8205510728d28bb1ee04abc32da3d21b7df12948053Charles Davis .Cases("armv7k", "thumbv7k", MachO::CPU_SUBTYPE_ARM_V7K) 8215510728d28bb1ee04abc32da3d21b7df12948053Charles Davis .Cases("armv7m", "thumbv7m", MachO::CPU_SUBTYPE_ARM_V7M) 8225510728d28bb1ee04abc32da3d21b7df12948053Charles Davis .Cases("armv7s", "thumbv7s", MachO::CPU_SUBTYPE_ARM_V7S) 8235510728d28bb1ee04abc32da3d21b7df12948053Charles Davis .Default(MachO::CPU_SUBTYPE_ARM_V7); 82419d54337169ae4af2d44ae39664d0bac1ae0309cQuentin Colombet 82519d54337169ae4af2d44ae39664d0bac1ae0309cQuentin Colombet return new DarwinARMAsmBackend(T, TT, CS); 8261721324d97e2b05c9276ffe116dfb6c808521c2bOwen Anderson } 827dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines case Triple::COFF: 828dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines assert(TheTriple.isOSWindows() && "non-Windows ARM COFF is not supported"); 829dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return new ARMWinCOFFAsmBackend(T, TT); 830dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines case Triple::ELF: 831dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines assert(TheTriple.isOSBinFormatELF() && "using ELF for non-ELF target"); 832dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(Triple(TT).getOS()); 833dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return new ELFARMAsmBackend(T, TT, OSABI, isLittle); 834dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } 83536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 83636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 83736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen HinesMCAsmBackend *llvm::createARMLEAsmBackend(const Target &T, 83836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const MCRegisterInfo &MRI, 83936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines StringRef TT, StringRef CPU) { 84036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return createARMAsmBackend(T, MRI, TT, CPU, true); 84136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 84236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 84336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen HinesMCAsmBackend *llvm::createARMBEAsmBackend(const Target &T, 84436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const MCRegisterInfo &MRI, 84536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines StringRef TT, StringRef CPU) { 84636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return createARMAsmBackend(T, MRI, TT, CPU, false); 847d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim} 84836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 84936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen HinesMCAsmBackend *llvm::createThumbLEAsmBackend(const Target &T, 85036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const MCRegisterInfo &MRI, 85136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines StringRef TT, StringRef CPU) { 85236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return createARMAsmBackend(T, MRI, TT, CPU, true); 85336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 85436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 85536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen HinesMCAsmBackend *llvm::createThumbBEAsmBackend(const Target &T, 85636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const MCRegisterInfo &MRI, 85736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines StringRef TT, StringRef CPU) { 85836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return createARMAsmBackend(T, MRI, TT, CPU, false); 85936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 86036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 861