summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVenkatraman Govindaraju <venkatra@cs.wisc.edu>2014-01-07 01:49:11 +0000
committerVenkatraman Govindaraju <venkatra@cs.wisc.edu>2014-01-07 01:49:11 +0000
commita16f1ce2d9e2849a020a4c2ce45efc7a29ca2edb (patch)
treeffb53fff75aac621976b90bd094a4e5b012b6049
parentced88c5918851fb6b34c247471a7d2b62f806a01 (diff)
downloadllvm-a16f1ce2d9e2849a020a4c2ce45efc7a29ca2edb.tar.gz
llvm-a16f1ce2d9e2849a020a4c2ce45efc7a29ca2edb.tar.bz2
llvm-a16f1ce2d9e2849a020a4c2ce45efc7a29ca2edb.tar.xz
[Sparc] Add support for parsing memory operands in sparc AsmParser.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@198658 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Target/Sparc/AsmParser/SparcAsmParser.cpp166
-rw-r--r--lib/Target/Sparc/SparcInstrInfo.td4
-rw-r--r--test/MC/Sparc/sparc-ctrl-instructions.s23
-rw-r--r--test/MC/Sparc/sparc-mem-instructions.s58
4 files changed, 202 insertions, 49 deletions
diff --git a/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp b/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
index d34678d401..13f62666fc 100644
--- a/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
+++ b/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
@@ -28,6 +28,7 @@ namespace llvm {
}
namespace {
+class SparcOperand;
class SparcAsmParser : public MCTargetAsmParser {
MCSubtargetInfo &STI;
@@ -55,18 +56,15 @@ class SparcAsmParser : public MCTargetAsmParser {
// Custom parse functions for Sparc specific operands.
OperandMatchResultTy
- parseMEMrrOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
- OperandMatchResultTy
- parseMEMriOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
-
- OperandMatchResultTy
- parseMEMOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
- int ImmOffsetOrReg);
+ parseMEMOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
OperandMatchResultTy
parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
StringRef Name);
+ 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);
@@ -298,7 +296,35 @@ public:
return Op;
}
+ static SparcOperand *MorphToMEMrr(unsigned Base, SparcOperand *Op) {
+ unsigned offsetReg = Op->getReg();
+ Op->Kind = k_MemoryReg;
+ Op->Mem.Base = Base;
+ Op->Mem.OffsetReg = offsetReg;
+ Op->Mem.Off = 0;
+ return Op;
+ }
+ static SparcOperand *CreateMEMri(unsigned Base,
+ const MCExpr *Off,
+ SMLoc S, SMLoc E) {
+ SparcOperand *Op = new SparcOperand(k_MemoryImm);
+ Op->Mem.Base = Base;
+ Op->Mem.OffsetReg = 0;
+ Op->Mem.Off = Off;
+ Op->StartLoc = S;
+ Op->EndLoc = E;
+ return Op;
+ }
+
+ static SparcOperand *MorphToMEMri(unsigned Base, SparcOperand *Op) {
+ const MCExpr *Imm = Op->getImm();
+ Op->Kind = k_MemoryImm;
+ Op->Mem.Base = Base;
+ Op->Mem.OffsetReg = 0;
+ Op->Mem.Off = Imm;
+ return Op;
+ }
};
} // end namespace
@@ -412,43 +438,99 @@ ParseDirective(AsmToken DirectiveID)
}
SparcAsmParser::OperandMatchResultTy SparcAsmParser::
-parseMEMOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
- int ImmOffsetOrReg)
+parseMEMOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands)
{
- // FIXME: Implement memory operand parsing here.
- return MatchOperand_NoMatch;
-}
-SparcAsmParser::OperandMatchResultTy SparcAsmParser::
-parseMEMrrOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands)
-{
- return parseMEMOperand(Operands, 2);
-}
+ SMLoc S, E;
+ unsigned BaseReg = 0;
-SparcAsmParser::OperandMatchResultTy SparcAsmParser::
-parseMEMriOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands)
-{
- return parseMEMOperand(Operands, 1);
+ if (ParseRegister(BaseReg, S, E)) {
+ return MatchOperand_NoMatch;
+ }
+
+ switch (getLexer().getKind()) {
+ default: return MatchOperand_NoMatch;
+
+ case AsmToken::RBrac:
+ case AsmToken::EndOfStatement:
+ Operands.push_back(SparcOperand::CreateMEMri(BaseReg, 0, S, E));
+ return MatchOperand_Success;
+
+ case AsmToken:: Plus:
+ Parser.Lex(); // Eat the '+'
+ break;
+ case AsmToken::Minus:
+ break;
+ }
+
+ SparcOperand *Offset = 0;
+ OperandMatchResultTy ResTy = parseSparcAsmOperand(Offset);
+ if (ResTy != MatchOperand_Success || !Offset)
+ return MatchOperand_NoMatch;
+
+ Offset = (Offset->isImm()
+ ? SparcOperand::MorphToMEMri(BaseReg, Offset)
+ : SparcOperand::MorphToMEMrr(BaseReg, Offset));
+
+ Operands.push_back(Offset);
+ return MatchOperand_Success;
}
SparcAsmParser::OperandMatchResultTy SparcAsmParser::
parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
StringRef Mnemonic)
{
+
OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
- if (ResTy == MatchOperand_Success)
- return ResTy;
+
// If there wasn't a custom match, try the generic matcher below. Otherwise,
// there was a match, but an error occurred, in which case, just return that
// the operand parsing failed.
- if (ResTy == MatchOperand_ParseFail)
+ if (ResTy == MatchOperand_Success || ResTy == MatchOperand_ParseFail)
return ResTy;
+ if (getLexer().is(AsmToken::LBrac)) {
+ // Memory operand
+ Operands.push_back(SparcOperand::CreateToken("[",
+ Parser.getTok().getLoc()));
+ Parser.Lex(); // Eat the [
+
+ ResTy = parseMEMOperand(Operands);
+ if (ResTy != MatchOperand_Success)
+ return ResTy;
+
+ if (!getLexer().is(AsmToken::RBrac))
+ return MatchOperand_ParseFail;
+
+ Operands.push_back(SparcOperand::CreateToken("]",
+ Parser.getTok().getLoc()));
+ Parser.Lex(); // Eat the ]
+ return MatchOperand_Success;
+ }
+
+ SparcOperand *Op = 0;
+ ResTy = parseSparcAsmOperand(Op);
+ if (ResTy != MatchOperand_Success || !Op)
+ return MatchOperand_ParseFail;
+
+ // Push the parsed operand into the list of operands
+ Operands.push_back(Op);
+
+ return MatchOperand_Success;
+}
+
+SparcAsmParser::OperandMatchResultTy
+SparcAsmParser::parseSparcAsmOperand(SparcOperand *&Op)
+{
+
SMLoc S = Parser.getTok().getLoc();
SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
const MCExpr *EVal;
- SparcOperand *Op;
+
+ Op = 0;
switch (getLexer().getKind()) {
+ default: break;
+
case AsmToken::Percent:
Parser.Lex(); // Eat the '%'.
unsigned RegNo;
@@ -458,40 +540,30 @@ parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
break;
}
// FIXME: Handle modifiers like %hi, %lo etc.,
- return MatchOperand_ParseFail;
+ break;
case AsmToken::Minus:
case AsmToken::Integer:
- if (getParser().parseExpression(EVal))
- return MatchOperand_ParseFail;
-
- Op = SparcOperand::CreateImm(EVal, S, E);
+ if (!getParser().parseExpression(EVal))
+ Op = SparcOperand::CreateImm(EVal, S, E);
break;
case AsmToken::Identifier: {
StringRef Identifier;
- if (getParser().parseIdentifier(Identifier))
- return MatchOperand_ParseFail;
- SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
- MCSymbol *Sym = getContext().GetOrCreateSymbol(Identifier);
+ if (!getParser().parseIdentifier(Identifier)) {
+ SMLoc E = SMLoc::getFromPointer(Parser.getTok().
+ getLoc().getPointer() - 1);
+ MCSymbol *Sym = getContext().GetOrCreateSymbol(Identifier);
- // Otherwise create a symbol reference.
- const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
- getContext());
+ const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
+ getContext());
- Op = SparcOperand::CreateImm(Res, S, E);
+ Op = SparcOperand::CreateImm(Res, S, E);
+ }
break;
}
-
- case AsmToken::LBrac: // handle [
- return parseMEMOperand(Operands, 0);
-
- default:
- return MatchOperand_ParseFail;
}
- // Push the parsed operand into the list of operands
- Operands.push_back(Op);
- return MatchOperand_Success;
+ return (Op) ? MatchOperand_Success : MatchOperand_ParseFail;
}
bool SparcAsmParser::matchRegisterName(const AsmToken &Tok,
diff --git a/lib/Target/Sparc/SparcInstrInfo.td b/lib/Target/Sparc/SparcInstrInfo.td
index c1ebbca923..7808a1aea4 100644
--- a/lib/Target/Sparc/SparcInstrInfo.td
+++ b/lib/Target/Sparc/SparcInstrInfo.td
@@ -78,12 +78,12 @@ def ADDRri : ComplexPattern<iPTR, 2, "SelectADDRri", [frameindex], []>;
// Address operands
def SparcMEMrrAsmOperand : AsmOperandClass {
let Name = "MEMrr";
- let ParserMethod = "parseMEMrrOperand";
+ let ParserMethod = "parseMEMOperand";
}
def SparcMEMriAsmOperand : AsmOperandClass {
let Name = "MEMri";
- let ParserMethod = "parseMEMriOperand";
+ let ParserMethod = "parseMEMOperand";
}
def MEMrr : Operand<iPTR> {
diff --git a/test/MC/Sparc/sparc-ctrl-instructions.s b/test/MC/Sparc/sparc-ctrl-instructions.s
new file mode 100644
index 0000000000..5a2c5975f6
--- /dev/null
+++ b/test/MC/Sparc/sparc-ctrl-instructions.s
@@ -0,0 +1,23 @@
+! RUN: llvm-mc %s -arch=sparc -show-encoding | FileCheck %s
+! RUN: llvm-mc %s -arch=sparcv9 -show-encoding | FileCheck %s
+
+ ! CHECK: call foo
+ call foo
+
+ ! CHECK: call %g1+%i2
+ call %g1 + %i2
+
+ ! CHECK: call %o1+8
+ call %o1 + 8
+
+ ! CHECK: call %g1
+ call %g1
+
+ ! CHECK: jmp %g1+%i2
+ jmp %g1 + %i2
+
+ ! CHECK: jmp %o1+8
+ jmp %o1 + 8
+
+ ! CHECK: jmp %g1
+ jmp %g1
diff --git a/test/MC/Sparc/sparc-mem-instructions.s b/test/MC/Sparc/sparc-mem-instructions.s
new file mode 100644
index 0000000000..e8eb5933c3
--- /dev/null
+++ b/test/MC/Sparc/sparc-mem-instructions.s
@@ -0,0 +1,58 @@
+! RUN: llvm-mc %s -arch=sparc -show-encoding | FileCheck %s
+! RUN: llvm-mc %s -arch=sparcv9 -show-encoding | FileCheck %s
+
+ ! CHECK: ldsb [%i0+%l6], %o2 ! encoding: [0xd4,0x4e,0x00,0x16]
+ ldsb [%i0 + %l6], %o2
+ ! CHECK: ldsb [%i0+32], %o2 ! encoding: [0xd4,0x4e,0x20,0x20]
+ ldsb [%i0 + 32], %o2
+ ! CHECK: ldsb [%g1], %o4 ! encoding: [0xd8,0x48,0x60,0x00]
+ ldsb [%g1], %o4
+
+ ! CHECK: ldsh [%i0+%l6], %o2 ! encoding: [0xd4,0x56,0x00,0x16]
+ ldsh [%i0 + %l6], %o2
+ ! CHECK: ldsh [%i0+32], %o2 ! encoding: [0xd4,0x56,0x20,0x20]
+ ldsh [%i0 + 32], %o2
+ ! CHECK: ldsh [%g1], %o4 ! encoding: [0xd8,0x50,0x60,0x00]
+ ldsh [%g1], %o4
+
+ ! CHECK: ldub [%i0+%l6], %o2 ! encoding: [0xd4,0x0e,0x00,0x16]
+ ldub [%i0 + %l6], %o2
+ ! CHECK: ldub [%i0+32], %o2 ! encoding: [0xd4,0x0e,0x20,0x20]
+ ldub [%i0 + 32], %o2
+ ! CHECK: ldub [%g1], %o2 ! encoding: [0xd4,0x08,0x60,0x00]
+ ldub [%g1], %o2
+
+ ! CHECK: lduh [%i0+%l6], %o2 ! encoding: [0xd4,0x16,0x00,0x16]
+ lduh [%i0 + %l6], %o2
+ ! CHECK: lduh [%i0+32], %o2 ! encoding: [0xd4,0x16,0x20,0x20]
+ lduh [%i0 + 32], %o2
+ ! CHECK: lduh [%g1], %o2 ! encoding: [0xd4,0x10,0x60,0x00]
+ lduh [%g1], %o2
+
+ ! CHECK: ld [%i0+%l6], %o2 ! encoding: [0xd4,0x06,0x00,0x16]
+ ld [%i0 + %l6], %o2
+ ! CHECK: ld [%i0+32], %o2 ! encoding: [0xd4,0x06,0x20,0x20]
+ ld [%i0 + 32], %o2
+ ! CHECK: ld [%g1], %o2 ! encoding: [0xd4,0x00,0x60,0x00]
+ ld [%g1], %o2
+
+ ! CHECK: stb %o2, [%i0+%l6] ! encoding: [0xd4,0x2e,0x00,0x16]
+ stb %o2, [%i0 + %l6]
+ ! CHECK: stb %o2, [%i0+32] ! encoding: [0xd4,0x2e,0x20,0x20]
+ stb %o2, [%i0 + 32]
+ ! CHECK: stb %o2, [%g1] ! encoding: [0xd4,0x28,0x60,0x00]
+ stb %o2, [%g1]
+
+ ! CHECK: sth %o2, [%i0+%l6] ! encoding: [0xd4,0x36,0x00,0x16]
+ sth %o2, [%i0 + %l6]
+ ! CHECK: sth %o2, [%i0+32] ! encoding: [0xd4,0x36,0x20,0x20]
+ sth %o2, [%i0 + 32]
+ ! CHECK: sth %o2, [%g1] ! encoding: [0xd4,0x30,0x60,0x00]
+ sth %o2, [%g1]
+
+ ! CHECK: st %o2, [%i0+%l6] ! encoding: [0xd4,0x26,0x00,0x16]
+ st %o2, [%i0 + %l6]
+ ! CHECK: st %o2, [%i0+32] ! encoding: [0xd4,0x26,0x20,0x20]
+ st %o2, [%i0 + 32]
+ ! CHECK: st %o2, [%g1] ! encoding: [0xd4,0x20,0x60,0x00]
+ st %o2, [%g1]