1226584Sdim//===-- ARM/ARMMCCodeEmitter.cpp - Convert ARM code to machine code -------===//
2226584Sdim//
3226584Sdim//                     The LLVM Compiler Infrastructure
4226584Sdim//
5226584Sdim// This file is distributed under the University of Illinois Open Source
6226584Sdim// License. See LICENSE.TXT for details.
7226584Sdim//
8226584Sdim//===----------------------------------------------------------------------===//
9226584Sdim//
10226584Sdim// This file implements the ARMMCCodeEmitter class.
11226584Sdim//
12226584Sdim//===----------------------------------------------------------------------===//
13226584Sdim
14226584Sdim#define DEBUG_TYPE "mccodeemitter"
15252723Sdim#include "MCTargetDesc/ARMMCTargetDesc.h"
16226584Sdim#include "MCTargetDesc/ARMAddressingModes.h"
17226584Sdim#include "MCTargetDesc/ARMBaseInfo.h"
18226584Sdim#include "MCTargetDesc/ARMFixupKinds.h"
19226584Sdim#include "MCTargetDesc/ARMMCExpr.h"
20252723Sdim#include "llvm/ADT/APFloat.h"
21252723Sdim#include "llvm/ADT/Statistic.h"
22226584Sdim#include "llvm/MC/MCCodeEmitter.h"
23245431Sdim#include "llvm/MC/MCContext.h"
24226584Sdim#include "llvm/MC/MCExpr.h"
25226584Sdim#include "llvm/MC/MCInst.h"
26226584Sdim#include "llvm/MC/MCInstrInfo.h"
27226584Sdim#include "llvm/MC/MCRegisterInfo.h"
28226584Sdim#include "llvm/MC/MCSubtargetInfo.h"
29226584Sdim#include "llvm/Support/raw_ostream.h"
30226584Sdim
31226584Sdimusing namespace llvm;
32226584Sdim
33226584SdimSTATISTIC(MCNumEmitted, "Number of MC instructions emitted.");
34226584SdimSTATISTIC(MCNumCPRelocations, "Number of constant pool relocations created.");
35226584Sdim
36226584Sdimnamespace {
37226584Sdimclass ARMMCCodeEmitter : public MCCodeEmitter {
38245431Sdim  ARMMCCodeEmitter(const ARMMCCodeEmitter &) LLVM_DELETED_FUNCTION;
39245431Sdim  void operator=(const ARMMCCodeEmitter &) LLVM_DELETED_FUNCTION;
40226584Sdim  const MCInstrInfo &MCII;
41226584Sdim  const MCSubtargetInfo &STI;
42245431Sdim  const MCContext &CTX;
43226584Sdim
44226584Sdimpublic:
45226584Sdim  ARMMCCodeEmitter(const MCInstrInfo &mcii, const MCSubtargetInfo &sti,
46226584Sdim                   MCContext &ctx)
47245431Sdim    : MCII(mcii), STI(sti), CTX(ctx) {
48226584Sdim  }
49226584Sdim
50226584Sdim  ~ARMMCCodeEmitter() {}
51226584Sdim
52226584Sdim  bool isThumb() const {
53226584Sdim    // FIXME: Can tablegen auto-generate this?
54226584Sdim    return (STI.getFeatureBits() & ARM::ModeThumb) != 0;
55226584Sdim  }
56226584Sdim  bool isThumb2() const {
57226584Sdim    return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2) != 0;
58226584Sdim  }
59226584Sdim  bool isTargetDarwin() const {
60226584Sdim    Triple TT(STI.getTargetTriple());
61263509Sdim  	return TT.isOSDarwin();
62226584Sdim  }
63226584Sdim
64226584Sdim  unsigned getMachineSoImmOpValue(unsigned SoImm) const;
65226584Sdim
66226584Sdim  // getBinaryCodeForInstr - TableGen'erated function for getting the
67226584Sdim  // binary encoding for an instruction.
68235633Sdim  uint64_t getBinaryCodeForInstr(const MCInst &MI,
69226584Sdim                                 SmallVectorImpl<MCFixup> &Fixups) const;
70226584Sdim
71226584Sdim  /// getMachineOpValue - Return binary encoding of operand. If the machine
72226584Sdim  /// operand requires relocation, record the relocation and return zero.
73226584Sdim  unsigned getMachineOpValue(const MCInst &MI,const MCOperand &MO,
74226584Sdim                             SmallVectorImpl<MCFixup> &Fixups) const;
75226584Sdim
76226584Sdim  /// getHiLo16ImmOpValue - Return the encoding for the hi / low 16-bit of
77226584Sdim  /// the specified operand. This is used for operands with :lower16: and
78226584Sdim  /// :upper16: prefixes.
79226584Sdim  uint32_t getHiLo16ImmOpValue(const MCInst &MI, unsigned OpIdx,
80226584Sdim                               SmallVectorImpl<MCFixup> &Fixups) const;
81226584Sdim
82226584Sdim  bool EncodeAddrModeOpValues(const MCInst &MI, unsigned OpIdx,
83226584Sdim                              unsigned &Reg, unsigned &Imm,
84226584Sdim                              SmallVectorImpl<MCFixup> &Fixups) const;
85226584Sdim
86226584Sdim  /// getThumbBLTargetOpValue - Return encoding info for Thumb immediate
87226584Sdim  /// BL branch target.
88226584Sdim  uint32_t getThumbBLTargetOpValue(const MCInst &MI, unsigned OpIdx,
89226584Sdim                                   SmallVectorImpl<MCFixup> &Fixups) const;
90226584Sdim
91226584Sdim  /// getThumbBLXTargetOpValue - Return encoding info for Thumb immediate
92226584Sdim  /// BLX branch target.
93226584Sdim  uint32_t getThumbBLXTargetOpValue(const MCInst &MI, unsigned OpIdx,
94226584Sdim                                    SmallVectorImpl<MCFixup> &Fixups) const;
95226584Sdim
96226584Sdim  /// getThumbBRTargetOpValue - Return encoding info for Thumb branch target.
97226584Sdim  uint32_t getThumbBRTargetOpValue(const MCInst &MI, unsigned OpIdx,
98226584Sdim                                   SmallVectorImpl<MCFixup> &Fixups) const;
99226584Sdim
100226584Sdim  /// getThumbBCCTargetOpValue - Return encoding info for Thumb branch target.
101226584Sdim  uint32_t getThumbBCCTargetOpValue(const MCInst &MI, unsigned OpIdx,
102226584Sdim                                    SmallVectorImpl<MCFixup> &Fixups) const;
103226584Sdim
104226584Sdim  /// getThumbCBTargetOpValue - Return encoding info for Thumb branch target.
105226584Sdim  uint32_t getThumbCBTargetOpValue(const MCInst &MI, unsigned OpIdx,
106226584Sdim                                   SmallVectorImpl<MCFixup> &Fixups) const;
107226584Sdim
108226584Sdim  /// getBranchTargetOpValue - Return encoding info for 24-bit immediate
109226584Sdim  /// branch target.
110226584Sdim  uint32_t getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
111226584Sdim                                  SmallVectorImpl<MCFixup> &Fixups) const;
112226584Sdim
113226584Sdim  /// getUnconditionalBranchTargetOpValue - Return encoding info for 24-bit
114226584Sdim  /// immediate Thumb2 direct branch target.
115226584Sdim  uint32_t getUnconditionalBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
116226584Sdim                                  SmallVectorImpl<MCFixup> &Fixups) const;
117226584Sdim
118226584Sdim  /// getARMBranchTargetOpValue - Return encoding info for 24-bit immediate
119226584Sdim  /// branch target.
120226584Sdim  uint32_t getARMBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
121226584Sdim                                     SmallVectorImpl<MCFixup> &Fixups) const;
122235633Sdim  uint32_t getARMBLTargetOpValue(const MCInst &MI, unsigned OpIdx,
123235633Sdim                                 SmallVectorImpl<MCFixup> &Fixups) const;
124226584Sdim  uint32_t getARMBLXTargetOpValue(const MCInst &MI, unsigned OpIdx,
125235633Sdim                                  SmallVectorImpl<MCFixup> &Fixups) const;
126226584Sdim
127226584Sdim  /// getAdrLabelOpValue - Return encoding info for 12-bit immediate
128226584Sdim  /// ADR label target.
129226584Sdim  uint32_t getAdrLabelOpValue(const MCInst &MI, unsigned OpIdx,
130226584Sdim                              SmallVectorImpl<MCFixup> &Fixups) const;
131226584Sdim  uint32_t getThumbAdrLabelOpValue(const MCInst &MI, unsigned OpIdx,
132226584Sdim                              SmallVectorImpl<MCFixup> &Fixups) const;
133226584Sdim  uint32_t getT2AdrLabelOpValue(const MCInst &MI, unsigned OpIdx,
134226584Sdim                              SmallVectorImpl<MCFixup> &Fixups) const;
135226584Sdim
136226584Sdim
137226584Sdim  /// getAddrModeImm12OpValue - Return encoding info for 'reg +/- imm12'
138226584Sdim  /// operand.
139226584Sdim  uint32_t getAddrModeImm12OpValue(const MCInst &MI, unsigned OpIdx,
140226584Sdim                                   SmallVectorImpl<MCFixup> &Fixups) const;
141226584Sdim
142226584Sdim  /// getThumbAddrModeRegRegOpValue - Return encoding for 'reg + reg' operand.
143226584Sdim  uint32_t getThumbAddrModeRegRegOpValue(const MCInst &MI, unsigned OpIdx,
144226584Sdim                                         SmallVectorImpl<MCFixup> &Fixups)const;
145226584Sdim
146226584Sdim  /// getT2AddrModeImm8s4OpValue - Return encoding info for 'reg +/- imm8<<2'
147226584Sdim  /// operand.
148226584Sdim  uint32_t getT2AddrModeImm8s4OpValue(const MCInst &MI, unsigned OpIdx,
149226584Sdim                                   SmallVectorImpl<MCFixup> &Fixups) const;
150226584Sdim
151226584Sdim  /// getT2AddrModeImm0_1020s4OpValue - Return encoding info for 'reg + imm8<<2'
152226584Sdim  /// operand.
153226584Sdim  uint32_t getT2AddrModeImm0_1020s4OpValue(const MCInst &MI, unsigned OpIdx,
154226584Sdim                                   SmallVectorImpl<MCFixup> &Fixups) const;
155226584Sdim
156226584Sdim  /// getT2Imm8s4OpValue - Return encoding info for '+/- imm8<<2'
157226584Sdim  /// operand.
158226584Sdim  uint32_t getT2Imm8s4OpValue(const MCInst &MI, unsigned OpIdx,
159226584Sdim                              SmallVectorImpl<MCFixup> &Fixups) const;
160226584Sdim
161226584Sdim
162226584Sdim  /// getLdStSORegOpValue - Return encoding info for 'reg +/- reg shop imm'
163226584Sdim  /// operand as needed by load/store instructions.
164226584Sdim  uint32_t getLdStSORegOpValue(const MCInst &MI, unsigned OpIdx,
165226584Sdim                               SmallVectorImpl<MCFixup> &Fixups) const;
166226584Sdim
167226584Sdim  /// getLdStmModeOpValue - Return encoding for load/store multiple mode.
168226584Sdim  uint32_t getLdStmModeOpValue(const MCInst &MI, unsigned OpIdx,
169226584Sdim                               SmallVectorImpl<MCFixup> &Fixups) const {
170226584Sdim    ARM_AM::AMSubMode Mode = (ARM_AM::AMSubMode)MI.getOperand(OpIdx).getImm();
171226584Sdim    switch (Mode) {
172235633Sdim    default: llvm_unreachable("Unknown addressing sub-mode!");
173226584Sdim    case ARM_AM::da: return 0;
174226584Sdim    case ARM_AM::ia: return 1;
175226584Sdim    case ARM_AM::db: return 2;
176226584Sdim    case ARM_AM::ib: return 3;
177226584Sdim    }
178226584Sdim  }
179226584Sdim  /// getShiftOp - Return the shift opcode (bit[6:5]) of the immediate value.
180226584Sdim  ///
181226584Sdim  unsigned getShiftOp(ARM_AM::ShiftOpc ShOpc) const {
182226584Sdim    switch (ShOpc) {
183226584Sdim    case ARM_AM::no_shift:
184226584Sdim    case ARM_AM::lsl: return 0;
185226584Sdim    case ARM_AM::lsr: return 1;
186226584Sdim    case ARM_AM::asr: return 2;
187226584Sdim    case ARM_AM::ror:
188226584Sdim    case ARM_AM::rrx: return 3;
189226584Sdim    }
190235633Sdim    llvm_unreachable("Invalid ShiftOpc!");
191226584Sdim  }
192226584Sdim
193226584Sdim  /// getAddrMode2OpValue - Return encoding for addrmode2 operands.
194226584Sdim  uint32_t getAddrMode2OpValue(const MCInst &MI, unsigned OpIdx,
195226584Sdim                               SmallVectorImpl<MCFixup> &Fixups) const;
196226584Sdim
197226584Sdim  /// getAddrMode2OffsetOpValue - Return encoding for am2offset operands.
198226584Sdim  uint32_t getAddrMode2OffsetOpValue(const MCInst &MI, unsigned OpIdx,
199226584Sdim                                     SmallVectorImpl<MCFixup> &Fixups) const;
200226584Sdim
201226584Sdim  /// getPostIdxRegOpValue - Return encoding for postidx_reg operands.
202226584Sdim  uint32_t getPostIdxRegOpValue(const MCInst &MI, unsigned OpIdx,
203226584Sdim                                SmallVectorImpl<MCFixup> &Fixups) const;
204226584Sdim
205226584Sdim  /// getAddrMode3OffsetOpValue - Return encoding for am3offset operands.
206226584Sdim  uint32_t getAddrMode3OffsetOpValue(const MCInst &MI, unsigned OpIdx,
207226584Sdim                                     SmallVectorImpl<MCFixup> &Fixups) const;
208226584Sdim
209226584Sdim  /// getAddrMode3OpValue - Return encoding for addrmode3 operands.
210226584Sdim  uint32_t getAddrMode3OpValue(const MCInst &MI, unsigned OpIdx,
211226584Sdim                               SmallVectorImpl<MCFixup> &Fixups) const;
212226584Sdim
213226584Sdim  /// getAddrModeThumbSPOpValue - Return encoding info for 'reg +/- imm12'
214226584Sdim  /// operand.
215226584Sdim  uint32_t getAddrModeThumbSPOpValue(const MCInst &MI, unsigned OpIdx,
216226584Sdim                                     SmallVectorImpl<MCFixup> &Fixups) const;
217226584Sdim
218226584Sdim  /// getAddrModeISOpValue - Encode the t_addrmode_is# operands.
219226584Sdim  uint32_t getAddrModeISOpValue(const MCInst &MI, unsigned OpIdx,
220226584Sdim                                SmallVectorImpl<MCFixup> &Fixups) const;
221226584Sdim
222226584Sdim  /// getAddrModePCOpValue - Return encoding for t_addrmode_pc operands.
223226584Sdim  uint32_t getAddrModePCOpValue(const MCInst &MI, unsigned OpIdx,
224226584Sdim                                SmallVectorImpl<MCFixup> &Fixups) const;
225226584Sdim
226226584Sdim  /// getAddrMode5OpValue - Return encoding info for 'reg +/- imm8' operand.
227226584Sdim  uint32_t getAddrMode5OpValue(const MCInst &MI, unsigned OpIdx,
228226584Sdim                               SmallVectorImpl<MCFixup> &Fixups) const;
229226584Sdim
230226584Sdim  /// getCCOutOpValue - Return encoding of the 's' bit.
231226584Sdim  unsigned getCCOutOpValue(const MCInst &MI, unsigned Op,
232226584Sdim                           SmallVectorImpl<MCFixup> &Fixups) const {
233226584Sdim    // The operand is either reg0 or CPSR. The 's' bit is encoded as '0' or
234226584Sdim    // '1' respectively.
235226584Sdim    return MI.getOperand(Op).getReg() == ARM::CPSR;
236226584Sdim  }
237226584Sdim
238226584Sdim  /// getSOImmOpValue - Return an encoded 12-bit shifted-immediate value.
239226584Sdim  unsigned getSOImmOpValue(const MCInst &MI, unsigned Op,
240226584Sdim                           SmallVectorImpl<MCFixup> &Fixups) const {
241226584Sdim    unsigned SoImm = MI.getOperand(Op).getImm();
242226584Sdim    int SoImmVal = ARM_AM::getSOImmVal(SoImm);
243226584Sdim    assert(SoImmVal != -1 && "Not a valid so_imm value!");
244226584Sdim
245226584Sdim    // Encode rotate_imm.
246226584Sdim    unsigned Binary = (ARM_AM::getSOImmValRot((unsigned)SoImmVal) >> 1)
247226584Sdim      << ARMII::SoRotImmShift;
248226584Sdim
249226584Sdim    // Encode immed_8.
250226584Sdim    Binary |= ARM_AM::getSOImmValImm((unsigned)SoImmVal);
251226584Sdim    return Binary;
252226584Sdim  }
253226584Sdim
254226584Sdim  /// getT2SOImmOpValue - Return an encoded 12-bit shifted-immediate value.
255226584Sdim  unsigned getT2SOImmOpValue(const MCInst &MI, unsigned Op,
256226584Sdim                           SmallVectorImpl<MCFixup> &Fixups) const {
257226584Sdim    unsigned SoImm = MI.getOperand(Op).getImm();
258226584Sdim    unsigned Encoded =  ARM_AM::getT2SOImmVal(SoImm);
259226584Sdim    assert(Encoded != ~0U && "Not a Thumb2 so_imm value?");
260226584Sdim    return Encoded;
261226584Sdim  }
262226584Sdim
263226584Sdim  unsigned getT2AddrModeSORegOpValue(const MCInst &MI, unsigned OpNum,
264226584Sdim    SmallVectorImpl<MCFixup> &Fixups) const;
265226584Sdim  unsigned getT2AddrModeImm8OpValue(const MCInst &MI, unsigned OpNum,
266226584Sdim    SmallVectorImpl<MCFixup> &Fixups) const;
267226584Sdim  unsigned getT2AddrModeImm8OffsetOpValue(const MCInst &MI, unsigned OpNum,
268226584Sdim    SmallVectorImpl<MCFixup> &Fixups) const;
269226584Sdim  unsigned getT2AddrModeImm12OffsetOpValue(const MCInst &MI, unsigned OpNum,
270226584Sdim    SmallVectorImpl<MCFixup> &Fixups) const;
271226584Sdim
272226584Sdim  /// getSORegOpValue - Return an encoded so_reg shifted register value.
273226584Sdim  unsigned getSORegRegOpValue(const MCInst &MI, unsigned Op,
274226584Sdim                           SmallVectorImpl<MCFixup> &Fixups) const;
275226584Sdim  unsigned getSORegImmOpValue(const MCInst &MI, unsigned Op,
276226584Sdim                           SmallVectorImpl<MCFixup> &Fixups) const;
277226584Sdim  unsigned getT2SORegOpValue(const MCInst &MI, unsigned Op,
278226584Sdim                             SmallVectorImpl<MCFixup> &Fixups) const;
279226584Sdim
280226584Sdim  unsigned getNEONVcvtImm32OpValue(const MCInst &MI, unsigned Op,
281226584Sdim                                   SmallVectorImpl<MCFixup> &Fixups) const {
282226584Sdim    return 64 - MI.getOperand(Op).getImm();
283226584Sdim  }
284226584Sdim
285226584Sdim  unsigned getBitfieldInvertedMaskOpValue(const MCInst &MI, unsigned Op,
286226584Sdim                                      SmallVectorImpl<MCFixup> &Fixups) const;
287226584Sdim
288226584Sdim  unsigned getRegisterListOpValue(const MCInst &MI, unsigned Op,
289226584Sdim                                  SmallVectorImpl<MCFixup> &Fixups) const;
290226584Sdim  unsigned getAddrMode6AddressOpValue(const MCInst &MI, unsigned Op,
291226584Sdim                                      SmallVectorImpl<MCFixup> &Fixups) const;
292226584Sdim  unsigned getAddrMode6OneLane32AddressOpValue(const MCInst &MI, unsigned Op,
293226584Sdim                                        SmallVectorImpl<MCFixup> &Fixups) const;
294226584Sdim  unsigned getAddrMode6DupAddressOpValue(const MCInst &MI, unsigned Op,
295226584Sdim                                        SmallVectorImpl<MCFixup> &Fixups) const;
296226584Sdim  unsigned getAddrMode6OffsetOpValue(const MCInst &MI, unsigned Op,
297226584Sdim                                     SmallVectorImpl<MCFixup> &Fixups) const;
298226584Sdim
299226584Sdim  unsigned getShiftRight8Imm(const MCInst &MI, unsigned Op,
300226584Sdim                             SmallVectorImpl<MCFixup> &Fixups) const;
301226584Sdim  unsigned getShiftRight16Imm(const MCInst &MI, unsigned Op,
302226584Sdim                              SmallVectorImpl<MCFixup> &Fixups) const;
303226584Sdim  unsigned getShiftRight32Imm(const MCInst &MI, unsigned Op,
304226584Sdim                              SmallVectorImpl<MCFixup> &Fixups) const;
305226584Sdim  unsigned getShiftRight64Imm(const MCInst &MI, unsigned Op,
306226584Sdim                              SmallVectorImpl<MCFixup> &Fixups) const;
307226584Sdim
308226584Sdim  unsigned getThumbSRImmOpValue(const MCInst &MI, unsigned Op,
309226584Sdim                                 SmallVectorImpl<MCFixup> &Fixups) const;
310226584Sdim
311226584Sdim  unsigned NEONThumb2DataIPostEncoder(const MCInst &MI,
312226584Sdim                                      unsigned EncodedValue) const;
313226584Sdim  unsigned NEONThumb2LoadStorePostEncoder(const MCInst &MI,
314226584Sdim                                          unsigned EncodedValue) const;
315226584Sdim  unsigned NEONThumb2DupPostEncoder(const MCInst &MI,
316226584Sdim                                    unsigned EncodedValue) const;
317263509Sdim  unsigned NEONThumb2V8PostEncoder(const MCInst &MI,
318263509Sdim                                   unsigned EncodedValue) const;
319226584Sdim
320226584Sdim  unsigned VFPThumb2PostEncoder(const MCInst &MI,
321226584Sdim                                unsigned EncodedValue) const;
322226584Sdim
323226584Sdim  void EmitByte(unsigned char C, raw_ostream &OS) const {
324226584Sdim    OS << (char)C;
325226584Sdim  }
326226584Sdim
327226584Sdim  void EmitConstant(uint64_t Val, unsigned Size, raw_ostream &OS) const {
328226584Sdim    // Output the constant in little endian byte order.
329226584Sdim    for (unsigned i = 0; i != Size; ++i) {
330226584Sdim      EmitByte(Val & 255, OS);
331226584Sdim      Val >>= 8;
332226584Sdim    }
333226584Sdim  }
334226584Sdim
335226584Sdim  void EncodeInstruction(const MCInst &MI, raw_ostream &OS,
336226584Sdim                         SmallVectorImpl<MCFixup> &Fixups) const;
337226584Sdim};
338226584Sdim
339226584Sdim} // end anonymous namespace
340226584Sdim
341226584SdimMCCodeEmitter *llvm::createARMMCCodeEmitter(const MCInstrInfo &MCII,
342245431Sdim                                            const MCRegisterInfo &MRI,
343226584Sdim                                            const MCSubtargetInfo &STI,
344226584Sdim                                            MCContext &Ctx) {
345226584Sdim  return new ARMMCCodeEmitter(MCII, STI, Ctx);
346226584Sdim}
347226584Sdim
348226584Sdim/// NEONThumb2DataIPostEncoder - Post-process encoded NEON data-processing
349226584Sdim/// instructions, and rewrite them to their Thumb2 form if we are currently in
350226584Sdim/// Thumb2 mode.
351226584Sdimunsigned ARMMCCodeEmitter::NEONThumb2DataIPostEncoder(const MCInst &MI,
352226584Sdim                                                 unsigned EncodedValue) const {
353226584Sdim  if (isThumb2()) {
354226584Sdim    // NEON Thumb2 data-processsing encodings are very simple: bit 24 is moved
355226584Sdim    // to bit 12 of the high half-word (i.e. bit 28), and bits 27-24 are
356226584Sdim    // set to 1111.
357226584Sdim    unsigned Bit24 = EncodedValue & 0x01000000;
358226584Sdim    unsigned Bit28 = Bit24 << 4;
359226584Sdim    EncodedValue &= 0xEFFFFFFF;
360226584Sdim    EncodedValue |= Bit28;
361226584Sdim    EncodedValue |= 0x0F000000;
362226584Sdim  }
363226584Sdim
364226584Sdim  return EncodedValue;
365226584Sdim}
366226584Sdim
367226584Sdim/// NEONThumb2LoadStorePostEncoder - Post-process encoded NEON load/store
368226584Sdim/// instructions, and rewrite them to their Thumb2 form if we are currently in
369226584Sdim/// Thumb2 mode.
370226584Sdimunsigned ARMMCCodeEmitter::NEONThumb2LoadStorePostEncoder(const MCInst &MI,
371226584Sdim                                                 unsigned EncodedValue) const {
372226584Sdim  if (isThumb2()) {
373226584Sdim    EncodedValue &= 0xF0FFFFFF;
374226584Sdim    EncodedValue |= 0x09000000;
375226584Sdim  }
376226584Sdim
377226584Sdim  return EncodedValue;
378226584Sdim}
379226584Sdim
380226584Sdim/// NEONThumb2DupPostEncoder - Post-process encoded NEON vdup
381226584Sdim/// instructions, and rewrite them to their Thumb2 form if we are currently in
382226584Sdim/// Thumb2 mode.
383226584Sdimunsigned ARMMCCodeEmitter::NEONThumb2DupPostEncoder(const MCInst &MI,
384226584Sdim                                                 unsigned EncodedValue) const {
385226584Sdim  if (isThumb2()) {
386226584Sdim    EncodedValue &= 0x00FFFFFF;
387226584Sdim    EncodedValue |= 0xEE000000;
388226584Sdim  }
389226584Sdim
390226584Sdim  return EncodedValue;
391226584Sdim}
392226584Sdim
393263509Sdim/// Post-process encoded NEON v8 instructions, and rewrite them to Thumb2 form
394263509Sdim/// if we are in Thumb2.
395263509Sdimunsigned ARMMCCodeEmitter::NEONThumb2V8PostEncoder(const MCInst &MI,
396263509Sdim                                                 unsigned EncodedValue) const {
397263509Sdim  if (isThumb2()) {
398263509Sdim    EncodedValue |= 0xC000000; // Set bits 27-26
399263509Sdim  }
400263509Sdim
401263509Sdim  return EncodedValue;
402263509Sdim}
403263509Sdim
404226584Sdim/// VFPThumb2PostEncoder - Post-process encoded VFP instructions and rewrite
405226584Sdim/// them to their Thumb2 form if we are currently in Thumb2 mode.
406226584Sdimunsigned ARMMCCodeEmitter::
407226584SdimVFPThumb2PostEncoder(const MCInst &MI, unsigned EncodedValue) const {
408226584Sdim  if (isThumb2()) {
409226584Sdim    EncodedValue &= 0x0FFFFFFF;
410226584Sdim    EncodedValue |= 0xE0000000;
411226584Sdim  }
412226584Sdim  return EncodedValue;
413226584Sdim}
414226584Sdim
415226584Sdim/// getMachineOpValue - Return binary encoding of operand. If the machine
416226584Sdim/// operand requires relocation, record the relocation and return zero.
417226584Sdimunsigned ARMMCCodeEmitter::
418226584SdimgetMachineOpValue(const MCInst &MI, const MCOperand &MO,
419226584Sdim                  SmallVectorImpl<MCFixup> &Fixups) const {
420226584Sdim  if (MO.isReg()) {
421226584Sdim    unsigned Reg = MO.getReg();
422263509Sdim    unsigned RegNo = CTX.getRegisterInfo()->getEncodingValue(Reg);
423226584Sdim
424226584Sdim    // Q registers are encoded as 2x their register number.
425226584Sdim    switch (Reg) {
426226584Sdim    default:
427226584Sdim      return RegNo;
428226584Sdim    case ARM::Q0:  case ARM::Q1:  case ARM::Q2:  case ARM::Q3:
429226584Sdim    case ARM::Q4:  case ARM::Q5:  case ARM::Q6:  case ARM::Q7:
430226584Sdim    case ARM::Q8:  case ARM::Q9:  case ARM::Q10: case ARM::Q11:
431226584Sdim    case ARM::Q12: case ARM::Q13: case ARM::Q14: case ARM::Q15:
432226584Sdim      return 2 * RegNo;
433226584Sdim    }
434226584Sdim  } else if (MO.isImm()) {
435226584Sdim    return static_cast<unsigned>(MO.getImm());
436226584Sdim  } else if (MO.isFPImm()) {
437226584Sdim    return static_cast<unsigned>(APFloat(MO.getFPImm())
438226584Sdim                     .bitcastToAPInt().getHiBits(32).getLimitedValue());
439226584Sdim  }
440226584Sdim
441226584Sdim  llvm_unreachable("Unable to encode MCOperand!");
442226584Sdim}
443226584Sdim
444226584Sdim/// getAddrModeImmOpValue - Return encoding info for 'reg +/- imm' operand.
445226584Sdimbool ARMMCCodeEmitter::
446226584SdimEncodeAddrModeOpValues(const MCInst &MI, unsigned OpIdx, unsigned &Reg,
447226584Sdim                       unsigned &Imm, SmallVectorImpl<MCFixup> &Fixups) const {
448226584Sdim  const MCOperand &MO  = MI.getOperand(OpIdx);
449226584Sdim  const MCOperand &MO1 = MI.getOperand(OpIdx + 1);
450226584Sdim
451263509Sdim  Reg = CTX.getRegisterInfo()->getEncodingValue(MO.getReg());
452226584Sdim
453226584Sdim  int32_t SImm = MO1.getImm();
454226584Sdim  bool isAdd = true;
455226584Sdim
456226584Sdim  // Special value for #-0
457226584Sdim  if (SImm == INT32_MIN) {
458226584Sdim    SImm = 0;
459226584Sdim    isAdd = false;
460226584Sdim  }
461226584Sdim
462226584Sdim  // Immediate is always encoded as positive. The 'U' bit controls add vs sub.
463226584Sdim  if (SImm < 0) {
464226584Sdim    SImm = -SImm;
465226584Sdim    isAdd = false;
466226584Sdim  }
467226584Sdim
468226584Sdim  Imm = SImm;
469226584Sdim  return isAdd;
470226584Sdim}
471226584Sdim
472226584Sdim/// getBranchTargetOpValue - Helper function to get the branch target operand,
473226584Sdim/// which is either an immediate or requires a fixup.
474226584Sdimstatic uint32_t getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
475226584Sdim                                       unsigned FixupKind,
476226584Sdim                                       SmallVectorImpl<MCFixup> &Fixups) {
477226584Sdim  const MCOperand &MO = MI.getOperand(OpIdx);
478226584Sdim
479226584Sdim  // If the destination is an immediate, we have nothing to do.
480226584Sdim  if (MO.isImm()) return MO.getImm();
481226584Sdim  assert(MO.isExpr() && "Unexpected branch target type!");
482226584Sdim  const MCExpr *Expr = MO.getExpr();
483226584Sdim  MCFixupKind Kind = MCFixupKind(FixupKind);
484235633Sdim  Fixups.push_back(MCFixup::Create(0, Expr, Kind, MI.getLoc()));
485226584Sdim
486226584Sdim  // All of the information is in the fixup.
487226584Sdim  return 0;
488226584Sdim}
489226584Sdim
490226584Sdim// Thumb BL and BLX use a strange offset encoding where bits 22 and 21 are
491226584Sdim// determined by negating them and XOR'ing them with bit 23.
492226584Sdimstatic int32_t encodeThumbBLOffset(int32_t offset) {
493226584Sdim  offset >>= 1;
494226584Sdim  uint32_t S  = (offset & 0x800000) >> 23;
495226584Sdim  uint32_t J1 = (offset & 0x400000) >> 22;
496226584Sdim  uint32_t J2 = (offset & 0x200000) >> 21;
497226584Sdim  J1 = (~J1 & 0x1);
498226584Sdim  J2 = (~J2 & 0x1);
499226584Sdim  J1 ^= S;
500226584Sdim  J2 ^= S;
501226584Sdim
502226584Sdim  offset &= ~0x600000;
503226584Sdim  offset |= J1 << 22;
504226584Sdim  offset |= J2 << 21;
505226584Sdim
506226584Sdim  return offset;
507226584Sdim}
508226584Sdim
509226584Sdim/// getThumbBLTargetOpValue - Return encoding info for immediate branch target.
510226584Sdimuint32_t ARMMCCodeEmitter::
511226584SdimgetThumbBLTargetOpValue(const MCInst &MI, unsigned OpIdx,
512226584Sdim                        SmallVectorImpl<MCFixup> &Fixups) const {
513226584Sdim  const MCOperand MO = MI.getOperand(OpIdx);
514226584Sdim  if (MO.isExpr())
515226584Sdim    return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_thumb_bl,
516226584Sdim                                    Fixups);
517226584Sdim  return encodeThumbBLOffset(MO.getImm());
518226584Sdim}
519226584Sdim
520226584Sdim/// getThumbBLXTargetOpValue - Return encoding info for Thumb immediate
521226584Sdim/// BLX branch target.
522226584Sdimuint32_t ARMMCCodeEmitter::
523226584SdimgetThumbBLXTargetOpValue(const MCInst &MI, unsigned OpIdx,
524226584Sdim                         SmallVectorImpl<MCFixup> &Fixups) const {
525226584Sdim  const MCOperand MO = MI.getOperand(OpIdx);
526226584Sdim  if (MO.isExpr())
527226584Sdim    return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_thumb_blx,
528226584Sdim                                    Fixups);
529226584Sdim  return encodeThumbBLOffset(MO.getImm());
530226584Sdim}
531226584Sdim
532226584Sdim/// getThumbBRTargetOpValue - Return encoding info for Thumb branch target.
533226584Sdimuint32_t ARMMCCodeEmitter::
534226584SdimgetThumbBRTargetOpValue(const MCInst &MI, unsigned OpIdx,
535226584Sdim                        SmallVectorImpl<MCFixup> &Fixups) const {
536226584Sdim  const MCOperand MO = MI.getOperand(OpIdx);
537226584Sdim  if (MO.isExpr())
538226584Sdim    return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_thumb_br,
539226584Sdim                                    Fixups);
540226584Sdim  return (MO.getImm() >> 1);
541226584Sdim}
542226584Sdim
543226584Sdim/// getThumbBCCTargetOpValue - Return encoding info for Thumb branch target.
544226584Sdimuint32_t ARMMCCodeEmitter::
545226584SdimgetThumbBCCTargetOpValue(const MCInst &MI, unsigned OpIdx,
546226584Sdim                         SmallVectorImpl<MCFixup> &Fixups) const {
547226584Sdim  const MCOperand MO = MI.getOperand(OpIdx);
548226584Sdim  if (MO.isExpr())
549226584Sdim    return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_thumb_bcc,
550226584Sdim                                    Fixups);
551226584Sdim  return (MO.getImm() >> 1);
552226584Sdim}
553226584Sdim
554226584Sdim/// getThumbCBTargetOpValue - Return encoding info for Thumb branch target.
555226584Sdimuint32_t ARMMCCodeEmitter::
556226584SdimgetThumbCBTargetOpValue(const MCInst &MI, unsigned OpIdx,
557226584Sdim                        SmallVectorImpl<MCFixup> &Fixups) const {
558226584Sdim  const MCOperand MO = MI.getOperand(OpIdx);
559226584Sdim  if (MO.isExpr())
560226584Sdim    return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_thumb_cb, Fixups);
561226584Sdim  return (MO.getImm() >> 1);
562226584Sdim}
563226584Sdim
564226584Sdim/// Return true if this branch has a non-always predication
565226584Sdimstatic bool HasConditionalBranch(const MCInst &MI) {
566226584Sdim  int NumOp = MI.getNumOperands();
567226584Sdim  if (NumOp >= 2) {
568226584Sdim    for (int i = 0; i < NumOp-1; ++i) {
569226584Sdim      const MCOperand &MCOp1 = MI.getOperand(i);
570226584Sdim      const MCOperand &MCOp2 = MI.getOperand(i + 1);
571226584Sdim      if (MCOp1.isImm() && MCOp2.isReg() &&
572226584Sdim          (MCOp2.getReg() == 0 || MCOp2.getReg() == ARM::CPSR)) {
573226584Sdim        if (ARMCC::CondCodes(MCOp1.getImm()) != ARMCC::AL)
574226584Sdim          return true;
575226584Sdim      }
576226584Sdim    }
577226584Sdim  }
578226584Sdim  return false;
579226584Sdim}
580226584Sdim
581226584Sdim/// getBranchTargetOpValue - Return encoding info for 24-bit immediate branch
582226584Sdim/// target.
583226584Sdimuint32_t ARMMCCodeEmitter::
584226584SdimgetBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
585226584Sdim                       SmallVectorImpl<MCFixup> &Fixups) const {
586226584Sdim  // FIXME: This really, really shouldn't use TargetMachine. We don't want
587226584Sdim  // coupling between MC and TM anywhere we can help it.
588226584Sdim  if (isThumb2())
589226584Sdim    return
590226584Sdim      ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_t2_condbranch, Fixups);
591226584Sdim  return getARMBranchTargetOpValue(MI, OpIdx, Fixups);
592226584Sdim}
593226584Sdim
594226584Sdim/// getBranchTargetOpValue - Return encoding info for 24-bit immediate branch
595226584Sdim/// target.
596226584Sdimuint32_t ARMMCCodeEmitter::
597226584SdimgetARMBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
598226584Sdim                          SmallVectorImpl<MCFixup> &Fixups) const {
599226584Sdim  const MCOperand MO = MI.getOperand(OpIdx);
600226584Sdim  if (MO.isExpr()) {
601226584Sdim    if (HasConditionalBranch(MI))
602226584Sdim      return ::getBranchTargetOpValue(MI, OpIdx,
603226584Sdim                                      ARM::fixup_arm_condbranch, Fixups);
604226584Sdim    return ::getBranchTargetOpValue(MI, OpIdx,
605226584Sdim                                    ARM::fixup_arm_uncondbranch, Fixups);
606226584Sdim  }
607226584Sdim
608226584Sdim  return MO.getImm() >> 2;
609226584Sdim}
610226584Sdim
611226584Sdimuint32_t ARMMCCodeEmitter::
612235633SdimgetARMBLTargetOpValue(const MCInst &MI, unsigned OpIdx,
613226584Sdim                          SmallVectorImpl<MCFixup> &Fixups) const {
614226584Sdim  const MCOperand MO = MI.getOperand(OpIdx);
615226584Sdim  if (MO.isExpr()) {
616226584Sdim    if (HasConditionalBranch(MI))
617235633Sdim      return ::getBranchTargetOpValue(MI, OpIdx,
618235633Sdim                                      ARM::fixup_arm_condbl, Fixups);
619235633Sdim    return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_uncondbl, Fixups);
620226584Sdim  }
621226584Sdim
622235633Sdim  return MO.getImm() >> 2;
623235633Sdim}
624235633Sdim
625235633Sdimuint32_t ARMMCCodeEmitter::
626235633SdimgetARMBLXTargetOpValue(const MCInst &MI, unsigned OpIdx,
627235633Sdim                          SmallVectorImpl<MCFixup> &Fixups) const {
628235633Sdim  const MCOperand MO = MI.getOperand(OpIdx);
629235633Sdim  if (MO.isExpr())
630235633Sdim    return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_blx, Fixups);
631235633Sdim
632226584Sdim  return MO.getImm() >> 1;
633226584Sdim}
634226584Sdim
635226584Sdim/// getUnconditionalBranchTargetOpValue - Return encoding info for 24-bit
636226584Sdim/// immediate branch target.
637226584Sdimuint32_t ARMMCCodeEmitter::
638226584SdimgetUnconditionalBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
639226584Sdim                       SmallVectorImpl<MCFixup> &Fixups) const {
640263509Sdim  unsigned Val = 0;
641263509Sdim  const MCOperand MO = MI.getOperand(OpIdx);
642263509Sdim
643263509Sdim  if(MO.isExpr())
644263509Sdim    return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_t2_uncondbranch, Fixups);
645263509Sdim  else
646263509Sdim    Val = MO.getImm() >> 1;
647263509Sdim
648226584Sdim  bool I  = (Val & 0x800000);
649226584Sdim  bool J1 = (Val & 0x400000);
650226584Sdim  bool J2 = (Val & 0x200000);
651226584Sdim  if (I ^ J1)
652226584Sdim    Val &= ~0x400000;
653226584Sdim  else
654226584Sdim    Val |= 0x400000;
655226584Sdim
656226584Sdim  if (I ^ J2)
657226584Sdim    Val &= ~0x200000;
658226584Sdim  else
659226584Sdim    Val |= 0x200000;
660226584Sdim
661226584Sdim  return Val;
662226584Sdim}
663226584Sdim
664245431Sdim/// getAdrLabelOpValue - Return encoding info for 12-bit shifted-immediate
665245431Sdim/// ADR label target.
666226584Sdimuint32_t ARMMCCodeEmitter::
667226584SdimgetAdrLabelOpValue(const MCInst &MI, unsigned OpIdx,
668226584Sdim                   SmallVectorImpl<MCFixup> &Fixups) const {
669226584Sdim  const MCOperand MO = MI.getOperand(OpIdx);
670226584Sdim  if (MO.isExpr())
671226584Sdim    return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_adr_pcrel_12,
672226584Sdim                                    Fixups);
673263509Sdim  int64_t offset = MO.getImm();
674226584Sdim  uint32_t Val = 0x2000;
675245431Sdim
676252723Sdim  int SoImmVal;
677245431Sdim  if (offset == INT32_MIN) {
678226584Sdim    Val = 0x1000;
679252723Sdim    SoImmVal = 0;
680245431Sdim  } else if (offset < 0) {
681245431Sdim    Val = 0x1000;
682226584Sdim    offset *= -1;
683252723Sdim    SoImmVal = ARM_AM::getSOImmVal(offset);
684252723Sdim    if(SoImmVal == -1) {
685252723Sdim      Val = 0x2000;
686252723Sdim      offset *= -1;
687252723Sdim      SoImmVal = ARM_AM::getSOImmVal(offset);
688252723Sdim    }
689252723Sdim  } else {
690252723Sdim    SoImmVal = ARM_AM::getSOImmVal(offset);
691252723Sdim    if(SoImmVal == -1) {
692252723Sdim      Val = 0x1000;
693252723Sdim      offset *= -1;
694252723Sdim      SoImmVal = ARM_AM::getSOImmVal(offset);
695252723Sdim    }
696226584Sdim  }
697245431Sdim
698245431Sdim  assert(SoImmVal != -1 && "Not a valid so_imm value!");
699245431Sdim
700245431Sdim  Val |= SoImmVal;
701226584Sdim  return Val;
702226584Sdim}
703226584Sdim
704245431Sdim/// getT2AdrLabelOpValue - Return encoding info for 12-bit immediate ADR label
705226584Sdim/// target.
706226584Sdimuint32_t ARMMCCodeEmitter::
707226584SdimgetT2AdrLabelOpValue(const MCInst &MI, unsigned OpIdx,
708226584Sdim                   SmallVectorImpl<MCFixup> &Fixups) const {
709226584Sdim  const MCOperand MO = MI.getOperand(OpIdx);
710226584Sdim  if (MO.isExpr())
711226584Sdim    return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_t2_adr_pcrel_12,
712226584Sdim                                    Fixups);
713226584Sdim  int32_t Val = MO.getImm();
714245431Sdim  if (Val == INT32_MIN)
715245431Sdim    Val = 0x1000;
716245431Sdim  else if (Val < 0) {
717226584Sdim    Val *= -1;
718226584Sdim    Val |= 0x1000;
719226584Sdim  }
720226584Sdim  return Val;
721226584Sdim}
722226584Sdim
723245431Sdim/// getThumbAdrLabelOpValue - Return encoding info for 8-bit immediate ADR label
724226584Sdim/// target.
725226584Sdimuint32_t ARMMCCodeEmitter::
726226584SdimgetThumbAdrLabelOpValue(const MCInst &MI, unsigned OpIdx,
727226584Sdim                   SmallVectorImpl<MCFixup> &Fixups) const {
728226584Sdim  const MCOperand MO = MI.getOperand(OpIdx);
729226584Sdim  if (MO.isExpr())
730226584Sdim    return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_thumb_adr_pcrel_10,
731226584Sdim                                    Fixups);
732226584Sdim  return MO.getImm();
733226584Sdim}
734226584Sdim
735226584Sdim/// getThumbAddrModeRegRegOpValue - Return encoding info for 'reg + reg'
736226584Sdim/// operand.
737226584Sdimuint32_t ARMMCCodeEmitter::
738226584SdimgetThumbAddrModeRegRegOpValue(const MCInst &MI, unsigned OpIdx,
739226584Sdim                              SmallVectorImpl<MCFixup> &) const {
740226584Sdim  // [Rn, Rm]
741226584Sdim  //   {5-3} = Rm
742226584Sdim  //   {2-0} = Rn
743226584Sdim  const MCOperand &MO1 = MI.getOperand(OpIdx);
744226584Sdim  const MCOperand &MO2 = MI.getOperand(OpIdx + 1);
745263509Sdim  unsigned Rn = CTX.getRegisterInfo()->getEncodingValue(MO1.getReg());
746263509Sdim  unsigned Rm = CTX.getRegisterInfo()->getEncodingValue(MO2.getReg());
747226584Sdim  return (Rm << 3) | Rn;
748226584Sdim}
749226584Sdim
750226584Sdim/// getAddrModeImm12OpValue - Return encoding info for 'reg +/- imm12' operand.
751226584Sdimuint32_t ARMMCCodeEmitter::
752226584SdimgetAddrModeImm12OpValue(const MCInst &MI, unsigned OpIdx,
753226584Sdim                        SmallVectorImpl<MCFixup> &Fixups) const {
754226584Sdim  // {17-13} = reg
755226584Sdim  // {12}    = (U)nsigned (add == '1', sub == '0')
756226584Sdim  // {11-0}  = imm12
757226584Sdim  unsigned Reg, Imm12;
758226584Sdim  bool isAdd = true;
759226584Sdim  // If The first operand isn't a register, we have a label reference.
760226584Sdim  const MCOperand &MO = MI.getOperand(OpIdx);
761226584Sdim  if (!MO.isReg()) {
762263509Sdim    Reg = CTX.getRegisterInfo()->getEncodingValue(ARM::PC);   // Rn is PC.
763226584Sdim    Imm12 = 0;
764226584Sdim
765226584Sdim    if (MO.isExpr()) {
766226584Sdim      const MCExpr *Expr = MO.getExpr();
767263509Sdim      isAdd = false ; // 'U' bit is set as part of the fixup.
768226584Sdim
769226584Sdim      MCFixupKind Kind;
770226584Sdim      if (isThumb2())
771226584Sdim        Kind = MCFixupKind(ARM::fixup_t2_ldst_pcrel_12);
772226584Sdim      else
773226584Sdim        Kind = MCFixupKind(ARM::fixup_arm_ldst_pcrel_12);
774235633Sdim      Fixups.push_back(MCFixup::Create(0, Expr, Kind, MI.getLoc()));
775226584Sdim
776226584Sdim      ++MCNumCPRelocations;
777226584Sdim    } else {
778226584Sdim      Reg = ARM::PC;
779226584Sdim      int32_t Offset = MO.getImm();
780263509Sdim      if (Offset == INT32_MIN) {
781263509Sdim        Offset = 0;
782263509Sdim        isAdd = false;
783263509Sdim      } else if (Offset < 0) {
784226584Sdim        Offset *= -1;
785226584Sdim        isAdd = false;
786226584Sdim      }
787226584Sdim      Imm12 = Offset;
788226584Sdim    }
789226584Sdim  } else
790226584Sdim    isAdd = EncodeAddrModeOpValues(MI, OpIdx, Reg, Imm12, Fixups);
791226584Sdim
792226584Sdim  uint32_t Binary = Imm12 & 0xfff;
793226584Sdim  // Immediate is always encoded as positive. The 'U' bit controls add vs sub.
794226584Sdim  if (isAdd)
795226584Sdim    Binary |= (1 << 12);
796226584Sdim  Binary |= (Reg << 13);
797226584Sdim  return Binary;
798226584Sdim}
799226584Sdim
800226584Sdim/// getT2Imm8s4OpValue - Return encoding info for
801226584Sdim/// '+/- imm8<<2' operand.
802226584Sdimuint32_t ARMMCCodeEmitter::
803226584SdimgetT2Imm8s4OpValue(const MCInst &MI, unsigned OpIdx,
804226584Sdim                   SmallVectorImpl<MCFixup> &Fixups) const {
805226584Sdim  // FIXME: The immediate operand should have already been encoded like this
806226584Sdim  // before ever getting here. The encoder method should just need to combine
807226584Sdim  // the MI operands for the register and the offset into a single
808226584Sdim  // representation for the complex operand in the .td file. This isn't just
809226584Sdim  // style, unfortunately. As-is, we can't represent the distinct encoding
810226584Sdim  // for #-0.
811226584Sdim
812226584Sdim  // {8}    = (U)nsigned (add == '1', sub == '0')
813226584Sdim  // {7-0}  = imm8
814226584Sdim  int32_t Imm8 = MI.getOperand(OpIdx).getImm();
815226584Sdim  bool isAdd = Imm8 >= 0;
816226584Sdim
817226584Sdim  // Immediate is always encoded as positive. The 'U' bit controls add vs sub.
818226584Sdim  if (Imm8 < 0)
819245431Sdim    Imm8 = -(uint32_t)Imm8;
820226584Sdim
821226584Sdim  // Scaled by 4.
822226584Sdim  Imm8 /= 4;
823226584Sdim
824226584Sdim  uint32_t Binary = Imm8 & 0xff;
825226584Sdim  // Immediate is always encoded as positive. The 'U' bit controls add vs sub.
826226584Sdim  if (isAdd)
827226584Sdim    Binary |= (1 << 8);
828226584Sdim  return Binary;
829226584Sdim}
830226584Sdim
831226584Sdim/// getT2AddrModeImm8s4OpValue - Return encoding info for
832226584Sdim/// 'reg +/- imm8<<2' operand.
833226584Sdimuint32_t ARMMCCodeEmitter::
834226584SdimgetT2AddrModeImm8s4OpValue(const MCInst &MI, unsigned OpIdx,
835226584Sdim                        SmallVectorImpl<MCFixup> &Fixups) const {
836226584Sdim  // {12-9} = reg
837226584Sdim  // {8}    = (U)nsigned (add == '1', sub == '0')
838226584Sdim  // {7-0}  = imm8
839226584Sdim  unsigned Reg, Imm8;
840226584Sdim  bool isAdd = true;
841226584Sdim  // If The first operand isn't a register, we have a label reference.
842226584Sdim  const MCOperand &MO = MI.getOperand(OpIdx);
843226584Sdim  if (!MO.isReg()) {
844263509Sdim    Reg = CTX.getRegisterInfo()->getEncodingValue(ARM::PC);   // Rn is PC.
845226584Sdim    Imm8 = 0;
846226584Sdim    isAdd = false ; // 'U' bit is set as part of the fixup.
847226584Sdim
848226584Sdim    assert(MO.isExpr() && "Unexpected machine operand type!");
849226584Sdim    const MCExpr *Expr = MO.getExpr();
850235633Sdim    MCFixupKind Kind = MCFixupKind(ARM::fixup_t2_pcrel_10);
851235633Sdim    Fixups.push_back(MCFixup::Create(0, Expr, Kind, MI.getLoc()));
852226584Sdim
853226584Sdim    ++MCNumCPRelocations;
854226584Sdim  } else
855226584Sdim    isAdd = EncodeAddrModeOpValues(MI, OpIdx, Reg, Imm8, Fixups);
856226584Sdim
857226584Sdim  // FIXME: The immediate operand should have already been encoded like this
858226584Sdim  // before ever getting here. The encoder method should just need to combine
859226584Sdim  // the MI operands for the register and the offset into a single
860226584Sdim  // representation for the complex operand in the .td file. This isn't just
861226584Sdim  // style, unfortunately. As-is, we can't represent the distinct encoding
862226584Sdim  // for #-0.
863226584Sdim  uint32_t Binary = (Imm8 >> 2) & 0xff;
864226584Sdim  // Immediate is always encoded as positive. The 'U' bit controls add vs sub.
865226584Sdim  if (isAdd)
866226584Sdim    Binary |= (1 << 8);
867226584Sdim  Binary |= (Reg << 9);
868226584Sdim  return Binary;
869226584Sdim}
870226584Sdim
871226584Sdim/// getT2AddrModeImm0_1020s4OpValue - Return encoding info for
872226584Sdim/// 'reg + imm8<<2' operand.
873226584Sdimuint32_t ARMMCCodeEmitter::
874226584SdimgetT2AddrModeImm0_1020s4OpValue(const MCInst &MI, unsigned OpIdx,
875226584Sdim                        SmallVectorImpl<MCFixup> &Fixups) const {
876226584Sdim  // {11-8} = reg
877226584Sdim  // {7-0}  = imm8
878226584Sdim  const MCOperand &MO = MI.getOperand(OpIdx);
879226584Sdim  const MCOperand &MO1 = MI.getOperand(OpIdx + 1);
880263509Sdim  unsigned Reg = CTX.getRegisterInfo()->getEncodingValue(MO.getReg());
881226584Sdim  unsigned Imm8 = MO1.getImm();
882226584Sdim  return (Reg << 8) | Imm8;
883226584Sdim}
884226584Sdim
885226584Sdim// FIXME: This routine assumes that a binary
886226584Sdim// expression will always result in a PCRel expression
887226584Sdim// In reality, its only true if one or more subexpressions
888226584Sdim// is itself a PCRel (i.e. "." in asm or some other pcrel construct)
889226584Sdim// but this is good enough for now.
890226584Sdimstatic bool EvaluateAsPCRel(const MCExpr *Expr) {
891226584Sdim  switch (Expr->getKind()) {
892235633Sdim  default: llvm_unreachable("Unexpected expression type");
893226584Sdim  case MCExpr::SymbolRef: return false;
894226584Sdim  case MCExpr::Binary: return true;
895226584Sdim  }
896226584Sdim}
897226584Sdim
898226584Sdimuint32_t
899226584SdimARMMCCodeEmitter::getHiLo16ImmOpValue(const MCInst &MI, unsigned OpIdx,
900226584Sdim                                      SmallVectorImpl<MCFixup> &Fixups) const {
901226584Sdim  // {20-16} = imm{15-12}
902226584Sdim  // {11-0}  = imm{11-0}
903226584Sdim  const MCOperand &MO = MI.getOperand(OpIdx);
904226584Sdim  if (MO.isImm())
905226584Sdim    // Hi / lo 16 bits already extracted during earlier passes.
906226584Sdim    return static_cast<unsigned>(MO.getImm());
907226584Sdim
908226584Sdim  // Handle :upper16: and :lower16: assembly prefixes.
909226584Sdim  const MCExpr *E = MO.getExpr();
910245431Sdim  MCFixupKind Kind;
911226584Sdim  if (E->getKind() == MCExpr::Target) {
912226584Sdim    const ARMMCExpr *ARM16Expr = cast<ARMMCExpr>(E);
913226584Sdim    E = ARM16Expr->getSubExpr();
914226584Sdim
915226584Sdim    switch (ARM16Expr->getKind()) {
916235633Sdim    default: llvm_unreachable("Unsupported ARMFixup");
917226584Sdim    case ARMMCExpr::VK_ARM_HI16:
918226584Sdim      if (!isTargetDarwin() && EvaluateAsPCRel(E))
919226584Sdim        Kind = MCFixupKind(isThumb2()
920226584Sdim                           ? ARM::fixup_t2_movt_hi16_pcrel
921226584Sdim                           : ARM::fixup_arm_movt_hi16_pcrel);
922226584Sdim      else
923226584Sdim        Kind = MCFixupKind(isThumb2()
924226584Sdim                           ? ARM::fixup_t2_movt_hi16
925226584Sdim                           : ARM::fixup_arm_movt_hi16);
926226584Sdim      break;
927226584Sdim    case ARMMCExpr::VK_ARM_LO16:
928226584Sdim      if (!isTargetDarwin() && EvaluateAsPCRel(E))
929226584Sdim        Kind = MCFixupKind(isThumb2()
930226584Sdim                           ? ARM::fixup_t2_movw_lo16_pcrel
931226584Sdim                           : ARM::fixup_arm_movw_lo16_pcrel);
932226584Sdim      else
933226584Sdim        Kind = MCFixupKind(isThumb2()
934226584Sdim                           ? ARM::fixup_t2_movw_lo16
935226584Sdim                           : ARM::fixup_arm_movw_lo16);
936226584Sdim      break;
937226584Sdim    }
938235633Sdim    Fixups.push_back(MCFixup::Create(0, E, Kind, MI.getLoc()));
939226584Sdim    return 0;
940245431Sdim  }
941245431Sdim  // If the expression doesn't have :upper16: or :lower16: on it,
942245431Sdim  // it's just a plain immediate expression, and those evaluate to
943245431Sdim  // the lower 16 bits of the expression regardless of whether
944245431Sdim  // we have a movt or a movw.
945245431Sdim  if (!isTargetDarwin() && EvaluateAsPCRel(E))
946245431Sdim    Kind = MCFixupKind(isThumb2()
947245431Sdim                       ? ARM::fixup_t2_movw_lo16_pcrel
948245431Sdim                       : ARM::fixup_arm_movw_lo16_pcrel);
949245431Sdim  else
950245431Sdim    Kind = MCFixupKind(isThumb2()
951245431Sdim                       ? ARM::fixup_t2_movw_lo16
952245431Sdim                       : ARM::fixup_arm_movw_lo16);
953245431Sdim  Fixups.push_back(MCFixup::Create(0, E, Kind, MI.getLoc()));
954245431Sdim  return 0;
955226584Sdim}
956226584Sdim
957226584Sdimuint32_t ARMMCCodeEmitter::
958226584SdimgetLdStSORegOpValue(const MCInst &MI, unsigned OpIdx,
959226584Sdim                    SmallVectorImpl<MCFixup> &Fixups) const {
960226584Sdim  const MCOperand &MO = MI.getOperand(OpIdx);
961226584Sdim  const MCOperand &MO1 = MI.getOperand(OpIdx+1);
962226584Sdim  const MCOperand &MO2 = MI.getOperand(OpIdx+2);
963263509Sdim  unsigned Rn = CTX.getRegisterInfo()->getEncodingValue(MO.getReg());
964263509Sdim  unsigned Rm = CTX.getRegisterInfo()->getEncodingValue(MO1.getReg());
965226584Sdim  unsigned ShImm = ARM_AM::getAM2Offset(MO2.getImm());
966226584Sdim  bool isAdd = ARM_AM::getAM2Op(MO2.getImm()) == ARM_AM::add;
967226584Sdim  ARM_AM::ShiftOpc ShOp = ARM_AM::getAM2ShiftOpc(MO2.getImm());
968226584Sdim  unsigned SBits = getShiftOp(ShOp);
969226584Sdim
970245431Sdim  // While "lsr #32" and "asr #32" exist, they are encoded with a 0 in the shift
971245431Sdim  // amount. However, it would be an easy mistake to make so check here.
972245431Sdim  assert((ShImm & ~0x1f) == 0 && "Out of range shift amount");
973245431Sdim
974226584Sdim  // {16-13} = Rn
975226584Sdim  // {12}    = isAdd
976226584Sdim  // {11-0}  = shifter
977226584Sdim  //  {3-0}  = Rm
978226584Sdim  //  {4}    = 0
979226584Sdim  //  {6-5}  = type
980226584Sdim  //  {11-7} = imm
981226584Sdim  uint32_t Binary = Rm;
982226584Sdim  Binary |= Rn << 13;
983226584Sdim  Binary |= SBits << 5;
984226584Sdim  Binary |= ShImm << 7;
985226584Sdim  if (isAdd)
986226584Sdim    Binary |= 1 << 12;
987226584Sdim  return Binary;
988226584Sdim}
989226584Sdim
990226584Sdimuint32_t ARMMCCodeEmitter::
991226584SdimgetAddrMode2OpValue(const MCInst &MI, unsigned OpIdx,
992226584Sdim                    SmallVectorImpl<MCFixup> &Fixups) const {
993226584Sdim  // {17-14}  Rn
994226584Sdim  // {13}     1 == imm12, 0 == Rm
995226584Sdim  // {12}     isAdd
996226584Sdim  // {11-0}   imm12/Rm
997226584Sdim  const MCOperand &MO = MI.getOperand(OpIdx);
998263509Sdim  unsigned Rn = CTX.getRegisterInfo()->getEncodingValue(MO.getReg());
999226584Sdim  uint32_t Binary = getAddrMode2OffsetOpValue(MI, OpIdx + 1, Fixups);
1000226584Sdim  Binary |= Rn << 14;
1001226584Sdim  return Binary;
1002226584Sdim}
1003226584Sdim
1004226584Sdimuint32_t ARMMCCodeEmitter::
1005226584SdimgetAddrMode2OffsetOpValue(const MCInst &MI, unsigned OpIdx,
1006226584Sdim                          SmallVectorImpl<MCFixup> &Fixups) const {
1007226584Sdim  // {13}     1 == imm12, 0 == Rm
1008226584Sdim  // {12}     isAdd
1009226584Sdim  // {11-0}   imm12/Rm
1010226584Sdim  const MCOperand &MO = MI.getOperand(OpIdx);
1011226584Sdim  const MCOperand &MO1 = MI.getOperand(OpIdx+1);
1012226584Sdim  unsigned Imm = MO1.getImm();
1013226584Sdim  bool isAdd = ARM_AM::getAM2Op(Imm) == ARM_AM::add;
1014226584Sdim  bool isReg = MO.getReg() != 0;
1015226584Sdim  uint32_t Binary = ARM_AM::getAM2Offset(Imm);
1016226584Sdim  // if reg +/- reg, Rm will be non-zero. Otherwise, we have reg +/- imm12
1017226584Sdim  if (isReg) {
1018226584Sdim    ARM_AM::ShiftOpc ShOp = ARM_AM::getAM2ShiftOpc(Imm);
1019226584Sdim    Binary <<= 7;                    // Shift amount is bits [11:7]
1020226584Sdim    Binary |= getShiftOp(ShOp) << 5; // Shift type is bits [6:5]
1021263509Sdim    Binary |= CTX.getRegisterInfo()->getEncodingValue(MO.getReg()); // Rm is bits [3:0]
1022226584Sdim  }
1023226584Sdim  return Binary | (isAdd << 12) | (isReg << 13);
1024226584Sdim}
1025226584Sdim
1026226584Sdimuint32_t ARMMCCodeEmitter::
1027226584SdimgetPostIdxRegOpValue(const MCInst &MI, unsigned OpIdx,
1028226584Sdim                     SmallVectorImpl<MCFixup> &Fixups) const {
1029226584Sdim  // {4}      isAdd
1030226584Sdim  // {3-0}    Rm
1031226584Sdim  const MCOperand &MO = MI.getOperand(OpIdx);
1032226584Sdim  const MCOperand &MO1 = MI.getOperand(OpIdx+1);
1033226584Sdim  bool isAdd = MO1.getImm() != 0;
1034263509Sdim  return CTX.getRegisterInfo()->getEncodingValue(MO.getReg()) | (isAdd << 4);
1035226584Sdim}
1036226584Sdim
1037226584Sdimuint32_t ARMMCCodeEmitter::
1038226584SdimgetAddrMode3OffsetOpValue(const MCInst &MI, unsigned OpIdx,
1039226584Sdim                          SmallVectorImpl<MCFixup> &Fixups) const {
1040226584Sdim  // {9}      1 == imm8, 0 == Rm
1041226584Sdim  // {8}      isAdd
1042226584Sdim  // {7-4}    imm7_4/zero
1043226584Sdim  // {3-0}    imm3_0/Rm
1044226584Sdim  const MCOperand &MO = MI.getOperand(OpIdx);
1045226584Sdim  const MCOperand &MO1 = MI.getOperand(OpIdx+1);
1046226584Sdim  unsigned Imm = MO1.getImm();
1047226584Sdim  bool isAdd = ARM_AM::getAM3Op(Imm) == ARM_AM::add;
1048226584Sdim  bool isImm = MO.getReg() == 0;
1049226584Sdim  uint32_t Imm8 = ARM_AM::getAM3Offset(Imm);
1050226584Sdim  // if reg +/- reg, Rm will be non-zero. Otherwise, we have reg +/- imm8
1051226584Sdim  if (!isImm)
1052263509Sdim    Imm8 = CTX.getRegisterInfo()->getEncodingValue(MO.getReg());
1053226584Sdim  return Imm8 | (isAdd << 8) | (isImm << 9);
1054226584Sdim}
1055226584Sdim
1056226584Sdimuint32_t ARMMCCodeEmitter::
1057226584SdimgetAddrMode3OpValue(const MCInst &MI, unsigned OpIdx,
1058226584Sdim                    SmallVectorImpl<MCFixup> &Fixups) const {
1059226584Sdim  // {13}     1 == imm8, 0 == Rm
1060226584Sdim  // {12-9}   Rn
1061226584Sdim  // {8}      isAdd
1062226584Sdim  // {7-4}    imm7_4/zero
1063226584Sdim  // {3-0}    imm3_0/Rm
1064226584Sdim  const MCOperand &MO = MI.getOperand(OpIdx);
1065226584Sdim  const MCOperand &MO1 = MI.getOperand(OpIdx+1);
1066226584Sdim  const MCOperand &MO2 = MI.getOperand(OpIdx+2);
1067235633Sdim
1068235633Sdim  // If The first operand isn't a register, we have a label reference.
1069235633Sdim  if (!MO.isReg()) {
1070263509Sdim    unsigned Rn = CTX.getRegisterInfo()->getEncodingValue(ARM::PC);   // Rn is PC.
1071235633Sdim
1072235633Sdim    assert(MO.isExpr() && "Unexpected machine operand type!");
1073235633Sdim    const MCExpr *Expr = MO.getExpr();
1074235633Sdim    MCFixupKind Kind = MCFixupKind(ARM::fixup_arm_pcrel_10_unscaled);
1075235633Sdim    Fixups.push_back(MCFixup::Create(0, Expr, Kind, MI.getLoc()));
1076235633Sdim
1077235633Sdim    ++MCNumCPRelocations;
1078235633Sdim    return (Rn << 9) | (1 << 13);
1079235633Sdim  }
1080263509Sdim  unsigned Rn = CTX.getRegisterInfo()->getEncodingValue(MO.getReg());
1081226584Sdim  unsigned Imm = MO2.getImm();
1082226584Sdim  bool isAdd = ARM_AM::getAM3Op(Imm) == ARM_AM::add;
1083226584Sdim  bool isImm = MO1.getReg() == 0;
1084226584Sdim  uint32_t Imm8 = ARM_AM::getAM3Offset(Imm);
1085226584Sdim  // if reg +/- reg, Rm will be non-zero. Otherwise, we have reg +/- imm8
1086226584Sdim  if (!isImm)
1087263509Sdim    Imm8 = CTX.getRegisterInfo()->getEncodingValue(MO1.getReg());
1088226584Sdim  return (Rn << 9) | Imm8 | (isAdd << 8) | (isImm << 13);
1089226584Sdim}
1090226584Sdim
1091226584Sdim/// getAddrModeThumbSPOpValue - Encode the t_addrmode_sp operands.
1092226584Sdimuint32_t ARMMCCodeEmitter::
1093226584SdimgetAddrModeThumbSPOpValue(const MCInst &MI, unsigned OpIdx,
1094226584Sdim                          SmallVectorImpl<MCFixup> &Fixups) const {
1095226584Sdim  // [SP, #imm]
1096226584Sdim  //   {7-0} = imm8
1097226584Sdim  const MCOperand &MO1 = MI.getOperand(OpIdx + 1);
1098226584Sdim  assert(MI.getOperand(OpIdx).getReg() == ARM::SP &&
1099226584Sdim         "Unexpected base register!");
1100226584Sdim
1101226584Sdim  // The immediate is already shifted for the implicit zeroes, so no change
1102226584Sdim  // here.
1103226584Sdim  return MO1.getImm() & 0xff;
1104226584Sdim}
1105226584Sdim
1106226584Sdim/// getAddrModeISOpValue - Encode the t_addrmode_is# operands.
1107226584Sdimuint32_t ARMMCCodeEmitter::
1108226584SdimgetAddrModeISOpValue(const MCInst &MI, unsigned OpIdx,
1109226584Sdim                     SmallVectorImpl<MCFixup> &Fixups) const {
1110226584Sdim  // [Rn, #imm]
1111226584Sdim  //   {7-3} = imm5
1112226584Sdim  //   {2-0} = Rn
1113226584Sdim  const MCOperand &MO = MI.getOperand(OpIdx);
1114226584Sdim  const MCOperand &MO1 = MI.getOperand(OpIdx + 1);
1115263509Sdim  unsigned Rn = CTX.getRegisterInfo()->getEncodingValue(MO.getReg());
1116226584Sdim  unsigned Imm5 = MO1.getImm();
1117226584Sdim  return ((Imm5 & 0x1f) << 3) | Rn;
1118226584Sdim}
1119226584Sdim
1120226584Sdim/// getAddrModePCOpValue - Return encoding for t_addrmode_pc operands.
1121226584Sdimuint32_t ARMMCCodeEmitter::
1122226584SdimgetAddrModePCOpValue(const MCInst &MI, unsigned OpIdx,
1123226584Sdim                     SmallVectorImpl<MCFixup> &Fixups) const {
1124226584Sdim  const MCOperand MO = MI.getOperand(OpIdx);
1125226584Sdim  if (MO.isExpr())
1126226584Sdim    return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_thumb_cp, Fixups);
1127226584Sdim  return (MO.getImm() >> 2);
1128226584Sdim}
1129226584Sdim
1130226584Sdim/// getAddrMode5OpValue - Return encoding info for 'reg +/- imm10' operand.
1131226584Sdimuint32_t ARMMCCodeEmitter::
1132226584SdimgetAddrMode5OpValue(const MCInst &MI, unsigned OpIdx,
1133226584Sdim                    SmallVectorImpl<MCFixup> &Fixups) const {
1134226584Sdim  // {12-9} = reg
1135226584Sdim  // {8}    = (U)nsigned (add == '1', sub == '0')
1136226584Sdim  // {7-0}  = imm8
1137226584Sdim  unsigned Reg, Imm8;
1138226584Sdim  bool isAdd;
1139226584Sdim  // If The first operand isn't a register, we have a label reference.
1140226584Sdim  const MCOperand &MO = MI.getOperand(OpIdx);
1141226584Sdim  if (!MO.isReg()) {
1142263509Sdim    Reg = CTX.getRegisterInfo()->getEncodingValue(ARM::PC);   // Rn is PC.
1143226584Sdim    Imm8 = 0;
1144226584Sdim    isAdd = false; // 'U' bit is handled as part of the fixup.
1145226584Sdim
1146226584Sdim    assert(MO.isExpr() && "Unexpected machine operand type!");
1147226584Sdim    const MCExpr *Expr = MO.getExpr();
1148226584Sdim    MCFixupKind Kind;
1149226584Sdim    if (isThumb2())
1150226584Sdim      Kind = MCFixupKind(ARM::fixup_t2_pcrel_10);
1151226584Sdim    else
1152226584Sdim      Kind = MCFixupKind(ARM::fixup_arm_pcrel_10);
1153235633Sdim    Fixups.push_back(MCFixup::Create(0, Expr, Kind, MI.getLoc()));
1154226584Sdim
1155226584Sdim    ++MCNumCPRelocations;
1156226584Sdim  } else {
1157226584Sdim    EncodeAddrModeOpValues(MI, OpIdx, Reg, Imm8, Fixups);
1158226584Sdim    isAdd = ARM_AM::getAM5Op(Imm8) == ARM_AM::add;
1159226584Sdim  }
1160226584Sdim
1161226584Sdim  uint32_t Binary = ARM_AM::getAM5Offset(Imm8);
1162226584Sdim  // Immediate is always encoded as positive. The 'U' bit controls add vs sub.
1163226584Sdim  if (isAdd)
1164226584Sdim    Binary |= (1 << 8);
1165226584Sdim  Binary |= (Reg << 9);
1166226584Sdim  return Binary;
1167226584Sdim}
1168226584Sdim
1169226584Sdimunsigned ARMMCCodeEmitter::
1170226584SdimgetSORegRegOpValue(const MCInst &MI, unsigned OpIdx,
1171226584Sdim                SmallVectorImpl<MCFixup> &Fixups) const {
1172226584Sdim  // Sub-operands are [reg, reg, imm]. The first register is Rm, the reg to be
1173226584Sdim  // shifted. The second is Rs, the amount to shift by, and the third specifies
1174226584Sdim  // the type of the shift.
1175226584Sdim  //
1176226584Sdim  // {3-0} = Rm.
1177226584Sdim  // {4}   = 1
1178226584Sdim  // {6-5} = type
1179226584Sdim  // {11-8} = Rs
1180226584Sdim  // {7}    = 0
1181226584Sdim
1182226584Sdim  const MCOperand &MO  = MI.getOperand(OpIdx);
1183226584Sdim  const MCOperand &MO1 = MI.getOperand(OpIdx + 1);
1184226584Sdim  const MCOperand &MO2 = MI.getOperand(OpIdx + 2);
1185226584Sdim  ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(MO2.getImm());
1186226584Sdim
1187226584Sdim  // Encode Rm.
1188263509Sdim  unsigned Binary = CTX.getRegisterInfo()->getEncodingValue(MO.getReg());
1189226584Sdim
1190226584Sdim  // Encode the shift opcode.
1191226584Sdim  unsigned SBits = 0;
1192226584Sdim  unsigned Rs = MO1.getReg();
1193226584Sdim  if (Rs) {
1194226584Sdim    // Set shift operand (bit[7:4]).
1195226584Sdim    // LSL - 0001
1196226584Sdim    // LSR - 0011
1197226584Sdim    // ASR - 0101
1198226584Sdim    // ROR - 0111
1199226584Sdim    switch (SOpc) {
1200226584Sdim    default: llvm_unreachable("Unknown shift opc!");
1201226584Sdim    case ARM_AM::lsl: SBits = 0x1; break;
1202226584Sdim    case ARM_AM::lsr: SBits = 0x3; break;
1203226584Sdim    case ARM_AM::asr: SBits = 0x5; break;
1204226584Sdim    case ARM_AM::ror: SBits = 0x7; break;
1205226584Sdim    }
1206226584Sdim  }
1207226584Sdim
1208226584Sdim  Binary |= SBits << 4;
1209226584Sdim
1210226584Sdim  // Encode the shift operation Rs.
1211226584Sdim  // Encode Rs bit[11:8].
1212226584Sdim  assert(ARM_AM::getSORegOffset(MO2.getImm()) == 0);
1213263509Sdim  return Binary | (CTX.getRegisterInfo()->getEncodingValue(Rs) << ARMII::RegRsShift);
1214226584Sdim}
1215226584Sdim
1216226584Sdimunsigned ARMMCCodeEmitter::
1217226584SdimgetSORegImmOpValue(const MCInst &MI, unsigned OpIdx,
1218226584Sdim                SmallVectorImpl<MCFixup> &Fixups) const {
1219226584Sdim  // Sub-operands are [reg, imm]. The first register is Rm, the reg to be
1220226584Sdim  // shifted. The second is the amount to shift by.
1221226584Sdim  //
1222226584Sdim  // {3-0} = Rm.
1223226584Sdim  // {4}   = 0
1224226584Sdim  // {6-5} = type
1225226584Sdim  // {11-7} = imm
1226226584Sdim
1227226584Sdim  const MCOperand &MO  = MI.getOperand(OpIdx);
1228226584Sdim  const MCOperand &MO1 = MI.getOperand(OpIdx + 1);
1229226584Sdim  ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(MO1.getImm());
1230226584Sdim
1231226584Sdim  // Encode Rm.
1232263509Sdim  unsigned Binary = CTX.getRegisterInfo()->getEncodingValue(MO.getReg());
1233226584Sdim
1234226584Sdim  // Encode the shift opcode.
1235226584Sdim  unsigned SBits = 0;
1236226584Sdim
1237226584Sdim  // Set shift operand (bit[6:4]).
1238226584Sdim  // LSL - 000
1239226584Sdim  // LSR - 010
1240226584Sdim  // ASR - 100
1241226584Sdim  // ROR - 110
1242226584Sdim  // RRX - 110 and bit[11:8] clear.
1243226584Sdim  switch (SOpc) {
1244226584Sdim  default: llvm_unreachable("Unknown shift opc!");
1245226584Sdim  case ARM_AM::lsl: SBits = 0x0; break;
1246226584Sdim  case ARM_AM::lsr: SBits = 0x2; break;
1247226584Sdim  case ARM_AM::asr: SBits = 0x4; break;
1248226584Sdim  case ARM_AM::ror: SBits = 0x6; break;
1249226584Sdim  case ARM_AM::rrx:
1250226584Sdim    Binary |= 0x60;
1251226584Sdim    return Binary;
1252226584Sdim  }
1253226584Sdim
1254226584Sdim  // Encode shift_imm bit[11:7].
1255226584Sdim  Binary |= SBits << 4;
1256226584Sdim  unsigned Offset = ARM_AM::getSORegOffset(MO1.getImm());
1257245431Sdim  assert(Offset < 32 && "Offset must be in range 0-31!");
1258226584Sdim  return Binary | (Offset << 7);
1259226584Sdim}
1260226584Sdim
1261226584Sdim
1262226584Sdimunsigned ARMMCCodeEmitter::
1263226584SdimgetT2AddrModeSORegOpValue(const MCInst &MI, unsigned OpNum,
1264226584Sdim                SmallVectorImpl<MCFixup> &Fixups) const {
1265226584Sdim  const MCOperand &MO1 = MI.getOperand(OpNum);
1266226584Sdim  const MCOperand &MO2 = MI.getOperand(OpNum+1);
1267226584Sdim  const MCOperand &MO3 = MI.getOperand(OpNum+2);
1268226584Sdim
1269226584Sdim  // Encoded as [Rn, Rm, imm].
1270226584Sdim  // FIXME: Needs fixup support.
1271263509Sdim  unsigned Value = CTX.getRegisterInfo()->getEncodingValue(MO1.getReg());
1272226584Sdim  Value <<= 4;
1273263509Sdim  Value |= CTX.getRegisterInfo()->getEncodingValue(MO2.getReg());
1274226584Sdim  Value <<= 2;
1275226584Sdim  Value |= MO3.getImm();
1276226584Sdim
1277226584Sdim  return Value;
1278226584Sdim}
1279226584Sdim
1280226584Sdimunsigned ARMMCCodeEmitter::
1281226584SdimgetT2AddrModeImm8OpValue(const MCInst &MI, unsigned OpNum,
1282226584Sdim                         SmallVectorImpl<MCFixup> &Fixups) const {
1283226584Sdim  const MCOperand &MO1 = MI.getOperand(OpNum);
1284226584Sdim  const MCOperand &MO2 = MI.getOperand(OpNum+1);
1285226584Sdim
1286226584Sdim  // FIXME: Needs fixup support.
1287263509Sdim  unsigned Value = CTX.getRegisterInfo()->getEncodingValue(MO1.getReg());
1288226584Sdim
1289226584Sdim  // Even though the immediate is 8 bits long, we need 9 bits in order
1290226584Sdim  // to represent the (inverse of the) sign bit.
1291226584Sdim  Value <<= 9;
1292226584Sdim  int32_t tmp = (int32_t)MO2.getImm();
1293226584Sdim  if (tmp < 0)
1294226584Sdim    tmp = abs(tmp);
1295226584Sdim  else
1296226584Sdim    Value |= 256; // Set the ADD bit
1297226584Sdim  Value |= tmp & 255;
1298226584Sdim  return Value;
1299226584Sdim}
1300226584Sdim
1301226584Sdimunsigned ARMMCCodeEmitter::
1302226584SdimgetT2AddrModeImm8OffsetOpValue(const MCInst &MI, unsigned OpNum,
1303226584Sdim                         SmallVectorImpl<MCFixup> &Fixups) const {
1304226584Sdim  const MCOperand &MO1 = MI.getOperand(OpNum);
1305226584Sdim
1306226584Sdim  // FIXME: Needs fixup support.
1307226584Sdim  unsigned Value = 0;
1308226584Sdim  int32_t tmp = (int32_t)MO1.getImm();
1309226584Sdim  if (tmp < 0)
1310226584Sdim    tmp = abs(tmp);
1311226584Sdim  else
1312226584Sdim    Value |= 256; // Set the ADD bit
1313226584Sdim  Value |= tmp & 255;
1314226584Sdim  return Value;
1315226584Sdim}
1316226584Sdim
1317226584Sdimunsigned ARMMCCodeEmitter::
1318226584SdimgetT2AddrModeImm12OffsetOpValue(const MCInst &MI, unsigned OpNum,
1319226584Sdim                         SmallVectorImpl<MCFixup> &Fixups) const {
1320226584Sdim  const MCOperand &MO1 = MI.getOperand(OpNum);
1321226584Sdim
1322226584Sdim  // FIXME: Needs fixup support.
1323226584Sdim  unsigned Value = 0;
1324226584Sdim  int32_t tmp = (int32_t)MO1.getImm();
1325226584Sdim  if (tmp < 0)
1326226584Sdim    tmp = abs(tmp);
1327226584Sdim  else
1328226584Sdim    Value |= 4096; // Set the ADD bit
1329226584Sdim  Value |= tmp & 4095;
1330226584Sdim  return Value;
1331226584Sdim}
1332226584Sdim
1333226584Sdimunsigned ARMMCCodeEmitter::
1334226584SdimgetT2SORegOpValue(const MCInst &MI, unsigned OpIdx,
1335226584Sdim                SmallVectorImpl<MCFixup> &Fixups) const {
1336226584Sdim  // Sub-operands are [reg, imm]. The first register is Rm, the reg to be
1337226584Sdim  // shifted. The second is the amount to shift by.
1338226584Sdim  //
1339226584Sdim  // {3-0} = Rm.
1340226584Sdim  // {4}   = 0
1341226584Sdim  // {6-5} = type
1342226584Sdim  // {11-7} = imm
1343226584Sdim
1344226584Sdim  const MCOperand &MO  = MI.getOperand(OpIdx);
1345226584Sdim  const MCOperand &MO1 = MI.getOperand(OpIdx + 1);
1346226584Sdim  ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(MO1.getImm());
1347226584Sdim
1348226584Sdim  // Encode Rm.
1349263509Sdim  unsigned Binary = CTX.getRegisterInfo()->getEncodingValue(MO.getReg());
1350226584Sdim
1351226584Sdim  // Encode the shift opcode.
1352226584Sdim  unsigned SBits = 0;
1353226584Sdim  // Set shift operand (bit[6:4]).
1354226584Sdim  // LSL - 000
1355226584Sdim  // LSR - 010
1356226584Sdim  // ASR - 100
1357226584Sdim  // ROR - 110
1358226584Sdim  switch (SOpc) {
1359226584Sdim  default: llvm_unreachable("Unknown shift opc!");
1360226584Sdim  case ARM_AM::lsl: SBits = 0x0; break;
1361226584Sdim  case ARM_AM::lsr: SBits = 0x2; break;
1362226584Sdim  case ARM_AM::asr: SBits = 0x4; break;
1363226584Sdim  case ARM_AM::rrx: // FALLTHROUGH
1364226584Sdim  case ARM_AM::ror: SBits = 0x6; break;
1365226584Sdim  }
1366226584Sdim
1367226584Sdim  Binary |= SBits << 4;
1368226584Sdim  if (SOpc == ARM_AM::rrx)
1369226584Sdim    return Binary;
1370226584Sdim
1371226584Sdim  // Encode shift_imm bit[11:7].
1372226584Sdim  return Binary | ARM_AM::getSORegOffset(MO1.getImm()) << 7;
1373226584Sdim}
1374226584Sdim
1375226584Sdimunsigned ARMMCCodeEmitter::
1376226584SdimgetBitfieldInvertedMaskOpValue(const MCInst &MI, unsigned Op,
1377226584Sdim                               SmallVectorImpl<MCFixup> &Fixups) const {
1378226584Sdim  // 10 bits. lower 5 bits are are the lsb of the mask, high five bits are the
1379226584Sdim  // msb of the mask.
1380226584Sdim  const MCOperand &MO = MI.getOperand(Op);
1381226584Sdim  uint32_t v = ~MO.getImm();
1382263509Sdim  uint32_t lsb = countTrailingZeros(v);
1383263509Sdim  uint32_t msb = (32 - countLeadingZeros (v)) - 1;
1384226584Sdim  assert (v != 0 && lsb < 32 && msb < 32 && "Illegal bitfield mask!");
1385226584Sdim  return lsb | (msb << 5);
1386226584Sdim}
1387226584Sdim
1388226584Sdimunsigned ARMMCCodeEmitter::
1389226584SdimgetRegisterListOpValue(const MCInst &MI, unsigned Op,
1390226584Sdim                       SmallVectorImpl<MCFixup> &Fixups) const {
1391226584Sdim  // VLDM/VSTM:
1392226584Sdim  //   {12-8} = Vd
1393226584Sdim  //   {7-0}  = Number of registers
1394226584Sdim  //
1395226584Sdim  // LDM/STM:
1396226584Sdim  //   {15-0}  = Bitfield of GPRs.
1397226584Sdim  unsigned Reg = MI.getOperand(Op).getReg();
1398235633Sdim  bool SPRRegs = ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg);
1399235633Sdim  bool DPRRegs = ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg);
1400226584Sdim
1401226584Sdim  unsigned Binary = 0;
1402226584Sdim
1403226584Sdim  if (SPRRegs || DPRRegs) {
1404226584Sdim    // VLDM/VSTM
1405263509Sdim    unsigned RegNo = CTX.getRegisterInfo()->getEncodingValue(Reg);
1406226584Sdim    unsigned NumRegs = (MI.getNumOperands() - Op) & 0xff;
1407226584Sdim    Binary |= (RegNo & 0x1f) << 8;
1408226584Sdim    if (SPRRegs)
1409226584Sdim      Binary |= NumRegs;
1410226584Sdim    else
1411226584Sdim      Binary |= NumRegs * 2;
1412226584Sdim  } else {
1413226584Sdim    for (unsigned I = Op, E = MI.getNumOperands(); I < E; ++I) {
1414263509Sdim      unsigned RegNo = CTX.getRegisterInfo()->getEncodingValue(MI.getOperand(I).getReg());
1415226584Sdim      Binary |= 1 << RegNo;
1416226584Sdim    }
1417226584Sdim  }
1418226584Sdim
1419226584Sdim  return Binary;
1420226584Sdim}
1421226584Sdim
1422226584Sdim/// getAddrMode6AddressOpValue - Encode an addrmode6 register number along
1423226584Sdim/// with the alignment operand.
1424226584Sdimunsigned ARMMCCodeEmitter::
1425226584SdimgetAddrMode6AddressOpValue(const MCInst &MI, unsigned Op,
1426226584Sdim                           SmallVectorImpl<MCFixup> &Fixups) const {
1427226584Sdim  const MCOperand &Reg = MI.getOperand(Op);
1428226584Sdim  const MCOperand &Imm = MI.getOperand(Op + 1);
1429226584Sdim
1430263509Sdim  unsigned RegNo = CTX.getRegisterInfo()->getEncodingValue(Reg.getReg());
1431226584Sdim  unsigned Align = 0;
1432226584Sdim
1433226584Sdim  switch (Imm.getImm()) {
1434226584Sdim  default: break;
1435226584Sdim  case 2:
1436226584Sdim  case 4:
1437226584Sdim  case 8:  Align = 0x01; break;
1438226584Sdim  case 16: Align = 0x02; break;
1439226584Sdim  case 32: Align = 0x03; break;
1440226584Sdim  }
1441226584Sdim
1442226584Sdim  return RegNo | (Align << 4);
1443226584Sdim}
1444226584Sdim
1445226584Sdim/// getAddrMode6OneLane32AddressOpValue - Encode an addrmode6 register number
1446226584Sdim/// along  with the alignment operand for use in VST1 and VLD1 with size 32.
1447226584Sdimunsigned ARMMCCodeEmitter::
1448226584SdimgetAddrMode6OneLane32AddressOpValue(const MCInst &MI, unsigned Op,
1449226584Sdim                                    SmallVectorImpl<MCFixup> &Fixups) const {
1450226584Sdim  const MCOperand &Reg = MI.getOperand(Op);
1451226584Sdim  const MCOperand &Imm = MI.getOperand(Op + 1);
1452226584Sdim
1453263509Sdim  unsigned RegNo = CTX.getRegisterInfo()->getEncodingValue(Reg.getReg());
1454226584Sdim  unsigned Align = 0;
1455226584Sdim
1456226584Sdim  switch (Imm.getImm()) {
1457226584Sdim  default: break;
1458226584Sdim  case 8:
1459235633Sdim  case 16:
1460235633Sdim  case 32: // Default '0' value for invalid alignments of 8, 16, 32 bytes.
1461235633Sdim  case 2: Align = 0x00; break;
1462235633Sdim  case 4: Align = 0x03; break;
1463226584Sdim  }
1464226584Sdim
1465226584Sdim  return RegNo | (Align << 4);
1466226584Sdim}
1467226584Sdim
1468226584Sdim
1469226584Sdim/// getAddrMode6DupAddressOpValue - Encode an addrmode6 register number and
1470226584Sdim/// alignment operand for use in VLD-dup instructions.  This is the same as
1471226584Sdim/// getAddrMode6AddressOpValue except for the alignment encoding, which is
1472226584Sdim/// different for VLD4-dup.
1473226584Sdimunsigned ARMMCCodeEmitter::
1474226584SdimgetAddrMode6DupAddressOpValue(const MCInst &MI, unsigned Op,
1475226584Sdim                              SmallVectorImpl<MCFixup> &Fixups) const {
1476226584Sdim  const MCOperand &Reg = MI.getOperand(Op);
1477226584Sdim  const MCOperand &Imm = MI.getOperand(Op + 1);
1478226584Sdim
1479263509Sdim  unsigned RegNo = CTX.getRegisterInfo()->getEncodingValue(Reg.getReg());
1480226584Sdim  unsigned Align = 0;
1481226584Sdim
1482226584Sdim  switch (Imm.getImm()) {
1483226584Sdim  default: break;
1484226584Sdim  case 2:
1485226584Sdim  case 4:
1486226584Sdim  case 8:  Align = 0x01; break;
1487226584Sdim  case 16: Align = 0x03; break;
1488226584Sdim  }
1489226584Sdim
1490226584Sdim  return RegNo | (Align << 4);
1491226584Sdim}
1492226584Sdim
1493226584Sdimunsigned ARMMCCodeEmitter::
1494226584SdimgetAddrMode6OffsetOpValue(const MCInst &MI, unsigned Op,
1495226584Sdim                          SmallVectorImpl<MCFixup> &Fixups) const {
1496226584Sdim  const MCOperand &MO = MI.getOperand(Op);
1497226584Sdim  if (MO.getReg() == 0) return 0x0D;
1498263509Sdim  return CTX.getRegisterInfo()->getEncodingValue(MO.getReg());
1499226584Sdim}
1500226584Sdim
1501226584Sdimunsigned ARMMCCodeEmitter::
1502226584SdimgetShiftRight8Imm(const MCInst &MI, unsigned Op,
1503226584Sdim                  SmallVectorImpl<MCFixup> &Fixups) const {
1504226584Sdim  return 8 - MI.getOperand(Op).getImm();
1505226584Sdim}
1506226584Sdim
1507226584Sdimunsigned ARMMCCodeEmitter::
1508226584SdimgetShiftRight16Imm(const MCInst &MI, unsigned Op,
1509226584Sdim                   SmallVectorImpl<MCFixup> &Fixups) const {
1510226584Sdim  return 16 - MI.getOperand(Op).getImm();
1511226584Sdim}
1512226584Sdim
1513226584Sdimunsigned ARMMCCodeEmitter::
1514226584SdimgetShiftRight32Imm(const MCInst &MI, unsigned Op,
1515226584Sdim                   SmallVectorImpl<MCFixup> &Fixups) const {
1516226584Sdim  return 32 - MI.getOperand(Op).getImm();
1517226584Sdim}
1518226584Sdim
1519226584Sdimunsigned ARMMCCodeEmitter::
1520226584SdimgetShiftRight64Imm(const MCInst &MI, unsigned Op,
1521226584Sdim                   SmallVectorImpl<MCFixup> &Fixups) const {
1522226584Sdim  return 64 - MI.getOperand(Op).getImm();
1523226584Sdim}
1524226584Sdim
1525226584Sdimvoid ARMMCCodeEmitter::
1526226584SdimEncodeInstruction(const MCInst &MI, raw_ostream &OS,
1527226584Sdim                  SmallVectorImpl<MCFixup> &Fixups) const {
1528226584Sdim  // Pseudo instructions don't get encoded.
1529226584Sdim  const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
1530226584Sdim  uint64_t TSFlags = Desc.TSFlags;
1531226584Sdim  if ((TSFlags & ARMII::FormMask) == ARMII::Pseudo)
1532226584Sdim    return;
1533226584Sdim
1534226584Sdim  int Size;
1535226584Sdim  if (Desc.getSize() == 2 || Desc.getSize() == 4)
1536226584Sdim    Size = Desc.getSize();
1537226584Sdim  else
1538226584Sdim    llvm_unreachable("Unexpected instruction size!");
1539226584Sdim
1540226584Sdim  uint32_t Binary = getBinaryCodeForInstr(MI, Fixups);
1541226584Sdim  // Thumb 32-bit wide instructions need to emit the high order halfword
1542226584Sdim  // first.
1543226584Sdim  if (isThumb() && Size == 4) {
1544226584Sdim    EmitConstant(Binary >> 16, 2, OS);
1545226584Sdim    EmitConstant(Binary & 0xffff, 2, OS);
1546226584Sdim  } else
1547226584Sdim    EmitConstant(Binary, Size, OS);
1548226584Sdim  ++MCNumEmitted;  // Keep track of the # of mi's emitted.
1549226584Sdim}
1550226584Sdim
1551226584Sdim#include "ARMGenMCCodeEmitter.inc"
1552