blob: 5a4940dfeb2d4c50641c80f560502003b7ba3f79 [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"
Evan Cheng7602e112008-09-02 06:52:38 +000016#include "ARM.h"
17#include "ARMAddressingModes.h"
Evan Cheng148b6a42007-07-05 21:15:40 +000018#include "ARMInstrInfo.h"
Evan Cheng7602e112008-09-02 06:52:38 +000019#include "ARMRelocations.h"
Evan Cheng148b6a42007-07-05 21:15:40 +000020#include "ARMSubtarget.h"
21#include "ARMTargetMachine.h"
Evan Cheng148b6a42007-07-05 21:15:40 +000022#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"
Evan Cheng148b6a42007-07-05 21:15:40 +000027#include "llvm/ADT/Statistic.h"
28#include "llvm/Support/Compiler.h"
29using namespace llvm;
30
31STATISTIC(NumEmitted, "Number of machine instructions emitted");
32
33namespace {
Evan Cheng7602e112008-09-02 06:52:38 +000034 class VISIBILITY_HIDDEN ARMCodeEmitter : public MachineFunctionPass {
Evan Cheng148b6a42007-07-05 21:15:40 +000035 const ARMInstrInfo *II;
36 const TargetData *TD;
37 TargetMachine &TM;
38 MachineCodeEmitter &MCE;
39 public:
40 static char ID;
Evan Cheng7602e112008-09-02 06:52:38 +000041 explicit ARMCodeEmitter(TargetMachine &tm, MachineCodeEmitter &mce)
Dan Gohmanae73dc12008-09-04 17:05:41 +000042 : MachineFunctionPass(&ID), II(0), TD(0), TM(tm),
Evan Cheng148b6a42007-07-05 21:15:40 +000043 MCE(mce) {}
Evan Cheng7602e112008-09-02 06:52:38 +000044 ARMCodeEmitter(TargetMachine &tm, MachineCodeEmitter &mce,
Evan Cheng148b6a42007-07-05 21:15:40 +000045 const ARMInstrInfo &ii, const TargetData &td)
Dan Gohmanae73dc12008-09-04 17:05:41 +000046 : MachineFunctionPass(&ID), II(&ii), TD(&td), TM(tm),
Evan Cheng148b6a42007-07-05 21:15:40 +000047 MCE(mce) {}
48
49 bool runOnMachineFunction(MachineFunction &MF);
50
51 virtual const char *getPassName() const {
52 return "ARM Machine Code Emitter";
53 }
54
55 void emitInstruction(const MachineInstr &MI);
Evan Cheng7602e112008-09-02 06:52:38 +000056
57 private:
58 unsigned getAddrModeNoneInstrBinary(const MachineInstr &MI,
59 const TargetInstrDesc &Desc,
Evan Cheng5f1db7b2008-09-12 22:01:15 +000060 unsigned Binary);
61
62 unsigned getMachineSoRegOpValue(const MachineInstr &MI,
63 const TargetInstrDesc &Desc,
64 unsigned OpIdx);
65
Evan Cheng7602e112008-09-02 06:52:38 +000066 unsigned getAddrMode1InstrBinary(const MachineInstr &MI,
67 const TargetInstrDesc &Desc,
68 unsigned Binary);
69 unsigned getAddrMode2InstrBinary(const MachineInstr &MI,
70 const TargetInstrDesc &Desc,
71 unsigned Binary);
72 unsigned getAddrMode3InstrBinary(const MachineInstr &MI,
73 const TargetInstrDesc &Desc,
74 unsigned Binary);
75 unsigned getAddrMode4InstrBinary(const MachineInstr &MI,
76 const TargetInstrDesc &Desc,
77 unsigned Binary);
78
79 /// getInstrBinary - Return binary encoding for the specified
80 /// machine instruction.
81 unsigned getInstrBinary(const MachineInstr &MI);
82
83 /// getBinaryCodeForInstr - This function, generated by the
84 /// CodeEmitterGenerator using TableGen, produces the binary encoding for
85 /// machine instructions.
86 ///
Raul Herbster9c1a3822007-08-30 23:29:26 +000087 unsigned getBinaryCodeForInstr(const MachineInstr &MI);
Evan Cheng0ff94f72007-08-07 01:37:15 +000088
Evan Cheng7602e112008-09-02 06:52:38 +000089 /// getMachineOpValue - Return binary encoding of operand. If the machine
90 /// operand requires relocation, record the relocation and return zero.
91 unsigned getMachineOpValue(const MachineInstr &MI, unsigned OpIdx) {
92 return getMachineOpValue(MI, MI.getOperand(OpIdx));
93 }
94 unsigned getMachineOpValue(const MachineInstr &MI,
95 const MachineOperand &MO);
96
97 /// getBaseOpcodeFor - Return the opcode value.
98 ///
99 unsigned getBaseOpcodeFor(const TargetInstrDesc &TID) const {
100 return (TID.TSFlags & ARMII::OpcodeMask) >> ARMII::OpcodeShift;
101 }
102
103 /// getShiftOp - Return the shift opcode (bit[6:5]) of the machine operand.
104 ///
105 unsigned getShiftOp(const MachineOperand &MO) const ;
106
107 /// Routines that handle operands which add machine relocations which are
108 /// fixed up by the JIT fixup stage.
Evan Cheng0ff94f72007-08-07 01:37:15 +0000109 void emitGlobalAddressForCall(GlobalValue *GV, bool DoesntNeedStub);
110 void emitExternalSymbolAddress(const char *ES, unsigned Reloc);
111 void emitConstPoolAddress(unsigned CPI, unsigned Reloc,
112 int Disp = 0, unsigned PCAdj = 0 );
113 void emitJumpTableAddress(unsigned JTI, unsigned Reloc,
114 unsigned PCAdj = 0);
Raul Herbster9c1a3822007-08-30 23:29:26 +0000115 void emitGlobalConstant(const Constant *CV);
116 void emitMachineBasicBlock(MachineBasicBlock *BB);
Evan Cheng148b6a42007-07-05 21:15:40 +0000117 };
Evan Cheng7602e112008-09-02 06:52:38 +0000118 char ARMCodeEmitter::ID = 0;
Evan Cheng148b6a42007-07-05 21:15:40 +0000119}
120
121/// createARMCodeEmitterPass - Return a pass that emits the collected ARM code
122/// to the specified MCE object.
123FunctionPass *llvm::createARMCodeEmitterPass(ARMTargetMachine &TM,
124 MachineCodeEmitter &MCE) {
Evan Cheng7602e112008-09-02 06:52:38 +0000125 return new ARMCodeEmitter(TM, MCE);
Evan Cheng148b6a42007-07-05 21:15:40 +0000126}
127
Evan Cheng7602e112008-09-02 06:52:38 +0000128bool ARMCodeEmitter::runOnMachineFunction(MachineFunction &MF) {
Evan Cheng148b6a42007-07-05 21:15:40 +0000129 assert((MF.getTarget().getRelocationModel() != Reloc::Default ||
130 MF.getTarget().getRelocationModel() != Reloc::Static) &&
131 "JIT relocation model must be set to static or default!");
132 II = ((ARMTargetMachine&)MF.getTarget()).getInstrInfo();
133 TD = ((ARMTargetMachine&)MF.getTarget()).getTargetData();
134
135 do {
136 MCE.startFunction(MF);
137 for (MachineFunction::iterator MBB = MF.begin(), E = MF.end();
138 MBB != E; ++MBB) {
139 MCE.StartMachineBasicBlock(MBB);
140 for (MachineBasicBlock::const_iterator I = MBB->begin(), E = MBB->end();
141 I != E; ++I)
142 emitInstruction(*I);
143 }
144 } while (MCE.finishFunction(MF));
145
146 return false;
147}
148
Evan Cheng7602e112008-09-02 06:52:38 +0000149/// getShiftOp - Return the shift opcode (bit[6:5]) of the machine operand.
150///
151unsigned ARMCodeEmitter::getShiftOp(const MachineOperand &MO) const {
152 switch (ARM_AM::getAM2ShiftOpc(MO.getImm())) {
Evan Cheng0ff94f72007-08-07 01:37:15 +0000153 default: assert(0 && "Unknown shift opc!");
Evan Cheng7602e112008-09-02 06:52:38 +0000154 case ARM_AM::asr: return 2;
155 case ARM_AM::lsl: return 0;
156 case ARM_AM::lsr: return 1;
Evan Cheng0ff94f72007-08-07 01:37:15 +0000157 case ARM_AM::ror:
Evan Cheng7602e112008-09-02 06:52:38 +0000158 case ARM_AM::rrx: return 3;
Evan Cheng0ff94f72007-08-07 01:37:15 +0000159 }
Evan Cheng7602e112008-09-02 06:52:38 +0000160 return 0;
Evan Cheng0ff94f72007-08-07 01:37:15 +0000161}
162
Evan Cheng7602e112008-09-02 06:52:38 +0000163/// getMachineOpValue - Return binary encoding of operand. If the machine
164/// operand requires relocation, record the relocation and return zero.
165unsigned ARMCodeEmitter::getMachineOpValue(const MachineInstr &MI,
166 const MachineOperand &MO) {
167 if (MO.isRegister())
168 return ARMRegisterInfo::getRegisterNumbering(MO.getReg());
169 else if (MO.isImmediate())
170 return static_cast<unsigned>(MO.getImm());
171 else if (MO.isGlobalAddress())
Raul Herbster9c1a3822007-08-30 23:29:26 +0000172 emitGlobalAddressForCall(MO.getGlobal(), false);
Evan Cheng7602e112008-09-02 06:52:38 +0000173 else if (MO.isExternalSymbol())
Raul Herbster9c1a3822007-08-30 23:29:26 +0000174 emitExternalSymbolAddress(MO.getSymbolName(), ARM::reloc_arm_relative);
Evan Cheng7602e112008-09-02 06:52:38 +0000175 else if (MO.isConstantPoolIndex())
Chris Lattner8aa797a2007-12-30 23:10:15 +0000176 emitConstPoolAddress(MO.getIndex(), ARM::reloc_arm_relative);
Evan Cheng7602e112008-09-02 06:52:38 +0000177 else if (MO.isJumpTableIndex())
Chris Lattner8aa797a2007-12-30 23:10:15 +0000178 emitJumpTableAddress(MO.getIndex(), ARM::reloc_arm_relative);
Evan Cheng7602e112008-09-02 06:52:38 +0000179 else if (MO.isMachineBasicBlock())
Chris Lattner8aa797a2007-12-30 23:10:15 +0000180 emitMachineBasicBlock(MO.getMBB());
Raul Herbster9c1a3822007-08-30 23:29:26 +0000181
Evan Cheng7602e112008-09-02 06:52:38 +0000182 abort();
183 return 0;
Evan Cheng0ff94f72007-08-07 01:37:15 +0000184}
185
186/// emitGlobalAddressForCall - Emit the specified address to the code stream
187/// assuming this is part of a function call, which is PC relative.
188///
Evan Cheng7602e112008-09-02 06:52:38 +0000189void ARMCodeEmitter::emitGlobalAddressForCall(GlobalValue *GV,
190 bool DoesntNeedStub) {
Evan Cheng0ff94f72007-08-07 01:37:15 +0000191 MCE.addRelocation(MachineRelocation::getGV(MCE.getCurrentPCOffset(),
Evan Cheng7602e112008-09-02 06:52:38 +0000192 ARM::reloc_arm_branch, GV, 0,
193 DoesntNeedStub));
Evan Cheng0ff94f72007-08-07 01:37:15 +0000194}
195
196/// emitExternalSymbolAddress - Arrange for the address of an external symbol to
197/// be emitted to the current location in the function, and allow it to be PC
198/// relative.
Evan Cheng7602e112008-09-02 06:52:38 +0000199void ARMCodeEmitter::emitExternalSymbolAddress(const char *ES, unsigned Reloc) {
Evan Cheng0ff94f72007-08-07 01:37:15 +0000200 MCE.addRelocation(MachineRelocation::getExtSym(MCE.getCurrentPCOffset(),
201 Reloc, ES));
202}
203
204/// emitConstPoolAddress - Arrange for the address of an constant pool
205/// to be emitted to the current location in the function, and allow it to be PC
206/// relative.
Evan Cheng7602e112008-09-02 06:52:38 +0000207void ARMCodeEmitter::emitConstPoolAddress(unsigned CPI, unsigned Reloc,
208 int Disp /* = 0 */,
209 unsigned PCAdj /* = 0 */) {
Evan Cheng0ff94f72007-08-07 01:37:15 +0000210 MCE.addRelocation(MachineRelocation::getConstPool(MCE.getCurrentPCOffset(),
211 Reloc, CPI, PCAdj));
212}
213
214/// emitJumpTableAddress - Arrange for the address of a jump table to
215/// be emitted to the current location in the function, and allow it to be PC
216/// relative.
Evan Cheng7602e112008-09-02 06:52:38 +0000217void ARMCodeEmitter::emitJumpTableAddress(unsigned JTI, unsigned Reloc,
218 unsigned PCAdj /* = 0 */) {
Evan Cheng0ff94f72007-08-07 01:37:15 +0000219 MCE.addRelocation(MachineRelocation::getJumpTable(MCE.getCurrentPCOffset(),
220 Reloc, JTI, PCAdj));
221}
222
Raul Herbster9c1a3822007-08-30 23:29:26 +0000223/// emitMachineBasicBlock - Emit the specified address basic block.
Evan Cheng7602e112008-09-02 06:52:38 +0000224void ARMCodeEmitter::emitMachineBasicBlock(MachineBasicBlock *BB) {
Raul Herbster9c1a3822007-08-30 23:29:26 +0000225 MCE.addRelocation(MachineRelocation::getBB(MCE.getCurrentPCOffset(),
Evan Cheng7602e112008-09-02 06:52:38 +0000226 ARM::reloc_arm_branch, BB));
Raul Herbster9c1a3822007-08-30 23:29:26 +0000227}
Evan Cheng0ff94f72007-08-07 01:37:15 +0000228
Evan Cheng7602e112008-09-02 06:52:38 +0000229void ARMCodeEmitter::emitInstruction(const MachineInstr &MI) {
Evan Cheng148b6a42007-07-05 21:15:40 +0000230 NumEmitted++; // Keep track of the # of mi's emitted
Evan Cheng7602e112008-09-02 06:52:38 +0000231 MCE.emitWordLE(getInstrBinary(MI));
Evan Cheng0ff94f72007-08-07 01:37:15 +0000232}
233
Evan Cheng7602e112008-09-02 06:52:38 +0000234unsigned ARMCodeEmitter::getAddrModeNoneInstrBinary(const MachineInstr &MI,
235 const TargetInstrDesc &Desc,
236 unsigned Binary) {
237 switch (Desc.TSFlags & ARMII::FormMask) {
238 default:
239 assert(0 && "Unknown instruction subtype!");
240 break;
241 case ARMII::Branch: {
242 // Set signed_immed_24 field
243 Binary |= getMachineOpValue(MI, 0);
244
245 // if it is a conditional branch, set cond field
246 if (Desc.Opcode == ARM::Bcc) {
247 Binary &= 0x0FFFFFFF; // clear conditional field
248 Binary |= getMachineOpValue(MI, 1) << 28; // set conditional field
249 }
250 break;
251 }
252 case ARMII::BranchMisc: {
253 // Set bit[19:8] to 0xFFF
254 Binary |= 0xfff << 8;
255 if (Desc.Opcode == ARM::BX_RET)
256 Binary |= 0xe; // the return register is LR
257 else
258 // otherwise, set the return register
259 Binary |= getMachineOpValue(MI, 0);
260 break;
261 }
262 }
263
264 return Binary;
265}
266
Evan Cheng5f1db7b2008-09-12 22:01:15 +0000267unsigned ARMCodeEmitter::getMachineSoRegOpValue(const MachineInstr &MI,
268 const TargetInstrDesc &Desc,
269 unsigned OpIdx) {
270 // Set last operand (register Rm)
271 unsigned Binary = getMachineOpValue(MI, OpIdx);
272
273 const MachineOperand &MO1 = MI.getOperand(OpIdx + 1);
274 const MachineOperand &MO2 = MI.getOperand(OpIdx + 2);
275 ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(MO2.getImm());
276
277 // Encode the shift opcode.
278 unsigned SBits = 0;
279 unsigned Rs = MO1.getReg();
280 if (Rs) {
281 // Set shift operand (bit[7:4]).
282 // LSL - 0001
283 // LSR - 0011
284 // ASR - 0101
285 // ROR - 0111
286 // RRX - 0110 and bit[11:8] clear.
287 switch (SOpc) {
288 default: assert(0 && "Unknown shift opc!");
289 case ARM_AM::lsl: SBits = 0x1; break;
290 case ARM_AM::lsr: SBits = 0x3; break;
291 case ARM_AM::asr: SBits = 0x5; break;
292 case ARM_AM::ror: SBits = 0x7; break;
293 case ARM_AM::rrx: SBits = 0x6; break;
294 }
295 } else {
296 // Set shift operand (bit[6:4]).
297 // LSL - 000
298 // LSR - 010
299 // ASR - 100
300 // ROR - 110
301 switch (SOpc) {
302 default: assert(0 && "Unknown shift opc!");
303 case ARM_AM::lsl: SBits = 0x0; break;
304 case ARM_AM::lsr: SBits = 0x2; break;
305 case ARM_AM::asr: SBits = 0x4; break;
306 case ARM_AM::ror: SBits = 0x6; break;
307 }
308 }
309 Binary |= SBits << 4;
310 if (SOpc == ARM_AM::rrx)
311 return Binary;
312
313 // Encode the shift operation Rs or shift_imm (except rrx).
314 if (Rs) {
315 // Encode Rs bit[11:8].
316 assert(ARM_AM::getSORegOffset(MO2.getImm()) == 0);
317 return Binary |
318 (ARMRegisterInfo::getRegisterNumbering(Rs) << ARMII::RegRsShift);
319 }
320
321 // Encode shift_imm bit[11:7].
322 return Binary | ARM_AM::getSORegOffset(MO2.getImm()) << 7;
323}
324
Evan Cheng7602e112008-09-02 06:52:38 +0000325unsigned ARMCodeEmitter::getAddrMode1InstrBinary(const MachineInstr &MI,
326 const TargetInstrDesc &Desc,
327 unsigned Binary) {
Evan Cheng5f1db7b2008-09-12 22:01:15 +0000328 if (MI.getOpcode() == ARM::MOVi2pieces)
329 // FIXME.
330 abort();
331
Evan Cheng7602e112008-09-02 06:52:38 +0000332 unsigned Format = Desc.TSFlags & ARMII::FormMask;
Evan Cheng5f1db7b2008-09-12 22:01:15 +0000333 // FIXME: Consolidate into a single bit.
334 bool isUnary = (Format == ARMII::DPRdMisc ||
335 Format == ARMII::DPRdIm ||
336 Format == ARMII::DPRdReg ||
337 Format == ARMII::DPRdSoReg ||
338 Format == ARMII::DPRnIm ||
339 Format == ARMII::DPRnReg ||
340 Format == ARMII::DPRnSoReg);
341
342 unsigned OpIdx = 0;
343
344 // Encode register def if there is one.
345 unsigned NumDefs = Desc.getNumDefs();
346 if (NumDefs) {
347 Binary |= getMachineOpValue(MI, OpIdx) << ARMII::RegRdShift;
348 ++OpIdx;
Evan Cheng7602e112008-09-02 06:52:38 +0000349 }
350
Evan Cheng5f1db7b2008-09-12 22:01:15 +0000351 // Encode first non-shifter register operand if ther is one.
352 if (!isUnary) {
353 Binary |= getMachineOpValue(MI, OpIdx) << ARMII::RegRnShift;
354 ++OpIdx;
Evan Cheng7602e112008-09-02 06:52:38 +0000355 }
356
Evan Cheng5f1db7b2008-09-12 22:01:15 +0000357 // Encode shifter operand.
358 if (Desc.getNumOperands() - OpIdx > 1)
359 // Encode SoReg.
360 return Binary | getMachineSoRegOpValue(MI, Desc, OpIdx);
Evan Cheng7602e112008-09-02 06:52:38 +0000361
Evan Cheng5f1db7b2008-09-12 22:01:15 +0000362 const MachineOperand &MO = MI.getOperand(OpIdx);
363 if (MO.isRegister())
364 // Encode register Rm.
365 return Binary | getMachineOpValue(MI, NumDefs + 1);
Evan Cheng7602e112008-09-02 06:52:38 +0000366
Evan Cheng5f1db7b2008-09-12 22:01:15 +0000367 // Encode so_imm.
368 // Set bit I(25) to identify this is the immediate form of <shifter_op>
369 Binary |= 1 << ARMII::I_BitShift;
370 unsigned SoImm = MO.getImm();
371 // Encode rotate_imm.
372 Binary |= ARM_AM::getSOImmValRot(SoImm) << ARMII::RotImmShift;
373 // Encode immed_8.
374 Binary |= ARM_AM::getSOImmVal(SoImm);
Evan Cheng7602e112008-09-02 06:52:38 +0000375 return Binary;
376}
377
378unsigned ARMCodeEmitter::getAddrMode2InstrBinary(const MachineInstr &MI,
379 const TargetInstrDesc &Desc,
380 unsigned Binary) {
381 // Set first operand
382 Binary |= getMachineOpValue(MI, 0) << ARMII::RegRdShift;
383
384 // Set second operand
385 Binary |= getMachineOpValue(MI, 1) << ARMII::RegRnShift;
386
387 const MachineOperand &MO2 = MI.getOperand(2);
388 const MachineOperand &MO3 = MI.getOperand(3);
389
390 // Set bit U(23) according to signal of immed value (positive or negative).
391 Binary |= ((ARM_AM::getAM2Op(MO3.getImm()) == ARM_AM::add ? 1 : 0) <<
392 ARMII::U_BitShift);
393 if (!MO2.getReg()) { // is immediate
394 if (ARM_AM::getAM2Offset(MO3.getImm()))
395 // Set the value of offset_12 field
396 Binary |= ARM_AM::getAM2Offset(MO3.getImm());
397 return Binary;
398 }
399
400 // Set bit I(25), because this is not in immediate enconding.
401 Binary |= 1 << ARMII::I_BitShift;
402 assert(TargetRegisterInfo::isPhysicalRegister(MO2.getReg()));
403 // Set bit[3:0] to the corresponding Rm register
404 Binary |= ARMRegisterInfo::getRegisterNumbering(MO2.getReg());
405
406 // if this instr is in scaled register offset/index instruction, set
407 // shift_immed(bit[11:7]) and shift(bit[6:5]) fields.
408 if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm())) {
409 Binary |= getShiftOp(MO3) << 5; // shift
410 Binary |= ShImm << 7; // shift_immed
411 }
412
413 return Binary;
414}
415
416unsigned ARMCodeEmitter::getAddrMode3InstrBinary(const MachineInstr &MI,
417 const TargetInstrDesc &Desc,
418 unsigned Binary) {
419 // Set first operand
420 Binary |= getMachineOpValue(MI, 0) << ARMII::RegRdShift;
421
422 // Set second operand
423 Binary |= getMachineOpValue(MI, 1) << ARMII::RegRnShift;
424
425 const MachineOperand &MO2 = MI.getOperand(2);
426 const MachineOperand &MO3 = MI.getOperand(3);
427
428 // Set bit U(23) according to signal of immed value (positive or negative)
429 Binary |= ((ARM_AM::getAM2Op(MO3.getImm()) == ARM_AM::add ? 1 : 0) <<
430 ARMII::U_BitShift);
431
432 // If this instr is in register offset/index encoding, set bit[3:0]
433 // to the corresponding Rm register.
434 if (MO2.getReg()) {
435 Binary |= ARMRegisterInfo::getRegisterNumbering(MO2.getReg());
436 return Binary;
437 }
438
439 // if this instr is in immediate offset/index encoding, set bit 22 to 1
440 if (unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm())) {
441 Binary |= 1 << 22;
442 // Set operands
443 Binary |= (ImmOffs >> 4) << 8; // immedH
444 Binary |= (ImmOffs & ~0xF); // immedL
445 }
446
447 return Binary;
448}
449
450unsigned ARMCodeEmitter::getAddrMode4InstrBinary(const MachineInstr &MI,
451 const TargetInstrDesc &Desc,
452 unsigned Binary) {
453 // Set first operand
454 Binary |= getMachineOpValue(MI, 0) << ARMII::RegRnShift;
455
456 // Set addressing mode by modifying bits U(23) and P(24)
457 // IA - Increment after - bit U = 1 and bit P = 0
458 // IB - Increment before - bit U = 1 and bit P = 1
459 // DA - Decrement after - bit U = 0 and bit P = 0
460 // DB - Decrement before - bit U = 0 and bit P = 1
461 const MachineOperand &MO = MI.getOperand(1);
462 ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MO.getImm());
463 switch (Mode) {
464 default: assert(0 && "Unknown addressing sub-mode!");
465 case ARM_AM::da: break;
466 case ARM_AM::db: Binary |= 0x1 << 24; break;
467 case ARM_AM::ia: Binary |= 0x1 << 23; break;
468 case ARM_AM::ib: Binary |= 0x3 << 23; break;
469 }
470
471 // Set bit W(21)
472 if (ARM_AM::getAM4WBFlag(MO.getImm()))
473 Binary |= 0x1 << 21;
474
475 // Set registers
476 for (unsigned i = 4, e = MI.getNumOperands(); i != e; ++i) {
477 const MachineOperand &MO = MI.getOperand(i);
478 if (MO.isRegister() && MO.isImplicit())
479 continue;
480 unsigned RegNum = ARMRegisterInfo::getRegisterNumbering(MO.getReg());
481 assert(TargetRegisterInfo::isPhysicalRegister(MO.getReg()) &&
482 RegNum < 16);
483 Binary |= 0x1 << RegNum;
484 }
485
486 return Binary;
487}
488
489/// getInstrBinary - Return binary encoding for the specified
490/// machine instruction.
491unsigned ARMCodeEmitter::getInstrBinary(const MachineInstr &MI) {
492 // Part of binary is determined by TableGn.
493 unsigned Binary = getBinaryCodeForInstr(MI);
494
Chris Lattner749c6f62008-01-07 07:27:27 +0000495 const TargetInstrDesc &Desc = MI.getDesc();
Chris Lattner749c6f62008-01-07 07:27:27 +0000496 switch (Desc.TSFlags & ARMII::AddrModeMask) {
Evan Cheng7602e112008-09-02 06:52:38 +0000497 case ARMII::AddrModeNone:
498 return getAddrModeNoneInstrBinary(MI, Desc, Binary);
499 case ARMII::AddrMode1:
500 return getAddrMode1InstrBinary(MI, Desc, Binary);
501 case ARMII::AddrMode2:
502 return getAddrMode2InstrBinary(MI, Desc, Binary);
503 case ARMII::AddrMode3:
504 return getAddrMode3InstrBinary(MI, Desc, Binary);
505 case ARMII::AddrMode4:
506 return getAddrMode4InstrBinary(MI, Desc, Binary);
Evan Cheng0ff94f72007-08-07 01:37:15 +0000507 }
508
Evan Cheng7602e112008-09-02 06:52:38 +0000509 abort();
510 return 0;
Evan Cheng148b6a42007-07-05 21:15:40 +0000511}
Evan Cheng7602e112008-09-02 06:52:38 +0000512
513#include "ARMGenCodeEmitter.inc"