+ 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);
+ }
+}
+
+
+// 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,
+ Value* destVal,
+ unsigned int numLowBits,
+ vector<MachineInstr*>& mvec,
+ MachineCodeForInstruction& mcfi)
+{
+ MachineInstr* M;
+
+ assert(numLowBits <= 32 && "Otherwise, nothing should be done here!");
+
+ if (numLowBits < 32)
+ { // SLL is needed since operand size is < 32 bits.
+ TmpInstruction *tmpI = new TmpInstruction(destVal->getType(),
+ srcVal, destVal, "make32");
+ mcfi.addTemp(tmpI);
+ M = Create3OperandInstr_UImmed(SLLX, srcVal, 32-numLowBits, tmpI);
+ mvec.push_back(M);
+ srcVal = tmpI;
+ }
+
+ M = Create3OperandInstr_UImmed(signExtend? SRA : SRL,
+ srcVal, 32-numLowBits, destVal);
+ mvec.push_back(M);
+}
+
+
+// Create instruction sequence to produce a sign-extended register value
+// from an arbitrary-sized integer value (sized in bits, not bytes).
+// 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::CreateSignExtensionInstructions(
+ const TargetMachine& target,
+ Function* F,
+ Value* srcVal,
+ Value* destVal,
+ unsigned int numLowBits,
+ vector<MachineInstr*>& mvec,
+ MachineCodeForInstruction& mcfi) const
+{
+ CreateBitExtensionInstructions(/*signExtend*/ true, target, F, srcVal,
+ destVal, numLowBits, mvec, mcfi);
+}
+
+
+// Create instruction sequence to produce a zero-extended register value
+// from an arbitrary-sized integer value (sized in bits, not bytes).
+// For SPARC v9, we sign-extend the given operand using SLL; SRL.
+// 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::CreateZeroExtensionInstructions(
+ const TargetMachine& target,
+ Function* F,
+ Value* srcVal,
+ Value* destVal,
+ unsigned int numLowBits,
+ vector<MachineInstr*>& mvec,
+ MachineCodeForInstruction& mcfi) const
+{
+ CreateBitExtensionInstructions(/*signExtend*/ false, target, F, srcVal,
+ destVal, numLowBits, mvec, mcfi);
+}