mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-15 04:30:12 +00:00
Support for ADD_PARTS, SUB_PARTS, SHL_PARTS, SHR_PARTS, and SRA_PARTS.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@25158 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
05a2d568c6
commit
e3413160ca
@ -133,6 +133,12 @@ X86TargetLowering::X86TargetLowering(TargetMachine &TM)
|
||||
setOperationAction(ISD::RET , MVT::Other, Custom);
|
||||
// Darwin ABI issue.
|
||||
setOperationAction(ISD::GlobalAddress , MVT::i32 , Custom);
|
||||
// 64-bit addm sub, shl, sra, srl (iff 32-bit x86)
|
||||
setOperationAction(ISD::ADD_PARTS , MVT::i32 , Custom);
|
||||
setOperationAction(ISD::SUB_PARTS , MVT::i32 , Custom);
|
||||
setOperationAction(ISD::SHL_PARTS , MVT::i32 , Custom);
|
||||
setOperationAction(ISD::SRA_PARTS , MVT::i32 , Custom);
|
||||
setOperationAction(ISD::SRL_PARTS , MVT::i32 , Custom);
|
||||
}
|
||||
|
||||
// We don't have line number support yet.
|
||||
@ -243,13 +249,13 @@ SDOperand X86TargetLowering::LowerReturnTo(SDOperand Chain, SDOperand Op,
|
||||
case MVT::f32:
|
||||
case MVT::f64:
|
||||
if (!X86ScalarSSE) {
|
||||
if (OpVT == MVT::f32)
|
||||
Op = DAG.getNode(ISD::FP_EXTEND, MVT::f64, Op);
|
||||
std::vector<MVT::ValueType> Tys;
|
||||
Tys.push_back(MVT::Other);
|
||||
Tys.push_back(MVT::Flag);
|
||||
std::vector<SDOperand> Ops;
|
||||
Ops.push_back(Chain);
|
||||
if (OpVT == MVT::f32)
|
||||
Op = DAG.getNode(ISD::FP_EXTEND, MVT::f64, Op);
|
||||
Ops.push_back(Op);
|
||||
Copy = DAG.getNode(X86ISD::FP_SET_RESULT, Tys, Ops);
|
||||
} else {
|
||||
@ -476,7 +482,6 @@ X86TargetLowering::LowerCCCCallTo(SDOperand Chain, const Type *RetTy,
|
||||
std::vector<MVT::ValueType> NodeTys;
|
||||
NodeTys.push_back(MVT::Other); // Returns a chain
|
||||
NodeTys.push_back(MVT::Flag); // Returns a flag for retval copy to use.
|
||||
|
||||
std::vector<SDOperand> Ops;
|
||||
Ops.push_back(Chain);
|
||||
Ops.push_back(Callee);
|
||||
@ -991,7 +996,6 @@ X86TargetLowering::LowerFastCCCallTo(SDOperand Chain, const Type *RetTy,
|
||||
std::vector<MVT::ValueType> NodeTys;
|
||||
NodeTys.push_back(MVT::Other); // Returns a chain
|
||||
NodeTys.push_back(MVT::Flag); // Returns a flag for retval copy to use.
|
||||
|
||||
std::vector<SDOperand> Ops;
|
||||
Ops.push_back(Chain);
|
||||
Ops.push_back(Callee);
|
||||
@ -1193,6 +1197,99 @@ static unsigned CCToX86CondCode(SDOperand CC, bool isFP) {
|
||||
SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
|
||||
switch (Op.getOpcode()) {
|
||||
default: assert(0 && "Should not custom lower this!");
|
||||
case ISD::ADD_PARTS:
|
||||
case ISD::SUB_PARTS: {
|
||||
assert(Op.getNumOperands() == 4 && Op.getValueType() == MVT::i32 &&
|
||||
"Not an i64 add/sub!");
|
||||
bool isAdd = Op.getOpcode() == ISD::ADD_PARTS;
|
||||
std::vector<MVT::ValueType> Tys;
|
||||
Tys.push_back(MVT::i32);
|
||||
Tys.push_back(MVT::Flag);
|
||||
std::vector<SDOperand> Ops;
|
||||
Ops.push_back(Op.getOperand(0));
|
||||
Ops.push_back(Op.getOperand(2));
|
||||
SDOperand Lo = DAG.getNode(isAdd ? X86ISD::ADD_FLAG : X86ISD::SUB_FLAG,
|
||||
Tys, Ops);
|
||||
SDOperand Hi = DAG.getNode(isAdd ? X86ISD::ADC : X86ISD::SBB, MVT::i32,
|
||||
Op.getOperand(1), Op.getOperand(3),
|
||||
Lo.getValue(1));
|
||||
Tys.clear();
|
||||
Tys.push_back(MVT::i32);
|
||||
Tys.push_back(MVT::i32);
|
||||
Ops.clear();
|
||||
Ops.push_back(Lo);
|
||||
Ops.push_back(Hi);
|
||||
return DAG.getNode(ISD::MERGE_VALUES, Tys, Ops);
|
||||
}
|
||||
case ISD::SHL_PARTS:
|
||||
case ISD::SRA_PARTS:
|
||||
case ISD::SRL_PARTS: {
|
||||
assert(Op.getNumOperands() == 3 && Op.getValueType() == MVT::i32 &&
|
||||
"Not an i64 shift!");
|
||||
bool isSRA = Op.getOpcode() == ISD::SRA_PARTS;
|
||||
SDOperand ShOpLo = Op.getOperand(0);
|
||||
SDOperand ShOpHi = Op.getOperand(1);
|
||||
SDOperand ShAmt = Op.getOperand(2);
|
||||
SDOperand Tmp1 = isSRA ? DAG.getNode(ISD::SRA, MVT::i32, ShOpHi,
|
||||
DAG.getConstant(32, MVT::i32))
|
||||
: DAG.getConstant(0, MVT::i32);
|
||||
|
||||
SDOperand Tmp2, Tmp3;
|
||||
if (Op.getOpcode() == ISD::SHL_PARTS) {
|
||||
Tmp2 = DAG.getNode(X86ISD::SHLD, MVT::i32, ShOpHi, ShOpLo, ShAmt);
|
||||
Tmp3 = DAG.getNode(ISD::SHL, MVT::i32, ShOpLo, ShAmt);
|
||||
} else {
|
||||
Tmp2 = DAG.getNode(X86ISD::SHRD, MVT::i32, ShOpLo, ShOpHi, ShAmt);
|
||||
Tmp3 = DAG.getNode(isSRA ? ISD::SRA : ISD::SHL, MVT::i32, ShOpHi, ShAmt);
|
||||
}
|
||||
|
||||
SDOperand InFlag = DAG.getNode(X86ISD::TEST, MVT::Flag,
|
||||
ShAmt, DAG.getConstant(32, MVT::i8));
|
||||
|
||||
SDOperand Hi, Lo;
|
||||
SDOperand CC = DAG.getConstant(X86ISD::COND_E, MVT::i8);
|
||||
|
||||
std::vector<MVT::ValueType> Tys;
|
||||
Tys.push_back(MVT::i32);
|
||||
Tys.push_back(MVT::Flag);
|
||||
std::vector<SDOperand> Ops;
|
||||
if (Op.getOpcode() == ISD::SHL_PARTS) {
|
||||
Ops.push_back(Tmp2);
|
||||
Ops.push_back(Tmp3);
|
||||
Ops.push_back(CC);
|
||||
Ops.push_back(InFlag);
|
||||
Hi = DAG.getNode(X86ISD::CMOV, Tys, Ops);
|
||||
InFlag = Hi.getValue(1);
|
||||
|
||||
Ops.clear();
|
||||
Ops.push_back(Tmp3);
|
||||
Ops.push_back(Tmp1);
|
||||
Ops.push_back(CC);
|
||||
Ops.push_back(InFlag);
|
||||
Lo = DAG.getNode(X86ISD::CMOV, Tys, Ops);
|
||||
} else {
|
||||
Ops.push_back(Tmp2);
|
||||
Ops.push_back(Tmp3);
|
||||
Ops.push_back(CC);
|
||||
Lo = DAG.getNode(X86ISD::CMOV, Tys, Ops);
|
||||
InFlag = Lo.getValue(1);
|
||||
|
||||
Ops.clear();
|
||||
Ops.push_back(Tmp3);
|
||||
Ops.push_back(Tmp1);
|
||||
Ops.push_back(CC);
|
||||
Ops.push_back(InFlag);
|
||||
Hi = DAG.getNode(X86ISD::CMOV, Tys, Ops);
|
||||
}
|
||||
|
||||
Tys.clear();
|
||||
Tys.push_back(MVT::i32);
|
||||
Tys.push_back(MVT::i32);
|
||||
Ops.clear();
|
||||
Ops.push_back(Lo);
|
||||
Ops.push_back(Hi);
|
||||
return DAG.getNode(ISD::MERGE_VALUES, Tys, Ops);
|
||||
}
|
||||
case ISD::SINT_TO_FP: {
|
||||
assert(Op.getValueType() == MVT::f64 &&
|
||||
Op.getOperand(0).getValueType() == MVT::i64 &&
|
||||
@ -1362,8 +1459,16 @@ SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
|
||||
CC = DAG.getConstant(X86ISD::COND_E, MVT::i8);
|
||||
Cond = DAG.getNode(X86ISD::TEST, MVT::Flag, Cond, Cond);
|
||||
}
|
||||
return DAG.getNode(X86ISD::CMOV, Op.getValueType(),
|
||||
Op.getOperand(1), Op.getOperand(2), CC, Cond);
|
||||
|
||||
std::vector<MVT::ValueType> Tys;
|
||||
Tys.push_back(Op.getValueType());
|
||||
Tys.push_back(MVT::Flag);
|
||||
std::vector<SDOperand> Ops;
|
||||
Ops.push_back(Op.getOperand(1));
|
||||
Ops.push_back(Op.getOperand(2));
|
||||
Ops.push_back(CC);
|
||||
Ops.push_back(Cond);
|
||||
return DAG.getNode(X86ISD::CMOV, Tys, Ops);
|
||||
}
|
||||
case ISD::BRCOND: {
|
||||
SDOperand Cond = Op.getOperand(1);
|
||||
@ -1389,7 +1494,7 @@ SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
|
||||
}
|
||||
case ISD::RET: {
|
||||
// Can only be return void.
|
||||
return DAG.getNode(X86ISD::RET, MVT::Other, Op.getOperand(0),
|
||||
return DAG.getNode(X86ISD::RET_FLAG, MVT::Other, Op.getOperand(0),
|
||||
DAG.getConstant(getBytesToPopOnReturn(), MVT::i16));
|
||||
}
|
||||
case ISD::GlobalAddress: {
|
||||
@ -1414,6 +1519,12 @@ SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
|
||||
const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const {
|
||||
switch (Opcode) {
|
||||
default: return NULL;
|
||||
case X86ISD::ADD_FLAG: return "X86ISD::ADD_FLAG";
|
||||
case X86ISD::SUB_FLAG: return "X86ISD::SUB_FLAG";
|
||||
case X86ISD::ADC: return "X86ISD::ADC";
|
||||
case X86ISD::SBB: return "X86ISD::SBB";
|
||||
case X86ISD::SHLD: return "X86ISD::SHLD";
|
||||
case X86ISD::SHRD: return "X86ISD::SHRD";
|
||||
case X86ISD::FILD64m: return "X86ISD::FILD64m";
|
||||
case X86ISD::FP_TO_INT16_IN_MEM: return "X86ISD::FP_TO_INT16_IN_MEM";
|
||||
case X86ISD::FP_TO_INT32_IN_MEM: return "X86ISD::FP_TO_INT32_IN_MEM";
|
||||
@ -1430,7 +1541,6 @@ const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const {
|
||||
case X86ISD::SETCC: return "X86ISD::SETCC";
|
||||
case X86ISD::CMOV: return "X86ISD::CMOV";
|
||||
case X86ISD::BRCOND: return "X86ISD::BRCOND";
|
||||
case X86ISD::RET: return "X86ISD::RET";
|
||||
case X86ISD::RET_FLAG: return "X86ISD::RET_FLAG";
|
||||
}
|
||||
}
|
||||
|
@ -25,6 +25,21 @@ namespace llvm {
|
||||
// Start the numbering where the builtin ops leave off.
|
||||
FIRST_NUMBER = ISD::BUILTIN_OP_END+X86::INSTRUCTION_LIST_END,
|
||||
|
||||
/// ADD_FLAG, SUB_FLAG - Same as ISD::ADD and ISD::SUB except it also
|
||||
/// produces a flag result.
|
||||
ADD_FLAG,
|
||||
SUB_FLAG,
|
||||
|
||||
/// ADC, SBB - Add with carry and subtraction with borrow. These
|
||||
/// correspond to X86::ADCxx and X86::SBBxx instructions.
|
||||
ADC,
|
||||
SBB,
|
||||
|
||||
/// SHLD, SHRD - Double shift instructions. These correspond to
|
||||
/// X86::SHLDxx and X86::SHRDxx instructions.
|
||||
SHLD,
|
||||
SHRD,
|
||||
|
||||
/// FILD64m - This instruction implements SINT_TO_FP with a
|
||||
/// 64-bit source in memory and a FP reg result. This corresponds to
|
||||
/// the X86::FILD64m instruction. It has two inputs (token chain and
|
||||
@ -99,7 +114,7 @@ namespace llvm {
|
||||
/// X86 conditional moves. Operand 1 and operand 2 are the two values
|
||||
/// to select from (operand 1 is a R/W operand). Operand 3 is the condition
|
||||
/// code, and operand 4 is the flag operand produced by a CMP or TEST
|
||||
/// instruction.
|
||||
/// instruction. It also writes a flag result.
|
||||
CMOV,
|
||||
|
||||
/// X86 conditional branches. Operand 1 is the chain operand, operand 2
|
||||
@ -108,10 +123,6 @@ namespace llvm {
|
||||
/// or TEST instruction.
|
||||
BRCOND,
|
||||
|
||||
/// Return without a flag operand. Operand 1 is the number of bytes of
|
||||
/// stack to pop, and operand 2 is the chain.
|
||||
RET,
|
||||
|
||||
/// Return with a flag operand. Operand 1 is the number of bytes of stack
|
||||
/// to pop, operand 2 is the chain and operand 3 is a flag operand.
|
||||
RET_FLAG,
|
||||
|
@ -17,6 +17,10 @@
|
||||
// X86 specific DAG Nodes.
|
||||
//
|
||||
|
||||
def SDTIntShiftDOp: SDTypeProfile<1, 3,
|
||||
[SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>,
|
||||
SDTCisInt<0>, SDTCisInt<3>]>;
|
||||
|
||||
def SDTX86CmpTest : SDTypeProfile<1, 2, [SDTCisVT<0, FlagVT>, SDTCisSameAs<1, 2>]>;
|
||||
|
||||
def SDTX86Cmov : SDTypeProfile<1, 4,
|
||||
@ -33,43 +37,67 @@ def SDTX86SetCC : SDTypeProfile<1, 2,
|
||||
|
||||
def SDTX86Ret : SDTypeProfile<0, 1, [SDTCisVT<0, i16>]>;
|
||||
|
||||
def SDT_X86CallSeqStart : SDTypeProfile<0, 1, [ SDTCisVT<0, i32> ]>;
|
||||
def SDT_X86CallSeqEnd : SDTypeProfile<0, 2, [ SDTCisVT<0, i32>,
|
||||
SDTCisVT<1, i32> ]>;
|
||||
|
||||
def SDT_X86Call : SDTypeProfile<0, 1, [SDTCisVT<0, i32>]>;
|
||||
|
||||
def SDTX86FpGet : SDTypeProfile<1, 0, [SDTCisVT<0, f64>]>;
|
||||
def SDTX86FpSet : SDTypeProfile<0, 1, [SDTCisFP<0>]>;
|
||||
|
||||
def SDTX86Fld : SDTypeProfile<1, 2, [SDTCisVT<0, f64>,
|
||||
SDTCisPtrTy<1>, SDTCisVT<2, OtherVT>]>;
|
||||
def SDTX86Fst : SDTypeProfile<0, 3, [SDTCisFP<0>,
|
||||
SDTCisPtrTy<1>, SDTCisVT<2, OtherVT>]>;
|
||||
|
||||
def SDTX86RdTsc : SDTypeProfile<0, 0, []>;
|
||||
|
||||
def SDTX86FpGet : SDTypeProfile<1, 0, [SDTCisVT<0, f64>]>;
|
||||
def SDTX86FpSet : SDTypeProfile<0, 1, [SDTCisFP<0>]>;
|
||||
def X86addflag : SDNode<"X86ISD::ADD_FLAG", SDTIntBinOp ,
|
||||
[SDNPCommutative, SDNPAssociative, SDNPOutFlag]>;
|
||||
def X86subflag : SDNode<"X86ISD::SUB_FLAG", SDTIntBinOp,
|
||||
[SDNPOutFlag]>;
|
||||
def X86adc : SDNode<"X86ISD::ADC" , SDTIntBinOp ,
|
||||
[SDNPCommutative, SDNPAssociative]>;
|
||||
def X86sbb : SDNode<"X86ISD::SBB" , SDTIntBinOp>;
|
||||
|
||||
def X86shld : SDNode<"X86ISD::SHLD", SDTIntShiftDOp>;
|
||||
def X86shrd : SDNode<"X86ISD::SHRD", SDTIntShiftDOp>;
|
||||
|
||||
def X86cmp : SDNode<"X86ISD::CMP" , SDTX86CmpTest, []>;
|
||||
def X86test : SDNode<"X86ISD::TEST", SDTX86CmpTest, []>;
|
||||
|
||||
def X86cmov : SDNode<"X86ISD::CMOV", SDTX86Cmov, []>;
|
||||
def X86brcond : SDNode<"X86ISD::BRCOND", SDTX86BrCond, [SDNPHasChain]>;
|
||||
def X86cmov : SDNode<"X86ISD::CMOV", SDTX86Cmov,
|
||||
[SDNPOutFlag]>;
|
||||
def X86brcond : SDNode<"X86ISD::BRCOND", SDTX86BrCond,
|
||||
[SDNPHasChain]>;
|
||||
def X86setcc : SDNode<"X86ISD::SETCC", SDTX86SetCC, []>;
|
||||
|
||||
def X86ret : SDNode<"X86ISD::RET", SDTX86Ret, [SDNPHasChain]>;
|
||||
def X86retflag : SDNode<"X86ISD::RET_FLAG", SDTX86Ret, [SDNPHasChain]>;
|
||||
def X86retflag : SDNode<"X86ISD::RET_FLAG", SDTX86Ret,
|
||||
[SDNPHasChain, SDNPOptInFlag]>;
|
||||
|
||||
def X86fld : SDNode<"X86ISD::FLD", SDTX86Fld, [SDNPHasChain]>;
|
||||
def X86fst : SDNode<"X86ISD::FST", SDTX86Fst, [SDNPHasChain]>;
|
||||
def X86callseq_start :
|
||||
SDNode<"ISD::CALLSEQ_START", SDT_X86CallSeqStart,
|
||||
[SDNPHasChain]>;
|
||||
def X86callseq_end :
|
||||
SDNode<"ISD::CALLSEQ_END", SDT_X86CallSeqEnd,
|
||||
[SDNPHasChain]>;
|
||||
|
||||
def X86fpget : SDNode<"X86ISD::FP_GET_RESULT",
|
||||
SDTX86FpGet, [SDNPHasChain]>;
|
||||
def X86fpset : SDNode<"X86ISD::FP_SET_RESULT",
|
||||
SDTX86FpSet, [SDNPHasChain]>;
|
||||
def X86call : SDNode<"X86ISD::CALL", SDT_X86Call,
|
||||
[SDNPHasChain, SDNPOutFlag, SDNPOptInFlag]>;
|
||||
|
||||
def SDT_X86CallSeqStart : SDTypeProfile<0, 1, [ SDTCisVT<0, i32> ]>;
|
||||
def SDT_X86CallSeqEnd : SDTypeProfile<0, 2, [ SDTCisVT<0, i32>,
|
||||
SDTCisVT<1, i32> ]>;
|
||||
def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_X86CallSeqStart,
|
||||
[SDNPHasChain]>;
|
||||
def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_X86CallSeqEnd,
|
||||
[SDNPHasChain]>;
|
||||
def X86fpget : SDNode<"X86ISD::FP_GET_RESULT", SDTX86FpGet,
|
||||
[SDNPHasChain, SDNPInFlag]>;
|
||||
def X86fpset : SDNode<"X86ISD::FP_SET_RESULT", SDTX86FpSet,
|
||||
[SDNPHasChain, SDNPOutFlag]>;
|
||||
|
||||
def SDT_X86Call : SDTypeProfile<0, 1, [SDTCisVT<0, i32>]>;
|
||||
def call : SDNode<"X86ISD::CALL", SDT_X86Call, [SDNPHasChain]>;
|
||||
def X86fld : SDNode<"X86ISD::FLD", SDTX86Fld,
|
||||
[SDNPHasChain]>;
|
||||
def X86fst : SDNode<"X86ISD::FST", SDTX86Fst,
|
||||
[SDNPHasChain]>;
|
||||
|
||||
def X86rdtsc : SDNode<"X86ISD::RDTSC_DAG",SDTX86RdTsc,
|
||||
[SDNPHasChain, SDNPOutFlag]>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// X86 Operand Definitions.
|
||||
@ -334,10 +362,10 @@ def PHI : I<0, Pseudo, (ops variable_ops), "PHINODE", []>; // PHI node.
|
||||
def NOOP : I<0x90, RawFrm, (ops), "nop", []>; // nop
|
||||
|
||||
def ADJCALLSTACKDOWN : I<0, Pseudo, (ops i32imm:$amt), "#ADJCALLSTACKDOWN",
|
||||
[(callseq_start imm:$amt)]>;
|
||||
[(X86callseq_start imm:$amt)]>;
|
||||
def ADJCALLSTACKUP : I<0, Pseudo, (ops i32imm:$amt1, i32imm:$amt2),
|
||||
"#ADJCALLSTACKUP",
|
||||
[(callseq_end imm:$amt1, imm:$amt2)]>;
|
||||
[(X86callseq_end imm:$amt1, imm:$amt2)]>;
|
||||
def IMPLICIT_USE : I<0, Pseudo, (ops variable_ops), "#IMPLICIT_USE", []>;
|
||||
def IMPLICIT_DEF : I<0, Pseudo, (ops variable_ops), "#IMPLICIT_DEF", []>;
|
||||
let isTerminator = 1 in
|
||||
@ -351,15 +379,9 @@ let isTerminator = 1 in
|
||||
// Return instructions.
|
||||
let isTerminator = 1, isReturn = 1, isBarrier = 1,
|
||||
hasCtrlDep = 1, noResults = 1 in {
|
||||
// FIXME: temporary workaround for return without an incoming flag.
|
||||
def RETVOID : I<0xC3, RawFrm, (ops), "ret", [(X86ret 0)]>;
|
||||
def RETIVOID : Ii16<0xC2, RawFrm, (ops i16imm:$amt), "ret $amt",
|
||||
[(X86ret imm:$amt)]>;
|
||||
let hasInFlag = 1 in {
|
||||
def RET : I<0xC3, RawFrm, (ops), "ret", [(X86retflag 0)]>;
|
||||
def RETI : Ii16<0xC2, RawFrm, (ops i16imm:$amt), "ret $amt",
|
||||
[(X86retflag imm:$amt)]>;
|
||||
}
|
||||
def RET : I<0xC3, RawFrm, (ops), "ret", [(X86retflag 0)]>;
|
||||
def RETI : Ii16<0xC2, RawFrm, (ops i16imm:$amt), "ret $amt",
|
||||
[(X86retflag imm:$amt)]>;
|
||||
}
|
||||
|
||||
// All branches are RawFrm, Void, Branch, and Terminators
|
||||
@ -404,23 +426,21 @@ def JNP : IBr<0x8B, (ops brtarget:$dst), "jnp $dst",
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Call Instructions...
|
||||
//
|
||||
// FIXME: How about hasInFlag = 1? A fastcall would require an incoming flag
|
||||
// to stick the CopyToRegs to the call.
|
||||
let isCall = 1, noResults = 1, hasOutFlag = 1 in
|
||||
let isCall = 1, noResults = 1 in
|
||||
// All calls clobber the non-callee saved registers...
|
||||
let Defs = [EAX, ECX, EDX, FP0, FP1, FP2, FP3, FP4, FP5, FP6, ST0,
|
||||
XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7] in {
|
||||
def CALLpcrel32 : I<0xE8, RawFrm, (ops calltarget:$dst), "call $dst",
|
||||
[]>;
|
||||
def CALL32r : I<0xFF, MRM2r, (ops R32:$dst), "call {*}$dst",
|
||||
[(call R32:$dst)]>;
|
||||
[(X86call R32:$dst)]>;
|
||||
def CALL32m : I<0xFF, MRM2m, (ops i32mem:$dst), "call {*}$dst",
|
||||
[(call (loadi32 addr:$dst))]>;
|
||||
[(X86call (loadi32 addr:$dst))]>;
|
||||
}
|
||||
|
||||
def : Pat<(call tglobaladdr:$dst),
|
||||
def : Pat<(X86call tglobaladdr:$dst),
|
||||
(CALLpcrel32 tglobaladdr:$dst)>;
|
||||
def : Pat<(call externalsym:$dst),
|
||||
def : Pat<(X86call externalsym:$dst),
|
||||
(CALLpcrel32 externalsym:$dst)>;
|
||||
|
||||
// Tail call stuff.
|
||||
@ -1544,64 +1564,94 @@ let isTwoAddress = 0 in {
|
||||
// Double shift instructions (generalizations of rotate)
|
||||
|
||||
def SHLD32rrCL : I<0xA5, MRMDestReg, (ops R32:$dst, R32:$src1, R32:$src2),
|
||||
"shld{l} {%cl, $src2, $dst|$dst, $src2, %CL}", []>,
|
||||
"shld{l} {%cl, $src2, $dst|$dst, $src2, %CL}",
|
||||
[(set R32:$dst, (X86shld R32:$src1, R32:$src2, CL))]>,
|
||||
Imp<[CL],[]>, TB;
|
||||
def SHRD32rrCL : I<0xAD, MRMDestReg, (ops R32:$dst, R32:$src1, R32:$src2),
|
||||
"shrd{l} {%cl, $src2, $dst|$dst, $src2, %CL}", []>,
|
||||
"shrd{l} {%cl, $src2, $dst|$dst, $src2, %CL}",
|
||||
[(set R32:$dst, (X86shrd R32:$src1, R32:$src2, CL))]>,
|
||||
Imp<[CL],[]>, TB;
|
||||
def SHLD16rrCL : I<0xA5, MRMDestReg, (ops R16:$dst, R16:$src1, R16:$src2),
|
||||
"shld{w} {%cl, $src2, $dst|$dst, $src2, %CL}", []>,
|
||||
"shld{w} {%cl, $src2, $dst|$dst, $src2, %CL}",
|
||||
[(set R16:$dst, (X86shld R16:$src1, R16:$src2, CL))]>,
|
||||
Imp<[CL],[]>, TB, OpSize;
|
||||
def SHRD16rrCL : I<0xAD, MRMDestReg, (ops R16:$dst, R16:$src1, R16:$src2),
|
||||
"shrd{w} {%cl, $src2, $dst|$dst, $src2, %CL}", []>,
|
||||
"shrd{w} {%cl, $src2, $dst|$dst, $src2, %CL}",
|
||||
[(set R16:$dst, (X86shrd R16:$src1, R16:$src2, CL))]>,
|
||||
Imp<[CL],[]>, TB, OpSize;
|
||||
|
||||
let isCommutable = 1 in { // These instructions commute to each other.
|
||||
def SHLD32rri8 : Ii8<0xA4, MRMDestReg,
|
||||
(ops R32:$dst, R32:$src1, R32:$src2, i8imm:$src3),
|
||||
"shld{l} {$src3, $src2, $dst|$dst, $src2, $src3}", []>, TB;
|
||||
"shld{l} {$src3, $src2, $dst|$dst, $src2, $src3}",
|
||||
[(set R32:$dst, (X86shld R32:$src1, R32:$src2,
|
||||
(i8 imm:$src3)))]>,
|
||||
TB;
|
||||
def SHRD32rri8 : Ii8<0xAC, MRMDestReg,
|
||||
(ops R32:$dst, R32:$src1, R32:$src2, i8imm:$src3),
|
||||
"shrd{l} {$src3, $src2, $dst|$dst, $src2, $src3}", []>, TB;
|
||||
"shrd{l} {$src3, $src2, $dst|$dst, $src2, $src3}",
|
||||
[(set R32:$dst, (X86shrd R32:$src1, R32:$src2,
|
||||
(i8 imm:$src3)))]>,
|
||||
TB;
|
||||
def SHLD16rri8 : Ii8<0xA4, MRMDestReg,
|
||||
(ops R16:$dst, R16:$src1, R16:$src2, i8imm:$src3),
|
||||
"shld{w} {$src3, $src2, $dst|$dst, $src2, $src3}", []>,
|
||||
"shld{w} {$src3, $src2, $dst|$dst, $src2, $src3}",
|
||||
[(set R16:$dst, (X86shld R16:$src1, R16:$src2,
|
||||
(i8 imm:$src3)))]>,
|
||||
TB, OpSize;
|
||||
def SHRD16rri8 : Ii8<0xAC, MRMDestReg,
|
||||
(ops R16:$dst, R16:$src1, R16:$src2, i8imm:$src3),
|
||||
"shrd{w} {$src3, $src2, $dst|$dst, $src2, $src3}", []>,
|
||||
"shrd{w} {$src3, $src2, $dst|$dst, $src2, $src3}",
|
||||
[(set R16:$dst, (X86shrd R16:$src1, R16:$src2,
|
||||
(i8 imm:$src3)))]>,
|
||||
TB, OpSize;
|
||||
}
|
||||
|
||||
let isTwoAddress = 0 in {
|
||||
def SHLD32mrCL : I<0xA5, MRMDestMem, (ops i32mem:$dst, R32:$src2),
|
||||
"shld{l} {%cl, $src2, $dst|$dst, $src2, %CL}", []>,
|
||||
"shld{l} {%cl, $src2, $dst|$dst, $src2, %CL}",
|
||||
[(store (X86shld (loadi32 addr:$dst), R32:$src2, CL),
|
||||
addr:$dst)]>,
|
||||
Imp<[CL],[]>, TB;
|
||||
def SHRD32mrCL : I<0xAD, MRMDestMem, (ops i32mem:$dst, R32:$src2),
|
||||
"shrd{l} {%cl, $src2, $dst|$dst, $src2, %CL}", []>,
|
||||
"shrd{l} {%cl, $src2, $dst|$dst, $src2, %CL}",
|
||||
[(store (X86shrd (loadi32 addr:$dst), R32:$src2, CL),
|
||||
addr:$dst)]>,
|
||||
Imp<[CL],[]>, TB;
|
||||
def SHLD32mri8 : Ii8<0xA4, MRMDestMem,
|
||||
(ops i32mem:$dst, R32:$src2, i8imm:$src3),
|
||||
"shld{l} {$src3, $src2, $dst|$dst, $src2, $src3}", []>,
|
||||
"shld{l} {$src3, $src2, $dst|$dst, $src2, $src3}",
|
||||
[(store (X86shld (loadi32 addr:$dst), R32:$src2,
|
||||
(i8 imm:$src3)), addr:$dst)]>,
|
||||
TB;
|
||||
def SHRD32mri8 : Ii8<0xAC, MRMDestMem,
|
||||
(ops i32mem:$dst, R32:$src2, i8imm:$src3),
|
||||
"shrd{l} {$src3, $src2, $dst|$dst, $src2, $src3}", []>,
|
||||
"shrd{l} {$src3, $src2, $dst|$dst, $src2, $src3}",
|
||||
[(store (X86shrd (loadi32 addr:$dst), R32:$src2,
|
||||
(i8 imm:$src3)), addr:$dst)]>,
|
||||
TB;
|
||||
|
||||
def SHLD16mrCL : I<0xA5, MRMDestMem, (ops i16mem:$dst, R16:$src2),
|
||||
"shld{w} {%cl, $src2, $dst|$dst, $src2, %CL}", []>,
|
||||
"shld{w} {%cl, $src2, $dst|$dst, $src2, %CL}",
|
||||
[(store (X86shld (loadi16 addr:$dst), R16:$src2, CL),
|
||||
addr:$dst)]>,
|
||||
Imp<[CL],[]>, TB, OpSize;
|
||||
def SHRD16mrCL : I<0xAD, MRMDestMem, (ops i16mem:$dst, R16:$src2),
|
||||
"shrd{w} {%cl, $src2, $dst|$dst, $src2, %CL}", []>,
|
||||
"shrd{w} {%cl, $src2, $dst|$dst, $src2, %CL}",
|
||||
[(store (X86shrd (loadi16 addr:$dst), R16:$src2, CL),
|
||||
addr:$dst)]>,
|
||||
Imp<[CL],[]>, TB, OpSize;
|
||||
def SHLD16mri8 : Ii8<0xA4, MRMDestMem,
|
||||
(ops i16mem:$dst, R16:$src2, i8imm:$src3),
|
||||
"shld{w} {$src3, $src2, $dst|$dst, $src2, $src3}", []>,
|
||||
"shld{w} {$src3, $src2, $dst|$dst, $src2, $src3}",
|
||||
[(store (X86shld (loadi16 addr:$dst), R16:$src2,
|
||||
(i8 imm:$src3)), addr:$dst)]>,
|
||||
TB, OpSize;
|
||||
def SHRD16mri8 : Ii8<0xAC, MRMDestMem,
|
||||
(ops i16mem:$dst, R16:$src2, i8imm:$src3),
|
||||
"shrd{w} {$src3, $src2, $dst|$dst, $src2, $src3}", []>,
|
||||
"shrd{w} {$src3, $src2, $dst|$dst, $src2, $src3}",
|
||||
[(store (X86shrd (loadi16 addr:$dst), R16:$src2,
|
||||
(i8 imm:$src3)), addr:$dst)]>,
|
||||
TB, OpSize;
|
||||
}
|
||||
|
||||
@ -1684,22 +1734,29 @@ let isTwoAddress = 0 in {
|
||||
|
||||
let isCommutable = 1 in { // X = ADC Y, Z --> X = ADC Z, Y
|
||||
def ADC32rr : I<0x11, MRMDestReg, (ops R32:$dst, R32:$src1, R32:$src2),
|
||||
"adc{l} {$src2, $dst|$dst, $src2}", []>;
|
||||
"adc{l} {$src2, $dst|$dst, $src2}",
|
||||
[(set R32:$dst, (X86adc R32:$src1, R32:$src2))]>;
|
||||
}
|
||||
def ADC32rm : I<0x13, MRMSrcMem , (ops R32:$dst, R32:$src1, i32mem:$src2),
|
||||
"adc{l} {$src2, $dst|$dst, $src2}", []>;
|
||||
"adc{l} {$src2, $dst|$dst, $src2}",
|
||||
[(set R32:$dst, (X86adc R32:$src1, (load addr:$src2)))]>;
|
||||
def ADC32ri : Ii32<0x81, MRM2r, (ops R32:$dst, R32:$src1, i32imm:$src2),
|
||||
"adc{l} {$src2, $dst|$dst, $src2}", []>;
|
||||
def ADC32ri8 : Ii8<0x83, MRM2r, (ops R32:$dst, R32:$src1, i8imm:$src2),
|
||||
"adc{l} {$src2, $dst|$dst, $src2}", []>;
|
||||
"adc{l} {$src2, $dst|$dst, $src2}",
|
||||
[(set R32:$dst, (X86adc R32:$src1, imm:$src2))]>;
|
||||
def ADC32ri8 : Ii8<0x83, MRM2r, (ops R32:$dst, R32:$src1, i32i8imm:$src2),
|
||||
"adc{l} {$src2, $dst|$dst, $src2}",
|
||||
[(set R32:$dst, (X86adc R32:$src1, i32immSExt8:$src2))]>;
|
||||
|
||||
let isTwoAddress = 0 in {
|
||||
def ADC32mr : I<0x11, MRMDestMem, (ops i32mem:$dst, R32:$src2),
|
||||
"adc{l} {$src2, $dst|$dst, $src2}", []>;
|
||||
"adc{l} {$src2, $dst|$dst, $src2}",
|
||||
[(store (X86adc (load addr:$dst), R32:$src2), addr:$dst)]>;
|
||||
def ADC32mi : Ii32<0x81, MRM2m, (ops i32mem:$dst, i32imm:$src2),
|
||||
"adc{l} {$src2, $dst|$dst, $src2}", []>;
|
||||
def ADC32mi8 : Ii8<0x83, MRM2m, (ops i32mem:$dst, i8imm :$src2),
|
||||
"adc{l} {$src2, $dst|$dst, $src2}", []>;
|
||||
"adc{l} {$src2, $dst|$dst, $src2}",
|
||||
[(store (X86adc (loadi32 addr:$dst), imm:$src2), addr:$dst)]>;
|
||||
def ADC32mi8 : Ii8<0x83, MRM2m, (ops i32mem:$dst, i32i8imm :$src2),
|
||||
"adc{l} {$src2, $dst|$dst, $src2}",
|
||||
[(store (X86adc (load addr:$dst), i32immSExt8:$src2), addr:$dst)]>;
|
||||
}
|
||||
|
||||
def SUB8rr : I<0x28, MRMDestReg, (ops R8 :$dst, R8 :$src1, R8 :$src2),
|
||||
@ -1768,36 +1825,52 @@ let isTwoAddress = 0 in {
|
||||
}
|
||||
|
||||
def SBB32rr : I<0x19, MRMDestReg, (ops R32:$dst, R32:$src1, R32:$src2),
|
||||
"sbb{l} {$src2, $dst|$dst, $src2}", []>;
|
||||
"sbb{l} {$src2, $dst|$dst, $src2}",
|
||||
[(set R32:$dst, (X86sbb R32:$src1, R32:$src2))]>;
|
||||
|
||||
let isTwoAddress = 0 in {
|
||||
def SBB32mr : I<0x19, MRMDestMem, (ops i32mem:$dst, R32:$src2),
|
||||
"sbb{l} {$src2, $dst|$dst, $src2}", []>;
|
||||
"sbb{l} {$src2, $dst|$dst, $src2}",
|
||||
[(store (X86sbb (load addr:$dst), R32:$src2), addr:$dst)]>;
|
||||
def SBB8mi : Ii32<0x80, MRM3m, (ops i8mem:$dst, i8imm:$src2),
|
||||
"sbb{b} {$src2, $dst|$dst, $src2}", []>;
|
||||
"sbb{b} {$src2, $dst|$dst, $src2}",
|
||||
[(store (X86sbb (loadi8 addr:$dst), imm:$src2), addr:$dst)]>;
|
||||
def SBB16mi : Ii32<0x81, MRM3m, (ops i16mem:$dst, i16imm:$src2),
|
||||
"sbb{w} {$src2, $dst|$dst, $src2}", []>, OpSize;
|
||||
"sbb{w} {$src2, $dst|$dst, $src2}",
|
||||
[(store (X86sbb (loadi16 addr:$dst), imm:$src2), addr:$dst)]>,
|
||||
OpSize;
|
||||
def SBB32mi : Ii32<0x81, MRM3m, (ops i32mem:$dst, i32imm:$src2),
|
||||
"sbb{l} {$src2, $dst|$dst, $src2}", []>;
|
||||
def SBB16mi8 : Ii8<0x83, MRM3m, (ops i16mem:$dst, i8imm :$src2),
|
||||
"sbb{w} {$src2, $dst|$dst, $src2}", []>, OpSize;
|
||||
def SBB32mi8 : Ii8<0x83, MRM3m, (ops i32mem:$dst, i8imm :$src2),
|
||||
"sbb{l} {$src2, $dst|$dst, $src2}", []>;
|
||||
"sbb{l} {$src2, $dst|$dst, $src2}",
|
||||
[(store (X86sbb (loadi32 addr:$dst), imm:$src2), addr:$dst)]>;
|
||||
def SBB16mi8 : Ii8<0x83, MRM3m, (ops i16mem:$dst, i16i8imm :$src2),
|
||||
"sbb{w} {$src2, $dst|$dst, $src2}",
|
||||
[(store (X86sbb (load addr:$dst), i16immSExt8:$src2), addr:$dst)]>,
|
||||
OpSize;
|
||||
def SBB32mi8 : Ii8<0x83, MRM3m, (ops i32mem:$dst, i32i8imm :$src2),
|
||||
"sbb{l} {$src2, $dst|$dst, $src2}",
|
||||
[(store (X86sbb (load addr:$dst), i32immSExt8:$src2), addr:$dst)]>;
|
||||
}
|
||||
def SBB8ri : Ii8<0x80, MRM3r, (ops R8:$dst, R8:$src1, i8imm:$src2),
|
||||
"sbb{b} {$src2, $dst|$dst, $src2}", []>;
|
||||
"sbb{b} {$src2, $dst|$dst, $src2}",
|
||||
[(set R8:$dst, (X86sbb R8:$src1, imm:$src2))]>;
|
||||
def SBB16ri : Ii16<0x81, MRM3r, (ops R16:$dst, R16:$src1, i16imm:$src2),
|
||||
"sbb{w} {$src2, $dst|$dst, $src2}", []>, OpSize;
|
||||
"sbb{w} {$src2, $dst|$dst, $src2}",
|
||||
[(set R16:$dst, (X86sbb R16:$src1, imm:$src2))]>, OpSize;
|
||||
|
||||
def SBB32rm : I<0x1B, MRMSrcMem, (ops R32:$dst, R32:$src1, i32mem:$src2),
|
||||
"sbb{l} {$src2, $dst|$dst, $src2}", []>;
|
||||
"sbb{l} {$src2, $dst|$dst, $src2}",
|
||||
[(set R32:$dst, (X86sbb R32:$src1, (load addr:$src2)))]>;
|
||||
def SBB32ri : Ii32<0x81, MRM3r, (ops R32:$dst, R32:$src1, i32imm:$src2),
|
||||
"sbb{l} {$src2, $dst|$dst, $src2}", []>;
|
||||
"sbb{l} {$src2, $dst|$dst, $src2}",
|
||||
[(set R32:$dst, (X86sbb R32:$src1, imm:$src2))]>;
|
||||
|
||||
def SBB16ri8 : Ii8<0x83, MRM3r, (ops R16:$dst, R16:$src1, i8imm:$src2),
|
||||
"sbb{w} {$src2, $dst|$dst, $src2}", []>, OpSize;
|
||||
def SBB32ri8 : Ii8<0x83, MRM3r, (ops R32:$dst, R32:$src1, i8imm:$src2),
|
||||
"sbb{l} {$src2, $dst|$dst, $src2}", []>;
|
||||
def SBB16ri8 : Ii8<0x83, MRM3r, (ops R16:$dst, R16:$src1, i16i8imm:$src2),
|
||||
"sbb{w} {$src2, $dst|$dst, $src2}",
|
||||
[(set R16:$dst, (X86sbb R16:$src1, i16immSExt8:$src2))]>,
|
||||
OpSize;
|
||||
def SBB32ri8 : Ii8<0x83, MRM3r, (ops R32:$dst, R32:$src1, i32i8imm:$src2),
|
||||
"sbb{l} {$src2, $dst|$dst, $src2}",
|
||||
[(set R32:$dst, (X86sbb R32:$src1, i32immSExt8:$src2))]>;
|
||||
|
||||
let isCommutable = 1 in { // X = IMUL Y, Z --> X = IMUL Z, Y
|
||||
def IMUL16rr : I<0xAF, MRMSrcReg, (ops R16:$dst, R16:$src1, R16:$src2),
|
||||
@ -1817,6 +1890,25 @@ def IMUL32rm : I<0xAF, MRMSrcMem, (ops R32:$dst, R32:$src1, i32mem:$src2),
|
||||
|
||||
} // end Two Address instructions
|
||||
|
||||
// X86 specific add which produces a flag.
|
||||
def : Pat<(X86addflag R32:$src1, R32:$src2),
|
||||
(ADD32rr R32:$src1, R32:$src2)>;
|
||||
def : Pat<(X86addflag R32:$src1, (load addr:$src2)),
|
||||
(ADD32rm R32:$src1, addr:$src2)>;
|
||||
def : Pat<(X86addflag R32:$src1, imm:$src2),
|
||||
(ADD32ri R32:$src1, imm:$src2)>;
|
||||
def : Pat<(X86addflag R32:$src1, i32immSExt8:$src2),
|
||||
(ADD32ri8 R32:$src1, i32immSExt8:$src2)>;
|
||||
|
||||
def : Pat<(X86subflag R32:$src1, R32:$src2),
|
||||
(SUB32rr R32:$src1, R32:$src2)>;
|
||||
def : Pat<(X86subflag R32:$src1, (load addr:$src2)),
|
||||
(SUB32rm R32:$src1, addr:$src2)>;
|
||||
def : Pat<(X86subflag R32:$src1, imm:$src2),
|
||||
(SUB32ri R32:$src1, imm:$src2)>;
|
||||
def : Pat<(X86subflag R32:$src1, i32immSExt8:$src2),
|
||||
(SUB32ri8 R32:$src1, i32immSExt8:$src2)>;
|
||||
|
||||
// Suprisingly enough, these are not two address instructions!
|
||||
def IMUL16rri : Ii16<0x69, MRMSrcReg, // R16 = R16*I16
|
||||
(ops R16:$dst, R16:$src1, i16imm:$src2),
|
||||
@ -2471,13 +2563,12 @@ class FpI<dag ops, FPFormat fp, list<dag> pattern>
|
||||
}
|
||||
|
||||
// Random Pseudo Instructions.
|
||||
let hasInFlag = 1 in
|
||||
def FpGETRESULT : FpI<(ops RFP:$dst), SpecialFP, []>; // FPR = ST(0)
|
||||
def FpGETRESULT : FpI<(ops RFP:$dst), SpecialFP, []>; // FPR = ST(0)
|
||||
|
||||
// Do not inline into instruction def. since it isn't predicated on FPStack.
|
||||
def : Pat<(X86fpget), (FpGETRESULT)>;
|
||||
|
||||
let noResults = 1, hasOutFlag = 1 in
|
||||
let noResults = 1 in
|
||||
def FpSETRESULT : FpI<(ops RFP:$src), SpecialFP,
|
||||
[]>, Imp<[], [ST0]>; // ST(0) = FPR
|
||||
|
||||
@ -2754,8 +2845,8 @@ def FLDCW16m : I<0xD9, MRM5m, // X87 control world = [mem16]
|
||||
// Miscellaneous Instructions
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
def RDTSC : I<0x31, RawFrm, (ops), "rdtsc", []>, TB, Imp<[],[EAX,EDX]>;
|
||||
|
||||
def RDTSC : I<0x31, RawFrm, (ops), "rdtsc", [(X86rdtsc)]>,
|
||||
TB, Imp<[],[EAX,EDX]>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Some peepholes
|
||||
|
@ -568,8 +568,6 @@ void X86RegisterInfo::emitEpilogue(MachineFunction &MF,
|
||||
switch (MBBI->getOpcode()) {
|
||||
case X86::RET:
|
||||
case X86::RETI:
|
||||
case X86::RETVOID: // FIXME: See X86InstrInfo.td
|
||||
case X86::RETIVOID: // FIXME: See X86InstrInfo.td
|
||||
case X86::TAILJMPd:
|
||||
case X86::TAILJMPr:
|
||||
case X86::TAILJMPm: break; // These are ok
|
||||
|
Loading…
Reference in New Issue
Block a user