1*9880d681SAndroid Build Coastguard Worker //===-- ARMAsmBackend.cpp - ARM Assembler Backend -------------------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker
10*9880d681SAndroid Build Coastguard Worker #include "MCTargetDesc/ARMMCTargetDesc.h"
11*9880d681SAndroid Build Coastguard Worker #include "MCTargetDesc/ARMAddressingModes.h"
12*9880d681SAndroid Build Coastguard Worker #include "MCTargetDesc/ARMAsmBackend.h"
13*9880d681SAndroid Build Coastguard Worker #include "MCTargetDesc/ARMAsmBackendDarwin.h"
14*9880d681SAndroid Build Coastguard Worker #include "MCTargetDesc/ARMAsmBackendELF.h"
15*9880d681SAndroid Build Coastguard Worker #include "MCTargetDesc/ARMAsmBackendWinCOFF.h"
16*9880d681SAndroid Build Coastguard Worker #include "MCTargetDesc/ARMBaseInfo.h"
17*9880d681SAndroid Build Coastguard Worker #include "MCTargetDesc/ARMFixupKinds.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/StringSwitch.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCAsmBackend.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCAssembler.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCContext.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCDirectives.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCELFObjectWriter.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCExpr.h"
25*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCFixupKindInfo.h"
26*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCMachObjectWriter.h"
27*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCObjectWriter.h"
28*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCRegisterInfo.h"
29*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCSectionELF.h"
30*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCSectionMachO.h"
31*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCSubtargetInfo.h"
32*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCValue.h"
33*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Debug.h"
34*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/ELF.h"
35*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/ErrorHandling.h"
36*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Format.h"
37*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/MachO.h"
38*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/TargetParser.h"
39*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
40*9880d681SAndroid Build Coastguard Worker using namespace llvm;
41*9880d681SAndroid Build Coastguard Worker
42*9880d681SAndroid Build Coastguard Worker namespace {
43*9880d681SAndroid Build Coastguard Worker class ARMELFObjectWriter : public MCELFObjectTargetWriter {
44*9880d681SAndroid Build Coastguard Worker public:
ARMELFObjectWriter(uint8_t OSABI)45*9880d681SAndroid Build Coastguard Worker ARMELFObjectWriter(uint8_t OSABI)
46*9880d681SAndroid Build Coastguard Worker : MCELFObjectTargetWriter(/*Is64Bit*/ false, OSABI, ELF::EM_ARM,
47*9880d681SAndroid Build Coastguard Worker /*HasRelocationAddend*/ false) {}
48*9880d681SAndroid Build Coastguard Worker };
49*9880d681SAndroid Build Coastguard Worker } // end anonymous namespace
50*9880d681SAndroid Build Coastguard Worker
getFixupKindInfo(MCFixupKind Kind) const51*9880d681SAndroid Build Coastguard Worker const MCFixupKindInfo &ARMAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
52*9880d681SAndroid Build Coastguard Worker const static MCFixupKindInfo InfosLE[ARM::NumTargetFixupKinds] = {
53*9880d681SAndroid Build Coastguard Worker // This table *must* be in the order that the fixup_* kinds are defined in
54*9880d681SAndroid Build Coastguard Worker // ARMFixupKinds.h.
55*9880d681SAndroid Build Coastguard Worker //
56*9880d681SAndroid Build Coastguard Worker // Name Offset (bits) Size (bits) Flags
57*9880d681SAndroid Build Coastguard Worker {"fixup_arm_ldst_pcrel_12", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
58*9880d681SAndroid Build Coastguard Worker {"fixup_t2_ldst_pcrel_12", 0, 32,
59*9880d681SAndroid Build Coastguard Worker MCFixupKindInfo::FKF_IsPCRel |
60*9880d681SAndroid Build Coastguard Worker MCFixupKindInfo::FKF_IsAlignedDownTo32Bits},
61*9880d681SAndroid Build Coastguard Worker {"fixup_arm_pcrel_10_unscaled", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
62*9880d681SAndroid Build Coastguard Worker {"fixup_arm_pcrel_10", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
63*9880d681SAndroid Build Coastguard Worker {"fixup_t2_pcrel_10", 0, 32,
64*9880d681SAndroid Build Coastguard Worker MCFixupKindInfo::FKF_IsPCRel |
65*9880d681SAndroid Build Coastguard Worker MCFixupKindInfo::FKF_IsAlignedDownTo32Bits},
66*9880d681SAndroid Build Coastguard Worker {"fixup_arm_pcrel_9", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
67*9880d681SAndroid Build Coastguard Worker {"fixup_t2_pcrel_9", 0, 32,
68*9880d681SAndroid Build Coastguard Worker MCFixupKindInfo::FKF_IsPCRel |
69*9880d681SAndroid Build Coastguard Worker MCFixupKindInfo::FKF_IsAlignedDownTo32Bits},
70*9880d681SAndroid Build Coastguard Worker {"fixup_thumb_adr_pcrel_10", 0, 8,
71*9880d681SAndroid Build Coastguard Worker MCFixupKindInfo::FKF_IsPCRel |
72*9880d681SAndroid Build Coastguard Worker MCFixupKindInfo::FKF_IsAlignedDownTo32Bits},
73*9880d681SAndroid Build Coastguard Worker {"fixup_arm_adr_pcrel_12", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
74*9880d681SAndroid Build Coastguard Worker {"fixup_t2_adr_pcrel_12", 0, 32,
75*9880d681SAndroid Build Coastguard Worker MCFixupKindInfo::FKF_IsPCRel |
76*9880d681SAndroid Build Coastguard Worker MCFixupKindInfo::FKF_IsAlignedDownTo32Bits},
77*9880d681SAndroid Build Coastguard Worker {"fixup_arm_condbranch", 0, 24, MCFixupKindInfo::FKF_IsPCRel},
78*9880d681SAndroid Build Coastguard Worker {"fixup_arm_uncondbranch", 0, 24, MCFixupKindInfo::FKF_IsPCRel},
79*9880d681SAndroid Build Coastguard Worker {"fixup_t2_condbranch", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
80*9880d681SAndroid Build Coastguard Worker {"fixup_t2_uncondbranch", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
81*9880d681SAndroid Build Coastguard Worker {"fixup_arm_thumb_br", 0, 16, MCFixupKindInfo::FKF_IsPCRel},
82*9880d681SAndroid Build Coastguard Worker {"fixup_arm_uncondbl", 0, 24, MCFixupKindInfo::FKF_IsPCRel},
83*9880d681SAndroid Build Coastguard Worker {"fixup_arm_condbl", 0, 24, MCFixupKindInfo::FKF_IsPCRel},
84*9880d681SAndroid Build Coastguard Worker {"fixup_arm_blx", 0, 24, MCFixupKindInfo::FKF_IsPCRel},
85*9880d681SAndroid Build Coastguard Worker {"fixup_arm_thumb_bl", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
86*9880d681SAndroid Build Coastguard Worker {"fixup_arm_thumb_blx", 0, 32,
87*9880d681SAndroid Build Coastguard Worker MCFixupKindInfo::FKF_IsPCRel |
88*9880d681SAndroid Build Coastguard Worker MCFixupKindInfo::FKF_IsAlignedDownTo32Bits},
89*9880d681SAndroid Build Coastguard Worker {"fixup_arm_thumb_cb", 0, 16, MCFixupKindInfo::FKF_IsPCRel},
90*9880d681SAndroid Build Coastguard Worker {"fixup_arm_thumb_cp", 0, 8,
91*9880d681SAndroid Build Coastguard Worker MCFixupKindInfo::FKF_IsPCRel |
92*9880d681SAndroid Build Coastguard Worker MCFixupKindInfo::FKF_IsAlignedDownTo32Bits},
93*9880d681SAndroid Build Coastguard Worker {"fixup_arm_thumb_bcc", 0, 8, MCFixupKindInfo::FKF_IsPCRel},
94*9880d681SAndroid Build Coastguard Worker // movw / movt: 16-bits immediate but scattered into two chunks 0 - 12, 16
95*9880d681SAndroid Build Coastguard Worker // - 19.
96*9880d681SAndroid Build Coastguard Worker {"fixup_arm_movt_hi16", 0, 20, 0},
97*9880d681SAndroid Build Coastguard Worker {"fixup_arm_movw_lo16", 0, 20, 0},
98*9880d681SAndroid Build Coastguard Worker {"fixup_t2_movt_hi16", 0, 20, 0},
99*9880d681SAndroid Build Coastguard Worker {"fixup_t2_movw_lo16", 0, 20, 0},
100*9880d681SAndroid Build Coastguard Worker {"fixup_arm_mod_imm", 0, 12, 0},
101*9880d681SAndroid Build Coastguard Worker };
102*9880d681SAndroid Build Coastguard Worker const static MCFixupKindInfo InfosBE[ARM::NumTargetFixupKinds] = {
103*9880d681SAndroid Build Coastguard Worker // This table *must* be in the order that the fixup_* kinds are defined in
104*9880d681SAndroid Build Coastguard Worker // ARMFixupKinds.h.
105*9880d681SAndroid Build Coastguard Worker //
106*9880d681SAndroid Build Coastguard Worker // Name Offset (bits) Size (bits) Flags
107*9880d681SAndroid Build Coastguard Worker {"fixup_arm_ldst_pcrel_12", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
108*9880d681SAndroid Build Coastguard Worker {"fixup_t2_ldst_pcrel_12", 0, 32,
109*9880d681SAndroid Build Coastguard Worker MCFixupKindInfo::FKF_IsPCRel |
110*9880d681SAndroid Build Coastguard Worker MCFixupKindInfo::FKF_IsAlignedDownTo32Bits},
111*9880d681SAndroid Build Coastguard Worker {"fixup_arm_pcrel_10_unscaled", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
112*9880d681SAndroid Build Coastguard Worker {"fixup_arm_pcrel_10", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
113*9880d681SAndroid Build Coastguard Worker {"fixup_t2_pcrel_10", 0, 32,
114*9880d681SAndroid Build Coastguard Worker MCFixupKindInfo::FKF_IsPCRel |
115*9880d681SAndroid Build Coastguard Worker MCFixupKindInfo::FKF_IsAlignedDownTo32Bits},
116*9880d681SAndroid Build Coastguard Worker {"fixup_arm_pcrel_9", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
117*9880d681SAndroid Build Coastguard Worker {"fixup_t2_pcrel_9", 0, 32,
118*9880d681SAndroid Build Coastguard Worker MCFixupKindInfo::FKF_IsPCRel |
119*9880d681SAndroid Build Coastguard Worker MCFixupKindInfo::FKF_IsAlignedDownTo32Bits},
120*9880d681SAndroid Build Coastguard Worker {"fixup_thumb_adr_pcrel_10", 8, 8,
121*9880d681SAndroid Build Coastguard Worker MCFixupKindInfo::FKF_IsPCRel |
122*9880d681SAndroid Build Coastguard Worker MCFixupKindInfo::FKF_IsAlignedDownTo32Bits},
123*9880d681SAndroid Build Coastguard Worker {"fixup_arm_adr_pcrel_12", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
124*9880d681SAndroid Build Coastguard Worker {"fixup_t2_adr_pcrel_12", 0, 32,
125*9880d681SAndroid Build Coastguard Worker MCFixupKindInfo::FKF_IsPCRel |
126*9880d681SAndroid Build Coastguard Worker MCFixupKindInfo::FKF_IsAlignedDownTo32Bits},
127*9880d681SAndroid Build Coastguard Worker {"fixup_arm_condbranch", 8, 24, MCFixupKindInfo::FKF_IsPCRel},
128*9880d681SAndroid Build Coastguard Worker {"fixup_arm_uncondbranch", 8, 24, MCFixupKindInfo::FKF_IsPCRel},
129*9880d681SAndroid Build Coastguard Worker {"fixup_t2_condbranch", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
130*9880d681SAndroid Build Coastguard Worker {"fixup_t2_uncondbranch", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
131*9880d681SAndroid Build Coastguard Worker {"fixup_arm_thumb_br", 0, 16, MCFixupKindInfo::FKF_IsPCRel},
132*9880d681SAndroid Build Coastguard Worker {"fixup_arm_uncondbl", 8, 24, MCFixupKindInfo::FKF_IsPCRel},
133*9880d681SAndroid Build Coastguard Worker {"fixup_arm_condbl", 8, 24, MCFixupKindInfo::FKF_IsPCRel},
134*9880d681SAndroid Build Coastguard Worker {"fixup_arm_blx", 8, 24, MCFixupKindInfo::FKF_IsPCRel},
135*9880d681SAndroid Build Coastguard Worker {"fixup_arm_thumb_bl", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
136*9880d681SAndroid Build Coastguard Worker {"fixup_arm_thumb_blx", 0, 32,
137*9880d681SAndroid Build Coastguard Worker MCFixupKindInfo::FKF_IsPCRel |
138*9880d681SAndroid Build Coastguard Worker MCFixupKindInfo::FKF_IsAlignedDownTo32Bits},
139*9880d681SAndroid Build Coastguard Worker {"fixup_arm_thumb_cb", 0, 16, MCFixupKindInfo::FKF_IsPCRel},
140*9880d681SAndroid Build Coastguard Worker {"fixup_arm_thumb_cp", 8, 8,
141*9880d681SAndroid Build Coastguard Worker MCFixupKindInfo::FKF_IsPCRel |
142*9880d681SAndroid Build Coastguard Worker MCFixupKindInfo::FKF_IsAlignedDownTo32Bits},
143*9880d681SAndroid Build Coastguard Worker {"fixup_arm_thumb_bcc", 8, 8, MCFixupKindInfo::FKF_IsPCRel},
144*9880d681SAndroid Build Coastguard Worker // movw / movt: 16-bits immediate but scattered into two chunks 0 - 12, 16
145*9880d681SAndroid Build Coastguard Worker // - 19.
146*9880d681SAndroid Build Coastguard Worker {"fixup_arm_movt_hi16", 12, 20, 0},
147*9880d681SAndroid Build Coastguard Worker {"fixup_arm_movw_lo16", 12, 20, 0},
148*9880d681SAndroid Build Coastguard Worker {"fixup_t2_movt_hi16", 12, 20, 0},
149*9880d681SAndroid Build Coastguard Worker {"fixup_t2_movw_lo16", 12, 20, 0},
150*9880d681SAndroid Build Coastguard Worker {"fixup_arm_mod_imm", 20, 12, 0},
151*9880d681SAndroid Build Coastguard Worker };
152*9880d681SAndroid Build Coastguard Worker
153*9880d681SAndroid Build Coastguard Worker if (Kind < FirstTargetFixupKind)
154*9880d681SAndroid Build Coastguard Worker return MCAsmBackend::getFixupKindInfo(Kind);
155*9880d681SAndroid Build Coastguard Worker
156*9880d681SAndroid Build Coastguard Worker assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
157*9880d681SAndroid Build Coastguard Worker "Invalid kind!");
158*9880d681SAndroid Build Coastguard Worker return (IsLittleEndian ? InfosLE : InfosBE)[Kind - FirstTargetFixupKind];
159*9880d681SAndroid Build Coastguard Worker }
160*9880d681SAndroid Build Coastguard Worker
handleAssemblerFlag(MCAssemblerFlag Flag)161*9880d681SAndroid Build Coastguard Worker void ARMAsmBackend::handleAssemblerFlag(MCAssemblerFlag Flag) {
162*9880d681SAndroid Build Coastguard Worker switch (Flag) {
163*9880d681SAndroid Build Coastguard Worker default:
164*9880d681SAndroid Build Coastguard Worker break;
165*9880d681SAndroid Build Coastguard Worker case MCAF_Code16:
166*9880d681SAndroid Build Coastguard Worker setIsThumb(true);
167*9880d681SAndroid Build Coastguard Worker break;
168*9880d681SAndroid Build Coastguard Worker case MCAF_Code32:
169*9880d681SAndroid Build Coastguard Worker setIsThumb(false);
170*9880d681SAndroid Build Coastguard Worker break;
171*9880d681SAndroid Build Coastguard Worker }
172*9880d681SAndroid Build Coastguard Worker }
173*9880d681SAndroid Build Coastguard Worker
getRelaxedOpcode(unsigned Op) const174*9880d681SAndroid Build Coastguard Worker unsigned ARMAsmBackend::getRelaxedOpcode(unsigned Op) const {
175*9880d681SAndroid Build Coastguard Worker bool HasThumb2 = STI->getFeatureBits()[ARM::FeatureThumb2];
176*9880d681SAndroid Build Coastguard Worker bool HasV8MBaselineOps = STI->getFeatureBits()[ARM::HasV8MBaselineOps];
177*9880d681SAndroid Build Coastguard Worker
178*9880d681SAndroid Build Coastguard Worker switch (Op) {
179*9880d681SAndroid Build Coastguard Worker default:
180*9880d681SAndroid Build Coastguard Worker return Op;
181*9880d681SAndroid Build Coastguard Worker case ARM::tBcc:
182*9880d681SAndroid Build Coastguard Worker return HasThumb2 ? (unsigned)ARM::t2Bcc : Op;
183*9880d681SAndroid Build Coastguard Worker case ARM::tLDRpci:
184*9880d681SAndroid Build Coastguard Worker return HasThumb2 ? (unsigned)ARM::t2LDRpci : Op;
185*9880d681SAndroid Build Coastguard Worker case ARM::tADR:
186*9880d681SAndroid Build Coastguard Worker return HasThumb2 ? (unsigned)ARM::t2ADR : Op;
187*9880d681SAndroid Build Coastguard Worker case ARM::tB:
188*9880d681SAndroid Build Coastguard Worker return HasV8MBaselineOps ? (unsigned)ARM::t2B : Op;
189*9880d681SAndroid Build Coastguard Worker case ARM::tCBZ:
190*9880d681SAndroid Build Coastguard Worker return ARM::tHINT;
191*9880d681SAndroid Build Coastguard Worker case ARM::tCBNZ:
192*9880d681SAndroid Build Coastguard Worker return ARM::tHINT;
193*9880d681SAndroid Build Coastguard Worker }
194*9880d681SAndroid Build Coastguard Worker }
195*9880d681SAndroid Build Coastguard Worker
mayNeedRelaxation(const MCInst & Inst) const196*9880d681SAndroid Build Coastguard Worker bool ARMAsmBackend::mayNeedRelaxation(const MCInst &Inst) const {
197*9880d681SAndroid Build Coastguard Worker if (getRelaxedOpcode(Inst.getOpcode()) != Inst.getOpcode())
198*9880d681SAndroid Build Coastguard Worker return true;
199*9880d681SAndroid Build Coastguard Worker return false;
200*9880d681SAndroid Build Coastguard Worker }
201*9880d681SAndroid Build Coastguard Worker
reasonForFixupRelaxation(const MCFixup & Fixup,uint64_t Value) const202*9880d681SAndroid Build Coastguard Worker const char *ARMAsmBackend::reasonForFixupRelaxation(const MCFixup &Fixup,
203*9880d681SAndroid Build Coastguard Worker uint64_t Value) const {
204*9880d681SAndroid Build Coastguard Worker switch ((unsigned)Fixup.getKind()) {
205*9880d681SAndroid Build Coastguard Worker case ARM::fixup_arm_thumb_br: {
206*9880d681SAndroid Build Coastguard Worker // Relaxing tB to t2B. tB has a signed 12-bit displacement with the
207*9880d681SAndroid Build Coastguard Worker // low bit being an implied zero. There's an implied +4 offset for the
208*9880d681SAndroid Build Coastguard Worker // branch, so we adjust the other way here to determine what's
209*9880d681SAndroid Build Coastguard Worker // encodable.
210*9880d681SAndroid Build Coastguard Worker //
211*9880d681SAndroid Build Coastguard Worker // Relax if the value is too big for a (signed) i8.
212*9880d681SAndroid Build Coastguard Worker int64_t Offset = int64_t(Value) - 4;
213*9880d681SAndroid Build Coastguard Worker if (Offset > 2046 || Offset < -2048)
214*9880d681SAndroid Build Coastguard Worker return "out of range pc-relative fixup value";
215*9880d681SAndroid Build Coastguard Worker break;
216*9880d681SAndroid Build Coastguard Worker }
217*9880d681SAndroid Build Coastguard Worker case ARM::fixup_arm_thumb_bcc: {
218*9880d681SAndroid Build Coastguard Worker // Relaxing tBcc to t2Bcc. tBcc has a signed 9-bit displacement with the
219*9880d681SAndroid Build Coastguard Worker // low bit being an implied zero. There's an implied +4 offset for the
220*9880d681SAndroid Build Coastguard Worker // branch, so we adjust the other way here to determine what's
221*9880d681SAndroid Build Coastguard Worker // encodable.
222*9880d681SAndroid Build Coastguard Worker //
223*9880d681SAndroid Build Coastguard Worker // Relax if the value is too big for a (signed) i8.
224*9880d681SAndroid Build Coastguard Worker int64_t Offset = int64_t(Value) - 4;
225*9880d681SAndroid Build Coastguard Worker if (Offset > 254 || Offset < -256)
226*9880d681SAndroid Build Coastguard Worker return "out of range pc-relative fixup value";
227*9880d681SAndroid Build Coastguard Worker break;
228*9880d681SAndroid Build Coastguard Worker }
229*9880d681SAndroid Build Coastguard Worker case ARM::fixup_thumb_adr_pcrel_10:
230*9880d681SAndroid Build Coastguard Worker case ARM::fixup_arm_thumb_cp: {
231*9880d681SAndroid Build Coastguard Worker // If the immediate is negative, greater than 1020, or not a multiple
232*9880d681SAndroid Build Coastguard Worker // of four, the wide version of the instruction must be used.
233*9880d681SAndroid Build Coastguard Worker int64_t Offset = int64_t(Value) - 4;
234*9880d681SAndroid Build Coastguard Worker if (Offset & 3)
235*9880d681SAndroid Build Coastguard Worker return "misaligned pc-relative fixup value";
236*9880d681SAndroid Build Coastguard Worker else if (Offset > 1020 || Offset < 0)
237*9880d681SAndroid Build Coastguard Worker return "out of range pc-relative fixup value";
238*9880d681SAndroid Build Coastguard Worker break;
239*9880d681SAndroid Build Coastguard Worker }
240*9880d681SAndroid Build Coastguard Worker case ARM::fixup_arm_thumb_cb: {
241*9880d681SAndroid Build Coastguard Worker // If we have a Thumb CBZ or CBNZ instruction and its target is the next
242*9880d681SAndroid Build Coastguard Worker // instruction it is is actually out of range for the instruction.
243*9880d681SAndroid Build Coastguard Worker // It will be changed to a NOP.
244*9880d681SAndroid Build Coastguard Worker int64_t Offset = (Value & ~1);
245*9880d681SAndroid Build Coastguard Worker if (Offset == 2)
246*9880d681SAndroid Build Coastguard Worker return "will be converted to nop";
247*9880d681SAndroid Build Coastguard Worker break;
248*9880d681SAndroid Build Coastguard Worker }
249*9880d681SAndroid Build Coastguard Worker default:
250*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Unexpected fixup kind in reasonForFixupRelaxation()!");
251*9880d681SAndroid Build Coastguard Worker }
252*9880d681SAndroid Build Coastguard Worker return nullptr;
253*9880d681SAndroid Build Coastguard Worker }
254*9880d681SAndroid Build Coastguard Worker
fixupNeedsRelaxation(const MCFixup & Fixup,uint64_t Value,const MCRelaxableFragment * DF,const MCAsmLayout & Layout) const255*9880d681SAndroid Build Coastguard Worker bool ARMAsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
256*9880d681SAndroid Build Coastguard Worker const MCRelaxableFragment *DF,
257*9880d681SAndroid Build Coastguard Worker const MCAsmLayout &Layout) const {
258*9880d681SAndroid Build Coastguard Worker return reasonForFixupRelaxation(Fixup, Value);
259*9880d681SAndroid Build Coastguard Worker }
260*9880d681SAndroid Build Coastguard Worker
relaxInstruction(const MCInst & Inst,const MCSubtargetInfo & STI,MCInst & Res) const261*9880d681SAndroid Build Coastguard Worker void ARMAsmBackend::relaxInstruction(const MCInst &Inst,
262*9880d681SAndroid Build Coastguard Worker const MCSubtargetInfo &STI,
263*9880d681SAndroid Build Coastguard Worker MCInst &Res) const {
264*9880d681SAndroid Build Coastguard Worker unsigned RelaxedOp = getRelaxedOpcode(Inst.getOpcode());
265*9880d681SAndroid Build Coastguard Worker
266*9880d681SAndroid Build Coastguard Worker // Sanity check w/ diagnostic if we get here w/ a bogus instruction.
267*9880d681SAndroid Build Coastguard Worker if (RelaxedOp == Inst.getOpcode()) {
268*9880d681SAndroid Build Coastguard Worker SmallString<256> Tmp;
269*9880d681SAndroid Build Coastguard Worker raw_svector_ostream OS(Tmp);
270*9880d681SAndroid Build Coastguard Worker Inst.dump_pretty(OS);
271*9880d681SAndroid Build Coastguard Worker OS << "\n";
272*9880d681SAndroid Build Coastguard Worker report_fatal_error("unexpected instruction to relax: " + OS.str());
273*9880d681SAndroid Build Coastguard Worker }
274*9880d681SAndroid Build Coastguard Worker
275*9880d681SAndroid Build Coastguard Worker // If we are changing Thumb CBZ or CBNZ instruction to a NOP, aka tHINT, we
276*9880d681SAndroid Build Coastguard Worker // have to change the operands too.
277*9880d681SAndroid Build Coastguard Worker if ((Inst.getOpcode() == ARM::tCBZ || Inst.getOpcode() == ARM::tCBNZ) &&
278*9880d681SAndroid Build Coastguard Worker RelaxedOp == ARM::tHINT) {
279*9880d681SAndroid Build Coastguard Worker Res.setOpcode(RelaxedOp);
280*9880d681SAndroid Build Coastguard Worker Res.addOperand(MCOperand::createImm(0));
281*9880d681SAndroid Build Coastguard Worker Res.addOperand(MCOperand::createImm(14));
282*9880d681SAndroid Build Coastguard Worker Res.addOperand(MCOperand::createReg(0));
283*9880d681SAndroid Build Coastguard Worker return;
284*9880d681SAndroid Build Coastguard Worker }
285*9880d681SAndroid Build Coastguard Worker
286*9880d681SAndroid Build Coastguard Worker // The rest of instructions we're relaxing have the same operands.
287*9880d681SAndroid Build Coastguard Worker // We just need to update to the proper opcode.
288*9880d681SAndroid Build Coastguard Worker Res = Inst;
289*9880d681SAndroid Build Coastguard Worker Res.setOpcode(RelaxedOp);
290*9880d681SAndroid Build Coastguard Worker }
291*9880d681SAndroid Build Coastguard Worker
writeNopData(uint64_t Count,MCObjectWriter * OW) const292*9880d681SAndroid Build Coastguard Worker bool ARMAsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW) const {
293*9880d681SAndroid Build Coastguard Worker const uint16_t Thumb1_16bitNopEncoding = 0x46c0; // using MOV r8,r8
294*9880d681SAndroid Build Coastguard Worker const uint16_t Thumb2_16bitNopEncoding = 0xbf00; // NOP
295*9880d681SAndroid Build Coastguard Worker const uint32_t ARMv4_NopEncoding = 0xe1a00000; // using MOV r0,r0
296*9880d681SAndroid Build Coastguard Worker const uint32_t ARMv6T2_NopEncoding = 0xe320f000; // NOP
297*9880d681SAndroid Build Coastguard Worker if (isThumb()) {
298*9880d681SAndroid Build Coastguard Worker const uint16_t nopEncoding =
299*9880d681SAndroid Build Coastguard Worker hasNOP() ? Thumb2_16bitNopEncoding : Thumb1_16bitNopEncoding;
300*9880d681SAndroid Build Coastguard Worker uint64_t NumNops = Count / 2;
301*9880d681SAndroid Build Coastguard Worker for (uint64_t i = 0; i != NumNops; ++i)
302*9880d681SAndroid Build Coastguard Worker OW->write16(nopEncoding);
303*9880d681SAndroid Build Coastguard Worker if (Count & 1)
304*9880d681SAndroid Build Coastguard Worker OW->write8(0);
305*9880d681SAndroid Build Coastguard Worker return true;
306*9880d681SAndroid Build Coastguard Worker }
307*9880d681SAndroid Build Coastguard Worker // ARM mode
308*9880d681SAndroid Build Coastguard Worker const uint32_t nopEncoding =
309*9880d681SAndroid Build Coastguard Worker hasNOP() ? ARMv6T2_NopEncoding : ARMv4_NopEncoding;
310*9880d681SAndroid Build Coastguard Worker uint64_t NumNops = Count / 4;
311*9880d681SAndroid Build Coastguard Worker for (uint64_t i = 0; i != NumNops; ++i)
312*9880d681SAndroid Build Coastguard Worker OW->write32(nopEncoding);
313*9880d681SAndroid Build Coastguard Worker // FIXME: should this function return false when unable to write exactly
314*9880d681SAndroid Build Coastguard Worker // 'Count' bytes with NOP encodings?
315*9880d681SAndroid Build Coastguard Worker switch (Count % 4) {
316*9880d681SAndroid Build Coastguard Worker default:
317*9880d681SAndroid Build Coastguard Worker break; // No leftover bytes to write
318*9880d681SAndroid Build Coastguard Worker case 1:
319*9880d681SAndroid Build Coastguard Worker OW->write8(0);
320*9880d681SAndroid Build Coastguard Worker break;
321*9880d681SAndroid Build Coastguard Worker case 2:
322*9880d681SAndroid Build Coastguard Worker OW->write16(0);
323*9880d681SAndroid Build Coastguard Worker break;
324*9880d681SAndroid Build Coastguard Worker case 3:
325*9880d681SAndroid Build Coastguard Worker OW->write16(0);
326*9880d681SAndroid Build Coastguard Worker OW->write8(0xa0);
327*9880d681SAndroid Build Coastguard Worker break;
328*9880d681SAndroid Build Coastguard Worker }
329*9880d681SAndroid Build Coastguard Worker
330*9880d681SAndroid Build Coastguard Worker return true;
331*9880d681SAndroid Build Coastguard Worker }
332*9880d681SAndroid Build Coastguard Worker
swapHalfWords(uint32_t Value,bool IsLittleEndian)333*9880d681SAndroid Build Coastguard Worker static uint32_t swapHalfWords(uint32_t Value, bool IsLittleEndian) {
334*9880d681SAndroid Build Coastguard Worker if (IsLittleEndian) {
335*9880d681SAndroid Build Coastguard Worker // Note that the halfwords are stored high first and low second in thumb;
336*9880d681SAndroid Build Coastguard Worker // so we need to swap the fixup value here to map properly.
337*9880d681SAndroid Build Coastguard Worker uint32_t Swapped = (Value & 0xFFFF0000) >> 16;
338*9880d681SAndroid Build Coastguard Worker Swapped |= (Value & 0x0000FFFF) << 16;
339*9880d681SAndroid Build Coastguard Worker return Swapped;
340*9880d681SAndroid Build Coastguard Worker } else
341*9880d681SAndroid Build Coastguard Worker return Value;
342*9880d681SAndroid Build Coastguard Worker }
343*9880d681SAndroid Build Coastguard Worker
joinHalfWords(uint32_t FirstHalf,uint32_t SecondHalf,bool IsLittleEndian)344*9880d681SAndroid Build Coastguard Worker static uint32_t joinHalfWords(uint32_t FirstHalf, uint32_t SecondHalf,
345*9880d681SAndroid Build Coastguard Worker bool IsLittleEndian) {
346*9880d681SAndroid Build Coastguard Worker uint32_t Value;
347*9880d681SAndroid Build Coastguard Worker
348*9880d681SAndroid Build Coastguard Worker if (IsLittleEndian) {
349*9880d681SAndroid Build Coastguard Worker Value = (SecondHalf & 0xFFFF) << 16;
350*9880d681SAndroid Build Coastguard Worker Value |= (FirstHalf & 0xFFFF);
351*9880d681SAndroid Build Coastguard Worker } else {
352*9880d681SAndroid Build Coastguard Worker Value = (SecondHalf & 0xFFFF);
353*9880d681SAndroid Build Coastguard Worker Value |= (FirstHalf & 0xFFFF) << 16;
354*9880d681SAndroid Build Coastguard Worker }
355*9880d681SAndroid Build Coastguard Worker
356*9880d681SAndroid Build Coastguard Worker return Value;
357*9880d681SAndroid Build Coastguard Worker }
358*9880d681SAndroid Build Coastguard Worker
adjustFixupValue(const MCFixup & Fixup,uint64_t Value,bool IsPCRel,MCContext * Ctx,bool IsLittleEndian,bool IsResolved) const359*9880d681SAndroid Build Coastguard Worker unsigned ARMAsmBackend::adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
360*9880d681SAndroid Build Coastguard Worker bool IsPCRel, MCContext *Ctx,
361*9880d681SAndroid Build Coastguard Worker bool IsLittleEndian,
362*9880d681SAndroid Build Coastguard Worker bool IsResolved) const {
363*9880d681SAndroid Build Coastguard Worker unsigned Kind = Fixup.getKind();
364*9880d681SAndroid Build Coastguard Worker switch (Kind) {
365*9880d681SAndroid Build Coastguard Worker default:
366*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Unknown fixup kind!");
367*9880d681SAndroid Build Coastguard Worker case FK_Data_1:
368*9880d681SAndroid Build Coastguard Worker case FK_Data_2:
369*9880d681SAndroid Build Coastguard Worker case FK_Data_4:
370*9880d681SAndroid Build Coastguard Worker return Value;
371*9880d681SAndroid Build Coastguard Worker case FK_SecRel_2:
372*9880d681SAndroid Build Coastguard Worker return Value;
373*9880d681SAndroid Build Coastguard Worker case FK_SecRel_4:
374*9880d681SAndroid Build Coastguard Worker return Value;
375*9880d681SAndroid Build Coastguard Worker case ARM::fixup_arm_movt_hi16:
376*9880d681SAndroid Build Coastguard Worker if (!IsPCRel)
377*9880d681SAndroid Build Coastguard Worker Value >>= 16;
378*9880d681SAndroid Build Coastguard Worker // Fallthrough
379*9880d681SAndroid Build Coastguard Worker case ARM::fixup_arm_movw_lo16: {
380*9880d681SAndroid Build Coastguard Worker unsigned Hi4 = (Value & 0xF000) >> 12;
381*9880d681SAndroid Build Coastguard Worker unsigned Lo12 = Value & 0x0FFF;
382*9880d681SAndroid Build Coastguard Worker // inst{19-16} = Hi4;
383*9880d681SAndroid Build Coastguard Worker // inst{11-0} = Lo12;
384*9880d681SAndroid Build Coastguard Worker Value = (Hi4 << 16) | (Lo12);
385*9880d681SAndroid Build Coastguard Worker return Value;
386*9880d681SAndroid Build Coastguard Worker }
387*9880d681SAndroid Build Coastguard Worker case ARM::fixup_t2_movt_hi16:
388*9880d681SAndroid Build Coastguard Worker if (!IsPCRel)
389*9880d681SAndroid Build Coastguard Worker Value >>= 16;
390*9880d681SAndroid Build Coastguard Worker // Fallthrough
391*9880d681SAndroid Build Coastguard Worker case ARM::fixup_t2_movw_lo16: {
392*9880d681SAndroid Build Coastguard Worker unsigned Hi4 = (Value & 0xF000) >> 12;
393*9880d681SAndroid Build Coastguard Worker unsigned i = (Value & 0x800) >> 11;
394*9880d681SAndroid Build Coastguard Worker unsigned Mid3 = (Value & 0x700) >> 8;
395*9880d681SAndroid Build Coastguard Worker unsigned Lo8 = Value & 0x0FF;
396*9880d681SAndroid Build Coastguard Worker // inst{19-16} = Hi4;
397*9880d681SAndroid Build Coastguard Worker // inst{26} = i;
398*9880d681SAndroid Build Coastguard Worker // inst{14-12} = Mid3;
399*9880d681SAndroid Build Coastguard Worker // inst{7-0} = Lo8;
400*9880d681SAndroid Build Coastguard Worker Value = (Hi4 << 16) | (i << 26) | (Mid3 << 12) | (Lo8);
401*9880d681SAndroid Build Coastguard Worker return swapHalfWords(Value, IsLittleEndian);
402*9880d681SAndroid Build Coastguard Worker }
403*9880d681SAndroid Build Coastguard Worker case ARM::fixup_arm_ldst_pcrel_12:
404*9880d681SAndroid Build Coastguard Worker // ARM PC-relative values are offset by 8.
405*9880d681SAndroid Build Coastguard Worker Value -= 4;
406*9880d681SAndroid Build Coastguard Worker // FALLTHROUGH
407*9880d681SAndroid Build Coastguard Worker case ARM::fixup_t2_ldst_pcrel_12: {
408*9880d681SAndroid Build Coastguard Worker // Offset by 4, adjusted by two due to the half-word ordering of thumb.
409*9880d681SAndroid Build Coastguard Worker Value -= 4;
410*9880d681SAndroid Build Coastguard Worker bool isAdd = true;
411*9880d681SAndroid Build Coastguard Worker if ((int64_t)Value < 0) {
412*9880d681SAndroid Build Coastguard Worker Value = -Value;
413*9880d681SAndroid Build Coastguard Worker isAdd = false;
414*9880d681SAndroid Build Coastguard Worker }
415*9880d681SAndroid Build Coastguard Worker if (Ctx && Value >= 4096) {
416*9880d681SAndroid Build Coastguard Worker Ctx->reportError(Fixup.getLoc(), "out of range pc-relative fixup value");
417*9880d681SAndroid Build Coastguard Worker return 0;
418*9880d681SAndroid Build Coastguard Worker }
419*9880d681SAndroid Build Coastguard Worker Value |= isAdd << 23;
420*9880d681SAndroid Build Coastguard Worker
421*9880d681SAndroid Build Coastguard Worker // Same addressing mode as fixup_arm_pcrel_10,
422*9880d681SAndroid Build Coastguard Worker // but with 16-bit halfwords swapped.
423*9880d681SAndroid Build Coastguard Worker if (Kind == ARM::fixup_t2_ldst_pcrel_12)
424*9880d681SAndroid Build Coastguard Worker return swapHalfWords(Value, IsLittleEndian);
425*9880d681SAndroid Build Coastguard Worker
426*9880d681SAndroid Build Coastguard Worker return Value;
427*9880d681SAndroid Build Coastguard Worker }
428*9880d681SAndroid Build Coastguard Worker case ARM::fixup_arm_adr_pcrel_12: {
429*9880d681SAndroid Build Coastguard Worker // ARM PC-relative values are offset by 8.
430*9880d681SAndroid Build Coastguard Worker Value -= 8;
431*9880d681SAndroid Build Coastguard Worker unsigned opc = 4; // bits {24-21}. Default to add: 0b0100
432*9880d681SAndroid Build Coastguard Worker if ((int64_t)Value < 0) {
433*9880d681SAndroid Build Coastguard Worker Value = -Value;
434*9880d681SAndroid Build Coastguard Worker opc = 2; // 0b0010
435*9880d681SAndroid Build Coastguard Worker }
436*9880d681SAndroid Build Coastguard Worker if (Ctx && ARM_AM::getSOImmVal(Value) == -1) {
437*9880d681SAndroid Build Coastguard Worker Ctx->reportError(Fixup.getLoc(), "out of range pc-relative fixup value");
438*9880d681SAndroid Build Coastguard Worker return 0;
439*9880d681SAndroid Build Coastguard Worker }
440*9880d681SAndroid Build Coastguard Worker // Encode the immediate and shift the opcode into place.
441*9880d681SAndroid Build Coastguard Worker return ARM_AM::getSOImmVal(Value) | (opc << 21);
442*9880d681SAndroid Build Coastguard Worker }
443*9880d681SAndroid Build Coastguard Worker
444*9880d681SAndroid Build Coastguard Worker case ARM::fixup_t2_adr_pcrel_12: {
445*9880d681SAndroid Build Coastguard Worker Value -= 4;
446*9880d681SAndroid Build Coastguard Worker unsigned opc = 0;
447*9880d681SAndroid Build Coastguard Worker if ((int64_t)Value < 0) {
448*9880d681SAndroid Build Coastguard Worker Value = -Value;
449*9880d681SAndroid Build Coastguard Worker opc = 5;
450*9880d681SAndroid Build Coastguard Worker }
451*9880d681SAndroid Build Coastguard Worker
452*9880d681SAndroid Build Coastguard Worker uint32_t out = (opc << 21);
453*9880d681SAndroid Build Coastguard Worker out |= (Value & 0x800) << 15;
454*9880d681SAndroid Build Coastguard Worker out |= (Value & 0x700) << 4;
455*9880d681SAndroid Build Coastguard Worker out |= (Value & 0x0FF);
456*9880d681SAndroid Build Coastguard Worker
457*9880d681SAndroid Build Coastguard Worker return swapHalfWords(out, IsLittleEndian);
458*9880d681SAndroid Build Coastguard Worker }
459*9880d681SAndroid Build Coastguard Worker
460*9880d681SAndroid Build Coastguard Worker case ARM::fixup_arm_condbranch:
461*9880d681SAndroid Build Coastguard Worker case ARM::fixup_arm_uncondbranch:
462*9880d681SAndroid Build Coastguard Worker case ARM::fixup_arm_uncondbl:
463*9880d681SAndroid Build Coastguard Worker case ARM::fixup_arm_condbl:
464*9880d681SAndroid Build Coastguard Worker case ARM::fixup_arm_blx:
465*9880d681SAndroid Build Coastguard Worker // These values don't encode the low two bits since they're always zero.
466*9880d681SAndroid Build Coastguard Worker // Offset by 8 just as above.
467*9880d681SAndroid Build Coastguard Worker if (const MCSymbolRefExpr *SRE =
468*9880d681SAndroid Build Coastguard Worker dyn_cast<MCSymbolRefExpr>(Fixup.getValue()))
469*9880d681SAndroid Build Coastguard Worker if (SRE->getKind() == MCSymbolRefExpr::VK_TLSCALL)
470*9880d681SAndroid Build Coastguard Worker return 0;
471*9880d681SAndroid Build Coastguard Worker return 0xffffff & ((Value - 8) >> 2);
472*9880d681SAndroid Build Coastguard Worker case ARM::fixup_t2_uncondbranch: {
473*9880d681SAndroid Build Coastguard Worker Value = Value - 4;
474*9880d681SAndroid Build Coastguard Worker Value >>= 1; // Low bit is not encoded.
475*9880d681SAndroid Build Coastguard Worker
476*9880d681SAndroid Build Coastguard Worker uint32_t out = 0;
477*9880d681SAndroid Build Coastguard Worker bool I = Value & 0x800000;
478*9880d681SAndroid Build Coastguard Worker bool J1 = Value & 0x400000;
479*9880d681SAndroid Build Coastguard Worker bool J2 = Value & 0x200000;
480*9880d681SAndroid Build Coastguard Worker J1 ^= I;
481*9880d681SAndroid Build Coastguard Worker J2 ^= I;
482*9880d681SAndroid Build Coastguard Worker
483*9880d681SAndroid Build Coastguard Worker out |= I << 26; // S bit
484*9880d681SAndroid Build Coastguard Worker out |= !J1 << 13; // J1 bit
485*9880d681SAndroid Build Coastguard Worker out |= !J2 << 11; // J2 bit
486*9880d681SAndroid Build Coastguard Worker out |= (Value & 0x1FF800) << 5; // imm6 field
487*9880d681SAndroid Build Coastguard Worker out |= (Value & 0x0007FF); // imm11 field
488*9880d681SAndroid Build Coastguard Worker
489*9880d681SAndroid Build Coastguard Worker return swapHalfWords(out, IsLittleEndian);
490*9880d681SAndroid Build Coastguard Worker }
491*9880d681SAndroid Build Coastguard Worker case ARM::fixup_t2_condbranch: {
492*9880d681SAndroid Build Coastguard Worker Value = Value - 4;
493*9880d681SAndroid Build Coastguard Worker Value >>= 1; // Low bit is not encoded.
494*9880d681SAndroid Build Coastguard Worker
495*9880d681SAndroid Build Coastguard Worker uint64_t out = 0;
496*9880d681SAndroid Build Coastguard Worker out |= (Value & 0x80000) << 7; // S bit
497*9880d681SAndroid Build Coastguard Worker out |= (Value & 0x40000) >> 7; // J2 bit
498*9880d681SAndroid Build Coastguard Worker out |= (Value & 0x20000) >> 4; // J1 bit
499*9880d681SAndroid Build Coastguard Worker out |= (Value & 0x1F800) << 5; // imm6 field
500*9880d681SAndroid Build Coastguard Worker out |= (Value & 0x007FF); // imm11 field
501*9880d681SAndroid Build Coastguard Worker
502*9880d681SAndroid Build Coastguard Worker return swapHalfWords(out, IsLittleEndian);
503*9880d681SAndroid Build Coastguard Worker }
504*9880d681SAndroid Build Coastguard Worker case ARM::fixup_arm_thumb_bl: {
505*9880d681SAndroid Build Coastguard Worker // The value doesn't encode the low bit (always zero) and is offset by
506*9880d681SAndroid Build Coastguard Worker // four. The 32-bit immediate value is encoded as
507*9880d681SAndroid Build Coastguard Worker // imm32 = SignExtend(S:I1:I2:imm10:imm11:0)
508*9880d681SAndroid Build Coastguard Worker // where I1 = NOT(J1 ^ S) and I2 = NOT(J2 ^ S).
509*9880d681SAndroid Build Coastguard Worker // The value is encoded into disjoint bit positions in the destination
510*9880d681SAndroid Build Coastguard Worker // opcode. x = unchanged, I = immediate value bit, S = sign extension bit,
511*9880d681SAndroid Build Coastguard Worker // J = either J1 or J2 bit
512*9880d681SAndroid Build Coastguard Worker //
513*9880d681SAndroid Build Coastguard Worker // BL: xxxxxSIIIIIIIIII xxJxJIIIIIIIIIII
514*9880d681SAndroid Build Coastguard Worker //
515*9880d681SAndroid Build Coastguard Worker // Note that the halfwords are stored high first, low second; so we need
516*9880d681SAndroid Build Coastguard Worker // to transpose the fixup value here to map properly.
517*9880d681SAndroid Build Coastguard Worker uint32_t offset = (Value - 4) >> 1;
518*9880d681SAndroid Build Coastguard Worker uint32_t signBit = (offset & 0x800000) >> 23;
519*9880d681SAndroid Build Coastguard Worker uint32_t I1Bit = (offset & 0x400000) >> 22;
520*9880d681SAndroid Build Coastguard Worker uint32_t J1Bit = (I1Bit ^ 0x1) ^ signBit;
521*9880d681SAndroid Build Coastguard Worker uint32_t I2Bit = (offset & 0x200000) >> 21;
522*9880d681SAndroid Build Coastguard Worker uint32_t J2Bit = (I2Bit ^ 0x1) ^ signBit;
523*9880d681SAndroid Build Coastguard Worker uint32_t imm10Bits = (offset & 0x1FF800) >> 11;
524*9880d681SAndroid Build Coastguard Worker uint32_t imm11Bits = (offset & 0x000007FF);
525*9880d681SAndroid Build Coastguard Worker
526*9880d681SAndroid Build Coastguard Worker uint32_t FirstHalf = (((uint16_t)signBit << 10) | (uint16_t)imm10Bits);
527*9880d681SAndroid Build Coastguard Worker uint32_t SecondHalf = (((uint16_t)J1Bit << 13) | ((uint16_t)J2Bit << 11) |
528*9880d681SAndroid Build Coastguard Worker (uint16_t)imm11Bits);
529*9880d681SAndroid Build Coastguard Worker return joinHalfWords(FirstHalf, SecondHalf, IsLittleEndian);
530*9880d681SAndroid Build Coastguard Worker }
531*9880d681SAndroid Build Coastguard Worker case ARM::fixup_arm_thumb_blx: {
532*9880d681SAndroid Build Coastguard Worker // The value doesn't encode the low two bits (always zero) and is offset by
533*9880d681SAndroid Build Coastguard Worker // four (see fixup_arm_thumb_cp). The 32-bit immediate value is encoded as
534*9880d681SAndroid Build Coastguard Worker // imm32 = SignExtend(S:I1:I2:imm10H:imm10L:00)
535*9880d681SAndroid Build Coastguard Worker // where I1 = NOT(J1 ^ S) and I2 = NOT(J2 ^ S).
536*9880d681SAndroid Build Coastguard Worker // The value is encoded into disjoint bit positions in the destination
537*9880d681SAndroid Build Coastguard Worker // opcode. x = unchanged, I = immediate value bit, S = sign extension bit,
538*9880d681SAndroid Build Coastguard Worker // J = either J1 or J2 bit, 0 = zero.
539*9880d681SAndroid Build Coastguard Worker //
540*9880d681SAndroid Build Coastguard Worker // BLX: xxxxxSIIIIIIIIII xxJxJIIIIIIIIII0
541*9880d681SAndroid Build Coastguard Worker //
542*9880d681SAndroid Build Coastguard Worker // Note that the halfwords are stored high first, low second; so we need
543*9880d681SAndroid Build Coastguard Worker // to transpose the fixup value here to map properly.
544*9880d681SAndroid Build Coastguard Worker if (Ctx && Value % 4 != 0) {
545*9880d681SAndroid Build Coastguard Worker Ctx->reportError(Fixup.getLoc(), "misaligned ARM call destination");
546*9880d681SAndroid Build Coastguard Worker return 0;
547*9880d681SAndroid Build Coastguard Worker }
548*9880d681SAndroid Build Coastguard Worker
549*9880d681SAndroid Build Coastguard Worker uint32_t offset = (Value - 4) >> 2;
550*9880d681SAndroid Build Coastguard Worker if (const MCSymbolRefExpr *SRE =
551*9880d681SAndroid Build Coastguard Worker dyn_cast<MCSymbolRefExpr>(Fixup.getValue()))
552*9880d681SAndroid Build Coastguard Worker if (SRE->getKind() == MCSymbolRefExpr::VK_TLSCALL)
553*9880d681SAndroid Build Coastguard Worker offset = 0;
554*9880d681SAndroid Build Coastguard Worker uint32_t signBit = (offset & 0x400000) >> 22;
555*9880d681SAndroid Build Coastguard Worker uint32_t I1Bit = (offset & 0x200000) >> 21;
556*9880d681SAndroid Build Coastguard Worker uint32_t J1Bit = (I1Bit ^ 0x1) ^ signBit;
557*9880d681SAndroid Build Coastguard Worker uint32_t I2Bit = (offset & 0x100000) >> 20;
558*9880d681SAndroid Build Coastguard Worker uint32_t J2Bit = (I2Bit ^ 0x1) ^ signBit;
559*9880d681SAndroid Build Coastguard Worker uint32_t imm10HBits = (offset & 0xFFC00) >> 10;
560*9880d681SAndroid Build Coastguard Worker uint32_t imm10LBits = (offset & 0x3FF);
561*9880d681SAndroid Build Coastguard Worker
562*9880d681SAndroid Build Coastguard Worker uint32_t FirstHalf = (((uint16_t)signBit << 10) | (uint16_t)imm10HBits);
563*9880d681SAndroid Build Coastguard Worker uint32_t SecondHalf = (((uint16_t)J1Bit << 13) | ((uint16_t)J2Bit << 11) |
564*9880d681SAndroid Build Coastguard Worker ((uint16_t)imm10LBits) << 1);
565*9880d681SAndroid Build Coastguard Worker return joinHalfWords(FirstHalf, SecondHalf, IsLittleEndian);
566*9880d681SAndroid Build Coastguard Worker }
567*9880d681SAndroid Build Coastguard Worker case ARM::fixup_thumb_adr_pcrel_10:
568*9880d681SAndroid Build Coastguard Worker case ARM::fixup_arm_thumb_cp:
569*9880d681SAndroid Build Coastguard Worker // On CPUs supporting Thumb2, this will be relaxed to an ldr.w, otherwise we
570*9880d681SAndroid Build Coastguard Worker // could have an error on our hands.
571*9880d681SAndroid Build Coastguard Worker if (Ctx && !STI->getFeatureBits()[ARM::FeatureThumb2] && IsResolved) {
572*9880d681SAndroid Build Coastguard Worker const char *FixupDiagnostic = reasonForFixupRelaxation(Fixup, Value);
573*9880d681SAndroid Build Coastguard Worker if (FixupDiagnostic) {
574*9880d681SAndroid Build Coastguard Worker Ctx->reportError(Fixup.getLoc(), FixupDiagnostic);
575*9880d681SAndroid Build Coastguard Worker return 0;
576*9880d681SAndroid Build Coastguard Worker }
577*9880d681SAndroid Build Coastguard Worker }
578*9880d681SAndroid Build Coastguard Worker // Offset by 4, and don't encode the low two bits.
579*9880d681SAndroid Build Coastguard Worker return ((Value - 4) >> 2) & 0xff;
580*9880d681SAndroid Build Coastguard Worker case ARM::fixup_arm_thumb_cb: {
581*9880d681SAndroid Build Coastguard Worker // Offset by 4 and don't encode the lower bit, which is always 0.
582*9880d681SAndroid Build Coastguard Worker // FIXME: diagnose if no Thumb2
583*9880d681SAndroid Build Coastguard Worker uint32_t Binary = (Value - 4) >> 1;
584*9880d681SAndroid Build Coastguard Worker return ((Binary & 0x20) << 4) | ((Binary & 0x1f) << 3);
585*9880d681SAndroid Build Coastguard Worker }
586*9880d681SAndroid Build Coastguard Worker case ARM::fixup_arm_thumb_br:
587*9880d681SAndroid Build Coastguard Worker // Offset by 4 and don't encode the lower bit, which is always 0.
588*9880d681SAndroid Build Coastguard Worker if (Ctx && !STI->getFeatureBits()[ARM::FeatureThumb2] &&
589*9880d681SAndroid Build Coastguard Worker !STI->getFeatureBits()[ARM::HasV8MBaselineOps]) {
590*9880d681SAndroid Build Coastguard Worker const char *FixupDiagnostic = reasonForFixupRelaxation(Fixup, Value);
591*9880d681SAndroid Build Coastguard Worker if (FixupDiagnostic) {
592*9880d681SAndroid Build Coastguard Worker Ctx->reportError(Fixup.getLoc(), FixupDiagnostic);
593*9880d681SAndroid Build Coastguard Worker return 0;
594*9880d681SAndroid Build Coastguard Worker }
595*9880d681SAndroid Build Coastguard Worker }
596*9880d681SAndroid Build Coastguard Worker return ((Value - 4) >> 1) & 0x7ff;
597*9880d681SAndroid Build Coastguard Worker case ARM::fixup_arm_thumb_bcc:
598*9880d681SAndroid Build Coastguard Worker // Offset by 4 and don't encode the lower bit, which is always 0.
599*9880d681SAndroid Build Coastguard Worker if (Ctx && !STI->getFeatureBits()[ARM::FeatureThumb2]) {
600*9880d681SAndroid Build Coastguard Worker const char *FixupDiagnostic = reasonForFixupRelaxation(Fixup, Value);
601*9880d681SAndroid Build Coastguard Worker if (FixupDiagnostic) {
602*9880d681SAndroid Build Coastguard Worker Ctx->reportError(Fixup.getLoc(), FixupDiagnostic);
603*9880d681SAndroid Build Coastguard Worker return 0;
604*9880d681SAndroid Build Coastguard Worker }
605*9880d681SAndroid Build Coastguard Worker }
606*9880d681SAndroid Build Coastguard Worker return ((Value - 4) >> 1) & 0xff;
607*9880d681SAndroid Build Coastguard Worker case ARM::fixup_arm_pcrel_10_unscaled: {
608*9880d681SAndroid Build Coastguard Worker Value = Value - 8; // ARM fixups offset by an additional word and don't
609*9880d681SAndroid Build Coastguard Worker // need to adjust for the half-word ordering.
610*9880d681SAndroid Build Coastguard Worker bool isAdd = true;
611*9880d681SAndroid Build Coastguard Worker if ((int64_t)Value < 0) {
612*9880d681SAndroid Build Coastguard Worker Value = -Value;
613*9880d681SAndroid Build Coastguard Worker isAdd = false;
614*9880d681SAndroid Build Coastguard Worker }
615*9880d681SAndroid Build Coastguard Worker // The value has the low 4 bits encoded in [3:0] and the high 4 in [11:8].
616*9880d681SAndroid Build Coastguard Worker if (Ctx && Value >= 256) {
617*9880d681SAndroid Build Coastguard Worker Ctx->reportError(Fixup.getLoc(), "out of range pc-relative fixup value");
618*9880d681SAndroid Build Coastguard Worker return 0;
619*9880d681SAndroid Build Coastguard Worker }
620*9880d681SAndroid Build Coastguard Worker Value = (Value & 0xf) | ((Value & 0xf0) << 4);
621*9880d681SAndroid Build Coastguard Worker return Value | (isAdd << 23);
622*9880d681SAndroid Build Coastguard Worker }
623*9880d681SAndroid Build Coastguard Worker case ARM::fixup_arm_pcrel_10:
624*9880d681SAndroid Build Coastguard Worker Value = Value - 4; // ARM fixups offset by an additional word and don't
625*9880d681SAndroid Build Coastguard Worker // need to adjust for the half-word ordering.
626*9880d681SAndroid Build Coastguard Worker // Fall through.
627*9880d681SAndroid Build Coastguard Worker case ARM::fixup_t2_pcrel_10: {
628*9880d681SAndroid Build Coastguard Worker // Offset by 4, adjusted by two due to the half-word ordering of thumb.
629*9880d681SAndroid Build Coastguard Worker Value = Value - 4;
630*9880d681SAndroid Build Coastguard Worker bool isAdd = true;
631*9880d681SAndroid Build Coastguard Worker if ((int64_t)Value < 0) {
632*9880d681SAndroid Build Coastguard Worker Value = -Value;
633*9880d681SAndroid Build Coastguard Worker isAdd = false;
634*9880d681SAndroid Build Coastguard Worker }
635*9880d681SAndroid Build Coastguard Worker // These values don't encode the low two bits since they're always zero.
636*9880d681SAndroid Build Coastguard Worker Value >>= 2;
637*9880d681SAndroid Build Coastguard Worker if (Ctx && Value >= 256) {
638*9880d681SAndroid Build Coastguard Worker Ctx->reportError(Fixup.getLoc(), "out of range pc-relative fixup value");
639*9880d681SAndroid Build Coastguard Worker return 0;
640*9880d681SAndroid Build Coastguard Worker }
641*9880d681SAndroid Build Coastguard Worker Value |= isAdd << 23;
642*9880d681SAndroid Build Coastguard Worker
643*9880d681SAndroid Build Coastguard Worker // Same addressing mode as fixup_arm_pcrel_10, but with 16-bit halfwords
644*9880d681SAndroid Build Coastguard Worker // swapped.
645*9880d681SAndroid Build Coastguard Worker if (Kind == ARM::fixup_t2_pcrel_10)
646*9880d681SAndroid Build Coastguard Worker return swapHalfWords(Value, IsLittleEndian);
647*9880d681SAndroid Build Coastguard Worker
648*9880d681SAndroid Build Coastguard Worker return Value;
649*9880d681SAndroid Build Coastguard Worker }
650*9880d681SAndroid Build Coastguard Worker case ARM::fixup_arm_pcrel_9:
651*9880d681SAndroid Build Coastguard Worker Value = Value - 4; // ARM fixups offset by an additional word and don't
652*9880d681SAndroid Build Coastguard Worker // need to adjust for the half-word ordering.
653*9880d681SAndroid Build Coastguard Worker // Fall through.
654*9880d681SAndroid Build Coastguard Worker case ARM::fixup_t2_pcrel_9: {
655*9880d681SAndroid Build Coastguard Worker // Offset by 4, adjusted by two due to the half-word ordering of thumb.
656*9880d681SAndroid Build Coastguard Worker Value = Value - 4;
657*9880d681SAndroid Build Coastguard Worker bool isAdd = true;
658*9880d681SAndroid Build Coastguard Worker if ((int64_t)Value < 0) {
659*9880d681SAndroid Build Coastguard Worker Value = -Value;
660*9880d681SAndroid Build Coastguard Worker isAdd = false;
661*9880d681SAndroid Build Coastguard Worker }
662*9880d681SAndroid Build Coastguard Worker // These values don't encode the low bit since it's always zero.
663*9880d681SAndroid Build Coastguard Worker if (Ctx && (Value & 1)) {
664*9880d681SAndroid Build Coastguard Worker Ctx->reportError(Fixup.getLoc(), "invalid value for this fixup");
665*9880d681SAndroid Build Coastguard Worker return 0;
666*9880d681SAndroid Build Coastguard Worker }
667*9880d681SAndroid Build Coastguard Worker Value >>= 1;
668*9880d681SAndroid Build Coastguard Worker if (Ctx && Value >= 256) {
669*9880d681SAndroid Build Coastguard Worker Ctx->reportError(Fixup.getLoc(), "out of range pc-relative fixup value");
670*9880d681SAndroid Build Coastguard Worker return 0;
671*9880d681SAndroid Build Coastguard Worker }
672*9880d681SAndroid Build Coastguard Worker Value |= isAdd << 23;
673*9880d681SAndroid Build Coastguard Worker
674*9880d681SAndroid Build Coastguard Worker // Same addressing mode as fixup_arm_pcrel_9, but with 16-bit halfwords
675*9880d681SAndroid Build Coastguard Worker // swapped.
676*9880d681SAndroid Build Coastguard Worker if (Kind == ARM::fixup_t2_pcrel_9)
677*9880d681SAndroid Build Coastguard Worker return swapHalfWords(Value, IsLittleEndian);
678*9880d681SAndroid Build Coastguard Worker
679*9880d681SAndroid Build Coastguard Worker return Value;
680*9880d681SAndroid Build Coastguard Worker }
681*9880d681SAndroid Build Coastguard Worker case ARM::fixup_arm_mod_imm:
682*9880d681SAndroid Build Coastguard Worker Value = ARM_AM::getSOImmVal(Value);
683*9880d681SAndroid Build Coastguard Worker if (Ctx && Value >> 12) {
684*9880d681SAndroid Build Coastguard Worker Ctx->reportError(Fixup.getLoc(), "out of range immediate fixup value");
685*9880d681SAndroid Build Coastguard Worker return 0;
686*9880d681SAndroid Build Coastguard Worker }
687*9880d681SAndroid Build Coastguard Worker return Value;
688*9880d681SAndroid Build Coastguard Worker }
689*9880d681SAndroid Build Coastguard Worker }
690*9880d681SAndroid Build Coastguard Worker
processFixupValue(const MCAssembler & Asm,const MCAsmLayout & Layout,const MCFixup & Fixup,const MCFragment * DF,const MCValue & Target,uint64_t & Value,bool & IsResolved)691*9880d681SAndroid Build Coastguard Worker void ARMAsmBackend::processFixupValue(const MCAssembler &Asm,
692*9880d681SAndroid Build Coastguard Worker const MCAsmLayout &Layout,
693*9880d681SAndroid Build Coastguard Worker const MCFixup &Fixup,
694*9880d681SAndroid Build Coastguard Worker const MCFragment *DF,
695*9880d681SAndroid Build Coastguard Worker const MCValue &Target, uint64_t &Value,
696*9880d681SAndroid Build Coastguard Worker bool &IsResolved) {
697*9880d681SAndroid Build Coastguard Worker const MCSymbolRefExpr *A = Target.getSymA();
698*9880d681SAndroid Build Coastguard Worker const MCSymbol *Sym = A ? &A->getSymbol() : nullptr;
699*9880d681SAndroid Build Coastguard Worker // Some fixups to thumb function symbols need the low bit (thumb bit)
700*9880d681SAndroid Build Coastguard Worker // twiddled.
701*9880d681SAndroid Build Coastguard Worker if ((unsigned)Fixup.getKind() != ARM::fixup_arm_ldst_pcrel_12 &&
702*9880d681SAndroid Build Coastguard Worker (unsigned)Fixup.getKind() != ARM::fixup_t2_ldst_pcrel_12 &&
703*9880d681SAndroid Build Coastguard Worker (unsigned)Fixup.getKind() != ARM::fixup_arm_adr_pcrel_12 &&
704*9880d681SAndroid Build Coastguard Worker (unsigned)Fixup.getKind() != ARM::fixup_thumb_adr_pcrel_10 &&
705*9880d681SAndroid Build Coastguard Worker (unsigned)Fixup.getKind() != ARM::fixup_t2_adr_pcrel_12 &&
706*9880d681SAndroid Build Coastguard Worker (unsigned)Fixup.getKind() != ARM::fixup_arm_thumb_cp) {
707*9880d681SAndroid Build Coastguard Worker if (Sym) {
708*9880d681SAndroid Build Coastguard Worker if (Asm.isThumbFunc(Sym))
709*9880d681SAndroid Build Coastguard Worker Value |= 1;
710*9880d681SAndroid Build Coastguard Worker }
711*9880d681SAndroid Build Coastguard Worker }
712*9880d681SAndroid Build Coastguard Worker if (IsResolved && (unsigned)Fixup.getKind() == ARM::fixup_arm_thumb_bl) {
713*9880d681SAndroid Build Coastguard Worker assert(Sym && "How did we resolve this?");
714*9880d681SAndroid Build Coastguard Worker
715*9880d681SAndroid Build Coastguard Worker // If the symbol is external the linker will handle it.
716*9880d681SAndroid Build Coastguard Worker // FIXME: Should we handle it as an optimization?
717*9880d681SAndroid Build Coastguard Worker
718*9880d681SAndroid Build Coastguard Worker // If the symbol is out of range, produce a relocation and hope the
719*9880d681SAndroid Build Coastguard Worker // linker can handle it. GNU AS produces an error in this case.
720*9880d681SAndroid Build Coastguard Worker if (Sym->isExternal() || Value >= 0x400004)
721*9880d681SAndroid Build Coastguard Worker IsResolved = false;
722*9880d681SAndroid Build Coastguard Worker }
723*9880d681SAndroid Build Coastguard Worker // We must always generate a relocation for BL/BLX instructions if we have
724*9880d681SAndroid Build Coastguard Worker // a symbol to reference, as the linker relies on knowing the destination
725*9880d681SAndroid Build Coastguard Worker // symbol's thumb-ness to get interworking right.
726*9880d681SAndroid Build Coastguard Worker if (A && ((unsigned)Fixup.getKind() == ARM::fixup_arm_thumb_blx ||
727*9880d681SAndroid Build Coastguard Worker (unsigned)Fixup.getKind() == ARM::fixup_arm_blx ||
728*9880d681SAndroid Build Coastguard Worker (unsigned)Fixup.getKind() == ARM::fixup_arm_uncondbl ||
729*9880d681SAndroid Build Coastguard Worker (unsigned)Fixup.getKind() == ARM::fixup_arm_condbl))
730*9880d681SAndroid Build Coastguard Worker IsResolved = false;
731*9880d681SAndroid Build Coastguard Worker
732*9880d681SAndroid Build Coastguard Worker // Try to get the encoded value for the fixup as-if we're mapping it into
733*9880d681SAndroid Build Coastguard Worker // the instruction. This allows adjustFixupValue() to issue a diagnostic
734*9880d681SAndroid Build Coastguard Worker // if the value aren't invalid.
735*9880d681SAndroid Build Coastguard Worker (void)adjustFixupValue(Fixup, Value, false, &Asm.getContext(),
736*9880d681SAndroid Build Coastguard Worker IsLittleEndian, IsResolved);
737*9880d681SAndroid Build Coastguard Worker }
738*9880d681SAndroid Build Coastguard Worker
739*9880d681SAndroid Build Coastguard Worker /// getFixupKindNumBytes - The number of bytes the fixup may change.
getFixupKindNumBytes(unsigned Kind)740*9880d681SAndroid Build Coastguard Worker static unsigned getFixupKindNumBytes(unsigned Kind) {
741*9880d681SAndroid Build Coastguard Worker switch (Kind) {
742*9880d681SAndroid Build Coastguard Worker default:
743*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Unknown fixup kind!");
744*9880d681SAndroid Build Coastguard Worker
745*9880d681SAndroid Build Coastguard Worker case FK_Data_1:
746*9880d681SAndroid Build Coastguard Worker case ARM::fixup_arm_thumb_bcc:
747*9880d681SAndroid Build Coastguard Worker case ARM::fixup_arm_thumb_cp:
748*9880d681SAndroid Build Coastguard Worker case ARM::fixup_thumb_adr_pcrel_10:
749*9880d681SAndroid Build Coastguard Worker return 1;
750*9880d681SAndroid Build Coastguard Worker
751*9880d681SAndroid Build Coastguard Worker case FK_Data_2:
752*9880d681SAndroid Build Coastguard Worker case ARM::fixup_arm_thumb_br:
753*9880d681SAndroid Build Coastguard Worker case ARM::fixup_arm_thumb_cb:
754*9880d681SAndroid Build Coastguard Worker case ARM::fixup_arm_mod_imm:
755*9880d681SAndroid Build Coastguard Worker return 2;
756*9880d681SAndroid Build Coastguard Worker
757*9880d681SAndroid Build Coastguard Worker case ARM::fixup_arm_pcrel_10_unscaled:
758*9880d681SAndroid Build Coastguard Worker case ARM::fixup_arm_ldst_pcrel_12:
759*9880d681SAndroid Build Coastguard Worker case ARM::fixup_arm_pcrel_10:
760*9880d681SAndroid Build Coastguard Worker case ARM::fixup_arm_pcrel_9:
761*9880d681SAndroid Build Coastguard Worker case ARM::fixup_arm_adr_pcrel_12:
762*9880d681SAndroid Build Coastguard Worker case ARM::fixup_arm_uncondbl:
763*9880d681SAndroid Build Coastguard Worker case ARM::fixup_arm_condbl:
764*9880d681SAndroid Build Coastguard Worker case ARM::fixup_arm_blx:
765*9880d681SAndroid Build Coastguard Worker case ARM::fixup_arm_condbranch:
766*9880d681SAndroid Build Coastguard Worker case ARM::fixup_arm_uncondbranch:
767*9880d681SAndroid Build Coastguard Worker return 3;
768*9880d681SAndroid Build Coastguard Worker
769*9880d681SAndroid Build Coastguard Worker case FK_Data_4:
770*9880d681SAndroid Build Coastguard Worker case ARM::fixup_t2_ldst_pcrel_12:
771*9880d681SAndroid Build Coastguard Worker case ARM::fixup_t2_condbranch:
772*9880d681SAndroid Build Coastguard Worker case ARM::fixup_t2_uncondbranch:
773*9880d681SAndroid Build Coastguard Worker case ARM::fixup_t2_pcrel_10:
774*9880d681SAndroid Build Coastguard Worker case ARM::fixup_t2_pcrel_9:
775*9880d681SAndroid Build Coastguard Worker case ARM::fixup_t2_adr_pcrel_12:
776*9880d681SAndroid Build Coastguard Worker case ARM::fixup_arm_thumb_bl:
777*9880d681SAndroid Build Coastguard Worker case ARM::fixup_arm_thumb_blx:
778*9880d681SAndroid Build Coastguard Worker case ARM::fixup_arm_movt_hi16:
779*9880d681SAndroid Build Coastguard Worker case ARM::fixup_arm_movw_lo16:
780*9880d681SAndroid Build Coastguard Worker case ARM::fixup_t2_movt_hi16:
781*9880d681SAndroid Build Coastguard Worker case ARM::fixup_t2_movw_lo16:
782*9880d681SAndroid Build Coastguard Worker return 4;
783*9880d681SAndroid Build Coastguard Worker
784*9880d681SAndroid Build Coastguard Worker case FK_SecRel_2:
785*9880d681SAndroid Build Coastguard Worker return 2;
786*9880d681SAndroid Build Coastguard Worker case FK_SecRel_4:
787*9880d681SAndroid Build Coastguard Worker return 4;
788*9880d681SAndroid Build Coastguard Worker }
789*9880d681SAndroid Build Coastguard Worker }
790*9880d681SAndroid Build Coastguard Worker
791*9880d681SAndroid Build Coastguard Worker /// getFixupKindContainerSizeBytes - The number of bytes of the
792*9880d681SAndroid Build Coastguard Worker /// container involved in big endian.
getFixupKindContainerSizeBytes(unsigned Kind)793*9880d681SAndroid Build Coastguard Worker static unsigned getFixupKindContainerSizeBytes(unsigned Kind) {
794*9880d681SAndroid Build Coastguard Worker switch (Kind) {
795*9880d681SAndroid Build Coastguard Worker default:
796*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Unknown fixup kind!");
797*9880d681SAndroid Build Coastguard Worker
798*9880d681SAndroid Build Coastguard Worker case FK_Data_1:
799*9880d681SAndroid Build Coastguard Worker return 1;
800*9880d681SAndroid Build Coastguard Worker case FK_Data_2:
801*9880d681SAndroid Build Coastguard Worker return 2;
802*9880d681SAndroid Build Coastguard Worker case FK_Data_4:
803*9880d681SAndroid Build Coastguard Worker return 4;
804*9880d681SAndroid Build Coastguard Worker
805*9880d681SAndroid Build Coastguard Worker case ARM::fixup_arm_thumb_bcc:
806*9880d681SAndroid Build Coastguard Worker case ARM::fixup_arm_thumb_cp:
807*9880d681SAndroid Build Coastguard Worker case ARM::fixup_thumb_adr_pcrel_10:
808*9880d681SAndroid Build Coastguard Worker case ARM::fixup_arm_thumb_br:
809*9880d681SAndroid Build Coastguard Worker case ARM::fixup_arm_thumb_cb:
810*9880d681SAndroid Build Coastguard Worker // Instruction size is 2 bytes.
811*9880d681SAndroid Build Coastguard Worker return 2;
812*9880d681SAndroid Build Coastguard Worker
813*9880d681SAndroid Build Coastguard Worker case ARM::fixup_arm_pcrel_10_unscaled:
814*9880d681SAndroid Build Coastguard Worker case ARM::fixup_arm_ldst_pcrel_12:
815*9880d681SAndroid Build Coastguard Worker case ARM::fixup_arm_pcrel_10:
816*9880d681SAndroid Build Coastguard Worker case ARM::fixup_arm_adr_pcrel_12:
817*9880d681SAndroid Build Coastguard Worker case ARM::fixup_arm_uncondbl:
818*9880d681SAndroid Build Coastguard Worker case ARM::fixup_arm_condbl:
819*9880d681SAndroid Build Coastguard Worker case ARM::fixup_arm_blx:
820*9880d681SAndroid Build Coastguard Worker case ARM::fixup_arm_condbranch:
821*9880d681SAndroid Build Coastguard Worker case ARM::fixup_arm_uncondbranch:
822*9880d681SAndroid Build Coastguard Worker case ARM::fixup_t2_ldst_pcrel_12:
823*9880d681SAndroid Build Coastguard Worker case ARM::fixup_t2_condbranch:
824*9880d681SAndroid Build Coastguard Worker case ARM::fixup_t2_uncondbranch:
825*9880d681SAndroid Build Coastguard Worker case ARM::fixup_t2_pcrel_10:
826*9880d681SAndroid Build Coastguard Worker case ARM::fixup_t2_adr_pcrel_12:
827*9880d681SAndroid Build Coastguard Worker case ARM::fixup_arm_thumb_bl:
828*9880d681SAndroid Build Coastguard Worker case ARM::fixup_arm_thumb_blx:
829*9880d681SAndroid Build Coastguard Worker case ARM::fixup_arm_movt_hi16:
830*9880d681SAndroid Build Coastguard Worker case ARM::fixup_arm_movw_lo16:
831*9880d681SAndroid Build Coastguard Worker case ARM::fixup_t2_movt_hi16:
832*9880d681SAndroid Build Coastguard Worker case ARM::fixup_t2_movw_lo16:
833*9880d681SAndroid Build Coastguard Worker case ARM::fixup_arm_mod_imm:
834*9880d681SAndroid Build Coastguard Worker // Instruction size is 4 bytes.
835*9880d681SAndroid Build Coastguard Worker return 4;
836*9880d681SAndroid Build Coastguard Worker }
837*9880d681SAndroid Build Coastguard Worker }
838*9880d681SAndroid Build Coastguard Worker
applyFixup(const MCFixup & Fixup,char * Data,unsigned DataSize,uint64_t Value,bool IsPCRel) const839*9880d681SAndroid Build Coastguard Worker void ARMAsmBackend::applyFixup(const MCFixup &Fixup, char *Data,
840*9880d681SAndroid Build Coastguard Worker unsigned DataSize, uint64_t Value,
841*9880d681SAndroid Build Coastguard Worker bool IsPCRel) const {
842*9880d681SAndroid Build Coastguard Worker unsigned NumBytes = getFixupKindNumBytes(Fixup.getKind());
843*9880d681SAndroid Build Coastguard Worker Value =
844*9880d681SAndroid Build Coastguard Worker adjustFixupValue(Fixup, Value, IsPCRel, nullptr, IsLittleEndian, true);
845*9880d681SAndroid Build Coastguard Worker if (!Value)
846*9880d681SAndroid Build Coastguard Worker return; // Doesn't change encoding.
847*9880d681SAndroid Build Coastguard Worker
848*9880d681SAndroid Build Coastguard Worker unsigned Offset = Fixup.getOffset();
849*9880d681SAndroid Build Coastguard Worker assert(Offset + NumBytes <= DataSize && "Invalid fixup offset!");
850*9880d681SAndroid Build Coastguard Worker
851*9880d681SAndroid Build Coastguard Worker // Used to point to big endian bytes.
852*9880d681SAndroid Build Coastguard Worker unsigned FullSizeBytes;
853*9880d681SAndroid Build Coastguard Worker if (!IsLittleEndian) {
854*9880d681SAndroid Build Coastguard Worker FullSizeBytes = getFixupKindContainerSizeBytes(Fixup.getKind());
855*9880d681SAndroid Build Coastguard Worker assert((Offset + FullSizeBytes) <= DataSize && "Invalid fixup size!");
856*9880d681SAndroid Build Coastguard Worker assert(NumBytes <= FullSizeBytes && "Invalid fixup size!");
857*9880d681SAndroid Build Coastguard Worker }
858*9880d681SAndroid Build Coastguard Worker
859*9880d681SAndroid Build Coastguard Worker // For each byte of the fragment that the fixup touches, mask in the bits from
860*9880d681SAndroid Build Coastguard Worker // the fixup value. The Value has been "split up" into the appropriate
861*9880d681SAndroid Build Coastguard Worker // bitfields above.
862*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0; i != NumBytes; ++i) {
863*9880d681SAndroid Build Coastguard Worker unsigned Idx = IsLittleEndian ? i : (FullSizeBytes - 1 - i);
864*9880d681SAndroid Build Coastguard Worker Data[Offset + Idx] |= uint8_t((Value >> (i * 8)) & 0xff);
865*9880d681SAndroid Build Coastguard Worker }
866*9880d681SAndroid Build Coastguard Worker }
867*9880d681SAndroid Build Coastguard Worker
868*9880d681SAndroid Build Coastguard Worker namespace CU {
869*9880d681SAndroid Build Coastguard Worker
870*9880d681SAndroid Build Coastguard Worker /// \brief Compact unwind encoding values.
871*9880d681SAndroid Build Coastguard Worker enum CompactUnwindEncodings {
872*9880d681SAndroid Build Coastguard Worker UNWIND_ARM_MODE_MASK = 0x0F000000,
873*9880d681SAndroid Build Coastguard Worker UNWIND_ARM_MODE_FRAME = 0x01000000,
874*9880d681SAndroid Build Coastguard Worker UNWIND_ARM_MODE_FRAME_D = 0x02000000,
875*9880d681SAndroid Build Coastguard Worker UNWIND_ARM_MODE_DWARF = 0x04000000,
876*9880d681SAndroid Build Coastguard Worker
877*9880d681SAndroid Build Coastguard Worker UNWIND_ARM_FRAME_STACK_ADJUST_MASK = 0x00C00000,
878*9880d681SAndroid Build Coastguard Worker
879*9880d681SAndroid Build Coastguard Worker UNWIND_ARM_FRAME_FIRST_PUSH_R4 = 0x00000001,
880*9880d681SAndroid Build Coastguard Worker UNWIND_ARM_FRAME_FIRST_PUSH_R5 = 0x00000002,
881*9880d681SAndroid Build Coastguard Worker UNWIND_ARM_FRAME_FIRST_PUSH_R6 = 0x00000004,
882*9880d681SAndroid Build Coastguard Worker
883*9880d681SAndroid Build Coastguard Worker UNWIND_ARM_FRAME_SECOND_PUSH_R8 = 0x00000008,
884*9880d681SAndroid Build Coastguard Worker UNWIND_ARM_FRAME_SECOND_PUSH_R9 = 0x00000010,
885*9880d681SAndroid Build Coastguard Worker UNWIND_ARM_FRAME_SECOND_PUSH_R10 = 0x00000020,
886*9880d681SAndroid Build Coastguard Worker UNWIND_ARM_FRAME_SECOND_PUSH_R11 = 0x00000040,
887*9880d681SAndroid Build Coastguard Worker UNWIND_ARM_FRAME_SECOND_PUSH_R12 = 0x00000080,
888*9880d681SAndroid Build Coastguard Worker
889*9880d681SAndroid Build Coastguard Worker UNWIND_ARM_FRAME_D_REG_COUNT_MASK = 0x00000F00,
890*9880d681SAndroid Build Coastguard Worker
891*9880d681SAndroid Build Coastguard Worker UNWIND_ARM_DWARF_SECTION_OFFSET = 0x00FFFFFF
892*9880d681SAndroid Build Coastguard Worker };
893*9880d681SAndroid Build Coastguard Worker
894*9880d681SAndroid Build Coastguard Worker } // end CU namespace
895*9880d681SAndroid Build Coastguard Worker
896*9880d681SAndroid Build Coastguard Worker /// Generate compact unwind encoding for the function based on the CFI
897*9880d681SAndroid Build Coastguard Worker /// instructions. If the CFI instructions describe a frame that cannot be
898*9880d681SAndroid Build Coastguard Worker /// encoded in compact unwind, the method returns UNWIND_ARM_MODE_DWARF which
899*9880d681SAndroid Build Coastguard Worker /// tells the runtime to fallback and unwind using dwarf.
generateCompactUnwindEncoding(ArrayRef<MCCFIInstruction> Instrs) const900*9880d681SAndroid Build Coastguard Worker uint32_t ARMAsmBackendDarwin::generateCompactUnwindEncoding(
901*9880d681SAndroid Build Coastguard Worker ArrayRef<MCCFIInstruction> Instrs) const {
902*9880d681SAndroid Build Coastguard Worker DEBUG_WITH_TYPE("compact-unwind", llvm::dbgs() << "generateCU()\n");
903*9880d681SAndroid Build Coastguard Worker // Only armv7k uses CFI based unwinding.
904*9880d681SAndroid Build Coastguard Worker if (Subtype != MachO::CPU_SUBTYPE_ARM_V7K)
905*9880d681SAndroid Build Coastguard Worker return 0;
906*9880d681SAndroid Build Coastguard Worker // No .cfi directives means no frame.
907*9880d681SAndroid Build Coastguard Worker if (Instrs.empty())
908*9880d681SAndroid Build Coastguard Worker return 0;
909*9880d681SAndroid Build Coastguard Worker // Start off assuming CFA is at SP+0.
910*9880d681SAndroid Build Coastguard Worker int CFARegister = ARM::SP;
911*9880d681SAndroid Build Coastguard Worker int CFARegisterOffset = 0;
912*9880d681SAndroid Build Coastguard Worker // Mark savable registers as initially unsaved
913*9880d681SAndroid Build Coastguard Worker DenseMap<unsigned, int> RegOffsets;
914*9880d681SAndroid Build Coastguard Worker int FloatRegCount = 0;
915*9880d681SAndroid Build Coastguard Worker // Process each .cfi directive and build up compact unwind info.
916*9880d681SAndroid Build Coastguard Worker for (size_t i = 0, e = Instrs.size(); i != e; ++i) {
917*9880d681SAndroid Build Coastguard Worker int Reg;
918*9880d681SAndroid Build Coastguard Worker const MCCFIInstruction &Inst = Instrs[i];
919*9880d681SAndroid Build Coastguard Worker switch (Inst.getOperation()) {
920*9880d681SAndroid Build Coastguard Worker case MCCFIInstruction::OpDefCfa: // DW_CFA_def_cfa
921*9880d681SAndroid Build Coastguard Worker CFARegisterOffset = -Inst.getOffset();
922*9880d681SAndroid Build Coastguard Worker CFARegister = MRI.getLLVMRegNum(Inst.getRegister(), true);
923*9880d681SAndroid Build Coastguard Worker break;
924*9880d681SAndroid Build Coastguard Worker case MCCFIInstruction::OpDefCfaOffset: // DW_CFA_def_cfa_offset
925*9880d681SAndroid Build Coastguard Worker CFARegisterOffset = -Inst.getOffset();
926*9880d681SAndroid Build Coastguard Worker break;
927*9880d681SAndroid Build Coastguard Worker case MCCFIInstruction::OpDefCfaRegister: // DW_CFA_def_cfa_register
928*9880d681SAndroid Build Coastguard Worker CFARegister = MRI.getLLVMRegNum(Inst.getRegister(), true);
929*9880d681SAndroid Build Coastguard Worker break;
930*9880d681SAndroid Build Coastguard Worker case MCCFIInstruction::OpOffset: // DW_CFA_offset
931*9880d681SAndroid Build Coastguard Worker Reg = MRI.getLLVMRegNum(Inst.getRegister(), true);
932*9880d681SAndroid Build Coastguard Worker if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
933*9880d681SAndroid Build Coastguard Worker RegOffsets[Reg] = Inst.getOffset();
934*9880d681SAndroid Build Coastguard Worker else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) {
935*9880d681SAndroid Build Coastguard Worker RegOffsets[Reg] = Inst.getOffset();
936*9880d681SAndroid Build Coastguard Worker ++FloatRegCount;
937*9880d681SAndroid Build Coastguard Worker } else {
938*9880d681SAndroid Build Coastguard Worker DEBUG_WITH_TYPE("compact-unwind",
939*9880d681SAndroid Build Coastguard Worker llvm::dbgs() << ".cfi_offset on unknown register="
940*9880d681SAndroid Build Coastguard Worker << Inst.getRegister() << "\n");
941*9880d681SAndroid Build Coastguard Worker return CU::UNWIND_ARM_MODE_DWARF;
942*9880d681SAndroid Build Coastguard Worker }
943*9880d681SAndroid Build Coastguard Worker break;
944*9880d681SAndroid Build Coastguard Worker case MCCFIInstruction::OpRelOffset: // DW_CFA_advance_loc
945*9880d681SAndroid Build Coastguard Worker // Ignore
946*9880d681SAndroid Build Coastguard Worker break;
947*9880d681SAndroid Build Coastguard Worker default:
948*9880d681SAndroid Build Coastguard Worker // Directive not convertable to compact unwind, bail out.
949*9880d681SAndroid Build Coastguard Worker DEBUG_WITH_TYPE("compact-unwind",
950*9880d681SAndroid Build Coastguard Worker llvm::dbgs()
951*9880d681SAndroid Build Coastguard Worker << "CFI directive not compatiable with comact "
952*9880d681SAndroid Build Coastguard Worker "unwind encoding, opcode=" << Inst.getOperation()
953*9880d681SAndroid Build Coastguard Worker << "\n");
954*9880d681SAndroid Build Coastguard Worker return CU::UNWIND_ARM_MODE_DWARF;
955*9880d681SAndroid Build Coastguard Worker break;
956*9880d681SAndroid Build Coastguard Worker }
957*9880d681SAndroid Build Coastguard Worker }
958*9880d681SAndroid Build Coastguard Worker
959*9880d681SAndroid Build Coastguard Worker // If no frame set up, return no unwind info.
960*9880d681SAndroid Build Coastguard Worker if ((CFARegister == ARM::SP) && (CFARegisterOffset == 0))
961*9880d681SAndroid Build Coastguard Worker return 0;
962*9880d681SAndroid Build Coastguard Worker
963*9880d681SAndroid Build Coastguard Worker // Verify standard frame (lr/r7) was used.
964*9880d681SAndroid Build Coastguard Worker if (CFARegister != ARM::R7) {
965*9880d681SAndroid Build Coastguard Worker DEBUG_WITH_TYPE("compact-unwind", llvm::dbgs() << "frame register is "
966*9880d681SAndroid Build Coastguard Worker << CFARegister
967*9880d681SAndroid Build Coastguard Worker << " instead of r7\n");
968*9880d681SAndroid Build Coastguard Worker return CU::UNWIND_ARM_MODE_DWARF;
969*9880d681SAndroid Build Coastguard Worker }
970*9880d681SAndroid Build Coastguard Worker int StackAdjust = CFARegisterOffset - 8;
971*9880d681SAndroid Build Coastguard Worker if (RegOffsets.lookup(ARM::LR) != (-4 - StackAdjust)) {
972*9880d681SAndroid Build Coastguard Worker DEBUG_WITH_TYPE("compact-unwind",
973*9880d681SAndroid Build Coastguard Worker llvm::dbgs()
974*9880d681SAndroid Build Coastguard Worker << "LR not saved as standard frame, StackAdjust="
975*9880d681SAndroid Build Coastguard Worker << StackAdjust
976*9880d681SAndroid Build Coastguard Worker << ", CFARegisterOffset=" << CFARegisterOffset
977*9880d681SAndroid Build Coastguard Worker << ", lr save at offset=" << RegOffsets[14] << "\n");
978*9880d681SAndroid Build Coastguard Worker return CU::UNWIND_ARM_MODE_DWARF;
979*9880d681SAndroid Build Coastguard Worker }
980*9880d681SAndroid Build Coastguard Worker if (RegOffsets.lookup(ARM::R7) != (-8 - StackAdjust)) {
981*9880d681SAndroid Build Coastguard Worker DEBUG_WITH_TYPE("compact-unwind",
982*9880d681SAndroid Build Coastguard Worker llvm::dbgs() << "r7 not saved as standard frame\n");
983*9880d681SAndroid Build Coastguard Worker return CU::UNWIND_ARM_MODE_DWARF;
984*9880d681SAndroid Build Coastguard Worker }
985*9880d681SAndroid Build Coastguard Worker uint32_t CompactUnwindEncoding = CU::UNWIND_ARM_MODE_FRAME;
986*9880d681SAndroid Build Coastguard Worker
987*9880d681SAndroid Build Coastguard Worker // If var-args are used, there may be a stack adjust required.
988*9880d681SAndroid Build Coastguard Worker switch (StackAdjust) {
989*9880d681SAndroid Build Coastguard Worker case 0:
990*9880d681SAndroid Build Coastguard Worker break;
991*9880d681SAndroid Build Coastguard Worker case 4:
992*9880d681SAndroid Build Coastguard Worker CompactUnwindEncoding |= 0x00400000;
993*9880d681SAndroid Build Coastguard Worker break;
994*9880d681SAndroid Build Coastguard Worker case 8:
995*9880d681SAndroid Build Coastguard Worker CompactUnwindEncoding |= 0x00800000;
996*9880d681SAndroid Build Coastguard Worker break;
997*9880d681SAndroid Build Coastguard Worker case 12:
998*9880d681SAndroid Build Coastguard Worker CompactUnwindEncoding |= 0x00C00000;
999*9880d681SAndroid Build Coastguard Worker break;
1000*9880d681SAndroid Build Coastguard Worker default:
1001*9880d681SAndroid Build Coastguard Worker DEBUG_WITH_TYPE("compact-unwind", llvm::dbgs()
1002*9880d681SAndroid Build Coastguard Worker << ".cfi_def_cfa stack adjust ("
1003*9880d681SAndroid Build Coastguard Worker << StackAdjust << ") out of range\n");
1004*9880d681SAndroid Build Coastguard Worker return CU::UNWIND_ARM_MODE_DWARF;
1005*9880d681SAndroid Build Coastguard Worker }
1006*9880d681SAndroid Build Coastguard Worker
1007*9880d681SAndroid Build Coastguard Worker // If r6 is saved, it must be right below r7.
1008*9880d681SAndroid Build Coastguard Worker static struct {
1009*9880d681SAndroid Build Coastguard Worker unsigned Reg;
1010*9880d681SAndroid Build Coastguard Worker unsigned Encoding;
1011*9880d681SAndroid Build Coastguard Worker } GPRCSRegs[] = {{ARM::R6, CU::UNWIND_ARM_FRAME_FIRST_PUSH_R6},
1012*9880d681SAndroid Build Coastguard Worker {ARM::R5, CU::UNWIND_ARM_FRAME_FIRST_PUSH_R5},
1013*9880d681SAndroid Build Coastguard Worker {ARM::R4, CU::UNWIND_ARM_FRAME_FIRST_PUSH_R4},
1014*9880d681SAndroid Build Coastguard Worker {ARM::R12, CU::UNWIND_ARM_FRAME_SECOND_PUSH_R12},
1015*9880d681SAndroid Build Coastguard Worker {ARM::R11, CU::UNWIND_ARM_FRAME_SECOND_PUSH_R11},
1016*9880d681SAndroid Build Coastguard Worker {ARM::R10, CU::UNWIND_ARM_FRAME_SECOND_PUSH_R10},
1017*9880d681SAndroid Build Coastguard Worker {ARM::R9, CU::UNWIND_ARM_FRAME_SECOND_PUSH_R9},
1018*9880d681SAndroid Build Coastguard Worker {ARM::R8, CU::UNWIND_ARM_FRAME_SECOND_PUSH_R8}};
1019*9880d681SAndroid Build Coastguard Worker
1020*9880d681SAndroid Build Coastguard Worker int CurOffset = -8 - StackAdjust;
1021*9880d681SAndroid Build Coastguard Worker for (auto CSReg : GPRCSRegs) {
1022*9880d681SAndroid Build Coastguard Worker auto Offset = RegOffsets.find(CSReg.Reg);
1023*9880d681SAndroid Build Coastguard Worker if (Offset == RegOffsets.end())
1024*9880d681SAndroid Build Coastguard Worker continue;
1025*9880d681SAndroid Build Coastguard Worker
1026*9880d681SAndroid Build Coastguard Worker int RegOffset = Offset->second;
1027*9880d681SAndroid Build Coastguard Worker if (RegOffset != CurOffset - 4) {
1028*9880d681SAndroid Build Coastguard Worker DEBUG_WITH_TYPE("compact-unwind",
1029*9880d681SAndroid Build Coastguard Worker llvm::dbgs() << MRI.getName(CSReg.Reg) << " saved at "
1030*9880d681SAndroid Build Coastguard Worker << RegOffset << " but only supported at "
1031*9880d681SAndroid Build Coastguard Worker << CurOffset << "\n");
1032*9880d681SAndroid Build Coastguard Worker return CU::UNWIND_ARM_MODE_DWARF;
1033*9880d681SAndroid Build Coastguard Worker }
1034*9880d681SAndroid Build Coastguard Worker CompactUnwindEncoding |= CSReg.Encoding;
1035*9880d681SAndroid Build Coastguard Worker CurOffset -= 4;
1036*9880d681SAndroid Build Coastguard Worker }
1037*9880d681SAndroid Build Coastguard Worker
1038*9880d681SAndroid Build Coastguard Worker // If no floats saved, we are done.
1039*9880d681SAndroid Build Coastguard Worker if (FloatRegCount == 0)
1040*9880d681SAndroid Build Coastguard Worker return CompactUnwindEncoding;
1041*9880d681SAndroid Build Coastguard Worker
1042*9880d681SAndroid Build Coastguard Worker // Switch mode to include D register saving.
1043*9880d681SAndroid Build Coastguard Worker CompactUnwindEncoding &= ~CU::UNWIND_ARM_MODE_MASK;
1044*9880d681SAndroid Build Coastguard Worker CompactUnwindEncoding |= CU::UNWIND_ARM_MODE_FRAME_D;
1045*9880d681SAndroid Build Coastguard Worker
1046*9880d681SAndroid Build Coastguard Worker // FIXME: supporting more than 4 saved D-registers compactly would be trivial,
1047*9880d681SAndroid Build Coastguard Worker // but needs coordination with the linker and libunwind.
1048*9880d681SAndroid Build Coastguard Worker if (FloatRegCount > 4) {
1049*9880d681SAndroid Build Coastguard Worker DEBUG_WITH_TYPE("compact-unwind",
1050*9880d681SAndroid Build Coastguard Worker llvm::dbgs() << "unsupported number of D registers saved ("
1051*9880d681SAndroid Build Coastguard Worker << FloatRegCount << ")\n");
1052*9880d681SAndroid Build Coastguard Worker return CU::UNWIND_ARM_MODE_DWARF;
1053*9880d681SAndroid Build Coastguard Worker }
1054*9880d681SAndroid Build Coastguard Worker
1055*9880d681SAndroid Build Coastguard Worker // Floating point registers must either be saved sequentially, or we defer to
1056*9880d681SAndroid Build Coastguard Worker // DWARF. No gaps allowed here so check that each saved d-register is
1057*9880d681SAndroid Build Coastguard Worker // precisely where it should be.
1058*9880d681SAndroid Build Coastguard Worker static unsigned FPRCSRegs[] = { ARM::D8, ARM::D10, ARM::D12, ARM::D14 };
1059*9880d681SAndroid Build Coastguard Worker for (int Idx = FloatRegCount - 1; Idx >= 0; --Idx) {
1060*9880d681SAndroid Build Coastguard Worker auto Offset = RegOffsets.find(FPRCSRegs[Idx]);
1061*9880d681SAndroid Build Coastguard Worker if (Offset == RegOffsets.end()) {
1062*9880d681SAndroid Build Coastguard Worker DEBUG_WITH_TYPE("compact-unwind",
1063*9880d681SAndroid Build Coastguard Worker llvm::dbgs() << FloatRegCount << " D-regs saved, but "
1064*9880d681SAndroid Build Coastguard Worker << MRI.getName(FPRCSRegs[Idx])
1065*9880d681SAndroid Build Coastguard Worker << " not saved\n");
1066*9880d681SAndroid Build Coastguard Worker return CU::UNWIND_ARM_MODE_DWARF;
1067*9880d681SAndroid Build Coastguard Worker } else if (Offset->second != CurOffset - 8) {
1068*9880d681SAndroid Build Coastguard Worker DEBUG_WITH_TYPE("compact-unwind",
1069*9880d681SAndroid Build Coastguard Worker llvm::dbgs() << FloatRegCount << " D-regs saved, but "
1070*9880d681SAndroid Build Coastguard Worker << MRI.getName(FPRCSRegs[Idx])
1071*9880d681SAndroid Build Coastguard Worker << " saved at " << Offset->second
1072*9880d681SAndroid Build Coastguard Worker << ", expected at " << CurOffset - 8
1073*9880d681SAndroid Build Coastguard Worker << "\n");
1074*9880d681SAndroid Build Coastguard Worker return CU::UNWIND_ARM_MODE_DWARF;
1075*9880d681SAndroid Build Coastguard Worker }
1076*9880d681SAndroid Build Coastguard Worker CurOffset -= 8;
1077*9880d681SAndroid Build Coastguard Worker }
1078*9880d681SAndroid Build Coastguard Worker
1079*9880d681SAndroid Build Coastguard Worker return CompactUnwindEncoding | ((FloatRegCount - 1) << 8);
1080*9880d681SAndroid Build Coastguard Worker }
1081*9880d681SAndroid Build Coastguard Worker
getMachOSubTypeFromArch(StringRef Arch)1082*9880d681SAndroid Build Coastguard Worker static MachO::CPUSubTypeARM getMachOSubTypeFromArch(StringRef Arch) {
1083*9880d681SAndroid Build Coastguard Worker unsigned AK = ARM::parseArch(Arch);
1084*9880d681SAndroid Build Coastguard Worker switch (AK) {
1085*9880d681SAndroid Build Coastguard Worker default:
1086*9880d681SAndroid Build Coastguard Worker return MachO::CPU_SUBTYPE_ARM_V7;
1087*9880d681SAndroid Build Coastguard Worker case ARM::AK_ARMV4T:
1088*9880d681SAndroid Build Coastguard Worker return MachO::CPU_SUBTYPE_ARM_V4T;
1089*9880d681SAndroid Build Coastguard Worker case ARM::AK_ARMV5T:
1090*9880d681SAndroid Build Coastguard Worker case ARM::AK_ARMV5TE:
1091*9880d681SAndroid Build Coastguard Worker case ARM::AK_ARMV5TEJ:
1092*9880d681SAndroid Build Coastguard Worker return MachO::CPU_SUBTYPE_ARM_V5;
1093*9880d681SAndroid Build Coastguard Worker case ARM::AK_ARMV6:
1094*9880d681SAndroid Build Coastguard Worker case ARM::AK_ARMV6K:
1095*9880d681SAndroid Build Coastguard Worker return MachO::CPU_SUBTYPE_ARM_V6;
1096*9880d681SAndroid Build Coastguard Worker case ARM::AK_ARMV7A:
1097*9880d681SAndroid Build Coastguard Worker return MachO::CPU_SUBTYPE_ARM_V7;
1098*9880d681SAndroid Build Coastguard Worker case ARM::AK_ARMV7S:
1099*9880d681SAndroid Build Coastguard Worker return MachO::CPU_SUBTYPE_ARM_V7S;
1100*9880d681SAndroid Build Coastguard Worker case ARM::AK_ARMV7K:
1101*9880d681SAndroid Build Coastguard Worker return MachO::CPU_SUBTYPE_ARM_V7K;
1102*9880d681SAndroid Build Coastguard Worker case ARM::AK_ARMV6M:
1103*9880d681SAndroid Build Coastguard Worker return MachO::CPU_SUBTYPE_ARM_V6M;
1104*9880d681SAndroid Build Coastguard Worker case ARM::AK_ARMV7M:
1105*9880d681SAndroid Build Coastguard Worker return MachO::CPU_SUBTYPE_ARM_V7M;
1106*9880d681SAndroid Build Coastguard Worker case ARM::AK_ARMV7EM:
1107*9880d681SAndroid Build Coastguard Worker return MachO::CPU_SUBTYPE_ARM_V7EM;
1108*9880d681SAndroid Build Coastguard Worker }
1109*9880d681SAndroid Build Coastguard Worker }
1110*9880d681SAndroid Build Coastguard Worker
createARMAsmBackend(const Target & T,const MCRegisterInfo & MRI,const Triple & TheTriple,StringRef CPU,bool isLittle)1111*9880d681SAndroid Build Coastguard Worker MCAsmBackend *llvm::createARMAsmBackend(const Target &T,
1112*9880d681SAndroid Build Coastguard Worker const MCRegisterInfo &MRI,
1113*9880d681SAndroid Build Coastguard Worker const Triple &TheTriple, StringRef CPU,
1114*9880d681SAndroid Build Coastguard Worker bool isLittle) {
1115*9880d681SAndroid Build Coastguard Worker switch (TheTriple.getObjectFormat()) {
1116*9880d681SAndroid Build Coastguard Worker default:
1117*9880d681SAndroid Build Coastguard Worker llvm_unreachable("unsupported object format");
1118*9880d681SAndroid Build Coastguard Worker case Triple::MachO: {
1119*9880d681SAndroid Build Coastguard Worker MachO::CPUSubTypeARM CS = getMachOSubTypeFromArch(TheTriple.getArchName());
1120*9880d681SAndroid Build Coastguard Worker return new ARMAsmBackendDarwin(T, TheTriple, MRI, CS);
1121*9880d681SAndroid Build Coastguard Worker }
1122*9880d681SAndroid Build Coastguard Worker case Triple::COFF:
1123*9880d681SAndroid Build Coastguard Worker assert(TheTriple.isOSWindows() && "non-Windows ARM COFF is not supported");
1124*9880d681SAndroid Build Coastguard Worker return new ARMAsmBackendWinCOFF(T, TheTriple);
1125*9880d681SAndroid Build Coastguard Worker case Triple::ELF:
1126*9880d681SAndroid Build Coastguard Worker assert(TheTriple.isOSBinFormatELF() && "using ELF for non-ELF target");
1127*9880d681SAndroid Build Coastguard Worker uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TheTriple.getOS());
1128*9880d681SAndroid Build Coastguard Worker return new ARMAsmBackendELF(T, TheTriple, OSABI, isLittle);
1129*9880d681SAndroid Build Coastguard Worker }
1130*9880d681SAndroid Build Coastguard Worker }
1131*9880d681SAndroid Build Coastguard Worker
createARMLEAsmBackend(const Target & T,const MCRegisterInfo & MRI,const Triple & TT,StringRef CPU)1132*9880d681SAndroid Build Coastguard Worker MCAsmBackend *llvm::createARMLEAsmBackend(const Target &T,
1133*9880d681SAndroid Build Coastguard Worker const MCRegisterInfo &MRI,
1134*9880d681SAndroid Build Coastguard Worker const Triple &TT, StringRef CPU) {
1135*9880d681SAndroid Build Coastguard Worker return createARMAsmBackend(T, MRI, TT, CPU, true);
1136*9880d681SAndroid Build Coastguard Worker }
1137*9880d681SAndroid Build Coastguard Worker
createARMBEAsmBackend(const Target & T,const MCRegisterInfo & MRI,const Triple & TT,StringRef CPU)1138*9880d681SAndroid Build Coastguard Worker MCAsmBackend *llvm::createARMBEAsmBackend(const Target &T,
1139*9880d681SAndroid Build Coastguard Worker const MCRegisterInfo &MRI,
1140*9880d681SAndroid Build Coastguard Worker const Triple &TT, StringRef CPU) {
1141*9880d681SAndroid Build Coastguard Worker return createARMAsmBackend(T, MRI, TT, CPU, false);
1142*9880d681SAndroid Build Coastguard Worker }
1143*9880d681SAndroid Build Coastguard Worker
createThumbLEAsmBackend(const Target & T,const MCRegisterInfo & MRI,const Triple & TT,StringRef CPU)1144*9880d681SAndroid Build Coastguard Worker MCAsmBackend *llvm::createThumbLEAsmBackend(const Target &T,
1145*9880d681SAndroid Build Coastguard Worker const MCRegisterInfo &MRI,
1146*9880d681SAndroid Build Coastguard Worker const Triple &TT, StringRef CPU) {
1147*9880d681SAndroid Build Coastguard Worker return createARMAsmBackend(T, MRI, TT, CPU, true);
1148*9880d681SAndroid Build Coastguard Worker }
1149*9880d681SAndroid Build Coastguard Worker
createThumbBEAsmBackend(const Target & T,const MCRegisterInfo & MRI,const Triple & TT,StringRef CPU)1150*9880d681SAndroid Build Coastguard Worker MCAsmBackend *llvm::createThumbBEAsmBackend(const Target &T,
1151*9880d681SAndroid Build Coastguard Worker const MCRegisterInfo &MRI,
1152*9880d681SAndroid Build Coastguard Worker const Triple &TT, StringRef CPU) {
1153*9880d681SAndroid Build Coastguard Worker return createARMAsmBackend(T, MRI, TT, CPU, false);
1154*9880d681SAndroid Build Coastguard Worker }
1155