mirror of
https://github.com/RPCSX/llvm.git
synced 2025-02-27 00:15:58 +00:00
ARM parsing and encoding for the <option> form of LDC/STC instructions.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@141786 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
01208d56e8
commit
9b8f2a0b36
@ -842,6 +842,14 @@ def c_imm : Operand<i32> {
|
|||||||
let PrintMethod = "printCImmediate";
|
let PrintMethod = "printCImmediate";
|
||||||
let ParserMatchClass = CoprocRegAsmOperand;
|
let ParserMatchClass = CoprocRegAsmOperand;
|
||||||
}
|
}
|
||||||
|
def CoprocOptionAsmOperand : AsmOperandClass {
|
||||||
|
let Name = "CoprocOption";
|
||||||
|
let ParserMethod = "parseCoprocOptionOperand";
|
||||||
|
}
|
||||||
|
def coproc_option_imm : Operand<i32> {
|
||||||
|
let PrintMethod = "printCoprocOptionImm";
|
||||||
|
let ParserMatchClass = CoprocOptionAsmOperand;
|
||||||
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
@ -4312,8 +4320,8 @@ multiclass LdStCop<bit load, bit Dbit, string asm> {
|
|||||||
}
|
}
|
||||||
def _OPTION : ACI<(outs),
|
def _OPTION : ACI<(outs),
|
||||||
(ins p_imm:$cop, c_imm:$CRd, addr_offset_none:$addr,
|
(ins p_imm:$cop, c_imm:$CRd, addr_offset_none:$addr,
|
||||||
nohash_imm:$option),
|
coproc_option_imm:$option),
|
||||||
asm, "\t$cop, $CRd, $addr, \\{$option\\}"> {
|
asm, "\t$cop, $CRd, $addr, $option"> {
|
||||||
bits<8> option;
|
bits<8> option;
|
||||||
bits<4> addr;
|
bits<4> addr;
|
||||||
bits<4> cop;
|
bits<4> cop;
|
||||||
@ -4383,8 +4391,8 @@ multiclass LdSt2Cop<bit load, bit Dbit, string asm> {
|
|||||||
}
|
}
|
||||||
def _OPTION : ACInoP<(outs),
|
def _OPTION : ACInoP<(outs),
|
||||||
(ins p_imm:$cop, c_imm:$CRd, addr_offset_none:$addr,
|
(ins p_imm:$cop, c_imm:$CRd, addr_offset_none:$addr,
|
||||||
nohash_imm:$option),
|
coproc_option_imm:$option),
|
||||||
asm, "\t$cop, $CRd, $addr, \\{$option\\}"> {
|
asm, "\t$cop, $CRd, $addr, $option"> {
|
||||||
bits<8> option;
|
bits<8> option;
|
||||||
bits<4> addr;
|
bits<4> addr;
|
||||||
bits<4> cop;
|
bits<4> cop;
|
||||||
|
@ -138,6 +138,8 @@ class ARMAsmParser : public MCTargetAsmParser {
|
|||||||
SmallVectorImpl<MCParsedAsmOperand*>&);
|
SmallVectorImpl<MCParsedAsmOperand*>&);
|
||||||
OperandMatchResultTy parseCoprocRegOperand(
|
OperandMatchResultTy parseCoprocRegOperand(
|
||||||
SmallVectorImpl<MCParsedAsmOperand*>&);
|
SmallVectorImpl<MCParsedAsmOperand*>&);
|
||||||
|
OperandMatchResultTy parseCoprocOptionOperand(
|
||||||
|
SmallVectorImpl<MCParsedAsmOperand*>&);
|
||||||
OperandMatchResultTy parseMemBarrierOptOperand(
|
OperandMatchResultTy parseMemBarrierOptOperand(
|
||||||
SmallVectorImpl<MCParsedAsmOperand*>&);
|
SmallVectorImpl<MCParsedAsmOperand*>&);
|
||||||
OperandMatchResultTy parseProcIFlagsOperand(
|
OperandMatchResultTy parseProcIFlagsOperand(
|
||||||
@ -247,6 +249,7 @@ class ARMOperand : public MCParsedAsmOperand {
|
|||||||
k_ITCondMask,
|
k_ITCondMask,
|
||||||
k_CoprocNum,
|
k_CoprocNum,
|
||||||
k_CoprocReg,
|
k_CoprocReg,
|
||||||
|
k_CoprocOption,
|
||||||
k_Immediate,
|
k_Immediate,
|
||||||
k_FPImmediate,
|
k_FPImmediate,
|
||||||
k_MemBarrierOpt,
|
k_MemBarrierOpt,
|
||||||
@ -279,6 +282,10 @@ class ARMOperand : public MCParsedAsmOperand {
|
|||||||
unsigned Val;
|
unsigned Val;
|
||||||
} Cop;
|
} Cop;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
unsigned Val;
|
||||||
|
} CoprocOption;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
unsigned Mask:4;
|
unsigned Mask:4;
|
||||||
} ITMask;
|
} ITMask;
|
||||||
@ -390,6 +397,9 @@ public:
|
|||||||
case k_CoprocReg:
|
case k_CoprocReg:
|
||||||
Cop = o.Cop;
|
Cop = o.Cop;
|
||||||
break;
|
break;
|
||||||
|
case k_CoprocOption:
|
||||||
|
CoprocOption = o.CoprocOption;
|
||||||
|
break;
|
||||||
case k_Immediate:
|
case k_Immediate:
|
||||||
Imm = o.Imm;
|
Imm = o.Imm;
|
||||||
break;
|
break;
|
||||||
@ -495,6 +505,7 @@ public:
|
|||||||
|
|
||||||
bool isCoprocNum() const { return Kind == k_CoprocNum; }
|
bool isCoprocNum() const { return Kind == k_CoprocNum; }
|
||||||
bool isCoprocReg() const { return Kind == k_CoprocReg; }
|
bool isCoprocReg() const { return Kind == k_CoprocReg; }
|
||||||
|
bool isCoprocOption() const { return Kind == k_CoprocOption; }
|
||||||
bool isCondCode() const { return Kind == k_CondCode; }
|
bool isCondCode() const { return Kind == k_CondCode; }
|
||||||
bool isCCOut() const { return Kind == k_CCOut; }
|
bool isCCOut() const { return Kind == k_CCOut; }
|
||||||
bool isITMask() const { return Kind == k_ITCondMask; }
|
bool isITMask() const { return Kind == k_ITCondMask; }
|
||||||
@ -924,6 +935,16 @@ public:
|
|||||||
Inst.addOperand(MCOperand::CreateImm(getCoproc()));
|
Inst.addOperand(MCOperand::CreateImm(getCoproc()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
|
||||||
|
assert(N == 1 && "Invalid number of operands!");
|
||||||
|
Inst.addOperand(MCOperand::CreateImm(getCoproc()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
|
||||||
|
assert(N == 1 && "Invalid number of operands!");
|
||||||
|
Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
|
||||||
|
}
|
||||||
|
|
||||||
void addITMaskOperands(MCInst &Inst, unsigned N) const {
|
void addITMaskOperands(MCInst &Inst, unsigned N) const {
|
||||||
assert(N == 1 && "Invalid number of operands!");
|
assert(N == 1 && "Invalid number of operands!");
|
||||||
Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
|
Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
|
||||||
@ -934,11 +955,6 @@ public:
|
|||||||
Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
|
Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
|
||||||
}
|
}
|
||||||
|
|
||||||
void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
|
|
||||||
assert(N == 1 && "Invalid number of operands!");
|
|
||||||
Inst.addOperand(MCOperand::CreateImm(getCoproc()));
|
|
||||||
}
|
|
||||||
|
|
||||||
void addCCOutOperands(MCInst &Inst, unsigned N) const {
|
void addCCOutOperands(MCInst &Inst, unsigned N) const {
|
||||||
assert(N == 1 && "Invalid number of operands!");
|
assert(N == 1 && "Invalid number of operands!");
|
||||||
Inst.addOperand(MCOperand::CreateReg(getReg()));
|
Inst.addOperand(MCOperand::CreateReg(getReg()));
|
||||||
@ -1453,6 +1469,14 @@ public:
|
|||||||
return Op;
|
return Op;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
|
||||||
|
ARMOperand *Op = new ARMOperand(k_CoprocOption);
|
||||||
|
Op->Cop.Val = Val;
|
||||||
|
Op->StartLoc = S;
|
||||||
|
Op->EndLoc = E;
|
||||||
|
return Op;
|
||||||
|
}
|
||||||
|
|
||||||
static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
|
static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
|
||||||
ARMOperand *Op = new ARMOperand(k_CCOut);
|
ARMOperand *Op = new ARMOperand(k_CCOut);
|
||||||
Op->Reg.RegNum = RegNum;
|
Op->Reg.RegNum = RegNum;
|
||||||
@ -1668,6 +1692,9 @@ void ARMOperand::print(raw_ostream &OS) const {
|
|||||||
case k_CoprocReg:
|
case k_CoprocReg:
|
||||||
OS << "<coprocessor register: " << getCoproc() << ">";
|
OS << "<coprocessor register: " << getCoproc() << ">";
|
||||||
break;
|
break;
|
||||||
|
case k_CoprocOption:
|
||||||
|
OS << "<coprocessor option: " << CoprocOption.Val << ">";
|
||||||
|
break;
|
||||||
case k_MSRMask:
|
case k_MSRMask:
|
||||||
OS << "<mask: " << getMSRMask() << ">";
|
OS << "<mask: " << getMSRMask() << ">";
|
||||||
break;
|
break;
|
||||||
@ -2088,6 +2115,40 @@ parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
|
|||||||
return MatchOperand_Success;
|
return MatchOperand_Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
|
||||||
|
/// coproc_option : '{' imm0_255 '}'
|
||||||
|
ARMAsmParser::OperandMatchResultTy ARMAsmParser::
|
||||||
|
parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
|
||||||
|
SMLoc S = Parser.getTok().getLoc();
|
||||||
|
|
||||||
|
// If this isn't a '{', this isn't a coprocessor immediate operand.
|
||||||
|
if (Parser.getTok().isNot(AsmToken::LCurly))
|
||||||
|
return MatchOperand_NoMatch;
|
||||||
|
Parser.Lex(); // Eat the '{'
|
||||||
|
|
||||||
|
const MCExpr *Expr;
|
||||||
|
SMLoc Loc = Parser.getTok().getLoc();
|
||||||
|
if (getParser().ParseExpression(Expr)) {
|
||||||
|
Error(Loc, "illegal expression");
|
||||||
|
return MatchOperand_ParseFail;
|
||||||
|
}
|
||||||
|
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
|
||||||
|
if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
|
||||||
|
Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
|
||||||
|
return MatchOperand_ParseFail;
|
||||||
|
}
|
||||||
|
int Val = CE->getValue();
|
||||||
|
|
||||||
|
// Check for and consume the closing '}'
|
||||||
|
if (Parser.getTok().isNot(AsmToken::RCurly))
|
||||||
|
return MatchOperand_ParseFail;
|
||||||
|
SMLoc E = Parser.getTok().getLoc();
|
||||||
|
Parser.Lex(); // Eat the '}'
|
||||||
|
|
||||||
|
Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
|
||||||
|
return MatchOperand_Success;
|
||||||
|
}
|
||||||
|
|
||||||
// For register list parsing, we need to map from raw GPR register numbering
|
// For register list parsing, we need to map from raw GPR register numbering
|
||||||
// to the enumeration values. The enumeration values aren't sorted by
|
// to the enumeration values. The enumeration values aren't sorted by
|
||||||
// register number due to our using "sp", "lr" and "pc" as canonical names.
|
// register number due to our using "sp", "lr" and "pc" as canonical names.
|
||||||
|
@ -719,6 +719,11 @@ void ARMInstPrinter::printCImmediate(const MCInst *MI, unsigned OpNum,
|
|||||||
O << "c" << MI->getOperand(OpNum).getImm();
|
O << "c" << MI->getOperand(OpNum).getImm();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ARMInstPrinter::printCoprocOptionImm(const MCInst *MI, unsigned OpNum,
|
||||||
|
raw_ostream &O) {
|
||||||
|
O << "{" << MI->getOperand(OpNum).getImm() << "}";
|
||||||
|
}
|
||||||
|
|
||||||
void ARMInstPrinter::printPCLabel(const MCInst *MI, unsigned OpNum,
|
void ARMInstPrinter::printPCLabel(const MCInst *MI, unsigned OpNum,
|
||||||
raw_ostream &O) {
|
raw_ostream &O) {
|
||||||
llvm_unreachable("Unhandled PC-relative pseudo-instruction!");
|
llvm_unreachable("Unhandled PC-relative pseudo-instruction!");
|
||||||
|
@ -120,6 +120,7 @@ public:
|
|||||||
void printNoHashImmediate(const MCInst *MI, unsigned OpNum, raw_ostream &O);
|
void printNoHashImmediate(const MCInst *MI, unsigned OpNum, raw_ostream &O);
|
||||||
void printPImmediate(const MCInst *MI, unsigned OpNum, raw_ostream &O);
|
void printPImmediate(const MCInst *MI, unsigned OpNum, raw_ostream &O);
|
||||||
void printCImmediate(const MCInst *MI, unsigned OpNum, raw_ostream &O);
|
void printCImmediate(const MCInst *MI, unsigned OpNum, raw_ostream &O);
|
||||||
|
void printCoprocOptionImm(const MCInst *MI, unsigned OpNum, raw_ostream &O);
|
||||||
void printFPImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
|
void printFPImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
|
||||||
void printNEONModImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
|
void printNEONModImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
|
||||||
void printImmPlusOneOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
|
void printImmPlusOneOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
|
||||||
|
@ -684,6 +684,8 @@ Lforward:
|
|||||||
ldcleq p6, c14, [r10], #16
|
ldcleq p6, c14, [r10], #16
|
||||||
ldclhi p7, c15, [r11], #-72
|
ldclhi p7, c15, [r11], #-72
|
||||||
|
|
||||||
|
ldc2 p2, c8, [r1], { 25 }
|
||||||
|
|
||||||
@ CHECK: ldc2 p0, c8, [r1, #4] @ encoding: [0x01,0x80,0x91,0xfd]
|
@ CHECK: ldc2 p0, c8, [r1, #4] @ encoding: [0x01,0x80,0x91,0xfd]
|
||||||
@ CHECK: ldc2 p1, c7, [r2] @ encoding: [0x00,0x71,0x92,0xfd]
|
@ CHECK: ldc2 p1, c7, [r2] @ encoding: [0x00,0x71,0x92,0xfd]
|
||||||
@ CHECK: ldc2 p2, c6, [r3, #-224] @ encoding: [0x38,0x62,0x13,0xfd]
|
@ CHECK: ldc2 p2, c6, [r3, #-224] @ encoding: [0x38,0x62,0x13,0xfd]
|
||||||
@ -723,6 +725,8 @@ Lforward:
|
|||||||
@ CHECK: ldcleq p6, c14, [r10], #16 @ encoding: [0x04,0xe6,0xfa,0x0c]
|
@ CHECK: ldcleq p6, c14, [r10], #16 @ encoding: [0x04,0xe6,0xfa,0x0c]
|
||||||
@ CHECK: ldclhi p7, c15, [r11], #-72 @ encoding: [0x12,0xf7,0x7b,0x8c]
|
@ CHECK: ldclhi p7, c15, [r11], #-72 @ encoding: [0x12,0xf7,0x7b,0x8c]
|
||||||
|
|
||||||
|
@ CHECK: ldc2 p2, c8, [r1], {25} @ encoding: [0x19,0x82,0x91,0xfc]
|
||||||
|
|
||||||
|
|
||||||
@------------------------------------------------------------------------------
|
@------------------------------------------------------------------------------
|
||||||
@ LDM*
|
@ LDM*
|
||||||
|
@ -305,3 +305,13 @@
|
|||||||
@ CHECK-ERRORS: vpush {s0, s3}
|
@ CHECK-ERRORS: vpush {s0, s3}
|
||||||
@ CHECK-ERRORS: ^
|
@ CHECK-ERRORS: ^
|
||||||
|
|
||||||
|
@ Out of range coprocessor option immediate.
|
||||||
|
ldc2 p2, c8, [r1], { 256 }
|
||||||
|
ldc2 p2, c8, [r1], { -1 }
|
||||||
|
|
||||||
|
@ CHECK-ERRORS: error: coprocessor option must be an immediate in range [0, 255]
|
||||||
|
@ CHECK-ERRORS: ldc2 p2, c8, [r1], { 256 }
|
||||||
|
@ CHECK-ERRORS: ^
|
||||||
|
@ CHECK-ERRORS: error: coprocessor option must be an immediate in range [0, 255]
|
||||||
|
@ CHECK-ERRORS: ldc2 p2, c8, [r1], { -1 }
|
||||||
|
@ CHECK-ERRORS: ^
|
||||||
|
@ -581,6 +581,7 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type,
|
|||||||
IMM("nohash_imm");
|
IMM("nohash_imm");
|
||||||
IMM("p_imm");
|
IMM("p_imm");
|
||||||
IMM("c_imm");
|
IMM("c_imm");
|
||||||
|
IMM("coproc_option_imm");
|
||||||
IMM("imod_op");
|
IMM("imod_op");
|
||||||
IMM("iflags_op");
|
IMM("iflags_op");
|
||||||
IMM("cpinst_operand");
|
IMM("cpinst_operand");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user