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