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
|
// PKH instructions
|
||||||
|
def PKHLSLAsmOperand : AsmOperandClass {
|
||||||
|
let Name = "PKHLSLImm";
|
||||||
|
let ParserMethod = "parsePKHLSLImm";
|
||||||
|
}
|
||||||
def pkh_lsl_amt: Operand<i32>, ImmLeaf<i32, [{ return Imm >= 0 && Imm < 32; }]>{
|
def pkh_lsl_amt: Operand<i32>, ImmLeaf<i32, [{ return Imm >= 0 && Imm < 32; }]>{
|
||||||
let PrintMethod = "printPKHLSLShiftImm";
|
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; }]>{
|
def pkh_asr_amt: Operand<i32>, ImmLeaf<i32, [{ return Imm > 0 && Imm <= 32; }]>{
|
||||||
let PrintMethod = "printPKHASRShiftImm";
|
let PrintMethod = "printPKHASRShiftImm";
|
||||||
|
let ParserMatchClass = PKHASRAsmOperand;
|
||||||
}
|
}
|
||||||
|
|
||||||
class APKHI<bits<8> opcod, bit tb, dag oops, dag iops, InstrItinClass itin,
|
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<"stmia", "stm">;
|
||||||
def : MnemonicAlias<"stmea", "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*>&);
|
SmallVectorImpl<MCParsedAsmOperand*>&);
|
||||||
OperandMatchResultTy tryParseMemMode3Operand(
|
OperandMatchResultTy tryParseMemMode3Operand(
|
||||||
SmallVectorImpl<MCParsedAsmOperand*>&);
|
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
|
// Asm Match Converter Methods
|
||||||
bool CvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
|
bool CvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
|
||||||
|
@ -419,6 +427,22 @@ public:
|
||||||
int64_t Value = CE->getValue();
|
int64_t Value = CE->getValue();
|
||||||
return Value >= 0 && Value < 65536;
|
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 {
|
bool isARMSOImm() const {
|
||||||
if (Kind != Immediate)
|
if (Kind != Immediate)
|
||||||
return false;
|
return false;
|
||||||
|
@ -638,6 +662,20 @@ public:
|
||||||
addExpr(Inst, getImm());
|
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 {
|
void addARMSOImmOperands(MCInst &Inst, unsigned N) const {
|
||||||
assert(N == 1 && "Invalid number of operands!");
|
assert(N == 1 && "Invalid number of operands!");
|
||||||
addExpr(Inst, getImm());
|
addExpr(Inst, getImm());
|
||||||
|
@ -1507,6 +1545,52 @@ tryParseMemMode3Operand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
|
||||||
return MatchOperand_Success;
|
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.
|
/// CvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
|
||||||
/// Needed here because the Asm Gen Matcher can't handle properly tied operands
|
/// Needed here because the Asm Gen Matcher can't handle properly tied operands
|
||||||
/// when they refer multiple MIOperands inside a single one.
|
/// when they refer multiple MIOperands inside a single one.
|
||||||
|
|
Loading…
Reference in New Issue