llvm.org GIT mirror llvm / bcd3a9c
Reapply r128585 without generating a lib depedency cycle. An updated log: - Implement asm parsing support for LDRT, LDRBT, STRT, STRBT and {STR,LDC}{2}_{PRE,POST} fixing the encoding wherever is possible. - Move all instructions which use am2offset without a pattern to use addrmode2. - Add a new encoding bit to describe the index mode used and teach printAddrMode2Operand to check by the addressing mode which index mode to print. - Testcases git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@128632 91177308-0d34-0410-b5e6-96231b3b80d8 Bruno Cardoso Lopes 9 years ago
10 changed file(s) with 362 addition(s) and 89 deletion(s). Raw diff Collapse all Expand all
407407 //
408408 // The first operand is always a Reg. The second operand is a reg if in
409409 // reg/reg form, otherwise it's reg#0. The third field encodes the operation
410 // in bit 12, the immediate in bits 0-11, and the shift op in 13-15.
410 // in bit 12, the immediate in bits 0-11, and the shift op in 13-15. The
411 // forth operand 16-17 encodes the index mode.
411412 //
412413 // If this addressing mode is a frame index (before prolog/epilog insertion
413414 // and code rewriting), this operand will have the form: FI#, reg0,
414415 // with no shift amount for the frame offset.
415416 //
416 static inline unsigned getAM2Opc(AddrOpc Opc, unsigned Imm12, ShiftOpc SO) {
417 static inline unsigned getAM2Opc(AddrOpc Opc, unsigned Imm12, ShiftOpc SO,
418 unsigned IdxMode = 0) {
417419 assert(Imm12 < (1 << 12) && "Imm too large!");
418420 bool isSub = Opc == sub;
419 return Imm12 | ((int)isSub << 12) | (SO << 13);
421 return Imm12 | ((int)isSub << 12) | (SO << 13) | (IdxMode << 16) ;
420422 }
421423 static inline unsigned getAM2Offset(unsigned AM2Opc) {
422424 return AM2Opc & ((1 << 12)-1);
425427 return ((AM2Opc >> 12) & 1) ? sub : add;
426428 }
427429 static inline ShiftOpc getAM2ShiftOpc(unsigned AM2Opc) {
428 return (ShiftOpc)(AM2Opc >> 13);
430 return (ShiftOpc)((AM2Opc >> 13) & 7);
431 }
432 static inline unsigned getAM2IdxMode(unsigned AM2Opc) {
433 return (AM2Opc >> 16);
429434 }
430435
431436
199199 }
200200
201201 namespace ARMII {
202
203 /// ARM Index Modes
204 enum IndexMode {
205 IndexModeNone = 0,
206 IndexModePre = 1,
207 IndexModePost = 2,
208 IndexModeUpd = 3
209 };
210
211 /// ARM Addressing Modes
212 enum AddrMode {
213 AddrModeNone = 0,
214 AddrMode1 = 1,
215 AddrMode2 = 2,
216 AddrMode3 = 3,
217 AddrMode4 = 4,
218 AddrMode5 = 5,
219 AddrMode6 = 6,
220 AddrModeT1_1 = 7,
221 AddrModeT1_2 = 8,
222 AddrModeT1_4 = 9,
223 AddrModeT1_s = 10, // i8 * 4 for pc and sp relative data
224 AddrModeT2_i12 = 11,
225 AddrModeT2_i8 = 12,
226 AddrModeT2_so = 13,
227 AddrModeT2_pc = 14, // +/- i12 for pc relative data
228 AddrModeT2_i8s4 = 15, // i8 * 4
229 AddrMode_i12 = 16
230 };
231
232 inline static const char *AddrModeToString(AddrMode addrmode) {
233 switch (addrmode) {
234 default: llvm_unreachable("Unknown memory operation");
235 case AddrModeNone: return "AddrModeNone";
236 case AddrMode1: return "AddrMode1";
237 case AddrMode2: return "AddrMode2";
238 case AddrMode3: return "AddrMode3";
239 case AddrMode4: return "AddrMode4";
240 case AddrMode5: return "AddrMode5";
241 case AddrMode6: return "AddrMode6";
242 case AddrModeT1_1: return "AddrModeT1_1";
243 case AddrModeT1_2: return "AddrModeT1_2";
244 case AddrModeT1_4: return "AddrModeT1_4";
245 case AddrModeT1_s: return "AddrModeT1_s";
246 case AddrModeT2_i12: return "AddrModeT2_i12";
247 case AddrModeT2_i8: return "AddrModeT2_i8";
248 case AddrModeT2_so: return "AddrModeT2_so";
249 case AddrModeT2_pc: return "AddrModeT2_pc";
250 case AddrModeT2_i8s4: return "AddrModeT2_i8s4";
251 case AddrMode_i12: return "AddrMode_i12";
252 }
253 }
254
202255 /// Target Operand Flag enum.
203256 enum TOF {
204257 //===------------------------------------------------------------------===//
3333
3434 //===------------------------------------------------------------------===//
3535 // This four-bit field describes the addressing mode used.
36
37 AddrModeMask = 0x1f,
38 AddrModeNone = 0,
39 AddrMode1 = 1,
40 AddrMode2 = 2,
41 AddrMode3 = 3,
42 AddrMode4 = 4,
43 AddrMode5 = 5,
44 AddrMode6 = 6,
45 AddrModeT1_1 = 7,
46 AddrModeT1_2 = 8,
47 AddrModeT1_4 = 9,
48 AddrModeT1_s = 10, // i8 * 4 for pc and sp relative data
49 AddrModeT2_i12 = 11,
50 AddrModeT2_i8 = 12,
51 AddrModeT2_so = 13,
52 AddrModeT2_pc = 14, // +/- i12 for pc relative data
53 AddrModeT2_i8s4 = 15, // i8 * 4
54 AddrMode_i12 = 16,
36 AddrModeMask = 0x1f, // The AddrMode enums are declared in ARMBaseInfo.h
5537
5638 // Size* - Flags to keep track of the size of an instruction.
5739 SizeShift = 5,
6345
6446 // IndexMode - Unindex, pre-indexed, or post-indexed are valid for load
6547 // and store ops only. Generic "updating" flag is used for ld/st multiple.
48 // The index mode enums are declared in ARMBaseInfo.h
6649 IndexModeShift = 8,
6750 IndexModeMask = 3 << IndexModeShift,
68 IndexModePre = 1,
69 IndexModePost = 2,
70 IndexModeUpd = 3,
7151
7252 //===------------------------------------------------------------------===//
7353 // Instruction encoding formats.
514514 : AI2ldstidx<0, isByte, isPre, oops, iops, im, f, itin, opc, asm, cstr,
515515 pattern> {
516516 // AM2 store w/ two operands: (GPR, am2offset)
517 // {17-14} Rn
517518 // {13} 1 == Rm, 0 == imm12
518519 // {12} isAdd
519520 // {11-0} imm12/Rm
520 bits<14> offset;
521 bits<4> Rn;
522 let Inst{25} = offset{13};
523 let Inst{23} = offset{12};
524 let Inst{19-16} = Rn;
525 let Inst{11-0} = offset{11-0};
521 bits<18> addr;
522 let Inst{25} = addr{13};
523 let Inst{23} = addr{12};
524 let Inst{19-16} = addr{17-14};
525 let Inst{11-0} = addr{11-0};
526526 }
527527
528528 // addrmode3 instructions
497497 let MIOperandInfo = (ops GPR:$base, GPR:$offsreg, i32imm:$offsimm);
498498 }
499499
500 def MemMode2AsmOperand : AsmOperandClass {
501 let Name = "MemMode2";
502 let SuperClasses = [];
503 let ParserMethod = "tryParseMemMode2Operand";
504 }
505
500506 // addrmode2 := reg +/- imm12
501507 // := reg +/- reg shop imm
502508 //
504510 ComplexPattern {
505511 let EncoderMethod = "getAddrMode2OpValue";
506512 let PrintMethod = "printAddrMode2Operand";
513 let ParserMatchClass = MemMode2AsmOperand;
507514 let MIOperandInfo = (ops GPR:$base, GPR:$offsreg, i32imm:$offsimm);
508515 }
509516
16551662 let Inst{23} = addr{12};
16561663 let Inst{19-16} = addr{17-14};
16571664 let Inst{11-0} = addr{11-0};
1665 let AsmMatchConverter = "CvtLdWriteBackRegAddrMode2";
16581666 }
16591667 def _POST : AI2ldstidx<1, isByte, 0, (outs GPR:$Rt, GPR:$Rn_wb),
1660 (ins GPR:$Rn, am2offset:$offset),
1661 IndexModePost, LdFrm, itin,
1662 opc, "\t$Rt, [$Rn], $offset", "$Rn = $Rn_wb", []> {
1668 (ins addrmode2:$addr), IndexModePost, LdFrm, itin,
1669 opc, "\t$Rt, $addr", "$addr.base = $Rn_wb", []> {
1670 // {17-14} Rn
16631671 // {13} 1 == Rm, 0 == imm12
16641672 // {12} isAdd
16651673 // {11-0} imm12/Rm
1666 bits<14> offset;
1667 bits<4> Rn;
1668 let Inst{25} = offset{13};
1669 let Inst{23} = offset{12};
1670 let Inst{19-16} = Rn;
1671 let Inst{11-0} = offset{11-0};
1674 bits<18> addr;
1675 let Inst{25} = addr{13};
1676 let Inst{23} = addr{12};
1677 let Inst{19-16} = addr{17-14};
1678 let Inst{11-0} = addr{11-0};
1679 let AsmMatchConverter = "CvtLdWriteBackRegAddrMode2";
16721680 }
16731681 }
16741682
17131721
17141722 // LDRT, LDRBT, LDRSBT, LDRHT, LDRSHT are for disassembly only.
17151723 let mayLoad = 1, neverHasSideEffects = 1 in {
1716 def LDRT : AI2ldstidx<1, 0, 0, (outs GPR:$dst, GPR:$base_wb),
1717 (ins GPR:$base, am2offset:$offset), IndexModePost,
1718 LdFrm, IIC_iLoad_ru,
1719 "ldrt", "\t$dst, [$base], $offset", "$base = $base_wb", []> {
1724 def LDRT : AI2ldstidx<1, 0, 0, (outs GPR:$Rt, GPR:$base_wb),
1725 (ins addrmode2:$addr), IndexModePost, LdFrm, IIC_iLoad_ru,
1726 "ldrt", "\t$Rt, $addr", "$addr.base = $base_wb", []> {
1727 // {17-14} Rn
1728 // {13} 1 == Rm, 0 == imm12
1729 // {12} isAdd
1730 // {11-0} imm12/Rm
1731 bits<18> addr;
1732 let Inst{25} = addr{13};
1733 let Inst{23} = addr{12};
17201734 let Inst{21} = 1; // overwrite
1721 }
1722 def LDRBT : AI2ldstidx<1, 1, 0, (outs GPR:$dst, GPR:$base_wb),
1723 (ins GPR:$base, am2offset:$offset), IndexModePost,
1724 LdFrm, IIC_iLoad_bh_ru,
1725 "ldrbt", "\t$dst, [$base], $offset", "$base = $base_wb", []> {
1735 let Inst{19-16} = addr{17-14};
1736 let Inst{11-0} = addr{11-0};
1737 let AsmMatchConverter = "CvtLdWriteBackRegAddrMode2";
1738 }
1739 def LDRBT : AI2ldstidx<1, 1, 0, (outs GPR:$Rt, GPR:$base_wb),
1740 (ins addrmode2:$addr), IndexModePost, LdFrm, IIC_iLoad_bh_ru,
1741 "ldrbt", "\t$Rt, $addr", "$addr.base = $base_wb", []> {
1742 // {17-14} Rn
1743 // {13} 1 == Rm, 0 == imm12
1744 // {12} isAdd
1745 // {11-0} imm12/Rm
1746 bits<18> addr;
1747 let Inst{25} = addr{13};
1748 let Inst{23} = addr{12};
17261749 let Inst{21} = 1; // overwrite
1750 let Inst{19-16} = addr{17-14};
1751 let Inst{11-0} = addr{11-0};
1752 let AsmMatchConverter = "CvtLdWriteBackRegAddrMode2";
17271753 }
17281754 def LDRSBT : AI3ldstidx<0b1101, 1, 1, 0, (outs GPR:$dst, GPR:$base_wb),
17291755 (ins GPR:$base, am3offset:$offset), IndexModePost,
18171843
18181844 // STRT, STRBT, and STRHT are for disassembly only.
18191845
1820 def STRT : AI2stridx<0, 0, (outs GPR:$Rn_wb),
1821 (ins GPR:$Rt, GPR:$Rn,am2offset:$offset),
1846 def STRT : AI2stridx<0, 0, (outs GPR:$Rn_wb), (ins GPR:$Rt, addrmode2:$addr),
18221847 IndexModePost, StFrm, IIC_iStore_ru,
1823 "strt", "\t$Rt, [$Rn], $offset", "$Rn = $Rn_wb",
1848 "strt", "\t$Rt, $addr", "$addr.base = $Rn_wb",
18241849 [/* For disassembly only; pattern left blank */]> {
18251850 let Inst{21} = 1; // overwrite
1826 }
1827
1828 def STRBT : AI2stridx<1, 0, (outs GPR:$Rn_wb),
1829 (ins GPR:$Rt, GPR:$Rn, am2offset:$offset),
1851 let AsmMatchConverter = "CvtStWriteBackRegAddrMode2";
1852 }
1853
1854 def STRBT : AI2stridx<1, 0, (outs GPR:$Rn_wb), (ins GPR:$Rt, addrmode2:$addr),
18301855 IndexModePost, StFrm, IIC_iStore_bh_ru,
1831 "strbt", "\t$Rt, [$Rn], $offset", "$Rn = $Rn_wb",
1856 "strbt", "\t$Rt, $addr", "$addr.base = $Rn_wb",
18321857 [/* For disassembly only; pattern left blank */]> {
18331858 let Inst{21} = 1; // overwrite
1859 let AsmMatchConverter = "CvtStWriteBackRegAddrMode2";
18341860 }
18351861
18361862 def STRHT: AI3sthpo<(outs GPR:$base_wb),
33903416 let Inst{23-20} = opc1;
33913417 }
33923418
3393 class ACI
3394 : I,
3419 class ACI,
3420 IndexMode im = IndexModeNone>
3421 : I
33953422 opc, asm, "", [/* For disassembly only; pattern left blank */]> {
33963423 let Inst{27-25} = 0b110;
33973424 }
34103437
34113438 def _PRE : ACI<(outs),
34123439 (ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr),
3413 opc, "\tp$cop, cr$CRd, $addr!"> {
3440 opc, "\tp$cop, cr$CRd, $addr!", IndexModePre> {
34143441 let Inst{31-28} = op31_28;
34153442 let Inst{24} = 1; // P = 1
34163443 let Inst{21} = 1; // W = 1
34193446 }
34203447
34213448 def _POST : ACI<(outs),
3422 (ins nohash_imm:$cop, nohash_imm:$CRd, GPR:$base, am2offset:$offset),
3423 opc, "\tp$cop, cr$CRd, [$base], $offset"> {
3449 (ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr),
3450 opc, "\tp$cop, cr$CRd, $addr", IndexModePost> {
34243451 let Inst{31-28} = op31_28;
34253452 let Inst{24} = 0; // P = 0
34263453 let Inst{21} = 1; // W = 1
34513478
34523479 def L_PRE : ACI<(outs),
34533480 (ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr),
3454 !strconcat(opc, "l"), "\tp$cop, cr$CRd, $addr!"> {
3481 !strconcat(opc, "l"), "\tp$cop, cr$CRd, $addr!", IndexModePre> {
34553482 let Inst{31-28} = op31_28;
34563483 let Inst{24} = 1; // P = 1
34573484 let Inst{21} = 1; // W = 1
34603487 }
34613488
34623489 def L_POST : ACI<(outs),
3463 (ins nohash_imm:$cop, nohash_imm:$CRd, GPR:$base, am2offset:$offset),
3464 !strconcat(opc, "l"), "\tp$cop, cr$CRd, [$base], $offset"> {
3490 (ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr),
3491 !strconcat(opc, "l"), "\tp$cop, cr$CRd, $addr", IndexModePost> {
34653492 let Inst{31-28} = op31_28;
34663493 let Inst{24} = 0; // P = 0
34673494 let Inst{21} = 1; // W = 1
4747 bool TryParseRegisterWithWriteBack(SmallVectorImpl &);
4848 bool TryParseShiftRegister(SmallVectorImpl &);
4949 bool ParseRegisterList(SmallVectorImpl &);
50 bool ParseMemory(SmallVectorImpl &);
50 bool ParseMemory(SmallVectorImpl &,
51 ARMII::AddrMode AddrMode);
5152 bool ParseOperand(SmallVectorImpl &, StringRef Mnemonic);
5253 bool ParsePrefix(ARMMCExpr::VariantKind &RefKind);
5354 const MCExpr *ApplyPrefixToExpr(const MCExpr *E,
9495 SmallVectorImpl&);
9596 OperandMatchResultTy tryParseMSRMaskOperand(
9697 SmallVectorImpl&);
98 OperandMatchResultTy tryParseMemMode2Operand(
99 SmallVectorImpl&);
100
101 // Asm Match Converter Methods
102 bool CvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
103 const SmallVectorImpl &);
104 bool CvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
105 const SmallVectorImpl &);
97106
98107 public:
99108 ARMAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &_TM)
171180
172181 /// Combined record for all forms of ARM address expressions.
173182 struct {
183 ARMII::AddrMode AddrMode;
174184 unsigned BaseRegNum;
175185 union {
176186 unsigned RegNum; ///< Offset register num, when OffsetIsReg.
292302
293303 /// @name Memory Operand Accessors
294304 /// @{
295
305 ARMII::AddrMode getMemAddrMode() const {
306 return Mem.AddrMode;
307 }
296308 unsigned getMemBaseRegNum() const {
297309 return Mem.BaseRegNum;
298310 }
337349 bool isMemBarrierOpt() const { return Kind == MemBarrierOpt; }
338350 bool isMemory() const { return Kind == Memory; }
339351 bool isShifter() const { return Kind == Shifter; }
352 bool isMemMode2() const {
353 if (getMemAddrMode() != ARMII::AddrMode2)
354 return false;
355
356 if (getMemOffsetIsReg())
357 return true;
358
359 if (getMemNegative() &&
360 !(getMemPostindexed() || getMemPreindexed()))
361 return false;
362
363 const MCConstantExpr *CE = dyn_cast(getMemOffset());
364 if (!CE) return false;
365 int64_t Value = CE->getValue();
366
367 // The offset must be in the range 0-4095 (imm12).
368 if (Value > 4095 || Value < -4095)
369 return false;
370
371 return true;
372 }
340373 bool isMemMode5() const {
341374 if (!isMemory() || getMemOffsetIsReg() || getMemWriteback() ||
342375 getMemNegative())
462495 (void)CE;
463496 assert((CE || CE->getValue() == 0) &&
464497 "No offset operand support in mode 7");
498 }
499
500 void addMemMode2Operands(MCInst &Inst, unsigned N) const {
501 assert(isMemMode2() && "Invalid mode or number of operands!");
502 Inst.addOperand(MCOperand::CreateReg(getMemBaseRegNum()));
503 unsigned IdxMode = (getMemPreindexed() | getMemPostindexed() << 1);
504
505 if (getMemOffsetIsReg()) {
506 Inst.addOperand(MCOperand::CreateReg(getMemOffsetRegNum()));
507
508 ARM_AM::AddrOpc AMOpc = getMemNegative() ? ARM_AM::sub : ARM_AM::add;
509 ARM_AM::ShiftOpc ShOpc = ARM_AM::no_shift;
510 int64_t ShiftAmount = 0;
511
512 if (getMemOffsetRegShifted()) {
513 ShOpc = getMemShiftType();
514 const MCConstantExpr *CE =
515 dyn_cast(getMemShiftAmount());
516 ShiftAmount = CE->getValue();
517 }
518
519 Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM2Opc(AMOpc, ShiftAmount,
520 ShOpc, IdxMode)));
521 return;
522 }
523
524 // Create a operand placeholder to always yield the same number of operands.
525 Inst.addOperand(MCOperand::CreateReg(0));
526
527 // FIXME: #-0 is encoded differently than #0. Does the parser preserve
528 // the difference?
529 const MCConstantExpr *CE = dyn_cast(getMemOffset());
530 assert(CE && "Non-constant mode 2 offset operand!");
531 int64_t Offset = CE->getValue();
532
533 if (Offset >= 0)
534 Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM2Opc(ARM_AM::add,
535 Offset, ARM_AM::no_shift, IdxMode)));
536 else
537 Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM2Opc(ARM_AM::sub,
538 -Offset, ARM_AM::no_shift, IdxMode)));
465539 }
466540
467541 void addMemMode5Operands(MCInst &Inst, unsigned N) const {
598672 return Op;
599673 }
600674
601 static ARMOperand *CreateMem(unsigned BaseRegNum, bool OffsetIsReg,
602 const MCExpr *Offset, int OffsetRegNum,
603 bool OffsetRegShifted,
675 static ARMOperand *CreateMem(ARMII::AddrMode AddrMode, unsigned BaseRegNum,
676 bool OffsetIsReg, const MCExpr *Offset,
677 int OffsetRegNum, bool OffsetRegShifted,
604678 enum ARM_AM::ShiftOpc ShiftType,
605679 const MCExpr *ShiftAmount, bool Preindexed,
606680 bool Postindexed, bool Negative, bool Writeback,
617691 "Cannot have expression offset and register offset!");
618692
619693 ARMOperand *Op = new ARMOperand(Memory);
694 Op->Mem.AddrMode = AddrMode;
620695 Op->Mem.BaseRegNum = BaseRegNum;
621696 Op->Mem.OffsetIsReg = OffsetIsReg;
622697 if (OffsetIsReg)
688763 break;
689764 case Memory:
690765 OS << "
691 << "base:" << getMemBaseRegNum();
766 << "am:" << ARMII::AddrModeToString(getMemAddrMode())
767 << " base:" << getMemBaseRegNum();
692768 if (getMemOffsetIsReg()) {
693769 OS << " offset:
694770 if (getMemOffsetRegShifted()) {
11311207 return MatchOperand_Success;
11321208 }
11331209
1210 /// tryParseMemMode2Operand - Try to parse memory addressing mode 2 operand.
1211 ARMAsmParser::OperandMatchResultTy ARMAsmParser::
1212 tryParseMemMode2Operand(SmallVectorImpl &Operands) {
1213 SMLoc S = Parser.getTok().getLoc();
1214 const AsmToken &Tok = Parser.getTok();
1215 assert(Tok.is(AsmToken::LBrac) && "Token is not a \"[\"");
1216
1217 if (ParseMemory(Operands, ARMII::AddrMode2))
1218 return MatchOperand_NoMatch;
1219
1220 return MatchOperand_Success;
1221 }
1222
1223 /// CvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
1224 /// Needed here because the Asm Gen Matcher can't handle properly tied operands
1225 /// when they refer multiple MIOperands inside a single one.
1226 bool ARMAsmParser::
1227 CvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
1228 const SmallVectorImpl &Operands) {
1229 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
1230
1231 // Create a writeback register dummy placeholder.
1232 Inst.addOperand(MCOperand::CreateImm(0));
1233
1234 ((ARMOperand*)Operands[3])->addMemMode2Operands(Inst, 3);
1235 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
1236 return true;
1237 }
1238
1239 /// CvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
1240 /// Needed here because the Asm Gen Matcher can't handle properly tied operands
1241 /// when they refer multiple MIOperands inside a single one.
1242 bool ARMAsmParser::
1243 CvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
1244 const SmallVectorImpl &Operands) {
1245 // Create a writeback register dummy placeholder.
1246 Inst.addOperand(MCOperand::CreateImm(0));
1247 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
1248 ((ARMOperand*)Operands[3])->addMemMode2Operands(Inst, 3);
1249 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
1250 return true;
1251 }
1252
11341253 /// Parse an ARM memory expression, return false if successful else return true
11351254 /// or an error. The first token must be a '[' when called.
11361255 ///
11371256 /// TODO Only preindexing and postindexing addressing are started, unindexed
11381257 /// with option, etc are still to do.
11391258 bool ARMAsmParser::
1140 ParseMemory(SmallVectorImpl &Operands) {
1259 ParseMemory(SmallVectorImpl &Operands,
1260 ARMII::AddrMode AddrMode = ARMII::AddrModeNone) {
11411261 SMLoc S, E;
11421262 assert(Parser.getTok().is(AsmToken::LBrac) &&
11431263 "Token is not a Left Bracket");
11951315 ExclaimTok.getLoc());
11961316 Writeback = true;
11971317 Parser.Lex(); // Eat exclaim token
1318 } else { // In addressing mode 2, pre-indexed mode always end with "!"
1319 if (AddrMode == ARMII::AddrMode2)
1320 Preindexed = false;
11981321 }
11991322 } else {
12001323 // The "[Rn" we have so far was not followed by a comma.
12301353 Offset = MCConstantExpr::Create(0, getContext());
12311354 }
12321355
1233 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, OffsetIsReg, Offset,
1234 OffsetRegNum, OffsetRegShifted,
1235 ShiftType, ShiftAmount, Preindexed,
1236 Postindexed, Negative, Writeback,
1237 S, E));
1356 Operands.push_back(ARMOperand::CreateMem(AddrMode, BaseRegNum, OffsetIsReg,
1357 Offset, OffsetRegNum, OffsetRegShifted,
1358 ShiftType, ShiftAmount, Preindexed,
1359 Postindexed, Negative, Writeback, S, E));
12381360 if (WBOp)
12391361 Operands.push_back(WBOp);
12401362
642642 if (PW) {
643643 MI.addOperand(MCOperand::CreateReg(0));
644644 ARM_AM::AddrOpc AddrOpcode = getUBit(insn) ? ARM_AM::add : ARM_AM::sub;
645 const TargetInstrDesc &TID = ARMInsts[Opcode];
646 unsigned IndexMode =
647 (TID.TSFlags & ARMII::IndexModeMask) >> ARMII::IndexModeShift;
645648 unsigned Offset = ARM_AM::getAM2Opc(AddrOpcode, slice(insn, 7, 0) << 2,
646 ARM_AM::no_shift);
649 ARM_AM::no_shift, IndexMode);
647650 MI.addOperand(MCOperand::CreateImm(Offset));
648651 OpIdx = 5;
649652 } else {
10721075 return false;
10731076
10741077 ARM_AM::AddrOpc AddrOpcode = getUBit(insn) ? ARM_AM::add : ARM_AM::sub;
1078 unsigned IndexMode =
1079 (TID.TSFlags & ARMII::IndexModeMask) >> ARMII::IndexModeShift;
10751080 if (getIBit(insn) == 0) {
10761081 // For pre- and post-indexed case, add a reg0 operand (Addressing Mode #2).
10771082 // Otherwise, skip the reg operand since for addrmode_imm12, Rn has already
10831088
10841089 // Disassemble the 12-bit immediate offset.
10851090 unsigned Imm12 = slice(insn, 11, 0);
1086 unsigned Offset = ARM_AM::getAM2Opc(AddrOpcode, Imm12, ARM_AM::no_shift);
1091 unsigned Offset = ARM_AM::getAM2Opc(AddrOpcode, Imm12, ARM_AM::no_shift,
1092 IndexMode);
10871093 MI.addOperand(MCOperand::CreateImm(Offset));
10881094 OpIdx += 1;
10891095 } else {
10981104 // A8.4.1. Possible rrx or shift amount of 32...
10991105 getImmShiftSE(ShOp, ShImm);
11001106 MI.addOperand(MCOperand::CreateImm(
1101 ARM_AM::getAM2Opc(AddrOpcode, ShImm, ShOp)));
1107 ARM_AM::getAM2Opc(AddrOpcode, ShImm, ShOp, IndexMode)));
11021108 OpIdx += 2;
11031109 }
11041110
180180 }
181181 }
182182
183
184 void ARMInstPrinter::printAddrMode2Operand(const MCInst *MI, unsigned Op,
185 raw_ostream &O) {
183 void ARMInstPrinter::printAM2PreOrOffsetIndexOp(const MCInst *MI, unsigned Op,
184 raw_ostream &O) {
186185 const MCOperand &MO1 = MI->getOperand(Op);
187186 const MCOperand &MO2 = MI->getOperand(Op+1);
188187 const MCOperand &MO3 = MI->getOperand(Op+2);
189
190 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
191 printOperand(MI, Op, O);
192 return;
193 }
194188
195189 O << "[" << getRegisterName(MO1.getReg());
196190
212206 << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO3.getImm()))
213207 << " #" << ShImm;
214208 O << "]";
209 }
210
211 void ARMInstPrinter::printAM2PostIndexOp(const MCInst *MI, unsigned Op,
212 raw_ostream &O) {
213 const MCOperand &MO1 = MI->getOperand(Op);
214 const MCOperand &MO2 = MI->getOperand(Op+1);
215 const MCOperand &MO3 = MI->getOperand(Op+2);
216
217 O << "[" << getRegisterName(MO1.getReg()) << "], ";
218
219 if (!MO2.getReg()) {
220 unsigned ImmOffs = ARM_AM::getAM2Offset(MO3.getImm());
221 O << '#'
222 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
223 << ImmOffs;
224 return;
225 }
226
227 O << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
228 << getRegisterName(MO2.getReg());
229
230 if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm()))
231 O << ", "
232 << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO3.getImm()))
233 << " #" << ShImm;
234 }
235
236 void ARMInstPrinter::printAddrMode2Operand(const MCInst *MI, unsigned Op,
237 raw_ostream &O) {
238 const MCOperand &MO1 = MI->getOperand(Op);
239
240 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
241 printOperand(MI, Op, O);
242 return;
243 }
244
245 const MCOperand &MO3 = MI->getOperand(Op+2);
246 unsigned IdxMode = ARM_AM::getAM2IdxMode(MO3.getImm());
247
248 if (IdxMode == ARMII::IndexModePost) {
249 printAM2PostIndexOp(MI, Op, O);
250 return;
251 }
252 printAM2PreOrOffsetIndexOp(MI, Op, O);
215253 }
216254
217255 void ARMInstPrinter::printAddrMode2OffsetOperand(const MCInst *MI,
4141 void printSOImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
4242
4343 void printSORegOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
44
4445 void printAddrMode2Operand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
46 void printAM2PostIndexOp(const MCInst *MI, unsigned OpNum, raw_ostream &O);
47 void printAM2PreOrOffsetIndexOp(const MCInst *MI, unsigned OpNum,
48 raw_ostream &O);
4549 void printAddrMode2OffsetOperand(const MCInst *MI, unsigned OpNum,
4650 raw_ostream &O);
4751 void printAddrMode3Operand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
0 @ RUN: llvm-mc -mcpu=cortex-a8 -triple arm-unknown-unknown -show-encoding %s | FileCheck %s
1
2 @ Post-indexed
3 @ CHECK: ldrt r1, [r0], r2 @ encoding: [0x02,0x10,0xb0,0xe6]
4 @ CHECK: ldrt r1, [r0], r2, lsr #3 @ encoding: [0xa2,0x11,0xb0,0xe6]
5 @ CHECK: ldrt r1, [r0], #4 @ encoding: [0x04,0x10,0xb0,0xe4]
6 @ CHECK: ldrbt r1, [r0], r2 @ encoding: [0x02,0x10,0xf0,0xe6]
7 @ CHECK: ldrbt r1, [r0], r2, lsr #3 @ encoding: [0xa2,0x11,0xf0,0xe6]
8 @ CHECK: ldrbt r1, [r0], #4 @ encoding: [0x04,0x10,0xf0,0xe4]
9 @ CHECK: strt r1, [r0], r2 @ encoding: [0x02,0x10,0xa0,0xe6]
10 @ CHECK: strt r1, [r0], r2, lsr #3 @ encoding: [0xa2,0x11,0xa0,0xe6]
11 @ CHECK: strt r1, [r0], #4 @ encoding: [0x04,0x10,0xa0,0xe4]
12 @ CHECK: strbt r1, [r0], r2 @ encoding: [0x02,0x10,0xe0,0xe6]
13 @ CHECK: strbt r1, [r0], r2, lsr #3 @ encoding: [0xa2,0x11,0xe0,0xe6]
14 @ CHECK: strbt r1, [r0], #4 @ encoding: [0x04,0x10,0xe0,0xe4]
15 @ CHECK: ldr r1, [r0], r2, lsr #3 @ encoding: [0xa2,0x11,0x90,0xe6]
16 @ CHECK: ldrb r1, [r0], r2, lsr #3 @ encoding: [0xa2,0x11,0xd0,0xe6]
17 ldrt r1, [r0], r2
18 ldrt r1, [r0], r2, lsr #3
19 ldrt r1, [r0], #4
20 ldrbt r1, [r0], r2
21 ldrbt r1, [r0], r2, lsr #3
22 ldrbt r1, [r0], #4
23 strt r1, [r0], r2
24 strt r1, [r0], r2, lsr #3
25 strt r1, [r0], #4
26 strbt r1, [r0], r2
27 strbt r1, [r0], r2, lsr #3
28 strbt r1, [r0], #4
29 ldr r1, [r0], r2, lsr #3
30 ldrb r1, [r0], r2, lsr #3
31
32 @ Pre-indexed
33 @ CHECK: ldr r1, [r0, r2, lsr #3]! @ encoding: [0xa2,0x11,0xb0,0xe7]
34 @ CHECK: ldrb r1, [r0, r2, lsr #3]! @ encoding: [0xa2,0x11,0xf0,0xe7]
35 ldr r1, [r0, r2, lsr #3]!
36 ldrb r1, [r0, r2, lsr #3]!
37