//===----------------------------------------------------------------------===//
#include "MCTargetDesc/SparcMCTargetDesc.h"
+#include "MCTargetDesc/SparcMCExpr.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCInst.h"
SmallVectorImpl<MCParsedAsmOperand*> &Operands);
bool ParseDirective(AsmToken DirectiveID);
+ virtual unsigned validateTargetOperandClass(MCParsedAsmOperand *Op,
+ unsigned Kind);
// Custom parse functions for Sparc specific operands.
OperandMatchResultTy
parseSparcAsmOperand(SparcOperand *&Operand);
// returns true if Tok is matched to a register and returns register in RegNo.
- bool matchRegisterName(const AsmToken &Tok, unsigned &RegNo, bool isDFP,
- bool isQFP);
+ bool matchRegisterName(const AsmToken &Tok, unsigned &RegNo,
+ unsigned &RegKind);
+ bool matchSparcAsmModifiers(const MCExpr *&EVal, SMLoc &EndLoc);
+ bool parseDirectiveWord(unsigned Size, SMLoc L);
+
+ bool is64Bit() const { return STI.getTargetTriple().startswith("sparcv9"); }
public:
SparcAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
const MCInstrInfo &MII)
static unsigned QuadFPRegs[32] = {
Sparc::Q0, Sparc::Q1, Sparc::Q2, Sparc::Q3,
Sparc::Q4, Sparc::Q5, Sparc::Q6, Sparc::Q7,
- Sparc::Q8, Sparc::Q7, Sparc::Q8, Sparc::Q9,
+ Sparc::Q8, Sparc::Q9, Sparc::Q10, Sparc::Q11,
Sparc::Q12, Sparc::Q13, Sparc::Q14, Sparc::Q15 };
bool isMEMrr() const { return Kind == k_MemoryReg; }
bool isMEMri() const { return Kind == k_MemoryImm; }
+ bool isFloatReg() const {
+ return (Kind == k_Register && Reg.Kind == rk_FloatReg);
+ }
+
+ bool isFloatOrDoubleReg() const {
+ return (Kind == k_Register && (Reg.Kind == rk_FloatReg
+ || Reg.Kind == rk_DoubleReg));
+ }
+
+
StringRef getToken() const {
assert(Kind == k_Token && "Invalid access!");
return StringRef(Tok.Data, Tok.Length);
}
static SparcOperand *CreateReg(unsigned RegNum,
- SparcOperand::RegisterKind Kind,
+ unsigned Kind,
SMLoc S, SMLoc E) {
SparcOperand *Op = new SparcOperand(k_Register);
Op->Reg.RegNum = RegNum;
- Op->Reg.Kind = Kind;
+ Op->Reg.Kind = (SparcOperand::RegisterKind)Kind;
Op->StartLoc = S;
Op->EndLoc = E;
return Op;
return Op;
}
+ static SparcOperand *MorphToDoubleReg(SparcOperand *Op) {
+ unsigned Reg = Op->getReg();
+ assert(Op->Reg.Kind == rk_FloatReg);
+ unsigned regIdx = Reg - Sparc::F0;
+ if (regIdx % 2 || regIdx > 31)
+ return 0;
+ Op->Reg.RegNum = DoubleRegs[regIdx / 2];
+ Op->Reg.Kind = rk_DoubleReg;
+ return Op;
+ }
+
+ static SparcOperand *MorphToQuadReg(SparcOperand *Op) {
+ unsigned Reg = Op->getReg();
+ unsigned regIdx = 0;
+ switch (Op->Reg.Kind) {
+ default: assert(0 && "Unexpected register kind!");
+ case rk_FloatReg:
+ regIdx = Reg - Sparc::F0;
+ if (regIdx % 4 || regIdx > 31)
+ return 0;
+ Reg = QuadFPRegs[regIdx / 4];
+ break;
+ case rk_DoubleReg:
+ regIdx = Reg - Sparc::D0;
+ if (regIdx % 2 || regIdx > 31)
+ return 0;
+ Reg = QuadFPRegs[regIdx / 2];
+ break;
+ }
+ Op->Reg.RegNum = Reg;
+ Op->Reg.Kind = rk_QuadReg;
+ return Op;
+ }
+
static SparcOperand *MorphToMEMrr(unsigned Base, SparcOperand *Op) {
unsigned offsetReg = Op->getReg();
Op->Kind = k_MemoryReg;
case Match_Success: {
Inst.setLoc(IDLoc);
- Out.EmitInstruction(Inst);
+ Out.EmitInstruction(Inst, STI);
return false;
}
if (getLexer().getKind() != AsmToken::Percent)
return false;
Parser.Lex();
- if (matchRegisterName(Tok, RegNo, false, false)) {
+ unsigned regKind = SparcOperand::rk_None;
+ if (matchRegisterName(Tok, RegNo, regKind)) {
Parser.Lex();
return false;
}
bool SparcAsmParser::
ParseDirective(AsmToken DirectiveID)
{
- // Ignore all directives for now.
- Parser.eatToEndOfStatement();
+ StringRef IDVal = DirectiveID.getString();
+
+ if (IDVal == ".byte")
+ return parseDirectiveWord(1, DirectiveID.getLoc());
+
+ if (IDVal == ".half")
+ return parseDirectiveWord(2, DirectiveID.getLoc());
+
+ if (IDVal == ".word")
+ return parseDirectiveWord(4, DirectiveID.getLoc());
+
+ if (IDVal == ".nword")
+ return parseDirectiveWord(is64Bit() ? 8 : 4, DirectiveID.getLoc());
+
+ if (is64Bit() && IDVal == ".xword")
+ return parseDirectiveWord(8, DirectiveID.getLoc());
+
+ if (IDVal == ".register") {
+ // For now, ignore .register directive.
+ Parser.eatToEndOfStatement();
+ return false;
+ }
+
+ // Let the MC layer to handle other directives.
+ return true;
+}
+
+bool SparcAsmParser:: parseDirectiveWord(unsigned Size, SMLoc L) {
+ if (getLexer().isNot(AsmToken::EndOfStatement)) {
+ for (;;) {
+ const MCExpr *Value;
+ if (getParser().parseExpression(Value))
+ return true;
+
+ getParser().getStreamer().EmitValue(Value, Size);
+
+ if (getLexer().is(AsmToken::EndOfStatement))
+ break;
+
+ // FIXME: Improve diagnostic.
+ if (getLexer().isNot(AsmToken::Comma))
+ return Error(L, "unexpected token in directive");
+ Parser.Lex();
+ }
+ }
+ Parser.Lex();
return false;
}
switch (getLexer().getKind()) {
default: return MatchOperand_NoMatch;
+ case AsmToken::Comma:
case AsmToken::RBrac:
case AsmToken::EndOfStatement:
Operands.push_back(SparcOperand::CreateMEMri(BaseReg, 0, S, E));
Parser.getTok().getLoc()));
Parser.Lex(); // Eat the [
- ResTy = parseMEMOperand(Operands);
+ if (Mnemonic == "cas" || Mnemonic == "casx") {
+ SMLoc S = Parser.getTok().getLoc();
+ if (getLexer().getKind() != AsmToken::Percent)
+ return MatchOperand_NoMatch;
+ Parser.Lex(); // eat %
+
+ unsigned RegNo, RegKind;
+ if (!matchRegisterName(Parser.getTok(), RegNo, RegKind))
+ return MatchOperand_NoMatch;
+
+ Parser.Lex(); // Eat the identifier token.
+ SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer()-1);
+ Operands.push_back(SparcOperand::CreateReg(RegNo, RegKind, S, E));
+ ResTy = MatchOperand_Success;
+ } else {
+ ResTy = parseMEMOperand(Operands);
+ }
+
if (ResTy != MatchOperand_Success)
return ResTy;
case AsmToken::Percent:
Parser.Lex(); // Eat the '%'.
unsigned RegNo;
- if (matchRegisterName(Parser.getTok(), RegNo, false, false)) {
+ unsigned RegKind;
+ if (matchRegisterName(Parser.getTok(), RegNo, RegKind)) {
+ StringRef name = Parser.getTok().getString();
Parser.Lex(); // Eat the identifier token.
- Op = SparcOperand::CreateReg(RegNo, SparcOperand::rk_None, S, E);
+ E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
+ switch (RegNo) {
+ default:
+ Op = SparcOperand::CreateReg(RegNo, RegKind, S, E);
+ break;
+ case Sparc::Y:
+ Op = SparcOperand::CreateToken("%y", S);
+ break;
+
+ case Sparc::ICC:
+ if (name == "xcc")
+ Op = SparcOperand::CreateToken("%xcc", S);
+ else
+ Op = SparcOperand::CreateToken("%icc", S);
+ break;
+
+ case Sparc::FCC:
+ assert(name == "fcc0" && "Cannot handle %fcc other than %fcc0 yet");
+ Op = SparcOperand::CreateToken("%fcc0", S);
+ break;
+ }
break;
}
- // FIXME: Handle modifiers like %hi, %lo etc.,
+ if (matchSparcAsmModifiers(EVal, E)) {
+ E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
+ Op = SparcOperand::CreateImm(EVal, S, E);
+ }
break;
case AsmToken::Minus:
case AsmToken::Integer:
- if (!getParser().parseExpression(EVal))
+ if (!getParser().parseExpression(EVal, E))
Op = SparcOperand::CreateImm(EVal, S, E);
break;
case AsmToken::Identifier: {
StringRef Identifier;
if (!getParser().parseIdentifier(Identifier)) {
- SMLoc E = SMLoc::getFromPointer(Parser.getTok().
- getLoc().getPointer() - 1);
+ E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
MCSymbol *Sym = getContext().GetOrCreateSymbol(Identifier);
const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
getContext());
-
Op = SparcOperand::CreateImm(Res, S, E);
}
break;
bool SparcAsmParser::matchRegisterName(const AsmToken &Tok,
unsigned &RegNo,
- bool isDFP,
- bool isQFP)
+ unsigned &RegKind)
{
int64_t intVal = 0;
RegNo = 0;
+ RegKind = SparcOperand::rk_None;
if (Tok.is(AsmToken::Identifier)) {
StringRef name = Tok.getString();
// %fp
if (name.equals("fp")) {
RegNo = Sparc::I6;
+ RegKind = SparcOperand::rk_IntReg;
return true;
}
// %sp
if (name.equals("sp")) {
RegNo = Sparc::O6;
+ RegKind = SparcOperand::rk_IntReg;
return true;
}
if (name.equals("y")) {
RegNo = Sparc::Y;
+ RegKind = SparcOperand::rk_Y;
return true;
}
if (name.equals("icc")) {
RegNo = Sparc::ICC;
+ RegKind = SparcOperand::rk_CCReg;
return true;
}
if (name.equals("xcc")) {
// FIXME:: check 64bit.
RegNo = Sparc::ICC;
+ RegKind = SparcOperand::rk_CCReg;
return true;
}
&& intVal < 4) {
// FIXME: check 64bit and handle %fcc1 - %fcc3
RegNo = Sparc::FCC;
+ RegKind = SparcOperand::rk_CCReg;
return true;
}
&& !name.substr(1).getAsInteger(10, intVal)
&& intVal < 8) {
RegNo = IntRegs[intVal];
+ RegKind = SparcOperand::rk_IntReg;
return true;
}
// %o0 - %o7
&& !name.substr(1).getAsInteger(10, intVal)
&& intVal < 8) {
RegNo = IntRegs[8 + intVal];
+ RegKind = SparcOperand::rk_IntReg;
return true;
}
if (name.substr(0, 1).equals_lower("l")
&& !name.substr(1).getAsInteger(10, intVal)
&& intVal < 8) {
RegNo = IntRegs[16 + intVal];
+ RegKind = SparcOperand::rk_IntReg;
return true;
}
if (name.substr(0, 1).equals_lower("i")
&& !name.substr(1).getAsInteger(10, intVal)
&& intVal < 8) {
RegNo = IntRegs[24 + intVal];
+ RegKind = SparcOperand::rk_IntReg;
return true;
}
// %f0 - %f31
if (name.substr(0, 1).equals_lower("f")
&& !name.substr(1, 2).getAsInteger(10, intVal) && intVal < 32) {
- if (isDFP && (intVal%2 == 0)) {
- RegNo = DoubleRegs[intVal/2];
- } else if (isQFP && (intVal%4 == 0)) {
- RegNo = QuadFPRegs[intVal/4];
- } else {
- RegNo = FloatRegs[intVal];
- }
+ RegNo = FloatRegs[intVal];
+ RegKind = SparcOperand::rk_FloatReg;
return true;
}
// %f32 - %f62
if (name.substr(0, 1).equals_lower("f")
&& !name.substr(1, 2).getAsInteger(10, intVal)
&& intVal >= 32 && intVal <= 62 && (intVal % 2 == 0)) {
- if (isDFP) {
- RegNo = DoubleRegs[16 + intVal/2];
- } else if (isQFP && (intVal % 4 == 0)) {
- RegNo = QuadFPRegs[8 + intVal/4];
- } else {
- return false;
- }
+ // FIXME: Check V9
+ RegNo = DoubleRegs[intVal/2];
+ RegKind = SparcOperand::rk_DoubleReg;
return true;
}
if (name.substr(0, 1).equals_lower("r")
&& !name.substr(1, 2).getAsInteger(10, intVal) && intVal < 31) {
RegNo = IntRegs[intVal];
+ RegKind = SparcOperand::rk_IntReg;
return true;
}
}
}
+bool SparcAsmParser::matchSparcAsmModifiers(const MCExpr *&EVal,
+ SMLoc &EndLoc)
+{
+ AsmToken Tok = Parser.getTok();
+ if (!Tok.is(AsmToken::Identifier))
+ return false;
+
+ StringRef name = Tok.getString();
+
+ SparcMCExpr::VariantKind VK = SparcMCExpr::parseVariantKind(name);
+
+ if (VK == SparcMCExpr::VK_Sparc_None)
+ return false;
+
+ Parser.Lex(); // Eat the identifier.
+ if (Parser.getTok().getKind() != AsmToken::LParen)
+ return false;
+
+ Parser.Lex(); // Eat the LParen token.
+ const MCExpr *subExpr;
+ if (Parser.parseParenExpression(subExpr, EndLoc))
+ return false;
+ EVal = SparcMCExpr::Create(VK, subExpr, getContext());
+ return true;
+}
+
extern "C" void LLVMInitializeSparcAsmParser() {
RegisterMCAsmParser<SparcAsmParser> A(TheSparcTarget);
#define GET_REGISTER_MATCHER
#define GET_MATCHER_IMPLEMENTATION
#include "SparcGenAsmMatcher.inc"
+
+
+
+unsigned SparcAsmParser::
+validateTargetOperandClass(MCParsedAsmOperand *GOp,
+ unsigned Kind)
+{
+ SparcOperand *Op = (SparcOperand*)GOp;
+ if (Op->isFloatOrDoubleReg()) {
+ switch (Kind) {
+ default: break;
+ case MCK_DFPRegs:
+ if (!Op->isFloatReg() || SparcOperand::MorphToDoubleReg(Op))
+ return MCTargetAsmParser::Match_Success;
+ break;
+ case MCK_QFPRegs:
+ if (SparcOperand::MorphToQuadReg(Op))
+ return MCTargetAsmParser::Match_Success;
+ break;
+ }
+ }
+ return Match_InvalidOperand;
+}