blob: f5ae1b4557242d68a6e00fc99f78c7cb3266998c [file] [log] [blame]
Jim Grosbach31c24bf2009-11-07 22:00:39 +00001//===- ARMBaseInstrInfo.cpp - ARM Instruction Information -------*- C++ -*-===//
David Goodwin334c2642009-07-08 16:09:28 +00002//
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 contains the Base ARM implementation of the TargetInstrInfo class.
11//
12//===----------------------------------------------------------------------===//
13
14#include "ARMBaseInstrInfo.h"
15#include "ARM.h"
16#include "ARMAddressingModes.h"
Evan Chengd457e6e2009-11-07 04:04:34 +000017#include "ARMConstantPoolValue.h"
David Goodwin334c2642009-07-08 16:09:28 +000018#include "ARMGenInstrInfo.inc"
19#include "ARMMachineFunctionInfo.h"
Anton Korobeynikovf95215f2009-11-02 00:10:38 +000020#include "ARMRegisterInfo.h"
Evan Chengfdc83402009-11-08 00:15:23 +000021#include "llvm/Constants.h"
22#include "llvm/Function.h"
23#include "llvm/GlobalValue.h"
David Goodwin334c2642009-07-08 16:09:28 +000024#include "llvm/ADT/STLExtras.h"
25#include "llvm/CodeGen/LiveVariables.h"
Evan Chengd457e6e2009-11-07 04:04:34 +000026#include "llvm/CodeGen/MachineConstantPool.h"
David Goodwin334c2642009-07-08 16:09:28 +000027#include "llvm/CodeGen/MachineFrameInfo.h"
28#include "llvm/CodeGen/MachineInstrBuilder.h"
29#include "llvm/CodeGen/MachineJumpTableInfo.h"
Anton Korobeynikov249fb332009-10-07 00:06:35 +000030#include "llvm/CodeGen/MachineMemOperand.h"
31#include "llvm/CodeGen/PseudoSourceValue.h"
Chris Lattneraf76e592009-08-22 20:48:53 +000032#include "llvm/MC/MCAsmInfo.h"
David Goodwin334c2642009-07-08 16:09:28 +000033#include "llvm/Support/CommandLine.h"
Anton Korobeynikovf95215f2009-11-02 00:10:38 +000034#include "llvm/Support/Debug.h"
Torok Edwinc25e7582009-07-11 20:10:48 +000035#include "llvm/Support/ErrorHandling.h"
David Goodwin334c2642009-07-08 16:09:28 +000036using namespace llvm;
37
38static cl::opt<bool>
39EnableARM3Addr("enable-arm-3-addr-conv", cl::Hidden,
40 cl::desc("Enable ARM 2-addr to 3-addr conv"));
41
Evan Chengac0869d2009-11-21 06:21:52 +000042static cl::opt<bool>
43PredicateNEON("predicate-neon", cl::Hidden,
44 cl::desc("Allow NEON instructions to be predicated"));
45
Anton Korobeynikovf95215f2009-11-02 00:10:38 +000046ARMBaseInstrInfo::ARMBaseInstrInfo(const ARMSubtarget& STI)
47 : TargetInstrInfoImpl(ARMInsts, array_lengthof(ARMInsts)),
48 Subtarget(STI) {
David Goodwin334c2642009-07-08 16:09:28 +000049}
50
51MachineInstr *
52ARMBaseInstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI,
53 MachineBasicBlock::iterator &MBBI,
54 LiveVariables *LV) const {
Evan Cheng78703dd2009-07-27 18:44:00 +000055 // FIXME: Thumb2 support.
56
David Goodwin334c2642009-07-08 16:09:28 +000057 if (!EnableARM3Addr)
58 return NULL;
59
60 MachineInstr *MI = MBBI;
61 MachineFunction &MF = *MI->getParent()->getParent();
62 unsigned TSFlags = MI->getDesc().TSFlags;
63 bool isPre = false;
64 switch ((TSFlags & ARMII::IndexModeMask) >> ARMII::IndexModeShift) {
65 default: return NULL;
66 case ARMII::IndexModePre:
67 isPre = true;
68 break;
69 case ARMII::IndexModePost:
70 break;
71 }
72
73 // Try splitting an indexed load/store to an un-indexed one plus an add/sub
74 // operation.
75 unsigned MemOpc = getUnindexedOpcode(MI->getOpcode());
76 if (MemOpc == 0)
77 return NULL;
78
79 MachineInstr *UpdateMI = NULL;
80 MachineInstr *MemMI = NULL;
81 unsigned AddrMode = (TSFlags & ARMII::AddrModeMask);
82 const TargetInstrDesc &TID = MI->getDesc();
83 unsigned NumOps = TID.getNumOperands();
84 bool isLoad = !TID.mayStore();
85 const MachineOperand &WB = isLoad ? MI->getOperand(1) : MI->getOperand(0);
86 const MachineOperand &Base = MI->getOperand(2);
87 const MachineOperand &Offset = MI->getOperand(NumOps-3);
88 unsigned WBReg = WB.getReg();
89 unsigned BaseReg = Base.getReg();
90 unsigned OffReg = Offset.getReg();
91 unsigned OffImm = MI->getOperand(NumOps-2).getImm();
92 ARMCC::CondCodes Pred = (ARMCC::CondCodes)MI->getOperand(NumOps-1).getImm();
93 switch (AddrMode) {
94 default:
95 assert(false && "Unknown indexed op!");
96 return NULL;
97 case ARMII::AddrMode2: {
98 bool isSub = ARM_AM::getAM2Op(OffImm) == ARM_AM::sub;
99 unsigned Amt = ARM_AM::getAM2Offset(OffImm);
100 if (OffReg == 0) {
Evan Chenge7cbe412009-07-08 21:03:57 +0000101 if (ARM_AM::getSOImmVal(Amt) == -1)
David Goodwin334c2642009-07-08 16:09:28 +0000102 // Can't encode it in a so_imm operand. This transformation will
103 // add more than 1 instruction. Abandon!
104 return NULL;
105 UpdateMI = BuildMI(MF, MI->getDebugLoc(),
Evan Cheng78703dd2009-07-27 18:44:00 +0000106 get(isSub ? ARM::SUBri : ARM::ADDri), WBReg)
Evan Chenge7cbe412009-07-08 21:03:57 +0000107 .addReg(BaseReg).addImm(Amt)
David Goodwin334c2642009-07-08 16:09:28 +0000108 .addImm(Pred).addReg(0).addReg(0);
109 } else if (Amt != 0) {
110 ARM_AM::ShiftOpc ShOpc = ARM_AM::getAM2ShiftOpc(OffImm);
111 unsigned SOOpc = ARM_AM::getSORegOpc(ShOpc, Amt);
112 UpdateMI = BuildMI(MF, MI->getDebugLoc(),
Evan Cheng78703dd2009-07-27 18:44:00 +0000113 get(isSub ? ARM::SUBrs : ARM::ADDrs), WBReg)
David Goodwin334c2642009-07-08 16:09:28 +0000114 .addReg(BaseReg).addReg(OffReg).addReg(0).addImm(SOOpc)
115 .addImm(Pred).addReg(0).addReg(0);
116 } else
117 UpdateMI = BuildMI(MF, MI->getDebugLoc(),
Evan Cheng78703dd2009-07-27 18:44:00 +0000118 get(isSub ? ARM::SUBrr : ARM::ADDrr), WBReg)
David Goodwin334c2642009-07-08 16:09:28 +0000119 .addReg(BaseReg).addReg(OffReg)
120 .addImm(Pred).addReg(0).addReg(0);
121 break;
122 }
123 case ARMII::AddrMode3 : {
124 bool isSub = ARM_AM::getAM3Op(OffImm) == ARM_AM::sub;
125 unsigned Amt = ARM_AM::getAM3Offset(OffImm);
126 if (OffReg == 0)
127 // Immediate is 8-bits. It's guaranteed to fit in a so_imm operand.
128 UpdateMI = BuildMI(MF, MI->getDebugLoc(),
Evan Cheng78703dd2009-07-27 18:44:00 +0000129 get(isSub ? ARM::SUBri : ARM::ADDri), WBReg)
David Goodwin334c2642009-07-08 16:09:28 +0000130 .addReg(BaseReg).addImm(Amt)
131 .addImm(Pred).addReg(0).addReg(0);
132 else
133 UpdateMI = BuildMI(MF, MI->getDebugLoc(),
Evan Cheng78703dd2009-07-27 18:44:00 +0000134 get(isSub ? ARM::SUBrr : ARM::ADDrr), WBReg)
David Goodwin334c2642009-07-08 16:09:28 +0000135 .addReg(BaseReg).addReg(OffReg)
136 .addImm(Pred).addReg(0).addReg(0);
137 break;
138 }
139 }
140
141 std::vector<MachineInstr*> NewMIs;
142 if (isPre) {
143 if (isLoad)
144 MemMI = BuildMI(MF, MI->getDebugLoc(),
145 get(MemOpc), MI->getOperand(0).getReg())
146 .addReg(WBReg).addReg(0).addImm(0).addImm(Pred);
147 else
148 MemMI = BuildMI(MF, MI->getDebugLoc(),
149 get(MemOpc)).addReg(MI->getOperand(1).getReg())
150 .addReg(WBReg).addReg(0).addImm(0).addImm(Pred);
151 NewMIs.push_back(MemMI);
152 NewMIs.push_back(UpdateMI);
153 } else {
154 if (isLoad)
155 MemMI = BuildMI(MF, MI->getDebugLoc(),
156 get(MemOpc), MI->getOperand(0).getReg())
157 .addReg(BaseReg).addReg(0).addImm(0).addImm(Pred);
158 else
159 MemMI = BuildMI(MF, MI->getDebugLoc(),
160 get(MemOpc)).addReg(MI->getOperand(1).getReg())
161 .addReg(BaseReg).addReg(0).addImm(0).addImm(Pred);
162 if (WB.isDead())
163 UpdateMI->getOperand(0).setIsDead();
164 NewMIs.push_back(UpdateMI);
165 NewMIs.push_back(MemMI);
166 }
167
168 // Transfer LiveVariables states, kill / dead info.
169 if (LV) {
170 for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
171 MachineOperand &MO = MI->getOperand(i);
172 if (MO.isReg() && MO.getReg() &&
173 TargetRegisterInfo::isVirtualRegister(MO.getReg())) {
174 unsigned Reg = MO.getReg();
175
176 LiveVariables::VarInfo &VI = LV->getVarInfo(Reg);
177 if (MO.isDef()) {
178 MachineInstr *NewMI = (Reg == WBReg) ? UpdateMI : MemMI;
179 if (MO.isDead())
180 LV->addVirtualRegisterDead(Reg, NewMI);
181 }
182 if (MO.isUse() && MO.isKill()) {
183 for (unsigned j = 0; j < 2; ++j) {
184 // Look at the two new MI's in reverse order.
185 MachineInstr *NewMI = NewMIs[j];
186 if (!NewMI->readsRegister(Reg))
187 continue;
188 LV->addVirtualRegisterKilled(Reg, NewMI);
189 if (VI.removeKill(MI))
190 VI.Kills.push_back(NewMI);
191 break;
192 }
193 }
194 }
195 }
196 }
197
198 MFI->insert(MBBI, NewMIs[1]);
199 MFI->insert(MBBI, NewMIs[0]);
200 return NewMIs[0];
201}
202
203// Branch analysis.
204bool
205ARMBaseInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,MachineBasicBlock *&TBB,
206 MachineBasicBlock *&FBB,
207 SmallVectorImpl<MachineOperand> &Cond,
208 bool AllowModify) const {
209 // If the block has no terminators, it just falls into the block after it.
210 MachineBasicBlock::iterator I = MBB.end();
211 if (I == MBB.begin() || !isUnpredicatedTerminator(--I))
212 return false;
213
214 // Get the last instruction in the block.
215 MachineInstr *LastInst = I;
216
217 // If there is only one terminator instruction, process it.
218 unsigned LastOpc = LastInst->getOpcode();
219 if (I == MBB.begin() || !isUnpredicatedTerminator(--I)) {
Evan Cheng5ca53a72009-07-27 18:20:05 +0000220 if (isUncondBranchOpcode(LastOpc)) {
David Goodwin334c2642009-07-08 16:09:28 +0000221 TBB = LastInst->getOperand(0).getMBB();
222 return false;
223 }
Evan Cheng5ca53a72009-07-27 18:20:05 +0000224 if (isCondBranchOpcode(LastOpc)) {
David Goodwin334c2642009-07-08 16:09:28 +0000225 // Block ends with fall-through condbranch.
226 TBB = LastInst->getOperand(0).getMBB();
227 Cond.push_back(LastInst->getOperand(1));
228 Cond.push_back(LastInst->getOperand(2));
229 return false;
230 }
231 return true; // Can't handle indirect branch.
232 }
233
234 // Get the instruction before it if it is a terminator.
235 MachineInstr *SecondLastInst = I;
236
237 // If there are three terminators, we don't know what sort of block this is.
238 if (SecondLastInst && I != MBB.begin() && isUnpredicatedTerminator(--I))
239 return true;
240
Evan Cheng5ca53a72009-07-27 18:20:05 +0000241 // If the block ends with a B and a Bcc, handle it.
David Goodwin334c2642009-07-08 16:09:28 +0000242 unsigned SecondLastOpc = SecondLastInst->getOpcode();
Evan Cheng5ca53a72009-07-27 18:20:05 +0000243 if (isCondBranchOpcode(SecondLastOpc) && isUncondBranchOpcode(LastOpc)) {
David Goodwin334c2642009-07-08 16:09:28 +0000244 TBB = SecondLastInst->getOperand(0).getMBB();
245 Cond.push_back(SecondLastInst->getOperand(1));
246 Cond.push_back(SecondLastInst->getOperand(2));
247 FBB = LastInst->getOperand(0).getMBB();
248 return false;
249 }
250
251 // If the block ends with two unconditional branches, handle it. The second
252 // one is not executed, so remove it.
Evan Cheng5ca53a72009-07-27 18:20:05 +0000253 if (isUncondBranchOpcode(SecondLastOpc) && isUncondBranchOpcode(LastOpc)) {
David Goodwin334c2642009-07-08 16:09:28 +0000254 TBB = SecondLastInst->getOperand(0).getMBB();
255 I = LastInst;
256 if (AllowModify)
257 I->eraseFromParent();
258 return false;
259 }
260
261 // ...likewise if it ends with a branch table followed by an unconditional
262 // branch. The branch folder can create these, and we must get rid of them for
263 // correctness of Thumb constant islands.
Bob Wilson8d4de5a2009-10-28 18:26:41 +0000264 if ((isJumpTableBranchOpcode(SecondLastOpc) ||
265 isIndirectBranchOpcode(SecondLastOpc)) &&
Evan Cheng5ca53a72009-07-27 18:20:05 +0000266 isUncondBranchOpcode(LastOpc)) {
David Goodwin334c2642009-07-08 16:09:28 +0000267 I = LastInst;
268 if (AllowModify)
269 I->eraseFromParent();
270 return true;
271 }
272
273 // Otherwise, can't handle this.
274 return true;
275}
276
277
278unsigned ARMBaseInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const {
David Goodwin334c2642009-07-08 16:09:28 +0000279 MachineBasicBlock::iterator I = MBB.end();
280 if (I == MBB.begin()) return 0;
281 --I;
Evan Cheng5ca53a72009-07-27 18:20:05 +0000282 if (!isUncondBranchOpcode(I->getOpcode()) &&
283 !isCondBranchOpcode(I->getOpcode()))
David Goodwin334c2642009-07-08 16:09:28 +0000284 return 0;
285
286 // Remove the branch.
287 I->eraseFromParent();
288
289 I = MBB.end();
290
291 if (I == MBB.begin()) return 1;
292 --I;
Evan Cheng5ca53a72009-07-27 18:20:05 +0000293 if (!isCondBranchOpcode(I->getOpcode()))
David Goodwin334c2642009-07-08 16:09:28 +0000294 return 1;
295
296 // Remove the branch.
297 I->eraseFromParent();
298 return 2;
299}
300
301unsigned
302ARMBaseInstrInfo::InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
303 MachineBasicBlock *FBB,
304 const SmallVectorImpl<MachineOperand> &Cond) const {
305 // FIXME this should probably have a DebugLoc argument
306 DebugLoc dl = DebugLoc::getUnknownLoc();
Evan Cheng6495f632009-07-28 05:48:47 +0000307
308 ARMFunctionInfo *AFI = MBB.getParent()->getInfo<ARMFunctionInfo>();
309 int BOpc = !AFI->isThumbFunction()
310 ? ARM::B : (AFI->isThumb2Function() ? ARM::t2B : ARM::tB);
311 int BccOpc = !AFI->isThumbFunction()
312 ? ARM::Bcc : (AFI->isThumb2Function() ? ARM::t2Bcc : ARM::tBcc);
David Goodwin334c2642009-07-08 16:09:28 +0000313
314 // Shouldn't be a fall through.
315 assert(TBB && "InsertBranch must not be told to insert a fallthrough");
316 assert((Cond.size() == 2 || Cond.size() == 0) &&
317 "ARM branch conditions have two components!");
318
319 if (FBB == 0) {
320 if (Cond.empty()) // Unconditional branch?
321 BuildMI(&MBB, dl, get(BOpc)).addMBB(TBB);
322 else
323 BuildMI(&MBB, dl, get(BccOpc)).addMBB(TBB)
324 .addImm(Cond[0].getImm()).addReg(Cond[1].getReg());
325 return 1;
326 }
327
328 // Two-way conditional branch.
329 BuildMI(&MBB, dl, get(BccOpc)).addMBB(TBB)
330 .addImm(Cond[0].getImm()).addReg(Cond[1].getReg());
331 BuildMI(&MBB, dl, get(BOpc)).addMBB(FBB);
332 return 2;
333}
334
335bool ARMBaseInstrInfo::
336ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const {
337 ARMCC::CondCodes CC = (ARMCC::CondCodes)(int)Cond[0].getImm();
338 Cond[0].setImm(ARMCC::getOppositeCondition(CC));
339 return false;
340}
341
David Goodwin334c2642009-07-08 16:09:28 +0000342bool ARMBaseInstrInfo::
343PredicateInstruction(MachineInstr *MI,
344 const SmallVectorImpl<MachineOperand> &Pred) const {
345 unsigned Opc = MI->getOpcode();
Evan Cheng5ca53a72009-07-27 18:20:05 +0000346 if (isUncondBranchOpcode(Opc)) {
347 MI->setDesc(get(getMatchingCondBranchOpcode(Opc)));
David Goodwin334c2642009-07-08 16:09:28 +0000348 MI->addOperand(MachineOperand::CreateImm(Pred[0].getImm()));
349 MI->addOperand(MachineOperand::CreateReg(Pred[1].getReg(), false));
350 return true;
351 }
352
353 int PIdx = MI->findFirstPredOperandIdx();
354 if (PIdx != -1) {
355 MachineOperand &PMO = MI->getOperand(PIdx);
356 PMO.setImm(Pred[0].getImm());
357 MI->getOperand(PIdx+1).setReg(Pred[1].getReg());
358 return true;
359 }
360 return false;
361}
362
363bool ARMBaseInstrInfo::
364SubsumesPredicate(const SmallVectorImpl<MachineOperand> &Pred1,
365 const SmallVectorImpl<MachineOperand> &Pred2) const {
366 if (Pred1.size() > 2 || Pred2.size() > 2)
367 return false;
368
369 ARMCC::CondCodes CC1 = (ARMCC::CondCodes)Pred1[0].getImm();
370 ARMCC::CondCodes CC2 = (ARMCC::CondCodes)Pred2[0].getImm();
371 if (CC1 == CC2)
372 return true;
373
374 switch (CC1) {
375 default:
376 return false;
377 case ARMCC::AL:
378 return true;
379 case ARMCC::HS:
380 return CC2 == ARMCC::HI;
381 case ARMCC::LS:
382 return CC2 == ARMCC::LO || CC2 == ARMCC::EQ;
383 case ARMCC::GE:
384 return CC2 == ARMCC::GT;
385 case ARMCC::LE:
386 return CC2 == ARMCC::LT;
387 }
388}
389
390bool ARMBaseInstrInfo::DefinesPredicate(MachineInstr *MI,
391 std::vector<MachineOperand> &Pred) const {
Evan Cheng8fb90362009-08-08 03:20:32 +0000392 // FIXME: This confuses implicit_def with optional CPSR def.
David Goodwin334c2642009-07-08 16:09:28 +0000393 const TargetInstrDesc &TID = MI->getDesc();
394 if (!TID.getImplicitDefs() && !TID.hasOptionalDef())
395 return false;
396
397 bool Found = false;
398 for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
399 const MachineOperand &MO = MI->getOperand(i);
400 if (MO.isReg() && MO.getReg() == ARM::CPSR) {
401 Pred.push_back(MO);
402 Found = true;
403 }
404 }
405
406 return Found;
407}
408
Evan Chengac0869d2009-11-21 06:21:52 +0000409/// isPredicable - Return true if the specified instruction can be predicated.
410/// By default, this returns true for every instruction with a
411/// PredicateOperand.
412bool ARMBaseInstrInfo::isPredicable(MachineInstr *MI) const {
413 const TargetInstrDesc &TID = MI->getDesc();
414 if (!TID.isPredicable())
415 return false;
416
417 if ((TID.TSFlags & ARMII::DomainMask) == ARMII::DomainNEON) {
418 ARMFunctionInfo *AFI =
419 MI->getParent()->getParent()->getInfo<ARMFunctionInfo>();
420 return PredicateNEON && AFI->isThumb2Function();
421 }
422 return true;
423}
David Goodwin334c2642009-07-08 16:09:28 +0000424
425/// FIXME: Works around a gcc miscompilation with -fstrict-aliasing
426static unsigned getNumJTEntries(const std::vector<MachineJumpTableEntry> &JT,
427 unsigned JTI) DISABLE_INLINE;
428static unsigned getNumJTEntries(const std::vector<MachineJumpTableEntry> &JT,
429 unsigned JTI) {
430 return JT[JTI].MBBs.size();
431}
432
433/// GetInstSize - Return the size of the specified MachineInstr.
434///
435unsigned ARMBaseInstrInfo::GetInstSizeInBytes(const MachineInstr *MI) const {
436 const MachineBasicBlock &MBB = *MI->getParent();
437 const MachineFunction *MF = MBB.getParent();
Chris Lattner33adcfb2009-08-22 21:43:10 +0000438 const MCAsmInfo *MAI = MF->getTarget().getMCAsmInfo();
David Goodwin334c2642009-07-08 16:09:28 +0000439
440 // Basic size info comes from the TSFlags field.
441 const TargetInstrDesc &TID = MI->getDesc();
442 unsigned TSFlags = TID.TSFlags;
443
Evan Chenga0ee8622009-07-31 22:22:22 +0000444 unsigned Opc = MI->getOpcode();
David Goodwin334c2642009-07-08 16:09:28 +0000445 switch ((TSFlags & ARMII::SizeMask) >> ARMII::SizeShift) {
446 default: {
447 // If this machine instr is an inline asm, measure it.
448 if (MI->getOpcode() == ARM::INLINEASM)
Chris Lattner33adcfb2009-08-22 21:43:10 +0000449 return getInlineAsmLength(MI->getOperand(0).getSymbolName(), *MAI);
David Goodwin334c2642009-07-08 16:09:28 +0000450 if (MI->isLabel())
451 return 0;
Evan Chenga0ee8622009-07-31 22:22:22 +0000452 switch (Opc) {
David Goodwin334c2642009-07-08 16:09:28 +0000453 default:
Torok Edwinc23197a2009-07-14 16:55:14 +0000454 llvm_unreachable("Unknown or unset size field for instr!");
David Goodwin334c2642009-07-08 16:09:28 +0000455 case TargetInstrInfo::IMPLICIT_DEF:
Jakob Stoklund Olesen26207e52009-09-28 20:32:26 +0000456 case TargetInstrInfo::KILL:
David Goodwin334c2642009-07-08 16:09:28 +0000457 case TargetInstrInfo::DBG_LABEL:
458 case TargetInstrInfo::EH_LABEL:
459 return 0;
460 }
461 break;
462 }
Evan Cheng78947622009-07-24 18:20:44 +0000463 case ARMII::Size8Bytes: return 8; // ARM instruction x 2.
464 case ARMII::Size4Bytes: return 4; // ARM / Thumb2 instruction.
465 case ARMII::Size2Bytes: return 2; // Thumb1 instruction.
David Goodwin334c2642009-07-08 16:09:28 +0000466 case ARMII::SizeSpecial: {
Evan Chenga0ee8622009-07-31 22:22:22 +0000467 switch (Opc) {
David Goodwin334c2642009-07-08 16:09:28 +0000468 case ARM::CONSTPOOL_ENTRY:
469 // If this machine instr is a constant pool entry, its size is recorded as
470 // operand #2.
471 return MI->getOperand(2).getImm();
Evan Cheng78947622009-07-24 18:20:44 +0000472 case ARM::Int_eh_sjlj_setjmp:
Jim Grosbachcdc17eb2009-08-11 17:08:15 +0000473 return 24;
Jim Grosbach5aa16842009-08-11 19:42:21 +0000474 case ARM::t2Int_eh_sjlj_setjmp:
Evan Cheng5a1cd362009-11-03 23:13:34 +0000475 return 22;
David Goodwin334c2642009-07-08 16:09:28 +0000476 case ARM::BR_JTr:
477 case ARM::BR_JTm:
478 case ARM::BR_JTadd:
Evan Chenga0ee8622009-07-31 22:22:22 +0000479 case ARM::tBR_JTr:
Evan Chengd26b14c2009-07-31 18:28:05 +0000480 case ARM::t2BR_JT:
481 case ARM::t2TBB:
482 case ARM::t2TBH: {
David Goodwin334c2642009-07-08 16:09:28 +0000483 // These are jumptable branches, i.e. a branch followed by an inlined
Evan Chengd26b14c2009-07-31 18:28:05 +0000484 // jumptable. The size is 4 + 4 * number of entries. For TBB, each
485 // entry is one byte; TBH two byte each.
Evan Chenga0ee8622009-07-31 22:22:22 +0000486 unsigned EntrySize = (Opc == ARM::t2TBB)
487 ? 1 : ((Opc == ARM::t2TBH) ? 2 : 4);
David Goodwin334c2642009-07-08 16:09:28 +0000488 unsigned NumOps = TID.getNumOperands();
489 MachineOperand JTOP =
490 MI->getOperand(NumOps - (TID.isPredicable() ? 3 : 2));
491 unsigned JTI = JTOP.getIndex();
492 const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
493 const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
494 assert(JTI < JT.size());
495 // Thumb instructions are 2 byte aligned, but JT entries are 4 byte
496 // 4 aligned. The assembler / linker may add 2 byte padding just before
497 // the JT entries. The size does not include this padding; the
498 // constant islands pass does separate bookkeeping for it.
499 // FIXME: If we know the size of the function is less than (1 << 16) *2
500 // bytes, we can use 16-bit entries instead. Then there won't be an
501 // alignment issue.
Evan Cheng25f7cfc2009-08-01 06:13:52 +0000502 unsigned InstSize = (Opc == ARM::tBR_JTr || Opc == ARM::t2BR_JT) ? 2 : 4;
503 unsigned NumEntries = getNumJTEntries(JT, JTI);
504 if (Opc == ARM::t2TBB && (NumEntries & 1))
505 // Make sure the instruction that follows TBB is 2-byte aligned.
506 // FIXME: Constant island pass should insert an "ALIGN" instruction
507 // instead.
508 ++NumEntries;
509 return NumEntries * EntrySize + InstSize;
David Goodwin334c2642009-07-08 16:09:28 +0000510 }
511 default:
512 // Otherwise, pseudo-instruction sizes are zero.
513 return 0;
514 }
515 }
516 }
517 return 0; // Not reached
518}
519
520/// Return true if the instruction is a register to register move and
521/// leave the source and dest operands in the passed parameters.
522///
523bool
524ARMBaseInstrInfo::isMoveInstr(const MachineInstr &MI,
525 unsigned &SrcReg, unsigned &DstReg,
526 unsigned& SrcSubIdx, unsigned& DstSubIdx) const {
527 SrcSubIdx = DstSubIdx = 0; // No sub-registers.
528
Evan Cheng68e3c6a2009-07-27 00:05:15 +0000529 switch (MI.getOpcode()) {
Evan Chengdced03f2009-07-27 00:24:36 +0000530 default: break;
Jim Grosbache5165492009-11-09 00:11:35 +0000531 case ARM::VMOVS:
Evan Cheng68e3c6a2009-07-27 00:05:15 +0000532 case ARM::VMOVD:
Jim Grosbache5165492009-11-09 00:11:35 +0000533 case ARM::VMOVDneon:
Anton Korobeynikovf95215f2009-11-02 00:10:38 +0000534 case ARM::VMOVQ: {
David Goodwin334c2642009-07-08 16:09:28 +0000535 SrcReg = MI.getOperand(1).getReg();
536 DstReg = MI.getOperand(0).getReg();
537 return true;
538 }
Evan Cheng68e3c6a2009-07-27 00:05:15 +0000539 case ARM::MOVr:
540 case ARM::tMOVr:
541 case ARM::tMOVgpr2tgpr:
542 case ARM::tMOVtgpr2gpr:
543 case ARM::tMOVgpr2gpr:
544 case ARM::t2MOVr: {
David Goodwin334c2642009-07-08 16:09:28 +0000545 assert(MI.getDesc().getNumOperands() >= 2 &&
546 MI.getOperand(0).isReg() &&
547 MI.getOperand(1).isReg() &&
548 "Invalid ARM MOV instruction");
549 SrcReg = MI.getOperand(1).getReg();
550 DstReg = MI.getOperand(0).getReg();
551 return true;
552 }
Evan Cheng68e3c6a2009-07-27 00:05:15 +0000553 }
David Goodwin334c2642009-07-08 16:09:28 +0000554
555 return false;
556}
557
Jim Grosbach764ab522009-08-11 15:33:49 +0000558unsigned
David Goodwin334c2642009-07-08 16:09:28 +0000559ARMBaseInstrInfo::isLoadFromStackSlot(const MachineInstr *MI,
560 int &FrameIndex) const {
Evan Chengdced03f2009-07-27 00:24:36 +0000561 switch (MI->getOpcode()) {
562 default: break;
563 case ARM::LDR:
564 case ARM::t2LDRs: // FIXME: don't use t2LDRs to access frame.
David Goodwin334c2642009-07-08 16:09:28 +0000565 if (MI->getOperand(1).isFI() &&
566 MI->getOperand(2).isReg() &&
567 MI->getOperand(3).isImm() &&
568 MI->getOperand(2).getReg() == 0 &&
569 MI->getOperand(3).getImm() == 0) {
570 FrameIndex = MI->getOperand(1).getIndex();
571 return MI->getOperand(0).getReg();
572 }
Evan Chengdced03f2009-07-27 00:24:36 +0000573 break;
574 case ARM::t2LDRi12:
575 case ARM::tRestore:
David Goodwin5ff58b52009-07-24 00:16:18 +0000576 if (MI->getOperand(1).isFI() &&
577 MI->getOperand(2).isImm() &&
578 MI->getOperand(2).getImm() == 0) {
579 FrameIndex = MI->getOperand(1).getIndex();
580 return MI->getOperand(0).getReg();
581 }
Evan Chengdced03f2009-07-27 00:24:36 +0000582 break;
Jim Grosbache5165492009-11-09 00:11:35 +0000583 case ARM::VLDRD:
584 case ARM::VLDRS:
David Goodwin334c2642009-07-08 16:09:28 +0000585 if (MI->getOperand(1).isFI() &&
586 MI->getOperand(2).isImm() &&
587 MI->getOperand(2).getImm() == 0) {
588 FrameIndex = MI->getOperand(1).getIndex();
589 return MI->getOperand(0).getReg();
590 }
Evan Chengdced03f2009-07-27 00:24:36 +0000591 break;
David Goodwin334c2642009-07-08 16:09:28 +0000592 }
593
594 return 0;
595}
596
597unsigned
598ARMBaseInstrInfo::isStoreToStackSlot(const MachineInstr *MI,
599 int &FrameIndex) const {
Evan Chengdced03f2009-07-27 00:24:36 +0000600 switch (MI->getOpcode()) {
601 default: break;
602 case ARM::STR:
603 case ARM::t2STRs: // FIXME: don't use t2STRs to access frame.
David Goodwin334c2642009-07-08 16:09:28 +0000604 if (MI->getOperand(1).isFI() &&
605 MI->getOperand(2).isReg() &&
606 MI->getOperand(3).isImm() &&
607 MI->getOperand(2).getReg() == 0 &&
608 MI->getOperand(3).getImm() == 0) {
609 FrameIndex = MI->getOperand(1).getIndex();
610 return MI->getOperand(0).getReg();
611 }
Evan Chengdced03f2009-07-27 00:24:36 +0000612 break;
613 case ARM::t2STRi12:
614 case ARM::tSpill:
David Goodwin5ff58b52009-07-24 00:16:18 +0000615 if (MI->getOperand(1).isFI() &&
616 MI->getOperand(2).isImm() &&
617 MI->getOperand(2).getImm() == 0) {
618 FrameIndex = MI->getOperand(1).getIndex();
619 return MI->getOperand(0).getReg();
620 }
Evan Chengdced03f2009-07-27 00:24:36 +0000621 break;
Jim Grosbache5165492009-11-09 00:11:35 +0000622 case ARM::VSTRD:
623 case ARM::VSTRS:
David Goodwin334c2642009-07-08 16:09:28 +0000624 if (MI->getOperand(1).isFI() &&
625 MI->getOperand(2).isImm() &&
626 MI->getOperand(2).getImm() == 0) {
627 FrameIndex = MI->getOperand(1).getIndex();
628 return MI->getOperand(0).getReg();
629 }
Evan Chengdced03f2009-07-27 00:24:36 +0000630 break;
David Goodwin334c2642009-07-08 16:09:28 +0000631 }
632
633 return 0;
634}
635
636bool
637ARMBaseInstrInfo::copyRegToReg(MachineBasicBlock &MBB,
638 MachineBasicBlock::iterator I,
639 unsigned DestReg, unsigned SrcReg,
640 const TargetRegisterClass *DestRC,
641 const TargetRegisterClass *SrcRC) const {
642 DebugLoc DL = DebugLoc::getUnknownLoc();
643 if (I != MBB.end()) DL = I->getDebugLoc();
644
645 if (DestRC != SrcRC) {
Evan Chengb4db6a42009-11-03 05:51:39 +0000646 if (DestRC->getSize() != SrcRC->getSize())
647 return false;
648
649 // Allow DPR / DPR_VFP2 / DPR_8 cross-class copies.
650 // Allow QPR / QPR_VFP2 / QPR_8 cross-class copies.
651 if (DestRC->getSize() != 8 && DestRC->getSize() != 16)
David Goodwin7bfdca02009-08-05 21:02:22 +0000652 return false;
David Goodwin334c2642009-07-08 16:09:28 +0000653 }
654
David Goodwin7bfdca02009-08-05 21:02:22 +0000655 if (DestRC == ARM::GPRRegisterClass) {
Evan Cheng08b93c62009-07-27 00:33:08 +0000656 AddDefaultCC(AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::MOVr),
Evan Chengdd6f6322009-07-11 06:37:27 +0000657 DestReg).addReg(SrcReg)));
David Goodwin7bfdca02009-08-05 21:02:22 +0000658 } else if (DestRC == ARM::SPRRegisterClass) {
Jim Grosbache5165492009-11-09 00:11:35 +0000659 AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VMOVS), DestReg)
David Goodwin334c2642009-07-08 16:09:28 +0000660 .addReg(SrcReg));
Evan Chengb4db6a42009-11-03 05:51:39 +0000661 } else if (DestRC == ARM::DPRRegisterClass) {
Jim Grosbache5165492009-11-09 00:11:35 +0000662 AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VMOVD), DestReg)
Evan Chengb4db6a42009-11-03 05:51:39 +0000663 .addReg(SrcReg));
Anton Korobeynikovf95215f2009-11-02 00:10:38 +0000664 } else if (DestRC == ARM::DPR_VFP2RegisterClass ||
665 DestRC == ARM::DPR_8RegisterClass ||
666 SrcRC == ARM::DPR_VFP2RegisterClass ||
667 SrcRC == ARM::DPR_8RegisterClass) {
668 // Always use neon reg-reg move if source or dest is NEON-only regclass.
Evan Chengac0869d2009-11-21 06:21:52 +0000669 AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VMOVDneon),
670 DestReg).addReg(SrcReg));
Anton Korobeynikove56f9082009-09-12 22:21:08 +0000671 } else if (DestRC == ARM::QPRRegisterClass ||
Evan Chengb4db6a42009-11-03 05:51:39 +0000672 DestRC == ARM::QPR_VFP2RegisterClass ||
673 DestRC == ARM::QPR_8RegisterClass) {
Evan Chengac0869d2009-11-21 06:21:52 +0000674 AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VMOVQ),
675 DestReg).addReg(SrcReg));
David Goodwin7bfdca02009-08-05 21:02:22 +0000676 } else {
David Goodwin334c2642009-07-08 16:09:28 +0000677 return false;
David Goodwin7bfdca02009-08-05 21:02:22 +0000678 }
David Goodwin334c2642009-07-08 16:09:28 +0000679
680 return true;
681}
682
683void ARMBaseInstrInfo::
684storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
685 unsigned SrcReg, bool isKill, int FI,
686 const TargetRegisterClass *RC) const {
687 DebugLoc DL = DebugLoc::getUnknownLoc();
688 if (I != MBB.end()) DL = I->getDebugLoc();
Anton Korobeynikov249fb332009-10-07 00:06:35 +0000689 MachineFunction &MF = *MBB.getParent();
690 MachineFrameInfo &MFI = *MF.getFrameInfo();
Jim Grosbach31bc8492009-11-08 00:27:19 +0000691 unsigned Align = MFI.getObjectAlignment(FI);
Anton Korobeynikov249fb332009-10-07 00:06:35 +0000692
693 MachineMemOperand *MMO =
Evan Chengff89dcb2009-10-18 18:16:27 +0000694 MF.getMachineMemOperand(PseudoSourceValue::getFixedStack(FI),
Anton Korobeynikov249fb332009-10-07 00:06:35 +0000695 MachineMemOperand::MOStore, 0,
696 MFI.getObjectSize(FI),
Jim Grosbach31bc8492009-11-08 00:27:19 +0000697 Align);
David Goodwin334c2642009-07-08 16:09:28 +0000698
699 if (RC == ARM::GPRRegisterClass) {
Evan Cheng5732ca02009-07-27 03:14:20 +0000700 AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::STR))
David Goodwin334c2642009-07-08 16:09:28 +0000701 .addReg(SrcReg, getKillRegState(isKill))
Anton Korobeynikov249fb332009-10-07 00:06:35 +0000702 .addFrameIndex(FI).addReg(0).addImm(0).addMemOperand(MMO));
Anton Korobeynikov6ca0b9e2009-09-08 15:22:32 +0000703 } else if (RC == ARM::DPRRegisterClass ||
704 RC == ARM::DPR_VFP2RegisterClass ||
705 RC == ARM::DPR_8RegisterClass) {
Jim Grosbache5165492009-11-09 00:11:35 +0000706 AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VSTRD))
David Goodwin334c2642009-07-08 16:09:28 +0000707 .addReg(SrcReg, getKillRegState(isKill))
Anton Korobeynikov249fb332009-10-07 00:06:35 +0000708 .addFrameIndex(FI).addImm(0).addMemOperand(MMO));
Anton Korobeynikovbaf31082009-08-08 13:35:48 +0000709 } else if (RC == ARM::SPRRegisterClass) {
Jim Grosbache5165492009-11-09 00:11:35 +0000710 AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VSTRS))
David Goodwin334c2642009-07-08 16:09:28 +0000711 .addReg(SrcReg, getKillRegState(isKill))
Anton Korobeynikov249fb332009-10-07 00:06:35 +0000712 .addFrameIndex(FI).addImm(0).addMemOperand(MMO));
Anton Korobeynikovbaf31082009-08-08 13:35:48 +0000713 } else {
Anton Korobeynikove56f9082009-09-12 22:21:08 +0000714 assert((RC == ARM::QPRRegisterClass ||
715 RC == ARM::QPR_VFP2RegisterClass) && "Unknown regclass!");
Anton Korobeynikovbaf31082009-08-08 13:35:48 +0000716 // FIXME: Neon instructions should support predicates
Jim Grosbach31bc8492009-11-08 00:27:19 +0000717 if (Align >= 16
718 && (getRegisterInfo().needsStackRealignment(MF))) {
Evan Chengac0869d2009-11-21 06:21:52 +0000719 AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VST1q64))
720 .addFrameIndex(FI).addImm(0).addImm(0).addImm(128)
721 .addMemOperand(MMO)
722 .addReg(SrcReg, getKillRegState(isKill)));
Jim Grosbach31bc8492009-11-08 00:27:19 +0000723 } else {
Evan Chengac0869d2009-11-21 06:21:52 +0000724 AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VSTRQ)).
725 addReg(SrcReg, getKillRegState(isKill))
726 .addFrameIndex(FI).addImm(0).addMemOperand(MMO));
Jim Grosbach31bc8492009-11-08 00:27:19 +0000727 }
David Goodwin334c2642009-07-08 16:09:28 +0000728 }
729}
730
David Goodwin334c2642009-07-08 16:09:28 +0000731void ARMBaseInstrInfo::
732loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
733 unsigned DestReg, int FI,
734 const TargetRegisterClass *RC) const {
735 DebugLoc DL = DebugLoc::getUnknownLoc();
736 if (I != MBB.end()) DL = I->getDebugLoc();
Anton Korobeynikov249fb332009-10-07 00:06:35 +0000737 MachineFunction &MF = *MBB.getParent();
738 MachineFrameInfo &MFI = *MF.getFrameInfo();
Jim Grosbach31bc8492009-11-08 00:27:19 +0000739 unsigned Align = MFI.getObjectAlignment(FI);
Anton Korobeynikov249fb332009-10-07 00:06:35 +0000740
741 MachineMemOperand *MMO =
Evan Chengff89dcb2009-10-18 18:16:27 +0000742 MF.getMachineMemOperand(PseudoSourceValue::getFixedStack(FI),
Anton Korobeynikov249fb332009-10-07 00:06:35 +0000743 MachineMemOperand::MOLoad, 0,
744 MFI.getObjectSize(FI),
Jim Grosbach31bc8492009-11-08 00:27:19 +0000745 Align);
David Goodwin334c2642009-07-08 16:09:28 +0000746
747 if (RC == ARM::GPRRegisterClass) {
Evan Cheng5732ca02009-07-27 03:14:20 +0000748 AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::LDR), DestReg)
Anton Korobeynikov249fb332009-10-07 00:06:35 +0000749 .addFrameIndex(FI).addReg(0).addImm(0).addMemOperand(MMO));
Anton Korobeynikov6ca0b9e2009-09-08 15:22:32 +0000750 } else if (RC == ARM::DPRRegisterClass ||
751 RC == ARM::DPR_VFP2RegisterClass ||
752 RC == ARM::DPR_8RegisterClass) {
Jim Grosbache5165492009-11-09 00:11:35 +0000753 AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VLDRD), DestReg)
Anton Korobeynikov249fb332009-10-07 00:06:35 +0000754 .addFrameIndex(FI).addImm(0).addMemOperand(MMO));
Anton Korobeynikovbaf31082009-08-08 13:35:48 +0000755 } else if (RC == ARM::SPRRegisterClass) {
Jim Grosbache5165492009-11-09 00:11:35 +0000756 AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VLDRS), DestReg)
Anton Korobeynikov249fb332009-10-07 00:06:35 +0000757 .addFrameIndex(FI).addImm(0).addMemOperand(MMO));
Anton Korobeynikovbaf31082009-08-08 13:35:48 +0000758 } else {
Anton Korobeynikove56f9082009-09-12 22:21:08 +0000759 assert((RC == ARM::QPRRegisterClass ||
Evan Chengb4db6a42009-11-03 05:51:39 +0000760 RC == ARM::QPR_VFP2RegisterClass ||
761 RC == ARM::QPR_8RegisterClass) && "Unknown regclass!");
Anton Korobeynikovbaf31082009-08-08 13:35:48 +0000762 // FIXME: Neon instructions should support predicates
Jim Grosbach31bc8492009-11-08 00:27:19 +0000763 if (Align >= 16
764 && (getRegisterInfo().needsStackRealignment(MF))) {
Evan Chengac0869d2009-11-21 06:21:52 +0000765 AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VLD1q64), DestReg)
766 .addFrameIndex(FI).addImm(0).addImm(0).addImm(128)
767 .addMemOperand(MMO));
Jim Grosbach31bc8492009-11-08 00:27:19 +0000768 } else {
Evan Chengac0869d2009-11-21 06:21:52 +0000769 AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VLDRQ), DestReg)
770 .addFrameIndex(FI).addImm(0).addMemOperand(MMO));
Jim Grosbach31bc8492009-11-08 00:27:19 +0000771 }
David Goodwin334c2642009-07-08 16:09:28 +0000772 }
773}
774
David Goodwin334c2642009-07-08 16:09:28 +0000775MachineInstr *ARMBaseInstrInfo::
776foldMemoryOperandImpl(MachineFunction &MF, MachineInstr *MI,
777 const SmallVectorImpl<unsigned> &Ops, int FI) const {
778 if (Ops.size() != 1) return NULL;
779
780 unsigned OpNum = Ops[0];
781 unsigned Opc = MI->getOpcode();
782 MachineInstr *NewMI = NULL;
Evan Cheng19068ba2009-08-10 06:32:05 +0000783 if (Opc == ARM::MOVr || Opc == ARM::t2MOVr) {
David Goodwin334c2642009-07-08 16:09:28 +0000784 // If it is updating CPSR, then it cannot be folded.
Evan Cheng19068ba2009-08-10 06:32:05 +0000785 if (MI->getOperand(4).getReg() == ARM::CPSR && !MI->getOperand(4).isDead())
786 return NULL;
787 unsigned Pred = MI->getOperand(2).getImm();
788 unsigned PredReg = MI->getOperand(3).getReg();
789 if (OpNum == 0) { // move -> store
790 unsigned SrcReg = MI->getOperand(1).getReg();
Evan Chenged3ad212009-10-25 07:52:27 +0000791 unsigned SrcSubReg = MI->getOperand(1).getSubReg();
Evan Cheng19068ba2009-08-10 06:32:05 +0000792 bool isKill = MI->getOperand(1).isKill();
793 bool isUndef = MI->getOperand(1).isUndef();
794 if (Opc == ARM::MOVr)
795 NewMI = BuildMI(MF, MI->getDebugLoc(), get(ARM::STR))
Evan Chenged3ad212009-10-25 07:52:27 +0000796 .addReg(SrcReg,
797 getKillRegState(isKill) | getUndefRegState(isUndef),
798 SrcSubReg)
Evan Cheng19068ba2009-08-10 06:32:05 +0000799 .addFrameIndex(FI).addReg(0).addImm(0).addImm(Pred).addReg(PredReg);
800 else // ARM::t2MOVr
801 NewMI = BuildMI(MF, MI->getDebugLoc(), get(ARM::t2STRi12))
Evan Chenged3ad212009-10-25 07:52:27 +0000802 .addReg(SrcReg,
803 getKillRegState(isKill) | getUndefRegState(isUndef),
804 SrcSubReg)
Evan Cheng19068ba2009-08-10 06:32:05 +0000805 .addFrameIndex(FI).addImm(0).addImm(Pred).addReg(PredReg);
806 } else { // move -> load
807 unsigned DstReg = MI->getOperand(0).getReg();
Evan Chenged3ad212009-10-25 07:52:27 +0000808 unsigned DstSubReg = MI->getOperand(0).getSubReg();
Evan Cheng19068ba2009-08-10 06:32:05 +0000809 bool isDead = MI->getOperand(0).isDead();
810 bool isUndef = MI->getOperand(0).isUndef();
811 if (Opc == ARM::MOVr)
812 NewMI = BuildMI(MF, MI->getDebugLoc(), get(ARM::LDR))
813 .addReg(DstReg,
814 RegState::Define |
815 getDeadRegState(isDead) |
Evan Chenged3ad212009-10-25 07:52:27 +0000816 getUndefRegState(isUndef), DstSubReg)
Evan Cheng19068ba2009-08-10 06:32:05 +0000817 .addFrameIndex(FI).addReg(0).addImm(0).addImm(Pred).addReg(PredReg);
818 else // ARM::t2MOVr
819 NewMI = BuildMI(MF, MI->getDebugLoc(), get(ARM::t2LDRi12))
820 .addReg(DstReg,
821 RegState::Define |
822 getDeadRegState(isDead) |
Evan Chenged3ad212009-10-25 07:52:27 +0000823 getUndefRegState(isUndef), DstSubReg)
Evan Cheng19068ba2009-08-10 06:32:05 +0000824 .addFrameIndex(FI).addImm(0).addImm(Pred).addReg(PredReg);
David Goodwin334c2642009-07-08 16:09:28 +0000825 }
Evan Cheng19068ba2009-08-10 06:32:05 +0000826 } else if (Opc == ARM::tMOVgpr2gpr ||
827 Opc == ARM::tMOVtgpr2gpr ||
828 Opc == ARM::tMOVgpr2tgpr) {
829 if (OpNum == 0) { // move -> store
830 unsigned SrcReg = MI->getOperand(1).getReg();
Evan Chenged3ad212009-10-25 07:52:27 +0000831 unsigned SrcSubReg = MI->getOperand(1).getSubReg();
Evan Cheng19068ba2009-08-10 06:32:05 +0000832 bool isKill = MI->getOperand(1).isKill();
833 bool isUndef = MI->getOperand(1).isUndef();
834 NewMI = BuildMI(MF, MI->getDebugLoc(), get(ARM::t2STRi12))
Evan Chenged3ad212009-10-25 07:52:27 +0000835 .addReg(SrcReg,
836 getKillRegState(isKill) | getUndefRegState(isUndef),
837 SrcSubReg)
Evan Cheng19068ba2009-08-10 06:32:05 +0000838 .addFrameIndex(FI).addImm(0).addImm(ARMCC::AL).addReg(0);
839 } else { // move -> load
840 unsigned DstReg = MI->getOperand(0).getReg();
Evan Chenged3ad212009-10-25 07:52:27 +0000841 unsigned DstSubReg = MI->getOperand(0).getSubReg();
Evan Cheng19068ba2009-08-10 06:32:05 +0000842 bool isDead = MI->getOperand(0).isDead();
843 bool isUndef = MI->getOperand(0).isUndef();
844 NewMI = BuildMI(MF, MI->getDebugLoc(), get(ARM::t2LDRi12))
845 .addReg(DstReg,
846 RegState::Define |
847 getDeadRegState(isDead) |
Evan Chenged3ad212009-10-25 07:52:27 +0000848 getUndefRegState(isUndef),
849 DstSubReg)
Evan Cheng19068ba2009-08-10 06:32:05 +0000850 .addFrameIndex(FI).addImm(0).addImm(ARMCC::AL).addReg(0);
851 }
Jim Grosbache5165492009-11-09 00:11:35 +0000852 } else if (Opc == ARM::VMOVS) {
David Goodwin334c2642009-07-08 16:09:28 +0000853 unsigned Pred = MI->getOperand(2).getImm();
854 unsigned PredReg = MI->getOperand(3).getReg();
855 if (OpNum == 0) { // move -> store
856 unsigned SrcReg = MI->getOperand(1).getReg();
Evan Chenged3ad212009-10-25 07:52:27 +0000857 unsigned SrcSubReg = MI->getOperand(1).getSubReg();
David Goodwin334c2642009-07-08 16:09:28 +0000858 bool isKill = MI->getOperand(1).isKill();
859 bool isUndef = MI->getOperand(1).isUndef();
Jim Grosbache5165492009-11-09 00:11:35 +0000860 NewMI = BuildMI(MF, MI->getDebugLoc(), get(ARM::VSTRS))
Evan Chenged3ad212009-10-25 07:52:27 +0000861 .addReg(SrcReg, getKillRegState(isKill) | getUndefRegState(isUndef),
862 SrcSubReg)
David Goodwin334c2642009-07-08 16:09:28 +0000863 .addFrameIndex(FI)
864 .addImm(0).addImm(Pred).addReg(PredReg);
865 } else { // move -> load
866 unsigned DstReg = MI->getOperand(0).getReg();
Evan Chenged3ad212009-10-25 07:52:27 +0000867 unsigned DstSubReg = MI->getOperand(0).getSubReg();
David Goodwin334c2642009-07-08 16:09:28 +0000868 bool isDead = MI->getOperand(0).isDead();
869 bool isUndef = MI->getOperand(0).isUndef();
Jim Grosbache5165492009-11-09 00:11:35 +0000870 NewMI = BuildMI(MF, MI->getDebugLoc(), get(ARM::VLDRS))
David Goodwin334c2642009-07-08 16:09:28 +0000871 .addReg(DstReg,
872 RegState::Define |
873 getDeadRegState(isDead) |
Evan Chenged3ad212009-10-25 07:52:27 +0000874 getUndefRegState(isUndef),
875 DstSubReg)
David Goodwin334c2642009-07-08 16:09:28 +0000876 .addFrameIndex(FI).addImm(0).addImm(Pred).addReg(PredReg);
877 }
878 }
Jim Grosbache5165492009-11-09 00:11:35 +0000879 else if (Opc == ARM::VMOVD) {
David Goodwin334c2642009-07-08 16:09:28 +0000880 unsigned Pred = MI->getOperand(2).getImm();
881 unsigned PredReg = MI->getOperand(3).getReg();
882 if (OpNum == 0) { // move -> store
883 unsigned SrcReg = MI->getOperand(1).getReg();
Evan Chenged3ad212009-10-25 07:52:27 +0000884 unsigned SrcSubReg = MI->getOperand(1).getSubReg();
David Goodwin334c2642009-07-08 16:09:28 +0000885 bool isKill = MI->getOperand(1).isKill();
886 bool isUndef = MI->getOperand(1).isUndef();
Jim Grosbache5165492009-11-09 00:11:35 +0000887 NewMI = BuildMI(MF, MI->getDebugLoc(), get(ARM::VSTRD))
Evan Chenged3ad212009-10-25 07:52:27 +0000888 .addReg(SrcReg,
889 getKillRegState(isKill) | getUndefRegState(isUndef),
890 SrcSubReg)
David Goodwin334c2642009-07-08 16:09:28 +0000891 .addFrameIndex(FI).addImm(0).addImm(Pred).addReg(PredReg);
892 } else { // move -> load
893 unsigned DstReg = MI->getOperand(0).getReg();
Evan Chenged3ad212009-10-25 07:52:27 +0000894 unsigned DstSubReg = MI->getOperand(0).getSubReg();
David Goodwin334c2642009-07-08 16:09:28 +0000895 bool isDead = MI->getOperand(0).isDead();
896 bool isUndef = MI->getOperand(0).isUndef();
Jim Grosbache5165492009-11-09 00:11:35 +0000897 NewMI = BuildMI(MF, MI->getDebugLoc(), get(ARM::VLDRD))
David Goodwin334c2642009-07-08 16:09:28 +0000898 .addReg(DstReg,
899 RegState::Define |
900 getDeadRegState(isDead) |
Evan Chenged3ad212009-10-25 07:52:27 +0000901 getUndefRegState(isUndef),
902 DstSubReg)
David Goodwin334c2642009-07-08 16:09:28 +0000903 .addFrameIndex(FI).addImm(0).addImm(Pred).addReg(PredReg);
904 }
905 }
906
907 return NewMI;
908}
909
Jim Grosbach764ab522009-08-11 15:33:49 +0000910MachineInstr*
David Goodwin334c2642009-07-08 16:09:28 +0000911ARMBaseInstrInfo::foldMemoryOperandImpl(MachineFunction &MF,
912 MachineInstr* MI,
913 const SmallVectorImpl<unsigned> &Ops,
914 MachineInstr* LoadMI) const {
Evan Cheng1f5c9882009-07-27 04:18:04 +0000915 // FIXME
David Goodwin334c2642009-07-08 16:09:28 +0000916 return 0;
917}
918
919bool
920ARMBaseInstrInfo::canFoldMemoryOperand(const MachineInstr *MI,
Evan Cheng22946452009-08-10 05:51:48 +0000921 const SmallVectorImpl<unsigned> &Ops) const {
David Goodwin334c2642009-07-08 16:09:28 +0000922 if (Ops.size() != 1) return false;
923
924 unsigned Opc = MI->getOpcode();
Evan Cheng5732ca02009-07-27 03:14:20 +0000925 if (Opc == ARM::MOVr || Opc == ARM::t2MOVr) {
David Goodwin334c2642009-07-08 16:09:28 +0000926 // If it is updating CPSR, then it cannot be folded.
Evan Cheng22946452009-08-10 05:51:48 +0000927 return MI->getOperand(4).getReg() != ARM::CPSR ||
928 MI->getOperand(4).isDead();
Evan Cheng19068ba2009-08-10 06:32:05 +0000929 } else if (Opc == ARM::tMOVgpr2gpr ||
930 Opc == ARM::tMOVtgpr2gpr ||
931 Opc == ARM::tMOVgpr2tgpr) {
932 return true;
Jim Grosbache5165492009-11-09 00:11:35 +0000933 } else if (Opc == ARM::VMOVS || Opc == ARM::VMOVD) {
David Goodwin334c2642009-07-08 16:09:28 +0000934 return true;
Jim Grosbache5165492009-11-09 00:11:35 +0000935 } else if (Opc == ARM::VMOVDneon || Opc == ARM::VMOVQ) {
David Goodwin334c2642009-07-08 16:09:28 +0000936 return false; // FIXME
937 }
938
939 return false;
940}
Evan Cheng5ca53a72009-07-27 18:20:05 +0000941
Evan Chengfdc83402009-11-08 00:15:23 +0000942void ARMBaseInstrInfo::
943reMaterialize(MachineBasicBlock &MBB,
944 MachineBasicBlock::iterator I,
945 unsigned DestReg, unsigned SubIdx,
Evan Chengd57cdd52009-11-14 02:55:43 +0000946 const MachineInstr *Orig,
947 const TargetRegisterInfo *TRI) const {
Evan Chengfdc83402009-11-08 00:15:23 +0000948 DebugLoc dl = Orig->getDebugLoc();
Evan Chengd57cdd52009-11-14 02:55:43 +0000949
950 if (SubIdx && TargetRegisterInfo::isPhysicalRegister(DestReg)) {
951 DestReg = TRI->getSubReg(DestReg, SubIdx);
952 SubIdx = 0;
953 }
954
Evan Chengfdc83402009-11-08 00:15:23 +0000955 unsigned Opcode = Orig->getOpcode();
956 switch (Opcode) {
957 default: {
958 MachineInstr *MI = MBB.getParent()->CloneMachineInstr(Orig);
959 MI->getOperand(0).setReg(DestReg);
960 MBB.insert(I, MI);
961 break;
962 }
963 case ARM::tLDRpci_pic:
964 case ARM::t2LDRpci_pic: {
965 MachineFunction &MF = *MBB.getParent();
966 ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
967 MachineConstantPool *MCP = MF.getConstantPool();
968 unsigned CPI = Orig->getOperand(1).getIndex();
969 const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPI];
970 assert(MCPE.isMachineConstantPoolEntry() &&
971 "Expecting a machine constantpool entry!");
972 ARMConstantPoolValue *ACPV =
973 static_cast<ARMConstantPoolValue*>(MCPE.Val.MachineCPVal);
974 unsigned PCLabelId = AFI->createConstPoolEntryUId();
975 ARMConstantPoolValue *NewCPV = 0;
976 if (ACPV->isGlobalValue())
977 NewCPV = new ARMConstantPoolValue(ACPV->getGV(), PCLabelId,
978 ARMCP::CPValue, 4);
979 else if (ACPV->isExtSymbol())
980 NewCPV = new ARMConstantPoolValue(MF.getFunction()->getContext(),
981 ACPV->getSymbol(), PCLabelId, 4);
982 else if (ACPV->isBlockAddress())
983 NewCPV = new ARMConstantPoolValue(ACPV->getBlockAddress(), PCLabelId,
984 ARMCP::CPBlockAddress, 4);
985 else
986 llvm_unreachable("Unexpected ARM constantpool value type!!");
987 CPI = MCP->getConstantPoolIndex(NewCPV, MCPE.getAlignment());
988 MachineInstrBuilder MIB = BuildMI(MBB, I, Orig->getDebugLoc(), get(Opcode),
989 DestReg)
990 .addConstantPoolIndex(CPI).addImm(PCLabelId);
991 (*MIB).setMemRefs(Orig->memoperands_begin(), Orig->memoperands_end());
992 break;
993 }
994 }
995
996 MachineInstr *NewMI = prior(I);
997 NewMI->getOperand(0).setSubReg(SubIdx);
998}
999
Evan Chengd457e6e2009-11-07 04:04:34 +00001000bool ARMBaseInstrInfo::isIdentical(const MachineInstr *MI0,
1001 const MachineInstr *MI1,
1002 const MachineRegisterInfo *MRI) const {
1003 int Opcode = MI0->getOpcode();
Evan Cheng9b824252009-11-20 02:10:27 +00001004 if (Opcode == ARM::t2LDRpci ||
1005 Opcode == ARM::t2LDRpci_pic ||
1006 Opcode == ARM::tLDRpci ||
1007 Opcode == ARM::tLDRpci_pic) {
Evan Chengd457e6e2009-11-07 04:04:34 +00001008 if (MI1->getOpcode() != Opcode)
1009 return false;
1010 if (MI0->getNumOperands() != MI1->getNumOperands())
1011 return false;
1012
1013 const MachineOperand &MO0 = MI0->getOperand(1);
1014 const MachineOperand &MO1 = MI1->getOperand(1);
1015 if (MO0.getOffset() != MO1.getOffset())
1016 return false;
1017
1018 const MachineFunction *MF = MI0->getParent()->getParent();
1019 const MachineConstantPool *MCP = MF->getConstantPool();
1020 int CPI0 = MO0.getIndex();
1021 int CPI1 = MO1.getIndex();
1022 const MachineConstantPoolEntry &MCPE0 = MCP->getConstants()[CPI0];
1023 const MachineConstantPoolEntry &MCPE1 = MCP->getConstants()[CPI1];
1024 ARMConstantPoolValue *ACPV0 =
1025 static_cast<ARMConstantPoolValue*>(MCPE0.Val.MachineCPVal);
1026 ARMConstantPoolValue *ACPV1 =
1027 static_cast<ARMConstantPoolValue*>(MCPE1.Val.MachineCPVal);
1028 return ACPV0->hasSameValue(ACPV1);
1029 }
1030
1031 return TargetInstrInfoImpl::isIdentical(MI0, MI1, MRI);
1032}
1033
Bob Wilson834b08a2009-11-18 03:34:27 +00001034unsigned ARMBaseInstrInfo::TailDuplicationLimit(const MachineBasicBlock &MBB,
1035 unsigned DefaultLimit) const {
1036 // If the target processor can predict indirect branches, it is highly
1037 // desirable to duplicate them, since it can often make them predictable.
1038 if (!MBB.empty() && isIndirectBranchOpcode(MBB.back().getOpcode()) &&
1039 getSubtarget().hasBranchTargetBuffer())
1040 return DefaultLimit + 2;
1041 return DefaultLimit;
1042}
1043
Evan Cheng8fb90362009-08-08 03:20:32 +00001044/// getInstrPredicate - If instruction is predicated, returns its predicate
1045/// condition, otherwise returns AL. It also returns the condition code
1046/// register by reference.
Evan Cheng5adb66a2009-09-28 09:14:39 +00001047ARMCC::CondCodes
1048llvm::getInstrPredicate(const MachineInstr *MI, unsigned &PredReg) {
Evan Cheng8fb90362009-08-08 03:20:32 +00001049 int PIdx = MI->findFirstPredOperandIdx();
1050 if (PIdx == -1) {
1051 PredReg = 0;
1052 return ARMCC::AL;
1053 }
1054
1055 PredReg = MI->getOperand(PIdx+1).getReg();
1056 return (ARMCC::CondCodes)MI->getOperand(PIdx).getImm();
1057}
1058
1059
Evan Cheng6495f632009-07-28 05:48:47 +00001060int llvm::getMatchingCondBranchOpcode(int Opc) {
Evan Cheng5ca53a72009-07-27 18:20:05 +00001061 if (Opc == ARM::B)
1062 return ARM::Bcc;
1063 else if (Opc == ARM::tB)
1064 return ARM::tBcc;
1065 else if (Opc == ARM::t2B)
1066 return ARM::t2Bcc;
1067
1068 llvm_unreachable("Unknown unconditional branch opcode!");
1069 return 0;
1070}
1071
Evan Cheng6495f632009-07-28 05:48:47 +00001072
1073void llvm::emitARMRegPlusImmediate(MachineBasicBlock &MBB,
1074 MachineBasicBlock::iterator &MBBI, DebugLoc dl,
1075 unsigned DestReg, unsigned BaseReg, int NumBytes,
1076 ARMCC::CondCodes Pred, unsigned PredReg,
1077 const ARMBaseInstrInfo &TII) {
1078 bool isSub = NumBytes < 0;
1079 if (isSub) NumBytes = -NumBytes;
1080
1081 while (NumBytes) {
1082 unsigned RotAmt = ARM_AM::getSOImmValRotate(NumBytes);
1083 unsigned ThisVal = NumBytes & ARM_AM::rotr32(0xFF, RotAmt);
1084 assert(ThisVal && "Didn't extract field correctly");
1085
1086 // We will handle these bits from offset, clear them.
1087 NumBytes &= ~ThisVal;
1088
1089 assert(ARM_AM::getSOImmVal(ThisVal) != -1 && "Bit extraction didn't work?");
1090
1091 // Build the new ADD / SUB.
1092 unsigned Opc = isSub ? ARM::SUBri : ARM::ADDri;
1093 BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg)
1094 .addReg(BaseReg, RegState::Kill).addImm(ThisVal)
1095 .addImm((unsigned)Pred).addReg(PredReg).addReg(0);
1096 BaseReg = DestReg;
1097 }
1098}
1099
Evan Chengcdbb3f52009-08-27 01:23:50 +00001100bool llvm::rewriteARMFrameIndex(MachineInstr &MI, unsigned FrameRegIdx,
1101 unsigned FrameReg, int &Offset,
1102 const ARMBaseInstrInfo &TII) {
Evan Cheng6495f632009-07-28 05:48:47 +00001103 unsigned Opcode = MI.getOpcode();
1104 const TargetInstrDesc &Desc = MI.getDesc();
1105 unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask);
1106 bool isSub = false;
Jim Grosbach764ab522009-08-11 15:33:49 +00001107
Evan Cheng6495f632009-07-28 05:48:47 +00001108 // Memory operands in inline assembly always use AddrMode2.
1109 if (Opcode == ARM::INLINEASM)
1110 AddrMode = ARMII::AddrMode2;
Jim Grosbach764ab522009-08-11 15:33:49 +00001111
Evan Cheng6495f632009-07-28 05:48:47 +00001112 if (Opcode == ARM::ADDri) {
1113 Offset += MI.getOperand(FrameRegIdx+1).getImm();
1114 if (Offset == 0) {
1115 // Turn it into a move.
1116 MI.setDesc(TII.get(ARM::MOVr));
1117 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
1118 MI.RemoveOperand(FrameRegIdx+1);
Evan Chengcdbb3f52009-08-27 01:23:50 +00001119 Offset = 0;
1120 return true;
Evan Cheng6495f632009-07-28 05:48:47 +00001121 } else if (Offset < 0) {
1122 Offset = -Offset;
1123 isSub = true;
1124 MI.setDesc(TII.get(ARM::SUBri));
1125 }
1126
1127 // Common case: small offset, fits into instruction.
1128 if (ARM_AM::getSOImmVal(Offset) != -1) {
1129 // Replace the FrameIndex with sp / fp
1130 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
1131 MI.getOperand(FrameRegIdx+1).ChangeToImmediate(Offset);
Evan Chengcdbb3f52009-08-27 01:23:50 +00001132 Offset = 0;
1133 return true;
Evan Cheng6495f632009-07-28 05:48:47 +00001134 }
1135
1136 // Otherwise, pull as much of the immedidate into this ADDri/SUBri
1137 // as possible.
1138 unsigned RotAmt = ARM_AM::getSOImmValRotate(Offset);
1139 unsigned ThisImmVal = Offset & ARM_AM::rotr32(0xFF, RotAmt);
1140
1141 // We will handle these bits from offset, clear them.
1142 Offset &= ~ThisImmVal;
1143
1144 // Get the properly encoded SOImmVal field.
1145 assert(ARM_AM::getSOImmVal(ThisImmVal) != -1 &&
1146 "Bit extraction didn't work?");
1147 MI.getOperand(FrameRegIdx+1).ChangeToImmediate(ThisImmVal);
1148 } else {
1149 unsigned ImmIdx = 0;
1150 int InstrOffs = 0;
1151 unsigned NumBits = 0;
1152 unsigned Scale = 1;
1153 switch (AddrMode) {
1154 case ARMII::AddrMode2: {
1155 ImmIdx = FrameRegIdx+2;
1156 InstrOffs = ARM_AM::getAM2Offset(MI.getOperand(ImmIdx).getImm());
1157 if (ARM_AM::getAM2Op(MI.getOperand(ImmIdx).getImm()) == ARM_AM::sub)
1158 InstrOffs *= -1;
1159 NumBits = 12;
1160 break;
1161 }
1162 case ARMII::AddrMode3: {
1163 ImmIdx = FrameRegIdx+2;
1164 InstrOffs = ARM_AM::getAM3Offset(MI.getOperand(ImmIdx).getImm());
1165 if (ARM_AM::getAM3Op(MI.getOperand(ImmIdx).getImm()) == ARM_AM::sub)
1166 InstrOffs *= -1;
1167 NumBits = 8;
1168 break;
1169 }
Anton Korobeynikovbaf31082009-08-08 13:35:48 +00001170 case ARMII::AddrMode4:
Jim Grosbacha4432172009-11-15 21:45:34 +00001171 case ARMII::AddrMode6:
Evan Chengcdbb3f52009-08-27 01:23:50 +00001172 // Can't fold any offset even if it's zero.
1173 return false;
Evan Cheng6495f632009-07-28 05:48:47 +00001174 case ARMII::AddrMode5: {
1175 ImmIdx = FrameRegIdx+1;
1176 InstrOffs = ARM_AM::getAM5Offset(MI.getOperand(ImmIdx).getImm());
1177 if (ARM_AM::getAM5Op(MI.getOperand(ImmIdx).getImm()) == ARM_AM::sub)
1178 InstrOffs *= -1;
1179 NumBits = 8;
1180 Scale = 4;
1181 break;
1182 }
1183 default:
1184 llvm_unreachable("Unsupported addressing mode!");
1185 break;
1186 }
1187
1188 Offset += InstrOffs * Scale;
1189 assert((Offset & (Scale-1)) == 0 && "Can't encode this offset!");
1190 if (Offset < 0) {
1191 Offset = -Offset;
1192 isSub = true;
1193 }
1194
1195 // Attempt to fold address comp. if opcode has offset bits
1196 if (NumBits > 0) {
1197 // Common case: small offset, fits into instruction.
1198 MachineOperand &ImmOp = MI.getOperand(ImmIdx);
1199 int ImmedOffset = Offset / Scale;
1200 unsigned Mask = (1 << NumBits) - 1;
1201 if ((unsigned)Offset <= Mask * Scale) {
1202 // Replace the FrameIndex with sp
1203 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
1204 if (isSub)
1205 ImmedOffset |= 1 << NumBits;
1206 ImmOp.ChangeToImmediate(ImmedOffset);
Evan Chengcdbb3f52009-08-27 01:23:50 +00001207 Offset = 0;
1208 return true;
Evan Cheng6495f632009-07-28 05:48:47 +00001209 }
Jim Grosbach764ab522009-08-11 15:33:49 +00001210
Evan Cheng6495f632009-07-28 05:48:47 +00001211 // Otherwise, it didn't fit. Pull in what we can to simplify the immed.
1212 ImmedOffset = ImmedOffset & Mask;
1213 if (isSub)
1214 ImmedOffset |= 1 << NumBits;
1215 ImmOp.ChangeToImmediate(ImmedOffset);
1216 Offset &= ~(Mask*Scale);
1217 }
1218 }
1219
Evan Chengcdbb3f52009-08-27 01:23:50 +00001220 Offset = (isSub) ? -Offset : Offset;
1221 return Offset == 0;
Evan Cheng6495f632009-07-28 05:48:47 +00001222}