mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-28 19:31:58 +00:00
[Sparc] Add long double (f128) instructions to sparc backend.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@189198 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
5ec8afa7cf
commit
2f17d0facf
@ -30,6 +30,10 @@ def FeatureVIS
|
||||
: SubtargetFeature<"vis", "IsVIS", "true",
|
||||
"Enable UltraSPARC Visual Instruction Set extensions">;
|
||||
|
||||
def FeatureHardQuad
|
||||
: SubtargetFeature<"hard-quad-float", "HasHardQuad", "true",
|
||||
"Enable quad-word floating point instructions">;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Register File, Calling Conv, Instruction Descriptions
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -1257,15 +1257,21 @@ SparcTargetLowering::SparcTargetLowering(TargetMachine &TM)
|
||||
addRegisterClass(MVT::i32, &SP::IntRegsRegClass);
|
||||
addRegisterClass(MVT::f32, &SP::FPRegsRegClass);
|
||||
addRegisterClass(MVT::f64, &SP::DFPRegsRegClass);
|
||||
addRegisterClass(MVT::f128, &SP::QFPRegsRegClass);
|
||||
if (Subtarget->is64Bit())
|
||||
addRegisterClass(MVT::i64, &SP::I64RegsRegClass);
|
||||
|
||||
// Turn FP extload into load/fextend
|
||||
setLoadExtAction(ISD::EXTLOAD, MVT::f32, Expand);
|
||||
setLoadExtAction(ISD::EXTLOAD, MVT::f64, Expand);
|
||||
|
||||
// Sparc doesn't have i1 sign extending load
|
||||
setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote);
|
||||
|
||||
// Turn FP truncstore into trunc + store.
|
||||
setTruncStoreAction(MVT::f64, MVT::f32, Expand);
|
||||
setTruncStoreAction(MVT::f128, MVT::f32, Expand);
|
||||
setTruncStoreAction(MVT::f128, MVT::f64, Expand);
|
||||
|
||||
// Custom legalize GlobalAddress nodes into LO/HI parts.
|
||||
setOperationAction(ISD::GlobalAddress, getPointerTy(), Custom);
|
||||
@ -1299,9 +1305,12 @@ SparcTargetLowering::SparcTargetLowering(TargetMachine &TM)
|
||||
setOperationAction(ISD::SELECT, MVT::i32, Expand);
|
||||
setOperationAction(ISD::SELECT, MVT::f32, Expand);
|
||||
setOperationAction(ISD::SELECT, MVT::f64, Expand);
|
||||
setOperationAction(ISD::SELECT, MVT::f128, Expand);
|
||||
|
||||
setOperationAction(ISD::SETCC, MVT::i32, Expand);
|
||||
setOperationAction(ISD::SETCC, MVT::f32, Expand);
|
||||
setOperationAction(ISD::SETCC, MVT::f64, Expand);
|
||||
setOperationAction(ISD::SETCC, MVT::f128, Expand);
|
||||
|
||||
// Sparc doesn't have BRCOND either, it has BR_CC.
|
||||
setOperationAction(ISD::BRCOND, MVT::Other, Expand);
|
||||
@ -1310,10 +1319,12 @@ SparcTargetLowering::SparcTargetLowering(TargetMachine &TM)
|
||||
setOperationAction(ISD::BR_CC, MVT::i32, Custom);
|
||||
setOperationAction(ISD::BR_CC, MVT::f32, Custom);
|
||||
setOperationAction(ISD::BR_CC, MVT::f64, Custom);
|
||||
setOperationAction(ISD::BR_CC, MVT::f128, Custom);
|
||||
|
||||
setOperationAction(ISD::SELECT_CC, MVT::i32, Custom);
|
||||
setOperationAction(ISD::SELECT_CC, MVT::f32, Custom);
|
||||
setOperationAction(ISD::SELECT_CC, MVT::f64, Custom);
|
||||
setOperationAction(ISD::SELECT_CC, MVT::f128, Custom);
|
||||
|
||||
if (Subtarget->is64Bit()) {
|
||||
setOperationAction(ISD::BITCAST, MVT::f64, Expand);
|
||||
@ -1334,6 +1345,11 @@ SparcTargetLowering::SparcTargetLowering(TargetMachine &TM)
|
||||
setOperationAction(ISD::FABS, MVT::f64, Custom);
|
||||
}
|
||||
|
||||
setOperationAction(ISD::FSIN , MVT::f128, Expand);
|
||||
setOperationAction(ISD::FCOS , MVT::f128, Expand);
|
||||
setOperationAction(ISD::FSINCOS, MVT::f128, Expand);
|
||||
setOperationAction(ISD::FREM , MVT::f128, Expand);
|
||||
setOperationAction(ISD::FMA , MVT::f128, Expand);
|
||||
setOperationAction(ISD::FSIN , MVT::f64, Expand);
|
||||
setOperationAction(ISD::FCOS , MVT::f64, Expand);
|
||||
setOperationAction(ISD::FSINCOS, MVT::f64, Expand);
|
||||
@ -1352,8 +1368,10 @@ SparcTargetLowering::SparcTargetLowering(TargetMachine &TM)
|
||||
setOperationAction(ISD::ROTL , MVT::i32, Expand);
|
||||
setOperationAction(ISD::ROTR , MVT::i32, Expand);
|
||||
setOperationAction(ISD::BSWAP, MVT::i32, Expand);
|
||||
setOperationAction(ISD::FCOPYSIGN, MVT::f128, Expand);
|
||||
setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand);
|
||||
setOperationAction(ISD::FCOPYSIGN, MVT::f32, Expand);
|
||||
setOperationAction(ISD::FPOW , MVT::f128, Expand);
|
||||
setOperationAction(ISD::FPOW , MVT::f64, Expand);
|
||||
setOperationAction(ISD::FPOW , MVT::f32, Expand);
|
||||
|
||||
@ -1387,6 +1405,31 @@ SparcTargetLowering::SparcTargetLowering(TargetMachine &TM)
|
||||
if (Subtarget->isV9())
|
||||
setOperationAction(ISD::CTPOP, MVT::i32, Legal);
|
||||
|
||||
if (Subtarget->isV9() && Subtarget->hasHardQuad()) {
|
||||
setOperationAction(ISD::LOAD, MVT::f128, Legal);
|
||||
setOperationAction(ISD::STORE, MVT::f128, Legal);
|
||||
} else {
|
||||
setOperationAction(ISD::LOAD, MVT::f128, Custom);
|
||||
setOperationAction(ISD::STORE, MVT::f128, Custom);
|
||||
}
|
||||
|
||||
if (Subtarget->hasHardQuad()) {
|
||||
setOperationAction(ISD::FADD, MVT::f128, Legal);
|
||||
setOperationAction(ISD::FSUB, MVT::f128, Legal);
|
||||
setOperationAction(ISD::FMUL, MVT::f128, Legal);
|
||||
setOperationAction(ISD::FDIV, MVT::f128, Legal);
|
||||
setOperationAction(ISD::FSQRT, MVT::f128, Legal);
|
||||
setOperationAction(ISD::FP_EXTEND, MVT::f128, Legal);
|
||||
setOperationAction(ISD::FP_ROUND, MVT::f64, Legal);
|
||||
if (Subtarget->isV9()) {
|
||||
setOperationAction(ISD::FNEG, MVT::f128, Legal);
|
||||
setOperationAction(ISD::FABS, MVT::f128, Legal);
|
||||
} else {
|
||||
setOperationAction(ISD::FNEG, MVT::f128, Custom);
|
||||
setOperationAction(ISD::FABS, MVT::f128, Custom);
|
||||
}
|
||||
}
|
||||
|
||||
setMinFunctionAlignment(2);
|
||||
|
||||
computeRegisterProperties();
|
||||
@ -1800,6 +1843,94 @@ static SDValue LowerF64Op(SDValue Op, SelectionDAG &DAG)
|
||||
return DstReg64;
|
||||
}
|
||||
|
||||
// Lower a f128 load into two f64 loads.
|
||||
static SDValue LowerF128Load(SDValue Op, SelectionDAG &DAG)
|
||||
{
|
||||
SDLoc dl(Op);
|
||||
LoadSDNode *LdNode = dyn_cast<LoadSDNode>(Op.getNode());
|
||||
assert(LdNode && LdNode->getOffset().getOpcode() == ISD::UNDEF
|
||||
&& "Unexpected node type");
|
||||
|
||||
SDValue Hi64 = DAG.getLoad(MVT::f64,
|
||||
dl,
|
||||
LdNode->getChain(),
|
||||
LdNode->getBasePtr(),
|
||||
LdNode->getPointerInfo(),
|
||||
false, false, false, 8);
|
||||
EVT addrVT = LdNode->getBasePtr().getValueType();
|
||||
SDValue LoPtr = DAG.getNode(ISD::ADD, dl, addrVT,
|
||||
LdNode->getBasePtr(),
|
||||
DAG.getConstant(8, addrVT));
|
||||
SDValue Lo64 = DAG.getLoad(MVT::f64,
|
||||
dl,
|
||||
LdNode->getChain(),
|
||||
LoPtr,
|
||||
LdNode->getPointerInfo(),
|
||||
false, false, false, 8);
|
||||
|
||||
SDValue SubRegEven = DAG.getTargetConstant(SP::sub_even64, MVT::i32);
|
||||
SDValue SubRegOdd = DAG.getTargetConstant(SP::sub_odd64, MVT::i32);
|
||||
|
||||
SDNode *InFP128 = DAG.getMachineNode(TargetOpcode::IMPLICIT_DEF,
|
||||
dl, MVT::f128);
|
||||
InFP128 = DAG.getMachineNode(TargetOpcode::INSERT_SUBREG, dl,
|
||||
MVT::f128,
|
||||
SDValue(InFP128, 0),
|
||||
Hi64,
|
||||
SubRegEven);
|
||||
InFP128 = DAG.getMachineNode(TargetOpcode::INSERT_SUBREG, dl,
|
||||
MVT::f128,
|
||||
SDValue(InFP128, 0),
|
||||
Lo64,
|
||||
SubRegOdd);
|
||||
SDValue OutChains[2] = { SDValue(Hi64.getNode(), 1),
|
||||
SDValue(Lo64.getNode(), 1) };
|
||||
SDValue OutChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
|
||||
&OutChains[0], 2);
|
||||
SDValue Ops[2] = {SDValue(InFP128,0), OutChain};
|
||||
return DAG.getMergeValues(Ops, 2, dl);
|
||||
}
|
||||
|
||||
// Lower a f128 store into two f64 stores.
|
||||
static SDValue LowerF128Store(SDValue Op, SelectionDAG &DAG) {
|
||||
SDLoc dl(Op);
|
||||
StoreSDNode *StNode = dyn_cast<StoreSDNode>(Op.getNode());
|
||||
assert(StNode && StNode->getOffset().getOpcode() == ISD::UNDEF
|
||||
&& "Unexpected node type");
|
||||
SDValue SubRegEven = DAG.getTargetConstant(SP::sub_even64, MVT::i32);
|
||||
SDValue SubRegOdd = DAG.getTargetConstant(SP::sub_odd64, MVT::i32);
|
||||
|
||||
SDNode *Hi64 = DAG.getMachineNode(TargetOpcode::EXTRACT_SUBREG,
|
||||
dl,
|
||||
MVT::f64,
|
||||
StNode->getValue(),
|
||||
SubRegEven);
|
||||
SDNode *Lo64 = DAG.getMachineNode(TargetOpcode::EXTRACT_SUBREG,
|
||||
dl,
|
||||
MVT::f64,
|
||||
StNode->getValue(),
|
||||
SubRegOdd);
|
||||
SDValue OutChains[2];
|
||||
OutChains[0] = DAG.getStore(StNode->getChain(),
|
||||
dl,
|
||||
SDValue(Hi64, 0),
|
||||
StNode->getBasePtr(),
|
||||
MachinePointerInfo(),
|
||||
false, false, 8);
|
||||
EVT addrVT = StNode->getBasePtr().getValueType();
|
||||
SDValue LoPtr = DAG.getNode(ISD::ADD, dl, addrVT,
|
||||
StNode->getBasePtr(),
|
||||
DAG.getConstant(8, addrVT));
|
||||
OutChains[1] = DAG.getStore(StNode->getChain(),
|
||||
dl,
|
||||
SDValue(Lo64, 0),
|
||||
LoPtr,
|
||||
MachinePointerInfo(),
|
||||
false, false, 8);
|
||||
return DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
|
||||
&OutChains[0], 2);
|
||||
}
|
||||
|
||||
SDValue SparcTargetLowering::
|
||||
LowerOperation(SDValue Op, SelectionDAG &DAG) const {
|
||||
switch (Op.getOpcode()) {
|
||||
@ -1822,6 +1953,9 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) const {
|
||||
case ISD::VASTART: return LowerVASTART(Op, DAG, *this);
|
||||
case ISD::VAARG: return LowerVAARG(Op, DAG);
|
||||
case ISD::DYNAMIC_STACKALLOC: return LowerDYNAMIC_STACKALLOC(Op, DAG);
|
||||
|
||||
case ISD::LOAD: return LowerF128Load(Op, DAG);
|
||||
case ISD::STORE: return LowerF128Store(Op, DAG);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -39,6 +39,10 @@ def HasNoV9 : Predicate<"!Subtarget.isV9()">;
|
||||
// HasVIS - This is true when the target processor has VIS extensions.
|
||||
def HasVIS : Predicate<"Subtarget.isVIS()">;
|
||||
|
||||
// HasHardQuad - This is true when the target processor supports quad floating
|
||||
// point instructions.
|
||||
def HasHardQuad : Predicate<"Subtarget.hasHardQuad()">;
|
||||
|
||||
// UseDeprecatedInsts - This predicate is true when the target processor is a
|
||||
// V8, or when it is V9 but the V8 deprecated instructions are efficient enough
|
||||
// to use when appropriate. In either of these cases, the instruction selector
|
||||
@ -354,6 +358,16 @@ def LDDFri : F3_2<3, 0b100011,
|
||||
(outs DFPRegs:$dst), (ins MEMri:$addr),
|
||||
"ldd [$addr], $dst",
|
||||
[(set f64:$dst, (load ADDRri:$addr))]>;
|
||||
def LDQFrr : F3_1<3, 0b100010,
|
||||
(outs QFPRegs:$dst), (ins MEMrr:$addr),
|
||||
"ldq [$addr], $dst",
|
||||
[(set f128:$dst, (load ADDRrr:$addr))]>,
|
||||
Requires<[HasV9, HasHardQuad]>;
|
||||
def LDQFri : F3_2<3, 0b100010,
|
||||
(outs QFPRegs:$dst), (ins MEMri:$addr),
|
||||
"ldq [$addr], $dst",
|
||||
[(set f128:$dst, (load ADDRri:$addr))]>,
|
||||
Requires<[HasV9, HasHardQuad]>;
|
||||
|
||||
// Section B.4 - Store Integer Instructions, p. 95
|
||||
def STBrr : F3_1<3, 0b000101,
|
||||
@ -398,6 +412,16 @@ def STDFri : F3_2<3, 0b100111,
|
||||
(outs), (ins MEMri:$addr, DFPRegs:$src),
|
||||
"std $src, [$addr]",
|
||||
[(store f64:$src, ADDRri:$addr)]>;
|
||||
def STQFrr : F3_1<3, 0b100110,
|
||||
(outs), (ins MEMrr:$addr, QFPRegs:$src),
|
||||
"stq $src, [$addr]",
|
||||
[(store f128:$src, ADDRrr:$addr)]>,
|
||||
Requires<[HasV9, HasHardQuad]>;
|
||||
def STQFri : F3_2<3, 0b100110,
|
||||
(outs), (ins MEMri:$addr, QFPRegs:$src),
|
||||
"stq $src, [$addr]",
|
||||
[(store f128:$src, ADDRri:$addr)]>,
|
||||
Requires<[HasV9, HasHardQuad]>;
|
||||
|
||||
// Section B.9 - SETHI Instruction, p. 104
|
||||
def SETHIi: F2_1<0b100,
|
||||
@ -599,6 +623,11 @@ def FITOD : F3_3<2, 0b110100, 0b011001000,
|
||||
(outs DFPRegs:$dst), (ins FPRegs:$src),
|
||||
"fitod $src, $dst",
|
||||
[(set DFPRegs:$dst, (SPitof FPRegs:$src))]>;
|
||||
def FITOQ : F3_3<2, 0b110100, 0b011001100,
|
||||
(outs QFPRegs:$dst), (ins FPRegs:$src),
|
||||
"fitoq $src, $dst",
|
||||
[(set QFPRegs:$dst, (SPitof FPRegs:$src))]>,
|
||||
Requires<[HasHardQuad]>;
|
||||
|
||||
// Convert Floating-point to Integer Instructions, p. 142
|
||||
def FSTOI : F3_3<2, 0b110100, 0b011010001,
|
||||
@ -609,16 +638,41 @@ def FDTOI : F3_3<2, 0b110100, 0b011010010,
|
||||
(outs FPRegs:$dst), (ins DFPRegs:$src),
|
||||
"fdtoi $src, $dst",
|
||||
[(set FPRegs:$dst, (SPftoi DFPRegs:$src))]>;
|
||||
def FQTOI : F3_3<2, 0b110100, 0b011010011,
|
||||
(outs FPRegs:$dst), (ins QFPRegs:$src),
|
||||
"fqtoi $src, $dst",
|
||||
[(set FPRegs:$dst, (SPftoi QFPRegs:$src))]>,
|
||||
Requires<[HasHardQuad]>;
|
||||
|
||||
// Convert between Floating-point Formats Instructions, p. 143
|
||||
def FSTOD : F3_3<2, 0b110100, 0b011001001,
|
||||
(outs DFPRegs:$dst), (ins FPRegs:$src),
|
||||
"fstod $src, $dst",
|
||||
[(set f64:$dst, (fextend f32:$src))]>;
|
||||
def FSTOQ : F3_3<2, 0b110100, 0b011001101,
|
||||
(outs QFPRegs:$dst), (ins FPRegs:$src),
|
||||
"fstoq $src, $dst",
|
||||
[(set f128:$dst, (fextend f32:$src))]>,
|
||||
Requires<[HasHardQuad]>;
|
||||
def FDTOS : F3_3<2, 0b110100, 0b011000110,
|
||||
(outs FPRegs:$dst), (ins DFPRegs:$src),
|
||||
"fdtos $src, $dst",
|
||||
[(set f32:$dst, (fround f64:$src))]>;
|
||||
def FDTOQ : F3_3<2, 0b110100, 0b01101110,
|
||||
(outs QFPRegs:$dst), (ins DFPRegs:$src),
|
||||
"fdtoq $src, $dst",
|
||||
[(set f128:$dst, (fextend f64:$src))]>,
|
||||
Requires<[HasHardQuad]>;
|
||||
def FQTOS : F3_3<2, 0b110100, 0b011000111,
|
||||
(outs FPRegs:$dst), (ins QFPRegs:$src),
|
||||
"fqtos $src, $dst",
|
||||
[(set f32:$dst, (fround f128:$src))]>,
|
||||
Requires<[HasHardQuad]>;
|
||||
def FQTOD : F3_3<2, 0b110100, 0b011001011,
|
||||
(outs DFPRegs:$dst), (ins QFPRegs:$src),
|
||||
"fqtod $src, $dst",
|
||||
[(set f64:$dst, (fround f128:$src))]>,
|
||||
Requires<[HasHardQuad]>;
|
||||
|
||||
// Floating-point Move Instructions, p. 144
|
||||
def FMOVS : F3_3<2, 0b110100, 0b000000001,
|
||||
@ -643,6 +697,11 @@ def FSQRTD : F3_3<2, 0b110100, 0b000101010,
|
||||
(outs DFPRegs:$dst), (ins DFPRegs:$src),
|
||||
"fsqrtd $src, $dst",
|
||||
[(set f64:$dst, (fsqrt f64:$src))]>;
|
||||
def FSQRTQ : F3_3<2, 0b110100, 0b000101011,
|
||||
(outs QFPRegs:$dst), (ins QFPRegs:$src),
|
||||
"fsqrtq $src, $dst",
|
||||
[(set f128:$dst, (fsqrt f128:$src))]>,
|
||||
Requires<[HasHardQuad]>;
|
||||
|
||||
|
||||
|
||||
@ -655,6 +714,12 @@ def FADDD : F3_3<2, 0b110100, 0b001000010,
|
||||
(outs DFPRegs:$dst), (ins DFPRegs:$src1, DFPRegs:$src2),
|
||||
"faddd $src1, $src2, $dst",
|
||||
[(set f64:$dst, (fadd f64:$src1, f64:$src2))]>;
|
||||
def FADDQ : F3_3<2, 0b110100, 0b001000011,
|
||||
(outs QFPRegs:$dst), (ins QFPRegs:$src1, QFPRegs:$src2),
|
||||
"faddq $src1, $src2, $dst",
|
||||
[(set f128:$dst, (fadd f128:$src1, f128:$src2))]>,
|
||||
Requires<[HasHardQuad]>;
|
||||
|
||||
def FSUBS : F3_3<2, 0b110100, 0b001000101,
|
||||
(outs FPRegs:$dst), (ins FPRegs:$src1, FPRegs:$src2),
|
||||
"fsubs $src1, $src2, $dst",
|
||||
@ -663,6 +728,12 @@ def FSUBD : F3_3<2, 0b110100, 0b001000110,
|
||||
(outs DFPRegs:$dst), (ins DFPRegs:$src1, DFPRegs:$src2),
|
||||
"fsubd $src1, $src2, $dst",
|
||||
[(set f64:$dst, (fsub f64:$src1, f64:$src2))]>;
|
||||
def FSUBQ : F3_3<2, 0b110100, 0b001000111,
|
||||
(outs QFPRegs:$dst), (ins QFPRegs:$src1, QFPRegs:$src2),
|
||||
"fsubq $src1, $src2, $dst",
|
||||
[(set f128:$dst, (fsub f128:$src1, f128:$src2))]>,
|
||||
Requires<[HasHardQuad]>;
|
||||
|
||||
|
||||
// Floating-point Multiply and Divide Instructions, p. 147
|
||||
def FMULS : F3_3<2, 0b110100, 0b001001001,
|
||||
@ -673,11 +744,24 @@ def FMULD : F3_3<2, 0b110100, 0b001001010,
|
||||
(outs DFPRegs:$dst), (ins DFPRegs:$src1, DFPRegs:$src2),
|
||||
"fmuld $src1, $src2, $dst",
|
||||
[(set f64:$dst, (fmul f64:$src1, f64:$src2))]>;
|
||||
def FMULQ : F3_3<2, 0b110100, 0b001001011,
|
||||
(outs QFPRegs:$dst), (ins QFPRegs:$src1, QFPRegs:$src2),
|
||||
"fmulq $src1, $src2, $dst",
|
||||
[(set f128:$dst, (fmul f128:$src1, f128:$src2))]>,
|
||||
Requires<[HasHardQuad]>;
|
||||
|
||||
def FSMULD : F3_3<2, 0b110100, 0b001101001,
|
||||
(outs DFPRegs:$dst), (ins FPRegs:$src1, FPRegs:$src2),
|
||||
"fsmuld $src1, $src2, $dst",
|
||||
[(set f64:$dst, (fmul (fextend f32:$src1),
|
||||
(fextend f32:$src2)))]>;
|
||||
def FDMULQ : F3_3<2, 0b110100, 0b001101110,
|
||||
(outs QFPRegs:$dst), (ins DFPRegs:$src1, DFPRegs:$src2),
|
||||
"fdmulq $src1, $src2, $dst",
|
||||
[(set f128:$dst, (fmul (fextend f64:$src1),
|
||||
(fextend f64:$src2)))]>,
|
||||
Requires<[HasHardQuad]>;
|
||||
|
||||
def FDIVS : F3_3<2, 0b110100, 0b001001101,
|
||||
(outs FPRegs:$dst), (ins FPRegs:$src1, FPRegs:$src2),
|
||||
"fdivs $src1, $src2, $dst",
|
||||
@ -686,6 +770,11 @@ def FDIVD : F3_3<2, 0b110100, 0b001001110,
|
||||
(outs DFPRegs:$dst), (ins DFPRegs:$src1, DFPRegs:$src2),
|
||||
"fdivd $src1, $src2, $dst",
|
||||
[(set f64:$dst, (fdiv f64:$src1, f64:$src2))]>;
|
||||
def FDIVQ : F3_3<2, 0b110100, 0b001001111,
|
||||
(outs QFPRegs:$dst), (ins QFPRegs:$src1, QFPRegs:$src2),
|
||||
"fdivq $src1, $src2, $dst",
|
||||
[(set f128:$dst, (fdiv f128:$src1, f128:$src2))]>,
|
||||
Requires<[HasHardQuad]>;
|
||||
|
||||
// Floating-point Compare Instructions, p. 148
|
||||
// Note: the 2nd template arg is different for these guys.
|
||||
@ -701,6 +790,11 @@ let Defs = [FCC] in {
|
||||
(outs), (ins DFPRegs:$src1, DFPRegs:$src2),
|
||||
"fcmpd $src1, $src2\n\tnop",
|
||||
[(SPcmpfcc f64:$src1, f64:$src2)]>;
|
||||
def FCMPQ : F3_3<2, 0b110101, 0b001010011,
|
||||
(outs), (ins QFPRegs:$src1, QFPRegs:$src2),
|
||||
"fcmpq $src1, $src2\n\tnop",
|
||||
[(SPcmpfcc f128:$src1, f128:$src2)]>,
|
||||
Requires<[HasHardQuad]>;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -762,14 +856,28 @@ let Predicates = [HasV9] in {
|
||||
def FMOVD : F3_3<2, 0b110100, 0b000000010,
|
||||
(outs DFPRegs:$dst), (ins DFPRegs:$src),
|
||||
"fmovd $src, $dst", []>;
|
||||
def FMOVQ : F3_3<2, 0b110100, 0b000000011,
|
||||
(outs QFPRegs:$dst), (ins QFPRegs:$src),
|
||||
"fmovq $src, $dst", []>,
|
||||
Requires<[HasHardQuad]>;
|
||||
def FNEGD : F3_3<2, 0b110100, 0b000000110,
|
||||
(outs DFPRegs:$dst), (ins DFPRegs:$src),
|
||||
"fnegd $src, $dst",
|
||||
[(set f64:$dst, (fneg f64:$src))]>;
|
||||
def FNEGQ : F3_3<2, 0b110100, 0b000000111,
|
||||
(outs QFPRegs:$dst), (ins QFPRegs:$src),
|
||||
"fnegq $src, $dst",
|
||||
[(set f128:$dst, (fneg f128:$src))]>,
|
||||
Requires<[HasHardQuad]>;
|
||||
def FABSD : F3_3<2, 0b110100, 0b000001010,
|
||||
(outs DFPRegs:$dst), (ins DFPRegs:$src),
|
||||
"fabsd $src, $dst",
|
||||
[(set f64:$dst, (fabs f64:$src))]>;
|
||||
def FABSQ : F3_3<2, 0b110100, 0b000001011,
|
||||
(outs QFPRegs:$dst), (ins QFPRegs:$src),
|
||||
"fabsq $src, $dst",
|
||||
[(set f128:$dst, (fabs f128:$src))]>,
|
||||
Requires<[HasHardQuad]>;
|
||||
}
|
||||
|
||||
// POPCrr - This does a ctpop of a 64-bit register. As such, we have to clear
|
||||
|
@ -30,7 +30,8 @@ SparcSubtarget::SparcSubtarget(const std::string &TT, const std::string &CPU,
|
||||
IsV9(false),
|
||||
V8DeprecatedInsts(false),
|
||||
IsVIS(false),
|
||||
Is64Bit(is64Bit) {
|
||||
Is64Bit(is64Bit),
|
||||
HasHardQuad(false) {
|
||||
|
||||
// Determine default and user specified characteristics
|
||||
std::string CPUName = CPU;
|
||||
|
@ -29,6 +29,7 @@ class SparcSubtarget : public SparcGenSubtargetInfo {
|
||||
bool V8DeprecatedInsts;
|
||||
bool IsVIS;
|
||||
bool Is64Bit;
|
||||
bool HasHardQuad;
|
||||
|
||||
public:
|
||||
SparcSubtarget(const std::string &TT, const std::string &CPU,
|
||||
@ -37,6 +38,7 @@ public:
|
||||
bool isV9() const { return IsV9; }
|
||||
bool isVIS() const { return IsVIS; }
|
||||
bool useDeprecatedV8Instructions() const { return V8DeprecatedInsts; }
|
||||
bool hasHardQuad() const { return HasHardQuad; }
|
||||
|
||||
/// ParseSubtargetFeatures - Parses features string setting specified
|
||||
/// subtarget options. Definition of function is auto generated by tblgen.
|
||||
|
27
test/CodeGen/SPARC/fp128.ll
Normal file
27
test/CodeGen/SPARC/fp128.ll
Normal file
@ -0,0 +1,27 @@
|
||||
; RUN: llc < %s -march=sparc -mattr=hard-quad-float | FileCheck %s
|
||||
|
||||
; CHECK-LABEL: f128_ops
|
||||
; CHECK: ldd
|
||||
; CHECK: ldd
|
||||
; CHECK: ldd
|
||||
; CHECK: ldd
|
||||
; CHECK: faddq [[R0:.+]], [[R1:.+]], [[R2:.+]]
|
||||
; CHECK: fsubq [[R2]], [[R3:.+]], [[R4:.+]]
|
||||
; CHECK: fmulq [[R4]], [[R5:.+]], [[R6:.+]]
|
||||
; CHECK: fdivq [[R6]], [[R2]]
|
||||
; CHECK: std
|
||||
; CHECK: std
|
||||
|
||||
define void @f128_ops(fp128* noalias sret %scalar.result, fp128* byval %a, fp128* byval %b, fp128* byval %c, fp128* byval %d) {
|
||||
entry:
|
||||
%0 = load fp128* %a, align 8
|
||||
%1 = load fp128* %b, align 8
|
||||
%2 = load fp128* %c, align 8
|
||||
%3 = load fp128* %d, align 8
|
||||
%4 = fadd fp128 %0, %1
|
||||
%5 = fsub fp128 %4, %2
|
||||
%6 = fmul fp128 %5, %3
|
||||
%7 = fdiv fp128 %6, %4
|
||||
store fp128 %7, fp128* %scalar.result, align 8
|
||||
ret void
|
||||
}
|
Loading…
Reference in New Issue
Block a user