Added new function UltraSparcInstrInfo::CreateCodeToCopyIntToFloat.
[oota-llvm.git] / lib / Target / SparcV9 / SparcV9InstrInfo.cpp
1 // $Id$
2 //***************************************************************************
3 // File:
4 //      SparcInstrInfo.cpp
5 // 
6 // Purpose:
7 //      
8 // History:
9 //      10/15/01         -  Vikram Adve  -  Created
10 //**************************************************************************/
11
12
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/MachineInstr.h"
19 #include "llvm/Method.h"
20 #include "llvm/ConstPoolVals.h"
21 #include "llvm/DerivedTypes.h"
22 #include "llvm/Type.h"
23
24
25 //************************ Internal Functions ******************************/
26
27
28 static inline MachineInstr*
29 CreateIntSetInstruction(int64_t C, bool isSigned, Value* dest,
30                         vector<TmpInstruction*>& tempVec)
31 {
32   MachineInstr* minstr;
33   uint64_t absC = (C >= 0)? C : -C;
34   if (absC > (unsigned int) ~0)
35     { // C does not fit in 32 bits
36       TmpInstruction* tmpReg =
37         new TmpInstruction(Instruction::UserOp1, Type::IntTy, NULL, NULL);
38       tempVec.push_back(tmpReg);
39       
40       minstr = new MachineInstr(SETX);
41       minstr->SetMachineOperand(0, MachineOperand::MO_SignExtendedImmed, C);
42       minstr->SetMachineOperand(1, MachineOperand::MO_VirtualRegister, tmpReg,
43                                    /*isdef*/ true);
44       minstr->SetMachineOperand(2, MachineOperand::MO_VirtualRegister,dest);
45     }
46   if (isSigned)
47     {
48       minstr = new MachineInstr(SETSW);
49       minstr->SetMachineOperand(0, MachineOperand::MO_SignExtendedImmed, C);
50       minstr->SetMachineOperand(1, MachineOperand::MO_VirtualRegister, dest);
51     }
52   else
53     {
54       minstr = new MachineInstr(SETUW);
55       minstr->SetMachineOperand(0, MachineOperand::MO_UnextendedImmed, C);
56       minstr->SetMachineOperand(1, MachineOperand::MO_VirtualRegister, dest);
57     }
58   
59   return minstr;
60 }
61
62 //************************* External Classes *******************************/
63
64 //---------------------------------------------------------------------------
65 // class UltraSparcInstrInfo 
66 // 
67 // Purpose:
68 //   Information about individual instructions.
69 //   Most information is stored in the SparcMachineInstrDesc array above.
70 //   Other information is computed on demand, and most such functions
71 //   default to member functions in base class MachineInstrInfo. 
72 //---------------------------------------------------------------------------
73
74 /*ctor*/
75 UltraSparcInstrInfo::UltraSparcInstrInfo(const TargetMachine& tgt)
76   : MachineInstrInfo(tgt, SparcMachineInstrDesc,
77                      /*descSize = */ NUM_TOTAL_OPCODES,
78                      /*numRealOpCodes = */ NUM_REAL_OPCODES)
79 {
80 }
81
82
83 // Create an instruction sequence to put the constant `val' into
84 // the virtual register `dest'.  `val' may be a ConstPoolVal or a
85 // GlobalValue, viz., the constant address of a global variable or function.
86 // The generated instructions are returned in `minstrVec'.
87 // Any temp. registers (TmpInstruction) created are returned in `tempVec'.
88 // 
89 void
90 UltraSparcInstrInfo::CreateCodeToLoadConst(Value* val,
91                                        Instruction* dest,
92                                        vector<MachineInstr*>& minstrVec,
93                                        vector<TmpInstruction*>& tempVec) const
94 {
95   MachineInstr* minstr;
96   
97   assert(isa<ConstPoolVal>(val) || isa<GlobalValue>(val) &&
98          "I only know about constant values and global addresses");
99   
100   // Use a "set" instruction for known constants that can go in an integer reg.
101   // Use a "load" instruction for all other constants, in particular,
102   // floating point constants and addresses of globals.
103   // 
104   const Type* valType = val->getType();
105   
106   if (valType->isIntegral() || valType == Type::BoolTy)
107     {
108       bool isValidConstant;
109       int64_t C = GetConstantValueAsSignedInt(val, isValidConstant);
110       assert(isValidConstant && "Unrecognized constant");
111       minstr = CreateIntSetInstruction(C, valType->isSigned(), dest, tempVec);
112       minstrVec.push_back(minstr);
113     }
114   else
115     {
116       // Make an instruction sequence to load the constant, viz:
117       //            SETX <addr-of-constant>, tmpReg, addrReg
118       //            LOAD  /*addr*/ addrReg, /*offset*/ 0, dest
119       // Only the SETX is needed if `val' is a GlobalValue, i.e,. it is
120       // itself a constant address.  Otherwise, both are needed.
121       
122       Value* addrVal;
123       int64_t zeroOffset = 0; // to avoid ambiguity with (Value*) 0
124       
125       TmpInstruction* tmpReg =
126         new TmpInstruction(Instruction::UserOp1,
127                            PointerType::get(val->getType()), val, NULL);
128       tempVec.push_back(tmpReg);
129       
130       if (isa<ConstPoolVal>(val))
131         {
132           // Create another TmpInstruction for the hidden integer register
133           TmpInstruction* addrReg =
134             new TmpInstruction(Instruction::UserOp1,
135                                PointerType::get(val->getType()), val, NULL);
136           tempVec.push_back(addrReg);
137           addrVal = addrReg;
138         }
139       else
140         addrVal = dest;
141       
142       minstr = new MachineInstr(SETX);
143       minstr->SetMachineOperand(0, MachineOperand::MO_PCRelativeDisp, val);
144       minstr->SetMachineOperand(1, MachineOperand::MO_VirtualRegister, tmpReg,
145                                    /*isdef*/ true);
146       minstr->SetMachineOperand(2, MachineOperand::MO_VirtualRegister,addrVal);
147       minstrVec.push_back(minstr);
148       
149       if (isa<ConstPoolVal>(val))
150         {
151           // addrVal->addMachineInstruction(minstr);
152       
153           minstr = new MachineInstr(ChooseLoadInstruction(val->getType()));
154           minstr->SetMachineOperand(0, MachineOperand::MO_VirtualRegister,
155                                        addrVal);
156           minstr->SetMachineOperand(1, MachineOperand::MO_SignExtendedImmed,
157                                        zeroOffset);
158           minstr->SetMachineOperand(2, MachineOperand::MO_VirtualRegister,
159                                        dest);
160           minstrVec.push_back(minstr);
161         }
162     }
163 }
164
165
166 // Create an instruction sequence to copy an integer value `val' from an
167 // integer to a floating point register `dest'.  val must be an integral
168 // type.  dest must be a Float or Double.
169 // The generated instructions are returned in `minstrVec'.
170 // Any temp. registers (TmpInstruction) created are returned in `tempVec'.
171 // 
172 void
173 UltraSparcInstrInfo::CreateCodeToCopyIntToFloat(Method* method,
174                                               Value* val,
175                                               Instruction* dest,
176                                               vector<MachineInstr*>& minstrVec,
177                                               vector<TmpInstruction*>& tempVec,
178                                               TargetMachine& target) const
179 {
180   assert(val->getType()->isIntegral() && "Source type must be integral");
181   assert((dest->getType() ==Type::FloatTy || dest->getType() ==Type::DoubleTy)
182          && "Dest type must be float/double");
183   
184   const MachineFrameInfo& frameInfo = ((UltraSparc&) target).getFrameInfo();
185   
186   MachineCodeForMethod& mcinfo = MachineCodeForMethod::get(method);
187   int offset = mcinfo.allocateLocalVar(target, val); 
188   
189   // int offset = mcinfo.getOffset(val);
190   // if (offset == MAXINT)
191   //   {
192   //     offset = frameInfo.getFirstAutomaticVarOffsetFromFP(method)
193   //              - mcinfo.getAutomaticVarsSize();
194   //     mcinfo.putLocalVarAtOffsetFromFP(val, offset,
195   //                           target.findOptimalStorageSize(val->getType()));
196   //   }
197   
198   // Store instruction stores `val' to [%fp+offset].
199   // We could potentially use up to the full 64 bits of the integer register
200   // but since there are the same number of single-prec and double-prec regs,
201   // we can avoid over-using one of these types.  So we make the store type
202   // the same size as the dest type:
203   // On SparcV9: int for float, long for double.
204   Type* tmpType = (dest->getType() == Type::FloatTy)? Type::IntTy
205                                                     : Type::LongTy;
206   MachineInstr* store = new MachineInstr(ChooseStoreInstruction(tmpType));
207   store->SetMachineOperand(0, MachineOperand::MO_VirtualRegister, val);
208   store->SetMachineOperand(1, target.getRegInfo().getFramePointer());
209   store->SetMachineOperand(2, MachineOperand::MO_SignExtendedImmed, offset);
210   minstrVec.push_back(store);
211
212   // Load instruction loads [%fp+offset] to `dest'.
213   // The load instruction should have type of the value being loaded,
214   // not the destination register type.
215   // 
216   MachineInstr* load = new MachineInstr(ChooseLoadInstruction(tmpType));
217   load->SetMachineOperand(0, target.getRegInfo().getFramePointer());
218   load->SetMachineOperand(1, MachineOperand::MO_SignExtendedImmed, offset);
219   load->SetMachineOperand(2, MachineOperand::MO_VirtualRegister, dest);
220   minstrVec.push_back(load);
221 }