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 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 35 bool 36 MachineInstrInfo::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 52 MachineInstr::MachineInstr(MachineOpCode _opCode, 53 OpCodeMask _opCodeMask) 54 : opCode(_opCode), 55 opCodeMask(_opCodeMask), 56 operands(TargetMachineInstrInfo[_opCode].numOperands) 57 { 58 } 59 60 MachineInstr::~MachineInstr() 61 { 62 } 63 64 void 65 MachineInstr::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 73 void 74 MachineInstr::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 82 void 83 MachineInstr::SetMachineOperand(unsigned int i, 84 unsigned int regNum) 85 { 86 assert(i < TargetMachineInstrInfo[opCode].numOperands); 87 operands[i].InitializeReg(regNum); 88 } 89 90 void 91 MachineInstr::dump(unsigned int indent) 92 { 93 for (unsigned i=0; i < indent; i++) 94 cout << " "; 95 96 cout << *this; 97 } 98 99 ostream& 100 operator<< (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 110 ostream& 111 operator<< (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 185 void 186 Set2OperandsFromInstr(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 199 unsigned 200 Set3OperandsFromInstrJUNK(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 271 void 272 Set3OperandsFromInstr(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 301 MachineOperand::MachineOperandType 302 ChooseRegOrImmed(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 } 345