forked from OSchip/llvm-project
[ARM] Add support for mrrc/mrrc2 intrinsics.
Differential Revision: http://reviews.llvm.org/D21178 llvm-svn: 272778
This commit is contained in:
parent
8d5ad5bdf2
commit
351364fe76
|
@ -123,12 +123,15 @@ def int_arm_cdp2 : GCCBuiltin<"__builtin_arm_cdp2">,
|
|||
llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>;
|
||||
|
||||
// Move from two registers to coprocessor
|
||||
def int_arm_mcrr : GCCBuiltin<"__builtin_arm_mcrr">,
|
||||
Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty,
|
||||
llvm_i32_ty, llvm_i32_ty], []>;
|
||||
def int_arm_mcrr2 : GCCBuiltin<"__builtin_arm_mcrr2">,
|
||||
Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty,
|
||||
llvm_i32_ty, llvm_i32_ty], []>;
|
||||
def int_arm_mcrr : Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty,
|
||||
llvm_i32_ty, llvm_i32_ty], []>;
|
||||
def int_arm_mcrr2 : Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty,
|
||||
llvm_i32_ty, llvm_i32_ty], []>;
|
||||
|
||||
def int_arm_mrrc : Intrinsic<[llvm_i32_ty, llvm_i32_ty], [llvm_i32_ty,
|
||||
llvm_i32_ty, llvm_i32_ty], []>;
|
||||
def int_arm_mrrc2 : Intrinsic<[llvm_i32_ty, llvm_i32_ty], [llvm_i32_ty,
|
||||
llvm_i32_ty, llvm_i32_ty], []>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// CRC32
|
||||
|
|
|
@ -3335,6 +3335,34 @@ void ARMDAGToDAGISel::Select(SDNode *N) {
|
|||
default:
|
||||
break;
|
||||
|
||||
case Intrinsic::arm_mrrc:
|
||||
case Intrinsic::arm_mrrc2: {
|
||||
SDLoc dl(N);
|
||||
SDValue Chain = N->getOperand(0);
|
||||
unsigned Opc;
|
||||
|
||||
if (Subtarget->isThumb())
|
||||
Opc = (IntNo == Intrinsic::arm_mrrc ? ARM::t2MRRC : ARM::t2MRRC2);
|
||||
else
|
||||
Opc = (IntNo == Intrinsic::arm_mrrc ? ARM::MRRC : ARM::MRRC2);
|
||||
|
||||
SmallVector<SDValue, 5> Ops;
|
||||
Ops.push_back(getI32Imm(cast<ConstantSDNode>(N->getOperand(2))->getZExtValue(), dl)); /* coproc */
|
||||
Ops.push_back(getI32Imm(cast<ConstantSDNode>(N->getOperand(3))->getZExtValue(), dl)); /* opc */
|
||||
Ops.push_back(getI32Imm(cast<ConstantSDNode>(N->getOperand(4))->getZExtValue(), dl)); /* CRm */
|
||||
Ops.push_back(getAL(CurDAG, dl));
|
||||
Ops.push_back(CurDAG->getRegister(0, MVT::i32));
|
||||
Ops.push_back(Chain);
|
||||
|
||||
// Writes to two registers.
|
||||
std::vector<EVT> RetType;
|
||||
RetType.push_back(MVT::i32);
|
||||
RetType.push_back(MVT::i32);
|
||||
RetType.push_back(MVT::Other);
|
||||
|
||||
ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, RetType, Ops));
|
||||
return;
|
||||
}
|
||||
case Intrinsic::arm_ldaexd:
|
||||
case Intrinsic::arm_ldrexd: {
|
||||
SDLoc dl(N);
|
||||
|
|
|
@ -5145,9 +5145,9 @@ def MRRC : MovRRCopro<"mrrc", 1 /* from coprocessor to ARM core register */,
|
|||
(outs GPRnopc:$Rt, GPRnopc:$Rt2),
|
||||
(ins p_imm:$cop, imm0_15:$opc1, c_imm:$CRm), []>;
|
||||
|
||||
class MovRRCopro2<string opc, bit direction, list<dag> pattern = []>
|
||||
: ABXI<0b1100, (outs), (ins p_imm:$cop, imm0_15:$opc1,
|
||||
GPRnopc:$Rt, GPRnopc:$Rt2, c_imm:$CRm), NoItinerary,
|
||||
class MovRRCopro2<string opc, bit direction, dag oops, dag iops,
|
||||
list<dag> pattern = []>
|
||||
: ABXI<0b1100, oops, iops, NoItinerary,
|
||||
!strconcat(opc, "\t$cop, $opc1, $Rt, $Rt2, $CRm"), pattern>,
|
||||
Requires<[PreV8]> {
|
||||
let Inst{31-28} = 0b1111;
|
||||
|
@ -5166,13 +5166,18 @@ class MovRRCopro2<string opc, bit direction, list<dag> pattern = []>
|
|||
let Inst{7-4} = opc1;
|
||||
let Inst{3-0} = CRm;
|
||||
|
||||
let DecoderMethod = "DecodeMRRC2";
|
||||
let DecoderMethod = "DecoderForMRRC2AndMCRR2";
|
||||
}
|
||||
|
||||
def MCRR2 : MovRRCopro2<"mcrr2", 0 /* from ARM core register to coprocessor */,
|
||||
(outs), (ins p_imm:$cop, imm0_15:$opc1, GPRnopc:$Rt,
|
||||
GPRnopc:$Rt2, c_imm:$CRm),
|
||||
[(int_arm_mcrr2 imm:$cop, imm:$opc1, GPRnopc:$Rt,
|
||||
GPRnopc:$Rt2, imm:$CRm)]>;
|
||||
def MRRC2 : MovRRCopro2<"mrrc2", 1 /* from coprocessor to ARM core register */>;
|
||||
|
||||
def MRRC2 : MovRRCopro2<"mrrc2", 1 /* from coprocessor to ARM core register */,
|
||||
(outs GPRnopc:$Rt, GPRnopc:$Rt2),
|
||||
(ins p_imm:$cop, imm0_15:$opc1, c_imm:$CRm), []>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Move between special register and ARM core register
|
||||
|
|
|
@ -395,8 +395,8 @@ static DecodeStatus DecodeT2ShifterImmOperand(MCInst &Inst, unsigned Val,
|
|||
|
||||
static DecodeStatus DecodeLDR(MCInst &Inst, unsigned Val,
|
||||
uint64_t Address, const void *Decoder);
|
||||
static DecodeStatus DecodeMRRC2(llvm::MCInst &Inst, unsigned Val,
|
||||
uint64_t Address, const void *Decoder);
|
||||
static DecodeStatus DecoderForMRRC2AndMCRR2(llvm::MCInst &Inst, unsigned Val,
|
||||
uint64_t Address, const void *Decoder);
|
||||
#include "ARMGenDisassemblerTables.inc"
|
||||
|
||||
static MCDisassembler *createARMDisassembler(const Target &T,
|
||||
|
@ -5265,8 +5265,8 @@ static DecodeStatus DecodeLDR(MCInst &Inst, unsigned Val,
|
|||
return S;
|
||||
}
|
||||
|
||||
static DecodeStatus DecodeMRRC2(llvm::MCInst &Inst, unsigned Val,
|
||||
uint64_t Address, const void *Decoder) {
|
||||
static DecodeStatus DecoderForMRRC2AndMCRR2(llvm::MCInst &Inst, unsigned Val,
|
||||
uint64_t Address, const void *Decoder) {
|
||||
|
||||
DecodeStatus S = MCDisassembler::Success;
|
||||
|
||||
|
@ -5282,12 +5282,30 @@ static DecodeStatus DecodeMRRC2(llvm::MCInst &Inst, unsigned Val,
|
|||
if (Rt == Rt2)
|
||||
S = MCDisassembler::SoftFail;
|
||||
|
||||
// We have to check if the instruction is MRRC2
|
||||
// or MCRR2 when constructing the operands for
|
||||
// Inst. Reason is because MRRC2 stores to two
|
||||
// registers so it's tablegen desc has has two
|
||||
// outputs whereas MCRR doesn't store to any
|
||||
// registers so all of it's operands are listed
|
||||
// as inputs, therefore the operand order for
|
||||
// MRRC2 needs to be [Rt, Rt2, cop, opc1, CRm]
|
||||
// and MCRR2 operand order is [cop, opc1, Rt, Rt2, CRm]
|
||||
|
||||
if (Inst.getOpcode() == ARM::MRRC2) {
|
||||
if (!Check(S, DecodeGPRnopcRegisterClass(Inst, Rt, Address, Decoder)))
|
||||
return MCDisassembler::Fail;
|
||||
if (!Check(S, DecodeGPRnopcRegisterClass(Inst, Rt2, Address, Decoder)))
|
||||
return MCDisassembler::Fail;
|
||||
}
|
||||
Inst.addOperand(MCOperand::createImm(cop));
|
||||
Inst.addOperand(MCOperand::createImm(opc1));
|
||||
if (!Check(S, DecodeGPRnopcRegisterClass(Inst, Rt, Address, Decoder)))
|
||||
return MCDisassembler::Fail;
|
||||
if (!Check(S, DecodeGPRnopcRegisterClass(Inst, Rt2, Address, Decoder)))
|
||||
return MCDisassembler::Fail;
|
||||
if (Inst.getOpcode() == ARM::MCRR2) {
|
||||
if (!Check(S, DecodeGPRnopcRegisterClass(Inst, Rt, Address, Decoder)))
|
||||
return MCDisassembler::Fail;
|
||||
if (!Check(S, DecodeGPRnopcRegisterClass(Inst, Rt2, Address, Decoder)))
|
||||
return MCDisassembler::Fail;
|
||||
}
|
||||
Inst.addOperand(MCOperand::createImm(CRm));
|
||||
|
||||
return S;
|
||||
|
|
|
@ -35,6 +35,10 @@ entry:
|
|||
tail call void @llvm.arm.stc2(i32 7, i32 3, i8* %i) nounwind
|
||||
; CHECK: stc2l p7, c3, [r{{[0-9]+}}]
|
||||
tail call void @llvm.arm.stc2l(i32 7, i32 3, i8* %i) nounwind
|
||||
; CHECK: mrrc p1, #2, r{{[0-9]+}}, r{{[0-9]+}}, c3
|
||||
%2 = tail call { i32, i32 } @llvm.arm.mrrc(i32 1, i32 2, i32 3) nounwind
|
||||
; CHECK: mrrc2 p1, #2, r{{[0-9]+}}, r{{[0-9]+}}, c3
|
||||
%3 = tail call { i32, i32 } @llvm.arm.mrrc2(i32 1, i32 2, i32 3) nounwind
|
||||
ret void
|
||||
}
|
||||
|
||||
|
@ -69,3 +73,7 @@ declare i32 @llvm.arm.mrc2(i32, i32, i32, i32, i32) nounwind
|
|||
declare void @llvm.arm.mcr(i32, i32, i32, i32, i32, i32) nounwind
|
||||
|
||||
declare i32 @llvm.arm.mrc(i32, i32, i32, i32, i32) nounwind
|
||||
|
||||
declare { i32, i32 } @llvm.arm.mrrc(i32, i32, i32) nounwind
|
||||
|
||||
declare { i32, i32 } @llvm.arm.mrrc2(i32, i32, i32) nounwind
|
||||
|
|
Loading…
Reference in New Issue