ARM assembly parsing and encoding for PKHBT and PKHTB instructions.

llvm-svn: 135682
This commit is contained in:
Jim Grosbach 2011-07-21 17:23:04 +00:00
parent b5a52ca0c9
commit 27c1e2560c
3 changed files with 100 additions and 0 deletions

View File

@ -847,11 +847,21 @@ class AMiscA1I<bits<8> opcod, bits<4> opc7_4, dag oops, dag iops,
}
// PKH instructions
def PKHLSLAsmOperand : AsmOperandClass {
let Name = "PKHLSLImm";
let ParserMethod = "parsePKHLSLImm";
}
def pkh_lsl_amt: Operand<i32>, ImmLeaf<i32, [{ return Imm >= 0 && Imm < 32; }]>{
let PrintMethod = "printPKHLSLShiftImm";
let ParserMatchClass = PKHLSLAsmOperand;
}
def PKHASRAsmOperand : AsmOperandClass {
let Name = "PKHASRImm";
let ParserMethod = "parsePKHASRImm";
}
def pkh_asr_amt: Operand<i32>, ImmLeaf<i32, [{ return Imm > 0 && Imm <= 32; }]>{
let PrintMethod = "printPKHASRShiftImm";
let ParserMatchClass = PKHASRAsmOperand;
}
class APKHI<bits<8> opcod, bit tb, dag oops, dag iops, InstrItinClass itin,

View File

@ -4067,3 +4067,9 @@ def : MnemonicAlias<"stmfd", "stmdb">;
def : MnemonicAlias<"stmia", "stm">;
def : MnemonicAlias<"stmea", "stm">;
// PKHBT/PKHTB with default shift amount. PKHTB is equivalent to PKHBT when the
// shift amount is zero (i.e., unspecified).
def : InstAlias<"pkhbt${p} $Rd, $Rn, $Rm",
(PKHBT GPR:$Rd, GPR:$Rn, GPR:$Rm, 0, pred:$p)>;
def : InstAlias<"pkhtb${p} $Rd, $Rn, $Rm",
(PKHBT GPR:$Rd, GPR:$Rn, GPR:$Rm, 0, pred:$p)>;

View File

@ -118,6 +118,14 @@ class ARMAsmParser : public TargetAsmParser {
SmallVectorImpl<MCParsedAsmOperand*>&);
OperandMatchResultTy tryParseMemMode3Operand(
SmallVectorImpl<MCParsedAsmOperand*>&);
OperandMatchResultTy parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &O,
StringRef Op, int Low, int High);
OperandMatchResultTy parsePKHLSLImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
return parsePKHImm(O, "lsl", 0, 31);
}
OperandMatchResultTy parsePKHASRImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
return parsePKHImm(O, "asr", 1, 32);
}
// Asm Match Converter Methods
bool CvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
@ -419,6 +427,22 @@ public:
int64_t Value = CE->getValue();
return Value >= 0 && Value < 65536;
}
bool isPKHLSLImm() const {
if (Kind != Immediate)
return false;
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
if (!CE) return false;
int64_t Value = CE->getValue();
return Value >= 0 && Value < 32;
}
bool isPKHASRImm() const {
if (Kind != Immediate)
return false;
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
if (!CE) return false;
int64_t Value = CE->getValue();
return Value > 0 && Value <= 32;
}
bool isARMSOImm() const {
if (Kind != Immediate)
return false;
@ -638,6 +662,20 @@ public:
addExpr(Inst, getImm());
}
void addPKHLSLImmOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
addExpr(Inst, getImm());
}
void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
// An ASR value of 32 encodes as 0, so that's how we want to add it to
// the instruction as well.
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
int Val = CE->getValue();
Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
}
void addARMSOImmOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
addExpr(Inst, getImm());
@ -1507,6 +1545,52 @@ tryParseMemMode3Operand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
return MatchOperand_Success;
}
ARMAsmParser::OperandMatchResultTy ARMAsmParser::
parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
int Low, int High) {
const AsmToken &Tok = Parser.getTok();
if (Tok.isNot(AsmToken::Identifier)) {
Error(Parser.getTok().getLoc(), Op + " operand expected.");
return MatchOperand_ParseFail;
}
StringRef ShiftName = Tok.getString();
std::string LowerOp = LowercaseString(Op);
std::string UpperOp = UppercaseString(Op);
if (ShiftName != LowerOp && ShiftName != UpperOp) {
Error(Parser.getTok().getLoc(), Op + " operand expected.");
return MatchOperand_ParseFail;
}
Parser.Lex(); // Eat shift type token.
// There must be a '#' and a shift amount.
if (Parser.getTok().isNot(AsmToken::Hash)) {
Error(Parser.getTok().getLoc(), "'#' expected");
return MatchOperand_ParseFail;
}
Parser.Lex(); // Eat hash token.
const MCExpr *ShiftAmount;
SMLoc Loc = Parser.getTok().getLoc();
if (getParser().ParseExpression(ShiftAmount)) {
Error(Loc, "illegal expression");
return MatchOperand_ParseFail;
}
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
if (!CE) {
Error(Loc, "constant expression expected");
return MatchOperand_ParseFail;
}
int Val = CE->getValue();
if (Val < Low || Val > High) {
Error(Loc, "immediate value out of range");
return MatchOperand_ParseFail;
}
Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
return MatchOperand_Success;
}
/// CvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
/// Needed here because the Asm Gen Matcher can't handle properly tied operands
/// when they refer multiple MIOperands inside a single one.