blob: 1b6f25ae77f427119b3e1cddf7045056b73f0d13 [file] [log] [blame]
Vikram S. Adve70bc4b52001-07-21 12:41:50 +00001// $Id$
2//***************************************************************************
3// File:
4// MachineInstr.cpp
5//
6// Purpose:
7//
8//
9// Strategy:
10//
11// History:
12// 7/2/01 - Vikram Adve - Created
13//**************************************************************************/
14
15
16//************************** System Include Files **************************/
17
18#include <strstream.h>
19#include <string>
20#include <vector>
21
22//*************************** User Include Files ***************************/
23
24#include "llvm/Type.h"
25#include "llvm/DerivedTypes.h"
26#include "llvm/ConstPoolVals.h"
27#include "llvm/Value.h"
28#include "llvm/Instruction.h"
29#include "llvm/Codegen/InstrForest.h"
30#include "llvm/Codegen/MachineInstr.h"
31
32//************************ Class Implementations **************************/
33
34
35bool
36MachineInstrInfo::constantFitsInImmedField(int64_t intValue) const
37{
38 // First, check if opCode has an immed field.
39 bool isSignExtended;
40 uint64_t maxImmedValue = this->maxImmedConstant(isSignExtended);
41 if (maxImmedValue != 0)
42 {
43 // Now check if the constant fits
44 if (intValue <= (int64_t) maxImmedValue &&
45 intValue >= -((int64_t) maxImmedValue+1))
46 return true;
47 }
48
49 return false;
50}
51
52MachineInstr::MachineInstr(MachineOpCode _opCode,
53 OpCodeMask _opCodeMask)
54 : opCode(_opCode),
55 opCodeMask(_opCodeMask),
56 operands(TargetMachineInstrInfo[_opCode].numOperands)
57{
58}
59
60MachineInstr::~MachineInstr()
61{
62}
63
64void
65MachineInstr::SetMachineOperand(unsigned int i,
66 MachineOperand::MachineOperandType operandType,
67 Value* _val)
68{
69 assert(i < TargetMachineInstrInfo[opCode].numOperands);
70 operands[i].Initialize(operandType, _val);
71}
72
73void
74MachineInstr::SetMachineOperand(unsigned int i,
75 MachineOperand::MachineOperandType operandType,
76 int64_t intValue)
77{
78 assert(i < TargetMachineInstrInfo[opCode].numOperands);
79 operands[i].InitializeConst(operandType, intValue);
80}
81
82void
83MachineInstr::SetMachineOperand(unsigned int i,
84 unsigned int regNum)
85{
86 assert(i < TargetMachineInstrInfo[opCode].numOperands);
87 operands[i].InitializeReg(regNum);
88}
89
90void
91MachineInstr::dump(unsigned int indent)
92{
93 for (unsigned i=0; i < indent; i++)
94 cout << " ";
95
96 cout << *this;
97}
98
99ostream&
100operator<< (ostream& os, const MachineInstr& minstr)
101{
102 os << TargetMachineInstrInfo[minstr.opCode].opCodeString;
103
104 for (unsigned i=0, N=minstr.getNumOperands(); i < N; i++)
105 os << "\t" << minstr.getOperand(i);
106
107 return os;
108}
109
110ostream&
111operator<< (ostream& os, const MachineOperand& mop)
112{
113 strstream regInfo;
114 if (mop.machineOperandType == MachineOperand::MO_Register)
115 {
116 if (mop.vregType == MachineOperand::MO_VirtualReg)
117 regInfo << "(val " << mop.value << ")" << ends;
118 else
119 regInfo << "(" << mop.regNum << ")" << ends;
120 }
121 else if (mop.machineOperandType == MachineOperand::MO_CCRegister)
122 regInfo << "(val " << mop.value << ")" << ends;
123
124 switch(mop.machineOperandType)
125 {
126 case MachineOperand::MO_Register:
127 os << "%reg" << regInfo.str();
128 free(regInfo.str());
129 break;
130
131 case MachineOperand::MO_CCRegister:
132 os << "%ccreg" << regInfo.str();
133 free(regInfo.str());
134 break;
135
136 case MachineOperand::MO_SignExtendedImmed:
137 os << mop.immedVal;
138 break;
139
140 case MachineOperand::MO_UnextendedImmed:
141 os << mop.immedVal;
142 break;
143
144 case MachineOperand::MO_PCRelativeDisp:
145 os << "%disp(label " << mop.value << ")";
146 break;
147
148 default:
149 assert(0 && "Unrecognized operand type");
150 break;
151 }
152
153 return os;
154}
155
156
157//---------------------------------------------------------------------------
158// Target-independent utility routines for creating machine instructions
159//---------------------------------------------------------------------------
160
161
162//------------------------------------------------------------------------
163// Function Set2OperandsFromInstr
164// Function Set3OperandsFromInstr
165//
166// For the common case of 2- and 3-operand arithmetic/logical instructions,
167// set the m/c instr. operands directly from the VM instruction's operands.
168// Check whether the first or second operand is 0 and can use a dedicated "0" register.
169// Check whether the second operand should use an immediate field or register.
170// (First and third operands are never immediates for such instructions.)
171//
172// Arguments:
173// canDiscardResult: Specifies that the result operand can be discarded
174// by using the dedicated "0"
175//
176// op1position, op2position and resultPosition: Specify in which position
177// in the machine instruction the 3 operands (arg1, arg2
178// and result) should go.
179//
180// RETURN VALUE: unsigned int flags, where
181// flags & 0x01 => operand 1 is constant and needs a register
182// flags & 0x02 => operand 2 is constant and needs a register
183//------------------------------------------------------------------------
184
185void
186Set2OperandsFromInstr(MachineInstr* minstr,
187 InstructionNode* vmInstrNode,
188 const TargetMachine& targetMachine,
189 bool canDiscardResult,
190 int op1Position,
191 int resultPosition)
192{
193 Set3OperandsFromInstr(minstr, vmInstrNode, targetMachine,
194 canDiscardResult, op1Position,
195 /*op2Position*/ -1, resultPosition);
196}
197
198
199unsigned
200Set3OperandsFromInstrJUNK(MachineInstr* minstr,
201 InstructionNode* vmInstrNode,
202 const TargetMachine& targetMachine,
203 bool canDiscardResult,
204 int op1Position,
205 int op2Position,
206 int resultPosition)
207{
208 assert(op1Position >= 0);
209 assert(resultPosition >= 0);
210
211 unsigned returnFlags = 0x0;
212
213 // Check if operand 1 is 0 and if so, try to use the register that gives 0, if any.
214 Value* op1Value = vmInstrNode->leftChild()->getValue();
215 bool isValidConstant;
216 int64_t intValue = GetConstantValueAsSignedInt(op1Value, isValidConstant);
217 if (isValidConstant && intValue == 0 && targetMachine.zeroRegNum >= 0)
218 minstr->SetMachineOperand(op1Position, /*regNum*/ targetMachine.zeroRegNum);
219 else
220 {
221 if (op1Value->getValueType() == Value::ConstantVal)
222 {// value is constant and must be loaded from constant pool
223 returnFlags = returnFlags | (1 << op1Position);
224 }
225 minstr->SetMachineOperand(op1Position, MachineOperand::MO_Register,
226 op1Value);
227 }
228
229 // Check if operand 2 (if any) fits in the immediate field of the instruction,
230 // of if it is 0 and can use a dedicated machine register
231 if (op2Position >= 0)
232 {
233 Value* op2Value = vmInstrNode->rightChild()->getValue();
234 int64_t immedValue;
235 MachineOperand::VirtualRegisterType vregType;
236 unsigned int machineRegNum;
237
238 MachineOperand::MachineOperandType
239 op2type = ChooseRegOrImmed(op2Value, minstr->getOpCode(),targetMachine,
240 /*canUseImmed*/ true,
241 vregType, machineRegNum, immedValue);
242
243 if (op2type == MachineOperand::MO_Register)
244 {
245 if (vregType == MachineOperand::MO_MachineReg)
246 minstr->SetMachineOperand(op2Position, machineRegNum);
247 else
248 {
249 if (op2Value->getValueType() == Value::ConstantVal)
250 {// value is constant and must be loaded from constant pool
251 returnFlags = returnFlags | (1 << op2Position);
252 }
253 minstr->SetMachineOperand(op2Position, op2type, op2Value);
254 }
255 }
256 else
257 minstr->SetMachineOperand(op2Position, op2type, immedValue);
258 }
259
260 // If operand 3 (result) can be discarded, use a dead register if one exists
261 if (canDiscardResult && targetMachine.zeroRegNum >= 0)
262 minstr->SetMachineOperand(resultPosition, targetMachine.zeroRegNum);
263 else
264 minstr->SetMachineOperand(resultPosition, MachineOperand::MO_Register,
265 vmInstrNode->getValue());
266
267 return returnFlags;
268}
269
270
271void
272Set3OperandsFromInstr(MachineInstr* minstr,
273 InstructionNode* vmInstrNode,
274 const TargetMachine& targetMachine,
275 bool canDiscardResult,
276 int op1Position,
277 int op2Position,
278 int resultPosition)
279{
280 assert(op1Position >= 0);
281 assert(resultPosition >= 0);
282
283 // operand 1
284 minstr->SetMachineOperand(op1Position, MachineOperand::MO_Register,
285 vmInstrNode->leftChild()->getValue());
286
287 // operand 2 (if any)
288 if (op2Position >= 0)
289 minstr->SetMachineOperand(op2Position, MachineOperand::MO_Register,
290 vmInstrNode->rightChild()->getValue());
291
292 // result operand: if it can be discarded, use a dead register if one exists
293 if (canDiscardResult && targetMachine.zeroRegNum >= 0)
294 minstr->SetMachineOperand(resultPosition, targetMachine.zeroRegNum);
295 else
296 minstr->SetMachineOperand(resultPosition, MachineOperand::MO_Register,
297 vmInstrNode->getValue());
298}
299
300
301MachineOperand::MachineOperandType
302ChooseRegOrImmed(Value* val,
303 MachineOpCode opCode,
304 const TargetMachine& targetMachine,
305 bool canUseImmed,
306 MachineOperand::VirtualRegisterType& getVRegType,
307 unsigned int& getMachineRegNum,
308 int64_t& getImmedValue)
309{
310 MachineOperand::MachineOperandType opType = MachineOperand::MO_Register;
311 getVRegType = MachineOperand::MO_VirtualReg;
312 getMachineRegNum = 0;
313 getImmedValue = 0;
314
315 // Check for the common case first: argument is not constant
316 //
317 if (val->getValueType() != Value::ConstantVal)
318 return opType;
319
320 // Now get the constant value and check if it fits in the IMMED field.
321 // Take advantage of the fact that the max unsigned value will rarely
322 // fit into any IMMED field and ignore that case (i.e., cast smaller
323 // unsigned constants to signed).
324 //
325 bool isValidConstant;
326 int64_t intValue = GetConstantValueAsSignedInt(val, isValidConstant);
327
328 if (isValidConstant)
329 {
330 if (intValue == 0 && targetMachine.zeroRegNum >= 0)
331 {
332 getVRegType = MachineOperand::MO_MachineReg;
333 getMachineRegNum = targetMachine.zeroRegNum;
334 }
335 else if (canUseImmed &&
336 targetMachine.machineInstrInfo[opCode].constantFitsInImmedField(intValue))
337 {
338 opType = MachineOperand::MO_SignExtendedImmed;
339 getImmedValue = intValue;
340 }
341 }
342
343 return opType;
344}