ARMAsmBackend.cpp revision 67b95f902a51b591b6178e370d23ffaca841275d
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" 2536d76a8dbc87b62de82a4a8c0d7cb4bb2a202934Daniel Dunbar#include "llvm/Object/MachOFormat.h" 26eecb858ca86fa949c06f819d6127e2ac68d165c8Wesley Peck#include "llvm/Support/ELF.h" 27d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim#include "llvm/Support/ErrorHandling.h" 28d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim#include "llvm/Support/raw_ostream.h" 29d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kimusing namespace llvm; 30d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim 31d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kimnamespace { 326024c97ffa15766bc0f200ffd309d9e017ae0d4bRafael Espindolaclass ARMELFObjectWriter : public MCELFObjectTargetWriter { 336024c97ffa15766bc0f200ffd309d9e017ae0d4bRafael Espindolapublic: 34bff66a86e6e44dc7424cd2d7719ac80630b3a5f8Rafael Espindola ARMELFObjectWriter(Triple::OSType OSType) 35bff66a86e6e44dc7424cd2d7719ac80630b3a5f8Rafael Espindola : MCELFObjectTargetWriter(/*Is64Bit*/ false, OSType, ELF::EM_ARM, 36bff66a86e6e44dc7424cd2d7719ac80630b3a5f8Rafael Espindola /*HasRelocationAddend*/ false) {} 376024c97ffa15766bc0f200ffd309d9e017ae0d4bRafael Espindola}; 386024c97ffa15766bc0f200ffd309d9e017ae0d4bRafael Espindola 3978c10eeaa57d1c6c4b7781d3c0bcb0cfbbc43b5cEvan Chengclass ARMAsmBackend : public MCAsmBackend { 40d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach const MCSubtargetInfo* STI; 415be6d2af38c29e3653998978345220974cc40c01Jim Grosbach bool isThumbMode; // Currently emitting Thumb code. 42d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kimpublic: 43d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach ARMAsmBackend(const Target &T, const StringRef TT) 44d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach : MCAsmBackend(), STI(ARM_MC::createARMMCSubtargetInfo(TT, "", "")), 45d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach isThumbMode(false) {} 46d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach 47d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach ~ARMAsmBackend() { 48d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach delete STI; 49d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach } 50d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim 512761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar unsigned getNumFixupKinds() const { return ARM::NumTargetFixupKinds; } 522761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar 53d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach bool hasNOP() const { 54d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach return (STI->getFeatureBits() & ARM::HasV6T2Ops) != 0; 55d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach } 56d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach 572761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const { 582761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar const static MCFixupKindInfo Infos[ARM::NumTargetFixupKinds] = { 592761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar// This table *must* be in the order that the fixup_* kinds are defined in 602761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar// ARMFixupKinds.h. 612761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar// 622761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar// Name Offset (bits) Size (bits) Flags 632761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar{ "fixup_arm_ldst_pcrel_12", 1, 24, MCFixupKindInfo::FKF_IsPCRel }, 642761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar{ "fixup_t2_ldst_pcrel_12", 0, 32, MCFixupKindInfo::FKF_IsPCRel | 652761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, 662761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar{ "fixup_arm_pcrel_10", 1, 24, MCFixupKindInfo::FKF_IsPCRel }, 672761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar{ "fixup_t2_pcrel_10", 0, 32, MCFixupKindInfo::FKF_IsPCRel | 682761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, 692761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar{ "fixup_thumb_adr_pcrel_10",0, 8, MCFixupKindInfo::FKF_IsPCRel | 702761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, 712761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar{ "fixup_arm_adr_pcrel_12", 1, 24, MCFixupKindInfo::FKF_IsPCRel }, 722761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar{ "fixup_t2_adr_pcrel_12", 0, 32, MCFixupKindInfo::FKF_IsPCRel | 732761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, 74685c350ae76b588e1f00c01a511fe8bd57f18394Jason W Kim{ "fixup_arm_condbranch", 0, 24, MCFixupKindInfo::FKF_IsPCRel }, 75685c350ae76b588e1f00c01a511fe8bd57f18394Jason W Kim{ "fixup_arm_uncondbranch", 0, 24, MCFixupKindInfo::FKF_IsPCRel }, 762761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar{ "fixup_t2_condbranch", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, 772761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar{ "fixup_t2_uncondbranch", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, 782761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar{ "fixup_arm_thumb_br", 0, 16, MCFixupKindInfo::FKF_IsPCRel }, 792761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar{ "fixup_arm_thumb_bl", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, 8090b5a08e1ffc4a1c18f7fa964ca561fa4b03c314Jim Grosbach{ "fixup_arm_thumb_blx", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, 812761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar{ "fixup_arm_thumb_cb", 0, 16, MCFixupKindInfo::FKF_IsPCRel }, 8267b95f902a51b591b6178e370d23ffaca841275dJim Grosbach{ "fixup_arm_thumb_cp", 0, 8, MCFixupKindInfo::FKF_IsPCRel }, 83fea51fc007598176d48fb7319a9bf471efb93127Eric Christopher{ "fixup_arm_thumb_bcc", 0, 8, MCFixupKindInfo::FKF_IsPCRel }, 84f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng// movw / movt: 16-bits immediate but scattered into two chunks 0 - 12, 16 - 19. 85f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng{ "fixup_arm_movt_hi16", 0, 20, 0 }, 86f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng{ "fixup_arm_movw_lo16", 0, 20, 0 }, 87f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng{ "fixup_t2_movt_hi16", 0, 20, 0 }, 88f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng{ "fixup_t2_movw_lo16", 0, 20, 0 }, 89f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng{ "fixup_arm_movt_hi16_pcrel", 0, 20, MCFixupKindInfo::FKF_IsPCRel }, 90f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng{ "fixup_arm_movw_lo16_pcrel", 0, 20, MCFixupKindInfo::FKF_IsPCRel }, 91f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng{ "fixup_t2_movt_hi16_pcrel", 0, 20, MCFixupKindInfo::FKF_IsPCRel }, 92f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng{ "fixup_t2_movw_lo16_pcrel", 0, 20, MCFixupKindInfo::FKF_IsPCRel }, 932761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar }; 942761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar 952761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar if (Kind < FirstTargetFixupKind) 9678c10eeaa57d1c6c4b7781d3c0bcb0cfbbc43b5cEvan Cheng return MCAsmBackend::getFixupKindInfo(Kind); 972761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar 982761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() && 992761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar "Invalid kind!"); 1002761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar return Infos[Kind - FirstTargetFixupKind]; 1012761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar } 1022761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbar 103d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim bool MayNeedRelaxation(const MCInst &Inst) const; 104d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim 105d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim void RelaxInstruction(const MCInst &Inst, MCInst &Res) const; 106d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim 107d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim bool WriteNopData(uint64_t Count, MCObjectWriter *OW) const; 1083787a40e038d6444a1b0e93f1cdc55fb006a5392Jim Grosbach 1095be6d2af38c29e3653998978345220974cc40c01Jim Grosbach void HandleAssemblerFlag(MCAssemblerFlag Flag) { 1105be6d2af38c29e3653998978345220974cc40c01Jim Grosbach switch (Flag) { 1115be6d2af38c29e3653998978345220974cc40c01Jim Grosbach default: break; 1125be6d2af38c29e3653998978345220974cc40c01Jim Grosbach case MCAF_Code16: 1135be6d2af38c29e3653998978345220974cc40c01Jim Grosbach setIsThumb(true); 1145be6d2af38c29e3653998978345220974cc40c01Jim Grosbach break; 1155be6d2af38c29e3653998978345220974cc40c01Jim Grosbach case MCAF_Code32: 1165be6d2af38c29e3653998978345220974cc40c01Jim Grosbach setIsThumb(false); 1175be6d2af38c29e3653998978345220974cc40c01Jim Grosbach break; 1185be6d2af38c29e3653998978345220974cc40c01Jim Grosbach } 1193787a40e038d6444a1b0e93f1cdc55fb006a5392Jim Grosbach } 1205be6d2af38c29e3653998978345220974cc40c01Jim Grosbach 1215be6d2af38c29e3653998978345220974cc40c01Jim Grosbach unsigned getPointerSize() const { return 4; } 1225be6d2af38c29e3653998978345220974cc40c01Jim Grosbach bool isThumb() const { return isThumbMode; } 1235be6d2af38c29e3653998978345220974cc40c01Jim Grosbach void setIsThumb(bool it) { isThumbMode = it; } 124d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim}; 125b75c651e22a63907b727664f044283bf9c9fb885Chris Lattner} // end anonymous namespace 126d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim 127d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kimbool ARMAsmBackend::MayNeedRelaxation(const MCInst &Inst) const { 128d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim // FIXME: Thumb targets, different move constant targets.. 129d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim return false; 130d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim} 131d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim 132d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kimvoid ARMAsmBackend::RelaxInstruction(const MCInst &Inst, MCInst &Res) const { 133d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim assert(0 && "ARMAsmBackend::RelaxInstruction() unimplemented"); 134d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim return; 135d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim} 136d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim 137d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kimbool ARMAsmBackend::WriteNopData(uint64_t Count, MCObjectWriter *OW) const { 138d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach const uint16_t Thumb1_16bitNopEncoding = 0x46c0; // using MOV r8,r8 139d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach const uint16_t Thumb2_16bitNopEncoding = 0xbf00; // NOP 140d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach const uint32_t ARMv4_NopEncoding = 0xe1a0000; // using MOV r0,r0 141d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach const uint32_t ARMv6T2_NopEncoding = 0xe3207800; // NOP 1425be6d2af38c29e3653998978345220974cc40c01Jim Grosbach if (isThumb()) { 143d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach const uint16_t nopEncoding = hasNOP() ? Thumb2_16bitNopEncoding 144d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach : Thumb1_16bitNopEncoding; 145a3dbd3a2444f2531763ba05b64a30932542a631fJim Grosbach uint64_t NumNops = Count / 2; 146a3dbd3a2444f2531763ba05b64a30932542a631fJim Grosbach for (uint64_t i = 0; i != NumNops; ++i) 147d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach OW->Write16(nopEncoding); 148a3dbd3a2444f2531763ba05b64a30932542a631fJim Grosbach if (Count & 1) 149a3dbd3a2444f2531763ba05b64a30932542a631fJim Grosbach OW->Write8(0); 1505be6d2af38c29e3653998978345220974cc40c01Jim Grosbach return true; 1515be6d2af38c29e3653998978345220974cc40c01Jim Grosbach } 1525be6d2af38c29e3653998978345220974cc40c01Jim Grosbach // ARM mode 153d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach const uint32_t nopEncoding = hasNOP() ? ARMv6T2_NopEncoding 154d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach : ARMv4_NopEncoding; 155a3dbd3a2444f2531763ba05b64a30932542a631fJim Grosbach uint64_t NumNops = Count / 4; 156a3dbd3a2444f2531763ba05b64a30932542a631fJim Grosbach for (uint64_t i = 0; i != NumNops; ++i) 157d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach OW->Write32(nopEncoding); 158d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach // FIXME: should this function return false when unable to write exactly 159d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach // 'Count' bytes with NOP encodings? 160a3dbd3a2444f2531763ba05b64a30932542a631fJim Grosbach switch (Count % 4) { 161a3dbd3a2444f2531763ba05b64a30932542a631fJim Grosbach default: break; // No leftover bytes to write 162a3dbd3a2444f2531763ba05b64a30932542a631fJim Grosbach case 1: OW->Write8(0); break; 163a3dbd3a2444f2531763ba05b64a30932542a631fJim Grosbach case 2: OW->Write16(0); break; 164a3dbd3a2444f2531763ba05b64a30932542a631fJim Grosbach case 3: OW->Write16(0); OW->Write8(0xa0); break; 165a3dbd3a2444f2531763ba05b64a30932542a631fJim Grosbach } 166a3dbd3a2444f2531763ba05b64a30932542a631fJim Grosbach 167cecbc3d28277ff4916326311cbf87335ed05d106Rafael Espindola return true; 16887dc3aa2d87871f1affc6f3f2fa587c7b6725d83Jim Grosbach} 169d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim 1700c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kimstatic unsigned adjustFixupValue(unsigned Kind, uint64_t Value) { 1710c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim switch (Kind) { 1720c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim default: 1730c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim llvm_unreachable("Unknown fixup kind!"); 1746ec6eeb692fa11b569af8b69b2bb11cc84f04926Jim Grosbach case FK_Data_1: 1756ec6eeb692fa11b569af8b69b2bb11cc84f04926Jim Grosbach case FK_Data_2: 1760c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim case FK_Data_4: 1772ccf148fbaaf9ea15233d7ef09e31ca0fa6ee3beJason W Kim return Value; 1780c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim case ARM::fixup_arm_movt_hi16: 179f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng Value >>= 16; 180f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng // Fallthrough 181f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng case ARM::fixup_arm_movw_lo16: 182861b9c6a397f2ed4b5601cacbc9121d0b07d1f65Jason W Kim case ARM::fixup_arm_movt_hi16_pcrel: 18386a97f2e4d0cde5e992f52ac287da0de687e0110Jason W Kim case ARM::fixup_arm_movw_lo16_pcrel: { 1842ccf148fbaaf9ea15233d7ef09e31ca0fa6ee3beJason W Kim unsigned Hi4 = (Value & 0xF000) >> 12; 1852ccf148fbaaf9ea15233d7ef09e31ca0fa6ee3beJason W Kim unsigned Lo12 = Value & 0x0FFF; 186861b9c6a397f2ed4b5601cacbc9121d0b07d1f65Jason W Kim assert ((((int64_t)Value) >= -0x8000) && (((int64_t)Value) <= 0x7fff) && 187861b9c6a397f2ed4b5601cacbc9121d0b07d1f65Jason W Kim "Out of range pc-relative fixup value!"); 1882ccf148fbaaf9ea15233d7ef09e31ca0fa6ee3beJason W Kim // inst{19-16} = Hi4; 1892ccf148fbaaf9ea15233d7ef09e31ca0fa6ee3beJason W Kim // inst{11-0} = Lo12; 1902ccf148fbaaf9ea15233d7ef09e31ca0fa6ee3beJason W Kim Value = (Hi4 << 16) | (Lo12); 1910c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim return Value; 1922ccf148fbaaf9ea15233d7ef09e31ca0fa6ee3beJason W Kim } 193f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng case ARM::fixup_t2_movt_hi16: 194f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng Value >>= 16; 195f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng // Fallthrough 196f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng case ARM::fixup_t2_movw_lo16: 1978b45456700f1e156b0a14000124f274dfac86f14Jim Grosbach case ARM::fixup_t2_movt_hi16_pcrel: //FIXME: Shouldn't this be shifted like 1988b45456700f1e156b0a14000124f274dfac86f14Jim Grosbach // the other hi16 fixup? 199f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng case ARM::fixup_t2_movw_lo16_pcrel: { 200f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng unsigned Hi4 = (Value & 0xF000) >> 12; 201f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng unsigned i = (Value & 0x800) >> 11; 202f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng unsigned Mid3 = (Value & 0x700) >> 8; 203f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng unsigned Lo8 = Value & 0x0FF; 204f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng // inst{19-16} = Hi4; 205f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng // inst{26} = i; 206f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng // inst{14-12} = Mid3; 207f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng // inst{7-0} = Lo8; 2088b45456700f1e156b0a14000124f274dfac86f14Jim Grosbach // The value comes in as the whole thing, not just the portion required 2098b45456700f1e156b0a14000124f274dfac86f14Jim Grosbach // for this fixup, so we need to mask off the bits not handled by this 2108b45456700f1e156b0a14000124f274dfac86f14Jim Grosbach // portion (lo vs. hi). 2118b45456700f1e156b0a14000124f274dfac86f14Jim Grosbach Value &= 0xffff; 212f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng Value = (Hi4 << 16) | (i << 26) | (Mid3 << 12) | (Lo8); 213f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng uint64_t swapped = (Value & 0xFFFF0000) >> 16; 214f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng swapped |= (Value & 0x0000FFFF) << 16; 215f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng return swapped; 216f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng } 217d7b3f5870d9d04351d9cd363d9d6af01482a2eb8Owen Anderson case ARM::fixup_arm_ldst_pcrel_12: 2180c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim // ARM PC-relative values are offset by 8. 21905018c2f2872a05b1a2fff1a9934621ba1f38084Owen Anderson Value -= 4; 220fe7fac74b4edaf9cc04460fc21aa949e5533aea2Owen Anderson // FALLTHROUGH 221d7b3f5870d9d04351d9cd363d9d6af01482a2eb8Owen Anderson case ARM::fixup_t2_ldst_pcrel_12: { 222d7b3f5870d9d04351d9cd363d9d6af01482a2eb8Owen Anderson // Offset by 4, adjusted by two due to the half-word ordering of thumb. 22305018c2f2872a05b1a2fff1a9934621ba1f38084Owen Anderson Value -= 4; 224d7b3f5870d9d04351d9cd363d9d6af01482a2eb8Owen Anderson bool isAdd = true; 2250c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim if ((int64_t)Value < 0) { 2260c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim Value = -Value; 2270c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim isAdd = false; 2280c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim } 2290c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim assert ((Value < 4096) && "Out of range pc-relative fixup value!"); 2300c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim Value |= isAdd << 23; 2317e294cfcf97cd7b94bf5c4de0f214480ec13adadJim Grosbach 232d7b3f5870d9d04351d9cd363d9d6af01482a2eb8Owen Anderson // Same addressing mode as fixup_arm_pcrel_10, 233d7b3f5870d9d04351d9cd363d9d6af01482a2eb8Owen Anderson // but with 16-bit halfwords swapped. 234d7b3f5870d9d04351d9cd363d9d6af01482a2eb8Owen Anderson if (Kind == ARM::fixup_t2_ldst_pcrel_12) { 235d7b3f5870d9d04351d9cd363d9d6af01482a2eb8Owen Anderson uint64_t swapped = (Value & 0xFFFF0000) >> 16; 236d7b3f5870d9d04351d9cd363d9d6af01482a2eb8Owen Anderson swapped |= (Value & 0x0000FFFF) << 16; 237d7b3f5870d9d04351d9cd363d9d6af01482a2eb8Owen Anderson return swapped; 238d7b3f5870d9d04351d9cd363d9d6af01482a2eb8Owen Anderson } 2397e294cfcf97cd7b94bf5c4de0f214480ec13adadJim Grosbach 2400c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim return Value; 2410c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim } 242d40963c4065432ec7e47879d3ca665a54ee903b6Jim Grosbach case ARM::fixup_thumb_adr_pcrel_10: 243d40963c4065432ec7e47879d3ca665a54ee903b6Jim Grosbach return ((Value - 4) >> 2) & 0xff; 244dff84b03258514463ede477af38f1246b95b0cd0Jim Grosbach case ARM::fixup_arm_adr_pcrel_12: { 245dff84b03258514463ede477af38f1246b95b0cd0Jim Grosbach // ARM PC-relative values are offset by 8. 246dff84b03258514463ede477af38f1246b95b0cd0Jim Grosbach Value -= 8; 247dff84b03258514463ede477af38f1246b95b0cd0Jim Grosbach unsigned opc = 4; // bits {24-21}. Default to add: 0b0100 248dff84b03258514463ede477af38f1246b95b0cd0Jim Grosbach if ((int64_t)Value < 0) { 249dff84b03258514463ede477af38f1246b95b0cd0Jim Grosbach Value = -Value; 250dff84b03258514463ede477af38f1246b95b0cd0Jim Grosbach opc = 2; // 0b0010 251dff84b03258514463ede477af38f1246b95b0cd0Jim Grosbach } 252dff84b03258514463ede477af38f1246b95b0cd0Jim Grosbach assert(ARM_AM::getSOImmVal(Value) != -1 && 253dff84b03258514463ede477af38f1246b95b0cd0Jim Grosbach "Out of range pc-relative fixup value!"); 254dff84b03258514463ede477af38f1246b95b0cd0Jim Grosbach // Encode the immediate and shift the opcode into place. 255dff84b03258514463ede477af38f1246b95b0cd0Jim Grosbach return ARM_AM::getSOImmVal(Value) | (opc << 21); 256dff84b03258514463ede477af38f1246b95b0cd0Jim Grosbach } 257e8eb1ea6acd54538b42491b95d8fc6281d4b5710Jim Grosbach 258a838a25d59838adfa91463f6a918ae3adeb352c1Owen Anderson case ARM::fixup_t2_adr_pcrel_12: { 259a838a25d59838adfa91463f6a918ae3adeb352c1Owen Anderson Value -= 4; 260a838a25d59838adfa91463f6a918ae3adeb352c1Owen Anderson unsigned opc = 0; 261a838a25d59838adfa91463f6a918ae3adeb352c1Owen Anderson if ((int64_t)Value < 0) { 262a838a25d59838adfa91463f6a918ae3adeb352c1Owen Anderson Value = -Value; 263a838a25d59838adfa91463f6a918ae3adeb352c1Owen Anderson opc = 5; 264a838a25d59838adfa91463f6a918ae3adeb352c1Owen Anderson } 265a838a25d59838adfa91463f6a918ae3adeb352c1Owen Anderson 266a838a25d59838adfa91463f6a918ae3adeb352c1Owen Anderson uint32_t out = (opc << 21); 267741ad15e26d1717433f326743800f30c63c6a9c1Owen Anderson out |= (Value & 0x800) << 15; 268a838a25d59838adfa91463f6a918ae3adeb352c1Owen Anderson out |= (Value & 0x700) << 4; 269a838a25d59838adfa91463f6a918ae3adeb352c1Owen Anderson out |= (Value & 0x0FF); 270e8eb1ea6acd54538b42491b95d8fc6281d4b5710Jim Grosbach 271a838a25d59838adfa91463f6a918ae3adeb352c1Owen Anderson uint64_t swapped = (out & 0xFFFF0000) >> 16; 272a838a25d59838adfa91463f6a918ae3adeb352c1Owen Anderson swapped |= (out & 0x0000FFFF) << 16; 273a838a25d59838adfa91463f6a918ae3adeb352c1Owen Anderson return swapped; 274a838a25d59838adfa91463f6a918ae3adeb352c1Owen Anderson } 275e8eb1ea6acd54538b42491b95d8fc6281d4b5710Jim Grosbach 276685c350ae76b588e1f00c01a511fe8bd57f18394Jason W Kim case ARM::fixup_arm_condbranch: 277685c350ae76b588e1f00c01a511fe8bd57f18394Jason W Kim case ARM::fixup_arm_uncondbranch: 2780c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim // These values don't encode the low two bits since they're always zero. 2790c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim // Offset by 8 just as above. 280662a816e89a9d77bf75e1328b09cf9235b4682aaJim Grosbach return 0xffffff & ((Value - 8) >> 2); 281c266600bec4b5ba0ee93ffdfeaafcab8f1295145Owen Anderson case ARM::fixup_t2_uncondbranch: { 28263ee22065dc4e8af7f4bf99c25b82da132700267Owen Anderson Value = Value - 4; 283fb20d890756b75d6ccfa7ab17f170a877d425dc6Owen Anderson Value >>= 1; // Low bit is not encoded. 2847e294cfcf97cd7b94bf5c4de0f214480ec13adadJim Grosbach 28556a2535474dd4482c432b3c75c3dab4b2f3dd1e2Jim Grosbach uint32_t out = 0; 286c266600bec4b5ba0ee93ffdfeaafcab8f1295145Owen Anderson bool I = Value & 0x800000; 287c266600bec4b5ba0ee93ffdfeaafcab8f1295145Owen Anderson bool J1 = Value & 0x400000; 288c266600bec4b5ba0ee93ffdfeaafcab8f1295145Owen Anderson bool J2 = Value & 0x200000; 289c266600bec4b5ba0ee93ffdfeaafcab8f1295145Owen Anderson J1 ^= I; 290c266600bec4b5ba0ee93ffdfeaafcab8f1295145Owen Anderson J2 ^= I; 291e8eb1ea6acd54538b42491b95d8fc6281d4b5710Jim Grosbach 292c266600bec4b5ba0ee93ffdfeaafcab8f1295145Owen Anderson out |= I << 26; // S bit 293c266600bec4b5ba0ee93ffdfeaafcab8f1295145Owen Anderson out |= !J1 << 13; // J1 bit 294c266600bec4b5ba0ee93ffdfeaafcab8f1295145Owen Anderson out |= !J2 << 11; // J2 bit 295c266600bec4b5ba0ee93ffdfeaafcab8f1295145Owen Anderson out |= (Value & 0x1FF800) << 5; // imm6 field 296c266600bec4b5ba0ee93ffdfeaafcab8f1295145Owen Anderson out |= (Value & 0x0007FF); // imm11 field 297e8eb1ea6acd54538b42491b95d8fc6281d4b5710Jim Grosbach 298c266600bec4b5ba0ee93ffdfeaafcab8f1295145Owen Anderson uint64_t swapped = (out & 0xFFFF0000) >> 16; 299c266600bec4b5ba0ee93ffdfeaafcab8f1295145Owen Anderson swapped |= (out & 0x0000FFFF) << 16; 300c266600bec4b5ba0ee93ffdfeaafcab8f1295145Owen Anderson return swapped; 301c266600bec4b5ba0ee93ffdfeaafcab8f1295145Owen Anderson } 302c266600bec4b5ba0ee93ffdfeaafcab8f1295145Owen Anderson case ARM::fixup_t2_condbranch: { 303c266600bec4b5ba0ee93ffdfeaafcab8f1295145Owen Anderson Value = Value - 4; 304c266600bec4b5ba0ee93ffdfeaafcab8f1295145Owen Anderson Value >>= 1; // Low bit is not encoded. 305e8eb1ea6acd54538b42491b95d8fc6281d4b5710Jim Grosbach 306c266600bec4b5ba0ee93ffdfeaafcab8f1295145Owen Anderson uint64_t out = 0; 3078f0794331765661f92cf074f638acb1ea927bb5dOwen Anderson out |= (Value & 0x80000) << 7; // S bit 3088f0794331765661f92cf074f638acb1ea927bb5dOwen Anderson out |= (Value & 0x40000) >> 7; // J2 bit 3098f0794331765661f92cf074f638acb1ea927bb5dOwen Anderson out |= (Value & 0x20000) >> 4; // J1 bit 3108f0794331765661f92cf074f638acb1ea927bb5dOwen Anderson out |= (Value & 0x1F800) << 5; // imm6 field 3118f0794331765661f92cf074f638acb1ea927bb5dOwen Anderson out |= (Value & 0x007FF); // imm11 field 3127e294cfcf97cd7b94bf5c4de0f214480ec13adadJim Grosbach 31356a2535474dd4482c432b3c75c3dab4b2f3dd1e2Jim Grosbach uint32_t swapped = (out & 0xFFFF0000) >> 16; 314fb20d890756b75d6ccfa7ab17f170a877d425dc6Owen Anderson swapped |= (out & 0x0000FFFF) << 16; 315fb20d890756b75d6ccfa7ab17f170a877d425dc6Owen Anderson return swapped; 316fb20d890756b75d6ccfa7ab17f170a877d425dc6Owen Anderson } 317662a816e89a9d77bf75e1328b09cf9235b4682aaJim Grosbach case ARM::fixup_arm_thumb_bl: { 318662a816e89a9d77bf75e1328b09cf9235b4682aaJim Grosbach // The value doesn't encode the low bit (always zero) and is offset by 319662a816e89a9d77bf75e1328b09cf9235b4682aaJim Grosbach // four. The value is encoded into disjoint bit positions in the destination 320662a816e89a9d77bf75e1328b09cf9235b4682aaJim Grosbach // opcode. x = unchanged, I = immediate value bit, S = sign extension bit 3217e294cfcf97cd7b94bf5c4de0f214480ec13adadJim Grosbach // 32209aa3f0ef35d9241c92439d74b8d5e9a81d814c2Bill Wendling // BL: xxxxxSIIIIIIIIII xxxxxIIIIIIIIIII 3237e294cfcf97cd7b94bf5c4de0f214480ec13adadJim Grosbach // 324662a816e89a9d77bf75e1328b09cf9235b4682aaJim Grosbach // Note that the halfwords are stored high first, low second; so we need 325662a816e89a9d77bf75e1328b09cf9235b4682aaJim Grosbach // to transpose the fixup value here to map properly. 326298c8e12ea063f7522c59d2a297b47a879b6ed55Rafael Espindola unsigned isNeg = (int64_t(Value - 4) < 0) ? 1 : 0; 327797b7aab35d815a48f58ce7f7b0b8d0fe06c92afBill Wendling uint32_t Binary = 0; 328797b7aab35d815a48f58ce7f7b0b8d0fe06c92afBill Wendling Value = 0x3fffff & ((Value - 4) >> 1); 329797b7aab35d815a48f58ce7f7b0b8d0fe06c92afBill Wendling Binary = (Value & 0x7ff) << 16; // Low imm11 value. 330797b7aab35d815a48f58ce7f7b0b8d0fe06c92afBill Wendling Binary |= (Value & 0x1ffc00) >> 11; // High imm10 value. 331797b7aab35d815a48f58ce7f7b0b8d0fe06c92afBill Wendling Binary |= isNeg << 10; // Sign bit. 33209aa3f0ef35d9241c92439d74b8d5e9a81d814c2Bill Wendling return Binary; 33309aa3f0ef35d9241c92439d74b8d5e9a81d814c2Bill Wendling } 33409aa3f0ef35d9241c92439d74b8d5e9a81d814c2Bill Wendling case ARM::fixup_arm_thumb_blx: { 33509aa3f0ef35d9241c92439d74b8d5e9a81d814c2Bill Wendling // The value doesn't encode the low two bits (always zero) and is offset by 33609aa3f0ef35d9241c92439d74b8d5e9a81d814c2Bill Wendling // four (see fixup_arm_thumb_cp). The value is encoded into disjoint bit 33709aa3f0ef35d9241c92439d74b8d5e9a81d814c2Bill Wendling // positions in the destination opcode. x = unchanged, I = immediate value 33809aa3f0ef35d9241c92439d74b8d5e9a81d814c2Bill Wendling // bit, S = sign extension bit, 0 = zero. 3397e294cfcf97cd7b94bf5c4de0f214480ec13adadJim Grosbach // 34009aa3f0ef35d9241c92439d74b8d5e9a81d814c2Bill Wendling // BLX: xxxxxSIIIIIIIIII xxxxxIIIIIIIIII0 3417e294cfcf97cd7b94bf5c4de0f214480ec13adadJim Grosbach // 34209aa3f0ef35d9241c92439d74b8d5e9a81d814c2Bill Wendling // Note that the halfwords are stored high first, low second; so we need 34309aa3f0ef35d9241c92439d74b8d5e9a81d814c2Bill Wendling // to transpose the fixup value here to map properly. 344298c8e12ea063f7522c59d2a297b47a879b6ed55Rafael Espindola unsigned isNeg = (int64_t(Value-4) < 0) ? 1 : 0; 345797b7aab35d815a48f58ce7f7b0b8d0fe06c92afBill Wendling uint32_t Binary = 0; 346797b7aab35d815a48f58ce7f7b0b8d0fe06c92afBill Wendling Value = 0xfffff & ((Value - 2) >> 2); 347797b7aab35d815a48f58ce7f7b0b8d0fe06c92afBill Wendling Binary = (Value & 0x3ff) << 17; // Low imm10L value. 348797b7aab35d815a48f58ce7f7b0b8d0fe06c92afBill Wendling Binary |= (Value & 0xffc00) >> 10; // High imm10H value. 349797b7aab35d815a48f58ce7f7b0b8d0fe06c92afBill Wendling Binary |= isNeg << 10; // Sign bit. 350662a816e89a9d77bf75e1328b09cf9235b4682aaJim Grosbach return Binary; 351662a816e89a9d77bf75e1328b09cf9235b4682aaJim Grosbach } 352b8958b031ec5163261f490f131780c5dc3d823d6Bill Wendling case ARM::fixup_arm_thumb_cp: 3530c2c217244573cdfb4be8b7fa62670412b4c1e71Jim Grosbach // Offset by 4, and don't encode the low two bits. Two bytes of that 3540c2c217244573cdfb4be8b7fa62670412b4c1e71Jim Grosbach // 'off by 4' is implicitly handled by the half-word ordering of the 3550c2c217244573cdfb4be8b7fa62670412b4c1e71Jim Grosbach // Thumb encoding, so we only need to adjust by 2 here. 3560c2c217244573cdfb4be8b7fa62670412b4c1e71Jim Grosbach return ((Value - 2) >> 2) & 0xff; 357b492a7c2134d3886f545f1b5ea55115d71529a10Jim Grosbach case ARM::fixup_arm_thumb_cb: { 358dff2f7151f695b86db8c4b0c6604463bdb8a63eaBill Wendling // Offset by 4 and don't encode the lower bit, which is always 0. 359dff2f7151f695b86db8c4b0c6604463bdb8a63eaBill Wendling uint32_t Binary = (Value - 4) >> 1; 36086abd48fd01080f08eec1b46f92c90308b03bfd4Owen Anderson return ((Binary & 0x20) << 4) | ((Binary & 0x1f) << 3); 361dff2f7151f695b86db8c4b0c6604463bdb8a63eaBill Wendling } 362e246717c3a36a913fd4200776ed621649bb2b624Jim Grosbach case ARM::fixup_arm_thumb_br: 363e246717c3a36a913fd4200776ed621649bb2b624Jim Grosbach // Offset by 4 and don't encode the lower bit, which is always 0. 364e246717c3a36a913fd4200776ed621649bb2b624Jim Grosbach return ((Value - 4) >> 1) & 0x7ff; 36501086451393ef33e82b6fad623989dd97dd70edfJim Grosbach case ARM::fixup_arm_thumb_bcc: 36601086451393ef33e82b6fad623989dd97dd70edfJim Grosbach // Offset by 4 and don't encode the lower bit, which is always 0. 36701086451393ef33e82b6fad623989dd97dd70edfJim Grosbach return ((Value - 4) >> 1) & 0xff; 3680c2c217244573cdfb4be8b7fa62670412b4c1e71Jim Grosbach case ARM::fixup_arm_pcrel_10: 369e2e0f58809374265bd75edeefae8817e7ade62b4Owen Anderson Value = Value - 4; // ARM fixups offset by an additional word and don't 3700c2c217244573cdfb4be8b7fa62670412b4c1e71Jim Grosbach // need to adjust for the half-word ordering. 3710c2c217244573cdfb4be8b7fa62670412b4c1e71Jim Grosbach // Fall through. 3720c2c217244573cdfb4be8b7fa62670412b4c1e71Jim Grosbach case ARM::fixup_t2_pcrel_10: { 3730c2c217244573cdfb4be8b7fa62670412b4c1e71Jim Grosbach // Offset by 4, adjusted by two due to the half-word ordering of thumb. 374e2e0f58809374265bd75edeefae8817e7ade62b4Owen Anderson Value = Value - 4; 3750c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim bool isAdd = true; 3760c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim if ((int64_t)Value < 0) { 3770c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim Value = -Value; 3780c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim isAdd = false; 3790c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim } 3800c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim // These values don't encode the low two bits since they're always zero. 3810c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim Value >>= 2; 3820c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim assert ((Value < 256) && "Out of range pc-relative fixup value!"); 3830c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim Value |= isAdd << 23; 3840c2c217244573cdfb4be8b7fa62670412b4c1e71Jim Grosbach 385cc78f5c09c451dd84ef5c4abdfcdadd4270a4942Owen Anderson // Same addressing mode as fixup_arm_pcrel_10, 386cc78f5c09c451dd84ef5c4abdfcdadd4270a4942Owen Anderson // but with 16-bit halfwords swapped. 387d8e351b96f5fd7007fbdd636acaa1fc9f6e18f3cOwen Anderson if (Kind == ARM::fixup_t2_pcrel_10) { 38856a2535474dd4482c432b3c75c3dab4b2f3dd1e2Jim Grosbach uint32_t swapped = (Value & 0xFFFF0000) >> 16; 389255eafbd498e7d41ceef45ee0ad13bfde573ff82Owen Anderson swapped |= (Value & 0x0000FFFF) << 16; 390d8e351b96f5fd7007fbdd636acaa1fc9f6e18f3cOwen Anderson return swapped; 391d8e351b96f5fd7007fbdd636acaa1fc9f6e18f3cOwen Anderson } 3920c2c217244573cdfb4be8b7fa62670412b4c1e71Jim Grosbach 3930c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim return Value; 3940c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim } 3950c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim } 3960c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim} 3970c628c2617a2c25cabea6d1cb8bd13b79b3cb15aJason W Kim 398d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kimnamespace { 39952e635ea3512cfcd03587201b20100074e5b6ac9Bill Wendling 400d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim// FIXME: This should be in a separate file. 401d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim// ELF is an ELF of course... 402d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kimclass ELFARMAsmBackend : public ARMAsmBackend { 403d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kimpublic: 404d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim Triple::OSType OSType; 405d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach ELFARMAsmBackend(const Target &T, const StringRef TT, 406d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach Triple::OSType _OSType) 407d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach : ARMAsmBackend(T, TT), OSType(_OSType) { } 408d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim 409179821ac1f282ef6f8d24d5ea346028aee8ba4c7Rafael Espindola void ApplyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, 410d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim uint64_t Value) const; 411d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim 412d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim MCObjectWriter *createObjectWriter(raw_ostream &OS) const { 413bff66a86e6e44dc7424cd2d7719ac80630b3a5f8Rafael Espindola return createELFObjectWriter(new ARMELFObjectWriter(OSType), OS, 414bff66a86e6e44dc7424cd2d7719ac80630b3a5f8Rafael Espindola /*IsLittleEndian*/ true); 415d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim } 416d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim}; 417d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim 41852e635ea3512cfcd03587201b20100074e5b6ac9Bill Wendling// FIXME: Raise this to share code between Darwin and ELF. 419179821ac1f282ef6f8d24d5ea346028aee8ba4c7Rafael Espindolavoid ELFARMAsmBackend::ApplyFixup(const MCFixup &Fixup, char *Data, 420179821ac1f282ef6f8d24d5ea346028aee8ba4c7Rafael Espindola unsigned DataSize, uint64_t Value) const { 42152e635ea3512cfcd03587201b20100074e5b6ac9Bill Wendling unsigned NumBytes = 4; // FIXME: 2 for Thumb 42285fed5e0c5bc010f967948a4af6b425a5a2f2bd0Jason W Kim Value = adjustFixupValue(Fixup.getKind(), Value); 423d832fa053b86f42a5bc1e55e979b61c1115a8053Bill Wendling if (!Value) return; // Doesn't change encoding. 42485fed5e0c5bc010f967948a4af6b425a5a2f2bd0Jason W Kim 42552e635ea3512cfcd03587201b20100074e5b6ac9Bill Wendling unsigned Offset = Fixup.getOffset(); 42652e635ea3512cfcd03587201b20100074e5b6ac9Bill Wendling 42752e635ea3512cfcd03587201b20100074e5b6ac9Bill Wendling // For each byte of the fragment that the fixup touches, mask in the bits from 42852e635ea3512cfcd03587201b20100074e5b6ac9Bill Wendling // the fixup value. The Value has been "split up" into the appropriate 42952e635ea3512cfcd03587201b20100074e5b6ac9Bill Wendling // bitfields above. 43052e635ea3512cfcd03587201b20100074e5b6ac9Bill Wendling for (unsigned i = 0; i != NumBytes; ++i) 43152e635ea3512cfcd03587201b20100074e5b6ac9Bill Wendling Data[Offset + i] |= uint8_t((Value >> (i * 8)) & 0xff); 432d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim} 433d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim 434d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim// FIXME: This should be in a separate file. 435d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kimclass DarwinARMAsmBackend : public ARMAsmBackend { 436d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kimpublic: 4371721324d97e2b05c9276ffe116dfb6c808521c2bOwen Anderson const object::mach::CPUSubtypeARM Subtype; 438d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach DarwinARMAsmBackend(const Target &T, const StringRef TT, 439d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach object::mach::CPUSubtypeARM st) 440d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach : ARMAsmBackend(T, TT), Subtype(st) { } 441d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim 442d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim MCObjectWriter *createObjectWriter(raw_ostream &OS) const { 4432fc689888623743502b62e979767dd5c71e692bbJim Grosbach return createARMMachObjectWriter(OS, /*Is64Bit=*/false, 4442fc689888623743502b62e979767dd5c71e692bbJim Grosbach object::mach::CTM_ARM, 4452fc689888623743502b62e979767dd5c71e692bbJim Grosbach Subtype); 446d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim } 447d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim 4481721324d97e2b05c9276ffe116dfb6c808521c2bOwen Anderson void ApplyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, 4491721324d97e2b05c9276ffe116dfb6c808521c2bOwen Anderson uint64_t Value) const; 4501721324d97e2b05c9276ffe116dfb6c808521c2bOwen Anderson 451d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim virtual bool doesSectionRequireSymbols(const MCSection &Section) const { 452d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim return false; 453d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim } 454d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim}; 455d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim 456d832fa053b86f42a5bc1e55e979b61c1115a8053Bill Wendling/// getFixupKindNumBytes - The number of bytes the fixup may change. 457c466b937dbdbaabeef0097fe340de1b8f49a3508Jim Grosbachstatic unsigned getFixupKindNumBytes(unsigned Kind) { 458679cbd3b215b1769a6035e334f9009aeeb940dddJim Grosbach switch (Kind) { 459662a816e89a9d77bf75e1328b09cf9235b4682aaJim Grosbach default: 460662a816e89a9d77bf75e1328b09cf9235b4682aaJim Grosbach llvm_unreachable("Unknown fixup kind!"); 461b8958b031ec5163261f490f131780c5dc3d823d6Bill Wendling 4626ec6eeb692fa11b569af8b69b2bb11cc84f04926Jim Grosbach case FK_Data_1: 46301086451393ef33e82b6fad623989dd97dd70edfJim Grosbach case ARM::fixup_arm_thumb_bcc: 464b8958b031ec5163261f490f131780c5dc3d823d6Bill Wendling case ARM::fixup_arm_thumb_cp: 465d40963c4065432ec7e47879d3ca665a54ee903b6Jim Grosbach case ARM::fixup_thumb_adr_pcrel_10: 466b8958b031ec5163261f490f131780c5dc3d823d6Bill Wendling return 1; 467b8958b031ec5163261f490f131780c5dc3d823d6Bill Wendling 4686ec6eeb692fa11b569af8b69b2bb11cc84f04926Jim Grosbach case FK_Data_2: 469e246717c3a36a913fd4200776ed621649bb2b624Jim Grosbach case ARM::fixup_arm_thumb_br: 470b492a7c2134d3886f545f1b5ea55115d71529a10Jim Grosbach case ARM::fixup_arm_thumb_cb: 471dff2f7151f695b86db8c4b0c6604463bdb8a63eaBill Wendling return 2; 472dff2f7151f695b86db8c4b0c6604463bdb8a63eaBill Wendling 473662a816e89a9d77bf75e1328b09cf9235b4682aaJim Grosbach case ARM::fixup_arm_ldst_pcrel_12: 474662a816e89a9d77bf75e1328b09cf9235b4682aaJim Grosbach case ARM::fixup_arm_pcrel_10: 475662a816e89a9d77bf75e1328b09cf9235b4682aaJim Grosbach case ARM::fixup_arm_adr_pcrel_12: 476685c350ae76b588e1f00c01a511fe8bd57f18394Jason W Kim case ARM::fixup_arm_condbranch: 477685c350ae76b588e1f00c01a511fe8bd57f18394Jason W Kim case ARM::fixup_arm_uncondbranch: 478662a816e89a9d77bf75e1328b09cf9235b4682aaJim Grosbach return 3; 479b8958b031ec5163261f490f131780c5dc3d823d6Bill Wendling 480b8958b031ec5163261f490f131780c5dc3d823d6Bill Wendling case FK_Data_4: 481d7b3f5870d9d04351d9cd363d9d6af01482a2eb8Owen Anderson case ARM::fixup_t2_ldst_pcrel_12: 482c266600bec4b5ba0ee93ffdfeaafcab8f1295145Owen Anderson case ARM::fixup_t2_condbranch: 483c266600bec4b5ba0ee93ffdfeaafcab8f1295145Owen Anderson case ARM::fixup_t2_uncondbranch: 484d8e351b96f5fd7007fbdd636acaa1fc9f6e18f3cOwen Anderson case ARM::fixup_t2_pcrel_10: 485a838a25d59838adfa91463f6a918ae3adeb352c1Owen Anderson case ARM::fixup_t2_adr_pcrel_12: 486662a816e89a9d77bf75e1328b09cf9235b4682aaJim Grosbach case ARM::fixup_arm_thumb_bl: 48709aa3f0ef35d9241c92439d74b8d5e9a81d814c2Bill Wendling case ARM::fixup_arm_thumb_blx: 488f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng case ARM::fixup_arm_movt_hi16: 489f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng case ARM::fixup_arm_movw_lo16: 490f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng case ARM::fixup_arm_movt_hi16_pcrel: 491f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng case ARM::fixup_arm_movw_lo16_pcrel: 492f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng case ARM::fixup_t2_movt_hi16: 493f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng case ARM::fixup_t2_movw_lo16: 494f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng case ARM::fixup_t2_movt_hi16_pcrel: 495f3eb3bba1614a7935b44fc963a805088d71267f3Evan Cheng case ARM::fixup_t2_movw_lo16_pcrel: 496662a816e89a9d77bf75e1328b09cf9235b4682aaJim Grosbach return 4; 497679cbd3b215b1769a6035e334f9009aeeb940dddJim Grosbach } 498679cbd3b215b1769a6035e334f9009aeeb940dddJim Grosbach} 499679cbd3b215b1769a6035e334f9009aeeb940dddJim Grosbach 500179821ac1f282ef6f8d24d5ea346028aee8ba4c7Rafael Espindolavoid DarwinARMAsmBackend::ApplyFixup(const MCFixup &Fixup, char *Data, 501179821ac1f282ef6f8d24d5ea346028aee8ba4c7Rafael Espindola unsigned DataSize, uint64_t Value) const { 502c466b937dbdbaabeef0097fe340de1b8f49a3508Jim Grosbach unsigned NumBytes = getFixupKindNumBytes(Fixup.getKind()); 503679cbd3b215b1769a6035e334f9009aeeb940dddJim Grosbach Value = adjustFixupValue(Fixup.getKind(), Value); 504d832fa053b86f42a5bc1e55e979b61c1115a8053Bill Wendling if (!Value) return; // Doesn't change encoding. 505d832fa053b86f42a5bc1e55e979b61c1115a8053Bill Wendling 506d832fa053b86f42a5bc1e55e979b61c1115a8053Bill Wendling unsigned Offset = Fixup.getOffset(); 507d832fa053b86f42a5bc1e55e979b61c1115a8053Bill Wendling assert(Offset + NumBytes <= DataSize && "Invalid fixup offset!"); 508679cbd3b215b1769a6035e334f9009aeeb940dddJim Grosbach 509679cbd3b215b1769a6035e334f9009aeeb940dddJim Grosbach // For each byte of the fragment that the fixup touches, mask in the 510679cbd3b215b1769a6035e334f9009aeeb940dddJim Grosbach // bits from the fixup value. 511679cbd3b215b1769a6035e334f9009aeeb940dddJim Grosbach for (unsigned i = 0; i != NumBytes; ++i) 512d832fa053b86f42a5bc1e55e979b61c1115a8053Bill Wendling Data[Offset + i] |= uint8_t((Value >> (i * 8)) & 0xff); 513d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim} 51452e635ea3512cfcd03587201b20100074e5b6ac9Bill Wendling 515f73fd7278f2bebd435c84c55a79db8ccb07d3534Jim Grosbach} // end anonymous namespace 516d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim 51778c10eeaa57d1c6c4b7781d3c0bcb0cfbbc43b5cEvan ChengMCAsmBackend *llvm::createARMAsmBackend(const Target &T, StringRef TT) { 5181721324d97e2b05c9276ffe116dfb6c808521c2bOwen Anderson Triple TheTriple(TT); 519912225e18559a73228099330a4c253fdccf9fa3dDaniel Dunbar 520912225e18559a73228099330a4c253fdccf9fa3dDaniel Dunbar if (TheTriple.isOSDarwin()) { 521a6eb2562b62fc293295f2fede2608753563e7005Evan Cheng if (TheTriple.getArchName() == "armv4t" || 522a6eb2562b62fc293295f2fede2608753563e7005Evan Cheng TheTriple.getArchName() == "thumbv4t") 523d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach return new DarwinARMAsmBackend(T, TT, object::mach::CSARM_V4T); 524a6eb2562b62fc293295f2fede2608753563e7005Evan Cheng else if (TheTriple.getArchName() == "armv5e" || 525a6eb2562b62fc293295f2fede2608753563e7005Evan Cheng TheTriple.getArchName() == "thumbv5e") 526d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach return new DarwinARMAsmBackend(T, TT, object::mach::CSARM_V5TEJ); 527a6eb2562b62fc293295f2fede2608753563e7005Evan Cheng else if (TheTriple.getArchName() == "armv6" || 5281721324d97e2b05c9276ffe116dfb6c808521c2bOwen Anderson TheTriple.getArchName() == "thumbv6") 529d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach return new DarwinARMAsmBackend(T, TT, object::mach::CSARM_V6); 530d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach return new DarwinARMAsmBackend(T, TT, object::mach::CSARM_V7); 5311721324d97e2b05c9276ffe116dfb6c808521c2bOwen Anderson } 532912225e18559a73228099330a4c253fdccf9fa3dDaniel Dunbar 533912225e18559a73228099330a4c253fdccf9fa3dDaniel Dunbar if (TheTriple.isOSWindows()) 534d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim assert(0 && "Windows not supported on ARM"); 535912225e18559a73228099330a4c253fdccf9fa3dDaniel Dunbar 536d0d3f7e01ff7f83575816f6e1d75aa2224ebc2cbJim Grosbach return new ELFARMAsmBackend(T, TT, Triple(TT).getOS()); 537d4d4f4f488d46a9743a0c494b42b22a1b15e0e7dJason W Kim} 538