a426b286c8
patch for r263619, and unify all the URLs to point to svnweb.
360 lines
12 KiB
Diff
360 lines
12 KiB
Diff
Pull in r198658 from upstream llvm trunk:
|
|
|
|
[Sparc] Add support for parsing memory operands in sparc AsmParser.
|
|
|
|
Introduced here: http://svnweb.freebsd.org/changeset/base/262261
|
|
|
|
Index: test/MC/Sparc/sparc-ctrl-instructions.s
|
|
===================================================================
|
|
--- test/MC/Sparc/sparc-ctrl-instructions.s
|
|
+++ 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
|
|
Index: test/MC/Sparc/sparc-mem-instructions.s
|
|
===================================================================
|
|
--- test/MC/Sparc/sparc-mem-instructions.s
|
|
+++ 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]
|
|
Index: lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
|
|
===================================================================
|
|
--- lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
|
|
+++ 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);
|
|
+ parseMEMOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
|
|
|
|
OperandMatchResultTy
|
|
- parseMEMOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
|
|
- int ImmOffsetOrReg);
|
|
-
|
|
- 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 @@ class SparcOperand : public MCParsedAsmOperand {
|
|
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,23 +438,42 @@ 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::
|
|
@@ -435,20 +480,57 @@ SparcAsmParser::OperandMatchResultTy SparcAsmParse
|
|
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*>
|
|
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,
|
|
Index: lib/Target/Sparc/SparcInstrInfo.td
|
|
===================================================================
|
|
--- lib/Target/Sparc/SparcInstrInfo.td
|
|
+++ lib/Target/Sparc/SparcInstrInfo.td
|
|
@@ -78,12 +78,12 @@ def ADDRri : ComplexPattern<iPTR, 2, "SelectADDRri
|
|
// 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> {
|