mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-13 04:30:23 +00:00
Added support for fround, fextend and FP_TO_SINT
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@72483 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
0d09b83a48
commit
d3bdf19ce7
@ -39,6 +39,8 @@ def FeatureFP64Bit : SubtargetFeature<"fp64", "IsFP64bit", "true",
|
||||
"Support 64-bit FP registers.">;
|
||||
def FeatureSingleFloat : SubtargetFeature<"single-float", "IsSingleFloat",
|
||||
"true", "Only supports single precision float">;
|
||||
def FeatureMips1 : SubtargetFeature<"mips1", "MipsArchVersion", "Mips1",
|
||||
"Mips1 ISA Support">;
|
||||
def FeatureMips2 : SubtargetFeature<"mips2", "MipsArchVersion", "Mips2",
|
||||
"Mips2 ISA Support">;
|
||||
def FeatureO32 : SubtargetFeature<"o32", "MipsABI", "O32",
|
||||
@ -67,9 +69,9 @@ def FeatureBitCount : SubtargetFeature<"bitcount", "HasBitCount", "true",
|
||||
class Proc<string Name, list<SubtargetFeature> Features>
|
||||
: Processor<Name, MipsGenericItineraries, Features>;
|
||||
|
||||
def : Proc<"mips1", []>;
|
||||
def : Proc<"r2000", []>;
|
||||
def : Proc<"r3000", []>;
|
||||
def : Proc<"mips1", [FeatureMips1]>;
|
||||
def : Proc<"r2000", [FeatureMips1]>;
|
||||
def : Proc<"r3000", [FeatureMips1]>;
|
||||
|
||||
def : Proc<"mips2", [FeatureMips2]>;
|
||||
def : Proc<"r6000", [FeatureMips2]>;
|
||||
|
@ -48,6 +48,7 @@ getTargetNodeName(unsigned Opcode) const
|
||||
case MipsISD::FPSelectCC : return "MipsISD::FPSelectCC";
|
||||
case MipsISD::FPBrcond : return "MipsISD::FPBrcond";
|
||||
case MipsISD::FPCmp : return "MipsISD::FPCmp";
|
||||
case MipsISD::FPRound : return "MipsISD::FPRound";
|
||||
default : return NULL;
|
||||
}
|
||||
}
|
||||
@ -96,8 +97,10 @@ MipsTargetLowering(MipsTargetMachine &TM): TargetLowering(TM)
|
||||
setOperationAction(ISD::SELECT, MVT::f32, Custom);
|
||||
setOperationAction(ISD::SELECT, MVT::i32, Custom);
|
||||
setOperationAction(ISD::SETCC, MVT::f32, Custom);
|
||||
setOperationAction(ISD::SETCC, MVT::f64, Custom);
|
||||
setOperationAction(ISD::BRCOND, MVT::Other, Custom);
|
||||
setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Custom);
|
||||
setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom);
|
||||
|
||||
// We custom lower AND/OR to handle the case where the DAG contain 'ands/ors'
|
||||
// with operands comming from setcc fp comparions. This is necessary since
|
||||
@ -166,6 +169,7 @@ LowerOperation(SDValue Op, SelectionDAG &DAG)
|
||||
case ISD::ConstantPool: return LowerConstantPool(Op, DAG);
|
||||
case ISD::DYNAMIC_STACKALLOC: return LowerDYNAMIC_STACKALLOC(Op, DAG);
|
||||
case ISD::FORMAL_ARGUMENTS: return LowerFORMAL_ARGUMENTS(Op, DAG);
|
||||
case ISD::FP_TO_SINT: return LowerFP_TO_SINT(Op, DAG);
|
||||
case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG);
|
||||
case ISD::GlobalTLSAddress: return LowerGlobalTLSAddress(Op, DAG);
|
||||
case ISD::JumpTable: return LowerJumpTable(Op, DAG);
|
||||
@ -358,6 +362,39 @@ MipsTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
|
||||
// Misc Lower Operation implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
SDValue MipsTargetLowering::
|
||||
LowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG)
|
||||
{
|
||||
if (!Subtarget->isMips1())
|
||||
return Op;
|
||||
|
||||
MachineFunction &MF = DAG.getMachineFunction();
|
||||
unsigned CCReg = AddLiveIn(MF, Mips::FCR31, Mips::CCRRegisterClass);
|
||||
|
||||
SDValue Chain = DAG.getEntryNode();
|
||||
DebugLoc dl = Op.getDebugLoc();
|
||||
SDValue Src = Op.getOperand(0);
|
||||
|
||||
// Set the condition register
|
||||
SDValue CondReg = DAG.getCopyFromReg(Chain, dl, CCReg, MVT::i32);
|
||||
CondReg = DAG.getCopyToReg(Chain, dl, Mips::AT, CondReg);
|
||||
CondReg = DAG.getCopyFromReg(CondReg, dl, Mips::AT, MVT::i32);
|
||||
|
||||
SDValue Cst = DAG.getConstant(3, MVT::i32);
|
||||
SDValue Or = DAG.getNode(ISD::OR, dl, MVT::i32, CondReg, Cst);
|
||||
Cst = DAG.getConstant(2, MVT::i32);
|
||||
SDValue Xor = DAG.getNode(ISD::XOR, dl, MVT::i32, Or, Cst);
|
||||
|
||||
SDValue InFlag(0, 0);
|
||||
CondReg = DAG.getCopyToReg(Chain, dl, Mips::FCR31, Xor, InFlag);
|
||||
|
||||
// Emit the round instruction and bit convert to integer
|
||||
SDValue Trunc = DAG.getNode(MipsISD::FPRound, dl, MVT::f32,
|
||||
Src, CondReg.getValue(1));
|
||||
SDValue BitCvt = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::i32, Trunc);
|
||||
return BitCvt;
|
||||
}
|
||||
|
||||
SDValue MipsTargetLowering::
|
||||
LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG)
|
||||
{
|
||||
|
@ -55,6 +55,9 @@ namespace llvm {
|
||||
// Floating Point Compare
|
||||
FPCmp,
|
||||
|
||||
// Floating Point Rounding
|
||||
FPRound,
|
||||
|
||||
// Return
|
||||
Ret
|
||||
};
|
||||
@ -98,6 +101,7 @@ namespace llvm {
|
||||
SDValue LowerConstantPool(SDValue Op, SelectionDAG &DAG);
|
||||
SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG);
|
||||
SDValue LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG);
|
||||
SDValue LowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG);
|
||||
SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG);
|
||||
SDValue LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG);
|
||||
SDValue LowerJumpTable(SDValue Op, SelectionDAG &DAG);
|
||||
|
@ -30,6 +30,8 @@ def SDT_MipsFPCmp : SDTypeProfile<0, 3, [SDTCisSameAs<0, 1>, SDTCisFP<0>,
|
||||
SDTCisInt<2>]>;
|
||||
def SDT_MipsFPSelectCC : SDTypeProfile<1, 4, [SDTCisInt<1>, SDTCisInt<4>,
|
||||
SDTCisSameAs<0, 2>, SDTCisSameAs<2, 3>]>;
|
||||
|
||||
def MipsFPRound : SDNode<"MipsISD::FPRound", SDTFPRoundOp, [SDNPOptInFlag]>;
|
||||
def MipsFPBrcond : SDNode<"MipsISD::FPBrcond", SDT_MipsFPBrcond,
|
||||
[SDNPHasChain]>;
|
||||
def MipsFPCmp : SDNode<"MipsISD::FPCmp", SDT_MipsFPCmp>;
|
||||
@ -66,7 +68,7 @@ multiclass FFR1_1<bits<6> funct, string asmstr>
|
||||
def _S32 : FFR<0x11, funct, 0x0, (outs FGR32:$fd), (ins FGR32:$fs),
|
||||
!strconcat(asmstr, ".s $fd, $fs"), []>;
|
||||
|
||||
def _D32 : FFR<0x11, funct, 0x1, (outs AFGR64:$fd), (ins AFGR64:$fs),
|
||||
def _D32 : FFR<0x11, funct, 0x1, (outs FGR32:$fd), (ins AFGR64:$fs),
|
||||
!strconcat(asmstr, ".d $fd, $fs"), []>, Requires<[In32BitMode]>;
|
||||
}
|
||||
|
||||
@ -157,12 +159,12 @@ let ft = 0 in {
|
||||
// regardless of register aliasing.
|
||||
let fd = 0 in {
|
||||
/// Move Control Registers From/To CPU Registers
|
||||
///def CFC1 : FFR<0x11, 0x0, 0x2, (outs CPURegs:$rt), (ins FGR32:$fs),
|
||||
/// "cfc1 $rt, $fs", []>;
|
||||
def CFC1 : FFR<0x11, 0x0, 0x2, (outs CPURegs:$rt), (ins CCR:$fs),
|
||||
"cfc1 $rt, $fs", []>;
|
||||
|
||||
///def CTC1 : FFR<0x11, 0x0, 0x6, (outs CPURegs:$rt), (ins FGR32:$fs),
|
||||
/// "ctc1 $rt, $fs", []>;
|
||||
///
|
||||
def CTC1 : FFR<0x11, 0x0, 0x6, (outs CCR:$rt), (ins CPURegs:$fs),
|
||||
"ctc1 $fs, $rt", []>;
|
||||
|
||||
def MFC1 : FFR<0x11, 0x00, 0x00, (outs CPURegs:$rt), (ins FGR32:$fs),
|
||||
"mfc1 $rt, $fs", []>;
|
||||
|
||||
@ -272,6 +274,9 @@ def Select_FCC_S32 : PseudoFPSelCC<FGR32, "# MipsSelect_FCC_S32_f32">;
|
||||
def Select_FCC_D32 : PseudoFPSelCC<AFGR64, "# MipsSelect_FCC_D32_f32">,
|
||||
Requires<[In32BitMode]>;
|
||||
|
||||
def MOVCCRToCCR : MipsPseudo<(outs CCR:$dst), (ins CCR:$src),
|
||||
"# MOVCCRToCCR", []>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Floating Point Patterns
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -288,3 +293,12 @@ def : Pat<(i32 (fp_to_sint FGR32:$src)), (MFC1 (TRUNC_W_S32 FGR32:$src))>;
|
||||
|
||||
def : Pat<(i32 (bitconvert FGR32:$src)), (MFC1 FGR32:$src)>;
|
||||
def : Pat<(f32 (bitconvert CPURegs:$src)), (MTC1 CPURegs:$src)>;
|
||||
|
||||
let Predicates = [In32BitMode] in {
|
||||
def : Pat<(f32 (fround AFGR64:$src)), (CVTS_D32 AFGR64:$src)>;
|
||||
def : Pat<(f64 (fextend FGR32:$src)), (CVTD_S32 FGR32:$src)>;
|
||||
}
|
||||
|
||||
// MipsFPRound is only emitted for MipsI targets.
|
||||
def : Pat<(f32 (MipsFPRound AFGR64:$src)), (CVTW_D32 AFGR64:$src)>;
|
||||
|
||||
|
@ -55,7 +55,8 @@ isMoveInstr(const MachineInstr &MI, unsigned &SrcReg, unsigned &DstReg,
|
||||
if (MI.getOpcode() == Mips::FMOV_S32 ||
|
||||
MI.getOpcode() == Mips::FMOV_D32 ||
|
||||
MI.getOpcode() == Mips::MFC1 ||
|
||||
MI.getOpcode() == Mips::MTC1 ) {
|
||||
MI.getOpcode() == Mips::MTC1 ||
|
||||
MI.getOpcode() == Mips::MOVCCRToCCR) {
|
||||
DstReg = MI.getOperand(0).getReg();
|
||||
SrcReg = MI.getOperand(1).getReg();
|
||||
return true;
|
||||
@ -69,6 +70,7 @@ isMoveInstr(const MachineInstr &MI, unsigned &SrcReg, unsigned &DstReg,
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -132,22 +134,23 @@ copyRegToReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
|
||||
if (I != MBB.end()) DL = I->getDebugLoc();
|
||||
|
||||
if (DestRC != SrcRC) {
|
||||
// Moves between coprocessors and cpu
|
||||
|
||||
// Copy to/from FCR31 condition register
|
||||
if ((DestRC == Mips::CPURegsRegisterClass) &&
|
||||
(SrcRC == Mips::CCRRegisterClass))
|
||||
BuildMI(MBB, I, DL, get(Mips::CFC1), DestReg).addReg(SrcReg);
|
||||
else if ((DestRC == Mips::CCRRegisterClass) &&
|
||||
(SrcRC == Mips::CPURegsRegisterClass))
|
||||
BuildMI(MBB, I, DL, get(Mips::CTC1), DestReg).addReg(SrcReg);
|
||||
|
||||
// Moves between coprocessors and cpu
|
||||
else if ((DestRC == Mips::CPURegsRegisterClass) &&
|
||||
(SrcRC == Mips::FGR32RegisterClass))
|
||||
BuildMI(MBB, I, DL, get(Mips::MFC1), DestReg).addReg(SrcReg);
|
||||
else if ((DestRC == Mips::FGR32RegisterClass) &&
|
||||
(SrcRC == Mips::CPURegsRegisterClass))
|
||||
BuildMI(MBB, I, DL, get(Mips::MTC1), DestReg).addReg(SrcReg);
|
||||
|
||||
// Condition registers
|
||||
else if ((SrcRC == Mips::CCRRegisterClass) &&
|
||||
(SrcReg == Mips::FCR31))
|
||||
return true; // This register is used implicitly, no copy needed.
|
||||
else if ((DestRC == Mips::CCRRegisterClass) &&
|
||||
(DestReg == Mips::FCR31))
|
||||
return true; // This register is used implicitly, no copy needed.
|
||||
|
||||
// Move from/to Hi/Lo registers
|
||||
else if ((DestRC == Mips::HILORegisterClass) &&
|
||||
(SrcRC == Mips::CPURegsRegisterClass)) {
|
||||
@ -172,6 +175,8 @@ copyRegToReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
|
||||
BuildMI(MBB, I, DL, get(Mips::FMOV_S32), DestReg).addReg(SrcReg);
|
||||
else if (DestRC == Mips::AFGR64RegisterClass)
|
||||
BuildMI(MBB, I, DL, get(Mips::FMOV_D32), DestReg).addReg(SrcReg);
|
||||
else if (DestRC == Mips::CCRRegisterClass)
|
||||
BuildMI(MBB, I, DL, get(Mips::MOVCCRToCCR), DestReg).addReg(SrcReg);
|
||||
else
|
||||
// Can't copy this register
|
||||
return false;
|
||||
|
@ -518,10 +518,10 @@ let Uses = [LO] in
|
||||
|
||||
/// Sign Ext In Register Instructions.
|
||||
let Predicates = [HasSEInReg] in {
|
||||
let shamt = 0x10, rs = 0 in
|
||||
let shamt = 0x10, rs = 0 in
|
||||
def SEB : SignExtInReg<0x21, "seb", i8>;
|
||||
|
||||
let shamt = 0x18, rs = 0 in
|
||||
let shamt = 0x18, rs = 0 in
|
||||
def SEH : SignExtInReg<0x20, "seh", i16>;
|
||||
}
|
||||
|
||||
|
@ -131,7 +131,7 @@ let Namespace = "Mips" in {
|
||||
def LO : Register<"lo">, DwarfRegNum<[65]>;
|
||||
|
||||
// Status flags register
|
||||
def FCR31 : Register<"FCR31">;
|
||||
def FCR31 : Register<"31">;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -244,11 +244,9 @@ def AFGR64 : RegisterClass<"Mips", [f64], 64,
|
||||
}];
|
||||
}
|
||||
|
||||
def CCR : RegisterClass<"Mips", [i32], 32, [FCR31]> {
|
||||
let CopyCost = -1; // Don't allow copying of status registers.
|
||||
}
|
||||
// Condition Register for floating point operations
|
||||
def CCR : RegisterClass<"Mips", [i32], 32, [FCR31]>;
|
||||
|
||||
def HILO : RegisterClass<"Mips", [i32], 32, [HI, LO]> {
|
||||
//let CopyCost = -1; // Don't allow copying of hi/lo registers.
|
||||
}
|
||||
// Hi/Lo Registers
|
||||
def HILO : RegisterClass<"Mips", [i32], 32, [HI, LO]>;
|
||||
|
||||
|
@ -37,6 +37,7 @@ MipsSubtarget::MipsSubtarget(const TargetMachine &TM, const Module &M,
|
||||
HasMulDivAdd(false), HasMinMax(false), HasSwap(false), HasBitCount(false)
|
||||
{
|
||||
std::string CPU = "mips1";
|
||||
MipsArchVersion = Mips1;
|
||||
|
||||
// Parse features string.
|
||||
ParseSubtargetFeatures(FS, CPU);
|
||||
|
@ -112,7 +112,7 @@ public:
|
||||
std::string ParseSubtargetFeatures(const std::string &FS,
|
||||
const std::string &CPU);
|
||||
|
||||
bool hasMips2Ops() const { return MipsArchVersion >= Mips2; }
|
||||
bool isMips1() const { return MipsArchVersion == Mips1; }
|
||||
|
||||
bool isLittle() const { return IsLittle; }
|
||||
bool isFP64bit() const { return IsFP64bit; };
|
||||
|
Loading…
Reference in New Issue
Block a user