blob: 273ca991d299fb63de02c96c2bb3a6f72061d196 [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 Grosbachc466b932010-11-11 18:04:49 +000048 // name offset bits flags
49 { "fixup_arm_pcrel_12", 2, 12, MCFixupKindInfo::FKF_IsPCRel },
50 { "fixup_arm_vfp_pcrel_12", 3, 8, MCFixupKindInfo::FKF_IsPCRel },
51 { "fixup_arm_branch", 1, 24, MCFixupKindInfo::FKF_IsPCRel },
Jim Grosbach70933262010-11-04 01:12:30 +000052 };
53
54 if (Kind < FirstTargetFixupKind)
55 return MCCodeEmitter::getFixupKindInfo(Kind);
56
57 assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
58 "Invalid kind!");
59 return Infos[Kind - FirstTargetFixupKind];
60 }
Jim Grosbach0de6ab32010-10-12 17:11:26 +000061 unsigned getMachineSoImmOpValue(unsigned SoImm) const;
62
Jim Grosbach9af82ba2010-10-07 21:57:55 +000063 // getBinaryCodeForInstr - TableGen'erated function for getting the
64 // binary encoding for an instruction.
Jim Grosbach806e80e2010-11-03 23:52:49 +000065 unsigned getBinaryCodeForInstr(const MCInst &MI,
66 SmallVectorImpl<MCFixup> &Fixups) const;
Jim Grosbach9af82ba2010-10-07 21:57:55 +000067
68 /// getMachineOpValue - Return binary encoding of operand. If the machine
69 /// operand requires relocation, record the relocation and return zero.
Jim Grosbach806e80e2010-11-03 23:52:49 +000070 unsigned getMachineOpValue(const MCInst &MI,const MCOperand &MO,
71 SmallVectorImpl<MCFixup> &Fixups) const;
Jim Grosbach9af82ba2010-10-07 21:57:55 +000072
Bill Wendling92b5a2e2010-11-03 01:49:29 +000073 bool EncodeAddrModeOpValues(const MCInst &MI, unsigned OpIdx,
Jim Grosbach806e80e2010-11-03 23:52:49 +000074 unsigned &Reg, unsigned &Imm,
75 SmallVectorImpl<MCFixup> &Fixups) const;
Bill Wendling92b5a2e2010-11-03 01:49:29 +000076
Jim Grosbachc466b932010-11-11 18:04:49 +000077 /// getBranchTargetOpValue - Return encoding info for 24-bit immediate
78 /// branch target.
79 uint32_t getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
80 SmallVectorImpl<MCFixup> &Fixups) const;
81
Bill Wendling92b5a2e2010-11-03 01:49:29 +000082 /// getAddrModeImm12OpValue - Return encoding info for 'reg +/- imm12'
83 /// operand.
Jim Grosbach806e80e2010-11-03 23:52:49 +000084 uint32_t getAddrModeImm12OpValue(const MCInst &MI, unsigned OpIdx,
85 SmallVectorImpl<MCFixup> &Fixups) const;
Bill Wendling92b5a2e2010-11-03 01:49:29 +000086
Jim Grosbach54fea632010-11-09 17:20:53 +000087 /// getLdStSORegOpValue - Return encoding info for 'reg +/- reg shop imm'
88 /// operand as needed by load/store instructions.
89 uint32_t getLdStSORegOpValue(const MCInst &MI, unsigned OpIdx,
90 SmallVectorImpl<MCFixup> &Fixups) const;
91
Jim Grosbach5d5eb9e2010-11-10 23:38:36 +000092 /// getLdStmModeOpValue - Return encoding for load/store multiple mode.
93 uint32_t getLdStmModeOpValue(const MCInst &MI, unsigned OpIdx,
94 SmallVectorImpl<MCFixup> &Fixups) const {
95 ARM_AM::AMSubMode Mode = (ARM_AM::AMSubMode)MI.getOperand(OpIdx).getImm();
96 switch (Mode) {
97 default: assert(0 && "Unknown addressing sub-mode!");
98 case ARM_AM::da: return 0;
99 case ARM_AM::ia: return 1;
100 case ARM_AM::db: return 2;
101 case ARM_AM::ib: return 3;
102 }
103 }
Jim Grosbach99f53d12010-11-15 20:47:07 +0000104 /// getShiftOp - Return the shift opcode (bit[6:5]) of the immediate value.
105 ///
106 unsigned getShiftOp(ARM_AM::ShiftOpc ShOpc) const {
107 switch (ShOpc) {
108 default: llvm_unreachable("Unknown shift opc!");
109 case ARM_AM::no_shift:
110 case ARM_AM::lsl: return 0;
111 case ARM_AM::lsr: return 1;
112 case ARM_AM::asr: return 2;
113 case ARM_AM::ror:
114 case ARM_AM::rrx: return 3;
115 }
116 return 0;
117 }
118
119 /// getAddrMode2OpValue - Return encoding for addrmode2 operands.
120 uint32_t getAddrMode2OpValue(const MCInst &MI, unsigned OpIdx,
121 SmallVectorImpl<MCFixup> &Fixups) const;
122
123 /// getAddrMode2OffsetOpValue - Return encoding for am2offset operands.
124 uint32_t getAddrMode2OffsetOpValue(const MCInst &MI, unsigned OpIdx,
125 SmallVectorImpl<MCFixup> &Fixups) const;
126
Jim Grosbach7eab97f2010-11-11 16:55:29 +0000127 /// getAddrMode3OffsetOpValue - Return encoding for am3offset operands.
128 uint32_t getAddrMode3OffsetOpValue(const MCInst &MI, unsigned OpIdx,
129 SmallVectorImpl<MCFixup> &Fixups) const;
130
Jim Grosbach570a9222010-11-11 01:09:40 +0000131 /// getAddrMode3OpValue - Return encoding for addrmode3 operands.
132 uint32_t getAddrMode3OpValue(const MCInst &MI, unsigned OpIdx,
133 SmallVectorImpl<MCFixup> &Fixups) const;
Jim Grosbach5d5eb9e2010-11-10 23:38:36 +0000134
Bill Wendling92b5a2e2010-11-03 01:49:29 +0000135 /// getAddrMode5OpValue - Return encoding info for 'reg +/- imm8' operand.
Jim Grosbach806e80e2010-11-03 23:52:49 +0000136 uint32_t getAddrMode5OpValue(const MCInst &MI, unsigned OpIdx,
137 SmallVectorImpl<MCFixup> &Fixups) const;
Jim Grosbach3e556122010-10-26 22:37:02 +0000138
Jim Grosbach08bd5492010-10-12 23:00:24 +0000139 /// getCCOutOpValue - Return encoding of the 's' bit.
Jim Grosbach806e80e2010-11-03 23:52:49 +0000140 unsigned getCCOutOpValue(const MCInst &MI, unsigned Op,
141 SmallVectorImpl<MCFixup> &Fixups) const {
Jim Grosbach08bd5492010-10-12 23:00:24 +0000142 // The operand is either reg0 or CPSR. The 's' bit is encoded as '0' or
143 // '1' respectively.
144 return MI.getOperand(Op).getReg() == ARM::CPSR;
145 }
Jim Grosbachef324d72010-10-12 23:53:58 +0000146
Jim Grosbach2a6a93d2010-10-12 23:18:08 +0000147 /// getSOImmOpValue - Return an encoded 12-bit shifted-immediate value.
Jim Grosbach806e80e2010-11-03 23:52:49 +0000148 unsigned getSOImmOpValue(const MCInst &MI, unsigned Op,
149 SmallVectorImpl<MCFixup> &Fixups) const {
Jim Grosbach2a6a93d2010-10-12 23:18:08 +0000150 unsigned SoImm = MI.getOperand(Op).getImm();
151 int SoImmVal = ARM_AM::getSOImmVal(SoImm);
152 assert(SoImmVal != -1 && "Not a valid so_imm value!");
153
154 // Encode rotate_imm.
155 unsigned Binary = (ARM_AM::getSOImmValRot((unsigned)SoImmVal) >> 1)
156 << ARMII::SoRotImmShift;
157
158 // Encode immed_8.
159 Binary |= ARM_AM::getSOImmValImm((unsigned)SoImmVal);
160 return Binary;
161 }
Owen Anderson5de6d842010-11-12 21:12:40 +0000162
163 /// getT2SOImmOpValue - Return an encoded 12-bit shifted-immediate value.
164 unsigned getT2SOImmOpValue(const MCInst &MI, unsigned Op,
165 SmallVectorImpl<MCFixup> &Fixups) const {
166 unsigned SoImm = MI.getOperand(Op).getImm();
167 unsigned Encoded = ARM_AM::getT2SOImmVal(SoImm);
168 assert(Encoded != ~0U && "Not a Thumb2 so_imm value?");
169 return Encoded;
170 }
Jim Grosbach08bd5492010-10-12 23:00:24 +0000171
Jim Grosbachef324d72010-10-12 23:53:58 +0000172 /// getSORegOpValue - Return an encoded so_reg shifted register value.
Jim Grosbach806e80e2010-11-03 23:52:49 +0000173 unsigned getSORegOpValue(const MCInst &MI, unsigned Op,
174 SmallVectorImpl<MCFixup> &Fixups) const;
Owen Anderson5de6d842010-11-12 21:12:40 +0000175 unsigned getT2SORegOpValue(const MCInst &MI, unsigned Op,
176 SmallVectorImpl<MCFixup> &Fixups) const;
Jim Grosbachef324d72010-10-12 23:53:58 +0000177
Jim Grosbach806e80e2010-11-03 23:52:49 +0000178 unsigned getRotImmOpValue(const MCInst &MI, unsigned Op,
179 SmallVectorImpl<MCFixup> &Fixups) const {
Jim Grosbachb35ad412010-10-13 19:56:10 +0000180 switch (MI.getOperand(Op).getImm()) {
181 default: assert (0 && "Not a valid rot_imm value!");
182 case 0: return 0;
183 case 8: return 1;
184 case 16: return 2;
185 case 24: return 3;
186 }
187 }
188
Jim Grosbach806e80e2010-11-03 23:52:49 +0000189 unsigned getImmMinusOneOpValue(const MCInst &MI, unsigned Op,
190 SmallVectorImpl<MCFixup> &Fixups) const {
Jim Grosbach8abe32a2010-10-15 17:15:16 +0000191 return MI.getOperand(Op).getImm() - 1;
192 }
Jim Grosbachd8a11c22010-10-29 23:21:03 +0000193
Jim Grosbach806e80e2010-11-03 23:52:49 +0000194 unsigned getNEONVcvtImm32OpValue(const MCInst &MI, unsigned Op,
195 SmallVectorImpl<MCFixup> &Fixups) const {
Owen Anderson498ec202010-10-27 22:49:00 +0000196 return 64 - MI.getOperand(Op).getImm();
197 }
Jim Grosbach8abe32a2010-10-15 17:15:16 +0000198
Jim Grosbach806e80e2010-11-03 23:52:49 +0000199 unsigned getBitfieldInvertedMaskOpValue(const MCInst &MI, unsigned Op,
200 SmallVectorImpl<MCFixup> &Fixups) const;
Jim Grosbach3fea191052010-10-21 22:03:21 +0000201
Jim Grosbach806e80e2010-11-03 23:52:49 +0000202 unsigned getRegisterListOpValue(const MCInst &MI, unsigned Op,
203 SmallVectorImpl<MCFixup> &Fixups) const;
204 unsigned getAddrMode6AddressOpValue(const MCInst &MI, unsigned Op,
205 SmallVectorImpl<MCFixup> &Fixups) const;
206 unsigned getAddrMode6OffsetOpValue(const MCInst &MI, unsigned Op,
207 SmallVectorImpl<MCFixup> &Fixups) const;
Jim Grosbach6b5252d2010-10-30 00:37:59 +0000208
Owen Andersonc7139a62010-11-11 19:07:48 +0000209 unsigned NEONThumb2DataIPostEncoder(const MCInst &MI,
210 unsigned EncodedValue) const;
Owen Anderson57dac882010-11-11 21:36:43 +0000211 unsigned NEONThumb2LoadStorePostEncoder(const MCInst &MI,
212 unsigned EncodedValue) const;
Owen Anderson8f143912010-11-11 23:12:55 +0000213 unsigned NEONThumb2DupPostEncoder(const MCInst &MI,
214 unsigned EncodedValue) const;
Owen Andersonc7139a62010-11-11 19:07:48 +0000215
Jim Grosbach70933262010-11-04 01:12:30 +0000216 void EmitByte(unsigned char C, raw_ostream &OS) const {
Jim Grosbach568eeed2010-09-17 18:46:17 +0000217 OS << (char)C;
Jim Grosbach568eeed2010-09-17 18:46:17 +0000218 }
219
Jim Grosbach70933262010-11-04 01:12:30 +0000220 void EmitConstant(uint64_t Val, unsigned Size, raw_ostream &OS) const {
Jim Grosbach568eeed2010-09-17 18:46:17 +0000221 // Output the constant in little endian byte order.
222 for (unsigned i = 0; i != Size; ++i) {
Jim Grosbach70933262010-11-04 01:12:30 +0000223 EmitByte(Val & 255, OS);
Jim Grosbach568eeed2010-09-17 18:46:17 +0000224 Val >>= 8;
225 }
226 }
227
Jim Grosbach568eeed2010-09-17 18:46:17 +0000228 void EncodeInstruction(const MCInst &MI, raw_ostream &OS,
229 SmallVectorImpl<MCFixup> &Fixups) const;
Jim Grosbach568eeed2010-09-17 18:46:17 +0000230};
231
232} // end anonymous namespace
233
Bill Wendling0800ce72010-11-02 22:53:11 +0000234MCCodeEmitter *llvm::createARMMCCodeEmitter(const Target &, TargetMachine &TM,
235 MCContext &Ctx) {
Jim Grosbach568eeed2010-09-17 18:46:17 +0000236 return new ARMMCCodeEmitter(TM, Ctx);
237}
238
Owen Anderson57dac882010-11-11 21:36:43 +0000239/// NEONThumb2DataIPostEncoder - Post-process encoded NEON data-processing
Owen Andersonc7139a62010-11-11 19:07:48 +0000240/// instructions, and rewrite them to their Thumb2 form if we are currently in
241/// Thumb2 mode.
242unsigned ARMMCCodeEmitter::NEONThumb2DataIPostEncoder(const MCInst &MI,
243 unsigned EncodedValue) const {
244 const ARMSubtarget &Subtarget = TM.getSubtarget<ARMSubtarget>();
245 if (Subtarget.isThumb2()) {
246 // NEON Thumb2 data-processsing encodings are very simple: bit 24 is moved
247 // to bit 12 of the high half-word (i.e. bit 28), and bits 27-24 are
248 // set to 1111.
249 unsigned Bit24 = EncodedValue & 0x01000000;
250 unsigned Bit28 = Bit24 << 4;
251 EncodedValue &= 0xEFFFFFFF;
252 EncodedValue |= Bit28;
253 EncodedValue |= 0x0F000000;
254 }
255
256 return EncodedValue;
257}
258
Owen Anderson57dac882010-11-11 21:36:43 +0000259/// NEONThumb2LoadStorePostEncoder - Post-process encoded NEON load/store
260/// instructions, and rewrite them to their Thumb2 form if we are currently in
261/// Thumb2 mode.
262unsigned ARMMCCodeEmitter::NEONThumb2LoadStorePostEncoder(const MCInst &MI,
263 unsigned EncodedValue) const {
264 const ARMSubtarget &Subtarget = TM.getSubtarget<ARMSubtarget>();
265 if (Subtarget.isThumb2()) {
266 EncodedValue &= 0xF0FFFFFF;
267 EncodedValue |= 0x09000000;
268 }
269
270 return EncodedValue;
271}
272
Owen Anderson8f143912010-11-11 23:12:55 +0000273/// NEONThumb2DupPostEncoder - Post-process encoded NEON vdup
274/// instructions, and rewrite them to their Thumb2 form if we are currently in
275/// Thumb2 mode.
276unsigned ARMMCCodeEmitter::NEONThumb2DupPostEncoder(const MCInst &MI,
277 unsigned EncodedValue) const {
278 const ARMSubtarget &Subtarget = TM.getSubtarget<ARMSubtarget>();
279 if (Subtarget.isThumb2()) {
280 EncodedValue &= 0x00FFFFFF;
281 EncodedValue |= 0xEE000000;
282 }
283
284 return EncodedValue;
285}
286
287
Owen Anderson57dac882010-11-11 21:36:43 +0000288
Jim Grosbach56ac9072010-10-08 21:45:55 +0000289/// getMachineOpValue - Return binary encoding of operand. If the machine
290/// operand requires relocation, record the relocation and return zero.
Jim Grosbach806e80e2010-11-03 23:52:49 +0000291unsigned ARMMCCodeEmitter::
292getMachineOpValue(const MCInst &MI, const MCOperand &MO,
293 SmallVectorImpl<MCFixup> &Fixups) const {
Bill Wendlingbbbdcd42010-10-14 02:33:26 +0000294 if (MO.isReg()) {
Bill Wendling0800ce72010-11-02 22:53:11 +0000295 unsigned Reg = MO.getReg();
296 unsigned RegNo = getARMRegisterNumbering(Reg);
Jim Grosbachd8a11c22010-10-29 23:21:03 +0000297
Owen Anderson90d4cf92010-10-21 20:49:13 +0000298 // Q registers are encodes as 2x their register number.
Bill Wendling0800ce72010-11-02 22:53:11 +0000299 switch (Reg) {
300 default:
301 return RegNo;
302 case ARM::Q0: case ARM::Q1: case ARM::Q2: case ARM::Q3:
303 case ARM::Q4: case ARM::Q5: case ARM::Q6: case ARM::Q7:
304 case ARM::Q8: case ARM::Q9: case ARM::Q10: case ARM::Q11:
305 case ARM::Q12: case ARM::Q13: case ARM::Q14: case ARM::Q15:
306 return 2 * RegNo;
Owen Anderson90d4cf92010-10-21 20:49:13 +0000307 }
Bill Wendlingbbbdcd42010-10-14 02:33:26 +0000308 } else if (MO.isImm()) {
Jim Grosbach56ac9072010-10-08 21:45:55 +0000309 return static_cast<unsigned>(MO.getImm());
Bill Wendlingbbbdcd42010-10-14 02:33:26 +0000310 } else if (MO.isFPImm()) {
311 return static_cast<unsigned>(APFloat(MO.getFPImm())
312 .bitcastToAPInt().getHiBits(32).getLimitedValue());
Jim Grosbach56ac9072010-10-08 21:45:55 +0000313 }
Bill Wendling0800ce72010-11-02 22:53:11 +0000314
315#ifndef NDEBUG
316 errs() << MO;
317#endif
318 llvm_unreachable(0);
Jim Grosbach56ac9072010-10-08 21:45:55 +0000319 return 0;
320}
321
Bill Wendling5df0e0a2010-11-02 22:31:46 +0000322/// getAddrModeImmOpValue - Return encoding info for 'reg +/- imm' operand.
Jim Grosbach806e80e2010-11-03 23:52:49 +0000323bool ARMMCCodeEmitter::
324EncodeAddrModeOpValues(const MCInst &MI, unsigned OpIdx, unsigned &Reg,
325 unsigned &Imm, SmallVectorImpl<MCFixup> &Fixups) const {
Jim Grosbach3e556122010-10-26 22:37:02 +0000326 const MCOperand &MO = MI.getOperand(OpIdx);
327 const MCOperand &MO1 = MI.getOperand(OpIdx + 1);
Jim Grosbach9af3d1c2010-11-01 23:45:50 +0000328
Bill Wendling92b5a2e2010-11-03 01:49:29 +0000329 Reg = getARMRegisterNumbering(MO.getReg());
330
331 int32_t SImm = MO1.getImm();
332 bool isAdd = true;
Bill Wendling5df0e0a2010-11-02 22:31:46 +0000333
Jim Grosbachab682a22010-10-28 18:34:10 +0000334 // Special value for #-0
Bill Wendling92b5a2e2010-11-03 01:49:29 +0000335 if (SImm == INT32_MIN)
336 SImm = 0;
Bill Wendling5df0e0a2010-11-02 22:31:46 +0000337
Jim Grosbachab682a22010-10-28 18:34:10 +0000338 // Immediate is always encoded as positive. The 'U' bit controls add vs sub.
Bill Wendling92b5a2e2010-11-03 01:49:29 +0000339 if (SImm < 0) {
340 SImm = -SImm;
341 isAdd = false;
342 }
Bill Wendling5df0e0a2010-11-02 22:31:46 +0000343
Bill Wendling92b5a2e2010-11-03 01:49:29 +0000344 Imm = SImm;
345 return isAdd;
346}
347
Jim Grosbachc466b932010-11-11 18:04:49 +0000348/// getBranchTargetOpValue - Return encoding info for 24-bit immediate
349/// branch target.
350uint32_t ARMMCCodeEmitter::
351getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
352 SmallVectorImpl<MCFixup> &Fixups) const {
353 const MCOperand &MO = MI.getOperand(OpIdx);
354
355 // If the destination is an immediate, we have nothing to do.
356 if (MO.isImm()) return MO.getImm();
357 assert (MO.isExpr() && "Unexpected branch target type!");
358 const MCExpr *Expr = MO.getExpr();
359 MCFixupKind Kind = MCFixupKind(ARM::fixup_arm_branch);
360 Fixups.push_back(MCFixup::Create(0, Expr, Kind));
361
362 // All of the information is in the fixup.
363 return 0;
364}
365
Bill Wendling92b5a2e2010-11-03 01:49:29 +0000366/// getAddrModeImm12OpValue - Return encoding info for 'reg +/- imm12' operand.
Jim Grosbach806e80e2010-11-03 23:52:49 +0000367uint32_t ARMMCCodeEmitter::
368getAddrModeImm12OpValue(const MCInst &MI, unsigned OpIdx,
369 SmallVectorImpl<MCFixup> &Fixups) const {
Bill Wendling92b5a2e2010-11-03 01:49:29 +0000370 // {17-13} = reg
371 // {12} = (U)nsigned (add == '1', sub == '0')
372 // {11-0} = imm12
373 unsigned Reg, Imm12;
Jim Grosbach70933262010-11-04 01:12:30 +0000374 bool isAdd = true;
375 // If The first operand isn't a register, we have a label reference.
376 const MCOperand &MO = MI.getOperand(OpIdx);
377 if (!MO.isReg()) {
Jim Grosbach679cbd32010-11-09 01:37:15 +0000378 Reg = getARMRegisterNumbering(ARM::PC); // Rn is PC.
Jim Grosbach70933262010-11-04 01:12:30 +0000379 Imm12 = 0;
380
381 assert(MO.isExpr() && "Unexpected machine operand type!");
382 const MCExpr *Expr = MO.getExpr();
383 MCFixupKind Kind = MCFixupKind(ARM::fixup_arm_pcrel_12);
384 Fixups.push_back(MCFixup::Create(0, Expr, Kind));
385
386 ++MCNumCPRelocations;
387 } else
388 isAdd = EncodeAddrModeOpValues(MI, OpIdx, Reg, Imm12, Fixups);
Bill Wendling92b5a2e2010-11-03 01:49:29 +0000389
Bill Wendling92b5a2e2010-11-03 01:49:29 +0000390 uint32_t Binary = Imm12 & 0xfff;
391 // Immediate is always encoded as positive. The 'U' bit controls add vs sub.
Jim Grosbachab682a22010-10-28 18:34:10 +0000392 if (isAdd)
Bill Wendling92b5a2e2010-11-03 01:49:29 +0000393 Binary |= (1 << 12);
394 Binary |= (Reg << 13);
395 return Binary;
396}
397
Jim Grosbach54fea632010-11-09 17:20:53 +0000398uint32_t ARMMCCodeEmitter::
399getLdStSORegOpValue(const MCInst &MI, unsigned OpIdx,
400 SmallVectorImpl<MCFixup> &Fixups) const {
401 const MCOperand &MO = MI.getOperand(OpIdx);
402 const MCOperand &MO1 = MI.getOperand(OpIdx+1);
403 const MCOperand &MO2 = MI.getOperand(OpIdx+2);
404 unsigned Rn = getARMRegisterNumbering(MO.getReg());
405 unsigned Rm = getARMRegisterNumbering(MO1.getReg());
Jim Grosbach54fea632010-11-09 17:20:53 +0000406 unsigned ShImm = ARM_AM::getAM2Offset(MO2.getImm());
407 bool isAdd = ARM_AM::getAM2Op(MO2.getImm()) == ARM_AM::add;
Jim Grosbach99f53d12010-11-15 20:47:07 +0000408 ARM_AM::ShiftOpc ShOp = ARM_AM::getAM2ShiftOpc(MO2.getImm());
409 unsigned SBits = getShiftOp(ShOp);
Jim Grosbach54fea632010-11-09 17:20:53 +0000410
411 // {16-13} = Rn
412 // {12} = isAdd
413 // {11-0} = shifter
414 // {3-0} = Rm
415 // {4} = 0
416 // {6-5} = type
417 // {11-7} = imm
Jim Grosbach570a9222010-11-11 01:09:40 +0000418 uint32_t Binary = Rm;
Jim Grosbach54fea632010-11-09 17:20:53 +0000419 Binary |= Rn << 13;
420 Binary |= SBits << 5;
421 Binary |= ShImm << 7;
422 if (isAdd)
423 Binary |= 1 << 12;
424 return Binary;
425}
426
Jim Grosbach570a9222010-11-11 01:09:40 +0000427uint32_t ARMMCCodeEmitter::
Jim Grosbach99f53d12010-11-15 20:47:07 +0000428getAddrMode2OpValue(const MCInst &MI, unsigned OpIdx,
429 SmallVectorImpl<MCFixup> &Fixups) const {
430 // {17-14} Rn
431 // {13} 1 == imm12, 0 == Rm
432 // {12} isAdd
433 // {11-0} imm12/Rm
434 const MCOperand &MO = MI.getOperand(OpIdx);
435 unsigned Rn = getARMRegisterNumbering(MO.getReg());
436 uint32_t Binary = getAddrMode2OffsetOpValue(MI, OpIdx + 1, Fixups);
437 Binary |= Rn << 14;
438 return Binary;
439}
440
441uint32_t ARMMCCodeEmitter::
442getAddrMode2OffsetOpValue(const MCInst &MI, unsigned OpIdx,
443 SmallVectorImpl<MCFixup> &Fixups) const {
444 // {13} 1 == imm12, 0 == Rm
445 // {12} isAdd
446 // {11-0} imm12/Rm
447 const MCOperand &MO = MI.getOperand(OpIdx);
448 const MCOperand &MO1 = MI.getOperand(OpIdx+1);
449 unsigned Imm = MO1.getImm();
450 bool isAdd = ARM_AM::getAM2Op(Imm) == ARM_AM::add;
451 bool isReg = MO.getReg() != 0;
452 uint32_t Binary = ARM_AM::getAM2Offset(Imm);
453 // if reg +/- reg, Rm will be non-zero. Otherwise, we have reg +/- imm12
454 if (isReg) {
455 ARM_AM::ShiftOpc ShOp = ARM_AM::getAM2ShiftOpc(Imm);
456 Binary <<= 7; // Shift amount is bits [11:7]
457 Binary |= getShiftOp(ShOp) << 5; // Shift type is bits [6:5]
458 Binary |= getARMRegisterNumbering(MO.getReg()); // Rm is bits [3:0]
459 }
460 return Binary | (isAdd << 12) | (isReg << 13);
461}
462
463uint32_t ARMMCCodeEmitter::
Jim Grosbach7eab97f2010-11-11 16:55:29 +0000464getAddrMode3OffsetOpValue(const MCInst &MI, unsigned OpIdx,
465 SmallVectorImpl<MCFixup> &Fixups) const {
466 // {9} 1 == imm8, 0 == Rm
467 // {8} isAdd
468 // {7-4} imm7_4/zero
469 // {3-0} imm3_0/Rm
470 const MCOperand &MO = MI.getOperand(OpIdx);
471 const MCOperand &MO1 = MI.getOperand(OpIdx+1);
472 unsigned Imm = MO1.getImm();
473 bool isAdd = ARM_AM::getAM3Op(Imm) == ARM_AM::add;
474 bool isImm = MO.getReg() == 0;
475 uint32_t Imm8 = ARM_AM::getAM3Offset(Imm);
476 // if reg +/- reg, Rm will be non-zero. Otherwise, we have reg +/- imm8
477 if (!isImm)
478 Imm8 = getARMRegisterNumbering(MO.getReg());
479 return Imm8 | (isAdd << 8) | (isImm << 9);
480}
481
482uint32_t ARMMCCodeEmitter::
Jim Grosbach570a9222010-11-11 01:09:40 +0000483getAddrMode3OpValue(const MCInst &MI, unsigned OpIdx,
484 SmallVectorImpl<MCFixup> &Fixups) const {
485 // {13} 1 == imm8, 0 == Rm
486 // {12-9} Rn
487 // {8} isAdd
488 // {7-4} imm7_4/zero
489 // {3-0} imm3_0/Rm
490 const MCOperand &MO = MI.getOperand(OpIdx);
491 const MCOperand &MO1 = MI.getOperand(OpIdx+1);
492 const MCOperand &MO2 = MI.getOperand(OpIdx+2);
493 unsigned Rn = getARMRegisterNumbering(MO.getReg());
494 unsigned Imm = MO2.getImm();
495 bool isAdd = ARM_AM::getAM3Op(Imm) == ARM_AM::add;
496 bool isImm = MO1.getReg() == 0;
497 uint32_t Imm8 = ARM_AM::getAM3Offset(Imm);
498 // if reg +/- reg, Rm will be non-zero. Otherwise, we have reg +/- imm8
499 if (!isImm)
500 Imm8 = getARMRegisterNumbering(MO1.getReg());
501 return (Rn << 9) | Imm8 | (isAdd << 8) | (isImm << 13);
502}
503
Bill Wendling92b5a2e2010-11-03 01:49:29 +0000504/// getAddrMode5OpValue - Return encoding info for 'reg +/- imm12' operand.
Jim Grosbach806e80e2010-11-03 23:52:49 +0000505uint32_t ARMMCCodeEmitter::
506getAddrMode5OpValue(const MCInst &MI, unsigned OpIdx,
507 SmallVectorImpl<MCFixup> &Fixups) const {
Bill Wendling92b5a2e2010-11-03 01:49:29 +0000508 // {12-9} = reg
509 // {8} = (U)nsigned (add == '1', sub == '0')
510 // {7-0} = imm8
511 unsigned Reg, Imm8;
Jim Grosbach70933262010-11-04 01:12:30 +0000512 // If The first operand isn't a register, we have a label reference.
513 const MCOperand &MO = MI.getOperand(OpIdx);
514 if (!MO.isReg()) {
Jim Grosbach679cbd32010-11-09 01:37:15 +0000515 Reg = getARMRegisterNumbering(ARM::PC); // Rn is PC.
Jim Grosbach70933262010-11-04 01:12:30 +0000516 Imm8 = 0;
517
518 assert(MO.isExpr() && "Unexpected machine operand type!");
519 const MCExpr *Expr = MO.getExpr();
520 MCFixupKind Kind = MCFixupKind(ARM::fixup_arm_vfp_pcrel_12);
521 Fixups.push_back(MCFixup::Create(0, Expr, Kind));
522
523 ++MCNumCPRelocations;
524 } else
525 EncodeAddrModeOpValues(MI, OpIdx, Reg, Imm8, Fixups);
Bill Wendling92b5a2e2010-11-03 01:49:29 +0000526
Bill Wendling92b5a2e2010-11-03 01:49:29 +0000527 uint32_t Binary = ARM_AM::getAM5Offset(Imm8);
528 // Immediate is always encoded as positive. The 'U' bit controls add vs sub.
529 if (ARM_AM::getAM5Op(Imm8) == ARM_AM::add)
530 Binary |= (1 << 8);
531 Binary |= (Reg << 9);
Jim Grosbach3e556122010-10-26 22:37:02 +0000532 return Binary;
533}
534
Jim Grosbach806e80e2010-11-03 23:52:49 +0000535unsigned ARMMCCodeEmitter::
536getSORegOpValue(const MCInst &MI, unsigned OpIdx,
537 SmallVectorImpl<MCFixup> &Fixups) const {
Bill Wendling0800ce72010-11-02 22:53:11 +0000538 // Sub-operands are [reg, reg, imm]. The first register is Rm, the reg to be
539 // shifted. The second is either Rs, the amount to shift by, or reg0 in which
540 // case the imm contains the amount to shift by.
Jim Grosbach35b2de02010-11-03 22:03:20 +0000541 //
Jim Grosbachef324d72010-10-12 23:53:58 +0000542 // {3-0} = Rm.
Bill Wendling0800ce72010-11-02 22:53:11 +0000543 // {4} = 1 if reg shift, 0 if imm shift
Jim Grosbachef324d72010-10-12 23:53:58 +0000544 // {6-5} = type
545 // If reg shift:
Jim Grosbachef324d72010-10-12 23:53:58 +0000546 // {11-8} = Rs
Bill Wendling0800ce72010-11-02 22:53:11 +0000547 // {7} = 0
Jim Grosbachef324d72010-10-12 23:53:58 +0000548 // else (imm shift)
549 // {11-7} = imm
550
551 const MCOperand &MO = MI.getOperand(OpIdx);
552 const MCOperand &MO1 = MI.getOperand(OpIdx + 1);
553 const MCOperand &MO2 = MI.getOperand(OpIdx + 2);
554 ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(MO2.getImm());
555
556 // Encode Rm.
557 unsigned Binary = getARMRegisterNumbering(MO.getReg());
558
559 // Encode the shift opcode.
560 unsigned SBits = 0;
561 unsigned Rs = MO1.getReg();
562 if (Rs) {
563 // Set shift operand (bit[7:4]).
564 // LSL - 0001
565 // LSR - 0011
566 // ASR - 0101
567 // ROR - 0111
568 // RRX - 0110 and bit[11:8] clear.
569 switch (SOpc) {
570 default: llvm_unreachable("Unknown shift opc!");
571 case ARM_AM::lsl: SBits = 0x1; break;
572 case ARM_AM::lsr: SBits = 0x3; break;
573 case ARM_AM::asr: SBits = 0x5; break;
574 case ARM_AM::ror: SBits = 0x7; break;
575 case ARM_AM::rrx: SBits = 0x6; break;
576 }
577 } else {
578 // Set shift operand (bit[6:4]).
579 // LSL - 000
580 // LSR - 010
581 // ASR - 100
582 // ROR - 110
583 switch (SOpc) {
584 default: llvm_unreachable("Unknown shift opc!");
585 case ARM_AM::lsl: SBits = 0x0; break;
586 case ARM_AM::lsr: SBits = 0x2; break;
587 case ARM_AM::asr: SBits = 0x4; break;
588 case ARM_AM::ror: SBits = 0x6; break;
589 }
590 }
Bill Wendling0800ce72010-11-02 22:53:11 +0000591
Jim Grosbachef324d72010-10-12 23:53:58 +0000592 Binary |= SBits << 4;
593 if (SOpc == ARM_AM::rrx)
594 return Binary;
595
596 // Encode the shift operation Rs or shift_imm (except rrx).
597 if (Rs) {
598 // Encode Rs bit[11:8].
599 assert(ARM_AM::getSORegOffset(MO2.getImm()) == 0);
600 return Binary | (getARMRegisterNumbering(Rs) << ARMII::RegRsShift);
601 }
602
603 // Encode shift_imm bit[11:7].
604 return Binary | ARM_AM::getSORegOffset(MO2.getImm()) << 7;
605}
606
Jim Grosbach806e80e2010-11-03 23:52:49 +0000607unsigned ARMMCCodeEmitter::
Owen Anderson5de6d842010-11-12 21:12:40 +0000608getT2SORegOpValue(const MCInst &MI, unsigned OpIdx,
609 SmallVectorImpl<MCFixup> &Fixups) const {
610 // Sub-operands are [reg, imm]. The first register is Rm, the reg to be
611 // shifted. The second is the amount to shift by.
612 //
613 // {3-0} = Rm.
614 // {4} = 0
615 // {6-5} = type
616 // {11-7} = imm
617
618 const MCOperand &MO = MI.getOperand(OpIdx);
619 const MCOperand &MO1 = MI.getOperand(OpIdx + 1);
620 ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(MO1.getImm());
621
622 // Encode Rm.
623 unsigned Binary = getARMRegisterNumbering(MO.getReg());
624
625 // Encode the shift opcode.
626 unsigned SBits = 0;
627 // Set shift operand (bit[6:4]).
628 // LSL - 000
629 // LSR - 010
630 // ASR - 100
631 // ROR - 110
632 switch (SOpc) {
633 default: llvm_unreachable("Unknown shift opc!");
634 case ARM_AM::lsl: SBits = 0x0; break;
635 case ARM_AM::lsr: SBits = 0x2; break;
636 case ARM_AM::asr: SBits = 0x4; break;
637 case ARM_AM::ror: SBits = 0x6; break;
638 }
639
640 Binary |= SBits << 4;
641 if (SOpc == ARM_AM::rrx)
642 return Binary;
643
644 // Encode shift_imm bit[11:7].
645 return Binary | ARM_AM::getSORegOffset(MO1.getImm()) << 7;
646}
647
648unsigned ARMMCCodeEmitter::
Jim Grosbach806e80e2010-11-03 23:52:49 +0000649getBitfieldInvertedMaskOpValue(const MCInst &MI, unsigned Op,
650 SmallVectorImpl<MCFixup> &Fixups) const {
Jim Grosbach3fea191052010-10-21 22:03:21 +0000651 // 10 bits. lower 5 bits are are the lsb of the mask, high five bits are the
652 // msb of the mask.
653 const MCOperand &MO = MI.getOperand(Op);
654 uint32_t v = ~MO.getImm();
655 uint32_t lsb = CountTrailingZeros_32(v);
656 uint32_t msb = (32 - CountLeadingZeros_32 (v)) - 1;
657 assert (v != 0 && lsb < 32 && msb < 32 && "Illegal bitfield mask!");
658 return lsb | (msb << 5);
659}
660
Jim Grosbach806e80e2010-11-03 23:52:49 +0000661unsigned ARMMCCodeEmitter::
662getRegisterListOpValue(const MCInst &MI, unsigned Op,
Bill Wendling5e559a22010-11-09 00:30:18 +0000663 SmallVectorImpl<MCFixup> &Fixups) const {
664 // Convert a list of GPRs into a bitfield (R0 -> bit 0). For each
665 // register in the list, set the corresponding bit.
666 unsigned Binary = 0;
667 for (unsigned i = Op, e = MI.getNumOperands(); i < e; ++i) {
668 unsigned regno = getARMRegisterNumbering(MI.getOperand(i).getReg());
669 Binary |= 1 << regno;
670 }
Jim Grosbach6b5252d2010-10-30 00:37:59 +0000671 return Binary;
672}
673
Jim Grosbach806e80e2010-11-03 23:52:49 +0000674unsigned ARMMCCodeEmitter::
675getAddrMode6AddressOpValue(const MCInst &MI, unsigned Op,
676 SmallVectorImpl<MCFixup> &Fixups) const {
Owen Andersond9aa7d32010-11-02 00:05:05 +0000677 const MCOperand &Reg = MI.getOperand(Op);
Bill Wendling0800ce72010-11-02 22:53:11 +0000678 const MCOperand &Imm = MI.getOperand(Op + 1);
Jim Grosbach35b2de02010-11-03 22:03:20 +0000679
Owen Andersond9aa7d32010-11-02 00:05:05 +0000680 unsigned RegNo = getARMRegisterNumbering(Reg.getReg());
Bill Wendling0800ce72010-11-02 22:53:11 +0000681 unsigned Align = 0;
682
683 switch (Imm.getImm()) {
684 default: break;
685 case 2:
686 case 4:
687 case 8: Align = 0x01; break;
688 case 16: Align = 0x02; break;
689 case 32: Align = 0x03; break;
Owen Andersond9aa7d32010-11-02 00:05:05 +0000690 }
Bill Wendling0800ce72010-11-02 22:53:11 +0000691
Owen Andersond9aa7d32010-11-02 00:05:05 +0000692 return RegNo | (Align << 4);
693}
694
Jim Grosbach806e80e2010-11-03 23:52:49 +0000695unsigned ARMMCCodeEmitter::
696getAddrMode6OffsetOpValue(const MCInst &MI, unsigned Op,
697 SmallVectorImpl<MCFixup> &Fixups) const {
Bill Wendling0800ce72010-11-02 22:53:11 +0000698 const MCOperand &MO = MI.getOperand(Op);
699 if (MO.getReg() == 0) return 0x0D;
700 return MO.getReg();
Owen Andersoncf667be2010-11-02 01:24:55 +0000701}
702
Jim Grosbach568eeed2010-09-17 18:46:17 +0000703void ARMMCCodeEmitter::
704EncodeInstruction(const MCInst &MI, raw_ostream &OS,
Jim Grosbach806e80e2010-11-03 23:52:49 +0000705 SmallVectorImpl<MCFixup> &Fixups) const {
Jim Grosbachd6d4b422010-10-07 22:12:50 +0000706 // Pseudo instructions don't get encoded.
Bill Wendling7292e0a2010-11-02 22:44:12 +0000707 const TargetInstrDesc &Desc = TII.get(MI.getOpcode());
Jim Grosbache50e6bc2010-11-11 23:41:09 +0000708 uint64_t TSFlags = Desc.TSFlags;
709 if ((TSFlags & ARMII::FormMask) == ARMII::Pseudo)
Jim Grosbachd6d4b422010-10-07 22:12:50 +0000710 return;
Jim Grosbache50e6bc2010-11-11 23:41:09 +0000711 int Size;
712 // Basic size info comes from the TSFlags field.
713 switch ((TSFlags & ARMII::SizeMask) >> ARMII::SizeShift) {
714 default: llvm_unreachable("Unexpected instruction size!");
715 case ARMII::Size2Bytes: Size = 2; break;
716 case ARMII::Size4Bytes: Size = 4; break;
717 }
718 EmitConstant(getBinaryCodeForInstr(MI, Fixups), Size, OS);
Bill Wendling7292e0a2010-11-02 22:44:12 +0000719 ++MCNumEmitted; // Keep track of the # of mi's emitted.
Jim Grosbach568eeed2010-09-17 18:46:17 +0000720}
Jim Grosbach9af82ba2010-10-07 21:57:55 +0000721
Jim Grosbach806e80e2010-11-03 23:52:49 +0000722#include "ARMGenMCCodeEmitter.inc"