mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-28 21:34:23 +00:00
Change the X86 backend to stop using the evil ADDC/ADDE/SUBC/SUBE nodes (which
their carry depenedencies with MVT::Flag operands) and use clean and beautiful EFLAGS dependences instead. We do this by changing the modelling of SBB/ADC to have EFLAGS input and outputs (which is what requires the previous scheduler change) and change X86 ISelLowering to custom lower ADDC and friends down to X86ISD::ADD/ADC/SUB/SBB nodes. With the previous series of changes, this causes no changes in the testsuite, woo. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@122213 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
4d8455ea4d
commit
5b85654844
@ -132,6 +132,26 @@ X86TargetLowering::X86TargetLowering(X86TargetMachine &TM)
|
|||||||
|
|
||||||
setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote);
|
setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote);
|
||||||
|
|
||||||
|
setOperationAction(ISD::ADDC, MVT::i8, Custom);
|
||||||
|
setOperationAction(ISD::ADDC, MVT::i16, Custom);
|
||||||
|
setOperationAction(ISD::ADDC, MVT::i32, Custom);
|
||||||
|
setOperationAction(ISD::ADDC, MVT::i64, Custom);
|
||||||
|
|
||||||
|
setOperationAction(ISD::ADDE, MVT::i8, Custom);
|
||||||
|
setOperationAction(ISD::ADDE, MVT::i16, Custom);
|
||||||
|
setOperationAction(ISD::ADDE, MVT::i32, Custom);
|
||||||
|
setOperationAction(ISD::ADDE, MVT::i64, Custom);
|
||||||
|
|
||||||
|
setOperationAction(ISD::SUBC, MVT::i8, Custom);
|
||||||
|
setOperationAction(ISD::SUBC, MVT::i16, Custom);
|
||||||
|
setOperationAction(ISD::SUBC, MVT::i32, Custom);
|
||||||
|
setOperationAction(ISD::SUBC, MVT::i64, Custom);
|
||||||
|
|
||||||
|
setOperationAction(ISD::SUBE, MVT::i8, Custom);
|
||||||
|
setOperationAction(ISD::SUBE, MVT::i16, Custom);
|
||||||
|
setOperationAction(ISD::SUBE, MVT::i32, Custom);
|
||||||
|
setOperationAction(ISD::SUBE, MVT::i64, Custom);
|
||||||
|
|
||||||
// We don't accept any truncstore of integer registers.
|
// We don't accept any truncstore of integer registers.
|
||||||
setTruncStoreAction(MVT::i64, MVT::i32, Expand);
|
setTruncStoreAction(MVT::i64, MVT::i32, Expand);
|
||||||
setTruncStoreAction(MVT::i64, MVT::i16, Expand);
|
setTruncStoreAction(MVT::i64, MVT::i16, Expand);
|
||||||
@ -7179,6 +7199,8 @@ static bool isX86LogicalCmp(SDValue Op) {
|
|||||||
if (Op.getResNo() == 1 &&
|
if (Op.getResNo() == 1 &&
|
||||||
(Opc == X86ISD::ADD ||
|
(Opc == X86ISD::ADD ||
|
||||||
Opc == X86ISD::SUB ||
|
Opc == X86ISD::SUB ||
|
||||||
|
Opc == X86ISD::ADC ||
|
||||||
|
Opc == X86ISD::SBB ||
|
||||||
Opc == X86ISD::SMUL ||
|
Opc == X86ISD::SMUL ||
|
||||||
Opc == X86ISD::UMUL ||
|
Opc == X86ISD::UMUL ||
|
||||||
Opc == X86ISD::INC ||
|
Opc == X86ISD::INC ||
|
||||||
@ -8614,6 +8636,7 @@ SDValue X86TargetLowering::LowerBITCAST(SDValue Op,
|
|||||||
// All other conversions need to be expanded.
|
// All other conversions need to be expanded.
|
||||||
return SDValue();
|
return SDValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
SDValue X86TargetLowering::LowerLOAD_SUB(SDValue Op, SelectionDAG &DAG) const {
|
SDValue X86TargetLowering::LowerLOAD_SUB(SDValue Op, SelectionDAG &DAG) const {
|
||||||
SDNode *Node = Op.getNode();
|
SDNode *Node = Op.getNode();
|
||||||
DebugLoc dl = Node->getDebugLoc();
|
DebugLoc dl = Node->getDebugLoc();
|
||||||
@ -8628,6 +8651,32 @@ SDValue X86TargetLowering::LowerLOAD_SUB(SDValue Op, SelectionDAG &DAG) const {
|
|||||||
cast<AtomicSDNode>(Node)->getAlignment());
|
cast<AtomicSDNode>(Node)->getAlignment());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static SDValue LowerADDC_ADDE_SUBC_SUBE(SDValue Op, SelectionDAG &DAG) {
|
||||||
|
EVT VT = Op.getNode()->getValueType(0);
|
||||||
|
|
||||||
|
// Let legalize expand this if it isn't a legal type yet.
|
||||||
|
if (!DAG.getTargetLoweringInfo().isTypeLegal(VT))
|
||||||
|
return SDValue();
|
||||||
|
|
||||||
|
SDVTList VTs = DAG.getVTList(VT, MVT::i32);
|
||||||
|
|
||||||
|
unsigned Opc;
|
||||||
|
bool ExtraOp = false;
|
||||||
|
switch (Op.getOpcode()) {
|
||||||
|
default: assert(0 && "Invalid code");
|
||||||
|
case ISD::ADDC: Opc = X86ISD::ADD; break;
|
||||||
|
case ISD::ADDE: Opc = X86ISD::ADC; ExtraOp = true; break;
|
||||||
|
case ISD::SUBC: Opc = X86ISD::SUB; break;
|
||||||
|
case ISD::SUBE: Opc = X86ISD::SBB; ExtraOp = true; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ExtraOp)
|
||||||
|
return DAG.getNode(Opc, Op->getDebugLoc(), VTs, Op.getOperand(0),
|
||||||
|
Op.getOperand(1));
|
||||||
|
return DAG.getNode(Opc, Op->getDebugLoc(), VTs, Op.getOperand(0),
|
||||||
|
Op.getOperand(1), Op.getOperand(2));
|
||||||
|
}
|
||||||
|
|
||||||
/// LowerOperation - Provide custom lowering hooks for some operations.
|
/// LowerOperation - Provide custom lowering hooks for some operations.
|
||||||
///
|
///
|
||||||
SDValue X86TargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
|
SDValue X86TargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
|
||||||
@ -8686,6 +8735,10 @@ SDValue X86TargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
|
|||||||
case ISD::UMULO: return LowerXALUO(Op, DAG);
|
case ISD::UMULO: return LowerXALUO(Op, DAG);
|
||||||
case ISD::READCYCLECOUNTER: return LowerREADCYCLECOUNTER(Op, DAG);
|
case ISD::READCYCLECOUNTER: return LowerREADCYCLECOUNTER(Op, DAG);
|
||||||
case ISD::BITCAST: return LowerBITCAST(Op, DAG);
|
case ISD::BITCAST: return LowerBITCAST(Op, DAG);
|
||||||
|
case ISD::ADDC:
|
||||||
|
case ISD::ADDE:
|
||||||
|
case ISD::SUBC:
|
||||||
|
case ISD::SUBE: return LowerADDC_ADDE_SUBC_SUBE(Op, DAG);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -8722,6 +8775,12 @@ void X86TargetLowering::ReplaceNodeResults(SDNode *N,
|
|||||||
default:
|
default:
|
||||||
assert(false && "Do not know how to custom type legalize this operation!");
|
assert(false && "Do not know how to custom type legalize this operation!");
|
||||||
return;
|
return;
|
||||||
|
case ISD::ADDC:
|
||||||
|
case ISD::ADDE:
|
||||||
|
case ISD::SUBC:
|
||||||
|
case ISD::SUBE:
|
||||||
|
// We don't want to expand or promote these.
|
||||||
|
return;
|
||||||
case ISD::FP_TO_SINT: {
|
case ISD::FP_TO_SINT: {
|
||||||
std::pair<SDValue,SDValue> Vals =
|
std::pair<SDValue,SDValue> Vals =
|
||||||
FP_TO_INTHelper(SDValue(N, 0), DAG, true);
|
FP_TO_INTHelper(SDValue(N, 0), DAG, true);
|
||||||
@ -8885,6 +8944,8 @@ const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const {
|
|||||||
case X86ISD::PCMPGTQ: return "X86ISD::PCMPGTQ";
|
case X86ISD::PCMPGTQ: return "X86ISD::PCMPGTQ";
|
||||||
case X86ISD::ADD: return "X86ISD::ADD";
|
case X86ISD::ADD: return "X86ISD::ADD";
|
||||||
case X86ISD::SUB: return "X86ISD::SUB";
|
case X86ISD::SUB: return "X86ISD::SUB";
|
||||||
|
case X86ISD::ADC: return "X86ISD::ADC";
|
||||||
|
case X86ISD::SBB: return "X86ISD::SBB";
|
||||||
case X86ISD::SMUL: return "X86ISD::SMUL";
|
case X86ISD::SMUL: return "X86ISD::SMUL";
|
||||||
case X86ISD::UMUL: return "X86ISD::UMUL";
|
case X86ISD::UMUL: return "X86ISD::UMUL";
|
||||||
case X86ISD::INC: return "X86ISD::INC";
|
case X86ISD::INC: return "X86ISD::INC";
|
||||||
@ -10324,6 +10385,8 @@ void X86TargetLowering::computeMaskedBitsForTargetNode(const SDValue Op,
|
|||||||
default: break;
|
default: break;
|
||||||
case X86ISD::ADD:
|
case X86ISD::ADD:
|
||||||
case X86ISD::SUB:
|
case X86ISD::SUB:
|
||||||
|
case X86ISD::ADC:
|
||||||
|
case X86ISD::SBB:
|
||||||
case X86ISD::SMUL:
|
case X86ISD::SMUL:
|
||||||
case X86ISD::UMUL:
|
case X86ISD::UMUL:
|
||||||
case X86ISD::INC:
|
case X86ISD::INC:
|
||||||
|
@ -86,8 +86,8 @@ namespace llvm {
|
|||||||
/// X86 bit-test instructions.
|
/// X86 bit-test instructions.
|
||||||
BT,
|
BT,
|
||||||
|
|
||||||
/// X86 SetCC. Operand 0 is condition code, and operand 1 is the flag
|
/// X86 SetCC. Operand 0 is condition code, and operand 1 is the EFLAGS
|
||||||
/// operand produced by a CMP instruction.
|
/// operand, usually produced by a CMP instruction.
|
||||||
SETCC,
|
SETCC,
|
||||||
|
|
||||||
// Same as SETCC except it's materialized with a sbb and the value is all
|
// Same as SETCC except it's materialized with a sbb and the value is all
|
||||||
@ -207,7 +207,7 @@ namespace llvm {
|
|||||||
PCMPGTB, PCMPGTW, PCMPGTD, PCMPGTQ,
|
PCMPGTB, PCMPGTW, PCMPGTD, PCMPGTQ,
|
||||||
|
|
||||||
// ADD, SUB, SMUL, etc. - Arithmetic operations with FLAGS results.
|
// ADD, SUB, SMUL, etc. - Arithmetic operations with FLAGS results.
|
||||||
ADD, SUB, SMUL,
|
ADD, SUB, ADC, SBB, SMUL,
|
||||||
INC, DEC, OR, XOR, AND,
|
INC, DEC, OR, XOR, AND,
|
||||||
|
|
||||||
UMUL, // LOW, HI, FLAGS = umul LHS, RHS
|
UMUL, // LOW, HI, FLAGS = umul LHS, RHS
|
||||||
|
@ -631,6 +631,15 @@ class BinOpRR_RF<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
|
|||||||
[(set typeinfo.RegClass:$dst, EFLAGS,
|
[(set typeinfo.RegClass:$dst, EFLAGS,
|
||||||
(opnode typeinfo.RegClass:$src1, typeinfo.RegClass:$src2))]>;
|
(opnode typeinfo.RegClass:$src1, typeinfo.RegClass:$src2))]>;
|
||||||
|
|
||||||
|
// BinOpRR_RFF - Instructions like "adc reg, reg, reg", where the pattern has
|
||||||
|
// both a regclass and EFLAGS as a result, and has EFLAGS as input.
|
||||||
|
class BinOpRR_RFF<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
|
||||||
|
SDNode opnode>
|
||||||
|
: BinOpRR<opcode, mnemonic, typeinfo, (outs typeinfo.RegClass:$dst),
|
||||||
|
[(set typeinfo.RegClass:$dst, EFLAGS,
|
||||||
|
(opnode typeinfo.RegClass:$src1, typeinfo.RegClass:$src2,
|
||||||
|
EFLAGS))]>;
|
||||||
|
|
||||||
// BinOpRR_Rev - Instructions like "add reg, reg, reg" (reversed encoding).
|
// BinOpRR_Rev - Instructions like "add reg, reg, reg" (reversed encoding).
|
||||||
class BinOpRR_Rev<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo>
|
class BinOpRR_Rev<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo>
|
||||||
: ITy<opcode, MRMSrcReg, typeinfo,
|
: ITy<opcode, MRMSrcReg, typeinfo,
|
||||||
@ -669,6 +678,14 @@ class BinOpRM_RF<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
|
|||||||
[(set typeinfo.RegClass:$dst, EFLAGS,
|
[(set typeinfo.RegClass:$dst, EFLAGS,
|
||||||
(opnode typeinfo.RegClass:$src1, (typeinfo.LoadNode addr:$src2)))]>;
|
(opnode typeinfo.RegClass:$src1, (typeinfo.LoadNode addr:$src2)))]>;
|
||||||
|
|
||||||
|
// BinOpRM_RFF - Instructions like "adc reg, reg, [mem]".
|
||||||
|
class BinOpRM_RFF<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
|
||||||
|
SDNode opnode>
|
||||||
|
: BinOpRM<opcode, mnemonic, typeinfo, (outs typeinfo.RegClass:$dst),
|
||||||
|
[(set typeinfo.RegClass:$dst, EFLAGS,
|
||||||
|
(opnode typeinfo.RegClass:$src1, (typeinfo.LoadNode addr:$src2),
|
||||||
|
EFLAGS))]>;
|
||||||
|
|
||||||
// BinOpRI - Instructions like "add reg, reg, imm".
|
// BinOpRI - Instructions like "add reg, reg, imm".
|
||||||
class BinOpRI<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
|
class BinOpRI<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
|
||||||
Format f, dag outlist, list<dag> pattern>
|
Format f, dag outlist, list<dag> pattern>
|
||||||
@ -699,6 +716,14 @@ class BinOpRI_RF<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
|
|||||||
[(set typeinfo.RegClass:$dst, EFLAGS,
|
[(set typeinfo.RegClass:$dst, EFLAGS,
|
||||||
(opnode typeinfo.RegClass:$src1, typeinfo.ImmOperator:$src2))]>;
|
(opnode typeinfo.RegClass:$src1, typeinfo.ImmOperator:$src2))]>;
|
||||||
|
|
||||||
|
// BinOpRI_RFF - Instructions like "adc reg, reg, imm".
|
||||||
|
class BinOpRI_RFF<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
|
||||||
|
SDNode opnode, Format f>
|
||||||
|
: BinOpRI<opcode, mnemonic, typeinfo, f, (outs typeinfo.RegClass:$dst),
|
||||||
|
[(set typeinfo.RegClass:$dst, EFLAGS,
|
||||||
|
(opnode typeinfo.RegClass:$src1, typeinfo.ImmOperator:$src2,
|
||||||
|
EFLAGS))]>;
|
||||||
|
|
||||||
// BinOpRI8 - Instructions like "add reg, reg, imm8".
|
// BinOpRI8 - Instructions like "add reg, reg, imm8".
|
||||||
class BinOpRI8<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
|
class BinOpRI8<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
|
||||||
Format f, dag outlist, list<dag> pattern>
|
Format f, dag outlist, list<dag> pattern>
|
||||||
@ -729,6 +754,14 @@ class BinOpRI8_RF<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
|
|||||||
[(set typeinfo.RegClass:$dst, EFLAGS,
|
[(set typeinfo.RegClass:$dst, EFLAGS,
|
||||||
(opnode typeinfo.RegClass:$src1, typeinfo.Imm8Operator:$src2))]>;
|
(opnode typeinfo.RegClass:$src1, typeinfo.Imm8Operator:$src2))]>;
|
||||||
|
|
||||||
|
// BinOpRI8_RFF - Instructions like "adc reg, reg, imm8".
|
||||||
|
class BinOpRI8_RFF<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
|
||||||
|
SDNode opnode, Format f>
|
||||||
|
: BinOpRI8<opcode, mnemonic, typeinfo, f, (outs typeinfo.RegClass:$dst),
|
||||||
|
[(set typeinfo.RegClass:$dst, EFLAGS,
|
||||||
|
(opnode typeinfo.RegClass:$src1, typeinfo.Imm8Operator:$src2,
|
||||||
|
EFLAGS))]>;
|
||||||
|
|
||||||
// BinOpMR - Instructions like "add [mem], reg".
|
// BinOpMR - Instructions like "add [mem], reg".
|
||||||
class BinOpMR<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
|
class BinOpMR<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
|
||||||
list<dag> pattern>
|
list<dag> pattern>
|
||||||
@ -743,6 +776,14 @@ class BinOpMR_RMW<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
|
|||||||
[(store (opnode (load addr:$dst), typeinfo.RegClass:$src), addr:$dst),
|
[(store (opnode (load addr:$dst), typeinfo.RegClass:$src), addr:$dst),
|
||||||
(implicit EFLAGS)]>;
|
(implicit EFLAGS)]>;
|
||||||
|
|
||||||
|
// BinOpMR_RMW_FF - Instructions like "adc [mem], reg".
|
||||||
|
class BinOpMR_RMW_FF<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
|
||||||
|
SDNode opnode>
|
||||||
|
: BinOpMR<opcode, mnemonic, typeinfo,
|
||||||
|
[(store (opnode (load addr:$dst), typeinfo.RegClass:$src, EFLAGS),
|
||||||
|
addr:$dst),
|
||||||
|
(implicit EFLAGS)]>;
|
||||||
|
|
||||||
// BinOpMR_F - Instructions like "cmp [mem], reg".
|
// BinOpMR_F - Instructions like "cmp [mem], reg".
|
||||||
class BinOpMR_F<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
|
class BinOpMR_F<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
|
||||||
SDNode opnode>
|
SDNode opnode>
|
||||||
@ -766,6 +807,14 @@ class BinOpMI_RMW<string mnemonic, X86TypeInfo typeinfo,
|
|||||||
typeinfo.ImmOperator:$src), addr:$dst),
|
typeinfo.ImmOperator:$src), addr:$dst),
|
||||||
(implicit EFLAGS)]>;
|
(implicit EFLAGS)]>;
|
||||||
|
|
||||||
|
// BinOpMI_RMW_FF - Instructions like "adc [mem], imm".
|
||||||
|
class BinOpMI_RMW_FF<string mnemonic, X86TypeInfo typeinfo,
|
||||||
|
SDNode opnode, Format f>
|
||||||
|
: BinOpMI<mnemonic, typeinfo, f,
|
||||||
|
[(store (opnode (typeinfo.VT (load addr:$dst)),
|
||||||
|
typeinfo.ImmOperator:$src, EFLAGS), addr:$dst),
|
||||||
|
(implicit EFLAGS)]>;
|
||||||
|
|
||||||
// BinOpMI_F - Instructions like "cmp [mem], imm".
|
// BinOpMI_F - Instructions like "cmp [mem], imm".
|
||||||
class BinOpMI_F<string mnemonic, X86TypeInfo typeinfo,
|
class BinOpMI_F<string mnemonic, X86TypeInfo typeinfo,
|
||||||
SDPatternOperator opnode, Format f, bits<8> opcode = 0x80>
|
SDPatternOperator opnode, Format f, bits<8> opcode = 0x80>
|
||||||
@ -791,6 +840,14 @@ class BinOpMI8_RMW<string mnemonic, X86TypeInfo typeinfo,
|
|||||||
typeinfo.Imm8Operator:$src), addr:$dst),
|
typeinfo.Imm8Operator:$src), addr:$dst),
|
||||||
(implicit EFLAGS)]>;
|
(implicit EFLAGS)]>;
|
||||||
|
|
||||||
|
// BinOpMI8_RMW_FF - Instructions like "adc [mem], imm8".
|
||||||
|
class BinOpMI8_RMW_FF<string mnemonic, X86TypeInfo typeinfo,
|
||||||
|
SDNode opnode, Format f>
|
||||||
|
: BinOpMI8<mnemonic, typeinfo, f,
|
||||||
|
[(store (opnode (load addr:$dst),
|
||||||
|
typeinfo.Imm8Operator:$src, EFLAGS), addr:$dst),
|
||||||
|
(implicit EFLAGS)]>;
|
||||||
|
|
||||||
// BinOpMI8_F - Instructions like "cmp [mem], imm8".
|
// BinOpMI8_F - Instructions like "cmp [mem], imm8".
|
||||||
class BinOpMI8_F<string mnemonic, X86TypeInfo typeinfo,
|
class BinOpMI8_F<string mnemonic, X86TypeInfo typeinfo,
|
||||||
SDNode opnode, Format f>
|
SDNode opnode, Format f>
|
||||||
@ -876,22 +933,24 @@ multiclass ArithBinOp_RF<bits<8> BaseOpc, bits<8> BaseOpc2, bits<8> BaseOpc4,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ArithBinOp_R - This is an arithmetic binary operator where the pattern is
|
/// ArithBinOp_RFF - This is an arithmetic binary operator where the pattern is
|
||||||
/// defined with "(set GPR:$dst, (...". It would be really nice to find a way
|
/// defined with "(set GPR:$dst, EFLAGS, (node LHS, RHS, EFLAGS))" like ADC and
|
||||||
/// to factor this with the other ArithBinOp_*.
|
/// SBB.
|
||||||
///
|
///
|
||||||
multiclass ArithBinOp_R<bits<8> BaseOpc, bits<8> BaseOpc2, bits<8> BaseOpc4,
|
/// It would be nice to get rid of the second and third argument here, but
|
||||||
string mnemonic, Format RegMRM, Format MemMRM,
|
/// tblgen can't handle dependent type references aggressively enough: PR8330
|
||||||
SDNode opnode,
|
multiclass ArithBinOp_RFF<bits<8> BaseOpc, bits<8> BaseOpc2, bits<8> BaseOpc4,
|
||||||
bit CommutableRR, bit ConvertibleToThreeAddress> {
|
string mnemonic, Format RegMRM, Format MemMRM,
|
||||||
|
SDNode opnode, bit CommutableRR,
|
||||||
|
bit ConvertibleToThreeAddress> {
|
||||||
let Defs = [EFLAGS] in {
|
let Defs = [EFLAGS] in {
|
||||||
let Constraints = "$src1 = $dst" in {
|
let Constraints = "$src1 = $dst" in {
|
||||||
let isCommutable = CommutableRR,
|
let isCommutable = CommutableRR,
|
||||||
isConvertibleToThreeAddress = ConvertibleToThreeAddress in {
|
isConvertibleToThreeAddress = ConvertibleToThreeAddress in {
|
||||||
def #NAME#8rr : BinOpRR_R<BaseOpc, mnemonic, Xi8 , opnode>;
|
def #NAME#8rr : BinOpRR_RFF<BaseOpc, mnemonic, Xi8 , opnode>;
|
||||||
def #NAME#16rr : BinOpRR_R<BaseOpc, mnemonic, Xi16, opnode>;
|
def #NAME#16rr : BinOpRR_RFF<BaseOpc, mnemonic, Xi16, opnode>;
|
||||||
def #NAME#32rr : BinOpRR_R<BaseOpc, mnemonic, Xi32, opnode>;
|
def #NAME#32rr : BinOpRR_RFF<BaseOpc, mnemonic, Xi32, opnode>;
|
||||||
def #NAME#64rr : BinOpRR_R<BaseOpc, mnemonic, Xi64, opnode>;
|
def #NAME#64rr : BinOpRR_RFF<BaseOpc, mnemonic, Xi64, opnode>;
|
||||||
} // isCommutable
|
} // isCommutable
|
||||||
|
|
||||||
def #NAME#8rr_REV : BinOpRR_Rev<BaseOpc2, mnemonic, Xi8>;
|
def #NAME#8rr_REV : BinOpRR_Rev<BaseOpc2, mnemonic, Xi8>;
|
||||||
@ -899,40 +958,40 @@ multiclass ArithBinOp_R<bits<8> BaseOpc, bits<8> BaseOpc2, bits<8> BaseOpc4,
|
|||||||
def #NAME#32rr_REV : BinOpRR_Rev<BaseOpc2, mnemonic, Xi32>;
|
def #NAME#32rr_REV : BinOpRR_Rev<BaseOpc2, mnemonic, Xi32>;
|
||||||
def #NAME#64rr_REV : BinOpRR_Rev<BaseOpc2, mnemonic, Xi64>;
|
def #NAME#64rr_REV : BinOpRR_Rev<BaseOpc2, mnemonic, Xi64>;
|
||||||
|
|
||||||
def #NAME#8rm : BinOpRM_R<BaseOpc2, mnemonic, Xi8 , opnode>;
|
def #NAME#8rm : BinOpRM_RFF<BaseOpc2, mnemonic, Xi8 , opnode>;
|
||||||
def #NAME#16rm : BinOpRM_R<BaseOpc2, mnemonic, Xi16, opnode>;
|
def #NAME#16rm : BinOpRM_RFF<BaseOpc2, mnemonic, Xi16, opnode>;
|
||||||
def #NAME#32rm : BinOpRM_R<BaseOpc2, mnemonic, Xi32, opnode>;
|
def #NAME#32rm : BinOpRM_RFF<BaseOpc2, mnemonic, Xi32, opnode>;
|
||||||
def #NAME#64rm : BinOpRM_R<BaseOpc2, mnemonic, Xi64, opnode>;
|
def #NAME#64rm : BinOpRM_RFF<BaseOpc2, mnemonic, Xi64, opnode>;
|
||||||
|
|
||||||
let isConvertibleToThreeAddress = ConvertibleToThreeAddress in {
|
let isConvertibleToThreeAddress = ConvertibleToThreeAddress in {
|
||||||
// NOTE: These are order specific, we want the ri8 forms to be listed
|
// NOTE: These are order specific, we want the ri8 forms to be listed
|
||||||
// first so that they are slightly preferred to the ri forms.
|
// first so that they are slightly preferred to the ri forms.
|
||||||
def #NAME#16ri8 : BinOpRI8_R<0x82, mnemonic, Xi16, opnode, RegMRM>;
|
def #NAME#16ri8 : BinOpRI8_RFF<0x82, mnemonic, Xi16, opnode, RegMRM>;
|
||||||
def #NAME#32ri8 : BinOpRI8_R<0x82, mnemonic, Xi32, opnode, RegMRM>;
|
def #NAME#32ri8 : BinOpRI8_RFF<0x82, mnemonic, Xi32, opnode, RegMRM>;
|
||||||
def #NAME#64ri8 : BinOpRI8_R<0x82, mnemonic, Xi64, opnode, RegMRM>;
|
def #NAME#64ri8 : BinOpRI8_RFF<0x82, mnemonic, Xi64, opnode, RegMRM>;
|
||||||
|
|
||||||
def #NAME#8ri : BinOpRI_R<0x80, mnemonic, Xi8 , opnode, RegMRM>;
|
def #NAME#8ri : BinOpRI_RFF<0x80, mnemonic, Xi8 , opnode, RegMRM>;
|
||||||
def #NAME#16ri : BinOpRI_R<0x80, mnemonic, Xi16, opnode, RegMRM>;
|
def #NAME#16ri : BinOpRI_RFF<0x80, mnemonic, Xi16, opnode, RegMRM>;
|
||||||
def #NAME#32ri : BinOpRI_R<0x80, mnemonic, Xi32, opnode, RegMRM>;
|
def #NAME#32ri : BinOpRI_RFF<0x80, mnemonic, Xi32, opnode, RegMRM>;
|
||||||
def #NAME#64ri32: BinOpRI_R<0x80, mnemonic, Xi64, opnode, RegMRM>;
|
def #NAME#64ri32: BinOpRI_RFF<0x80, mnemonic, Xi64, opnode, RegMRM>;
|
||||||
}
|
}
|
||||||
} // Constraints = "$src1 = $dst"
|
} // Constraints = "$src1 = $dst"
|
||||||
|
|
||||||
def #NAME#8mr : BinOpMR_RMW<BaseOpc, mnemonic, Xi8 , opnode>;
|
def #NAME#8mr : BinOpMR_RMW_FF<BaseOpc, mnemonic, Xi8 , opnode>;
|
||||||
def #NAME#16mr : BinOpMR_RMW<BaseOpc, mnemonic, Xi16, opnode>;
|
def #NAME#16mr : BinOpMR_RMW_FF<BaseOpc, mnemonic, Xi16, opnode>;
|
||||||
def #NAME#32mr : BinOpMR_RMW<BaseOpc, mnemonic, Xi32, opnode>;
|
def #NAME#32mr : BinOpMR_RMW_FF<BaseOpc, mnemonic, Xi32, opnode>;
|
||||||
def #NAME#64mr : BinOpMR_RMW<BaseOpc, mnemonic, Xi64, opnode>;
|
def #NAME#64mr : BinOpMR_RMW_FF<BaseOpc, mnemonic, Xi64, opnode>;
|
||||||
|
|
||||||
// NOTE: These are order specific, we want the mi8 forms to be listed
|
// NOTE: These are order specific, we want the mi8 forms to be listed
|
||||||
// first so that they are slightly preferred to the mi forms.
|
// first so that they are slightly preferred to the mi forms.
|
||||||
def #NAME#16mi8 : BinOpMI8_RMW<mnemonic, Xi16, opnode, MemMRM>;
|
def #NAME#16mi8 : BinOpMI8_RMW_FF<mnemonic, Xi16, opnode, MemMRM>;
|
||||||
def #NAME#32mi8 : BinOpMI8_RMW<mnemonic, Xi32, opnode, MemMRM>;
|
def #NAME#32mi8 : BinOpMI8_RMW_FF<mnemonic, Xi32, opnode, MemMRM>;
|
||||||
def #NAME#64mi8 : BinOpMI8_RMW<mnemonic, Xi64, opnode, MemMRM>;
|
def #NAME#64mi8 : BinOpMI8_RMW_FF<mnemonic, Xi64, opnode, MemMRM>;
|
||||||
|
|
||||||
def #NAME#8mi : BinOpMI_RMW<mnemonic, Xi8 , opnode, MemMRM>;
|
def #NAME#8mi : BinOpMI_RMW_FF<mnemonic, Xi8 , opnode, MemMRM>;
|
||||||
def #NAME#16mi : BinOpMI_RMW<mnemonic, Xi16, opnode, MemMRM>;
|
def #NAME#16mi : BinOpMI_RMW_FF<mnemonic, Xi16, opnode, MemMRM>;
|
||||||
def #NAME#32mi : BinOpMI_RMW<mnemonic, Xi32, opnode, MemMRM>;
|
def #NAME#32mi : BinOpMI_RMW_FF<mnemonic, Xi32, opnode, MemMRM>;
|
||||||
def #NAME#64mi32 : BinOpMI_RMW<mnemonic, Xi64, opnode, MemMRM>;
|
def #NAME#64mi32 : BinOpMI_RMW_FF<mnemonic, Xi64, opnode, MemMRM>;
|
||||||
|
|
||||||
def #NAME#8i8 : BinOpAI<BaseOpc4, mnemonic, Xi8 , AL>;
|
def #NAME#8i8 : BinOpAI<BaseOpc4, mnemonic, Xi8 , AL>;
|
||||||
def #NAME#16i16 : BinOpAI<BaseOpc4, mnemonic, Xi16, AX>;
|
def #NAME#16i16 : BinOpAI<BaseOpc4, mnemonic, Xi16, AX>;
|
||||||
@ -1018,13 +1077,12 @@ defm SUB : ArithBinOp_RF<0x28, 0x2A, 0x2C, "sub", MRM5r, MRM5m,
|
|||||||
|
|
||||||
// Arithmetic.
|
// Arithmetic.
|
||||||
let Uses = [EFLAGS] in {
|
let Uses = [EFLAGS] in {
|
||||||
// FIXME: Delete ArithBinOp_R if these switch off adde/sube.
|
defm ADC : ArithBinOp_RFF<0x10, 0x12, 0x14, "adc", MRM2r, MRM2m, X86adc_flag,
|
||||||
defm ADC : ArithBinOp_R<0x10, 0x12, 0x14, "adc", MRM2r, MRM2m, adde, 1, 0>;
|
1, 0>;
|
||||||
defm SBB : ArithBinOp_R<0x18, 0x1A, 0x1C, "sbb", MRM3r, MRM3m, sube, 0, 0>;
|
defm SBB : ArithBinOp_RFF<0x18, 0x1A, 0x1C, "sbb", MRM3r, MRM3m, X86sbb_flag,
|
||||||
|
0, 0>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
defm CMP : ArithBinOp_F<0x38, 0x3A, 0x3C, "cmp", MRM7r, MRM7m, X86cmp, 0, 0>;
|
defm CMP : ArithBinOp_F<0x38, 0x3A, 0x3C, "cmp", MRM7r, MRM7m, X86cmp, 0, 0>;
|
||||||
|
|
||||||
|
|
||||||
|
@ -35,6 +35,14 @@ def SDTBinaryArithWithFlags : SDTypeProfile<2, 2,
|
|||||||
[SDTCisSameAs<0, 2>,
|
[SDTCisSameAs<0, 2>,
|
||||||
SDTCisSameAs<0, 3>,
|
SDTCisSameAs<0, 3>,
|
||||||
SDTCisInt<0>, SDTCisVT<1, i32>]>;
|
SDTCisInt<0>, SDTCisVT<1, i32>]>;
|
||||||
|
|
||||||
|
// SDTBinaryArithWithFlagsInOut - RES1, EFLAGS = op LHS, RHS, EFLAGS
|
||||||
|
def SDTBinaryArithWithFlagsInOut : SDTypeProfile<2, 3,
|
||||||
|
[SDTCisSameAs<0, 2>,
|
||||||
|
SDTCisSameAs<0, 3>,
|
||||||
|
SDTCisInt<0>,
|
||||||
|
SDTCisVT<1, i32>,
|
||||||
|
SDTCisVT<4, i32>]>;
|
||||||
// RES1, RES2, FLAGS = op LHS, RHS
|
// RES1, RES2, FLAGS = op LHS, RHS
|
||||||
def SDT2ResultBinaryArithWithFlags : SDTypeProfile<3, 2,
|
def SDT2ResultBinaryArithWithFlags : SDTypeProfile<3, 2,
|
||||||
[SDTCisSameAs<0, 1>,
|
[SDTCisSameAs<0, 1>,
|
||||||
@ -196,6 +204,8 @@ def X86smul_flag : SDNode<"X86ISD::SMUL", SDTBinaryArithWithFlags,
|
|||||||
[SDNPCommutative]>;
|
[SDNPCommutative]>;
|
||||||
def X86umul_flag : SDNode<"X86ISD::UMUL", SDT2ResultBinaryArithWithFlags,
|
def X86umul_flag : SDNode<"X86ISD::UMUL", SDT2ResultBinaryArithWithFlags,
|
||||||
[SDNPCommutative]>;
|
[SDNPCommutative]>;
|
||||||
|
def X86adc_flag : SDNode<"X86ISD::ADC", SDTBinaryArithWithFlagsInOut>;
|
||||||
|
def X86sbb_flag : SDNode<"X86ISD::SBB", SDTBinaryArithWithFlagsInOut>;
|
||||||
|
|
||||||
def X86inc_flag : SDNode<"X86ISD::INC", SDTUnaryArithWithFlags>;
|
def X86inc_flag : SDNode<"X86ISD::INC", SDTUnaryArithWithFlags>;
|
||||||
def X86dec_flag : SDNode<"X86ISD::DEC", SDTUnaryArithWithFlags>;
|
def X86dec_flag : SDNode<"X86ISD::DEC", SDTUnaryArithWithFlags>;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user