/// }
-
public:
ARMAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &_TM)
: TargetAsmParser(T), Parser(_Parser), TM(_TM) {
virtual bool ParseInstruction(StringRef Name, SMLoc NameLoc,
SmallVectorImpl<MCParsedAsmOperand*> &Operands);
-
virtual bool ParseDirective(AsmToken DirectiveID);
};
} // end anonymous namespace
bool Writeback;
} Reg;
- struct {
- unsigned RegStart;
- unsigned Number;
+ struct {
+ SmallVector<unsigned, 32> *Registers;
} RegList;
struct {
break;
}
}
+ ~ARMOperand() {
+ if (isRegList())
+ delete RegList.Registers;
+ }
/// getStartLoc - Get the location of the first token of this operand.
SMLoc getStartLoc() const { return StartLoc; }
return Reg.RegNum;
}
- std::pair<unsigned, unsigned> getRegList() const {
+ const SmallVectorImpl<unsigned> &getRegList() const {
assert(Kind == RegisterList && "Invalid access!");
- return std::make_pair(RegList.RegStart, RegList.Number);
+ return *RegList.Registers;
}
const MCExpr *getImm() const {
bool isRegList() const { return Kind == RegisterList; }
bool isToken() const { return Kind == Token; }
bool isMemory() const { return Kind == Memory; }
+ bool isMemMode5() const {
+ if (!isMemory() || Mem.OffsetIsReg || Mem.OffsetRegShifted ||
+ Mem.Writeback || Mem.Negative)
+ return false;
+ // If there is an offset expression, make sure it's valid.
+ if (!Mem.Offset)
+ return true;
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Mem.Offset);
+ if (!CE)
+ return false;
+ // The offset must be a multiple of 4 in the range 0-1020.
+ int64_t Value = CE->getValue();
+ return ((Value & 0x3) == 0 && Value <= 1020 && Value >= -1020);
+ }
void addExpr(MCInst &Inst, const MCExpr *Expr) const {
// Add as immediates when possible. Null MCExpr = 0.
Inst.addOperand(MCOperand::CreateReg(getReg()));
}
- void addImmOperands(MCInst &Inst, unsigned N) const {
+ void addRegListOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
- addExpr(Inst, getImm());
+ const SmallVectorImpl<unsigned> &RegList = getRegList();
+ for (SmallVectorImpl<unsigned>::const_iterator
+ I = RegList.begin(), E = RegList.end(); I != E; ++I)
+ Inst.addOperand(MCOperand::CreateReg(*I));
}
- bool isMemMode5() const {
- if (!isMemory() || Mem.OffsetIsReg || Mem.OffsetRegShifted ||
- Mem.Writeback || Mem.Negative)
- return false;
- // If there is an offset expression, make sure it's valid.
- if (!Mem.Offset)
- return true;
- const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Mem.Offset);
- if (!CE)
- return false;
- // The offset must be a multiple of 4 in the range 0-1020.
- int64_t Value = CE->getValue();
- return ((Value & 0x3) == 0 && Value <= 1020 && Value >= -1020);
+ void addImmOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ addExpr(Inst, getImm());
}
void addMemMode5Operands(MCInst &Inst, unsigned N) const {
return Op;
}
- static ARMOperand *CreateRegList(unsigned RegStart, unsigned Number,
- SMLoc S, SMLoc E) {
+ static ARMOperand *
+ CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
+ SMLoc S, SMLoc E) {
ARMOperand *Op = new ARMOperand(RegisterList);
- Op->RegList.RegStart = RegStart;
- Op->RegList.Number = Number;
+ Op->RegList.Registers = new SmallVector<unsigned, 32>();
+ for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
+ I = Regs.begin(), E = Regs.end(); I != E; ++I)
+ Op->RegList.Registers->push_back(I->first);
+ std::sort(Op->RegList.Registers->begin(), Op->RegList.Registers->end());
Op->StartLoc = S;
Op->EndLoc = E;
return Op;
break;
case RegisterList: {
OS << "<register_list ";
- std::pair<unsigned, unsigned> List = getRegList();
- unsigned RegEnd = List.first + List.second;
- for (unsigned Idx = List.first; Idx < RegEnd; ) {
- OS << Idx;
- if (++Idx < RegEnd) OS << ", ";
+ const SmallVectorImpl<unsigned> &RegList = getRegList();
+ for (SmallVectorImpl<unsigned>::const_iterator
+ I = RegList.begin(), E = RegList.end(); I != E; ) {
+ OS << *I;
+ if (++I < E) OS << ", ";
}
OS << ">";
ARMOperand *ARMAsmParser::TryParseRegisterWithWriteBack() {
SMLoc S = Parser.getTok().getLoc();
int RegNo = TryParseRegister();
- if (RegNo == -1) return 0;
+ if (RegNo == -1)
+ return 0;
SMLoc E = Parser.getTok().getLoc();
/// Parse a register list, return it if successful else return null. The first
/// token must be a '{' when called.
ARMOperand *ARMAsmParser::ParseRegisterList() {
- SMLoc S, E;
assert(Parser.getTok().is(AsmToken::LCurly) &&
"Token is not a Left Curly Brace");
- S = Parser.getTok().getLoc();
- Parser.Lex(); // Eat left curly brace token.
-
- const AsmToken &RegTok = Parser.getTok();
- SMLoc RegLoc = RegTok.getLoc();
- if (RegTok.isNot(AsmToken::Identifier)) {
- Error(RegLoc, "register expected");
- return 0;
- }
- int RegNum = TryParseRegister();
- if (RegNum == -1) {
- Error(RegLoc, "register expected");
- return 0;
- }
+ SMLoc S = Parser.getTok().getLoc();
- unsigned RegList = 1 << RegNum;
+ // Read the rest of the registers in the list.
+ unsigned PrevRegNum = 0;
+ SmallVector<std::pair<unsigned, SMLoc>, 32> Registers;
- int HighRegNum = RegNum;
- // TODO ranges like "{Rn-Rm}"
- while (Parser.getTok().is(AsmToken::Comma)) {
- Parser.Lex(); // Eat comma token.
+ do {
+ bool IsRange = Parser.getTok().is(AsmToken::Minus);
+ Parser.Lex(); // Eat non-identifier token.
const AsmToken &RegTok = Parser.getTok();
SMLoc RegLoc = RegTok.getLoc();
Error(RegLoc, "register expected");
return 0;
}
+
int RegNum = TryParseRegister();
if (RegNum == -1) {
Error(RegLoc, "register expected");
return 0;
}
- if (RegList & (1 << RegNum))
- Warning(RegLoc, "register duplicated in register list");
- else if (RegNum <= HighRegNum)
- Warning(RegLoc, "register not in ascending order in register list");
- RegList |= 1 << RegNum;
- HighRegNum = RegNum;
- }
+ if (IsRange) {
+ int Reg = PrevRegNum;
+ do {
+ ++Reg;
+ Registers.push_back(std::make_pair(Reg, RegLoc));
+ } while (Reg != RegNum);
+ } else {
+ Registers.push_back(std::make_pair(RegNum, RegLoc));
+ }
+
+ PrevRegNum = RegNum;
+ } while (Parser.getTok().is(AsmToken::Comma) ||
+ Parser.getTok().is(AsmToken::Minus));
+
+ // Process the right curly brace of the list.
const AsmToken &RCurlyTok = Parser.getTok();
if (RCurlyTok.isNot(AsmToken::RCurly)) {
Error(RCurlyTok.getLoc(), "'}' expected");
return 0;
}
- E = RCurlyTok.getLoc();
- Parser.Lex(); // Eat left curly brace token.
- // FIXME: Need to return an operand!
- Error(E, "FIXME: register list parsing not implemented");
- return 0;
+ SMLoc E = RCurlyTok.getLoc();
+ Parser.Lex(); // Eat right curly brace token.
+
+ // Verify the register list.
+ SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
+ RI = Registers.begin(), RE = Registers.end();
+
+ unsigned HighRegNum = RI->first;
+ DenseMap<unsigned, bool> RegMap;
+ RegMap[RI->first] = true;
+
+ for (++RI; RI != RE; ++RI) {
+ const std::pair<unsigned, SMLoc> &RegInfo = *RI;
+
+ if (RegMap[RegInfo.first]) {
+ Error(RegInfo.second, "register duplicated in register list");
+ return 0;
+ }
+
+ if (RegInfo.first < HighRegNum)
+ Warning(RegInfo.second,
+ "register not in ascending order in register list");
+
+ RegMap[RegInfo.first] = true;
+ HighRegNum = std::max(RegInfo.first, HighRegNum);
+ }
+
+ return ARMOperand::CreateRegList(Registers, S, E);
}
-/// Parse an arm memory expression, return false if successful else return true
+/// Parse an ARM memory expression, return false if successful else return true
/// or an error. The first token must be a '[' when called.
/// TODO Only preindexing and postindexing addressing are started, unindexed
/// with option, etc are still to do.