ARMAsmParser.cpp revision b72d2a92b75daa9cbac7338aff0cd8ae04c2b4bd
1//===-- ARMAsmParser.cpp - Parse ARM assembly to MCInst instructions ------===// 2// 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#include "ARM.h" 11#include "ARMAddressingModes.h" 12#include "ARMBaseRegisterInfo.h" 13#include "ARMSubtarget.h" 14#include "llvm/MC/MCParser/MCAsmLexer.h" 15#include "llvm/MC/MCParser/MCAsmParser.h" 16#include "llvm/MC/MCParser/MCParsedAsmOperand.h" 17#include "llvm/MC/MCContext.h" 18#include "llvm/MC/MCStreamer.h" 19#include "llvm/MC/MCExpr.h" 20#include "llvm/MC/MCInst.h" 21#include "llvm/Target/TargetRegistry.h" 22#include "llvm/Target/TargetAsmParser.h" 23#include "llvm/Support/SourceMgr.h" 24#include "llvm/Support/raw_ostream.h" 25#include "llvm/ADT/SmallVector.h" 26#include "llvm/ADT/StringSwitch.h" 27#include "llvm/ADT/Twine.h" 28using namespace llvm; 29 30/// Shift types used for register controlled shifts in ARM memory addressing. 31enum ShiftType { 32 Lsl, 33 Lsr, 34 Asr, 35 Ror, 36 Rrx 37}; 38 39namespace { 40 41class ARMOperand; 42 43class ARMAsmParser : public TargetAsmParser { 44 MCAsmParser &Parser; 45 TargetMachine &TM; 46 47 MCAsmParser &getParser() const { return Parser; } 48 MCAsmLexer &getLexer() const { return Parser.getLexer(); } 49 50 void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); } 51 bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); } 52 53 int TryParseRegister(); 54 bool TryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &); 55 bool ParseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &); 56 bool ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &); 57 bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &); 58 59 bool ParseMemoryOffsetReg(bool &Negative, 60 bool &OffsetRegShifted, 61 enum ShiftType &ShiftType, 62 const MCExpr *&ShiftAmount, 63 const MCExpr *&Offset, 64 bool &OffsetIsReg, 65 int &OffsetRegNum, 66 SMLoc &E); 67 bool ParseShift(enum ShiftType &St, const MCExpr *&ShiftAmount, SMLoc &E); 68 bool ParseDirectiveWord(unsigned Size, SMLoc L); 69 bool ParseDirectiveThumb(SMLoc L); 70 bool ParseDirectiveThumbFunc(SMLoc L); 71 bool ParseDirectiveCode(SMLoc L); 72 bool ParseDirectiveSyntax(SMLoc L); 73 74 bool MatchAndEmitInstruction(SMLoc IDLoc, 75 SmallVectorImpl<MCParsedAsmOperand*> &Operands, 76 MCStreamer &Out); 77 78 /// @name Auto-generated Match Functions 79 /// { 80 81#define GET_ASSEMBLER_HEADER 82#include "ARMGenAsmMatcher.inc" 83 84 /// } 85 86public: 87 ARMAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &_TM) 88 : TargetAsmParser(T), Parser(_Parser), TM(_TM) { 89 // Initialize the set of available features. 90 setAvailableFeatures(ComputeAvailableFeatures( 91 &TM.getSubtarget<ARMSubtarget>())); 92 } 93 94 virtual bool ParseInstruction(StringRef Name, SMLoc NameLoc, 95 SmallVectorImpl<MCParsedAsmOperand*> &Operands); 96 virtual bool ParseDirective(AsmToken DirectiveID); 97}; 98} // end anonymous namespace 99 100namespace { 101 102/// ARMOperand - Instances of this class represent a parsed ARM machine 103/// instruction. 104class ARMOperand : public MCParsedAsmOperand { 105 enum KindTy { 106 CondCode, 107 CCOut, 108 Immediate, 109 Memory, 110 Register, 111 RegisterList, 112 DPRRegisterList, 113 SPRRegisterList, 114 Token 115 } Kind; 116 117 SMLoc StartLoc, EndLoc; 118 SmallVector<unsigned, 8> Registers; 119 120 union { 121 struct { 122 ARMCC::CondCodes Val; 123 } CC; 124 125 struct { 126 const char *Data; 127 unsigned Length; 128 } Tok; 129 130 struct { 131 unsigned RegNum; 132 } Reg; 133 134 struct { 135 const MCExpr *Val; 136 } Imm; 137 138 /// Combined record for all forms of ARM address expressions. 139 struct { 140 unsigned BaseRegNum; 141 unsigned OffsetRegNum; // used when OffsetIsReg is true 142 const MCExpr *Offset; // used when OffsetIsReg is false 143 const MCExpr *ShiftAmount; // used when OffsetRegShifted is true 144 enum ShiftType ShiftType; // used when OffsetRegShifted is true 145 unsigned OffsetRegShifted : 1; // only used when OffsetIsReg is true 146 unsigned Preindexed : 1; 147 unsigned Postindexed : 1; 148 unsigned OffsetIsReg : 1; 149 unsigned Negative : 1; // only used when OffsetIsReg is true 150 unsigned Writeback : 1; 151 } Mem; 152 }; 153 154 ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {} 155public: 156 ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() { 157 Kind = o.Kind; 158 StartLoc = o.StartLoc; 159 EndLoc = o.EndLoc; 160 switch (Kind) { 161 case CondCode: 162 CC = o.CC; 163 break; 164 case Token: 165 Tok = o.Tok; 166 break; 167 case CCOut: 168 case Register: 169 Reg = o.Reg; 170 break; 171 case RegisterList: 172 case DPRRegisterList: 173 case SPRRegisterList: 174 Registers = o.Registers; 175 break; 176 case Immediate: 177 Imm = o.Imm; 178 break; 179 case Memory: 180 Mem = o.Mem; 181 break; 182 } 183 } 184 185 /// getStartLoc - Get the location of the first token of this operand. 186 SMLoc getStartLoc() const { return StartLoc; } 187 /// getEndLoc - Get the location of the last token of this operand. 188 SMLoc getEndLoc() const { return EndLoc; } 189 190 ARMCC::CondCodes getCondCode() const { 191 assert(Kind == CondCode && "Invalid access!"); 192 return CC.Val; 193 } 194 195 StringRef getToken() const { 196 assert(Kind == Token && "Invalid access!"); 197 return StringRef(Tok.Data, Tok.Length); 198 } 199 200 unsigned getReg() const { 201 assert((Kind == Register || Kind == CCOut) && "Invalid access!"); 202 return Reg.RegNum; 203 } 204 205 const SmallVectorImpl<unsigned> &getRegList() const { 206 assert((Kind == RegisterList || Kind == DPRRegisterList || 207 Kind == SPRRegisterList) && "Invalid access!"); 208 return Registers; 209 } 210 211 const MCExpr *getImm() const { 212 assert(Kind == Immediate && "Invalid access!"); 213 return Imm.Val; 214 } 215 216 bool isCondCode() const { return Kind == CondCode; } 217 bool isCCOut() const { return Kind == CCOut; } 218 bool isImm() const { return Kind == Immediate; } 219 bool isReg() const { return Kind == Register; } 220 bool isRegList() const { return Kind == RegisterList; } 221 bool isDPRRegList() const { return Kind == DPRRegisterList; } 222 bool isSPRRegList() const { return Kind == SPRRegisterList; } 223 bool isToken() const { return Kind == Token; } 224 bool isMemory() const { return Kind == Memory; } 225 bool isMemMode5() const { 226 if (!isMemory() || Mem.OffsetIsReg || Mem.OffsetRegShifted || 227 Mem.Writeback || Mem.Negative) 228 return false; 229 230 // If there is an offset expression, make sure it's valid. 231 if (!Mem.Offset) return true; 232 233 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Mem.Offset); 234 if (!CE) return false; 235 236 // The offset must be a multiple of 4 in the range 0-1020. 237 int64_t Value = CE->getValue(); 238 return ((Value & 0x3) == 0 && Value <= 1020 && Value >= -1020); 239 } 240 bool isMemModeRegThumb() const { 241 if (!isMemory() || (!Mem.OffsetIsReg && !Mem.Offset) || Mem.Writeback) 242 return false; 243 return !Mem.Offset || !isa<MCConstantExpr>(Mem.Offset); 244 } 245 bool isMemModeImmThumb() const { 246 if (!isMemory() || (!Mem.OffsetIsReg && !Mem.Offset) || Mem.Writeback) 247 return false; 248 249 if (!Mem.Offset) return false; 250 251 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Mem.Offset); 252 if (!CE) return false; 253 254 // The offset must be a multiple of 4 in the range 0-124. 255 uint64_t Value = CE->getValue(); 256 return ((Value & 0x3) == 0 && Value <= 124); 257 } 258 259 void addExpr(MCInst &Inst, const MCExpr *Expr) const { 260 // Add as immediates when possible. Null MCExpr = 0. 261 if (Expr == 0) 262 Inst.addOperand(MCOperand::CreateImm(0)); 263 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr)) 264 Inst.addOperand(MCOperand::CreateImm(CE->getValue())); 265 else 266 Inst.addOperand(MCOperand::CreateExpr(Expr)); 267 } 268 269 void addCondCodeOperands(MCInst &Inst, unsigned N) const { 270 assert(N == 2 && "Invalid number of operands!"); 271 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode()))); 272 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR; 273 Inst.addOperand(MCOperand::CreateReg(RegNum)); 274 } 275 276 void addCCOutOperands(MCInst &Inst, unsigned N) const { 277 assert(N == 1 && "Invalid number of operands!"); 278 Inst.addOperand(MCOperand::CreateReg(getReg())); 279 } 280 281 void addRegOperands(MCInst &Inst, unsigned N) const { 282 assert(N == 1 && "Invalid number of operands!"); 283 Inst.addOperand(MCOperand::CreateReg(getReg())); 284 } 285 286 void addRegListOperands(MCInst &Inst, unsigned N) const { 287 assert(N == 1 && "Invalid number of operands!"); 288 const SmallVectorImpl<unsigned> &RegList = getRegList(); 289 for (SmallVectorImpl<unsigned>::const_iterator 290 I = RegList.begin(), E = RegList.end(); I != E; ++I) 291 Inst.addOperand(MCOperand::CreateReg(*I)); 292 } 293 294 void addDPRRegListOperands(MCInst &Inst, unsigned N) const { 295 addRegListOperands(Inst, N); 296 } 297 298 void addSPRRegListOperands(MCInst &Inst, unsigned N) const { 299 addRegListOperands(Inst, N); 300 } 301 302 void addImmOperands(MCInst &Inst, unsigned N) const { 303 assert(N == 1 && "Invalid number of operands!"); 304 addExpr(Inst, getImm()); 305 } 306 307 void addMemMode5Operands(MCInst &Inst, unsigned N) const { 308 assert(N == 2 && isMemMode5() && "Invalid number of operands!"); 309 310 Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum)); 311 assert(!Mem.OffsetIsReg && "Invalid mode 5 operand"); 312 313 // FIXME: #-0 is encoded differently than #0. Does the parser preserve 314 // the difference? 315 if (Mem.Offset) { 316 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Mem.Offset); 317 assert(CE && "Non-constant mode 5 offset operand!"); 318 319 // The MCInst offset operand doesn't include the low two bits (like 320 // the instruction encoding). 321 int64_t Offset = CE->getValue() / 4; 322 if (Offset >= 0) 323 Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM5Opc(ARM_AM::add, 324 Offset))); 325 else 326 Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM5Opc(ARM_AM::sub, 327 -Offset))); 328 } else { 329 Inst.addOperand(MCOperand::CreateImm(0)); 330 } 331 } 332 333 void addMemModeRegThumbOperands(MCInst &Inst, unsigned N) const { 334 assert(N == 2 && isMemModeRegThumb() && "Invalid number of operands!"); 335 Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum)); 336 Inst.addOperand(MCOperand::CreateReg(Mem.OffsetRegNum)); 337 } 338 339 void addMemModeImmThumbOperands(MCInst &Inst, unsigned N) const { 340 assert(N == 2 && isMemModeImmThumb() && "Invalid number of operands!"); 341 Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum)); 342 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Mem.Offset); 343 assert(CE && "Non-constant mode offset operand!"); 344 Inst.addOperand(MCOperand::CreateImm(CE->getValue())); 345 } 346 347 virtual void dump(raw_ostream &OS) const; 348 349 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) { 350 ARMOperand *Op = new ARMOperand(CondCode); 351 Op->CC.Val = CC; 352 Op->StartLoc = S; 353 Op->EndLoc = S; 354 return Op; 355 } 356 357 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) { 358 ARMOperand *Op = new ARMOperand(CCOut); 359 Op->Reg.RegNum = RegNum; 360 Op->StartLoc = S; 361 Op->EndLoc = S; 362 return Op; 363 } 364 365 static ARMOperand *CreateToken(StringRef Str, SMLoc S) { 366 ARMOperand *Op = new ARMOperand(Token); 367 Op->Tok.Data = Str.data(); 368 Op->Tok.Length = Str.size(); 369 Op->StartLoc = S; 370 Op->EndLoc = S; 371 return Op; 372 } 373 374 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) { 375 ARMOperand *Op = new ARMOperand(Register); 376 Op->Reg.RegNum = RegNum; 377 Op->StartLoc = S; 378 Op->EndLoc = E; 379 return Op; 380 } 381 382 static ARMOperand * 383 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs, 384 SMLoc StartLoc, SMLoc EndLoc) { 385 KindTy Kind = RegisterList; 386 387 if (ARM::DPRRegClass.contains(Regs.front().first)) 388 Kind = DPRRegisterList; 389 else if (ARM::SPRRegClass.contains(Regs.front().first)) 390 Kind = SPRRegisterList; 391 392 ARMOperand *Op = new ARMOperand(Kind); 393 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator 394 I = Regs.begin(), E = Regs.end(); I != E; ++I) 395 Op->Registers.push_back(I->first); 396 array_pod_sort(Op->Registers.begin(), Op->Registers.end()); 397 Op->StartLoc = StartLoc; 398 Op->EndLoc = EndLoc; 399 return Op; 400 } 401 402 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) { 403 ARMOperand *Op = new ARMOperand(Immediate); 404 Op->Imm.Val = Val; 405 Op->StartLoc = S; 406 Op->EndLoc = E; 407 return Op; 408 } 409 410 static ARMOperand *CreateMem(unsigned BaseRegNum, bool OffsetIsReg, 411 const MCExpr *Offset, unsigned OffsetRegNum, 412 bool OffsetRegShifted, enum ShiftType ShiftType, 413 const MCExpr *ShiftAmount, bool Preindexed, 414 bool Postindexed, bool Negative, bool Writeback, 415 SMLoc S, SMLoc E) { 416 ARMOperand *Op = new ARMOperand(Memory); 417 Op->Mem.BaseRegNum = BaseRegNum; 418 Op->Mem.OffsetIsReg = OffsetIsReg; 419 Op->Mem.Offset = Offset; 420 Op->Mem.OffsetRegNum = OffsetRegNum; 421 Op->Mem.OffsetRegShifted = OffsetRegShifted; 422 Op->Mem.ShiftType = ShiftType; 423 Op->Mem.ShiftAmount = ShiftAmount; 424 Op->Mem.Preindexed = Preindexed; 425 Op->Mem.Postindexed = Postindexed; 426 Op->Mem.Negative = Negative; 427 Op->Mem.Writeback = Writeback; 428 429 Op->StartLoc = S; 430 Op->EndLoc = E; 431 return Op; 432 } 433}; 434 435} // end anonymous namespace. 436 437void ARMOperand::dump(raw_ostream &OS) const { 438 switch (Kind) { 439 case CondCode: 440 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">"; 441 break; 442 case CCOut: 443 OS << "<ccout " << getReg() << ">"; 444 break; 445 case Immediate: 446 getImm()->print(OS); 447 break; 448 case Memory: 449 OS << "<memory>"; 450 break; 451 case Register: 452 OS << "<register " << getReg() << ">"; 453 break; 454 case RegisterList: 455 case DPRRegisterList: 456 case SPRRegisterList: { 457 OS << "<register_list "; 458 459 const SmallVectorImpl<unsigned> &RegList = getRegList(); 460 for (SmallVectorImpl<unsigned>::const_iterator 461 I = RegList.begin(), E = RegList.end(); I != E; ) { 462 OS << *I; 463 if (++I < E) OS << ", "; 464 } 465 466 OS << ">"; 467 break; 468 } 469 case Token: 470 OS << "'" << getToken() << "'"; 471 break; 472 } 473} 474 475/// @name Auto-generated Match Functions 476/// { 477 478static unsigned MatchRegisterName(StringRef Name); 479 480/// } 481 482/// Try to parse a register name. The token must be an Identifier when called, 483/// and if it is a register name the token is eaten and the register number is 484/// returned. Otherwise return -1. 485/// 486int ARMAsmParser::TryParseRegister() { 487 const AsmToken &Tok = Parser.getTok(); 488 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier"); 489 490 // FIXME: Validate register for the current architecture; we have to do 491 // validation later, so maybe there is no need for this here. 492 unsigned RegNum = MatchRegisterName(Tok.getString()); 493 if (RegNum == 0) 494 return -1; 495 Parser.Lex(); // Eat identifier token. 496 return RegNum; 497} 498 499 500/// Try to parse a register name. The token must be an Identifier when called. 501/// If it's a register, an AsmOperand is created. Another AsmOperand is created 502/// if there is a "writeback". 'true' if it's not a register. 503/// 504/// TODO this is likely to change to allow different register types and or to 505/// parse for a specific register type. 506bool ARMAsmParser:: 507TryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 508 SMLoc S = Parser.getTok().getLoc(); 509 int RegNo = TryParseRegister(); 510 if (RegNo == -1) 511 return true; 512 513 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc())); 514 515 const AsmToken &ExclaimTok = Parser.getTok(); 516 if (ExclaimTok.is(AsmToken::Exclaim)) { 517 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(), 518 ExclaimTok.getLoc())); 519 Parser.Lex(); // Eat exclaim token 520 } 521 522 return false; 523} 524 525/// Parse a register list, return it if successful else return null. The first 526/// token must be a '{' when called. 527bool ARMAsmParser:: 528ParseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 529 assert(Parser.getTok().is(AsmToken::LCurly) && 530 "Token is not a Left Curly Brace"); 531 SMLoc S = Parser.getTok().getLoc(); 532 533 // Read the rest of the registers in the list. 534 unsigned PrevRegNum = 0; 535 SmallVector<std::pair<unsigned, SMLoc>, 32> Registers; 536 537 do { 538 bool IsRange = Parser.getTok().is(AsmToken::Minus); 539 Parser.Lex(); // Eat non-identifier token. 540 541 const AsmToken &RegTok = Parser.getTok(); 542 SMLoc RegLoc = RegTok.getLoc(); 543 if (RegTok.isNot(AsmToken::Identifier)) { 544 Error(RegLoc, "register expected"); 545 return true; 546 } 547 548 int RegNum = TryParseRegister(); 549 if (RegNum == -1) { 550 Error(RegLoc, "register expected"); 551 return true; 552 } 553 554 if (IsRange) { 555 int Reg = PrevRegNum; 556 do { 557 ++Reg; 558 Registers.push_back(std::make_pair(Reg, RegLoc)); 559 } while (Reg != RegNum); 560 } else { 561 Registers.push_back(std::make_pair(RegNum, RegLoc)); 562 } 563 564 PrevRegNum = RegNum; 565 } while (Parser.getTok().is(AsmToken::Comma) || 566 Parser.getTok().is(AsmToken::Minus)); 567 568 // Process the right curly brace of the list. 569 const AsmToken &RCurlyTok = Parser.getTok(); 570 if (RCurlyTok.isNot(AsmToken::RCurly)) { 571 Error(RCurlyTok.getLoc(), "'}' expected"); 572 return true; 573 } 574 575 SMLoc E = RCurlyTok.getLoc(); 576 Parser.Lex(); // Eat right curly brace token. 577 578 // Verify the register list. 579 SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator 580 RI = Registers.begin(), RE = Registers.end(); 581 582 DenseMap<unsigned, bool> RegMap; 583 RegMap[RI->first] = true; 584 585 unsigned HighRegNum = RI->first; 586 bool EmittedWarning = false; 587 588 for (++RI; RI != RE; ++RI) { 589 const std::pair<unsigned, SMLoc> &RegInfo = *RI; 590 unsigned Reg = RegInfo.first; 591 592 if (RegMap[Reg]) { 593 Error(RegInfo.second, "register duplicated in register list"); 594 return true; 595 } 596 597 if (!EmittedWarning && Reg < HighRegNum) 598 Warning(RegInfo.second, 599 "register not in ascending order in register list"); 600 601 RegMap[Reg] = true; 602 HighRegNum = std::max(Reg, HighRegNum); 603 } 604 605 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E)); 606 return false; 607} 608 609/// Parse an ARM memory expression, return false if successful else return true 610/// or an error. The first token must be a '[' when called. 611/// 612/// TODO Only preindexing and postindexing addressing are started, unindexed 613/// with option, etc are still to do. 614bool ARMAsmParser:: 615ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 616 SMLoc S, E; 617 assert(Parser.getTok().is(AsmToken::LBrac) && 618 "Token is not a Left Bracket"); 619 S = Parser.getTok().getLoc(); 620 Parser.Lex(); // Eat left bracket token. 621 622 const AsmToken &BaseRegTok = Parser.getTok(); 623 if (BaseRegTok.isNot(AsmToken::Identifier)) { 624 Error(BaseRegTok.getLoc(), "register expected"); 625 return true; 626 } 627 int BaseRegNum = TryParseRegister(); 628 if (BaseRegNum == -1) { 629 Error(BaseRegTok.getLoc(), "register expected"); 630 return true; 631 } 632 633 bool Preindexed = false; 634 bool Postindexed = false; 635 bool OffsetIsReg = false; 636 bool Negative = false; 637 bool Writeback = false; 638 639 // First look for preindexed address forms, that is after the "[Rn" we now 640 // have to see if the next token is a comma. 641 const AsmToken &Tok = Parser.getTok(); 642 if (Tok.is(AsmToken::Comma)) { 643 Preindexed = true; 644 Parser.Lex(); // Eat comma token. 645 int OffsetRegNum; 646 bool OffsetRegShifted; 647 enum ShiftType ShiftType; 648 const MCExpr *ShiftAmount = 0; 649 const MCExpr *Offset = 0; 650 if (ParseMemoryOffsetReg(Negative, OffsetRegShifted, ShiftType, ShiftAmount, 651 Offset, OffsetIsReg, OffsetRegNum, E)) 652 return true; 653 const AsmToken &RBracTok = Parser.getTok(); 654 if (RBracTok.isNot(AsmToken::RBrac)) { 655 Error(RBracTok.getLoc(), "']' expected"); 656 return true; 657 } 658 E = RBracTok.getLoc(); 659 Parser.Lex(); // Eat right bracket token. 660 661 662 const AsmToken &ExclaimTok = Parser.getTok(); 663 ARMOperand *WBOp = 0; 664 if (ExclaimTok.is(AsmToken::Exclaim)) { 665 WBOp = ARMOperand::CreateToken(ExclaimTok.getString(), 666 ExclaimTok.getLoc()); 667 Writeback = true; 668 Parser.Lex(); // Eat exclaim token 669 } 670 671 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, OffsetIsReg, Offset, 672 OffsetRegNum, OffsetRegShifted, 673 ShiftType, ShiftAmount, Preindexed, 674 Postindexed, Negative, Writeback, 675 S, E)); 676 if (WBOp) 677 Operands.push_back(WBOp); 678 679 return false; 680 } 681 // The "[Rn" we have so far was not followed by a comma. 682 else if (Tok.is(AsmToken::RBrac)) { 683 // If there's anything other than the right brace, this is a post indexing 684 // addressing form. 685 E = Tok.getLoc(); 686 Parser.Lex(); // Eat right bracket token. 687 688 int OffsetRegNum = 0; 689 bool OffsetRegShifted = false; 690 enum ShiftType ShiftType = Lsl; 691 const MCExpr *ShiftAmount = 0; 692 const MCExpr *Offset = 0; 693 694 const AsmToken &NextTok = Parser.getTok(); 695 696 if (NextTok.isNot(AsmToken::EndOfStatement)) { 697 Postindexed = true; 698 Writeback = true; 699 700 if (NextTok.isNot(AsmToken::Comma)) { 701 Error(NextTok.getLoc(), "',' expected"); 702 return true; 703 } 704 705 Parser.Lex(); // Eat comma token. 706 707 if (ParseMemoryOffsetReg(Negative, OffsetRegShifted, ShiftType, 708 ShiftAmount, Offset, OffsetIsReg, OffsetRegNum, 709 E)) 710 return true; 711 } 712 713 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, OffsetIsReg, Offset, 714 OffsetRegNum, OffsetRegShifted, 715 ShiftType, ShiftAmount, Preindexed, 716 Postindexed, Negative, Writeback, 717 S, E)); 718 return false; 719 } 720 721 return true; 722} 723 724/// Parse the offset of a memory operand after we have seen "[Rn," or "[Rn]," 725/// we will parse the following (were +/- means that a plus or minus is 726/// optional): 727/// +/-Rm 728/// +/-Rm, shift 729/// #offset 730/// we return false on success or an error otherwise. 731bool ARMAsmParser::ParseMemoryOffsetReg(bool &Negative, 732 bool &OffsetRegShifted, 733 enum ShiftType &ShiftType, 734 const MCExpr *&ShiftAmount, 735 const MCExpr *&Offset, 736 bool &OffsetIsReg, 737 int &OffsetRegNum, 738 SMLoc &E) { 739 Negative = false; 740 OffsetRegShifted = false; 741 OffsetIsReg = false; 742 OffsetRegNum = -1; 743 const AsmToken &NextTok = Parser.getTok(); 744 E = NextTok.getLoc(); 745 if (NextTok.is(AsmToken::Plus)) 746 Parser.Lex(); // Eat plus token. 747 else if (NextTok.is(AsmToken::Minus)) { 748 Negative = true; 749 Parser.Lex(); // Eat minus token 750 } 751 // See if there is a register following the "[Rn," or "[Rn]," we have so far. 752 const AsmToken &OffsetRegTok = Parser.getTok(); 753 if (OffsetRegTok.is(AsmToken::Identifier)) { 754 SMLoc CurLoc = OffsetRegTok.getLoc(); 755 OffsetRegNum = TryParseRegister(); 756 if (OffsetRegNum != -1) { 757 OffsetIsReg = true; 758 E = CurLoc; 759 } 760 } 761 762 // If we parsed a register as the offset then there can be a shift after that. 763 if (OffsetRegNum != -1) { 764 // Look for a comma then a shift 765 const AsmToken &Tok = Parser.getTok(); 766 if (Tok.is(AsmToken::Comma)) { 767 Parser.Lex(); // Eat comma token. 768 769 const AsmToken &Tok = Parser.getTok(); 770 if (ParseShift(ShiftType, ShiftAmount, E)) 771 return Error(Tok.getLoc(), "shift expected"); 772 OffsetRegShifted = true; 773 } 774 } 775 else { // the "[Rn," or "[Rn,]" we have so far was not followed by "Rm" 776 // Look for #offset following the "[Rn," or "[Rn]," 777 const AsmToken &HashTok = Parser.getTok(); 778 if (HashTok.isNot(AsmToken::Hash)) 779 return Error(HashTok.getLoc(), "'#' expected"); 780 781 Parser.Lex(); // Eat hash token. 782 783 if (getParser().ParseExpression(Offset)) 784 return true; 785 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); 786 } 787 return false; 788} 789 790/// ParseShift as one of these two: 791/// ( lsl | lsr | asr | ror ) , # shift_amount 792/// rrx 793/// and returns true if it parses a shift otherwise it returns false. 794bool ARMAsmParser::ParseShift(ShiftType &St, const MCExpr *&ShiftAmount, 795 SMLoc &E) { 796 const AsmToken &Tok = Parser.getTok(); 797 if (Tok.isNot(AsmToken::Identifier)) 798 return true; 799 StringRef ShiftName = Tok.getString(); 800 if (ShiftName == "lsl" || ShiftName == "LSL") 801 St = Lsl; 802 else if (ShiftName == "lsr" || ShiftName == "LSR") 803 St = Lsr; 804 else if (ShiftName == "asr" || ShiftName == "ASR") 805 St = Asr; 806 else if (ShiftName == "ror" || ShiftName == "ROR") 807 St = Ror; 808 else if (ShiftName == "rrx" || ShiftName == "RRX") 809 St = Rrx; 810 else 811 return true; 812 Parser.Lex(); // Eat shift type token. 813 814 // Rrx stands alone. 815 if (St == Rrx) 816 return false; 817 818 // Otherwise, there must be a '#' and a shift amount. 819 const AsmToken &HashTok = Parser.getTok(); 820 if (HashTok.isNot(AsmToken::Hash)) 821 return Error(HashTok.getLoc(), "'#' expected"); 822 Parser.Lex(); // Eat hash token. 823 824 if (getParser().ParseExpression(ShiftAmount)) 825 return true; 826 827 return false; 828} 829 830/// Parse a arm instruction operand. For now this parses the operand regardless 831/// of the mnemonic. 832bool ARMAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands){ 833 SMLoc S, E; 834 switch (getLexer().getKind()) { 835 default: 836 Error(Parser.getTok().getLoc(), "unexpected token in operand"); 837 return true; 838 case AsmToken::Identifier: { 839 if (!TryParseRegisterWithWriteBack(Operands)) 840 return false; 841 842 // This was not a register so parse other operands that start with an 843 // identifier (like labels) as expressions and create them as immediates. 844 const MCExpr *IdVal; 845 S = Parser.getTok().getLoc(); 846 if (getParser().ParseExpression(IdVal)) 847 return true; 848 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); 849 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E)); 850 return false; 851 } 852 case AsmToken::LBrac: 853 return ParseMemory(Operands); 854 case AsmToken::LCurly: 855 return ParseRegisterList(Operands); 856 case AsmToken::Hash: 857 // #42 -> immediate. 858 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate 859 S = Parser.getTok().getLoc(); 860 Parser.Lex(); 861 const MCExpr *ImmVal; 862 if (getParser().ParseExpression(ImmVal)) 863 return true; 864 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); 865 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E)); 866 return false; 867 } 868} 869 870/// \brief Given a mnemonic, split out possible predication code and carry 871/// setting letters to form a canonical mnemonic and flags. 872// 873// FIXME: Would be nice to autogen this. 874static StringRef SplitMnemonicAndCC(StringRef Mnemonic, 875 unsigned &PredicationCode, 876 bool &CarrySetting) { 877 PredicationCode = ARMCC::AL; 878 CarrySetting = false; 879 880 // Ignore some mnemonics we know aren't predicated forms. 881 // 882 // FIXME: Would be nice to autogen this. 883 if (Mnemonic == "teq" || Mnemonic == "vceq" || 884 Mnemonic == "movs" || 885 Mnemonic == "svc" || 886 (Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" || 887 Mnemonic == "vmls" || Mnemonic == "vnmls") || 888 Mnemonic == "vacge" || Mnemonic == "vcge" || 889 Mnemonic == "vclt" || 890 Mnemonic == "vacgt" || Mnemonic == "vcgt" || 891 Mnemonic == "vcle" || 892 (Mnemonic == "smlal" || Mnemonic == "umaal" || Mnemonic == "umlal" || 893 Mnemonic == "vabal" || Mnemonic == "vmlal" || Mnemonic == "vpadal" || 894 Mnemonic == "vqdmlal")) 895 return Mnemonic; 896 897 // First, split out any predication code. 898 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2)) 899 .Case("eq", ARMCC::EQ) 900 .Case("ne", ARMCC::NE) 901 .Case("hs", ARMCC::HS) 902 .Case("lo", ARMCC::LO) 903 .Case("mi", ARMCC::MI) 904 .Case("pl", ARMCC::PL) 905 .Case("vs", ARMCC::VS) 906 .Case("vc", ARMCC::VC) 907 .Case("hi", ARMCC::HI) 908 .Case("ls", ARMCC::LS) 909 .Case("ge", ARMCC::GE) 910 .Case("lt", ARMCC::LT) 911 .Case("gt", ARMCC::GT) 912 .Case("le", ARMCC::LE) 913 .Case("al", ARMCC::AL) 914 .Default(~0U); 915 if (CC != ~0U) { 916 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2); 917 PredicationCode = CC; 918 } 919 920 // Next, determine if we have a carry setting bit. We explicitly ignore all 921 // the instructions we know end in 's'. 922 if (Mnemonic.endswith("s") && 923 !(Mnemonic == "asrs" || Mnemonic == "cps" || Mnemonic == "mls" || 924 Mnemonic == "movs" || Mnemonic == "mrs" || Mnemonic == "smmls" || 925 Mnemonic == "vabs" || Mnemonic == "vcls" || Mnemonic == "vmls" || 926 Mnemonic == "vmrs" || Mnemonic == "vnmls" || Mnemonic == "vqabs" || 927 Mnemonic == "vrecps" || Mnemonic == "vrsqrts")) { 928 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1); 929 CarrySetting = true; 930 } 931 932 return Mnemonic; 933} 934 935/// \brief Given a canonical mnemonic, determine if the instruction ever allows 936/// inclusion of carry set or predication code operands. 937// 938// FIXME: It would be nice to autogen this. 939static void GetMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet, 940 bool &CanAcceptPredicationCode) { 941 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" || 942 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" || 943 Mnemonic == "smull" || Mnemonic == "add" || Mnemonic == "adc" || 944 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" || 945 Mnemonic == "umlal" || Mnemonic == "orr" || Mnemonic == "mov" || 946 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" || 947 Mnemonic == "sbc" || Mnemonic == "mla" || Mnemonic == "umull" || 948 Mnemonic == "eor" || Mnemonic == "smlal" || Mnemonic == "mvn") { 949 CanAcceptCarrySet = true; 950 } else { 951 CanAcceptCarrySet = false; 952 } 953 954 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" || 955 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" || 956 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" || 957 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" || 958 Mnemonic == "dsb" || Mnemonic == "movs") { 959 CanAcceptPredicationCode = false; 960 } else { 961 CanAcceptPredicationCode = true; 962 } 963} 964 965/// Parse an arm instruction mnemonic followed by its operands. 966bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc, 967 SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 968 // Create the leading tokens for the mnemonic, split by '.' characters. 969 size_t Start = 0, Next = Name.find('.'); 970 StringRef Head = Name.slice(Start, Next); 971 972 // Split out the predication code and carry setting flag from the mnemonic. 973 unsigned PredicationCode; 974 bool CarrySetting; 975 Head = SplitMnemonicAndCC(Head, PredicationCode, CarrySetting); 976 977 Operands.push_back(ARMOperand::CreateToken(Head, NameLoc)); 978 979 // Next, add the CCOut and ConditionCode operands, if needed. 980 // 981 // For mnemonics which can ever incorporate a carry setting bit or predication 982 // code, our matching model involves us always generating CCOut and 983 // ConditionCode operands to match the mnemonic "as written" and then we let 984 // the matcher deal with finding the right instruction or generating an 985 // appropriate error. 986 bool CanAcceptCarrySet, CanAcceptPredicationCode; 987 GetMnemonicAcceptInfo(Head, CanAcceptCarrySet, CanAcceptPredicationCode); 988 989 // Add the carry setting operand, if necessary. 990 // 991 // FIXME: It would be awesome if we could somehow invent a location such that 992 // match errors on this operand would print a nice diagnostic about how the 993 // 's' character in the mnemonic resulted in a CCOut operand. 994 if (CanAcceptCarrySet) { 995 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0, 996 NameLoc)); 997 } else { 998 // This mnemonic can't ever accept a carry set, but the user wrote one (or 999 // misspelled another mnemonic). 1000 1001 // FIXME: Issue a nice error. 1002 } 1003 1004 // Add the predication code operand, if necessary. 1005 if (CanAcceptPredicationCode) { 1006 Operands.push_back(ARMOperand::CreateCondCode( 1007 ARMCC::CondCodes(PredicationCode), NameLoc)); 1008 } else { 1009 // This mnemonic can't ever accept a predication code, but the user wrote 1010 // one (or misspelled another mnemonic). 1011 1012 // FIXME: Issue a nice error. 1013 } 1014 1015 // Add the remaining tokens in the mnemonic. 1016 while (Next != StringRef::npos) { 1017 Start = Next; 1018 Next = Name.find('.', Start + 1); 1019 Head = Name.slice(Start, Next); 1020 1021 Operands.push_back(ARMOperand::CreateToken(Head, NameLoc)); 1022 } 1023 1024 // Read the remaining operands. 1025 if (getLexer().isNot(AsmToken::EndOfStatement)) { 1026 // Read the first operand. 1027 if (ParseOperand(Operands)) { 1028 Parser.EatToEndOfStatement(); 1029 return true; 1030 } 1031 1032 while (getLexer().is(AsmToken::Comma)) { 1033 Parser.Lex(); // Eat the comma. 1034 1035 // Parse and remember the operand. 1036 if (ParseOperand(Operands)) { 1037 Parser.EatToEndOfStatement(); 1038 return true; 1039 } 1040 } 1041 } 1042 1043 if (getLexer().isNot(AsmToken::EndOfStatement)) { 1044 Parser.EatToEndOfStatement(); 1045 return TokError("unexpected token in argument list"); 1046 } 1047 1048 Parser.Lex(); // Consume the EndOfStatement 1049 return false; 1050} 1051 1052bool ARMAsmParser:: 1053MatchAndEmitInstruction(SMLoc IDLoc, 1054 SmallVectorImpl<MCParsedAsmOperand*> &Operands, 1055 MCStreamer &Out) { 1056 MCInst Inst; 1057 unsigned ErrorInfo; 1058 MatchResultTy MatchResult, MatchResult2; 1059 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo); 1060 if (MatchResult != Match_Success) { 1061 // If we get a Match_InvalidOperand it might be some arithmetic instruction 1062 // that does not update the condition codes. So try adding a CCOut operand 1063 // with a value of reg0. 1064 if (MatchResult == Match_InvalidOperand) { 1065 Operands.insert(Operands.begin() + 1, 1066 ARMOperand::CreateCCOut(0, 1067 ((ARMOperand*)Operands[0])->getStartLoc())); 1068 MatchResult2 = MatchInstructionImpl(Operands, Inst, ErrorInfo); 1069 if (MatchResult2 == Match_Success) 1070 MatchResult = Match_Success; 1071 else { 1072 ARMOperand *CCOut = ((ARMOperand*)Operands[1]); 1073 Operands.erase(Operands.begin() + 1); 1074 delete CCOut; 1075 } 1076 } 1077 // If we get a Match_MnemonicFail it might be some arithmetic instruction 1078 // that updates the condition codes if it ends in 's'. So see if the 1079 // mnemonic ends in 's' and if so try removing the 's' and adding a CCOut 1080 // operand with a value of CPSR. 1081 else if(MatchResult == Match_MnemonicFail) { 1082 // Get the instruction mnemonic, which is the first token. 1083 StringRef Mnemonic = ((ARMOperand*)Operands[0])->getToken(); 1084 if (Mnemonic.substr(Mnemonic.size()-1) == "s") { 1085 // removed the 's' from the mnemonic for matching. 1086 StringRef MnemonicNoS = Mnemonic.slice(0, Mnemonic.size() - 1); 1087 SMLoc NameLoc = ((ARMOperand*)Operands[0])->getStartLoc(); 1088 ARMOperand *OldMnemonic = ((ARMOperand*)Operands[0]); 1089 Operands.erase(Operands.begin()); 1090 delete OldMnemonic; 1091 Operands.insert(Operands.begin(), 1092 ARMOperand::CreateToken(MnemonicNoS, NameLoc)); 1093 Operands.insert(Operands.begin() + 1, 1094 ARMOperand::CreateCCOut(ARM::CPSR, NameLoc)); 1095 MatchResult2 = MatchInstructionImpl(Operands, Inst, ErrorInfo); 1096 if (MatchResult2 == Match_Success) 1097 MatchResult = Match_Success; 1098 else { 1099 ARMOperand *OldMnemonic = ((ARMOperand*)Operands[0]); 1100 Operands.erase(Operands.begin()); 1101 delete OldMnemonic; 1102 Operands.insert(Operands.begin(), 1103 ARMOperand::CreateToken(Mnemonic, NameLoc)); 1104 ARMOperand *CCOut = ((ARMOperand*)Operands[1]); 1105 Operands.erase(Operands.begin() + 1); 1106 delete CCOut; 1107 } 1108 } 1109 } 1110 } 1111 switch (MatchResult) { 1112 case Match_Success: 1113 Out.EmitInstruction(Inst); 1114 return false; 1115 case Match_MissingFeature: 1116 Error(IDLoc, "instruction requires a CPU feature not currently enabled"); 1117 return true; 1118 case Match_InvalidOperand: { 1119 SMLoc ErrorLoc = IDLoc; 1120 if (ErrorInfo != ~0U) { 1121 if (ErrorInfo >= Operands.size()) 1122 return Error(IDLoc, "too few operands for instruction"); 1123 1124 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc(); 1125 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc; 1126 } 1127 1128 return Error(ErrorLoc, "invalid operand for instruction"); 1129 } 1130 case Match_MnemonicFail: 1131 return Error(IDLoc, "unrecognized instruction mnemonic"); 1132 } 1133 1134 llvm_unreachable("Implement any new match types added!"); 1135 return true; 1136} 1137 1138/// ParseDirective parses the arm specific directives 1139bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) { 1140 StringRef IDVal = DirectiveID.getIdentifier(); 1141 if (IDVal == ".word") 1142 return ParseDirectiveWord(4, DirectiveID.getLoc()); 1143 else if (IDVal == ".thumb") 1144 return ParseDirectiveThumb(DirectiveID.getLoc()); 1145 else if (IDVal == ".thumb_func") 1146 return ParseDirectiveThumbFunc(DirectiveID.getLoc()); 1147 else if (IDVal == ".code") 1148 return ParseDirectiveCode(DirectiveID.getLoc()); 1149 else if (IDVal == ".syntax") 1150 return ParseDirectiveSyntax(DirectiveID.getLoc()); 1151 return true; 1152} 1153 1154/// ParseDirectiveWord 1155/// ::= .word [ expression (, expression)* ] 1156bool ARMAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) { 1157 if (getLexer().isNot(AsmToken::EndOfStatement)) { 1158 for (;;) { 1159 const MCExpr *Value; 1160 if (getParser().ParseExpression(Value)) 1161 return true; 1162 1163 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/); 1164 1165 if (getLexer().is(AsmToken::EndOfStatement)) 1166 break; 1167 1168 // FIXME: Improve diagnostic. 1169 if (getLexer().isNot(AsmToken::Comma)) 1170 return Error(L, "unexpected token in directive"); 1171 Parser.Lex(); 1172 } 1173 } 1174 1175 Parser.Lex(); 1176 return false; 1177} 1178 1179/// ParseDirectiveThumb 1180/// ::= .thumb 1181bool ARMAsmParser::ParseDirectiveThumb(SMLoc L) { 1182 if (getLexer().isNot(AsmToken::EndOfStatement)) 1183 return Error(L, "unexpected token in directive"); 1184 Parser.Lex(); 1185 1186 // TODO: set thumb mode 1187 // TODO: tell the MC streamer the mode 1188 // getParser().getStreamer().Emit???(); 1189 return false; 1190} 1191 1192/// ParseDirectiveThumbFunc 1193/// ::= .thumbfunc symbol_name 1194bool ARMAsmParser::ParseDirectiveThumbFunc(SMLoc L) { 1195 const AsmToken &Tok = Parser.getTok(); 1196 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String)) 1197 return Error(L, "unexpected token in .thumb_func directive"); 1198 StringRef Name = Tok.getString(); 1199 Parser.Lex(); // Consume the identifier token. 1200 if (getLexer().isNot(AsmToken::EndOfStatement)) 1201 return Error(L, "unexpected token in directive"); 1202 Parser.Lex(); 1203 1204 // Mark symbol as a thumb symbol. 1205 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name); 1206 getParser().getStreamer().EmitThumbFunc(Func); 1207 return false; 1208} 1209 1210/// ParseDirectiveSyntax 1211/// ::= .syntax unified | divided 1212bool ARMAsmParser::ParseDirectiveSyntax(SMLoc L) { 1213 const AsmToken &Tok = Parser.getTok(); 1214 if (Tok.isNot(AsmToken::Identifier)) 1215 return Error(L, "unexpected token in .syntax directive"); 1216 StringRef Mode = Tok.getString(); 1217 if (Mode == "unified" || Mode == "UNIFIED") 1218 Parser.Lex(); 1219 else if (Mode == "divided" || Mode == "DIVIDED") 1220 Parser.Lex(); 1221 else 1222 return Error(L, "unrecognized syntax mode in .syntax directive"); 1223 1224 if (getLexer().isNot(AsmToken::EndOfStatement)) 1225 return Error(Parser.getTok().getLoc(), "unexpected token in directive"); 1226 Parser.Lex(); 1227 1228 // TODO tell the MC streamer the mode 1229 // getParser().getStreamer().Emit???(); 1230 return false; 1231} 1232 1233/// ParseDirectiveCode 1234/// ::= .code 16 | 32 1235bool ARMAsmParser::ParseDirectiveCode(SMLoc L) { 1236 const AsmToken &Tok = Parser.getTok(); 1237 if (Tok.isNot(AsmToken::Integer)) 1238 return Error(L, "unexpected token in .code directive"); 1239 int64_t Val = Parser.getTok().getIntVal(); 1240 if (Val == 16) 1241 Parser.Lex(); 1242 else if (Val == 32) 1243 Parser.Lex(); 1244 else 1245 return Error(L, "invalid operand to .code directive"); 1246 1247 if (getLexer().isNot(AsmToken::EndOfStatement)) 1248 return Error(Parser.getTok().getLoc(), "unexpected token in directive"); 1249 Parser.Lex(); 1250 1251 if (Val == 16) 1252 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16); 1253 else 1254 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32); 1255 1256 return false; 1257} 1258 1259extern "C" void LLVMInitializeARMAsmLexer(); 1260 1261/// Force static initialization. 1262extern "C" void LLVMInitializeARMAsmParser() { 1263 RegisterAsmParser<ARMAsmParser> X(TheARMTarget); 1264 RegisterAsmParser<ARMAsmParser> Y(TheThumbTarget); 1265 LLVMInitializeARMAsmLexer(); 1266} 1267 1268#define GET_REGISTER_MATCHER 1269#define GET_MATCHER_IMPLEMENTATION 1270#include "ARMGenAsmMatcher.inc" 1271