+ // Make sure constant is emitted to constant pool in assembly code.
+ MachineFunction::get(F).addToConstantPool(cast<Constant>(val));
+ }
+}
+
+
+// Create an instruction sequence to copy an integer register `val'
+// 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.
+// The generated instructions are returned in `mvec'.
+// Any temp. registers (TmpInstruction) created are recorded in mcfi.
+// Any stack space required is allocated via MachineFunction.
+//
+void
+UltraSparcInstrInfo::CreateCodeToCopyIntToFloat(const TargetMachine& target,
+ Function* F,
+ Value* val,
+ Instruction* dest,
+ vector<MachineInstr*>& mvec,
+ MachineCodeForInstruction& mcfi) const
+{
+ assert((val->getType()->isIntegral() || isa<PointerType>(val->getType()))
+ && "Source type must be integral (integer or bool) or pointer");
+ assert(dest->getType()->isFloatingPoint()
+ && "Dest type must be float/double");
+
+ // Get a stack slot to use for the copy
+ int offset = MachineFunction::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].
+ // The store and load opCodes are based on the size of the source value.
+ // If the value is smaller than 32 bits, we must sign- or zero-extend it
+ // to 32 bits since the load-float will load 32 bits.
+ // Note that the store instruction is the same for signed and unsigned ints.
+ const Type* storeType = (srcSize <= 4)? Type::IntTy : Type::LongTy;
+ Value* storeVal = val;
+ if (srcSize < target.DataLayout.getTypeSize(Type::FloatTy))
+ { // sign- or zero-extend respectively
+ storeVal = new TmpInstruction(storeType, val);
+ if (val->getType()->isSigned())
+ CreateSignExtensionInstructions(target, F, val, storeVal, 8*srcSize,
+ mvec, mcfi);
+ else
+ CreateZeroExtensionInstructions(target, F, val, storeVal, 8*srcSize,
+ mvec, mcfi);
+ }
+ MachineInstr* store=new MachineInstr(ChooseStoreInstruction(storeType));
+ store->SetMachineOperandVal(0, MachineOperand::MO_VirtualRegister, storeVal);
+ store->SetMachineOperandReg(1, target.getRegInfo().getFramePointer());
+ store->SetMachineOperandConst(2,MachineOperand::MO_SignExtendedImmed,offset);
+ mvec.push_back(store);
+
+ // 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.
+ //
+ const Type* loadType = (srcSize <= 4)? Type::FloatTy : Type::DoubleTy;
+ MachineInstr* load = new MachineInstr(ChooseLoadInstruction(loadType));
+ load->SetMachineOperandReg(0, target.getRegInfo().getFramePointer());
+ load->SetMachineOperandConst(1, MachineOperand::MO_SignExtendedImmed,offset);
+ load->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister, dest);
+ mvec.push_back(load);
+}
+
+// Similarly, create an instruction sequence to copy an FP register
+// `val' to an integer register `dest' by copying to memory and back.
+// The generated instructions are returned in `mvec'.
+// Any temp. registers (TmpInstruction) created are recorded in mcfi.
+// Any stack space required is allocated via MachineFunction.
+//
+void
+UltraSparcInstrInfo::CreateCodeToCopyFloatToInt(const TargetMachine& target,
+ Function* F,
+ Value* val,
+ Instruction* dest,
+ vector<MachineInstr*>& mvec,
+ MachineCodeForInstruction& mcfi) const
+{
+ const Type* opTy = val->getType();
+ const Type* destTy = dest->getType();
+
+ assert(opTy->isFloatingPoint() && "Source type must be float/double");
+ assert((destTy->isIntegral() || isa<PointerType>(destTy))
+ && "Dest type must be integer, bool or pointer");
+
+ int offset = MachineFunction::get(F).allocateLocalVar(target, val);
+
+ // Store instruction stores `val' to [%fp+offset].
+ // The store opCode is based only the source value being copied.
+ //
+ MachineInstr* store=new MachineInstr(ChooseStoreInstruction(opTy));
+ store->SetMachineOperandVal(0, MachineOperand::MO_VirtualRegister, val);
+ store->SetMachineOperandReg(1, target.getRegInfo().getFramePointer());
+ store->SetMachineOperandConst(2,MachineOperand::MO_SignExtendedImmed,offset);
+ mvec.push_back(store);
+
+ // Load instruction loads [%fp+offset] to `dest'.
+ // The type of the load opCode is the integer type that matches the
+ // source type in size:
+ // On SparcV9: int for float, long for double.
+ // Note that we *must* use signed loads even for unsigned dest types, to
+ // ensure correct sign-extension for UByte, UShort or UInt:
+ //
+ const Type* loadTy = (opTy == Type::FloatTy)? Type::IntTy : Type::LongTy;
+ MachineInstr* load = new MachineInstr(ChooseLoadInstruction(loadTy));
+ load->SetMachineOperandReg(0, target.getRegInfo().getFramePointer());
+ load->SetMachineOperandConst(1, MachineOperand::MO_SignExtendedImmed,offset);
+ load->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister, dest);
+ mvec.push_back(load);
+}
+
+
+// Create instruction(s) to copy src to dest, for arbitrary types
+// The generated instructions are returned in `mvec'.
+// Any temp. registers (TmpInstruction) created are recorded in mcfi.
+// Any stack space required is allocated via MachineFunction.
+//
+void
+UltraSparcInstrInfo::CreateCopyInstructionsByType(const TargetMachine& target,
+ Function *F,
+ Value* src,
+ Instruction* dest,
+ vector<MachineInstr*>& mvec,
+ MachineCodeForInstruction& mcfi) const
+{
+ bool loadConstantToReg = false;
+
+ const Type* resultType = dest->getType();
+
+ MachineOpCode opCode = ChooseAddInstructionByType(resultType);
+ if (opCode == INVALID_OPCODE)
+ {
+ assert(0 && "Unsupported result type in CreateCopyInstructionsByType()");
+ return;
+ }
+
+ // if `src' is a constant that doesn't fit in the immed field or if it is
+ // a global variable (i.e., a constant address), generate a load
+ // instruction instead of an add
+ //
+ if (isa<Constant>(src))
+ {
+ unsigned int machineRegNum;
+ int64_t immedValue;
+ MachineOperand::MachineOperandType opType =
+ ChooseRegOrImmed(src, opCode, target, /*canUseImmed*/ true,
+ machineRegNum, immedValue);
+
+ if (opType == MachineOperand::MO_VirtualRegister)
+ loadConstantToReg = true;
+ }
+ else if (isa<GlobalValue>(src))
+ loadConstantToReg = true;
+
+ if (loadConstantToReg)
+ { // `src' is constant and cannot fit in immed field for the ADD
+ // Insert instructions to "load" the constant into a register
+ target.getInstrInfo().CreateCodeToLoadConst(target, F, src, dest,
+ mvec, mcfi);
+ }
+ else
+ { // Create an add-with-0 instruction of the appropriate type.
+ // Make `src' the second operand, in case it is a constant
+ // Use (unsigned long) 0 for a NULL pointer value.
+ //
+ const Type* zeroValueType =
+ isa<PointerType>(resultType) ? Type::ULongTy : resultType;
+ MachineInstr* minstr =
+ Create3OperandInstr(opCode, Constant::getNullValue(zeroValueType),
+ src, dest);
+ mvec.push_back(minstr);