forked from OSchip/llvm-project
ARM assembly parsing and encoding for PKHBT and PKHTB instructions.
llvm-svn: 135682
This commit is contained in:
parent
b5a52ca0c9
commit
27c1e2560c
|
@ -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,
|
||||
|
|
|
@ -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)>;
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in New Issue