MachineInstr.cpp revision 4bc3daaa3f3c9f22d5dd695e987e8d20f999791c
1// $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#include "llvm/CodeGen/MachineInstr.h"
16#include "llvm/ConstPoolVals.h"
17#include "llvm/Instruction.h"
18#include <strstream>
19
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
48void
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}
329