mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-12 03:32:10 +00:00
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@412 91177308-0d34-0410-b5e6-96231b3b80d8
416 lines
11 KiB
C++
416 lines
11 KiB
C++
// $Id$
|
|
//***************************************************************************
|
|
// File:
|
|
// Sparc.cpp
|
|
//
|
|
// Purpose:
|
|
//
|
|
// History:
|
|
// 7/15/01 - Vikram Adve - Created
|
|
//**************************************************************************/
|
|
|
|
#include "llvm/Method.h"
|
|
#include "llvm/Instruction.h"
|
|
|
|
#include "llvm/CodeGen/LiveRange.h"
|
|
#include "llvm/CodeGen/LiveRangeInfo.h"
|
|
#include "llvm/CodeGen/Sparc.h"
|
|
#include "llvm/CodeGen/SparcRegInfo.h"
|
|
|
|
//************************ Class Implementations **************************/
|
|
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
// UltraSparcRegInfo
|
|
// Purpose:
|
|
// This method will color incoming args to a method. If there are more
|
|
// args than that can fit in regs, code will be inserted to pop them from
|
|
// stack
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
void UltraSparcRegInfo::colorArgs(const Method *const Meth,
|
|
LiveRangeInfo& LRI) const
|
|
{
|
|
|
|
// get the argument list
|
|
const Method::ArgumentListType& ArgList = Meth->getArgumentList();
|
|
// get an iterator to arg list
|
|
Method::ArgumentListType::const_iterator ArgIt = ArgList.begin();
|
|
unsigned intArgNo=0;
|
|
|
|
// to keep track of which float regs are allocated for argument passing
|
|
bool FloatArgUsedArr[NumOfFloatArgRegs];
|
|
|
|
// init float arg used array
|
|
for(unsigned i=0; i < NumOfFloatArgRegs; ++i)
|
|
FloatArgUsedArr[i] = false;
|
|
|
|
// for each argument
|
|
for( ; ArgIt != ArgList.end() ; ++ArgIt) {
|
|
|
|
// get the LR of arg
|
|
LiveRange *const LR = LRI.getLiveRangeForValue((const Value *) *ArgIt);
|
|
unsigned RegClassID = (LR->getRegClass())->getID();
|
|
|
|
// if the arg is in int class - allocate a reg for an int arg
|
|
if( RegClassID == IntRegClassID ) {
|
|
|
|
if( intArgNo < NumOfIntArgRegs) {
|
|
LR->setColor( SparcIntRegOrder::i0 + intArgNo );
|
|
|
|
if( DEBUG_RA) printReg( LR );
|
|
}
|
|
|
|
else {
|
|
// TODO: Insert push code here
|
|
assert( 0 && "Insert push code here!");
|
|
}
|
|
++intArgNo;
|
|
}
|
|
|
|
// if the arg is float/double
|
|
else if ( RegClassID == FloatRegClassID) {
|
|
|
|
if( LR->getTypeID() == Type::DoubleTyID ) {
|
|
|
|
// find the first reg # we can pass a double arg
|
|
for(unsigned i=0; i < NumOfFloatArgRegs; i+= 2) {
|
|
if ( !FloatArgUsedArr[i] && !FloatArgUsedArr[i+1] ) {
|
|
LR->setColor( SparcFloatRegOrder::f0 + i );
|
|
FloatArgUsedArr[i] = true;
|
|
FloatArgUsedArr[i+1] = true;
|
|
if( DEBUG_RA) printReg( LR );
|
|
break;
|
|
}
|
|
}
|
|
if( ! LR->hasColor() ) { // if LR was not colored above
|
|
|
|
assert(0 && "insert push code here for a double");
|
|
|
|
}
|
|
|
|
}
|
|
else if( LR->getTypeID() == Type::FloatTyID ) {
|
|
|
|
// find the first reg # we can pass a float arg
|
|
for(unsigned i=0; i < NumOfFloatArgRegs; ++i) {
|
|
if ( !FloatArgUsedArr[i] ) {
|
|
LR->setColor( SparcFloatRegOrder::f0 + i );
|
|
FloatArgUsedArr[i] = true;
|
|
if( DEBUG_RA) printReg( LR );
|
|
break;
|
|
}
|
|
}
|
|
if( ! LR->hasColor() ) { // if LR was not colored above
|
|
assert(0 && "insert push code here for a float");
|
|
}
|
|
|
|
}
|
|
else
|
|
assert(0 && "unknown float type in method arg");
|
|
|
|
} // float register class
|
|
|
|
else
|
|
assert(0 && "Unknown RegClassID");
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void UltraSparcRegInfo::printReg(const LiveRange *const LR) {
|
|
|
|
unsigned RegClassID = (LR->getRegClass())->getID();
|
|
|
|
cout << " *Node " << (LR->getUserIGNode())->getIndex();
|
|
|
|
if( ! LR->hasColor() ) {
|
|
cout << " - could not find a color" << endl;
|
|
return;
|
|
}
|
|
|
|
// if a color is found
|
|
|
|
cout << " colored with color "<< LR->getColor();
|
|
|
|
if( RegClassID == IntRegClassID ) {
|
|
|
|
cout<< " [" << SparcIntRegOrder::getRegName(LR->getColor()) ;
|
|
cout << "]" << endl;
|
|
}
|
|
else if ( RegClassID == FloatRegClassID) {
|
|
cout << "[" << SparcFloatRegOrder::getRegName(LR->getColor());
|
|
if( LR->getTypeID() == Type::DoubleTyID )
|
|
cout << "+" << SparcFloatRegOrder::getRegName(LR->getColor()+1);
|
|
cout << "]" << endl;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void UltraSparcRegInfo::colorCallArgs(vector<const Instruction *> &
|
|
CallInstrList, LiveRangeInfo& LRI ) const
|
|
{
|
|
|
|
vector<const Instruction *>::const_iterator InstIt = CallInstrList.begin();
|
|
|
|
for( ; InstIt != CallInstrList.end(); ++InstIt) {
|
|
|
|
// Inst = LLVM call instruction
|
|
const Instruction *const CallI = *InstIt;
|
|
|
|
MachineCodeForVMInstr & MInstVec = CallI->getMachineInstrVec();
|
|
MachineCodeForVMInstr::const_iterator MIIt = MInstVec.begin();
|
|
|
|
// find the CALL/JMMPL machine instruction
|
|
for( ; MIIt != MInstVec.end() &&
|
|
! getUltraSparcInfo().getInstrInfo().isCall((*MIIt)->getOpCode());
|
|
++MIIt );
|
|
|
|
assert( (MIIt != MInstVec.end()) && "CALL/JMPL not found");
|
|
|
|
// CallMI = CALL/JMPL machine isntruction
|
|
const MachineInstr *const CallMI = *MIIt;
|
|
|
|
Instruction::op_const_iterator OpIt = CallI->op_begin();
|
|
|
|
unsigned intArgNo=0;
|
|
//unsigned NumOfCallInterfs = LR->getNumOfCallInterferences();
|
|
|
|
// to keep track of which float regs are allocated for argument passing
|
|
bool FloatArgUsedArr[NumOfFloatArgRegs];
|
|
|
|
// init float arg used array
|
|
for(unsigned i=0; i < NumOfFloatArgRegs; ++i)
|
|
FloatArgUsedArr[i] = false;
|
|
|
|
// go thru all the operands of LLVM instruction
|
|
for( ; OpIt != CallI->op_end(); ++OpIt ) {
|
|
|
|
// get the LR of call operand (parameter)
|
|
LiveRange *const LR = LRI.getLiveRangeForValue((const Value *) *OpIt);
|
|
|
|
if ( !LR ) {
|
|
cout << " Warning: In call instr, no LR for arg: " ;
|
|
printValue(*OpIt);
|
|
cout << endl;
|
|
continue;
|
|
}
|
|
|
|
unsigned RegClassID = (LR->getRegClass())->getID();
|
|
|
|
// if the arg is in int class - allocate a reg for an int arg
|
|
if( RegClassID == IntRegClassID ) {
|
|
|
|
if( intArgNo < NumOfIntArgRegs) {
|
|
setCallArgColor( LR, SparcIntRegOrder::o0 + intArgNo );
|
|
}
|
|
|
|
else {
|
|
// TODO: Insert push code here
|
|
assert( 0 && "Insert push code here!");
|
|
}
|
|
++intArgNo;
|
|
}
|
|
|
|
// if the arg is float/double
|
|
else if ( RegClassID == FloatRegClassID) {
|
|
|
|
if( LR->getTypeID() == Type::DoubleTyID ) {
|
|
|
|
// find the first reg # we can pass a double arg
|
|
for(unsigned i=0; i < NumOfFloatArgRegs; i+= 2) {
|
|
if ( !FloatArgUsedArr[i] && !FloatArgUsedArr[i+1] ) {
|
|
setCallArgColor(LR, SparcFloatRegOrder::f0 + i );
|
|
FloatArgUsedArr[i] = true;
|
|
FloatArgUsedArr[i+1] = true;
|
|
//if( DEBUG_RA) printReg( LR );
|
|
break;
|
|
}
|
|
}
|
|
if( ! LR->hasColor() ) { // if LR was not colored above
|
|
|
|
assert(0 && "insert push code here for a double");
|
|
|
|
}
|
|
|
|
}
|
|
else if( LR->getTypeID() == Type::FloatTyID ) {
|
|
|
|
// find the first reg # we can pass a float arg
|
|
for(unsigned i=0; i < NumOfFloatArgRegs; ++i) {
|
|
if ( !FloatArgUsedArr[i] ) {
|
|
setCallArgColor(LR, SparcFloatRegOrder::f0 + i );
|
|
FloatArgUsedArr[i] = true;
|
|
// LR->setColor( SparcFloatRegOrder::f0 + i );
|
|
// if( DEBUG_RA) printReg( LR );
|
|
break;
|
|
}
|
|
}
|
|
if( ! LR->hasColor() ) { // if LR was not colored above
|
|
assert(0 && "insert push code here for a float");
|
|
}
|
|
|
|
}
|
|
else
|
|
assert(0 && "unknown float type in method arg");
|
|
|
|
} // float register class
|
|
|
|
else
|
|
assert(0 && "Unknown RegClassID");
|
|
|
|
|
|
} // for each operand in a call instruction
|
|
|
|
|
|
|
|
|
|
} // for all call instrctions in CallInstrList
|
|
|
|
}
|
|
|
|
|
|
void UltraSparcRegInfo::setCallArgColor(LiveRange *const LR,
|
|
const unsigned RegNo) const {
|
|
|
|
// if no call interference and LR is NOT previously colored (e.g., as an
|
|
// incoming arg)
|
|
if( ! LR->getNumOfCallInterferences() && ! LR->hasColor() ) {
|
|
// we can directly allocate a %o register
|
|
LR->setColor( RegNo);
|
|
if( DEBUG_RA) printReg( LR );
|
|
}
|
|
else { // there are call interferences
|
|
|
|
/*
|
|
// insert a copy machine instr to copy from LR to %o(reg)
|
|
PreMInstrMap[ CallMI ] =
|
|
getNewCopyMInstr( LR->, SparcIntRegOrder::o0 + intArgNo );
|
|
*/
|
|
cout << " $$$ TODO: Insert a copy for call argument!: " << endl;
|
|
|
|
// We don't color LR here. It's colored as any other normal LR
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
// class UltraSparcInstrInfo
|
|
//
|
|
// Purpose:
|
|
// Information about individual instructions.
|
|
// Most information is stored in the SparcMachineInstrDesc array above.
|
|
// Other information is computed on demand, and most such functions
|
|
// default to member functions in base class MachineInstrInfo.
|
|
//---------------------------------------------------------------------------
|
|
|
|
/*ctor*/
|
|
UltraSparcInstrInfo::UltraSparcInstrInfo()
|
|
: MachineInstrInfo(SparcMachineInstrDesc,
|
|
/*descSize = */ NUM_TOTAL_OPCODES,
|
|
/*numRealOpCodes = */ NUM_REAL_OPCODES)
|
|
{
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
// class UltraSparcSchedInfo
|
|
//
|
|
// Purpose:
|
|
// Scheduling information for the UltraSPARC.
|
|
// Primarily just initializes machine-dependent parameters in
|
|
// class MachineSchedInfo.
|
|
//---------------------------------------------------------------------------
|
|
|
|
/*ctor*/
|
|
UltraSparcSchedInfo::UltraSparcSchedInfo(const MachineInstrInfo* mii)
|
|
: MachineSchedInfo((unsigned int) SPARC_NUM_SCHED_CLASSES,
|
|
mii,
|
|
SparcRUsageDesc,
|
|
SparcInstrUsageDeltas,
|
|
SparcInstrIssueDeltas,
|
|
sizeof(SparcInstrUsageDeltas)/sizeof(InstrRUsageDelta),
|
|
sizeof(SparcInstrIssueDeltas)/sizeof(InstrIssueDelta))
|
|
{
|
|
maxNumIssueTotal = 4;
|
|
longestIssueConflict = 0; // computed from issuesGaps[]
|
|
|
|
branchMispredictPenalty = 4; // 4 for SPARC IIi
|
|
branchTargetUnknownPenalty = 2; // 2 for SPARC IIi
|
|
l1DCacheMissPenalty = 8; // 7 or 9 for SPARC IIi
|
|
l1ICacheMissPenalty = 8; // ? for SPARC IIi
|
|
|
|
inOrderLoads = true; // true for SPARC IIi
|
|
inOrderIssue = true; // true for SPARC IIi
|
|
inOrderExec = false; // false for most architectures
|
|
inOrderRetire= true; // true for most architectures
|
|
|
|
// must be called after above parameters are initialized.
|
|
this->initializeResources();
|
|
}
|
|
|
|
void
|
|
UltraSparcSchedInfo::initializeResources()
|
|
{
|
|
// Compute MachineSchedInfo::instrRUsages and MachineSchedInfo::issueGaps
|
|
MachineSchedInfo::initializeResources();
|
|
|
|
// Machine-dependent fixups go here. None for now.
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
// class UltraSparcMachine
|
|
//
|
|
// Purpose:
|
|
// Primary interface to machine description for the UltraSPARC.
|
|
// Primarily just initializes machine-dependent parameters in
|
|
// class TargetMachine, and creates machine-dependent subclasses
|
|
// for classes such as MachineInstrInfo.
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
UltraSparc::UltraSparc()
|
|
|
|
: TargetMachine("UltraSparc-Native")
|
|
{
|
|
machineInstrInfo = new UltraSparcInstrInfo;
|
|
machineSchedInfo = new UltraSparcSchedInfo(machineInstrInfo);
|
|
machineRegInfo = new UltraSparcRegInfo(this);
|
|
|
|
optSizeForSubWordData = 4;
|
|
minMemOpWordSize = 8;
|
|
maxAtomicMemOpWordSize = 8;
|
|
zeroRegNum = 0; // %g0 always gives 0 on Sparc
|
|
}
|
|
|
|
UltraSparc::~UltraSparc()
|
|
{
|
|
delete (UltraSparcInstrInfo*) machineInstrInfo;
|
|
delete (UltraSparcRegInfo*) machineRegInfo;
|
|
delete (UltraSparcSchedInfo*) machineSchedInfo;
|
|
}
|
|
|
|
//**************************************************************************/
|