mirror of
https://github.com/RPCS3/llvm.git
synced 2024-12-24 13:06:56 +00:00
Add initial conditional branch support. This doesn't actually work yet due
to a bug in the scheduler. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@24807 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
a5282d8df2
commit
4d55aca87a
@ -27,11 +27,21 @@ using namespace llvm;
|
||||
// TargetLowering Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
namespace V8ISD {
|
||||
enum {
|
||||
FIRST_NUMBER = ISD::BUILTIN_OP_END+V8::INSTRUCTION_LIST_END,
|
||||
CMPICC, // Compare two GPR operands, set icc.
|
||||
CMPFCC, // Compare two FP operands, set fcc.
|
||||
BRICC, // Branch to dest on icc condition
|
||||
BRFCC, // Branch to dest on fcc condition
|
||||
};
|
||||
}
|
||||
|
||||
namespace {
|
||||
class SparcV8TargetLowering : public TargetLowering {
|
||||
public:
|
||||
SparcV8TargetLowering(TargetMachine &TM);
|
||||
|
||||
virtual SDOperand LowerOperation(SDOperand Op, SelectionDAG &DAG);
|
||||
virtual std::vector<SDOperand>
|
||||
LowerArguments(Function &F, SelectionDAG &DAG);
|
||||
virtual std::pair<SDOperand, SDOperand>
|
||||
@ -70,6 +80,22 @@ SparcV8TargetLowering::SparcV8TargetLowering(TargetMachine &TM)
|
||||
setOperationAction(ISD::UREM, MVT::i32, Expand);
|
||||
setOperationAction(ISD::SREM, MVT::i32, Expand);
|
||||
|
||||
// Sparc has no select or setcc: expand to SELECT_CC.
|
||||
setOperationAction(ISD::SELECT, MVT::i32, Expand);
|
||||
setOperationAction(ISD::SELECT, MVT::f32, Expand);
|
||||
setOperationAction(ISD::SELECT, MVT::f64, Expand);
|
||||
setOperationAction(ISD::SETCC, MVT::i32, Expand);
|
||||
setOperationAction(ISD::SETCC, MVT::f32, Expand);
|
||||
setOperationAction(ISD::SETCC, MVT::f64, Expand);
|
||||
|
||||
// Sparc doesn't have BRCOND either, it has BR_CC.
|
||||
setOperationAction(ISD::BRCOND, MVT::Other, Expand);
|
||||
setOperationAction(ISD::BRCONDTWOWAY, MVT::Other, Expand);
|
||||
setOperationAction(ISD::BRTWOWAY_CC, MVT::Other, Expand);
|
||||
setOperationAction(ISD::BR_CC, MVT::i32, Custom);
|
||||
setOperationAction(ISD::BR_CC, MVT::f32, Custom);
|
||||
setOperationAction(ISD::BR_CC, MVT::f64, Custom);
|
||||
|
||||
computeRegisterProperties();
|
||||
}
|
||||
|
||||
@ -171,26 +197,52 @@ SDOperand SparcV8TargetLowering::LowerReturnTo(SDOperand Chain, SDOperand Op,
|
||||
}
|
||||
}
|
||||
|
||||
SDOperand SparcV8TargetLowering::LowerVAStart(SDOperand Chain, SDOperand VAListP,
|
||||
Value *VAListV, SelectionDAG &DAG) {
|
||||
SDOperand SparcV8TargetLowering::
|
||||
LowerVAStart(SDOperand Chain, SDOperand VAListP, Value *VAListV,
|
||||
SelectionDAG &DAG) {
|
||||
|
||||
assert(0 && "Unimp");
|
||||
abort();
|
||||
}
|
||||
|
||||
std::pair<SDOperand,SDOperand>
|
||||
SparcV8TargetLowering::LowerVAArg(SDOperand Chain, SDOperand VAListP, Value *VAListV,
|
||||
const Type *ArgTy, SelectionDAG &DAG) {
|
||||
std::pair<SDOperand,SDOperand> SparcV8TargetLowering::
|
||||
LowerVAArg(SDOperand Chain, SDOperand VAListP, Value *VAListV,
|
||||
const Type *ArgTy, SelectionDAG &DAG) {
|
||||
assert(0 && "Unimp");
|
||||
abort();
|
||||
}
|
||||
|
||||
std::pair<SDOperand, SDOperand>
|
||||
SparcV8TargetLowering::LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth,
|
||||
SelectionDAG &DAG) {
|
||||
std::pair<SDOperand, SDOperand> SparcV8TargetLowering::
|
||||
LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth,
|
||||
SelectionDAG &DAG) {
|
||||
assert(0 && "Unimp");
|
||||
abort();
|
||||
}
|
||||
|
||||
SDOperand SparcV8TargetLowering::
|
||||
LowerOperation(SDOperand Op, SelectionDAG &DAG) {
|
||||
switch (Op.getOpcode()) {
|
||||
default: assert(0 && "Should not custom lower this!");
|
||||
case ISD::BR_CC: {
|
||||
SDOperand Chain = Op.getOperand(0);
|
||||
SDOperand CC = Op.getOperand(1);
|
||||
SDOperand LHS = Op.getOperand(2);
|
||||
SDOperand RHS = Op.getOperand(3);
|
||||
SDOperand Dest = Op.getOperand(4);
|
||||
|
||||
// Get the condition flag.
|
||||
if (LHS.getValueType() == MVT::i32) {
|
||||
SDOperand Cond = DAG.getNode(V8ISD::CMPICC, MVT::Flag, LHS, RHS);
|
||||
return DAG.getNode(V8ISD::BRICC, MVT::Other, Chain, Dest, CC, Cond);
|
||||
} else {
|
||||
SDOperand Cond = DAG.getNode(V8ISD::CMPFCC, MVT::Flag, LHS, RHS);
|
||||
return DAG.getNode(V8ISD::BRFCC, MVT::Other, Chain, Dest, CC, Cond);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Instruction Selector Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -273,8 +325,8 @@ bool SparcV8DAGToDAGISel::SelectADDRri(SDOperand Addr, SDOperand &Base,
|
||||
|
||||
SDOperand SparcV8DAGToDAGISel::Select(SDOperand Op) {
|
||||
SDNode *N = Op.Val;
|
||||
if (N->getOpcode() >= ISD::BUILTIN_OP_END/* &&
|
||||
N->getOpcode() < V8ISD::FIRST_NUMBER*/)
|
||||
if (N->getOpcode() >= ISD::BUILTIN_OP_END &&
|
||||
N->getOpcode() < V8ISD::FIRST_NUMBER)
|
||||
return Op; // Already selected.
|
||||
// If this has already been converted, use it.
|
||||
std::map<SDOperand, SDOperand>::iterator CGMI = CodeGenMap.find(Op);
|
||||
@ -282,6 +334,15 @@ SDOperand SparcV8DAGToDAGISel::Select(SDOperand Op) {
|
||||
|
||||
switch (N->getOpcode()) {
|
||||
default: break;
|
||||
case ISD::BasicBlock: return CodeGenMap[Op] = Op;
|
||||
case V8ISD::CMPICC: {
|
||||
// FIXME: Handle compare with immediate.
|
||||
SDOperand LHS = Select(N->getOperand(0));
|
||||
SDOperand RHS = Select(N->getOperand(1));
|
||||
SDOperand Result = CurDAG->getTargetNode(V8::SUBCCrr, MVT::i32, MVT::Flag,
|
||||
LHS, RHS);
|
||||
return CodeGenMap[Op] = Result.getValue(1);
|
||||
}
|
||||
case ISD::ADD_PARTS: {
|
||||
SDOperand LHSL = Select(N->getOperand(0));
|
||||
SDOperand LHSH = Select(N->getOperand(1));
|
||||
|
@ -33,12 +33,14 @@ class F2_1<bits<3> op2Val, dag ops, string asmstr, list<dag> pattern> : F2 {
|
||||
let Inst{29-25} = rd;
|
||||
}
|
||||
|
||||
class F2_2<bits<4> condVal, bits<3> op2Val, dag ops, string asmstr> : F2 {
|
||||
class F2_2<bits<4> condVal, bits<3> op2Val, dag ops, string asmstr,
|
||||
list<dag> pattern> : F2 {
|
||||
bits<4> cond;
|
||||
bit annul = 0; // currently unused
|
||||
|
||||
dag OperandList = ops;
|
||||
let AsmString = asmstr;
|
||||
let Pattern = pattern;
|
||||
|
||||
let cond = condVal;
|
||||
let op2 = op2Val;
|
||||
|
@ -68,6 +68,19 @@ def MEMri : Operand<i32> {
|
||||
let MIOperandInfo = (ops IntRegs, i32imm);
|
||||
}
|
||||
|
||||
def SDTV8cmpicc :
|
||||
SDTypeProfile<1, 2, [SDTCisVT<0, FlagVT>, SDTCisInt<1>, SDTCisSameAs<1, 2>]>;
|
||||
def SDTV8cmpfcc :
|
||||
SDTypeProfile<1, 2, [SDTCisVT<0, FlagVT>, SDTCisFP<1>, SDTCisSameAs<1, 2>]>;
|
||||
def SDTV8brcc :
|
||||
SDTypeProfile<0, 3, [SDTCisInt<0>, SDTCisVT<1, OtherVT>, SDTCisVT<2, FlagVT>]>;
|
||||
|
||||
def V8cmpicc : SDNode<"V8ISD::CMPICC", SDTV8cmpicc>;
|
||||
def V8cmpfcc : SDNode<"V8ISD::CMPFCC", SDTV8cmpfcc>;
|
||||
def V8bricc : SDNode<"V8ISD::BRICC", SDTV8brcc, [SDNPHasChain]>;
|
||||
def V8brfcc : SDNode<"V8ISD::BRFCC", SDTV8brcc, [SDNPHasChain]>;
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Instructions
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -389,53 +402,81 @@ def RESTOREri : F3_2<2, 0b111101,
|
||||
// Section B.21 - Branch on Integer Condition Codes Instructions, p. 119
|
||||
|
||||
// conditional branch class:
|
||||
class BranchV8<bits<4> cc, dag ops, string asmstr>
|
||||
: F2_2<cc, 0b010, ops, asmstr> {
|
||||
class BranchV8<bits<4> cc, dag ops, string asmstr, list<dag> pattern>
|
||||
: F2_2<cc, 0b010, ops, asmstr, pattern> {
|
||||
let isBranch = 1;
|
||||
let isTerminator = 1;
|
||||
let hasDelaySlot = 1;
|
||||
}
|
||||
|
||||
let isBarrier = 1 in
|
||||
def BA : BranchV8<0b1000, (ops IntRegs:$dst), "ba $dst">;
|
||||
def BN : BranchV8<0b0000, (ops IntRegs:$dst), "bn $dst">;
|
||||
def BNE : BranchV8<0b1001, (ops IntRegs:$dst), "bne $dst">;
|
||||
def BE : BranchV8<0b0001, (ops IntRegs:$dst), "be $dst">;
|
||||
def BG : BranchV8<0b1010, (ops IntRegs:$dst), "bg $dst">;
|
||||
def BLE : BranchV8<0b0010, (ops IntRegs:$dst), "ble $dst">;
|
||||
def BGE : BranchV8<0b1011, (ops IntRegs:$dst), "bge $dst">;
|
||||
def BL : BranchV8<0b0011, (ops IntRegs:$dst), "bl $dst">;
|
||||
def BGU : BranchV8<0b1100, (ops IntRegs:$dst), "bgu $dst">;
|
||||
def BLEU : BranchV8<0b0100, (ops IntRegs:$dst), "bleu $dst">;
|
||||
def BCC : BranchV8<0b1101, (ops IntRegs:$dst), "bcc $dst">;
|
||||
def BCS : BranchV8<0b0101, (ops IntRegs:$dst), "bcs $dst">;
|
||||
def BA : BranchV8<0b1000, (ops IntRegs:$dst),
|
||||
"ba $dst", []>;
|
||||
def BN : BranchV8<0b0000, (ops IntRegs:$dst),
|
||||
"bn $dst", []>;
|
||||
def BNE : BranchV8<0b1001, (ops IntRegs:$dst),
|
||||
"bne $dst",
|
||||
[(V8bricc IntRegs:$dst, SETNE, ICC)]>;
|
||||
def BE : BranchV8<0b0001, (ops IntRegs:$dst),
|
||||
"be $dst",
|
||||
[(V8bricc IntRegs:$dst, SETEQ, ICC)]>;
|
||||
def BG : BranchV8<0b1010, (ops IntRegs:$dst),
|
||||
"bg $dst", []>;
|
||||
def BLE : BranchV8<0b0010, (ops IntRegs:$dst),
|
||||
"ble $dst", []>;
|
||||
def BGE : BranchV8<0b1011, (ops IntRegs:$dst),
|
||||
"bge $dst", []>;
|
||||
def BL : BranchV8<0b0011, (ops IntRegs:$dst),
|
||||
"bl $dst", []>;
|
||||
def BGU : BranchV8<0b1100, (ops IntRegs:$dst),
|
||||
"bgu $dst", []>;
|
||||
def BLEU : BranchV8<0b0100, (ops IntRegs:$dst),
|
||||
"bleu $dst", []>;
|
||||
def BCC : BranchV8<0b1101, (ops IntRegs:$dst),
|
||||
"bcc $dst", []>;
|
||||
def BCS : BranchV8<0b0101, (ops IntRegs:$dst),
|
||||
"bcs $dst", []>;
|
||||
|
||||
// Section B.22 - Branch on Floating-point Condition Codes Instructions, p. 121
|
||||
|
||||
// floating-point conditional branch class:
|
||||
class FPBranchV8<bits<4> cc, dag ops, string asmstr>
|
||||
: F2_2<cc, 0b110, ops, asmstr> {
|
||||
class FPBranchV8<bits<4> cc, dag ops, string asmstr, list<dag> pattern>
|
||||
: F2_2<cc, 0b110, ops, asmstr, pattern> {
|
||||
let isBranch = 1;
|
||||
let isTerminator = 1;
|
||||
let hasDelaySlot = 1;
|
||||
}
|
||||
|
||||
def FBA : FPBranchV8<0b1000, (ops IntRegs:$dst), "fba $dst">;
|
||||
def FBN : FPBranchV8<0b0000, (ops IntRegs:$dst), "fbn $dst">;
|
||||
def FBU : FPBranchV8<0b0111, (ops IntRegs:$dst), "fbu $dst">;
|
||||
def FBG : FPBranchV8<0b0110, (ops IntRegs:$dst), "fbg $dst">;
|
||||
def FBUG : FPBranchV8<0b0101, (ops IntRegs:$dst), "fbug $dst">;
|
||||
def FBL : FPBranchV8<0b0100, (ops IntRegs:$dst), "fbl $dst">;
|
||||
def FBUL : FPBranchV8<0b0011, (ops IntRegs:$dst), "fbul $dst">;
|
||||
def FBLG : FPBranchV8<0b0010, (ops IntRegs:$dst), "fblg $dst">;
|
||||
def FBNE : FPBranchV8<0b0001, (ops IntRegs:$dst), "fbne $dst">;
|
||||
def FBE : FPBranchV8<0b1001, (ops IntRegs:$dst), "fbe $dst">;
|
||||
def FBUE : FPBranchV8<0b1010, (ops IntRegs:$dst), "fbue $dst">;
|
||||
def FBGE : FPBranchV8<0b1011, (ops IntRegs:$dst), "fbge $dst">;
|
||||
def FBUGE: FPBranchV8<0b1100, (ops IntRegs:$dst), "fbuge $dst">;
|
||||
def FBLE : FPBranchV8<0b1101, (ops IntRegs:$dst), "fble $dst">;
|
||||
def FBULE: FPBranchV8<0b1110, (ops IntRegs:$dst), "fbule $dst">;
|
||||
def FBO : FPBranchV8<0b1111, (ops IntRegs:$dst), "fbo $dst">;
|
||||
def FBN : FPBranchV8<0b0000, (ops IntRegs:$dst),
|
||||
"fbn $dst", []>;
|
||||
def FBU : FPBranchV8<0b0111, (ops IntRegs:$dst),
|
||||
"fbu $dst", []>;
|
||||
def FBG : FPBranchV8<0b0110, (ops IntRegs:$dst),
|
||||
"fbg $dst", []>;
|
||||
def FBUG : FPBranchV8<0b0101, (ops IntRegs:$dst),
|
||||
"fbug $dst", []>;
|
||||
def FBL : FPBranchV8<0b0100, (ops IntRegs:$dst),
|
||||
"fbl $dst", []>;
|
||||
def FBUL : FPBranchV8<0b0011, (ops IntRegs:$dst),
|
||||
"fbul $dst", []>;
|
||||
def FBLG : FPBranchV8<0b0010, (ops IntRegs:$dst),
|
||||
"fblg $dst", []>;
|
||||
def FBNE : FPBranchV8<0b0001, (ops IntRegs:$dst),
|
||||
"fbne $dst", []>;
|
||||
def FBE : FPBranchV8<0b1001, (ops IntRegs:$dst),
|
||||
"fbe $dst", []>;
|
||||
def FBUE : FPBranchV8<0b1010, (ops IntRegs:$dst),
|
||||
"fbue $dst", []>;
|
||||
def FBGE : FPBranchV8<0b1011, (ops IntRegs:$dst),
|
||||
"fbge $dst", []>;
|
||||
def FBUGE: FPBranchV8<0b1100, (ops IntRegs:$dst),
|
||||
"fbuge $dst", []>;
|
||||
def FBLE : FPBranchV8<0b1101, (ops IntRegs:$dst),
|
||||
"fble $dst", []>;
|
||||
def FBULE: FPBranchV8<0b1110, (ops IntRegs:$dst),
|
||||
"fbule $dst", []>;
|
||||
def FBO : FPBranchV8<0b1111, (ops IntRegs:$dst),
|
||||
"fbo $dst", []>;
|
||||
|
||||
|
||||
|
||||
@ -576,10 +617,12 @@ def FDIVD : F3_3<2, 0b110100, 0b001001110,
|
||||
// is modelled with a forced noop after the instruction.
|
||||
def FCMPS : F3_3<2, 0b110101, 0b001010001,
|
||||
(ops FPRegs:$src1, FPRegs:$src2),
|
||||
"fcmps $src1, $src2\n\tnop", []>;
|
||||
"fcmps $src1, $src2\n\tnop",
|
||||
[(set FCC, (V8cmpfcc FPRegs:$src1, FPRegs:$src2))]>;
|
||||
def FCMPD : F3_3<2, 0b110101, 0b001010010,
|
||||
(ops DFPRegs:$src1, DFPRegs:$src2),
|
||||
"fcmpd $src1, $src2\n\tnop", []>;
|
||||
"fcmpd $src1, $src2\n\tnop",
|
||||
[(set FCC, (V8cmpfcc DFPRegs:$src1, DFPRegs:$src2))]>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Non-Instruction Patterns
|
||||
|
@ -71,6 +71,14 @@ def D10 : Rd<20, "F20", [F20, F21]>; def D11 : Rd<22, "F22", [F22, F23]>;
|
||||
def D12 : Rd<24, "F24", [F24, F25]>; def D13 : Rd<26, "F26", [F26, F27]>;
|
||||
def D14 : Rd<28, "F28", [F28, F29]>; def D15 : Rd<30, "F30", [F30, F31]>;
|
||||
|
||||
/// Integer and FP Condition codes.
|
||||
let Namespace = "V8" in {
|
||||
def ICC : Register<"ICC">;
|
||||
def FCC : Register<"FCC">;
|
||||
}
|
||||
def FLAGS_REGS : RegisterClass<"V8", [FlagVT], 32, [ICC, FCC]> {
|
||||
let Size = 32;
|
||||
}
|
||||
|
||||
// Register classes.
|
||||
//
|
||||
|
@ -27,11 +27,21 @@ using namespace llvm;
|
||||
// TargetLowering Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
namespace V8ISD {
|
||||
enum {
|
||||
FIRST_NUMBER = ISD::BUILTIN_OP_END+V8::INSTRUCTION_LIST_END,
|
||||
CMPICC, // Compare two GPR operands, set icc.
|
||||
CMPFCC, // Compare two FP operands, set fcc.
|
||||
BRICC, // Branch to dest on icc condition
|
||||
BRFCC, // Branch to dest on fcc condition
|
||||
};
|
||||
}
|
||||
|
||||
namespace {
|
||||
class SparcV8TargetLowering : public TargetLowering {
|
||||
public:
|
||||
SparcV8TargetLowering(TargetMachine &TM);
|
||||
|
||||
virtual SDOperand LowerOperation(SDOperand Op, SelectionDAG &DAG);
|
||||
virtual std::vector<SDOperand>
|
||||
LowerArguments(Function &F, SelectionDAG &DAG);
|
||||
virtual std::pair<SDOperand, SDOperand>
|
||||
@ -70,6 +80,22 @@ SparcV8TargetLowering::SparcV8TargetLowering(TargetMachine &TM)
|
||||
setOperationAction(ISD::UREM, MVT::i32, Expand);
|
||||
setOperationAction(ISD::SREM, MVT::i32, Expand);
|
||||
|
||||
// Sparc has no select or setcc: expand to SELECT_CC.
|
||||
setOperationAction(ISD::SELECT, MVT::i32, Expand);
|
||||
setOperationAction(ISD::SELECT, MVT::f32, Expand);
|
||||
setOperationAction(ISD::SELECT, MVT::f64, Expand);
|
||||
setOperationAction(ISD::SETCC, MVT::i32, Expand);
|
||||
setOperationAction(ISD::SETCC, MVT::f32, Expand);
|
||||
setOperationAction(ISD::SETCC, MVT::f64, Expand);
|
||||
|
||||
// Sparc doesn't have BRCOND either, it has BR_CC.
|
||||
setOperationAction(ISD::BRCOND, MVT::Other, Expand);
|
||||
setOperationAction(ISD::BRCONDTWOWAY, MVT::Other, Expand);
|
||||
setOperationAction(ISD::BRTWOWAY_CC, MVT::Other, Expand);
|
||||
setOperationAction(ISD::BR_CC, MVT::i32, Custom);
|
||||
setOperationAction(ISD::BR_CC, MVT::f32, Custom);
|
||||
setOperationAction(ISD::BR_CC, MVT::f64, Custom);
|
||||
|
||||
computeRegisterProperties();
|
||||
}
|
||||
|
||||
@ -171,26 +197,52 @@ SDOperand SparcV8TargetLowering::LowerReturnTo(SDOperand Chain, SDOperand Op,
|
||||
}
|
||||
}
|
||||
|
||||
SDOperand SparcV8TargetLowering::LowerVAStart(SDOperand Chain, SDOperand VAListP,
|
||||
Value *VAListV, SelectionDAG &DAG) {
|
||||
SDOperand SparcV8TargetLowering::
|
||||
LowerVAStart(SDOperand Chain, SDOperand VAListP, Value *VAListV,
|
||||
SelectionDAG &DAG) {
|
||||
|
||||
assert(0 && "Unimp");
|
||||
abort();
|
||||
}
|
||||
|
||||
std::pair<SDOperand,SDOperand>
|
||||
SparcV8TargetLowering::LowerVAArg(SDOperand Chain, SDOperand VAListP, Value *VAListV,
|
||||
const Type *ArgTy, SelectionDAG &DAG) {
|
||||
std::pair<SDOperand,SDOperand> SparcV8TargetLowering::
|
||||
LowerVAArg(SDOperand Chain, SDOperand VAListP, Value *VAListV,
|
||||
const Type *ArgTy, SelectionDAG &DAG) {
|
||||
assert(0 && "Unimp");
|
||||
abort();
|
||||
}
|
||||
|
||||
std::pair<SDOperand, SDOperand>
|
||||
SparcV8TargetLowering::LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth,
|
||||
SelectionDAG &DAG) {
|
||||
std::pair<SDOperand, SDOperand> SparcV8TargetLowering::
|
||||
LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth,
|
||||
SelectionDAG &DAG) {
|
||||
assert(0 && "Unimp");
|
||||
abort();
|
||||
}
|
||||
|
||||
SDOperand SparcV8TargetLowering::
|
||||
LowerOperation(SDOperand Op, SelectionDAG &DAG) {
|
||||
switch (Op.getOpcode()) {
|
||||
default: assert(0 && "Should not custom lower this!");
|
||||
case ISD::BR_CC: {
|
||||
SDOperand Chain = Op.getOperand(0);
|
||||
SDOperand CC = Op.getOperand(1);
|
||||
SDOperand LHS = Op.getOperand(2);
|
||||
SDOperand RHS = Op.getOperand(3);
|
||||
SDOperand Dest = Op.getOperand(4);
|
||||
|
||||
// Get the condition flag.
|
||||
if (LHS.getValueType() == MVT::i32) {
|
||||
SDOperand Cond = DAG.getNode(V8ISD::CMPICC, MVT::Flag, LHS, RHS);
|
||||
return DAG.getNode(V8ISD::BRICC, MVT::Other, Chain, Dest, CC, Cond);
|
||||
} else {
|
||||
SDOperand Cond = DAG.getNode(V8ISD::CMPFCC, MVT::Flag, LHS, RHS);
|
||||
return DAG.getNode(V8ISD::BRFCC, MVT::Other, Chain, Dest, CC, Cond);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Instruction Selector Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -273,8 +325,8 @@ bool SparcV8DAGToDAGISel::SelectADDRri(SDOperand Addr, SDOperand &Base,
|
||||
|
||||
SDOperand SparcV8DAGToDAGISel::Select(SDOperand Op) {
|
||||
SDNode *N = Op.Val;
|
||||
if (N->getOpcode() >= ISD::BUILTIN_OP_END/* &&
|
||||
N->getOpcode() < V8ISD::FIRST_NUMBER*/)
|
||||
if (N->getOpcode() >= ISD::BUILTIN_OP_END &&
|
||||
N->getOpcode() < V8ISD::FIRST_NUMBER)
|
||||
return Op; // Already selected.
|
||||
// If this has already been converted, use it.
|
||||
std::map<SDOperand, SDOperand>::iterator CGMI = CodeGenMap.find(Op);
|
||||
@ -282,6 +334,15 @@ SDOperand SparcV8DAGToDAGISel::Select(SDOperand Op) {
|
||||
|
||||
switch (N->getOpcode()) {
|
||||
default: break;
|
||||
case ISD::BasicBlock: return CodeGenMap[Op] = Op;
|
||||
case V8ISD::CMPICC: {
|
||||
// FIXME: Handle compare with immediate.
|
||||
SDOperand LHS = Select(N->getOperand(0));
|
||||
SDOperand RHS = Select(N->getOperand(1));
|
||||
SDOperand Result = CurDAG->getTargetNode(V8::SUBCCrr, MVT::i32, MVT::Flag,
|
||||
LHS, RHS);
|
||||
return CodeGenMap[Op] = Result.getValue(1);
|
||||
}
|
||||
case ISD::ADD_PARTS: {
|
||||
SDOperand LHSL = Select(N->getOperand(0));
|
||||
SDOperand LHSH = Select(N->getOperand(1));
|
||||
|
@ -33,12 +33,14 @@ class F2_1<bits<3> op2Val, dag ops, string asmstr, list<dag> pattern> : F2 {
|
||||
let Inst{29-25} = rd;
|
||||
}
|
||||
|
||||
class F2_2<bits<4> condVal, bits<3> op2Val, dag ops, string asmstr> : F2 {
|
||||
class F2_2<bits<4> condVal, bits<3> op2Val, dag ops, string asmstr,
|
||||
list<dag> pattern> : F2 {
|
||||
bits<4> cond;
|
||||
bit annul = 0; // currently unused
|
||||
|
||||
dag OperandList = ops;
|
||||
let AsmString = asmstr;
|
||||
let Pattern = pattern;
|
||||
|
||||
let cond = condVal;
|
||||
let op2 = op2Val;
|
||||
|
@ -68,6 +68,19 @@ def MEMri : Operand<i32> {
|
||||
let MIOperandInfo = (ops IntRegs, i32imm);
|
||||
}
|
||||
|
||||
def SDTV8cmpicc :
|
||||
SDTypeProfile<1, 2, [SDTCisVT<0, FlagVT>, SDTCisInt<1>, SDTCisSameAs<1, 2>]>;
|
||||
def SDTV8cmpfcc :
|
||||
SDTypeProfile<1, 2, [SDTCisVT<0, FlagVT>, SDTCisFP<1>, SDTCisSameAs<1, 2>]>;
|
||||
def SDTV8brcc :
|
||||
SDTypeProfile<0, 3, [SDTCisInt<0>, SDTCisVT<1, OtherVT>, SDTCisVT<2, FlagVT>]>;
|
||||
|
||||
def V8cmpicc : SDNode<"V8ISD::CMPICC", SDTV8cmpicc>;
|
||||
def V8cmpfcc : SDNode<"V8ISD::CMPFCC", SDTV8cmpfcc>;
|
||||
def V8bricc : SDNode<"V8ISD::BRICC", SDTV8brcc, [SDNPHasChain]>;
|
||||
def V8brfcc : SDNode<"V8ISD::BRFCC", SDTV8brcc, [SDNPHasChain]>;
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Instructions
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -389,53 +402,81 @@ def RESTOREri : F3_2<2, 0b111101,
|
||||
// Section B.21 - Branch on Integer Condition Codes Instructions, p. 119
|
||||
|
||||
// conditional branch class:
|
||||
class BranchV8<bits<4> cc, dag ops, string asmstr>
|
||||
: F2_2<cc, 0b010, ops, asmstr> {
|
||||
class BranchV8<bits<4> cc, dag ops, string asmstr, list<dag> pattern>
|
||||
: F2_2<cc, 0b010, ops, asmstr, pattern> {
|
||||
let isBranch = 1;
|
||||
let isTerminator = 1;
|
||||
let hasDelaySlot = 1;
|
||||
}
|
||||
|
||||
let isBarrier = 1 in
|
||||
def BA : BranchV8<0b1000, (ops IntRegs:$dst), "ba $dst">;
|
||||
def BN : BranchV8<0b0000, (ops IntRegs:$dst), "bn $dst">;
|
||||
def BNE : BranchV8<0b1001, (ops IntRegs:$dst), "bne $dst">;
|
||||
def BE : BranchV8<0b0001, (ops IntRegs:$dst), "be $dst">;
|
||||
def BG : BranchV8<0b1010, (ops IntRegs:$dst), "bg $dst">;
|
||||
def BLE : BranchV8<0b0010, (ops IntRegs:$dst), "ble $dst">;
|
||||
def BGE : BranchV8<0b1011, (ops IntRegs:$dst), "bge $dst">;
|
||||
def BL : BranchV8<0b0011, (ops IntRegs:$dst), "bl $dst">;
|
||||
def BGU : BranchV8<0b1100, (ops IntRegs:$dst), "bgu $dst">;
|
||||
def BLEU : BranchV8<0b0100, (ops IntRegs:$dst), "bleu $dst">;
|
||||
def BCC : BranchV8<0b1101, (ops IntRegs:$dst), "bcc $dst">;
|
||||
def BCS : BranchV8<0b0101, (ops IntRegs:$dst), "bcs $dst">;
|
||||
def BA : BranchV8<0b1000, (ops IntRegs:$dst),
|
||||
"ba $dst", []>;
|
||||
def BN : BranchV8<0b0000, (ops IntRegs:$dst),
|
||||
"bn $dst", []>;
|
||||
def BNE : BranchV8<0b1001, (ops IntRegs:$dst),
|
||||
"bne $dst",
|
||||
[(V8bricc IntRegs:$dst, SETNE, ICC)]>;
|
||||
def BE : BranchV8<0b0001, (ops IntRegs:$dst),
|
||||
"be $dst",
|
||||
[(V8bricc IntRegs:$dst, SETEQ, ICC)]>;
|
||||
def BG : BranchV8<0b1010, (ops IntRegs:$dst),
|
||||
"bg $dst", []>;
|
||||
def BLE : BranchV8<0b0010, (ops IntRegs:$dst),
|
||||
"ble $dst", []>;
|
||||
def BGE : BranchV8<0b1011, (ops IntRegs:$dst),
|
||||
"bge $dst", []>;
|
||||
def BL : BranchV8<0b0011, (ops IntRegs:$dst),
|
||||
"bl $dst", []>;
|
||||
def BGU : BranchV8<0b1100, (ops IntRegs:$dst),
|
||||
"bgu $dst", []>;
|
||||
def BLEU : BranchV8<0b0100, (ops IntRegs:$dst),
|
||||
"bleu $dst", []>;
|
||||
def BCC : BranchV8<0b1101, (ops IntRegs:$dst),
|
||||
"bcc $dst", []>;
|
||||
def BCS : BranchV8<0b0101, (ops IntRegs:$dst),
|
||||
"bcs $dst", []>;
|
||||
|
||||
// Section B.22 - Branch on Floating-point Condition Codes Instructions, p. 121
|
||||
|
||||
// floating-point conditional branch class:
|
||||
class FPBranchV8<bits<4> cc, dag ops, string asmstr>
|
||||
: F2_2<cc, 0b110, ops, asmstr> {
|
||||
class FPBranchV8<bits<4> cc, dag ops, string asmstr, list<dag> pattern>
|
||||
: F2_2<cc, 0b110, ops, asmstr, pattern> {
|
||||
let isBranch = 1;
|
||||
let isTerminator = 1;
|
||||
let hasDelaySlot = 1;
|
||||
}
|
||||
|
||||
def FBA : FPBranchV8<0b1000, (ops IntRegs:$dst), "fba $dst">;
|
||||
def FBN : FPBranchV8<0b0000, (ops IntRegs:$dst), "fbn $dst">;
|
||||
def FBU : FPBranchV8<0b0111, (ops IntRegs:$dst), "fbu $dst">;
|
||||
def FBG : FPBranchV8<0b0110, (ops IntRegs:$dst), "fbg $dst">;
|
||||
def FBUG : FPBranchV8<0b0101, (ops IntRegs:$dst), "fbug $dst">;
|
||||
def FBL : FPBranchV8<0b0100, (ops IntRegs:$dst), "fbl $dst">;
|
||||
def FBUL : FPBranchV8<0b0011, (ops IntRegs:$dst), "fbul $dst">;
|
||||
def FBLG : FPBranchV8<0b0010, (ops IntRegs:$dst), "fblg $dst">;
|
||||
def FBNE : FPBranchV8<0b0001, (ops IntRegs:$dst), "fbne $dst">;
|
||||
def FBE : FPBranchV8<0b1001, (ops IntRegs:$dst), "fbe $dst">;
|
||||
def FBUE : FPBranchV8<0b1010, (ops IntRegs:$dst), "fbue $dst">;
|
||||
def FBGE : FPBranchV8<0b1011, (ops IntRegs:$dst), "fbge $dst">;
|
||||
def FBUGE: FPBranchV8<0b1100, (ops IntRegs:$dst), "fbuge $dst">;
|
||||
def FBLE : FPBranchV8<0b1101, (ops IntRegs:$dst), "fble $dst">;
|
||||
def FBULE: FPBranchV8<0b1110, (ops IntRegs:$dst), "fbule $dst">;
|
||||
def FBO : FPBranchV8<0b1111, (ops IntRegs:$dst), "fbo $dst">;
|
||||
def FBN : FPBranchV8<0b0000, (ops IntRegs:$dst),
|
||||
"fbn $dst", []>;
|
||||
def FBU : FPBranchV8<0b0111, (ops IntRegs:$dst),
|
||||
"fbu $dst", []>;
|
||||
def FBG : FPBranchV8<0b0110, (ops IntRegs:$dst),
|
||||
"fbg $dst", []>;
|
||||
def FBUG : FPBranchV8<0b0101, (ops IntRegs:$dst),
|
||||
"fbug $dst", []>;
|
||||
def FBL : FPBranchV8<0b0100, (ops IntRegs:$dst),
|
||||
"fbl $dst", []>;
|
||||
def FBUL : FPBranchV8<0b0011, (ops IntRegs:$dst),
|
||||
"fbul $dst", []>;
|
||||
def FBLG : FPBranchV8<0b0010, (ops IntRegs:$dst),
|
||||
"fblg $dst", []>;
|
||||
def FBNE : FPBranchV8<0b0001, (ops IntRegs:$dst),
|
||||
"fbne $dst", []>;
|
||||
def FBE : FPBranchV8<0b1001, (ops IntRegs:$dst),
|
||||
"fbe $dst", []>;
|
||||
def FBUE : FPBranchV8<0b1010, (ops IntRegs:$dst),
|
||||
"fbue $dst", []>;
|
||||
def FBGE : FPBranchV8<0b1011, (ops IntRegs:$dst),
|
||||
"fbge $dst", []>;
|
||||
def FBUGE: FPBranchV8<0b1100, (ops IntRegs:$dst),
|
||||
"fbuge $dst", []>;
|
||||
def FBLE : FPBranchV8<0b1101, (ops IntRegs:$dst),
|
||||
"fble $dst", []>;
|
||||
def FBULE: FPBranchV8<0b1110, (ops IntRegs:$dst),
|
||||
"fbule $dst", []>;
|
||||
def FBO : FPBranchV8<0b1111, (ops IntRegs:$dst),
|
||||
"fbo $dst", []>;
|
||||
|
||||
|
||||
|
||||
@ -576,10 +617,12 @@ def FDIVD : F3_3<2, 0b110100, 0b001001110,
|
||||
// is modelled with a forced noop after the instruction.
|
||||
def FCMPS : F3_3<2, 0b110101, 0b001010001,
|
||||
(ops FPRegs:$src1, FPRegs:$src2),
|
||||
"fcmps $src1, $src2\n\tnop", []>;
|
||||
"fcmps $src1, $src2\n\tnop",
|
||||
[(set FCC, (V8cmpfcc FPRegs:$src1, FPRegs:$src2))]>;
|
||||
def FCMPD : F3_3<2, 0b110101, 0b001010010,
|
||||
(ops DFPRegs:$src1, DFPRegs:$src2),
|
||||
"fcmpd $src1, $src2\n\tnop", []>;
|
||||
"fcmpd $src1, $src2\n\tnop",
|
||||
[(set FCC, (V8cmpfcc DFPRegs:$src1, DFPRegs:$src2))]>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Non-Instruction Patterns
|
||||
|
@ -71,6 +71,14 @@ def D10 : Rd<20, "F20", [F20, F21]>; def D11 : Rd<22, "F22", [F22, F23]>;
|
||||
def D12 : Rd<24, "F24", [F24, F25]>; def D13 : Rd<26, "F26", [F26, F27]>;
|
||||
def D14 : Rd<28, "F28", [F28, F29]>; def D15 : Rd<30, "F30", [F30, F31]>;
|
||||
|
||||
/// Integer and FP Condition codes.
|
||||
let Namespace = "V8" in {
|
||||
def ICC : Register<"ICC">;
|
||||
def FCC : Register<"FCC">;
|
||||
}
|
||||
def FLAGS_REGS : RegisterClass<"V8", [FlagVT], 32, [ICC, FCC]> {
|
||||
let Size = 32;
|
||||
}
|
||||
|
||||
// Register classes.
|
||||
//
|
||||
|
Loading…
Reference in New Issue
Block a user