blob: df28a992913607315a114357c75022ef872d1d55 [file] [log] [blame]
Jim Grosbach568eeed2010-09-17 18:46:17 +00001//===-- ARM/ARMMCCodeEmitter.cpp - Convert ARM code to machine code -------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the ARMMCCodeEmitter class.
11//
12//===----------------------------------------------------------------------===//
13
Chris Lattner2ac19022010-11-15 05:19:05 +000014#define DEBUG_TYPE "mccodeemitter"
Jim Grosbach568eeed2010-09-17 18:46:17 +000015#include "ARM.h"
Jim Grosbach42fac8e2010-10-11 23:16:21 +000016#include "ARMAddressingModes.h"
Jim Grosbach70933262010-11-04 01:12:30 +000017#include "ARMFixupKinds.h"
Jim Grosbachd6d4b422010-10-07 22:12:50 +000018#include "ARMInstrInfo.h"
Jim Grosbach568eeed2010-09-17 18:46:17 +000019#include "llvm/MC/MCCodeEmitter.h"
20#include "llvm/MC/MCExpr.h"
21#include "llvm/MC/MCInst.h"
Jim Grosbachd6d4b422010-10-07 22:12:50 +000022#include "llvm/ADT/Statistic.h"
Jim Grosbach568eeed2010-09-17 18:46:17 +000023#include "llvm/Support/raw_ostream.h"
24using namespace llvm;
25
Jim Grosbach70933262010-11-04 01:12:30 +000026STATISTIC(MCNumEmitted, "Number of MC instructions emitted.");
27STATISTIC(MCNumCPRelocations, "Number of constant pool relocations created.");
Jim Grosbachd6d4b422010-10-07 22:12:50 +000028
Jim Grosbach568eeed2010-09-17 18:46:17 +000029namespace {
30class ARMMCCodeEmitter : public MCCodeEmitter {
31 ARMMCCodeEmitter(const ARMMCCodeEmitter &); // DO NOT IMPLEMENT
32 void operator=(const ARMMCCodeEmitter &); // DO NOT IMPLEMENT
33 const TargetMachine &TM;
34 const TargetInstrInfo &TII;
35 MCContext &Ctx;
36
37public:
38 ARMMCCodeEmitter(TargetMachine &tm, MCContext &ctx)
39 : TM(tm), TII(*TM.getInstrInfo()), Ctx(ctx) {
Jim Grosbach568eeed2010-09-17 18:46:17 +000040 }
41
42 ~ARMMCCodeEmitter() {}
43
Jim Grosbachc466b932010-11-11 18:04:49 +000044 unsigned getNumFixupKinds() const { return ARM::NumTargetFixupKinds; }
Jim Grosbach70933262010-11-04 01:12:30 +000045
46 const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const {
47 const static MCFixupKindInfo Infos[] = {
Jim Grosbachdff84b02010-12-02 00:28:45 +000048 // name off bits flags
49 { "fixup_arm_ldst_pcrel_12", 1, 24, MCFixupKindInfo::FKF_IsPCRel },
Owen Anderson05018c22010-12-09 20:27:52 +000050 { "fixup_t2_ldst_pcrel_12", 0, 32, MCFixupKindInfo::FKF_IsPCRel |
51 MCFixupKindInfo::FKF_IsAligned},
Jim Grosbachdff84b02010-12-02 00:28:45 +000052 { "fixup_arm_pcrel_10", 1, 24, MCFixupKindInfo::FKF_IsPCRel },
Owen Andersond8e351b2010-12-08 00:18:36 +000053 { "fixup_t2_pcrel_10", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
Jim Grosbachdff84b02010-12-02 00:28:45 +000054 { "fixup_arm_adr_pcrel_12", 1, 24, MCFixupKindInfo::FKF_IsPCRel },
55 { "fixup_arm_branch", 1, 24, MCFixupKindInfo::FKF_IsPCRel },
Owen Andersonfe7fac72010-12-09 21:34:47 +000056 { "fixup_t2_branch", 0, 32, MCFixupKindInfo::FKF_IsPCRel |
57 MCFixupKindInfo::FKF_IsAligned},
Jim Grosbach662a8162010-12-06 23:57:07 +000058 { "fixup_arm_thumb_bl", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
Bill Wendling09aa3f02010-12-09 00:39:08 +000059 { "fixup_arm_thumb_blx", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
Jim Grosbachb492a7c2010-12-09 19:50:12 +000060 { "fixup_arm_thumb_cb", 0, 16, MCFixupKindInfo::FKF_IsPCRel },
Bill Wendlingb8958b02010-12-08 01:57:09 +000061 { "fixup_arm_thumb_cp", 1, 8, MCFixupKindInfo::FKF_IsPCRel },
Jim Grosbache2467172010-12-10 18:21:33 +000062 { "fixup_arm_thumb_br", 0, 16, MCFixupKindInfo::FKF_IsPCRel },
Jim Grosbach01086452010-12-10 17:13:40 +000063 { "fixup_arm_thumb_bcc", 1, 8, MCFixupKindInfo::FKF_IsPCRel },
Jim Grosbachdff84b02010-12-02 00:28:45 +000064 { "fixup_arm_movt_hi16", 0, 16, 0 },
65 { "fixup_arm_movw_lo16", 0, 16, 0 },
Jim Grosbach70933262010-11-04 01:12:30 +000066 };
67
68 if (Kind < FirstTargetFixupKind)
69 return MCCodeEmitter::getFixupKindInfo(Kind);
70
71 assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
72 "Invalid kind!");
73 return Infos[Kind - FirstTargetFixupKind];
74 }
Jim Grosbach0de6ab32010-10-12 17:11:26 +000075 unsigned getMachineSoImmOpValue(unsigned SoImm) const;
76
Jim Grosbach9af82ba2010-10-07 21:57:55 +000077 // getBinaryCodeForInstr - TableGen'erated function for getting the
78 // binary encoding for an instruction.
Jim Grosbach806e80e2010-11-03 23:52:49 +000079 unsigned getBinaryCodeForInstr(const MCInst &MI,
80 SmallVectorImpl<MCFixup> &Fixups) const;
Jim Grosbach9af82ba2010-10-07 21:57:55 +000081
82 /// getMachineOpValue - Return binary encoding of operand. If the machine
83 /// operand requires relocation, record the relocation and return zero.
Jim Grosbach806e80e2010-11-03 23:52:49 +000084 unsigned getMachineOpValue(const MCInst &MI,const MCOperand &MO,
85 SmallVectorImpl<MCFixup> &Fixups) const;
Jim Grosbach9af82ba2010-10-07 21:57:55 +000086
Jason W Kim837caa92010-11-18 23:37:15 +000087 /// getMovtImmOpValue - Return the encoding for the movw/movt pair
88 uint32_t getMovtImmOpValue(const MCInst &MI, unsigned OpIdx,
89 SmallVectorImpl<MCFixup> &Fixups) const;
90
Bill Wendling92b5a2e2010-11-03 01:49:29 +000091 bool EncodeAddrModeOpValues(const MCInst &MI, unsigned OpIdx,
Jim Grosbach806e80e2010-11-03 23:52:49 +000092 unsigned &Reg, unsigned &Imm,
93 SmallVectorImpl<MCFixup> &Fixups) const;
Bill Wendling92b5a2e2010-11-03 01:49:29 +000094
Jim Grosbach662a8162010-12-06 23:57:07 +000095 /// getThumbBLTargetOpValue - Return encoding info for Thumb immediate
Bill Wendling09aa3f02010-12-09 00:39:08 +000096 /// BL branch target.
Jim Grosbach662a8162010-12-06 23:57:07 +000097 uint32_t getThumbBLTargetOpValue(const MCInst &MI, unsigned OpIdx,
98 SmallVectorImpl<MCFixup> &Fixups) const;
99
Bill Wendling09aa3f02010-12-09 00:39:08 +0000100 /// getThumbBLXTargetOpValue - Return encoding info for Thumb immediate
101 /// BLX branch target.
102 uint32_t getThumbBLXTargetOpValue(const MCInst &MI, unsigned OpIdx,
103 SmallVectorImpl<MCFixup> &Fixups) const;
104
Jim Grosbache2467172010-12-10 18:21:33 +0000105 /// getThumbBRTargetOpValue - Return encoding info for Thumb branch target.
106 uint32_t getThumbBRTargetOpValue(const MCInst &MI, unsigned OpIdx,
107 SmallVectorImpl<MCFixup> &Fixups) const;
108
Jim Grosbach01086452010-12-10 17:13:40 +0000109 /// getThumbBCCTargetOpValue - Return encoding info for Thumb branch target.
110 uint32_t getThumbBCCTargetOpValue(const MCInst &MI, unsigned OpIdx,
111 SmallVectorImpl<MCFixup> &Fixups) const;
112
Jim Grosbach027d6e82010-12-09 19:04:53 +0000113 /// getThumbCBTargetOpValue - Return encoding info for Thumb branch target.
114 uint32_t getThumbCBTargetOpValue(const MCInst &MI, unsigned OpIdx,
Bill Wendlingdff2f712010-12-08 23:01:43 +0000115 SmallVectorImpl<MCFixup> &Fixups) const;
116
Jim Grosbachc466b932010-11-11 18:04:49 +0000117 /// getBranchTargetOpValue - Return encoding info for 24-bit immediate
118 /// branch target.
119 uint32_t getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
120 SmallVectorImpl<MCFixup> &Fixups) const;
121
Jim Grosbach5d14f9b2010-12-01 19:47:31 +0000122 /// getAdrLabelOpValue - Return encoding info for 12-bit immediate
123 /// ADR label target.
124 uint32_t getAdrLabelOpValue(const MCInst &MI, unsigned OpIdx,
125 SmallVectorImpl<MCFixup> &Fixups) const;
126
Bill Wendling92b5a2e2010-11-03 01:49:29 +0000127 /// getAddrModeImm12OpValue - Return encoding info for 'reg +/- imm12'
128 /// operand.
Jim Grosbach806e80e2010-11-03 23:52:49 +0000129 uint32_t getAddrModeImm12OpValue(const MCInst &MI, unsigned OpIdx,
130 SmallVectorImpl<MCFixup> &Fixups) const;
Bill Wendling92b5a2e2010-11-03 01:49:29 +0000131
Owen Anderson9d63d902010-12-01 19:18:46 +0000132 /// getT2AddrModeImm8s4OpValue - Return encoding info for 'reg +/- imm8<<2'
133 /// operand.
134 uint32_t getT2AddrModeImm8s4OpValue(const MCInst &MI, unsigned OpIdx,
135 SmallVectorImpl<MCFixup> &Fixups) const;
136
137
Jim Grosbach54fea632010-11-09 17:20:53 +0000138 /// getLdStSORegOpValue - Return encoding info for 'reg +/- reg shop imm'
139 /// operand as needed by load/store instructions.
140 uint32_t getLdStSORegOpValue(const MCInst &MI, unsigned OpIdx,
141 SmallVectorImpl<MCFixup> &Fixups) const;
142
Jim Grosbach5d5eb9e2010-11-10 23:38:36 +0000143 /// getLdStmModeOpValue - Return encoding for load/store multiple mode.
144 uint32_t getLdStmModeOpValue(const MCInst &MI, unsigned OpIdx,
145 SmallVectorImpl<MCFixup> &Fixups) const {
146 ARM_AM::AMSubMode Mode = (ARM_AM::AMSubMode)MI.getOperand(OpIdx).getImm();
147 switch (Mode) {
148 default: assert(0 && "Unknown addressing sub-mode!");
149 case ARM_AM::da: return 0;
150 case ARM_AM::ia: return 1;
151 case ARM_AM::db: return 2;
152 case ARM_AM::ib: return 3;
153 }
154 }
Jim Grosbach99f53d12010-11-15 20:47:07 +0000155 /// getShiftOp - Return the shift opcode (bit[6:5]) of the immediate value.
156 ///
157 unsigned getShiftOp(ARM_AM::ShiftOpc ShOpc) const {
158 switch (ShOpc) {
159 default: llvm_unreachable("Unknown shift opc!");
160 case ARM_AM::no_shift:
161 case ARM_AM::lsl: return 0;
162 case ARM_AM::lsr: return 1;
163 case ARM_AM::asr: return 2;
164 case ARM_AM::ror:
165 case ARM_AM::rrx: return 3;
166 }
167 return 0;
168 }
169
170 /// getAddrMode2OpValue - Return encoding for addrmode2 operands.
171 uint32_t getAddrMode2OpValue(const MCInst &MI, unsigned OpIdx,
172 SmallVectorImpl<MCFixup> &Fixups) const;
173
174 /// getAddrMode2OffsetOpValue - Return encoding for am2offset operands.
175 uint32_t getAddrMode2OffsetOpValue(const MCInst &MI, unsigned OpIdx,
176 SmallVectorImpl<MCFixup> &Fixups) const;
177
Jim Grosbach7eab97f2010-11-11 16:55:29 +0000178 /// getAddrMode3OffsetOpValue - Return encoding for am3offset operands.
179 uint32_t getAddrMode3OffsetOpValue(const MCInst &MI, unsigned OpIdx,
180 SmallVectorImpl<MCFixup> &Fixups) const;
181
Jim Grosbach570a9222010-11-11 01:09:40 +0000182 /// getAddrMode3OpValue - Return encoding for addrmode3 operands.
183 uint32_t getAddrMode3OpValue(const MCInst &MI, unsigned OpIdx,
184 SmallVectorImpl<MCFixup> &Fixups) const;
Jim Grosbach5d5eb9e2010-11-10 23:38:36 +0000185
Jim Grosbachd967cd02010-12-07 21:50:47 +0000186 /// getAddrModeThumbSPOpValue - Return encoding info for 'reg +/- imm12'
187 /// operand.
188 uint32_t getAddrModeThumbSPOpValue(const MCInst &MI, unsigned OpIdx,
189 SmallVectorImpl<MCFixup> &Fixups) const;
190
Bill Wendling272df512010-12-09 21:49:07 +0000191 /// getAddrModeSOpValue - Encode the t_addrmode_s# operands.
192 uint32_t getAddrModeSOpValue(const MCInst &MI, unsigned OpIdx,
193 SmallVectorImpl<MCFixup> &) const;
Bill Wendling1fd374e2010-11-30 22:57:21 +0000194
Bill Wendlingb8958b02010-12-08 01:57:09 +0000195 /// getAddrModePCOpValue - Return encoding for t_addrmode_pc operands.
196 uint32_t getAddrModePCOpValue(const MCInst &MI, unsigned OpIdx,
197 SmallVectorImpl<MCFixup> &Fixups) const;
198
Bill Wendling92b5a2e2010-11-03 01:49:29 +0000199 /// getAddrMode5OpValue - Return encoding info for 'reg +/- imm8' operand.
Jim Grosbach806e80e2010-11-03 23:52:49 +0000200 uint32_t getAddrMode5OpValue(const MCInst &MI, unsigned OpIdx,
201 SmallVectorImpl<MCFixup> &Fixups) const;
Jim Grosbach3e556122010-10-26 22:37:02 +0000202
Jim Grosbach08bd5492010-10-12 23:00:24 +0000203 /// getCCOutOpValue - Return encoding of the 's' bit.
Jim Grosbach806e80e2010-11-03 23:52:49 +0000204 unsigned getCCOutOpValue(const MCInst &MI, unsigned Op,
205 SmallVectorImpl<MCFixup> &Fixups) const {
Jim Grosbach08bd5492010-10-12 23:00:24 +0000206 // The operand is either reg0 or CPSR. The 's' bit is encoded as '0' or
207 // '1' respectively.
208 return MI.getOperand(Op).getReg() == ARM::CPSR;
209 }
Jim Grosbachef324d72010-10-12 23:53:58 +0000210
Jim Grosbach2a6a93d2010-10-12 23:18:08 +0000211 /// getSOImmOpValue - Return an encoded 12-bit shifted-immediate value.
Jim Grosbach806e80e2010-11-03 23:52:49 +0000212 unsigned getSOImmOpValue(const MCInst &MI, unsigned Op,
213 SmallVectorImpl<MCFixup> &Fixups) const {
Jim Grosbach2a6a93d2010-10-12 23:18:08 +0000214 unsigned SoImm = MI.getOperand(Op).getImm();
215 int SoImmVal = ARM_AM::getSOImmVal(SoImm);
216 assert(SoImmVal != -1 && "Not a valid so_imm value!");
217
218 // Encode rotate_imm.
219 unsigned Binary = (ARM_AM::getSOImmValRot((unsigned)SoImmVal) >> 1)
220 << ARMII::SoRotImmShift;
221
222 // Encode immed_8.
223 Binary |= ARM_AM::getSOImmValImm((unsigned)SoImmVal);
224 return Binary;
225 }
Owen Anderson5de6d842010-11-12 21:12:40 +0000226
227 /// getT2SOImmOpValue - Return an encoded 12-bit shifted-immediate value.
228 unsigned getT2SOImmOpValue(const MCInst &MI, unsigned Op,
229 SmallVectorImpl<MCFixup> &Fixups) const {
230 unsigned SoImm = MI.getOperand(Op).getImm();
231 unsigned Encoded = ARM_AM::getT2SOImmVal(SoImm);
232 assert(Encoded != ~0U && "Not a Thumb2 so_imm value?");
233 return Encoded;
234 }
Jim Grosbach08bd5492010-10-12 23:00:24 +0000235
Owen Anderson75579f72010-11-29 22:44:32 +0000236 unsigned getT2AddrModeSORegOpValue(const MCInst &MI, unsigned OpNum,
237 SmallVectorImpl<MCFixup> &Fixups) const;
238 unsigned getT2AddrModeImm8OpValue(const MCInst &MI, unsigned OpNum,
239 SmallVectorImpl<MCFixup> &Fixups) const;
Owen Anderson6af50f72010-11-30 00:14:31 +0000240 unsigned getT2AddrModeImm8OffsetOpValue(const MCInst &MI, unsigned OpNum,
241 SmallVectorImpl<MCFixup> &Fixups) const;
Owen Anderson0e1bcdf2010-11-30 19:19:31 +0000242 unsigned getT2AddrModeImm12OffsetOpValue(const MCInst &MI, unsigned OpNum,
243 SmallVectorImpl<MCFixup> &Fixups) const;
Owen Anderson75579f72010-11-29 22:44:32 +0000244
Jim Grosbachef324d72010-10-12 23:53:58 +0000245 /// getSORegOpValue - Return an encoded so_reg shifted register value.
Jim Grosbach806e80e2010-11-03 23:52:49 +0000246 unsigned getSORegOpValue(const MCInst &MI, unsigned Op,
247 SmallVectorImpl<MCFixup> &Fixups) const;
Owen Anderson5de6d842010-11-12 21:12:40 +0000248 unsigned getT2SORegOpValue(const MCInst &MI, unsigned Op,
249 SmallVectorImpl<MCFixup> &Fixups) const;
Jim Grosbachef324d72010-10-12 23:53:58 +0000250
Jim Grosbach806e80e2010-11-03 23:52:49 +0000251 unsigned getRotImmOpValue(const MCInst &MI, unsigned Op,
252 SmallVectorImpl<MCFixup> &Fixups) const {
Jim Grosbachb35ad412010-10-13 19:56:10 +0000253 switch (MI.getOperand(Op).getImm()) {
254 default: assert (0 && "Not a valid rot_imm value!");
255 case 0: return 0;
256 case 8: return 1;
257 case 16: return 2;
258 case 24: return 3;
259 }
260 }
261
Jim Grosbach806e80e2010-11-03 23:52:49 +0000262 unsigned getImmMinusOneOpValue(const MCInst &MI, unsigned Op,
263 SmallVectorImpl<MCFixup> &Fixups) const {
Jim Grosbach8abe32a2010-10-15 17:15:16 +0000264 return MI.getOperand(Op).getImm() - 1;
265 }
Jim Grosbachd8a11c22010-10-29 23:21:03 +0000266
Jim Grosbach806e80e2010-11-03 23:52:49 +0000267 unsigned getNEONVcvtImm32OpValue(const MCInst &MI, unsigned Op,
268 SmallVectorImpl<MCFixup> &Fixups) const {
Owen Anderson498ec202010-10-27 22:49:00 +0000269 return 64 - MI.getOperand(Op).getImm();
270 }
Jim Grosbach8abe32a2010-10-15 17:15:16 +0000271
Jim Grosbach806e80e2010-11-03 23:52:49 +0000272 unsigned getBitfieldInvertedMaskOpValue(const MCInst &MI, unsigned Op,
273 SmallVectorImpl<MCFixup> &Fixups) const;
Jim Grosbach3fea191052010-10-21 22:03:21 +0000274
Jim Grosbach806e80e2010-11-03 23:52:49 +0000275 unsigned getRegisterListOpValue(const MCInst &MI, unsigned Op,
276 SmallVectorImpl<MCFixup> &Fixups) const;
277 unsigned getAddrMode6AddressOpValue(const MCInst &MI, unsigned Op,
278 SmallVectorImpl<MCFixup> &Fixups) const;
Bob Wilson8e0c7b52010-11-30 00:00:42 +0000279 unsigned getAddrMode6DupAddressOpValue(const MCInst &MI, unsigned Op,
280 SmallVectorImpl<MCFixup> &Fixups) const;
Jim Grosbach806e80e2010-11-03 23:52:49 +0000281 unsigned getAddrMode6OffsetOpValue(const MCInst &MI, unsigned Op,
282 SmallVectorImpl<MCFixup> &Fixups) const;
Jim Grosbach6b5252d2010-10-30 00:37:59 +0000283
Owen Andersonc7139a62010-11-11 19:07:48 +0000284 unsigned NEONThumb2DataIPostEncoder(const MCInst &MI,
285 unsigned EncodedValue) const;
Owen Anderson57dac882010-11-11 21:36:43 +0000286 unsigned NEONThumb2LoadStorePostEncoder(const MCInst &MI,
Bill Wendlingcf590262010-12-01 21:54:50 +0000287 unsigned EncodedValue) const;
Owen Anderson8f143912010-11-11 23:12:55 +0000288 unsigned NEONThumb2DupPostEncoder(const MCInst &MI,
Bill Wendlingcf590262010-12-01 21:54:50 +0000289 unsigned EncodedValue) const;
290
291 unsigned VFPThumb2PostEncoder(const MCInst &MI,
292 unsigned EncodedValue) const;
Owen Andersonc7139a62010-11-11 19:07:48 +0000293
Jim Grosbach70933262010-11-04 01:12:30 +0000294 void EmitByte(unsigned char C, raw_ostream &OS) const {
Jim Grosbach568eeed2010-09-17 18:46:17 +0000295 OS << (char)C;
Jim Grosbach568eeed2010-09-17 18:46:17 +0000296 }
297
Jim Grosbach70933262010-11-04 01:12:30 +0000298 void EmitConstant(uint64_t Val, unsigned Size, raw_ostream &OS) const {
Jim Grosbach568eeed2010-09-17 18:46:17 +0000299 // Output the constant in little endian byte order.
300 for (unsigned i = 0; i != Size; ++i) {
Jim Grosbach70933262010-11-04 01:12:30 +0000301 EmitByte(Val & 255, OS);
Jim Grosbach568eeed2010-09-17 18:46:17 +0000302 Val >>= 8;
303 }
304 }
305
Jim Grosbach568eeed2010-09-17 18:46:17 +0000306 void EncodeInstruction(const MCInst &MI, raw_ostream &OS,
307 SmallVectorImpl<MCFixup> &Fixups) const;
Jim Grosbach568eeed2010-09-17 18:46:17 +0000308};
309
310} // end anonymous namespace
311
Bill Wendling0800ce72010-11-02 22:53:11 +0000312MCCodeEmitter *llvm::createARMMCCodeEmitter(const Target &, TargetMachine &TM,
313 MCContext &Ctx) {
Jim Grosbach568eeed2010-09-17 18:46:17 +0000314 return new ARMMCCodeEmitter(TM, Ctx);
315}
316
Owen Anderson57dac882010-11-11 21:36:43 +0000317/// NEONThumb2DataIPostEncoder - Post-process encoded NEON data-processing
Owen Andersonc7139a62010-11-11 19:07:48 +0000318/// instructions, and rewrite them to their Thumb2 form if we are currently in
319/// Thumb2 mode.
320unsigned ARMMCCodeEmitter::NEONThumb2DataIPostEncoder(const MCInst &MI,
321 unsigned EncodedValue) const {
322 const ARMSubtarget &Subtarget = TM.getSubtarget<ARMSubtarget>();
323 if (Subtarget.isThumb2()) {
324 // NEON Thumb2 data-processsing encodings are very simple: bit 24 is moved
325 // to bit 12 of the high half-word (i.e. bit 28), and bits 27-24 are
326 // set to 1111.
327 unsigned Bit24 = EncodedValue & 0x01000000;
328 unsigned Bit28 = Bit24 << 4;
329 EncodedValue &= 0xEFFFFFFF;
330 EncodedValue |= Bit28;
331 EncodedValue |= 0x0F000000;
332 }
333
334 return EncodedValue;
335}
336
Owen Anderson57dac882010-11-11 21:36:43 +0000337/// NEONThumb2LoadStorePostEncoder - Post-process encoded NEON load/store
338/// instructions, and rewrite them to their Thumb2 form if we are currently in
339/// Thumb2 mode.
340unsigned ARMMCCodeEmitter::NEONThumb2LoadStorePostEncoder(const MCInst &MI,
341 unsigned EncodedValue) const {
342 const ARMSubtarget &Subtarget = TM.getSubtarget<ARMSubtarget>();
343 if (Subtarget.isThumb2()) {
344 EncodedValue &= 0xF0FFFFFF;
345 EncodedValue |= 0x09000000;
346 }
347
348 return EncodedValue;
349}
350
Owen Anderson8f143912010-11-11 23:12:55 +0000351/// NEONThumb2DupPostEncoder - Post-process encoded NEON vdup
352/// instructions, and rewrite them to their Thumb2 form if we are currently in
353/// Thumb2 mode.
354unsigned ARMMCCodeEmitter::NEONThumb2DupPostEncoder(const MCInst &MI,
355 unsigned EncodedValue) const {
356 const ARMSubtarget &Subtarget = TM.getSubtarget<ARMSubtarget>();
357 if (Subtarget.isThumb2()) {
358 EncodedValue &= 0x00FFFFFF;
359 EncodedValue |= 0xEE000000;
360 }
361
362 return EncodedValue;
363}
364
Bill Wendlingcf590262010-12-01 21:54:50 +0000365/// VFPThumb2PostEncoder - Post-process encoded VFP instructions and rewrite
366/// them to their Thumb2 form if we are currently in Thumb2 mode.
367unsigned ARMMCCodeEmitter::
368VFPThumb2PostEncoder(const MCInst &MI, unsigned EncodedValue) const {
369 if (TM.getSubtarget<ARMSubtarget>().isThumb2()) {
370 EncodedValue &= 0x0FFFFFFF;
371 EncodedValue |= 0xE0000000;
372 }
373 return EncodedValue;
374}
Owen Anderson57dac882010-11-11 21:36:43 +0000375
Jim Grosbach56ac9072010-10-08 21:45:55 +0000376/// getMachineOpValue - Return binary encoding of operand. If the machine
377/// operand requires relocation, record the relocation and return zero.
Jim Grosbach806e80e2010-11-03 23:52:49 +0000378unsigned ARMMCCodeEmitter::
379getMachineOpValue(const MCInst &MI, const MCOperand &MO,
380 SmallVectorImpl<MCFixup> &Fixups) const {
Bill Wendlingbbbdcd42010-10-14 02:33:26 +0000381 if (MO.isReg()) {
Bill Wendling0800ce72010-11-02 22:53:11 +0000382 unsigned Reg = MO.getReg();
383 unsigned RegNo = getARMRegisterNumbering(Reg);
Jim Grosbachd8a11c22010-10-29 23:21:03 +0000384
Jim Grosbachb0708d22010-11-30 23:51:41 +0000385 // Q registers are encoded as 2x their register number.
Bill Wendling0800ce72010-11-02 22:53:11 +0000386 switch (Reg) {
387 default:
388 return RegNo;
389 case ARM::Q0: case ARM::Q1: case ARM::Q2: case ARM::Q3:
390 case ARM::Q4: case ARM::Q5: case ARM::Q6: case ARM::Q7:
391 case ARM::Q8: case ARM::Q9: case ARM::Q10: case ARM::Q11:
392 case ARM::Q12: case ARM::Q13: case ARM::Q14: case ARM::Q15:
393 return 2 * RegNo;
Owen Anderson90d4cf92010-10-21 20:49:13 +0000394 }
Bill Wendlingbbbdcd42010-10-14 02:33:26 +0000395 } else if (MO.isImm()) {
Jim Grosbach56ac9072010-10-08 21:45:55 +0000396 return static_cast<unsigned>(MO.getImm());
Bill Wendlingbbbdcd42010-10-14 02:33:26 +0000397 } else if (MO.isFPImm()) {
398 return static_cast<unsigned>(APFloat(MO.getFPImm())
399 .bitcastToAPInt().getHiBits(32).getLimitedValue());
Jim Grosbach56ac9072010-10-08 21:45:55 +0000400 }
Bill Wendling0800ce72010-11-02 22:53:11 +0000401
Jim Grosbach817c1a62010-11-19 00:27:09 +0000402 llvm_unreachable("Unable to encode MCOperand!");
Jim Grosbach56ac9072010-10-08 21:45:55 +0000403 return 0;
404}
405
Bill Wendling5df0e0a2010-11-02 22:31:46 +0000406/// getAddrModeImmOpValue - Return encoding info for 'reg +/- imm' operand.
Jim Grosbach806e80e2010-11-03 23:52:49 +0000407bool ARMMCCodeEmitter::
408EncodeAddrModeOpValues(const MCInst &MI, unsigned OpIdx, unsigned &Reg,
409 unsigned &Imm, SmallVectorImpl<MCFixup> &Fixups) const {
Jim Grosbach3e556122010-10-26 22:37:02 +0000410 const MCOperand &MO = MI.getOperand(OpIdx);
411 const MCOperand &MO1 = MI.getOperand(OpIdx + 1);
Jim Grosbach9af3d1c2010-11-01 23:45:50 +0000412
Bill Wendling92b5a2e2010-11-03 01:49:29 +0000413 Reg = getARMRegisterNumbering(MO.getReg());
414
415 int32_t SImm = MO1.getImm();
416 bool isAdd = true;
Bill Wendling5df0e0a2010-11-02 22:31:46 +0000417
Jim Grosbachab682a22010-10-28 18:34:10 +0000418 // Special value for #-0
Bill Wendling92b5a2e2010-11-03 01:49:29 +0000419 if (SImm == INT32_MIN)
420 SImm = 0;
Bill Wendling5df0e0a2010-11-02 22:31:46 +0000421
Jim Grosbachab682a22010-10-28 18:34:10 +0000422 // Immediate is always encoded as positive. The 'U' bit controls add vs sub.
Bill Wendling92b5a2e2010-11-03 01:49:29 +0000423 if (SImm < 0) {
424 SImm = -SImm;
425 isAdd = false;
426 }
Bill Wendling5df0e0a2010-11-02 22:31:46 +0000427
Bill Wendling92b5a2e2010-11-03 01:49:29 +0000428 Imm = SImm;
429 return isAdd;
430}
431
Bill Wendlingdff2f712010-12-08 23:01:43 +0000432/// getBranchTargetOpValue - Helper function to get the branch target operand,
433/// which is either an immediate or requires a fixup.
434static uint32_t getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
435 unsigned FixupKind,
436 SmallVectorImpl<MCFixup> &Fixups) {
437 const MCOperand &MO = MI.getOperand(OpIdx);
438
439 // If the destination is an immediate, we have nothing to do.
440 if (MO.isImm()) return MO.getImm();
441 assert(MO.isExpr() && "Unexpected branch target type!");
442 const MCExpr *Expr = MO.getExpr();
443 MCFixupKind Kind = MCFixupKind(FixupKind);
444 Fixups.push_back(MCFixup::Create(0, Expr, Kind));
445
446 // All of the information is in the fixup.
447 return 0;
448}
449
450/// getThumbBLTargetOpValue - Return encoding info for immediate branch target.
Jim Grosbach662a8162010-12-06 23:57:07 +0000451uint32_t ARMMCCodeEmitter::
452getThumbBLTargetOpValue(const MCInst &MI, unsigned OpIdx,
453 SmallVectorImpl<MCFixup> &Fixups) const {
Bill Wendlingdff2f712010-12-08 23:01:43 +0000454 return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_thumb_bl, Fixups);
Jim Grosbach662a8162010-12-06 23:57:07 +0000455}
456
Bill Wendling09aa3f02010-12-09 00:39:08 +0000457/// getThumbBLXTargetOpValue - Return encoding info for Thumb immediate
458/// BLX branch target.
459uint32_t ARMMCCodeEmitter::
460getThumbBLXTargetOpValue(const MCInst &MI, unsigned OpIdx,
461 SmallVectorImpl<MCFixup> &Fixups) const {
462 return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_thumb_blx, Fixups);
463}
464
Jim Grosbache2467172010-12-10 18:21:33 +0000465/// getThumbBRTargetOpValue - Return encoding info for Thumb branch target.
466uint32_t ARMMCCodeEmitter::
467getThumbBRTargetOpValue(const MCInst &MI, unsigned OpIdx,
468 SmallVectorImpl<MCFixup> &Fixups) const {
469 return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_thumb_br, Fixups);
470}
471
Jim Grosbach01086452010-12-10 17:13:40 +0000472/// getThumbBCCTargetOpValue - Return encoding info for Thumb branch target.
473uint32_t ARMMCCodeEmitter::
474getThumbBCCTargetOpValue(const MCInst &MI, unsigned OpIdx,
Jim Grosbache2467172010-12-10 18:21:33 +0000475 SmallVectorImpl<MCFixup> &Fixups) const {
Jim Grosbach01086452010-12-10 17:13:40 +0000476 return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_thumb_bcc, Fixups);
477}
478
Jim Grosbach027d6e82010-12-09 19:04:53 +0000479/// getThumbCBTargetOpValue - Return encoding info for Thumb branch target.
Bill Wendlingdff2f712010-12-08 23:01:43 +0000480uint32_t ARMMCCodeEmitter::
Jim Grosbach027d6e82010-12-09 19:04:53 +0000481getThumbCBTargetOpValue(const MCInst &MI, unsigned OpIdx,
Bill Wendlingdff2f712010-12-08 23:01:43 +0000482 SmallVectorImpl<MCFixup> &Fixups) const {
Jim Grosbachb492a7c2010-12-09 19:50:12 +0000483 return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_thumb_cb, Fixups);
Bill Wendlingdff2f712010-12-08 23:01:43 +0000484}
485
486/// getBranchTargetOpValue - Return encoding info for 24-bit immediate branch
487/// target.
Jim Grosbachc466b932010-11-11 18:04:49 +0000488uint32_t ARMMCCodeEmitter::
489getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
Bill Wendlingdff2f712010-12-08 23:01:43 +0000490 SmallVectorImpl<MCFixup> &Fixups) const {
Owen Andersonfb20d892010-12-09 00:27:41 +0000491 const ARMSubtarget &Subtarget = TM.getSubtarget<ARMSubtarget>();
492 if (Subtarget.isThumb2())
493 return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_t2_branch, Fixups);
Bill Wendlingdff2f712010-12-08 23:01:43 +0000494 return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_branch, Fixups);
Jim Grosbachc466b932010-11-11 18:04:49 +0000495}
496
Bill Wendlingdff2f712010-12-08 23:01:43 +0000497/// getAdrLabelOpValue - Return encoding info for 12-bit immediate ADR label
498/// target.
Jim Grosbach5d14f9b2010-12-01 19:47:31 +0000499uint32_t ARMMCCodeEmitter::
500getAdrLabelOpValue(const MCInst &MI, unsigned OpIdx,
501 SmallVectorImpl<MCFixup> &Fixups) const {
Bill Wendlingdff2f712010-12-08 23:01:43 +0000502 assert(MI.getOperand(OpIdx).isExpr() && "Unexpected adr target type!");
503 return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_adr_pcrel_12,
504 Fixups);
Jim Grosbach5d14f9b2010-12-01 19:47:31 +0000505}
506
Bill Wendling92b5a2e2010-11-03 01:49:29 +0000507/// getAddrModeImm12OpValue - Return encoding info for 'reg +/- imm12' operand.
Jim Grosbach806e80e2010-11-03 23:52:49 +0000508uint32_t ARMMCCodeEmitter::
509getAddrModeImm12OpValue(const MCInst &MI, unsigned OpIdx,
510 SmallVectorImpl<MCFixup> &Fixups) const {
Bill Wendling92b5a2e2010-11-03 01:49:29 +0000511 // {17-13} = reg
512 // {12} = (U)nsigned (add == '1', sub == '0')
513 // {11-0} = imm12
514 unsigned Reg, Imm12;
Jim Grosbach70933262010-11-04 01:12:30 +0000515 bool isAdd = true;
516 // If The first operand isn't a register, we have a label reference.
517 const MCOperand &MO = MI.getOperand(OpIdx);
Owen Andersoneb6779c2010-12-07 00:45:21 +0000518 const MCOperand &MO2 = MI.getOperand(OpIdx+1);
519 if (!MO.isReg() || (MO.getReg() == ARM::PC && MO2.isExpr())) {
Jim Grosbach679cbd32010-11-09 01:37:15 +0000520 Reg = getARMRegisterNumbering(ARM::PC); // Rn is PC.
Jim Grosbach70933262010-11-04 01:12:30 +0000521 Imm12 = 0;
Jim Grosbach97dd28f2010-11-30 22:40:36 +0000522 isAdd = false ; // 'U' bit is set as part of the fixup.
Jim Grosbach70933262010-11-04 01:12:30 +0000523
Owen Andersoneb6779c2010-12-07 00:45:21 +0000524 const MCExpr *Expr = 0;
525 if (!MO.isReg())
526 Expr = MO.getExpr();
527 else
528 Expr = MO2.getExpr();
529
Owen Andersond7b3f582010-12-09 01:51:07 +0000530 const ARMSubtarget &Subtarget = TM.getSubtarget<ARMSubtarget>();
531 MCFixupKind Kind;
532 if (Subtarget.isThumb2())
533 Kind = MCFixupKind(ARM::fixup_t2_ldst_pcrel_12);
534 else
535 Kind = MCFixupKind(ARM::fixup_arm_ldst_pcrel_12);
Jim Grosbach70933262010-11-04 01:12:30 +0000536 Fixups.push_back(MCFixup::Create(0, Expr, Kind));
537
538 ++MCNumCPRelocations;
539 } else
540 isAdd = EncodeAddrModeOpValues(MI, OpIdx, Reg, Imm12, Fixups);
Bill Wendling92b5a2e2010-11-03 01:49:29 +0000541
Bill Wendling92b5a2e2010-11-03 01:49:29 +0000542 uint32_t Binary = Imm12 & 0xfff;
543 // Immediate is always encoded as positive. The 'U' bit controls add vs sub.
Jim Grosbachab682a22010-10-28 18:34:10 +0000544 if (isAdd)
Bill Wendling92b5a2e2010-11-03 01:49:29 +0000545 Binary |= (1 << 12);
546 Binary |= (Reg << 13);
547 return Binary;
548}
549
Owen Anderson9d63d902010-12-01 19:18:46 +0000550/// getT2AddrModeImm8s4OpValue - Return encoding info for
551/// 'reg +/- imm8<<2' operand.
552uint32_t ARMMCCodeEmitter::
553getT2AddrModeImm8s4OpValue(const MCInst &MI, unsigned OpIdx,
554 SmallVectorImpl<MCFixup> &Fixups) const {
Jim Grosbach90cc5332010-12-10 21:05:07 +0000555 // {12-9} = reg
556 // {8} = (U)nsigned (add == '1', sub == '0')
557 // {7-0} = imm8
Owen Anderson9d63d902010-12-01 19:18:46 +0000558 unsigned Reg, Imm8;
559 bool isAdd = true;
560 // If The first operand isn't a register, we have a label reference.
561 const MCOperand &MO = MI.getOperand(OpIdx);
562 if (!MO.isReg()) {
563 Reg = getARMRegisterNumbering(ARM::PC); // Rn is PC.
564 Imm8 = 0;
565 isAdd = false ; // 'U' bit is set as part of the fixup.
566
567 assert(MO.isExpr() && "Unexpected machine operand type!");
568 const MCExpr *Expr = MO.getExpr();
569 MCFixupKind Kind = MCFixupKind(ARM::fixup_arm_pcrel_10);
570 Fixups.push_back(MCFixup::Create(0, Expr, Kind));
571
572 ++MCNumCPRelocations;
573 } else
574 isAdd = EncodeAddrModeOpValues(MI, OpIdx, Reg, Imm8, Fixups);
575
576 uint32_t Binary = (Imm8 >> 2) & 0xff;
577 // Immediate is always encoded as positive. The 'U' bit controls add vs sub.
578 if (isAdd)
Jim Grosbach90cc5332010-12-10 21:05:07 +0000579 Binary |= (1 << 8);
Owen Anderson9d63d902010-12-01 19:18:46 +0000580 Binary |= (Reg << 9);
581 return Binary;
582}
583
Jim Grosbach54fea632010-11-09 17:20:53 +0000584uint32_t ARMMCCodeEmitter::
Jason W Kim837caa92010-11-18 23:37:15 +0000585getMovtImmOpValue(const MCInst &MI, unsigned OpIdx,
586 SmallVectorImpl<MCFixup> &Fixups) const {
587 // {20-16} = imm{15-12}
588 // {11-0} = imm{11-0}
589 const MCOperand &MO = MI.getOperand(OpIdx);
590 if (MO.isImm()) {
591 return static_cast<unsigned>(MO.getImm());
592 } else if (const MCSymbolRefExpr *Expr =
593 dyn_cast<MCSymbolRefExpr>(MO.getExpr())) {
594 MCFixupKind Kind;
595 switch (Expr->getKind()) {
Duncan Sands3d938932010-11-22 09:38:00 +0000596 default: assert(0 && "Unsupported ARMFixup");
Jason W Kim837caa92010-11-18 23:37:15 +0000597 case MCSymbolRefExpr::VK_ARM_HI16:
598 Kind = MCFixupKind(ARM::fixup_arm_movt_hi16);
599 break;
600 case MCSymbolRefExpr::VK_ARM_LO16:
601 Kind = MCFixupKind(ARM::fixup_arm_movw_lo16);
602 break;
Jason W Kim837caa92010-11-18 23:37:15 +0000603 }
604 Fixups.push_back(MCFixup::Create(0, Expr, Kind));
605 return 0;
Jim Grosbach817c1a62010-11-19 00:27:09 +0000606 };
607 llvm_unreachable("Unsupported MCExpr type in MCOperand!");
Jason W Kim837caa92010-11-18 23:37:15 +0000608 return 0;
609}
610
611uint32_t ARMMCCodeEmitter::
Jim Grosbach54fea632010-11-09 17:20:53 +0000612getLdStSORegOpValue(const MCInst &MI, unsigned OpIdx,
613 SmallVectorImpl<MCFixup> &Fixups) const {
614 const MCOperand &MO = MI.getOperand(OpIdx);
615 const MCOperand &MO1 = MI.getOperand(OpIdx+1);
616 const MCOperand &MO2 = MI.getOperand(OpIdx+2);
617 unsigned Rn = getARMRegisterNumbering(MO.getReg());
618 unsigned Rm = getARMRegisterNumbering(MO1.getReg());
Jim Grosbach54fea632010-11-09 17:20:53 +0000619 unsigned ShImm = ARM_AM::getAM2Offset(MO2.getImm());
620 bool isAdd = ARM_AM::getAM2Op(MO2.getImm()) == ARM_AM::add;
Jim Grosbach99f53d12010-11-15 20:47:07 +0000621 ARM_AM::ShiftOpc ShOp = ARM_AM::getAM2ShiftOpc(MO2.getImm());
622 unsigned SBits = getShiftOp(ShOp);
Jim Grosbach54fea632010-11-09 17:20:53 +0000623
624 // {16-13} = Rn
625 // {12} = isAdd
626 // {11-0} = shifter
627 // {3-0} = Rm
628 // {4} = 0
629 // {6-5} = type
630 // {11-7} = imm
Jim Grosbach570a9222010-11-11 01:09:40 +0000631 uint32_t Binary = Rm;
Jim Grosbach54fea632010-11-09 17:20:53 +0000632 Binary |= Rn << 13;
633 Binary |= SBits << 5;
634 Binary |= ShImm << 7;
635 if (isAdd)
636 Binary |= 1 << 12;
637 return Binary;
638}
639
Jim Grosbach570a9222010-11-11 01:09:40 +0000640uint32_t ARMMCCodeEmitter::
Jim Grosbach99f53d12010-11-15 20:47:07 +0000641getAddrMode2OpValue(const MCInst &MI, unsigned OpIdx,
642 SmallVectorImpl<MCFixup> &Fixups) const {
643 // {17-14} Rn
644 // {13} 1 == imm12, 0 == Rm
645 // {12} isAdd
646 // {11-0} imm12/Rm
647 const MCOperand &MO = MI.getOperand(OpIdx);
648 unsigned Rn = getARMRegisterNumbering(MO.getReg());
649 uint32_t Binary = getAddrMode2OffsetOpValue(MI, OpIdx + 1, Fixups);
650 Binary |= Rn << 14;
651 return Binary;
652}
653
654uint32_t ARMMCCodeEmitter::
655getAddrMode2OffsetOpValue(const MCInst &MI, unsigned OpIdx,
656 SmallVectorImpl<MCFixup> &Fixups) const {
657 // {13} 1 == imm12, 0 == Rm
658 // {12} isAdd
659 // {11-0} imm12/Rm
660 const MCOperand &MO = MI.getOperand(OpIdx);
661 const MCOperand &MO1 = MI.getOperand(OpIdx+1);
662 unsigned Imm = MO1.getImm();
663 bool isAdd = ARM_AM::getAM2Op(Imm) == ARM_AM::add;
664 bool isReg = MO.getReg() != 0;
665 uint32_t Binary = ARM_AM::getAM2Offset(Imm);
666 // if reg +/- reg, Rm will be non-zero. Otherwise, we have reg +/- imm12
667 if (isReg) {
668 ARM_AM::ShiftOpc ShOp = ARM_AM::getAM2ShiftOpc(Imm);
669 Binary <<= 7; // Shift amount is bits [11:7]
670 Binary |= getShiftOp(ShOp) << 5; // Shift type is bits [6:5]
671 Binary |= getARMRegisterNumbering(MO.getReg()); // Rm is bits [3:0]
672 }
673 return Binary | (isAdd << 12) | (isReg << 13);
674}
675
676uint32_t ARMMCCodeEmitter::
Jim Grosbach7eab97f2010-11-11 16:55:29 +0000677getAddrMode3OffsetOpValue(const MCInst &MI, unsigned OpIdx,
678 SmallVectorImpl<MCFixup> &Fixups) const {
679 // {9} 1 == imm8, 0 == Rm
680 // {8} isAdd
681 // {7-4} imm7_4/zero
682 // {3-0} imm3_0/Rm
683 const MCOperand &MO = MI.getOperand(OpIdx);
684 const MCOperand &MO1 = MI.getOperand(OpIdx+1);
685 unsigned Imm = MO1.getImm();
686 bool isAdd = ARM_AM::getAM3Op(Imm) == ARM_AM::add;
687 bool isImm = MO.getReg() == 0;
688 uint32_t Imm8 = ARM_AM::getAM3Offset(Imm);
689 // if reg +/- reg, Rm will be non-zero. Otherwise, we have reg +/- imm8
690 if (!isImm)
691 Imm8 = getARMRegisterNumbering(MO.getReg());
692 return Imm8 | (isAdd << 8) | (isImm << 9);
693}
694
695uint32_t ARMMCCodeEmitter::
Jim Grosbach570a9222010-11-11 01:09:40 +0000696getAddrMode3OpValue(const MCInst &MI, unsigned OpIdx,
697 SmallVectorImpl<MCFixup> &Fixups) const {
698 // {13} 1 == imm8, 0 == Rm
699 // {12-9} Rn
700 // {8} isAdd
701 // {7-4} imm7_4/zero
702 // {3-0} imm3_0/Rm
703 const MCOperand &MO = MI.getOperand(OpIdx);
704 const MCOperand &MO1 = MI.getOperand(OpIdx+1);
705 const MCOperand &MO2 = MI.getOperand(OpIdx+2);
706 unsigned Rn = getARMRegisterNumbering(MO.getReg());
707 unsigned Imm = MO2.getImm();
708 bool isAdd = ARM_AM::getAM3Op(Imm) == ARM_AM::add;
709 bool isImm = MO1.getReg() == 0;
710 uint32_t Imm8 = ARM_AM::getAM3Offset(Imm);
711 // if reg +/- reg, Rm will be non-zero. Otherwise, we have reg +/- imm8
712 if (!isImm)
713 Imm8 = getARMRegisterNumbering(MO1.getReg());
714 return (Rn << 9) | Imm8 | (isAdd << 8) | (isImm << 13);
715}
716
Bill Wendlingb8958b02010-12-08 01:57:09 +0000717/// getAddrModeThumbSPOpValue - Encode the t_addrmode_sp operands.
Jim Grosbachd967cd02010-12-07 21:50:47 +0000718uint32_t ARMMCCodeEmitter::
719getAddrModeThumbSPOpValue(const MCInst &MI, unsigned OpIdx,
720 SmallVectorImpl<MCFixup> &Fixups) const {
721 // [SP, #imm]
722 // {7-0} = imm8
Jim Grosbachd967cd02010-12-07 21:50:47 +0000723 const MCOperand &MO1 = MI.getOperand(OpIdx + 1);
Bill Wendlingb8958b02010-12-08 01:57:09 +0000724#if 0 // FIXME: This crashes2003-05-14-initialize-string.c
725 assert(MI.getOperand(OpIdx).getReg() == ARM::SP &&
726 "Unexpected base register!");
727#endif
Jim Grosbachd967cd02010-12-07 21:50:47 +0000728 // The immediate is already shifted for the implicit zeroes, so no change
729 // here.
730 return MO1.getImm() & 0xff;
731}
732
Bill Wendling1fd374e2010-11-30 22:57:21 +0000733/// getAddrModeSOpValue - Encode the t_addrmode_s# operands.
Bill Wendling272df512010-12-09 21:49:07 +0000734uint32_t ARMMCCodeEmitter::
735getAddrModeSOpValue(const MCInst &MI, unsigned OpIdx,
736 SmallVectorImpl<MCFixup> &) const {
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000737 // [Rn, Rm]
738 // {5-3} = Rm
739 // {2-0} = Rn
740 //
741 // [Rn, #imm]
742 // {7-3} = imm5
743 // {2-0} = Rn
744 const MCOperand &MO = MI.getOperand(OpIdx);
745 const MCOperand &MO1 = MI.getOperand(OpIdx + 1);
746 const MCOperand &MO2 = MI.getOperand(OpIdx + 2);
747 unsigned Rn = getARMRegisterNumbering(MO.getReg());
Bill Wendling272df512010-12-09 21:49:07 +0000748 unsigned Imm5 = MO1.getImm();
Bill Wendling0bdf0c02010-12-03 00:53:22 +0000749
750 if (MO2.getReg() != 0)
751 // Is an immediate.
752 Imm5 = getARMRegisterNumbering(MO2.getReg());
753
Bill Wendling272df512010-12-09 21:49:07 +0000754 return ((Imm5 & 0x1f) << 3) | Rn;
Bill Wendling1fd374e2010-11-30 22:57:21 +0000755}
756
Bill Wendlingb8958b02010-12-08 01:57:09 +0000757/// getAddrModePCOpValue - Return encoding for t_addrmode_pc operands.
758uint32_t ARMMCCodeEmitter::
759getAddrModePCOpValue(const MCInst &MI, unsigned OpIdx,
760 SmallVectorImpl<MCFixup> &Fixups) const {
Bill Wendling09aa3f02010-12-09 00:39:08 +0000761 return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_thumb_cp, Fixups);
Bill Wendlingb8958b02010-12-08 01:57:09 +0000762}
763
Jim Grosbach5177f792010-12-01 21:09:40 +0000764/// getAddrMode5OpValue - Return encoding info for 'reg +/- imm10' operand.
Jim Grosbach806e80e2010-11-03 23:52:49 +0000765uint32_t ARMMCCodeEmitter::
766getAddrMode5OpValue(const MCInst &MI, unsigned OpIdx,
767 SmallVectorImpl<MCFixup> &Fixups) const {
Bill Wendling92b5a2e2010-11-03 01:49:29 +0000768 // {12-9} = reg
769 // {8} = (U)nsigned (add == '1', sub == '0')
770 // {7-0} = imm8
771 unsigned Reg, Imm8;
Jim Grosbach97dd28f2010-11-30 22:40:36 +0000772 bool isAdd;
Jim Grosbach70933262010-11-04 01:12:30 +0000773 // If The first operand isn't a register, we have a label reference.
774 const MCOperand &MO = MI.getOperand(OpIdx);
775 if (!MO.isReg()) {
Jim Grosbach679cbd32010-11-09 01:37:15 +0000776 Reg = getARMRegisterNumbering(ARM::PC); // Rn is PC.
Jim Grosbach70933262010-11-04 01:12:30 +0000777 Imm8 = 0;
Jim Grosbach97dd28f2010-11-30 22:40:36 +0000778 isAdd = false; // 'U' bit is handled as part of the fixup.
Jim Grosbach70933262010-11-04 01:12:30 +0000779
780 assert(MO.isExpr() && "Unexpected machine operand type!");
781 const MCExpr *Expr = MO.getExpr();
Owen Andersond8e351b2010-12-08 00:18:36 +0000782 MCFixupKind Kind;
783 const ARMSubtarget &Subtarget = TM.getSubtarget<ARMSubtarget>();
784 if (Subtarget.isThumb2())
785 Kind = MCFixupKind(ARM::fixup_t2_pcrel_10);
786 else
787 Kind = MCFixupKind(ARM::fixup_arm_pcrel_10);
Jim Grosbach70933262010-11-04 01:12:30 +0000788 Fixups.push_back(MCFixup::Create(0, Expr, Kind));
789
790 ++MCNumCPRelocations;
Jim Grosbach97dd28f2010-11-30 22:40:36 +0000791 } else {
Jim Grosbach70933262010-11-04 01:12:30 +0000792 EncodeAddrModeOpValues(MI, OpIdx, Reg, Imm8, Fixups);
Jim Grosbach97dd28f2010-11-30 22:40:36 +0000793 isAdd = ARM_AM::getAM5Op(Imm8) == ARM_AM::add;
794 }
Bill Wendling92b5a2e2010-11-03 01:49:29 +0000795
Bill Wendling92b5a2e2010-11-03 01:49:29 +0000796 uint32_t Binary = ARM_AM::getAM5Offset(Imm8);
797 // Immediate is always encoded as positive. The 'U' bit controls add vs sub.
Jim Grosbach97dd28f2010-11-30 22:40:36 +0000798 if (isAdd)
Bill Wendling92b5a2e2010-11-03 01:49:29 +0000799 Binary |= (1 << 8);
800 Binary |= (Reg << 9);
Jim Grosbach3e556122010-10-26 22:37:02 +0000801 return Binary;
802}
803
Jim Grosbach806e80e2010-11-03 23:52:49 +0000804unsigned ARMMCCodeEmitter::
805getSORegOpValue(const MCInst &MI, unsigned OpIdx,
806 SmallVectorImpl<MCFixup> &Fixups) const {
Bill Wendling0800ce72010-11-02 22:53:11 +0000807 // Sub-operands are [reg, reg, imm]. The first register is Rm, the reg to be
808 // shifted. The second is either Rs, the amount to shift by, or reg0 in which
809 // case the imm contains the amount to shift by.
Jim Grosbach35b2de02010-11-03 22:03:20 +0000810 //
Jim Grosbachef324d72010-10-12 23:53:58 +0000811 // {3-0} = Rm.
Bill Wendling0800ce72010-11-02 22:53:11 +0000812 // {4} = 1 if reg shift, 0 if imm shift
Jim Grosbachef324d72010-10-12 23:53:58 +0000813 // {6-5} = type
814 // If reg shift:
Jim Grosbachef324d72010-10-12 23:53:58 +0000815 // {11-8} = Rs
Bill Wendling0800ce72010-11-02 22:53:11 +0000816 // {7} = 0
Jim Grosbachef324d72010-10-12 23:53:58 +0000817 // else (imm shift)
818 // {11-7} = imm
819
820 const MCOperand &MO = MI.getOperand(OpIdx);
821 const MCOperand &MO1 = MI.getOperand(OpIdx + 1);
822 const MCOperand &MO2 = MI.getOperand(OpIdx + 2);
823 ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(MO2.getImm());
824
825 // Encode Rm.
826 unsigned Binary = getARMRegisterNumbering(MO.getReg());
827
828 // Encode the shift opcode.
829 unsigned SBits = 0;
830 unsigned Rs = MO1.getReg();
831 if (Rs) {
832 // Set shift operand (bit[7:4]).
833 // LSL - 0001
834 // LSR - 0011
835 // ASR - 0101
836 // ROR - 0111
837 // RRX - 0110 and bit[11:8] clear.
838 switch (SOpc) {
839 default: llvm_unreachable("Unknown shift opc!");
840 case ARM_AM::lsl: SBits = 0x1; break;
841 case ARM_AM::lsr: SBits = 0x3; break;
842 case ARM_AM::asr: SBits = 0x5; break;
843 case ARM_AM::ror: SBits = 0x7; break;
844 case ARM_AM::rrx: SBits = 0x6; break;
845 }
846 } else {
847 // Set shift operand (bit[6:4]).
848 // LSL - 000
849 // LSR - 010
850 // ASR - 100
851 // ROR - 110
852 switch (SOpc) {
853 default: llvm_unreachable("Unknown shift opc!");
854 case ARM_AM::lsl: SBits = 0x0; break;
855 case ARM_AM::lsr: SBits = 0x2; break;
856 case ARM_AM::asr: SBits = 0x4; break;
857 case ARM_AM::ror: SBits = 0x6; break;
858 }
859 }
Bill Wendling0800ce72010-11-02 22:53:11 +0000860
Jim Grosbachef324d72010-10-12 23:53:58 +0000861 Binary |= SBits << 4;
862 if (SOpc == ARM_AM::rrx)
863 return Binary;
864
865 // Encode the shift operation Rs or shift_imm (except rrx).
866 if (Rs) {
867 // Encode Rs bit[11:8].
868 assert(ARM_AM::getSORegOffset(MO2.getImm()) == 0);
869 return Binary | (getARMRegisterNumbering(Rs) << ARMII::RegRsShift);
870 }
871
872 // Encode shift_imm bit[11:7].
873 return Binary | ARM_AM::getSORegOffset(MO2.getImm()) << 7;
874}
875
Jim Grosbach806e80e2010-11-03 23:52:49 +0000876unsigned ARMMCCodeEmitter::
Owen Anderson75579f72010-11-29 22:44:32 +0000877getT2AddrModeSORegOpValue(const MCInst &MI, unsigned OpNum,
878 SmallVectorImpl<MCFixup> &Fixups) const {
879 const MCOperand &MO1 = MI.getOperand(OpNum);
880 const MCOperand &MO2 = MI.getOperand(OpNum+1);
881 const MCOperand &MO3 = MI.getOperand(OpNum+2);
882
883 // Encoded as [Rn, Rm, imm].
884 // FIXME: Needs fixup support.
885 unsigned Value = getARMRegisterNumbering(MO1.getReg());
886 Value <<= 4;
887 Value |= getARMRegisterNumbering(MO2.getReg());
888 Value <<= 2;
889 Value |= MO3.getImm();
890
891 return Value;
892}
893
894unsigned ARMMCCodeEmitter::
895getT2AddrModeImm8OpValue(const MCInst &MI, unsigned OpNum,
896 SmallVectorImpl<MCFixup> &Fixups) const {
897 const MCOperand &MO1 = MI.getOperand(OpNum);
898 const MCOperand &MO2 = MI.getOperand(OpNum+1);
899
900 // FIXME: Needs fixup support.
901 unsigned Value = getARMRegisterNumbering(MO1.getReg());
902
903 // Even though the immediate is 8 bits long, we need 9 bits in order
904 // to represent the (inverse of the) sign bit.
905 Value <<= 9;
Owen Anderson6af50f72010-11-30 00:14:31 +0000906 int32_t tmp = (int32_t)MO2.getImm();
907 if (tmp < 0)
908 tmp = abs(tmp);
909 else
910 Value |= 256; // Set the ADD bit
911 Value |= tmp & 255;
912 return Value;
913}
914
915unsigned ARMMCCodeEmitter::
916getT2AddrModeImm8OffsetOpValue(const MCInst &MI, unsigned OpNum,
917 SmallVectorImpl<MCFixup> &Fixups) const {
918 const MCOperand &MO1 = MI.getOperand(OpNum);
919
920 // FIXME: Needs fixup support.
921 unsigned Value = 0;
922 int32_t tmp = (int32_t)MO1.getImm();
923 if (tmp < 0)
924 tmp = abs(tmp);
925 else
926 Value |= 256; // Set the ADD bit
927 Value |= tmp & 255;
Owen Anderson75579f72010-11-29 22:44:32 +0000928 return Value;
929}
930
931unsigned ARMMCCodeEmitter::
Owen Anderson0e1bcdf2010-11-30 19:19:31 +0000932getT2AddrModeImm12OffsetOpValue(const MCInst &MI, unsigned OpNum,
933 SmallVectorImpl<MCFixup> &Fixups) const {
934 const MCOperand &MO1 = MI.getOperand(OpNum);
935
936 // FIXME: Needs fixup support.
937 unsigned Value = 0;
938 int32_t tmp = (int32_t)MO1.getImm();
939 if (tmp < 0)
940 tmp = abs(tmp);
941 else
942 Value |= 4096; // Set the ADD bit
943 Value |= tmp & 4095;
944 return Value;
945}
946
947unsigned ARMMCCodeEmitter::
Owen Anderson5de6d842010-11-12 21:12:40 +0000948getT2SORegOpValue(const MCInst &MI, unsigned OpIdx,
949 SmallVectorImpl<MCFixup> &Fixups) const {
950 // Sub-operands are [reg, imm]. The first register is Rm, the reg to be
951 // shifted. The second is the amount to shift by.
952 //
953 // {3-0} = Rm.
954 // {4} = 0
955 // {6-5} = type
956 // {11-7} = imm
957
958 const MCOperand &MO = MI.getOperand(OpIdx);
959 const MCOperand &MO1 = MI.getOperand(OpIdx + 1);
960 ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(MO1.getImm());
961
962 // Encode Rm.
963 unsigned Binary = getARMRegisterNumbering(MO.getReg());
964
965 // Encode the shift opcode.
966 unsigned SBits = 0;
967 // Set shift operand (bit[6:4]).
968 // LSL - 000
969 // LSR - 010
970 // ASR - 100
971 // ROR - 110
972 switch (SOpc) {
973 default: llvm_unreachable("Unknown shift opc!");
974 case ARM_AM::lsl: SBits = 0x0; break;
975 case ARM_AM::lsr: SBits = 0x2; break;
976 case ARM_AM::asr: SBits = 0x4; break;
977 case ARM_AM::ror: SBits = 0x6; break;
978 }
979
980 Binary |= SBits << 4;
981 if (SOpc == ARM_AM::rrx)
982 return Binary;
983
984 // Encode shift_imm bit[11:7].
985 return Binary | ARM_AM::getSORegOffset(MO1.getImm()) << 7;
986}
987
988unsigned ARMMCCodeEmitter::
Jim Grosbach806e80e2010-11-03 23:52:49 +0000989getBitfieldInvertedMaskOpValue(const MCInst &MI, unsigned Op,
990 SmallVectorImpl<MCFixup> &Fixups) const {
Jim Grosbach3fea191052010-10-21 22:03:21 +0000991 // 10 bits. lower 5 bits are are the lsb of the mask, high five bits are the
992 // msb of the mask.
993 const MCOperand &MO = MI.getOperand(Op);
994 uint32_t v = ~MO.getImm();
995 uint32_t lsb = CountTrailingZeros_32(v);
996 uint32_t msb = (32 - CountLeadingZeros_32 (v)) - 1;
997 assert (v != 0 && lsb < 32 && msb < 32 && "Illegal bitfield mask!");
998 return lsb | (msb << 5);
999}
1000
Jim Grosbach806e80e2010-11-03 23:52:49 +00001001unsigned ARMMCCodeEmitter::
1002getRegisterListOpValue(const MCInst &MI, unsigned Op,
Bill Wendling5e559a22010-11-09 00:30:18 +00001003 SmallVectorImpl<MCFixup> &Fixups) const {
Bill Wendling6bc105a2010-11-17 00:45:23 +00001004 // VLDM/VSTM:
1005 // {12-8} = Vd
1006 // {7-0} = Number of registers
1007 //
1008 // LDM/STM:
1009 // {15-0} = Bitfield of GPRs.
1010 unsigned Reg = MI.getOperand(Op).getReg();
1011 bool SPRRegs = ARM::SPRRegClass.contains(Reg);
1012 bool DPRRegs = ARM::DPRRegClass.contains(Reg);
1013
Bill Wendling5e559a22010-11-09 00:30:18 +00001014 unsigned Binary = 0;
Bill Wendling6bc105a2010-11-17 00:45:23 +00001015
1016 if (SPRRegs || DPRRegs) {
1017 // VLDM/VSTM
1018 unsigned RegNo = getARMRegisterNumbering(Reg);
1019 unsigned NumRegs = (MI.getNumOperands() - Op) & 0xff;
1020 Binary |= (RegNo & 0x1f) << 8;
1021 if (SPRRegs)
1022 Binary |= NumRegs;
1023 else
1024 Binary |= NumRegs * 2;
1025 } else {
1026 for (unsigned I = Op, E = MI.getNumOperands(); I < E; ++I) {
1027 unsigned RegNo = getARMRegisterNumbering(MI.getOperand(I).getReg());
1028 Binary |= 1 << RegNo;
1029 }
Bill Wendling5e559a22010-11-09 00:30:18 +00001030 }
Bill Wendling6bc105a2010-11-17 00:45:23 +00001031
Jim Grosbach6b5252d2010-10-30 00:37:59 +00001032 return Binary;
1033}
1034
Bob Wilson8e0c7b52010-11-30 00:00:42 +00001035/// getAddrMode6AddressOpValue - Encode an addrmode6 register number along
1036/// with the alignment operand.
Jim Grosbach806e80e2010-11-03 23:52:49 +00001037unsigned ARMMCCodeEmitter::
1038getAddrMode6AddressOpValue(const MCInst &MI, unsigned Op,
1039 SmallVectorImpl<MCFixup> &Fixups) const {
Owen Andersond9aa7d32010-11-02 00:05:05 +00001040 const MCOperand &Reg = MI.getOperand(Op);
Bill Wendling0800ce72010-11-02 22:53:11 +00001041 const MCOperand &Imm = MI.getOperand(Op + 1);
Jim Grosbach35b2de02010-11-03 22:03:20 +00001042
Owen Andersond9aa7d32010-11-02 00:05:05 +00001043 unsigned RegNo = getARMRegisterNumbering(Reg.getReg());
Bill Wendling0800ce72010-11-02 22:53:11 +00001044 unsigned Align = 0;
1045
1046 switch (Imm.getImm()) {
1047 default: break;
1048 case 2:
1049 case 4:
1050 case 8: Align = 0x01; break;
1051 case 16: Align = 0x02; break;
1052 case 32: Align = 0x03; break;
Owen Andersond9aa7d32010-11-02 00:05:05 +00001053 }
Bill Wendling0800ce72010-11-02 22:53:11 +00001054
Owen Andersond9aa7d32010-11-02 00:05:05 +00001055 return RegNo | (Align << 4);
1056}
1057
Bob Wilson8e0c7b52010-11-30 00:00:42 +00001058/// getAddrMode6DupAddressOpValue - Encode an addrmode6 register number and
1059/// alignment operand for use in VLD-dup instructions. This is the same as
1060/// getAddrMode6AddressOpValue except for the alignment encoding, which is
1061/// different for VLD4-dup.
1062unsigned ARMMCCodeEmitter::
1063getAddrMode6DupAddressOpValue(const MCInst &MI, unsigned Op,
1064 SmallVectorImpl<MCFixup> &Fixups) const {
1065 const MCOperand &Reg = MI.getOperand(Op);
1066 const MCOperand &Imm = MI.getOperand(Op + 1);
1067
1068 unsigned RegNo = getARMRegisterNumbering(Reg.getReg());
1069 unsigned Align = 0;
1070
1071 switch (Imm.getImm()) {
1072 default: break;
1073 case 2:
1074 case 4:
1075 case 8: Align = 0x01; break;
1076 case 16: Align = 0x03; break;
1077 }
1078
1079 return RegNo | (Align << 4);
1080}
1081
Jim Grosbach806e80e2010-11-03 23:52:49 +00001082unsigned ARMMCCodeEmitter::
1083getAddrMode6OffsetOpValue(const MCInst &MI, unsigned Op,
1084 SmallVectorImpl<MCFixup> &Fixups) const {
Bill Wendling0800ce72010-11-02 22:53:11 +00001085 const MCOperand &MO = MI.getOperand(Op);
1086 if (MO.getReg() == 0) return 0x0D;
1087 return MO.getReg();
Owen Andersoncf667be2010-11-02 01:24:55 +00001088}
1089
Jim Grosbach568eeed2010-09-17 18:46:17 +00001090void ARMMCCodeEmitter::
1091EncodeInstruction(const MCInst &MI, raw_ostream &OS,
Jim Grosbach806e80e2010-11-03 23:52:49 +00001092 SmallVectorImpl<MCFixup> &Fixups) const {
Jim Grosbachd91f4e42010-12-03 22:31:40 +00001093 const ARMSubtarget &Subtarget = TM.getSubtarget<ARMSubtarget>();
Jim Grosbachd6d4b422010-10-07 22:12:50 +00001094 // Pseudo instructions don't get encoded.
Bill Wendling7292e0a2010-11-02 22:44:12 +00001095 const TargetInstrDesc &Desc = TII.get(MI.getOpcode());
Jim Grosbache50e6bc2010-11-11 23:41:09 +00001096 uint64_t TSFlags = Desc.TSFlags;
1097 if ((TSFlags & ARMII::FormMask) == ARMII::Pseudo)
Jim Grosbachd6d4b422010-10-07 22:12:50 +00001098 return;
Jim Grosbache50e6bc2010-11-11 23:41:09 +00001099 int Size;
1100 // Basic size info comes from the TSFlags field.
1101 switch ((TSFlags & ARMII::SizeMask) >> ARMII::SizeShift) {
1102 default: llvm_unreachable("Unexpected instruction size!");
1103 case ARMII::Size2Bytes: Size = 2; break;
1104 case ARMII::Size4Bytes: Size = 4; break;
1105 }
Jim Grosbachd91f4e42010-12-03 22:31:40 +00001106 uint32_t Binary = getBinaryCodeForInstr(MI, Fixups);
1107 // Thumb 32-bit wide instructions need to be have the high order halfword
1108 // emitted first.
1109 if (Subtarget.isThumb() && Size == 4) {
1110 EmitConstant(Binary >> 16, 2, OS);
1111 EmitConstant(Binary & 0xffff, 2, OS);
1112 } else
1113 EmitConstant(Binary, Size, OS);
Bill Wendling7292e0a2010-11-02 22:44:12 +00001114 ++MCNumEmitted; // Keep track of the # of mi's emitted.
Jim Grosbach568eeed2010-09-17 18:46:17 +00001115}
Jim Grosbach9af82ba2010-10-07 21:57:55 +00001116
Jim Grosbach806e80e2010-11-03 23:52:49 +00001117#include "ARMGenMCCodeEmitter.inc"