llvm-6502/lib/Target/SparcV9/SparcV9InstrInfo.cpp
Chris Lattner 2fbfdcffd3 Change references to the Method class to be references to the Function
class.  The Method class is obsolete (renamed) and all references to it
are being converted over to Function.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@2144 91177308-0d34-0410-b5e6-96231b3b80d8
2002-04-07 20:49:59 +00:00

312 lines
12 KiB
C++

// $Id$
//***************************************************************************
// File:
// SparcInstrInfo.cpp
//
// Purpose:
//
// History:
// 10/15/01 - Vikram Adve - Created
//**************************************************************************/
#include "SparcInternals.h"
#include "SparcInstrSelectionSupport.h"
#include "llvm/Target/Sparc.h"
#include "llvm/CodeGen/InstrSelection.h"
#include "llvm/CodeGen/InstrSelectionSupport.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineCodeForMethod.h"
#include "llvm/Function.h"
#include "llvm/ConstantVals.h"
#include "llvm/DerivedTypes.h"
//************************ Internal Functions ******************************/
static inline MachineInstr*
CreateIntSetInstruction(int64_t C, Value* dest,
std::vector<TmpInstruction*>& tempVec)
{
MachineInstr* minstr;
uint64_t absC = (C >= 0)? C : -C;
if (absC > (unsigned int) ~0)
{ // C does not fit in 32 bits
TmpInstruction* tmpReg = new TmpInstruction(Type::IntTy);
tempVec.push_back(tmpReg);
minstr = new MachineInstr(SETX);
minstr->SetMachineOperandConst(0, MachineOperand::MO_SignExtendedImmed, C);
minstr->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister, tmpReg,
/*isdef*/ true);
minstr->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister,dest);
}
else
{
minstr = new MachineInstr(SETSW);
minstr->SetMachineOperandConst(0,MachineOperand::MO_SignExtendedImmed,C);
minstr->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister,dest);
}
return minstr;
}
static inline MachineInstr*
CreateUIntSetInstruction(uint64_t C, Value* dest,
std::vector<TmpInstruction*>& tempVec)
{
MachineInstr* minstr;
if (C > (unsigned int) ~0)
{ // C does not fit in 32 bits
assert(dest->getType() == Type::ULongTy && "Sign extension problems");
TmpInstruction *tmpReg = new TmpInstruction(Type::IntTy);
tempVec.push_back(tmpReg);
minstr = new MachineInstr(SETX);
minstr->SetMachineOperandConst(0,MachineOperand::MO_SignExtendedImmed,C);
minstr->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister,
tmpReg, /*isdef*/ true);
minstr->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister,dest);
}
else if (dest->getType() == Type::ULongTy)
{
minstr = new MachineInstr(SETUW);
minstr->SetMachineOperandConst(0, MachineOperand::MO_UnextendedImmed, C);
minstr->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister,dest);
}
else
{ // cast to signed type of the right length and use signed op (SETSW)
// to get correct sign extension
//
minstr = new MachineInstr(SETSW);
minstr->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister,dest);
switch (dest->getType()->getPrimitiveID())
{
case Type::UIntTyID:
minstr->SetMachineOperandConst(0,
MachineOperand::MO_SignExtendedImmed,
(int) C);
break;
case Type::UShortTyID:
minstr->SetMachineOperandConst(0,
MachineOperand::MO_SignExtendedImmed,
(short) C);
break;
case Type::UByteTyID:
minstr->SetMachineOperandConst(0,
MachineOperand::MO_SignExtendedImmed,
(char) C);
break;
default:
assert(0 && "Unexpected unsigned type");
break;
}
}
return minstr;
}
//************************* External Classes *******************************/
//---------------------------------------------------------------------------
// 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(const TargetMachine& tgt)
: MachineInstrInfo(tgt, SparcMachineInstrDesc,
/*descSize = */ NUM_TOTAL_OPCODES,
/*numRealOpCodes = */ NUM_REAL_OPCODES)
{
}
//
// Create an instruction sequence to put the constant `val' into
// the virtual register `dest'. `val' may be a Constant or a
// GlobalValue, viz., the constant address of a global variable or function.
// The generated instructions are returned in `minstrVec'.
// Any temp. registers (TmpInstruction) created are returned in `tempVec'.
//
void
UltraSparcInstrInfo::CreateCodeToLoadConst(Function *F, Value* val,
Instruction* dest,
std::vector<MachineInstr*>&minstrVec,
std::vector<TmpInstruction*>& tempVec) const
{
MachineInstr* minstr;
assert(isa<Constant>(val) || isa<GlobalValue>(val) &&
"I only know about constant values and global addresses");
// Use a "set" instruction for known constants that can go in an integer reg.
// Use a "load" instruction for all other constants, in particular,
// floating point constants and addresses of globals.
//
const Type* valType = val->getType();
if (valType->isIntegral() || valType == Type::BoolTy)
{
if (ConstantUInt* uval = dyn_cast<ConstantUInt>(val))
{
uint64_t C = uval->getValue();
minstr = CreateUIntSetInstruction(C, dest, tempVec);
}
else
{
bool isValidConstant;
int64_t C = GetConstantValueAsSignedInt(val, isValidConstant);
assert(isValidConstant && "Unrecognized constant");
minstr = CreateIntSetInstruction(C, dest, tempVec);
}
minstrVec.push_back(minstr);
}
else
{
// Make an instruction sequence to load the constant, viz:
// SETX <addr-of-constant>, tmpReg, addrReg
// LOAD /*addr*/ addrReg, /*offset*/ 0, dest
// Only the SETX is needed if `val' is a GlobalValue, i.e,. it is
// itself a constant address. Otherwise, both are needed.
Value* addrVal;
int64_t zeroOffset = 0; // to avoid ambiguity with (Value*) 0
TmpInstruction* tmpReg =
new TmpInstruction(PointerType::get(val->getType()), val);
tempVec.push_back(tmpReg);
if (isa<Constant>(val))
{
// Create another TmpInstruction for the hidden integer register
TmpInstruction* addrReg =
new TmpInstruction(PointerType::get(val->getType()), val);
tempVec.push_back(addrReg);
addrVal = addrReg;
}
else
addrVal = dest;
minstr = new MachineInstr(SETX);
minstr->SetMachineOperandVal(0, MachineOperand::MO_PCRelativeDisp, val);
minstr->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister,tmpReg,
/*isdef*/ true);
minstr->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister,
addrVal);
minstrVec.push_back(minstr);
if (isa<Constant>(val))
{
// Make sure constant is emitted to constant pool in assembly code.
MachineCodeForMethod& mcinfo = MachineCodeForMethod::get(F);
mcinfo.addToConstantPool(cast<Constant>(val));
// Generate the load instruction
minstr = new MachineInstr(ChooseLoadInstruction(val->getType()));
minstr->SetMachineOperandVal(0, MachineOperand::MO_VirtualRegister,
addrVal);
minstr->SetMachineOperandConst(1,MachineOperand::MO_SignExtendedImmed,
zeroOffset);
minstr->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister,
dest);
minstrVec.push_back(minstr);
}
}
}
// Create an instruction sequence to copy an integer value `val'
// to a floating point value `dest' by copying to memory and back.
// val must be an integral type. dest must be a Float or Double.
// The generated instructions are returned in `minstrVec'.
// Any temp. registers (TmpInstruction) created are returned in `tempVec'.
//
void
UltraSparcInstrInfo::CreateCodeToCopyIntToFloat(Function *F,
Value* val,
Instruction* dest,
std::vector<MachineInstr*>& minstrVec,
std::vector<TmpInstruction*>& tempVec,
TargetMachine& target) const
{
assert((val->getType()->isIntegral() || val->getType()->isPointerType())
&& "Source type must be integral");
assert((dest->getType() == Type::FloatTy || dest->getType() == Type::DoubleTy)
&& "Dest type must be float/double");
MachineCodeForMethod& mcinfo = MachineCodeForMethod::get(F);
int offset = mcinfo.allocateLocalVar(target, val);
// Store instruction stores `val' to [%fp+offset].
// The store and load opCodes are based on the value being copied, and
// they use integer and float types that accomodate the
// larger of the source type and the destination type:
// On SparcV9: int for float, long for double.
//
Type* tmpType = (dest->getType() == Type::FloatTy)? Type::IntTy
: Type::LongTy;
MachineInstr* store = new MachineInstr(ChooseStoreInstruction(tmpType));
store->SetMachineOperandVal(0, MachineOperand::MO_VirtualRegister, val);
store->SetMachineOperandReg(1, target.getRegInfo().getFramePointer());
store->SetMachineOperandConst(2,MachineOperand::MO_SignExtendedImmed, offset);
minstrVec.push_back(store);
// Load instruction loads [%fp+offset] to `dest'.
//
MachineInstr* load =new MachineInstr(ChooseLoadInstruction(dest->getType()));
load->SetMachineOperandReg(0, target.getRegInfo().getFramePointer());
load->SetMachineOperandConst(1, MachineOperand::MO_SignExtendedImmed,offset);
load->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister, dest);
minstrVec.push_back(load);
}
// Similarly, create an instruction sequence to copy an FP value
// `val' to an integer value `dest' by copying to memory and back.
// See the previous function for information about return values.
//
void
UltraSparcInstrInfo::CreateCodeToCopyFloatToInt(Function *F,
Value* val,
Instruction* dest,
std::vector<MachineInstr*>& minstrVec,
std::vector<TmpInstruction*>& tempVec,
TargetMachine& target) const
{
assert((val->getType() ==Type::FloatTy || val->getType() ==Type::DoubleTy)
&& "Source type must be float/double");
assert((dest->getType()->isIntegral() || dest->getType()->isPointerType())
&& "Dest type must be integral");
MachineCodeForMethod& mcinfo = MachineCodeForMethod::get(F);
int offset = mcinfo.allocateLocalVar(target, val);
// Store instruction stores `val' to [%fp+offset].
// The store and load opCodes are based on the value being copied, and
// they use the integer type that matches the source type in size:
// On SparcV9: int for float, long for double.
//
Type* tmpType = (val->getType() == Type::FloatTy)? Type::IntTy
: Type::LongTy;
MachineInstr* store=new MachineInstr(ChooseStoreInstruction(val->getType()));
store->SetMachineOperandVal(0, MachineOperand::MO_VirtualRegister, val);
store->SetMachineOperandReg(1, target.getRegInfo().getFramePointer());
store->SetMachineOperandConst(2,MachineOperand::MO_SignExtendedImmed,offset);
minstrVec.push_back(store);
// Load instruction loads [%fp+offset] to `dest'.
//
MachineInstr* load = new MachineInstr(ChooseLoadInstruction(tmpType));
load->SetMachineOperandReg(0, target.getRegInfo().getFramePointer());
load->SetMachineOperandConst(1, MachineOperand::MO_SignExtendedImmed, offset);
load->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister, dest);
minstrVec.push_back(load);
}