mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-08-19 19:29:31 +00:00
Bug fixes in casting between floats and ints smaller than 64 bits.
Add UltraSparcInstrInfo::CreateZeroExtensionInstructions to help with that. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@3580 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
babc0fab19
commit
84c0fcbde4
@ -381,8 +381,8 @@ UltraSparcInstrInfo::CreateCodeToLoadConst(const TargetMachine& target,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Create an instruction sequence to copy an integer value `val'
|
// Create an instruction sequence to copy an integer register `val'
|
||||||
// to a floating point value `dest' by copying to memory and back.
|
// to a floating point register `dest' by copying to memory and back.
|
||||||
// val must be an integral type. dest must be a Float or Double.
|
// val must be an integral type. dest must be a Float or Double.
|
||||||
// The generated instructions are returned in `mvec'.
|
// The generated instructions are returned in `mvec'.
|
||||||
// Any temp. registers (TmpInstruction) created are recorded in mcfi.
|
// Any temp. registers (TmpInstruction) created are recorded in mcfi.
|
||||||
@ -396,39 +396,55 @@ UltraSparcInstrInfo::CreateCodeToCopyIntToFloat(const TargetMachine& target,
|
|||||||
vector<MachineInstr*>& mvec,
|
vector<MachineInstr*>& mvec,
|
||||||
MachineCodeForInstruction& mcfi) const
|
MachineCodeForInstruction& mcfi) const
|
||||||
{
|
{
|
||||||
assert((val->getType()->isInteger() || isa<PointerType>(val->getType()))
|
assert((val->getType()->isIntegral() || isa<PointerType>(val->getType()))
|
||||||
&& "Source type must be integer or pointer");
|
&& "Source type must be integral (integer or bool) or pointer");
|
||||||
assert(dest->getType()->isFloatingPoint()
|
assert(dest->getType()->isFloatingPoint()
|
||||||
&& "Dest type must be float/double");
|
&& "Dest type must be float/double");
|
||||||
|
|
||||||
|
// Get a stack slot to use for the copy
|
||||||
int offset = MachineCodeForMethod::get(F).allocateLocalVar(target, val);
|
int offset = MachineCodeForMethod::get(F).allocateLocalVar(target, val);
|
||||||
|
|
||||||
|
// Get the size of the source value being copied.
|
||||||
|
size_t srcSize = target.DataLayout.getTypeSize(val->getType());
|
||||||
|
|
||||||
// Store instruction stores `val' to [%fp+offset].
|
// Store instruction stores `val' to [%fp+offset].
|
||||||
// The store and load opCodes are based on the value being copied, and
|
// The store and load opCodes are based on the size of the source value.
|
||||||
// they use integer and float types that accomodate the
|
// If the value is smaller than 32 bits, we must sign- or zero-extend it
|
||||||
// larger of the source type and the destination type:
|
// to 32 bits since the load-float will load 32 bits.
|
||||||
// On SparcV9: int for float, long for double.
|
|
||||||
// Note that the store instruction is the same for signed and unsigned ints.
|
// Note that the store instruction is the same for signed and unsigned ints.
|
||||||
Type* tmpType = (dest->getType() == Type::FloatTy)? Type::IntTy
|
const Type* storeType = (srcSize <= 4)? Type::IntTy : Type::LongTy;
|
||||||
: Type::LongTy;
|
Value* storeVal = val;
|
||||||
MachineInstr* store = new MachineInstr(ChooseStoreInstruction(tmpType));
|
if (srcSize < target.DataLayout.getTypeSize(Type::FloatTy))
|
||||||
store->SetMachineOperandVal(0, MachineOperand::MO_VirtualRegister, val);
|
{ // sign- or zero-extend respectively
|
||||||
|
storeVal = new TmpInstruction(storeType, val);
|
||||||
|
if (val->getType()->isSigned())
|
||||||
|
CreateSignExtensionInstructions(target, F, val, 8*srcSize, storeVal,
|
||||||
|
mvec, mcfi);
|
||||||
|
else
|
||||||
|
CreateZeroExtensionInstructions(target, F, val, 8*srcSize, storeVal,
|
||||||
|
mvec, mcfi);
|
||||||
|
}
|
||||||
|
MachineInstr* store=new MachineInstr(ChooseStoreInstruction(storeType));
|
||||||
|
store->SetMachineOperandVal(0, MachineOperand::MO_VirtualRegister, storeVal);
|
||||||
store->SetMachineOperandReg(1, target.getRegInfo().getFramePointer());
|
store->SetMachineOperandReg(1, target.getRegInfo().getFramePointer());
|
||||||
store->SetMachineOperandConst(2,MachineOperand::MO_SignExtendedImmed,offset);
|
store->SetMachineOperandConst(2,MachineOperand::MO_SignExtendedImmed,offset);
|
||||||
mvec.push_back(store);
|
mvec.push_back(store);
|
||||||
|
|
||||||
// Load instruction loads [%fp+offset] to `dest'.
|
// Load instruction loads [%fp+offset] to `dest'.
|
||||||
|
// The type of the load opCode is the floating point type that matches the
|
||||||
|
// stored type in size:
|
||||||
|
// On SparcV9: float for int or smaller, double for long.
|
||||||
//
|
//
|
||||||
MachineInstr* load =new MachineInstr(ChooseLoadInstruction(dest->getType()));
|
const Type* loadType = (srcSize <= 4)? Type::FloatTy : Type::DoubleTy;
|
||||||
|
MachineInstr* load = new MachineInstr(ChooseLoadInstruction(loadType));
|
||||||
load->SetMachineOperandReg(0, target.getRegInfo().getFramePointer());
|
load->SetMachineOperandReg(0, target.getRegInfo().getFramePointer());
|
||||||
load->SetMachineOperandConst(1, MachineOperand::MO_SignExtendedImmed,offset);
|
load->SetMachineOperandConst(1, MachineOperand::MO_SignExtendedImmed,offset);
|
||||||
load->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister, dest);
|
load->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister, dest);
|
||||||
mvec.push_back(load);
|
mvec.push_back(load);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Similarly, create an instruction sequence to copy an FP register
|
||||||
// Similarly, create an instruction sequence to copy an FP value
|
// `val' to an integer register `dest' by copying to memory and back.
|
||||||
// `val' to an integer value `dest' by copying to memory and back.
|
|
||||||
// The generated instructions are returned in `mvec'.
|
// The generated instructions are returned in `mvec'.
|
||||||
// Any temp. registers (TmpInstruction) created are recorded in mcfi.
|
// Any temp. registers (TmpInstruction) created are recorded in mcfi.
|
||||||
// Any stack space required is allocated via MachineCodeForMethod.
|
// Any stack space required is allocated via MachineCodeForMethod.
|
||||||
@ -443,30 +459,30 @@ UltraSparcInstrInfo::CreateCodeToCopyFloatToInt(const TargetMachine& target,
|
|||||||
{
|
{
|
||||||
const Type* opTy = val->getType();
|
const Type* opTy = val->getType();
|
||||||
const Type* destTy = dest->getType();
|
const Type* destTy = dest->getType();
|
||||||
|
|
||||||
assert(opTy->isFloatingPoint() && "Source type must be float/double");
|
assert(opTy->isFloatingPoint() && "Source type must be float/double");
|
||||||
assert((destTy->isInteger() || isa<PointerType>(destTy))
|
assert((destTy->isIntegral() || isa<PointerType>(destTy))
|
||||||
&& "Dest type must be integer or pointer");
|
&& "Dest type must be integer, bool or pointer");
|
||||||
|
|
||||||
int offset = MachineCodeForMethod::get(F).allocateLocalVar(target, val);
|
int offset = MachineCodeForMethod::get(F).allocateLocalVar(target, val);
|
||||||
|
|
||||||
// Store instruction stores `val' to [%fp+offset].
|
// Store instruction stores `val' to [%fp+offset].
|
||||||
// The store opCode is based only the source value being copied.
|
// The store opCode is based only the source value being copied.
|
||||||
//
|
//
|
||||||
MachineInstr* store=new MachineInstr(ChooseStoreInstruction(val->getType()));
|
MachineInstr* store=new MachineInstr(ChooseStoreInstruction(opTy));
|
||||||
store->SetMachineOperandVal(0, MachineOperand::MO_VirtualRegister, val);
|
store->SetMachineOperandVal(0, MachineOperand::MO_VirtualRegister, val);
|
||||||
store->SetMachineOperandReg(1, target.getRegInfo().getFramePointer());
|
store->SetMachineOperandReg(1, target.getRegInfo().getFramePointer());
|
||||||
store->SetMachineOperandConst(2,MachineOperand::MO_SignExtendedImmed,offset);
|
store->SetMachineOperandConst(2,MachineOperand::MO_SignExtendedImmed,offset);
|
||||||
mvec.push_back(store);
|
mvec.push_back(store);
|
||||||
|
|
||||||
// Load instruction loads [%fp+offset] to `dest'.
|
// Load instruction loads [%fp+offset] to `dest'.
|
||||||
// The type of the load opCode is the integer type that matches the
|
// The type of the load opCode is the integer type that matches the
|
||||||
// source type in size: (and the dest type in sign):
|
// source type in size:
|
||||||
// On SparcV9: int for float, long for double.
|
// On SparcV9: int for float, long for double.
|
||||||
// Note that we *must* use signed loads even for unsigned dest types, to
|
// Note that we *must* use signed loads even for unsigned dest types, to
|
||||||
// ensure that we get the right sign-extension for smaller-than-64-bit
|
// ensure correct sign-extension for UByte, UShort or UInt:
|
||||||
// unsigned dest. types (i.e., UByte, UShort or UInt):
|
//
|
||||||
const Type* loadTy = opTy == Type::FloatTy? Type::IntTy : Type::LongTy;
|
const Type* loadTy = (opTy == Type::FloatTy)? Type::IntTy : Type::LongTy;
|
||||||
MachineInstr* load = new MachineInstr(ChooseLoadInstruction(loadTy));
|
MachineInstr* load = new MachineInstr(ChooseLoadInstruction(loadTy));
|
||||||
load->SetMachineOperandReg(0, target.getRegInfo().getFramePointer());
|
load->SetMachineOperandReg(0, target.getRegInfo().getFramePointer());
|
||||||
load->SetMachineOperandConst(1, MachineOperand::MO_SignExtendedImmed,offset);
|
load->SetMachineOperandConst(1, MachineOperand::MO_SignExtendedImmed,offset);
|
||||||
@ -538,9 +554,40 @@ UltraSparcInstrInfo::CreateCopyInstructionsByType(const TargetMachine& target,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Helper function for sign-extension and zero-extension.
|
||||||
|
// For SPARC v9, we sign-extend the given operand using SLL; SRA/SRL.
|
||||||
|
inline void
|
||||||
|
CreateBitExtensionInstructions(bool signExtend,
|
||||||
|
const TargetMachine& target,
|
||||||
|
Function* F,
|
||||||
|
Value* srcVal,
|
||||||
|
unsigned int srcSizeInBits,
|
||||||
|
Value* dest,
|
||||||
|
vector<MachineInstr*>& mvec,
|
||||||
|
MachineCodeForInstruction& mcfi)
|
||||||
|
{
|
||||||
|
MachineInstr* M;
|
||||||
|
assert(srcSizeInBits <= 32 &&
|
||||||
|
"Hmmm... 32 < srcSizeInBits < 64 unexpected but could be handled.");
|
||||||
|
|
||||||
|
if (srcSizeInBits < 32)
|
||||||
|
{ // SLL is needed since operand size is < 32 bits.
|
||||||
|
TmpInstruction *tmpI = new TmpInstruction(dest->getType(),
|
||||||
|
srcVal, dest,"make32");
|
||||||
|
mcfi.addTemp(tmpI);
|
||||||
|
M = Create3OperandInstr_UImmed(SLLX, srcVal, 32-srcSizeInBits, tmpI);
|
||||||
|
mvec.push_back(M);
|
||||||
|
srcVal = tmpI;
|
||||||
|
}
|
||||||
|
|
||||||
|
M = Create3OperandInstr_UImmed(signExtend? SRA : SRL,
|
||||||
|
srcVal, 32-srcSizeInBits, dest);
|
||||||
|
mvec.push_back(M);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Create instruction sequence to produce a sign-extended register value
|
// Create instruction sequence to produce a sign-extended register value
|
||||||
// from an arbitrary sized value (sized in bits, not bytes).
|
// from an arbitrary-sized integer value (sized in bits, not bytes).
|
||||||
// For SPARC v9, we sign-extend the given unsigned operand using SLL; SRA.
|
|
||||||
// The generated instructions are returned in `mvec'.
|
// The generated instructions are returned in `mvec'.
|
||||||
// Any temp. registers (TmpInstruction) created are recorded in mcfi.
|
// Any temp. registers (TmpInstruction) created are recorded in mcfi.
|
||||||
// Any stack space required is allocated via MachineCodeForMethod.
|
// Any stack space required is allocated via MachineCodeForMethod.
|
||||||
@ -549,27 +596,34 @@ void
|
|||||||
UltraSparcInstrInfo::CreateSignExtensionInstructions(
|
UltraSparcInstrInfo::CreateSignExtensionInstructions(
|
||||||
const TargetMachine& target,
|
const TargetMachine& target,
|
||||||
Function* F,
|
Function* F,
|
||||||
Value* unsignedSrcVal,
|
Value* srcVal,
|
||||||
unsigned int srcSizeInBits,
|
unsigned int srcSizeInBits,
|
||||||
Value* dest,
|
Value* dest,
|
||||||
vector<MachineInstr*>& mvec,
|
vector<MachineInstr*>& mvec,
|
||||||
MachineCodeForInstruction& mcfi) const
|
MachineCodeForInstruction& mcfi) const
|
||||||
{
|
{
|
||||||
MachineInstr* M;
|
CreateBitExtensionInstructions(/*signExtend*/ true, target, F, srcVal,
|
||||||
assert(srcSizeInBits < 64 && "Sign extension unnecessary!");
|
srcSizeInBits, dest, mvec, mcfi);
|
||||||
assert(srcSizeInBits > 0 && srcSizeInBits <= 32
|
}
|
||||||
&& "Hmmm... 32 < srcSizeInBits < 64 unexpected but could be handled here.");
|
|
||||||
|
|
||||||
if (srcSizeInBits < 32)
|
// Create instruction sequence to produce a zero-extended register value
|
||||||
{ // SLL is needed since operand size is < 32 bits.
|
// from an arbitrary-sized integer value (sized in bits, not bytes).
|
||||||
TmpInstruction *tmpI = new TmpInstruction(dest->getType(),
|
// For SPARC v9, we sign-extend the given operand using SLL; SRL.
|
||||||
unsignedSrcVal, dest,"make32");
|
// The generated instructions are returned in `mvec'.
|
||||||
mcfi.addTemp(tmpI);
|
// Any temp. registers (TmpInstruction) created are recorded in mcfi.
|
||||||
M = Create3OperandInstr_UImmed(SLL,unsignedSrcVal,32-srcSizeInBits,tmpI);
|
// Any stack space required is allocated via MachineCodeForMethod.
|
||||||
mvec.push_back(M);
|
//
|
||||||
unsignedSrcVal = tmpI;
|
void
|
||||||
}
|
UltraSparcInstrInfo::CreateZeroExtensionInstructions(
|
||||||
|
const TargetMachine& target,
|
||||||
M = Create3OperandInstr_UImmed(SRA, unsignedSrcVal, 32-srcSizeInBits, dest);
|
Function* F,
|
||||||
mvec.push_back(M);
|
Value* srcVal,
|
||||||
|
unsigned int srcSizeInBits,
|
||||||
|
Value* dest,
|
||||||
|
vector<MachineInstr*>& mvec,
|
||||||
|
MachineCodeForInstruction& mcfi) const
|
||||||
|
{
|
||||||
|
CreateBitExtensionInstructions(/*signExtend*/ false, target, F, srcVal,
|
||||||
|
srcSizeInBits, dest, mvec, mcfi);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user