llvm.org GIT mirror llvm / 0082830
Add support to the ARM asm parser for the register-shifted-register forms of basic instructions like ADD. More work left to be done to support other instances of shifter ops in the ISA. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@127917 91177308-0d34-0410-b5e6-96231b3b80d8 Owen Anderson 9 years ago
3 changed file(s) with 96 addition(s) and 26 deletion(s). Raw diff Collapse all Expand all
380380 let EncoderMethod = "getRotImmOpValue";
381381 }
382382
383 def ShifterAsmOperand : AsmOperandClass {
384 let Name = "Shifter";
385 let SuperClasses = [];
386 }
387
383388 // shift_imm: An integer that encodes a shift amount and the type of shift
384389 // (currently either asr or lsl) using the same encoding used for the
385390 // immediates in so_reg operands.
386391 def shift_imm : Operand {
387392 let PrintMethod = "printShiftImmOperand";
393 let ParserMatchClass = ShifterAsmOperand;
388394 }
389395
390396 // shifter_operand operands: so_reg and so_imm.
393399 [shl,srl,sra,rotr]> {
394400 let EncoderMethod = "getSORegOpValue";
395401 let PrintMethod = "printSORegOperand";
396 let MIOperandInfo = (ops GPR, GPR, i32imm);
402 let MIOperandInfo = (ops GPR, GPR, shift_imm);
397403 }
398404 def shift_so_reg : Operand, // reg reg imm
399405 ComplexPattern
400406 [shl,srl,sra,rotr]> {
401407 let EncoderMethod = "getSORegOpValue";
402408 let PrintMethod = "printSORegOperand";
403 let MIOperandInfo = (ops GPR, GPR, i32imm);
409 let MIOperandInfo = (ops GPR, GPR, shift_imm);
404410 }
405411
406412 // so_imm - Match a 32-bit shifter_operand immediate operand, which is an
2828 #include "llvm/ADT/Twine.h"
2929 using namespace llvm;
3030
31 /// Shift types used for register controlled shifts in ARM memory addressing.
32 enum ShiftType {
33 Lsl,
34 Lsr,
35 Asr,
36 Ror,
37 Rrx
38 };
39
4031 namespace {
4132
4233 class ARMOperand;
5445 int TryParseRegister();
5546 virtual bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
5647 bool TryParseRegisterWithWriteBack(SmallVectorImpl &);
48 bool TryParseShiftRegister(SmallVectorImpl &);
5749 bool ParseRegisterList(SmallVectorImpl &);
5850 bool ParseMemory(SmallVectorImpl &);
5951 bool ParseOperand(SmallVectorImpl &, StringRef Mnemonic);
6456
6557 bool ParseMemoryOffsetReg(bool &Negative,
6658 bool &OffsetRegShifted,
67 enum ShiftType &ShiftType,
59 enum ARM_AM::ShiftOpc &ShiftType,
6860 const MCExpr *&ShiftAmount,
6961 const MCExpr *&Offset,
7062 bool &OffsetIsReg,
7163 int &OffsetRegNum,
7264 SMLoc &E);
73 bool ParseShift(enum ShiftType &St, const MCExpr *&ShiftAmount, SMLoc &E);
65 bool ParseShift(enum ARM_AM::ShiftOpc &St,
66 const MCExpr *&ShiftAmount, SMLoc &E);
7467 bool ParseDirectiveWord(unsigned Size, SMLoc L);
7568 bool ParseDirectiveThumb(SMLoc L);
7669 bool ParseDirectiveThumbFunc(SMLoc L);
135128 RegisterList,
136129 DPRRegisterList,
137130 SPRRegisterList,
131 Shifter,
138132 Token
139133 } Kind;
140134
183177 const MCExpr *Value; ///< Offset value, when !OffsetIsReg.
184178 } Offset;
185179 const MCExpr *ShiftAmount; // used when OffsetRegShifted is true
186 enum ShiftType ShiftType; // used when OffsetRegShifted is true
180 enum ARM_AM::ShiftOpc ShiftType; // used when OffsetRegShifted is true
187181 unsigned OffsetRegShifted : 1; // only used when OffsetIsReg is true
188182 unsigned Preindexed : 1;
189183 unsigned Postindexed : 1;
191185 unsigned Negative : 1; // only used when OffsetIsReg is true
192186 unsigned Writeback : 1;
193187 } Mem;
188
189 struct {
190 ARM_AM::ShiftOpc ShiftTy;
191 unsigned RegNum;
192 } Shift;
194193 };
195194
196195 ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
233232 break;
234233 case ProcIFlags:
235234 IFlags = o.IFlags;
235 break;
236 case Shifter:
237 Shift = o.Shift;
238 break;
236239 }
237240 }
238241
309312 assert(Mem.OffsetIsReg && Mem.OffsetRegShifted && "Invalid access!");
310313 return Mem.ShiftAmount;
311314 }
312 enum ShiftType getMemShiftType() const {
315 enum ARM_AM::ShiftOpc getMemShiftType() const {
313316 assert(Mem.OffsetIsReg && Mem.OffsetRegShifted && "Invalid access!");
314317 return Mem.ShiftType;
315318 }
333336 bool isToken() const { return Kind == Token; }
334337 bool isMemBarrierOpt() const { return Kind == MemBarrierOpt; }
335338 bool isMemory() const { return Kind == Memory; }
339 bool isShifter() const { return Kind == Shifter; }
336340 bool isMemMode5() const {
337341 if (!isMemory() || getMemOffsetIsReg() || getMemWriteback() ||
338342 getMemNegative())
399403 void addRegOperands(MCInst &Inst, unsigned N) const {
400404 assert(N == 1 && "Invalid number of operands!");
401405 Inst.addOperand(MCOperand::CreateReg(getReg()));
406 }
407
408 void addShifterOperands(MCInst &Inst, unsigned N) const {
409 assert(N == 1 && "Invalid number of operands!");
410 Inst.addOperand(MCOperand::CreateImm(
411 ARM_AM::getSORegOpc(Shift.ShiftTy, 0)));
402412 }
403413
404414 void addRegListOperands(MCInst &Inst, unsigned N) const {
524534 return Op;
525535 }
526536
537 static ARMOperand *CreateShifter(ARM_AM::ShiftOpc ShTy,
538 SMLoc S, SMLoc E) {
539 ARMOperand *Op = new ARMOperand(Shifter);
540 Op->Shift.ShiftTy = ShTy;
541 Op->StartLoc = S;
542 Op->EndLoc = E;
543 return Op;
544 }
545
527546 static ARMOperand *
528547 CreateRegList(const SmallVectorImpl > &Regs,
529548 SMLoc StartLoc, SMLoc EndLoc) {
554573
555574 static ARMOperand *CreateMem(unsigned BaseRegNum, bool OffsetIsReg,
556575 const MCExpr *Offset, int OffsetRegNum,
557 bool OffsetRegShifted, enum ShiftType ShiftType,
576 bool OffsetRegShifted,
577 enum ARM_AM::ShiftOpc ShiftType,
558578 const MCExpr *ShiftAmount, bool Preindexed,
559579 bool Postindexed, bool Negative, bool Writeback,
560580 SMLoc S, SMLoc E) {
675695 case Register:
676696 OS << "";
677697 break;
698 case Shifter:
699 OS << "";
700 break;
678701 case RegisterList:
679702 case DPRRegisterList:
680703 case SPRRegisterList: {
736759 Parser.Lex(); // Eat identifier token.
737760 return RegNum;
738761 }
762
763 /// Try to parse a register name. The token must be an Identifier when called,
764 /// and if it is a register name the token is eaten and the register number is
765 /// returned. Otherwise return -1.
766 ///
767 bool ARMAsmParser::TryParseShiftRegister(
768 SmallVectorImpl &Operands) {
769 SMLoc S = Parser.getTok().getLoc();
770 const AsmToken &Tok = Parser.getTok();
771 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
772
773 std::string upperCase = Tok.getString().str();
774 std::string lowerCase = LowercaseString(upperCase);
775 ARM_AM::ShiftOpc ShiftTy = StringSwitch(lowerCase)
776 .Case("lsl", ARM_AM::lsl)
777 .Case("lsr", ARM_AM::lsr)
778 .Case("asr", ARM_AM::asr)
779 .Case("ror", ARM_AM::ror)
780 .Case("rrx", ARM_AM::rrx)
781 .Default(ARM_AM::no_shift);
782
783 if (ShiftTy == ARM_AM::no_shift)
784 return true;
785
786 Parser.Lex(); // Eat shift-type operand;
787 int RegNum = TryParseRegister();
788 if (RegNum == -1)
789 return Error(Parser.getTok().getLoc(), "register expected");
790
791 Operands.push_back(ARMOperand::CreateReg(RegNum,S, Parser.getTok().getLoc()));
792 Operands.push_back(ARMOperand::CreateShifter(ShiftTy,
793 S, Parser.getTok().getLoc()));
794
795 return false;
796 }
797
739798
740799 /// Try to parse a register name. The token must be an Identifier when called.
741800 /// If it's a register, an AsmOperand is created. Another AsmOperand is created
10821141 ARMOperand *WBOp = 0;
10831142 int OffsetRegNum = -1;
10841143 bool OffsetRegShifted = false;
1085 enum ShiftType ShiftType = Lsl;
1144 enum ARM_AM::ShiftOpc ShiftType = ARM_AM::lsl;
10861145 const MCExpr *ShiftAmount = 0;
10871146 const MCExpr *Offset = 0;
10881147
11641223 /// we return false on success or an error otherwise.
11651224 bool ARMAsmParser::ParseMemoryOffsetReg(bool &Negative,
11661225 bool &OffsetRegShifted,
1167 enum ShiftType &ShiftType,
1226 enum ARM_AM::ShiftOpc &ShiftType,
11681227 const MCExpr *&ShiftAmount,
11691228 const MCExpr *&Offset,
11701229 bool &OffsetIsReg,
12251284 /// ( lsl | lsr | asr | ror ) , # shift_amount
12261285 /// rrx
12271286 /// and returns true if it parses a shift otherwise it returns false.
1228 bool ARMAsmParser::ParseShift(ShiftType &St, const MCExpr *&ShiftAmount,
1229 SMLoc &E) {
1287 bool ARMAsmParser::ParseShift(ARM_AM::ShiftOpc &St,
1288 const MCExpr *&ShiftAmount, SMLoc &E) {
12301289 const AsmToken &Tok = Parser.getTok();
12311290 if (Tok.isNot(AsmToken::Identifier))
12321291 return true;
12331292 StringRef ShiftName = Tok.getString();
12341293 if (ShiftName == "lsl" || ShiftName == "LSL")
1235 St = Lsl;
1294 St = ARM_AM::lsl;
12361295 else if (ShiftName == "lsr" || ShiftName == "LSR")
1237 St = Lsr;
1296 St = ARM_AM::lsr;
12381297 else if (ShiftName == "asr" || ShiftName == "ASR")
1239 St = Asr;
1298 St = ARM_AM::asr;
12401299 else if (ShiftName == "ror" || ShiftName == "ROR")
1241 St = Ror;
1300 St = ARM_AM::ror;
12421301 else if (ShiftName == "rrx" || ShiftName == "RRX")
1243 St = Rrx;
1302 St = ARM_AM::rrx;
12441303 else
12451304 return true;
12461305 Parser.Lex(); // Eat shift type token.
12471306
12481307 // Rrx stands alone.
1249 if (St == Rrx)
1308 if (St == ARM_AM::rrx)
12501309 return false;
12511310
12521311 // Otherwise, there must be a '#' and a shift amount.
12851344 case AsmToken::Identifier:
12861345 if (!TryParseRegisterWithWriteBack(Operands))
12871346 return false;
1347 if (!TryParseShiftRegister(Operands))
1348 return false;
1349
12881350
12891351 // Fall though for the Identifier case that is not a register or a
12901352 // special name.
281281 @ CHECK: msr cpsr_fsxc, r0 @ encoding: [0x00,0xf0,0x2f,0xe1]
282282 msr cpsr_fsxc, r0
283283
284 @ CHECK: add r1, r2, r3, lsl r4 @ encoding: [0x13,0x14,0x82,0xe0]
285 add r1, r2, r3, lsl r4