ARM assembly parsing and encoding for SETEND instruction.

Add parsing and diagnostics for malformed inputs. Tests for diagnostics and
for correct encodings.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@135776 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Jim Grosbach 2011-07-22 17:44:50 +00:00
parent 9076b6e8f4
commit c27d4f9ea0
4 changed files with 78 additions and 6 deletions

View File

@ -193,8 +193,13 @@ def s_cc_out : OptionalDefOperand<OtherVT, (ops CCR), (ops (i32 CPSR))> {
// ARM special operands for disassembly only.
//
def SetEndAsmOperand : AsmOperandClass {
let Name = "SetEndImm";
let ParserMethod = "parseSetEndImm";
}
def setend_op : Operand<i32> {
let PrintMethod = "printSetendOperand";
let ParserMatchClass = SetEndAsmOperand;
}
def msr_mask : Operand<i32> {

View File

@ -126,6 +126,7 @@ class ARMAsmParser : public TargetAsmParser {
OperandMatchResultTy parsePKHASRImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
return parsePKHImm(O, "asr", 1, 32);
}
OperandMatchResultTy parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*>&);
// Asm Match Converter Methods
bool CvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
@ -476,6 +477,14 @@ public:
int64_t Value = CE->getValue();
return ARM_AM::getT2SOImmVal(Value) != -1;
}
bool isSetEndImm() const {
if (Kind != Immediate)
return false;
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
if (!CE) return false;
int64_t Value = CE->getValue();
return Value == 1 || Value == 0;
}
bool isReg() const { return Kind == Register; }
bool isRegList() const { return Kind == RegisterList; }
bool isDPRRegList() const { return Kind == DPRRegisterList; }
@ -715,6 +724,11 @@ public:
addExpr(Inst, getImm());
}
void addSetEndImmOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
addExpr(Inst, getImm());
}
void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
@ -1644,6 +1658,30 @@ parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
return MatchOperand_Success;
}
ARMAsmParser::OperandMatchResultTy ARMAsmParser::
parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
const AsmToken &Tok = Parser.getTok();
SMLoc S = Tok.getLoc();
if (Tok.isNot(AsmToken::Identifier)) {
Error(Tok.getLoc(), "'be' or 'le' operand expected");
return MatchOperand_ParseFail;
}
int Val = StringSwitch<int>(Tok.getString())
.Case("be", 1)
.Case("le", 0)
.Default(-1);
Parser.Lex(); // Eat the token.
if (Val == -1) {
Error(Tok.getLoc(), "'be' or 'le' operand expected");
return MatchOperand_ParseFail;
}
Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
getContext()),
S, 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.
@ -2197,6 +2235,7 @@ GetMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "clrex" ||
Mnemonic == "setend" ||
Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumb())) {
CanAcceptPredicationCode = false;
} else {
@ -2221,7 +2260,7 @@ bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
unsigned ProcessorIMod;
bool CarrySetting;
Mnemonic = SplitMnemonic(Mnemonic, PredicationCode, CarrySetting,
ProcessorIMod);
ProcessorIMod);
Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
@ -2245,6 +2284,13 @@ bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
return Error(NameLoc, "instruction '" + Mnemonic +
"' can not set flags, but 's' suffix specified");
}
// If we had a predication code on an instruction that can't do that, issue an
// error.
if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
Parser.EatToEndOfStatement();
return Error(NameLoc, "instruction '" + Mnemonic +
"' is not predicable, but condition code specified");
}
// Add the carry setting operand, if necessary.
//
@ -2259,11 +2305,6 @@ bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
if (CanAcceptPredicationCode) {
Operands.push_back(ARMOperand::CreateCondCode(
ARMCC::CondCodes(PredicationCode), NameLoc));
} else {
// This mnemonic can't ever accept a predication code, but the user wrote
// one (or misspelled another mnemonic).
// FIXME: Issue a nice error.
}
// Add the processor imod operand, if necessary.

View File

@ -1303,6 +1303,16 @@ _func:
@ CHECK: selne r9, r2, r1 @ encoding: [0xb1,0x9f,0x82,0x16]
@------------------------------------------------------------------------------
@ SETEND
@------------------------------------------------------------------------------
setend be
setend le
sel r9, r2, r1 @ encoding: [0xb1,0x9f,0x82,0xe6]
selne r9, r2, r1 @ encoding: [0xb1,0x9f,0x82,0x16]
@------------------------------------------------------------------------------
@ STM*
@------------------------------------------------------------------------------

View File

@ -144,3 +144,19 @@
@ CHECK: error: asr operand expected.
@ CHECK: pkhtb r2, r2, r3, lsl #3
@ CHECK: ^
@ bad values for SETEND
setendne be
setend me
setend 1
@ CHECK: error: instruction 'setend' is not predicable, but condition code specified
@ CHECK: setendne be
@ CHECK: ^
@ CHECK: error: 'be' or 'le' operand expected
@ CHECK: setend me
@ CHECK: ^
@ CHECK: error: 'be' or 'le' operand expected
@ CHECK: setend 1
@ CHECK: ^