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