Generate SETX for 64-bit integers!
[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/ConstPoolVals.h"
20 #include "llvm/Type.h"
21
22
23 //************************ Internal Functions ******************************/
24
25
26 static inline MachineInstr*
27 CreateIntSetInstruction(int64_t C, bool isSigned, Value* dest,
28                         vector<TmpInstruction*>& tempVec)
29 {
30   MachineInstr* minstr;
31   uint64_t absC = (C >= 0)? C : -C;
32   if (absC > (unsigned int) ~0)
33     { // C does not fit in 32 bits
34       TmpInstruction* tmpReg =
35         new TmpInstruction(Instruction::UserOp1, NULL, NULL);
36       tempVec.push_back(tmpReg);
37       
38       minstr = new MachineInstr(SETX);
39       minstr->SetMachineOperand(0, MachineOperand::MO_SignExtendedImmed, C);
40       minstr->SetMachineOperand(1, MachineOperand::MO_VirtualRegister, tmpReg,
41                                    /*isdef*/ true);
42       minstr->SetMachineOperand(2, MachineOperand::MO_VirtualRegister,dest);
43     }
44   if (isSigned)
45     {
46       minstr = new MachineInstr(SETSW);
47       minstr->SetMachineOperand(0, MachineOperand::MO_SignExtendedImmed, C);
48       minstr->SetMachineOperand(1, MachineOperand::MO_VirtualRegister, dest);
49     }
50   else
51     {
52       minstr = new MachineInstr(SETUW);
53       minstr->SetMachineOperand(0, MachineOperand::MO_UnextendedImmed, C);
54       minstr->SetMachineOperand(1, MachineOperand::MO_VirtualRegister, dest);
55     }
56   
57   return minstr;
58 }
59
60 //************************* External Classes *******************************/
61
62 //---------------------------------------------------------------------------
63 // class UltraSparcInstrInfo 
64 // 
65 // Purpose:
66 //   Information about individual instructions.
67 //   Most information is stored in the SparcMachineInstrDesc array above.
68 //   Other information is computed on demand, and most such functions
69 //   default to member functions in base class MachineInstrInfo. 
70 //---------------------------------------------------------------------------
71
72 /*ctor*/
73 UltraSparcInstrInfo::UltraSparcInstrInfo()
74   : MachineInstrInfo(SparcMachineInstrDesc,
75                      /*descSize = */ NUM_TOTAL_OPCODES,
76                      /*numRealOpCodes = */ NUM_REAL_OPCODES)
77 {
78 }
79
80
81 // Create an instruction sequence to put the constant `val' into
82 // the virtual register `dest'.  `val' may be a ConstPoolVal or a
83 // GlobalValue, viz., the constant address of a global variable or function.
84 // The generated instructions are returned in `minstrVec'.
85 // Any temp. registers (TmpInstruction) created are returned in `tempVec'.
86 // 
87 void
88 UltraSparcInstrInfo::CreateCodeToLoadConst(Value* val,
89                                        Instruction* dest,
90                                        vector<MachineInstr*>& minstrVec,
91                                        vector<TmpInstruction*>& tempVec) const
92 {
93   MachineInstr* minstr;
94   
95   assert(isa<ConstPoolVal>(val) || isa<GlobalValue>(val) &&
96          "I only know about constant values and global addresses");
97   
98   // Use a "set" instruction for known constants that can go in an integer reg.
99   // Use a "load" instruction for all other constants, in particular,
100   // floating point constants and addresses of globals.
101   // 
102   const Type* valType = val->getType();
103   
104   if (valType->isIntegral() || valType == Type::BoolTy)
105     {
106       bool isValidConstant;
107       int64_t C = GetConstantValueAsSignedInt(val, isValidConstant);
108       assert(isValidConstant && "Unrecognized constant");
109       minstr = CreateIntSetInstruction(C, valType->isSigned(), dest, tempVec);
110       minstrVec.push_back(minstr);
111     }
112   else
113     {
114       // Make an instruction sequence to load the constant, viz:
115       //            SETX <addr-of-constant>, tmpReg, addrReg
116       //            LOAD  /*addr*/ addrReg, /*offset*/ 0, dest
117       // Only the SETX is needed if `val' is a GlobalValue, i.e,. it is
118       // itself a constant address.  Otherwise, both are needed.
119       
120       Value* addrVal;
121       int64_t zeroOffset = 0; // to avoid ambiguity with (Value*) 0
122       
123       TmpInstruction* tmpReg =
124         new TmpInstruction(Instruction::UserOp1, val, NULL);
125       tempVec.push_back(tmpReg);
126       
127       if (isa<ConstPoolVal>(val))
128         {
129           // Create another TmpInstruction for the hidden integer register
130           TmpInstruction* addrReg =
131             new TmpInstruction(Instruction::UserOp1, val, NULL);
132           tempVec.push_back(addrReg);
133           addrVal = addrReg;
134         }
135       else
136         addrVal = dest;
137       
138       minstr = new MachineInstr(SETX);
139       minstr->SetMachineOperand(0, MachineOperand::MO_PCRelativeDisp, val);
140       minstr->SetMachineOperand(1, MachineOperand::MO_VirtualRegister, tmpReg,
141                                    /*isdef*/ true);
142       minstr->SetMachineOperand(2, MachineOperand::MO_VirtualRegister,addrVal);
143       minstrVec.push_back(minstr);
144       
145       if (isa<ConstPoolVal>(val))
146         {
147           // addrVal->addMachineInstruction(minstr);
148       
149           minstr = new MachineInstr(ChooseLoadInstruction(val->getType()));
150           minstr->SetMachineOperand(0, MachineOperand::MO_VirtualRegister,
151                                        addrVal);
152           minstr->SetMachineOperand(1, MachineOperand::MO_SignExtendedImmed,
153                                        zeroOffset);
154           minstr->SetMachineOperand(2, MachineOperand::MO_VirtualRegister,
155                                        dest);
156           minstrVec.push_back(minstr);
157         }
158     }
159 }
160
161
162 //************************ External Functions ******************************/
163