blob: 97df9e603da85ce1fe142cbf5ec6250f1ab13adf [file] [log] [blame]
Evan Cheng148b6a42007-07-05 21:15:40 +00001//===-- ARM/ARMCodeEmitter.cpp - Convert ARM code to machine code ---------===//
2//
3// The LLVM Compiler Infrastructure
4//
Chris Lattner4ee451d2007-12-29 20:36:04 +00005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Evan Cheng148b6a42007-07-05 21:15:40 +00007//
8//===----------------------------------------------------------------------===//
9//
10// This file contains the pass that transforms the ARM machine instructions into
11// relocatable machine code.
12//
13//===----------------------------------------------------------------------===//
14
15#define DEBUG_TYPE "arm-emitter"
16#include "ARMInstrInfo.h"
17#include "ARMSubtarget.h"
18#include "ARMTargetMachine.h"
Evan Cheng0ff94f72007-08-07 01:37:15 +000019#include "ARMRelocations.h"
20#include "ARMAddressingModes.h"
Evan Cheng148b6a42007-07-05 21:15:40 +000021#include "ARM.h"
22#include "llvm/PassManager.h"
23#include "llvm/CodeGen/MachineCodeEmitter.h"
24#include "llvm/CodeGen/MachineFunctionPass.h"
25#include "llvm/CodeGen/MachineInstr.h"
26#include "llvm/CodeGen/Passes.h"
27#include "llvm/Function.h"
28#include "llvm/ADT/Statistic.h"
29#include "llvm/Support/Compiler.h"
30using namespace llvm;
31
32STATISTIC(NumEmitted, "Number of machine instructions emitted");
33
34namespace {
35 class VISIBILITY_HIDDEN Emitter : public MachineFunctionPass {
36 const ARMInstrInfo *II;
37 const TargetData *TD;
38 TargetMachine &TM;
39 MachineCodeEmitter &MCE;
40 public:
41 static char ID;
42 explicit Emitter(TargetMachine &tm, MachineCodeEmitter &mce)
43 : MachineFunctionPass((intptr_t)&ID), II(0), TD(0), TM(tm),
44 MCE(mce) {}
45 Emitter(TargetMachine &tm, MachineCodeEmitter &mce,
46 const ARMInstrInfo &ii, const TargetData &td)
47 : MachineFunctionPass((intptr_t)&ID), II(&ii), TD(&td), TM(tm),
48 MCE(mce) {}
49
50 bool runOnMachineFunction(MachineFunction &MF);
51
52 virtual const char *getPassName() const {
53 return "ARM Machine Code Emitter";
54 }
55
56 void emitInstruction(const MachineInstr &MI);
Evan Cheng0ff94f72007-08-07 01:37:15 +000057 int getMachineOpValue(const MachineInstr &MI, unsigned OpIndex);
58 unsigned getBaseOpcodeFor(const TargetInstrDescriptor *TID);
Raul Herbster9c1a3822007-08-30 23:29:26 +000059 unsigned getBinaryCodeForInstr(const MachineInstr &MI);
Evan Cheng0ff94f72007-08-07 01:37:15 +000060
61 void emitGlobalAddressForCall(GlobalValue *GV, bool DoesntNeedStub);
62 void emitExternalSymbolAddress(const char *ES, unsigned Reloc);
63 void emitConstPoolAddress(unsigned CPI, unsigned Reloc,
64 int Disp = 0, unsigned PCAdj = 0 );
65 void emitJumpTableAddress(unsigned JTI, unsigned Reloc,
66 unsigned PCAdj = 0);
Raul Herbster9c1a3822007-08-30 23:29:26 +000067 void emitGlobalConstant(const Constant *CV);
68 void emitMachineBasicBlock(MachineBasicBlock *BB);
Evan Cheng148b6a42007-07-05 21:15:40 +000069
70 private:
Evan Cheng0ff94f72007-08-07 01:37:15 +000071 int getShiftOp(const MachineOperand &MO);
Evan Cheng148b6a42007-07-05 21:15:40 +000072
73 };
74 char Emitter::ID = 0;
75}
76
77/// createARMCodeEmitterPass - Return a pass that emits the collected ARM code
78/// to the specified MCE object.
79FunctionPass *llvm::createARMCodeEmitterPass(ARMTargetMachine &TM,
80 MachineCodeEmitter &MCE) {
81 return new Emitter(TM, MCE);
82}
83
84bool Emitter::runOnMachineFunction(MachineFunction &MF) {
85 assert((MF.getTarget().getRelocationModel() != Reloc::Default ||
86 MF.getTarget().getRelocationModel() != Reloc::Static) &&
87 "JIT relocation model must be set to static or default!");
88 II = ((ARMTargetMachine&)MF.getTarget()).getInstrInfo();
89 TD = ((ARMTargetMachine&)MF.getTarget()).getTargetData();
90
91 do {
92 MCE.startFunction(MF);
93 for (MachineFunction::iterator MBB = MF.begin(), E = MF.end();
94 MBB != E; ++MBB) {
95 MCE.StartMachineBasicBlock(MBB);
96 for (MachineBasicBlock::const_iterator I = MBB->begin(), E = MBB->end();
97 I != E; ++I)
98 emitInstruction(*I);
99 }
100 } while (MCE.finishFunction(MF));
101
102 return false;
103}
104
Raul Herbster9c1a3822007-08-30 23:29:26 +0000105/// getBaseOpcodeFor - Return the opcode value
Evan Cheng0ff94f72007-08-07 01:37:15 +0000106unsigned Emitter::getBaseOpcodeFor(const TargetInstrDescriptor *TID) {
107 return (TID->TSFlags & ARMII::OpcodeMask) >> ARMII::OpcodeShift;
108}
109
Raul Herbster9c1a3822007-08-30 23:29:26 +0000110/// getShiftOp - Verify which is the shift opcode (bit[6:5]) of the
111/// machine operand.
Evan Cheng0ff94f72007-08-07 01:37:15 +0000112int Emitter::getShiftOp(const MachineOperand &MO) {
113 unsigned ShiftOp = 0x0;
114 switch(ARM_AM::getAM2ShiftOpc(MO.getImmedValue())) {
115 default: assert(0 && "Unknown shift opc!");
116 case ARM_AM::asr:
117 ShiftOp = 0X2;
118 break;
119 case ARM_AM::lsl:
120 ShiftOp = 0X0;
121 break;
122 case ARM_AM::lsr:
123 ShiftOp = 0X1;
124 break;
125 case ARM_AM::ror:
126 case ARM_AM::rrx:
127 ShiftOp = 0X3;
128 break;
129 }
130 return ShiftOp;
131}
132
133int Emitter::getMachineOpValue(const MachineInstr &MI, unsigned OpIndex) {
134 intptr_t rv = 0;
135 const MachineOperand &MO = MI.getOperand(OpIndex);
136 if (MO.isRegister()) {
137 assert(MRegisterInfo::isPhysicalRegister(MO.getReg()));
138 rv = ARMRegisterInfo::getRegisterNumbering(MO.getReg());
139 } else if (MO.isImmediate()) {
140 rv = MO.getImmedValue();
Raul Herbster9c1a3822007-08-30 23:29:26 +0000141 } else if (MO.isGlobalAddress()) {
142 emitGlobalAddressForCall(MO.getGlobal(), false);
143 } else if (MO.isExternalSymbol()) {
144 emitExternalSymbolAddress(MO.getSymbolName(), ARM::reloc_arm_relative);
145 } else if (MO.isConstantPoolIndex()) {
146 emitConstPoolAddress(MO.getConstantPoolIndex(), ARM::reloc_arm_relative);
147 } else if (MO.isJumpTableIndex()) {
148 emitJumpTableAddress(MO.getJumpTableIndex(), ARM::reloc_arm_relative);
149 } else if (MO.isMachineBasicBlock()) {
150 emitMachineBasicBlock(MO.getMachineBasicBlock());
Evan Cheng0ff94f72007-08-07 01:37:15 +0000151 }
Raul Herbster9c1a3822007-08-30 23:29:26 +0000152
Evan Cheng0ff94f72007-08-07 01:37:15 +0000153 return rv;
154}
155
156/// emitGlobalAddressForCall - Emit the specified address to the code stream
157/// assuming this is part of a function call, which is PC relative.
158///
159void Emitter::emitGlobalAddressForCall(GlobalValue *GV, bool DoesntNeedStub) {
160 MCE.addRelocation(MachineRelocation::getGV(MCE.getCurrentPCOffset(),
161 ARM::reloc_arm_branch, GV, 0,
162 DoesntNeedStub));
163}
164
165/// emitExternalSymbolAddress - Arrange for the address of an external symbol to
166/// be emitted to the current location in the function, and allow it to be PC
167/// relative.
168void Emitter::emitExternalSymbolAddress(const char *ES, unsigned Reloc) {
169 MCE.addRelocation(MachineRelocation::getExtSym(MCE.getCurrentPCOffset(),
170 Reloc, ES));
171}
172
173/// emitConstPoolAddress - Arrange for the address of an constant pool
174/// to be emitted to the current location in the function, and allow it to be PC
175/// relative.
176void Emitter::emitConstPoolAddress(unsigned CPI, unsigned Reloc,
177 int Disp /* = 0 */,
178 unsigned PCAdj /* = 0 */) {
179 MCE.addRelocation(MachineRelocation::getConstPool(MCE.getCurrentPCOffset(),
180 Reloc, CPI, PCAdj));
181}
182
183/// emitJumpTableAddress - Arrange for the address of a jump table to
184/// be emitted to the current location in the function, and allow it to be PC
185/// relative.
186void Emitter::emitJumpTableAddress(unsigned JTI, unsigned Reloc,
187 unsigned PCAdj /* = 0 */) {
188 MCE.addRelocation(MachineRelocation::getJumpTable(MCE.getCurrentPCOffset(),
189 Reloc, JTI, PCAdj));
190}
191
Raul Herbster9c1a3822007-08-30 23:29:26 +0000192/// emitMachineBasicBlock - Emit the specified address basic block.
193void Emitter::emitMachineBasicBlock(MachineBasicBlock *BB) {
194 MCE.addRelocation(MachineRelocation::getBB(MCE.getCurrentPCOffset(),
195 ARM::reloc_arm_branch, BB));
196}
Evan Cheng0ff94f72007-08-07 01:37:15 +0000197
Evan Cheng148b6a42007-07-05 21:15:40 +0000198void Emitter::emitInstruction(const MachineInstr &MI) {
199 NumEmitted++; // Keep track of the # of mi's emitted
Evan Cheng0ff94f72007-08-07 01:37:15 +0000200 MCE.emitWordLE(getBinaryCodeForInstr(MI));
201}
202
203unsigned Emitter::getBinaryCodeForInstr(const MachineInstr &MI) {
204 const TargetInstrDescriptor *Desc = MI.getInstrDescriptor();
205 const unsigned opcode = MI.getOpcode();
Raul Herbster9c1a3822007-08-30 23:29:26 +0000206 // initial instruction mask
Evan Cheng0ff94f72007-08-07 01:37:15 +0000207 unsigned Value = 0xE0000000;
208 unsigned op;
209
210 switch (Desc->TSFlags & ARMII::AddrModeMask) {
211 case ARMII::AddrModeNone: {
212 switch(Desc->TSFlags & ARMII::FormMask) {
213 default: {
214 assert(0 && "Unknown instruction subtype!");
Raul Herbster9c1a3822007-08-30 23:29:26 +0000215 // treat special instruction CLZ
Evan Cheng0ff94f72007-08-07 01:37:15 +0000216 if(opcode == ARM::CLZ) {
217 // set first operand
218 op = getMachineOpValue(MI,0);
Raul Herbster9c1a3822007-08-30 23:29:26 +0000219 Value |= op << ARMII::RegRdShift;
Evan Cheng0ff94f72007-08-07 01:37:15 +0000220
221 // set second operand
222 op = getMachineOpValue(MI,1);
223 Value |= op;
224 }
225 break;
226 }
Raul Herbster9c1a3822007-08-30 23:29:26 +0000227 case ARMII::MulSMLAW:
228 case ARMII::MulSMULW:
229 // set bit W(21)
230 Value |= 1 << 21;
231 case ARMII::MulSMLA:
232 case ARMII::MulSMUL: {
233 // set bit W(21)
234 Value |= 1 << 24;
Evan Cheng0ff94f72007-08-07 01:37:15 +0000235
Raul Herbster9c1a3822007-08-30 23:29:26 +0000236 // set opcode (bit[7:4]). For more information, see ARM-ARM page A3-31
237 // SMLA<x><y> - 1yx0
238 // SMLAW<y> - 1y00
239 // SMULW<y> - 1y10
240 // SMUL<x><y> - 1yx0
241 unsigned char BaseOpcode = getBaseOpcodeFor(Desc);
242 Value |= BaseOpcode << 4;
243
244 unsigned Format = (Desc->TSFlags & ARMII::FormMask);
245 if (Format == ARMII::MulSMUL)
246 Value |= 1 << 22;
247
248 // set first operand
249 op = getMachineOpValue(MI,0);
250 Value |= op << ARMII::RegRnShift;
251
252 // set second operand
253 op = getMachineOpValue(MI,1);
254 Value |= op;
255
256 // set third operand
257 op = getMachineOpValue(MI,2);
258 Value |= op << ARMII::RegRsShift;
259
260 // instructions SMLA and SMLAW have a fourth operand
261 if (Format != ARMII::MulSMULW && Format != ARMII::MulSMUL) {
262 op = getMachineOpValue(MI,3);
263 Value |= op << ARMII::RegRdShift;
264 }
265
266 break;
267 }
268 case ARMII::MulFrm: {
269 // bit[7:4] is always 9
270 Value |= 9 << 4;
271 // set opcode (bit[23:20])
Evan Cheng0ff94f72007-08-07 01:37:15 +0000272 unsigned char BaseOpcode = getBaseOpcodeFor(Desc);
273 Value |= BaseOpcode << 20;
274
275 bool isMUL = opcode == ARM::MUL;
276 bool isMLA = opcode == ARM::MLA;
277
278 // set first operand
279 op = getMachineOpValue(MI,0);
Raul Herbster9c1a3822007-08-30 23:29:26 +0000280 Value |= op << (isMUL || isMLA ? ARMII::RegRnShift : ARMII::RegRdShift);
Evan Cheng0ff94f72007-08-07 01:37:15 +0000281
282 // set second operand
283 op = getMachineOpValue(MI,1);
Raul Herbster9c1a3822007-08-30 23:29:26 +0000284 Value |= op << (isMUL || isMLA ? 0 : ARMII::RegRnShift);
Evan Cheng0ff94f72007-08-07 01:37:15 +0000285
286 // set third operand
287 op = getMachineOpValue(MI,2);
Raul Herbster9c1a3822007-08-30 23:29:26 +0000288 Value |= op << (isMUL || isMLA ? ARMII::RegRsShift : 0);
Evan Cheng0ff94f72007-08-07 01:37:15 +0000289
Raul Herbster9c1a3822007-08-30 23:29:26 +0000290 // multiply instructions (except MUL), have a fourth operand
Evan Cheng0ff94f72007-08-07 01:37:15 +0000291 if (!isMUL) {
292 op = getMachineOpValue(MI,3);
Raul Herbster9c1a3822007-08-30 23:29:26 +0000293 Value |= op << (isMLA ? ARMII::RegRdShift : ARMII::RegRsShift);
Evan Cheng0ff94f72007-08-07 01:37:15 +0000294 }
295
296 break;
297 }
298 case ARMII::Branch: {
Raul Herbster9c1a3822007-08-30 23:29:26 +0000299 // set opcode (bit[27:24])
Evan Cheng0ff94f72007-08-07 01:37:15 +0000300 unsigned BaseOpcode = getBaseOpcodeFor(Desc);
301 Value |= BaseOpcode << 24;
302
Raul Herbster9c1a3822007-08-30 23:29:26 +0000303 // set signed_immed_24 field
Evan Cheng0ff94f72007-08-07 01:37:15 +0000304 op = getMachineOpValue(MI,0);
305 Value |= op;
306
Raul Herbster9c1a3822007-08-30 23:29:26 +0000307 // if it is a conditional branch, set cond field
308 if (opcode == ARM::Bcc) {
309 op = getMachineOpValue(MI,1);
310 Value &= 0x0FFFFFFF; // clear conditional field
311 Value |= op << 28; // set conditional field
312 }
313
Evan Cheng0ff94f72007-08-07 01:37:15 +0000314 break;
315 }
316 case ARMII::BranchMisc: {
Raul Herbster9c1a3822007-08-30 23:29:26 +0000317 // set opcode (bit[7:4])
Evan Cheng0ff94f72007-08-07 01:37:15 +0000318 unsigned char BaseOpcode = getBaseOpcodeFor(Desc);
319 Value |= BaseOpcode << 4;
Raul Herbster9c1a3822007-08-30 23:29:26 +0000320 // set bit[27:24] to 1, set bit[23:20] to 2 and set bit[19:8] to 0xFFF
Evan Cheng0ff94f72007-08-07 01:37:15 +0000321 Value |= 0x12fff << 8;
322
323 if (opcode == ARM::BX_RET)
Raul Herbster9c1a3822007-08-30 23:29:26 +0000324 op = 0xe; // the return register is LR
Evan Cheng0ff94f72007-08-07 01:37:15 +0000325 else
Raul Herbster9c1a3822007-08-30 23:29:26 +0000326 // otherwise, set the return register
Evan Cheng0ff94f72007-08-07 01:37:15 +0000327 op = getMachineOpValue(MI,0);
328 Value |= op;
329
330 break;
331 }
332 case ARMII::Pseudo:
333 break;
334 }
335
336 break;
337 }
338 case ARMII::AddrMode1: {
Raul Herbster9c1a3822007-08-30 23:29:26 +0000339 // set opcode (bit[24:21]) of data-processing instructions
Evan Cheng0ff94f72007-08-07 01:37:15 +0000340 unsigned char BaseOpcode = getBaseOpcodeFor(Desc);
341 Value |= BaseOpcode << 21;
342
Raul Herbster9c1a3822007-08-30 23:29:26 +0000343 // treat 3 special instructions: MOVsra_flag, MOVsrl_flag and
344 // MOVrx.
Evan Cheng0ff94f72007-08-07 01:37:15 +0000345 unsigned Format = (Desc->TSFlags & ARMII::FormMask);
346 if (Format == ARMII::DPRdMisc) {
Raul Herbster9c1a3822007-08-30 23:29:26 +0000347 Value |= getMachineOpValue(MI,0) << ARMII::RegRdShift;
Evan Cheng0ff94f72007-08-07 01:37:15 +0000348 Value |= getMachineOpValue(MI,1);
349 switch(opcode) {
350 case ARM::MOVsra_flag: {
351 Value |= 0x1 << 6;
352 Value |= 0x1 << 7;
353 break;
354 }
355 case ARM::MOVsrl_flag: {
356 Value |= 0x1 << 5;
357 Value |= 0x1 << 7;
358 break;
359 }
360 case ARM::MOVrx: {
361 Value |= 0x3 << 5;
362 break;
363 }
364 }
365 break;
366 }
367
Raul Herbster9c1a3822007-08-30 23:29:26 +0000368 // Data processing operand instructions has 3 possible encodings (for more
369 // information, see ARM-ARM page A3-10):
370 // 1. <instr> <Rd>,<shifter_operand>
371 // 2. <instr> <Rn>,<shifter_operand>
372 // 3. <instr> <Rd>,<Rn>,<shifter_operand>
Evan Cheng0ff94f72007-08-07 01:37:15 +0000373 bool IsDataProcessing1 = Format == ARMII::DPRdIm ||
374 Format == ARMII::DPRdReg ||
375 Format == ARMII::DPRdSoReg;
376 bool IsDataProcessing2 = Format == ARMII::DPRnIm ||
377 Format == ARMII::DPRnReg ||
378 Format == ARMII::DPRnSoReg;
Raul Herbster9c1a3822007-08-30 23:29:26 +0000379 bool IsDataProcessing3 = false;
380
381 // set bit S(20)
382 if (Format == ARMII::DPRImS || Format == ARMII::DPRRegS ||
383 Format == ARMII::DPRSoRegS || IsDataProcessing2) {
384 Value |= 1 << ARMII::S_BitShift;
385 IsDataProcessing3 = !IsDataProcessing2;
386 }
387
Evan Cheng0ff94f72007-08-07 01:37:15 +0000388 IsDataProcessing3 = Format == ARMII::DPRIm ||
389 Format == ARMII::DPRReg ||
390 Format == ARMII::DPRSoReg ||
391 IsDataProcessing3;
392
393 // set first operand
394 op = getMachineOpValue(MI,0);
395 if (IsDataProcessing1 || IsDataProcessing3) {
Raul Herbster9c1a3822007-08-30 23:29:26 +0000396 Value |= op << ARMII::RegRdShift;
Evan Cheng0ff94f72007-08-07 01:37:15 +0000397 } else if (IsDataProcessing2) {
Raul Herbster9c1a3822007-08-30 23:29:26 +0000398 Value |= op << ARMII::RegRnShift;
Evan Cheng0ff94f72007-08-07 01:37:15 +0000399 }
400
Raul Herbster9c1a3822007-08-30 23:29:26 +0000401 // set second operand of data processing #3 instructions
Evan Cheng0ff94f72007-08-07 01:37:15 +0000402 if (IsDataProcessing3) {
403 op = getMachineOpValue(MI,1);
Raul Herbster9c1a3822007-08-30 23:29:26 +0000404 Value |= op << ARMII::RegRnShift;
Evan Cheng0ff94f72007-08-07 01:37:15 +0000405 }
406
407 unsigned OperandIndex = IsDataProcessing3 ? 2 : 1;
Evan Cheng0ff94f72007-08-07 01:37:15 +0000408 switch (Format) {
409 case ARMII::DPRdIm: case ARMII::DPRnIm:
410 case ARMII::DPRIm: case ARMII::DPRImS: {
Raul Herbster9c1a3822007-08-30 23:29:26 +0000411 // set bit I(25) to identify this is the immediate form of <shifter_op>
412 Value |= 1 << ARMII::I_BitShift;
413 // set immed_8 field
Evan Cheng0ff94f72007-08-07 01:37:15 +0000414 const MachineOperand &MO = MI.getOperand(OperandIndex);
415 op = ARM_AM::getSOImmVal(MO.getImmedValue());
416 Value |= op;
417
418 break;
419 }
420 case ARMII::DPRdReg: case ARMII::DPRnReg:
421 case ARMII::DPRReg: case ARMII::DPRRegS: {
Raul Herbster9c1a3822007-08-30 23:29:26 +0000422 // set last operand (register Rm)
Evan Cheng0ff94f72007-08-07 01:37:15 +0000423 op = getMachineOpValue(MI,OperandIndex);
424 Value |= op;
425
426 break;
427 }
428 case ARMII::DPRdSoReg: case ARMII::DPRnSoReg:
429 case ARMII::DPRSoReg: case ARMII::DPRSoRegS: {
Raul Herbster9c1a3822007-08-30 23:29:26 +0000430 // set last operand (register Rm)
Evan Cheng0ff94f72007-08-07 01:37:15 +0000431 op = getMachineOpValue(MI,OperandIndex);
432 Value |= op;
433
434 const MachineOperand &MO1 = MI.getOperand(OperandIndex + 1);
435 const MachineOperand &MO2 = MI.getOperand(OperandIndex + 2);
Raul Herbster9c1a3822007-08-30 23:29:26 +0000436 // identify it the instr is in immed or register shifts encoding
Evan Cheng0ff94f72007-08-07 01:37:15 +0000437 bool IsShiftByRegister = MO1.getReg() > 0;
Raul Herbster9c1a3822007-08-30 23:29:26 +0000438 // set shift operand (bit[6:4]).
439 // ASR - 101 if it is in register shifts encoding; 100, otherwise.
440 // LSL - 001 if it is in register shifts encoding; 000, otherwise.
441 // LSR - 011 if it is in register shifts encoding; 010, otherwise.
442 // ROR - 111 if it is in register shifts encoding; 110, otherwise.
443 // RRX - 110 and bit[11:7] clear.
Evan Cheng0ff94f72007-08-07 01:37:15 +0000444 switch(ARM_AM::getSORegShOp(MO2.getImmedValue())) {
445 default: assert(0 && "Unknown shift opc!");
446 case ARM_AM::asr: {
447 if(IsShiftByRegister)
448 Value |= 0x5 << 4;
449 else
450 Value |= 0x1 << 6;
451 break;
452 }
453 case ARM_AM::lsl: {
454 if(IsShiftByRegister)
455 Value |= 0x1 << 4;
456 break;
457 }
458 case ARM_AM::lsr: {
459 if(IsShiftByRegister)
460 Value |= 0x3 << 4;
461 else
462 Value |= 0x1 << 5;
463 break;
464 }
465 case ARM_AM::ror: {
466 if(IsShiftByRegister)
467 Value |= 0x7 << 4;
468 else
469 Value |= 0x3 << 5;
470 break;
471 }
472 case ARM_AM::rrx: {
473 Value |= 0x3 << 5;
474 break;
475 }
476 }
Raul Herbster9c1a3822007-08-30 23:29:26 +0000477 // set the field related to shift operations (except rrx).
Evan Cheng0ff94f72007-08-07 01:37:15 +0000478 if(ARM_AM::getSORegShOp(MO2.getImmedValue()) != ARM_AM::rrx)
479 if(IsShiftByRegister) {
Raul Herbster9c1a3822007-08-30 23:29:26 +0000480 // set the value of bit[11:8] (register Rs).
Evan Cheng0ff94f72007-08-07 01:37:15 +0000481 assert(MRegisterInfo::isPhysicalRegister(MO1.getReg()));
482 op = ARMRegisterInfo::getRegisterNumbering(MO1.getReg());
483 assert(ARM_AM::getSORegOffset(MO2.getImm()) == 0);
Raul Herbster9c1a3822007-08-30 23:29:26 +0000484 Value |= op << ARMII::RegRsShift;
Evan Cheng0ff94f72007-08-07 01:37:15 +0000485 } else {
Raul Herbster9c1a3822007-08-30 23:29:26 +0000486 // set the value of bit [11:7] (shift_immed field).
Evan Cheng0ff94f72007-08-07 01:37:15 +0000487 op = ARM_AM::getSORegOffset(MO2.getImm());
488 Value |= op << 7;
489 }
490 break;
491 }
492 default: assert(false && "Unknown operand type!");
493 break;
494 }
495
496 break;
497 }
498 case ARMII::AddrMode2: {
Raul Herbster9c1a3822007-08-30 23:29:26 +0000499 // bit 26 is always 1
Evan Cheng0ff94f72007-08-07 01:37:15 +0000500 Value |= 1 << 26;
501
502 unsigned Index = (Desc->TSFlags & ARMII::IndexModeMask);
Raul Herbster9c1a3822007-08-30 23:29:26 +0000503 // if the instruction uses offset addressing or pre-indexed addressing,
504 // set bit P(24) to 1
Evan Cheng0ff94f72007-08-07 01:37:15 +0000505 if (Index == ARMII::IndexModePre || Index == 0)
Raul Herbster9c1a3822007-08-30 23:29:26 +0000506 Value |= 1 << ARMII::IndexShift;
507 // if the instruction uses post-indexed addressing, set bit W(21) to 1
Evan Cheng0ff94f72007-08-07 01:37:15 +0000508 if (Index == ARMII::IndexModePre)
509 Value |= 1 << 21;
510
511 unsigned Format = (Desc->TSFlags & ARMII::FormMask);
Raul Herbster9c1a3822007-08-30 23:29:26 +0000512 // If it is a load instruction (except LDRD), set bit L(20) to 1
Evan Cheng0ff94f72007-08-07 01:37:15 +0000513 if (Format == ARMII::LdFrm)
Raul Herbster9c1a3822007-08-30 23:29:26 +0000514 Value |= 1 << ARMII::L_BitShift;
Evan Cheng0ff94f72007-08-07 01:37:15 +0000515
Raul Herbster9c1a3822007-08-30 23:29:26 +0000516 // set bit B(22)
Evan Cheng0ff94f72007-08-07 01:37:15 +0000517 unsigned BitByte = getBaseOpcodeFor(Desc);
518 Value |= BitByte << 22;
519
520 // set first operand
521 op = getMachineOpValue(MI,0);
Raul Herbster9c1a3822007-08-30 23:29:26 +0000522 Value |= op << ARMII::RegRdShift;
Evan Cheng0ff94f72007-08-07 01:37:15 +0000523
Raul Herbster9c1a3822007-08-30 23:29:26 +0000524 // set second operand
Evan Cheng0ff94f72007-08-07 01:37:15 +0000525 op = getMachineOpValue(MI,1);
Raul Herbster9c1a3822007-08-30 23:29:26 +0000526 Value |= op << ARMII::RegRnShift;
Evan Cheng0ff94f72007-08-07 01:37:15 +0000527
528 const MachineOperand &MO2 = MI.getOperand(2);
529 const MachineOperand &MO3 = MI.getOperand(3);
530
Raul Herbster9c1a3822007-08-30 23:29:26 +0000531 // set bit U(23) according to signal of immed value (positive or negative)
532 Value |= (ARM_AM::getAM2Op(MO3.getImm()) == ARM_AM::add ? 1 : 0) <<
533 ARMII::U_BitShift;
Evan Cheng0ff94f72007-08-07 01:37:15 +0000534 if (!MO2.getReg()) { // is immediate
535 if (ARM_AM::getAM2Offset(MO3.getImm()))
Raul Herbster9c1a3822007-08-30 23:29:26 +0000536 // set the value of offset_12 field
Evan Cheng0ff94f72007-08-07 01:37:15 +0000537 Value |= ARM_AM::getAM2Offset(MO3.getImm());
538 break;
539 }
540
Raul Herbster9c1a3822007-08-30 23:29:26 +0000541 // set bit I(25), because this is not in immediate enconding.
542 Value |= 1 << ARMII::I_BitShift;
Evan Cheng0ff94f72007-08-07 01:37:15 +0000543 assert(MRegisterInfo::isPhysicalRegister(MO2.getReg()));
Raul Herbster9c1a3822007-08-30 23:29:26 +0000544 // set bit[3:0] to the corresponding Rm register
Evan Cheng0ff94f72007-08-07 01:37:15 +0000545 Value |= ARMRegisterInfo::getRegisterNumbering(MO2.getReg());
546
Raul Herbster9c1a3822007-08-30 23:29:26 +0000547 // if this instr is in scaled register offset/index instruction, set
548 // shift_immed(bit[11:7]) and shift(bit[6:5]) fields.
Evan Cheng0ff94f72007-08-07 01:37:15 +0000549 if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm())) {
550 unsigned ShiftOp = getShiftOp(MO3);
Raul Herbster9c1a3822007-08-30 23:29:26 +0000551 Value |= ShiftOp << 5; // shift
552 Value |= ShImm << 7; // shift_immed
Evan Cheng0ff94f72007-08-07 01:37:15 +0000553 }
554
555 break;
556 }
557 case ARMII::AddrMode3: {
Raul Herbster9c1a3822007-08-30 23:29:26 +0000558
Evan Cheng0ff94f72007-08-07 01:37:15 +0000559 unsigned Index = (Desc->TSFlags & ARMII::IndexModeMask);
Raul Herbster9c1a3822007-08-30 23:29:26 +0000560 // if the instruction uses offset addressing or pre-indexed addressing,
561 // set bit P(24) to 1
Evan Cheng0ff94f72007-08-07 01:37:15 +0000562 if (Index == ARMII::IndexModePre || Index == 0)
Raul Herbster9c1a3822007-08-30 23:29:26 +0000563 Value |= 1 << ARMII::IndexShift;
Evan Cheng0ff94f72007-08-07 01:37:15 +0000564
565 unsigned Format = (Desc->TSFlags & ARMII::FormMask);
Raul Herbster9c1a3822007-08-30 23:29:26 +0000566 // If it is a load instruction (except LDRD), set bit L(20) to 1
567 if (Format == ARMII::LdFrm && opcode != ARM::LDRD)
568 Value |= 1 << ARMII::L_BitShift;
Evan Cheng0ff94f72007-08-07 01:37:15 +0000569
Raul Herbster9c1a3822007-08-30 23:29:26 +0000570 // bit[7:4] is the opcode of this instruction class (bits S and H).
Evan Cheng0ff94f72007-08-07 01:37:15 +0000571 unsigned char BaseOpcode = getBaseOpcodeFor(Desc);
572 Value |= BaseOpcode << 4;
573
574 // set first operand
575 op = getMachineOpValue(MI,0);
Raul Herbster9c1a3822007-08-30 23:29:26 +0000576 Value |= op << ARMII::RegRdShift;
Evan Cheng0ff94f72007-08-07 01:37:15 +0000577
Raul Herbster9c1a3822007-08-30 23:29:26 +0000578 // set second operand
Evan Cheng0ff94f72007-08-07 01:37:15 +0000579 op = getMachineOpValue(MI,1);
Raul Herbster9c1a3822007-08-30 23:29:26 +0000580 Value |= op << ARMII::RegRnShift;
Evan Cheng0ff94f72007-08-07 01:37:15 +0000581
582 const MachineOperand &MO2 = MI.getOperand(2);
583 const MachineOperand &MO3 = MI.getOperand(3);
584
Raul Herbster9c1a3822007-08-30 23:29:26 +0000585 // set bit U(23) according to signal of immed value (positive or negative)
586 Value |= (ARM_AM::getAM2Op(MO3.getImm()) == ARM_AM::add ? 1 : 0) <<
587 ARMII::U_BitShift;
Evan Cheng0ff94f72007-08-07 01:37:15 +0000588
Raul Herbster9c1a3822007-08-30 23:29:26 +0000589 // if this instr is in register offset/index encoding, set bit[3:0]
590 // to the corresponding Rm register.
Evan Cheng0ff94f72007-08-07 01:37:15 +0000591 if (MO2.getReg()) {
592 Value |= ARMRegisterInfo::getRegisterNumbering(MO2.getReg());
593 break;
594 }
595
Raul Herbster9c1a3822007-08-30 23:29:26 +0000596 // if this instr is in immediate offset/index encoding, set bit 22 to 1
Evan Cheng0ff94f72007-08-07 01:37:15 +0000597 if (unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm())) {
598 Value |= 1 << 22;
Raul Herbster9c1a3822007-08-30 23:29:26 +0000599 // set operands
Evan Cheng0ff94f72007-08-07 01:37:15 +0000600 Value |= (ImmOffs >> 4) << 8; // immedH
601 Value |= (ImmOffs & ~0xF); // immedL
602 }
603
604 break;
605 }
606 case ARMII::AddrMode4: {
Raul Herbster9c1a3822007-08-30 23:29:26 +0000607 // bit 27 is always 1
Evan Cheng0ff94f72007-08-07 01:37:15 +0000608 Value |= 1 << 27;
609
610 unsigned Format = (Desc->TSFlags & ARMII::FormMask);
Raul Herbster9c1a3822007-08-30 23:29:26 +0000611 // if it is a load instr, set bit L(20) to 1
Evan Cheng0ff94f72007-08-07 01:37:15 +0000612 if (Format == ARMII::LdFrm)
Raul Herbster9c1a3822007-08-30 23:29:26 +0000613 Value |= 1 << ARMII::L_BitShift;
Evan Cheng0ff94f72007-08-07 01:37:15 +0000614
615 unsigned OpIndex = 0;
616
617 // set first operand
618 op = getMachineOpValue(MI,OpIndex);
Raul Herbster9c1a3822007-08-30 23:29:26 +0000619 Value |= op << ARMII::RegRnShift;
Evan Cheng0ff94f72007-08-07 01:37:15 +0000620
Raul Herbster9c1a3822007-08-30 23:29:26 +0000621 // set addressing mode by modifying bits U(23) and P(24)
622 // IA - Increment after - bit U = 1 and bit P = 0
623 // IB - Increment before - bit U = 1 and bit P = 1
624 // DA - Decrement after - bit U = 0 and bit P = 0
625 // DB - Decrement before - bit U = 0 and bit P = 1
Evan Cheng0ff94f72007-08-07 01:37:15 +0000626 const MachineOperand &MO = MI.getOperand(OpIndex + 1);
627 ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MO.getImm());
628 switch(Mode) {
629 default: assert(0 && "Unknown addressing sub-mode!");
630 case ARM_AM::ia: Value |= 0x1 << 23; break;
Raul Herbster9c1a3822007-08-30 23:29:26 +0000631 case ARM_AM::ib: Value |= 0x3 << 23; break;
Evan Cheng0ff94f72007-08-07 01:37:15 +0000632 case ARM_AM::da: break;
633 case ARM_AM::db: Value |= 0x1 << 24; break;
634 }
635
Raul Herbster9c1a3822007-08-30 23:29:26 +0000636 // set bit W(21)
Evan Cheng0ff94f72007-08-07 01:37:15 +0000637 if (ARM_AM::getAM4WBFlag(MO.getImm()))
638 Value |= 0x1 << 21;
639
640 // set registers
641 for (unsigned i = OpIndex + 4, e = MI.getNumOperands(); i != e; ++i) {
642 const MachineOperand &MOR = MI.getOperand(i);
643 unsigned RegNumber = ARMRegisterInfo::getRegisterNumbering(MOR.getReg());
644 assert(MRegisterInfo::isPhysicalRegister(MOR.getReg()) && RegNumber < 16);
645 Value |= 0x1 << RegNumber;
646 }
647
648 break;
649 }
650 }
651
652 return Value;
Evan Cheng148b6a42007-07-05 21:15:40 +0000653}