2 //***************************************************************************
9 // 10/15/01 - Vikram Adve - Created
10 //**************************************************************************/
13 #include "SparcInternals.h"
14 #include "SparcInstrSelectionSupport.h"
15 #include "llvm/Target/Sparc.h"
16 #include "llvm/CodeGen/InstrSelection.h"
17 #include "llvm/CodeGen/InstrSelectionSupport.h"
18 #include "llvm/CodeGen/MachineCodeForMethod.h"
19 #include "llvm/CodeGen/MachineCodeForInstruction.h"
20 #include "llvm/Function.h"
21 #include "llvm/BasicBlock.h"
22 #include "llvm/Instruction.h"
23 #include "llvm/Constants.h"
24 #include "llvm/DerivedTypes.h"
27 //************************ Internal Functions ******************************/
31 CreateIntSetInstruction(const TargetMachine& target, Function* F,
32 int64_t C, Instruction* dest,
33 std::vector<MachineInstr*>& mvec,
34 MachineCodeForInstruction& mcfi)
36 assert(dest->getType()->isSigned() && "Use CreateUIntSetInstruction()");
39 uint64_t absC = (C >= 0)? C : -C;
40 if (absC > (unsigned int) ~0)
41 { // C does not fit in 32 bits
42 TmpInstruction* tmpReg = new TmpInstruction(Type::IntTy);
45 M = new MachineInstr(SETX);
46 M->SetMachineOperandConst(0,MachineOperand::MO_SignExtendedImmed,C);
47 M->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister, tmpReg,
49 M->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister,dest);
54 M = Create2OperandInstr_SImmed(SETSW, C, dest);
60 CreateUIntSetInstruction(const TargetMachine& target, Function* F,
61 uint64_t C, Instruction* dest,
62 std::vector<MachineInstr*>& mvec,
63 MachineCodeForInstruction& mcfi)
65 assert(! dest->getType()->isSigned() && "Use CreateIntSetInstruction()");
66 unsigned destSize = target.DataLayout.getTypeSize(dest->getType());
69 if (C > (unsigned int) ~0)
70 { // C does not fit in 32 bits
71 assert(dest->getType() == Type::ULongTy && "Sign extension problems");
72 TmpInstruction *tmpReg = new TmpInstruction(Type::IntTy);
75 M = new MachineInstr(SETX);
76 M->SetMachineOperandConst(0, MachineOperand::MO_UnextendedImmed, C);
77 M->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister, tmpReg,
79 M->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister, dest);
84 // If the destination is smaller than the standard integer reg. size,
85 // we have to extend the sign-bit into upper bits of dest, so we
86 // need to put the result of the SETUW into a temporary.
88 Value* setuwDest = dest;
89 if (destSize < target.DataLayout.getIntegerRegize())
91 setuwDest = new TmpInstruction(dest, NULL, "setTmp");
92 mcfi.addTemp(setuwDest);
95 M = Create2OperandInstr_UImmed(SETUW, C, setuwDest);
98 if (setuwDest != dest)
99 { // extend the sign-bit of the result into all upper bits of dest
100 assert(8*destSize <= 32 &&
101 "Unexpected type size > 4 and < IntRegSize?");
102 target.getInstrInfo().
103 CreateSignExtensionInstructions(target, F,
104 setuwDest, 8*destSize, dest,
109 #define USE_DIRECT_SIGN_EXTENSION_INSTRS
110 #ifndef USE_DIRECT_SIGN_EXTENSION_INSTRS
112 { // cast to signed type of the right length and use signed op (SETSW)
113 // to get correct sign extension
115 minstr = new MachineInstr(SETSW);
116 minstr->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister,dest);
118 switch (dest->getType()->getPrimitiveID())
121 minstr->SetMachineOperandConst(0,
122 MachineOperand::MO_SignExtendedImmed,
125 case Type::UShortTyID:
126 minstr->SetMachineOperandConst(0,
127 MachineOperand::MO_SignExtendedImmed,
130 case Type::UByteTyID:
131 minstr->SetMachineOperandConst(0,
132 MachineOperand::MO_SignExtendedImmed,
136 assert(0 && "Unexpected unsigned type");
140 #endif USE_DIRECT_SIGN_EXTENSION_INSTRS
143 //************************* External Classes *******************************/
145 //---------------------------------------------------------------------------
146 // class UltraSparcInstrInfo
149 // Information about individual instructions.
150 // Most information is stored in the SparcMachineInstrDesc array above.
151 // Other information is computed on demand, and most such functions
152 // default to member functions in base class MachineInstrInfo.
153 //---------------------------------------------------------------------------
156 UltraSparcInstrInfo::UltraSparcInstrInfo(const TargetMachine& tgt)
157 : MachineInstrInfo(tgt, SparcMachineInstrDesc,
158 /*descSize = */ NUM_TOTAL_OPCODES,
159 /*numRealOpCodes = */ NUM_REAL_OPCODES)
164 // Create an instruction sequence to put the constant `val' into
165 // the virtual register `dest'. `val' may be a Constant or a
166 // GlobalValue, viz., the constant address of a global variable or function.
167 // The generated instructions are returned in `mvec'.
168 // Any temp. registers (TmpInstruction) created are recorded in mcfi.
169 // Any stack space required is allocated via MachineCodeForMethod.
172 UltraSparcInstrInfo::CreateCodeToLoadConst(const TargetMachine& target,
176 std::vector<MachineInstr*>& mvec,
177 MachineCodeForInstruction& mcfi) const
179 assert(isa<Constant>(val) || isa<GlobalValue>(val) &&
180 "I only know about constant values and global addresses");
182 // Use a "set" instruction for known constants that can go in an integer reg.
183 // Use a "load" instruction for all other constants, in particular,
184 // floating point constants and addresses of globals.
186 const Type* valType = val->getType();
188 if (valType->isIntegral() || valType == Type::BoolTy)
190 if (! val->getType()->isSigned())
192 uint64_t C = cast<ConstantUInt>(val)->getValue();
193 CreateUIntSetInstruction(target, F, C, dest, mvec, mcfi);
197 bool isValidConstant;
198 int64_t C = GetConstantValueAsSignedInt(val, isValidConstant);
199 assert(isValidConstant && "Unrecognized constant");
200 CreateIntSetInstruction(target, F, C, dest, mvec, mcfi);
205 // Make an instruction sequence to load the constant, viz:
206 // SETX <addr-of-constant>, tmpReg, addrReg
207 // LOAD /*addr*/ addrReg, /*offset*/ 0, dest
208 // Only the SETX is needed if `val' is a GlobalValue, i.e,. it is
209 // itself a constant address. Otherwise, both are needed.
212 int64_t zeroOffset = 0; // to avoid ambiguity with (Value*) 0
214 TmpInstruction* tmpReg =
215 new TmpInstruction(PointerType::get(val->getType()), val);
216 mcfi.addTemp(tmpReg);
218 if (isa<Constant>(val))
220 // Create another TmpInstruction for the hidden integer register
221 TmpInstruction* addrReg =
222 new TmpInstruction(PointerType::get(val->getType()), val);
223 mcfi.addTemp(addrReg);
229 MachineInstr* M = new MachineInstr(SETX);
230 M->SetMachineOperandVal(0, MachineOperand::MO_PCRelativeDisp, val);
231 M->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister, tmpReg,
233 M->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister, addrVal);
236 if (isa<Constant>(val))
238 // Make sure constant is emitted to constant pool in assembly code.
239 MachineCodeForMethod::get(F).addToConstantPool(cast<Constant>(val));
241 // Generate the load instruction
242 M = Create3OperandInstr_SImmed(ChooseLoadInstruction(val->getType()),
243 addrVal, zeroOffset, dest);
250 // Create an instruction sequence to copy an integer value `val'
251 // to a floating point value `dest' by copying to memory and back.
252 // val must be an integral type. dest must be a Float or Double.
253 // The generated instructions are returned in `mvec'.
254 // Any temp. registers (TmpInstruction) created are recorded in mcfi.
255 // Any stack space required is allocated via MachineCodeForMethod.
258 UltraSparcInstrInfo::CreateCodeToCopyIntToFloat(const TargetMachine& target,
262 std::vector<MachineInstr*>& mvec,
263 MachineCodeForInstruction& mcfi) const
265 assert((val->getType()->isIntegral() || isa<PointerType>(val->getType()))
266 && "Source type must be integral");
267 assert(dest->getType()->isFloatingPoint()
268 && "Dest type must be float/double");
270 int offset = MachineCodeForMethod::get(F).allocateLocalVar(target, val);
272 // Store instruction stores `val' to [%fp+offset].
273 // The store and load opCodes are based on the value being copied, and
274 // they use integer and float types that accomodate the
275 // larger of the source type and the destination type:
276 // On SparcV9: int for float, long for double.
278 Type* tmpType = (dest->getType() == Type::FloatTy)? Type::IntTy
280 MachineInstr* store = new MachineInstr(ChooseStoreInstruction(tmpType));
281 store->SetMachineOperandVal(0, MachineOperand::MO_VirtualRegister, val);
282 store->SetMachineOperandReg(1, target.getRegInfo().getFramePointer());
283 store->SetMachineOperandConst(2,MachineOperand::MO_SignExtendedImmed,offset);
284 mvec.push_back(store);
286 // Load instruction loads [%fp+offset] to `dest'.
288 MachineInstr* load =new MachineInstr(ChooseLoadInstruction(dest->getType()));
289 load->SetMachineOperandReg(0, target.getRegInfo().getFramePointer());
290 load->SetMachineOperandConst(1, MachineOperand::MO_SignExtendedImmed,offset);
291 load->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister, dest);
292 mvec.push_back(load);
296 // Similarly, create an instruction sequence to copy an FP value
297 // `val' to an integer value `dest' by copying to memory and back.
298 // The generated instructions are returned in `mvec'.
299 // Any temp. registers (TmpInstruction) created are recorded in mcfi.
300 // Any stack space required is allocated via MachineCodeForMethod.
303 UltraSparcInstrInfo::CreateCodeToCopyFloatToInt(const TargetMachine& target,
307 std::vector<MachineInstr*>& mvec,
308 MachineCodeForInstruction& mcfi) const
310 assert(val->getType()->isFloatingPoint()
311 && "Source type must be float/double");
312 assert((dest->getType()->isIntegral() || isa<PointerType>(dest->getType()))
313 && "Dest type must be integral");
315 int offset = MachineCodeForMethod::get(F).allocateLocalVar(target, val);
317 // Store instruction stores `val' to [%fp+offset].
318 // The store and load opCodes are based on the value being copied, and
319 // they use the integer type that matches the source type in size:
320 // On SparcV9: int for float, long for double.
322 Type* tmpType = (val->getType() == Type::FloatTy)? Type::IntTy
324 MachineInstr* store=new MachineInstr(ChooseStoreInstruction(val->getType()));
325 store->SetMachineOperandVal(0, MachineOperand::MO_VirtualRegister, val);
326 store->SetMachineOperandReg(1, target.getRegInfo().getFramePointer());
327 store->SetMachineOperandConst(2,MachineOperand::MO_SignExtendedImmed,offset);
328 mvec.push_back(store);
330 // Load instruction loads [%fp+offset] to `dest'.
332 MachineInstr* load = new MachineInstr(ChooseLoadInstruction(tmpType));
333 load->SetMachineOperandReg(0, target.getRegInfo().getFramePointer());
334 load->SetMachineOperandConst(1, MachineOperand::MO_SignExtendedImmed,offset);
335 load->SetMachineOperandVal(2, MachineOperand::MO_VirtualRegister, dest);
336 mvec.push_back(load);
340 // Create instruction(s) to copy src to dest, for arbitrary types
341 // The generated instructions are returned in `mvec'.
342 // Any temp. registers (TmpInstruction) created are recorded in mcfi.
343 // Any stack space required is allocated via MachineCodeForMethod.
346 UltraSparcInstrInfo::CreateCopyInstructionsByType(const TargetMachine& target,
350 vector<MachineInstr*>& mvec,
351 MachineCodeForInstruction& mcfi) const
353 bool loadConstantToReg = false;
355 const Type* resultType = dest->getType();
357 MachineOpCode opCode = ChooseAddInstructionByType(resultType);
358 if (opCode == INVALID_OPCODE)
360 assert(0 && "Unsupported result type in CreateCopyInstructionsByType()");
364 // if `src' is a constant that doesn't fit in the immed field or if it is
365 // a global variable (i.e., a constant address), generate a load
366 // instruction instead of an add
368 if (isa<Constant>(src))
370 unsigned int machineRegNum;
372 MachineOperand::MachineOperandType opType =
373 ChooseRegOrImmed(src, opCode, target, /*canUseImmed*/ true,
374 machineRegNum, immedValue);
376 if (opType == MachineOperand::MO_VirtualRegister)
377 loadConstantToReg = true;
379 else if (isa<GlobalValue>(src))
380 loadConstantToReg = true;
382 if (loadConstantToReg)
383 { // `src' is constant and cannot fit in immed field for the ADD
384 // Insert instructions to "load" the constant into a register
385 target.getInstrInfo().CreateCodeToLoadConst(target, F, src, dest,
389 { // Create an add-with-0 instruction of the appropriate type.
390 // Make `src' the second operand, in case it is a constant
391 // Use (unsigned long) 0 for a NULL pointer value.
393 const Type* zeroValueType =
394 isa<PointerType>(resultType) ? Type::ULongTy : resultType;
395 MachineInstr* minstr =
396 Create3OperandInstr(opCode, Constant::getNullValue(zeroValueType),
398 mvec.push_back(minstr);
403 // Create instruction sequence to produce a sign-extended register value
404 // from an arbitrary sized value (sized in bits, not bytes).
405 // For SPARC v9, we sign-extend the given unsigned operand using SLL; SRA.
406 // The generated instructions are returned in `mvec'.
407 // Any temp. registers (TmpInstruction) created are recorded in mcfi.
408 // Any stack space required is allocated via MachineCodeForMethod.
411 UltraSparcInstrInfo::CreateSignExtensionInstructions(
412 const TargetMachine& target,
414 Value* unsignedSrcVal,
415 unsigned int srcSizeInBits,
417 vector<MachineInstr*>& mvec,
418 MachineCodeForInstruction& mcfi) const
422 assert(srcSizeInBits > 0 && srcSizeInBits <= 32
423 && "Hmmm... srcSizeInBits > 32 unexpected but could be handled here.");
425 if (srcSizeInBits < 32)
426 { // SLL is needed since operand size is < 32 bits.
427 TmpInstruction *tmpI = new TmpInstruction(dest->getType(),
428 unsignedSrcVal, dest,"make32");
430 M = Create3OperandInstr_UImmed(SLL,unsignedSrcVal,32-srcSizeInBits,tmpI);
432 unsignedSrcVal = tmpI;
435 M = Create3OperandInstr_UImmed(SRA, unsignedSrcVal, 32-srcSizeInBits, dest);