};
namespace {
- struct ARMOperand;
+
+class ARMOperand;
class ARMAsmParser : public TargetAsmParser {
MCAsmParser &Parser;
TargetMachine &TM;
-private:
MCAsmParser &getParser() const { return Parser; }
-
MCAsmLexer &getLexer() const { return Parser.getLexer(); }
void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
-
bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
int TryParseRegister();
ARMOperand *TryParseRegisterWithWriteBack();
ARMOperand *ParseRegisterList();
ARMOperand *ParseMemory();
+ ARMOperand *ParseOperand();
bool ParseMemoryOffsetReg(bool &Negative,
bool &OffsetRegShifted,
bool &OffsetIsReg,
int &OffsetRegNum,
SMLoc &E);
-
bool ParseShift(enum ShiftType &St, const MCExpr *&ShiftAmount, SMLoc &E);
-
- ARMOperand *ParseOperand();
-
bool ParseDirectiveWord(unsigned Size, SMLoc L);
-
bool ParseDirectiveThumb(SMLoc L);
-
bool ParseDirectiveThumbFunc(SMLoc L);
-
bool ParseDirectiveCode(SMLoc L);
-
bool ParseDirectiveSyntax(SMLoc L);
bool MatchAndEmitInstruction(SMLoc IDLoc,
/// }
-
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
/// ARMOperand - Instances of this class represent a parsed ARM machine
/// instruction.
-struct ARMOperand : public MCParsedAsmOperand {
-public:
+class ARMOperand : public MCParsedAsmOperand {
enum KindTy {
CondCode,
Immediate,
Memory,
Register,
+ RegisterList,
Token
} Kind;
bool Writeback;
} Reg;
+ struct {
+ SmallVector<unsigned, 32> *Registers;
+ } RegList;
+
struct {
const MCExpr *Val;
} Imm;
// This is for all forms of ARM address expressions
struct {
unsigned BaseRegNum;
- unsigned OffsetRegNum; // used when OffsetIsReg is true
- const MCExpr *Offset; // used when OffsetIsReg is false
- const MCExpr *ShiftAmount; // used when OffsetRegShifted is true
- enum ShiftType ShiftType; // used when OffsetRegShifted is true
- unsigned
- OffsetRegShifted : 1, // only used when OffsetIsReg is true
- Preindexed : 1,
- Postindexed : 1,
- OffsetIsReg : 1,
- Negative : 1, // only used when OffsetIsReg is true
- Writeback : 1;
+ unsigned OffsetRegNum; // used when OffsetIsReg is true
+ const MCExpr *Offset; // used when OffsetIsReg is false
+ const MCExpr *ShiftAmount; // used when OffsetRegShifted is true
+ enum ShiftType ShiftType; // used when OffsetRegShifted is true
+ unsigned OffsetRegShifted : 1; // only used when OffsetIsReg is true
+ unsigned Preindexed : 1;
+ unsigned Postindexed : 1;
+ unsigned OffsetIsReg : 1;
+ unsigned Negative : 1; // only used when OffsetIsReg is true
+ unsigned Writeback : 1;
} Mem;
-
};
+ ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
+public:
ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
Kind = o.Kind;
StartLoc = o.StartLoc;
case Register:
Reg = o.Reg;
break;
+ case RegisterList:
+ RegList = o.RegList;
+ break;
case Immediate:
Imm = o.Imm;
break;
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;
}
+ const SmallVectorImpl<unsigned> &getRegList() const {
+ assert(Kind == RegisterList && "Invalid access!");
+ return *RegList.Registers;
+ }
+
const MCExpr *getImm() const {
assert(Kind == Immediate && "Invalid access!");
return Imm.Val;
bool isCondCode() const { return Kind == CondCode; }
bool isImm() const { return Kind == Immediate; }
bool isReg() const { return Kind == Register; }
+ 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(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
+ SMLoc S, SMLoc E) {
+ ARMOperand *Op = new ARMOperand(RegisterList);
+ 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;
+ }
+
static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
ARMOperand *Op = new ARMOperand(Immediate);
Op->Imm.Val = Val;
Op->EndLoc = E;
return Op;
}
-
-private:
- ARMOperand(KindTy K) : Kind(K) {}
};
} // end anonymous namespace.
case Register:
OS << "<register " << getReg() << ">";
break;
+ case RegisterList: {
+ OS << "<register_list ";
+
+ 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 << ">";
+ break;
+ }
case Token:
OS << "'" << getToken() << "'";
break;
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.
/// of the mnemonic.
ARMOperand *ARMAsmParser::ParseOperand() {
SMLoc S, E;
-
switch (getLexer().getKind()) {
+ default:
+ Error(Parser.getTok().getLoc(), "unexpected token in operand");
+ return 0;
case AsmToken::Identifier:
if (ARMOperand *Op = TryParseRegisterWithWriteBack())
return Op;
return 0;
E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
return ARMOperand::CreateImm(ImmVal, S, E);
- default:
- Error(Parser.getTok().getLoc(), "unexpected token in operand");
- return 0;
}
}
Parser.EatToEndOfStatement();
return TokError("unexpected token in argument list");
}
+
Parser.Lex(); // Consume the EndOfStatement
return false;
}
case Match_Success:
Out.EmitInstruction(Inst);
return false;
-
case Match_MissingFeature:
Error(IDLoc, "instruction requires a CPU feature not currently enabled");
return true;
}
llvm_unreachable("Implement any new match types added!");
+ return true;
}
-
-
/// ParseDirective parses the arm specific directives
bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
StringRef IDVal = DirectiveID.getIdentifier();