001 /* 002 * This file is part of the Jikes RVM project (http://jikesrvm.org). 003 * 004 * This file is licensed to You under the Eclipse Public License (EPL); 005 * You may not use this file except in compliance with the License. You 006 * may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/eclipse-1.0.php 009 * 010 * See the COPYRIGHT.txt file distributed with this work for information 011 * regarding copyright ownership. 012 */ 013 package org.jikesrvm.compilers.opt.regalloc.ia32; 014 015 import static org.jikesrvm.SizeConstants.BYTES_IN_ADDRESS; 016 017 import java.util.Enumeration; 018 import org.jikesrvm.ArchitectureSpecificOpt.PhysicalRegisterSet; 019 import org.jikesrvm.VM; 020 import org.jikesrvm.classloader.InterfaceMethodSignature; 021 import org.jikesrvm.classloader.TypeReference; 022 import org.jikesrvm.compilers.opt.DefUse; 023 import org.jikesrvm.compilers.opt.ir.Call; 024 import org.jikesrvm.compilers.opt.ir.MIR_Call; 025 import org.jikesrvm.compilers.opt.ir.MIR_Move; 026 import org.jikesrvm.compilers.opt.ir.MIR_Return; 027 import org.jikesrvm.compilers.opt.ir.MIR_UnaryNoRes; 028 import org.jikesrvm.compilers.opt.ir.IR; 029 import org.jikesrvm.compilers.opt.ir.IRTools; 030 import org.jikesrvm.compilers.opt.ir.Instruction; 031 import org.jikesrvm.compilers.opt.ir.Operators; 032 import org.jikesrvm.compilers.opt.ir.Register; 033 import org.jikesrvm.compilers.opt.ir.Prologue; 034 import org.jikesrvm.compilers.opt.ir.ia32.PhysicalRegisterTools; 035 import org.jikesrvm.compilers.opt.ir.operand.LocationOperand; 036 import org.jikesrvm.compilers.opt.ir.operand.MemoryOperand; 037 import org.jikesrvm.compilers.opt.ir.operand.MethodOperand; 038 import org.jikesrvm.compilers.opt.ir.operand.Operand; 039 import org.jikesrvm.compilers.opt.ir.operand.RegisterOperand; 040 import org.jikesrvm.compilers.opt.ir.operand.StackLocationOperand; 041 import org.jikesrvm.ia32.ArchConstants; 042 import org.jikesrvm.runtime.ArchEntrypoints; 043 import org.jikesrvm.runtime.Entrypoints; 044 045 /** 046 * This class contains IA32 calling conventions 047 * The two public methods are: 048 * <ol> 049 * <li>expandCallingConventions(IR) which is called by the 050 * register allocator immediately before allocation to make manifest the 051 * use of registers by the calling convention. 052 * <li>expandSysCall(Instruction, IR) which is called to expand 053 * a SYSCALL HIR instruction into the appropriate sequence of 054 * LIR instructions. 055 * </ol> 056 * <p> 057 * TODO: Much of this code could still be factored out as 058 * architecture-independent. 059 */ 060 public abstract class CallingConvention extends IRTools 061 implements Operators, PhysicalRegisterConstants { 062 063 /** 064 * Size of a word, in bytes 065 */ 066 private static final int WORDSIZE = BYTES_IN_ADDRESS; 067 068 /** 069 * Expand calling conventions to make physical registers explicit in the 070 * IR when required for calls, returns, and the prologue. 071 */ 072 public static void expandCallingConventions(IR ir) { 073 // expand each call and return instruction 074 for (Instruction inst = ir.firstInstructionInCodeOrder(); inst != null; inst = 075 inst.nextInstructionInCodeOrder()) { 076 if (inst.isCall()) { 077 callExpand(inst, ir); 078 } else if (inst.isReturn()) { 079 returnExpand(inst, ir); 080 } 081 } 082 083 // expand the prologue instruction 084 expandPrologue(ir); 085 } 086 087 /** 088 * Expand the calling convention for a particular call instruction 089 */ 090 private static void callExpand(Instruction call, IR ir) { 091 boolean isSysCall = call.operator() == IA32_SYSCALL; 092 093 // 0. Handle the parameters 094 int parameterBytes = isSysCall ? expandParametersToSysCall(call, ir) : expandParametersToCall(call, ir); 095 096 // 1. Clear the floating-point stack if dirty. 097 if (!ArchConstants.SSE2_FULL) { 098 if (call.operator != CALL_SAVE_VOLATILE) { 099 int FPRRegisterParams = countFPRParams(call); 100 FPRRegisterParams = Math.min(FPRRegisterParams, PhysicalRegisterSet.getNumberOfFPRParams()); 101 call.insertBefore(MIR_UnaryNoRes.create(IA32_FCLEAR, IC(FPRRegisterParams))); 102 } 103 } 104 105 // 2. Move the return value into a register 106 expandResultOfCall(call, isSysCall, ir); 107 108 // 3. If this is an interface invocation, set up the hidden parameter 109 // in the processor object to hold the interface signature id. 110 if (VM.BuildForIMTInterfaceInvocation) { 111 if (MIR_Call.hasMethod(call)) { 112 MethodOperand mo = MIR_Call.getMethod(call); 113 if (mo.isInterface()) { 114 InterfaceMethodSignature sig = InterfaceMethodSignature.findOrCreate(mo.getMemberRef()); 115 MemoryOperand M = 116 MemoryOperand.BD(ir.regpool.makeTROp(), 117 ArchEntrypoints.hiddenSignatureIdField.getOffset(), 118 (byte) WORDSIZE, 119 null, 120 null); 121 call.insertBefore(MIR_Move.create(IA32_MOV, M, IC(sig.getId()))); 122 } 123 } 124 } 125 126 // 4. ESP must be parameterBytes before call, will be at either parameterBytes 127 // or 0 afterwards depending on whether or it is an RVM method or a sysCall. 128 call.insertBefore(MIR_UnaryNoRes.create(REQUIRE_ESP, IC(parameterBytes))); 129 call.insertAfter(MIR_UnaryNoRes.create(ADVISE_ESP, IC(isSysCall ? parameterBytes : 0))); 130 } 131 132 /** 133 * Expand the calling convention for a particular return instruction 134 */ 135 private static void returnExpand(Instruction ret, IR ir) { 136 PhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet(); 137 138 if (MIR_Return.hasVal(ret)) { 139 Operand symb1 = MIR_Return.getClearVal(ret); 140 MIR_Return.setVal(ret, null); 141 TypeReference type = symb1.getType(); 142 if (type.isFloatType() || type.isDoubleType()) { 143 Register r = phys.getReturnFPR(); 144 RegisterOperand rOp = new RegisterOperand(r, type); 145 if (ArchConstants.SSE2_FULL) { 146 if (type.isFloatType()) { 147 ret.insertBefore(MIR_Move.create(IA32_MOVSS, rOp, symb1)); 148 } else { 149 ret.insertBefore(MIR_Move.create(IA32_MOVSD, rOp, symb1)); 150 } 151 } else { 152 ret.insertBefore(MIR_Move.create(IA32_FMOV, rOp, symb1)); 153 } 154 MIR_Return.setVal(ret, rOp.copyD2U()); 155 } else { 156 Register r = phys.getFirstReturnGPR(); 157 RegisterOperand rOp = new RegisterOperand(r, type); 158 ret.insertBefore(MIR_Move.create(IA32_MOV, rOp, symb1)); 159 MIR_Return.setVal(ret, rOp.copyD2U()); 160 } 161 } 162 163 if (MIR_Return.hasVal2(ret)) { 164 Operand symb2 = MIR_Return.getClearVal2(ret); 165 MIR_Return.setVal2(ret, null); 166 TypeReference type = symb2.getType(); 167 Register r = phys.getSecondReturnGPR(); 168 RegisterOperand rOp = new RegisterOperand(r, type); 169 ret.insertBefore(MIR_Move.create(IA32_MOV, rOp, symb2)); 170 MIR_Return.setVal2(ret, rOp.copyD2U()); 171 } 172 173 // Clear the floating-point stack if dirty. 174 if (!ArchConstants.SSE2_FULL) { 175 int nSave = 0; 176 if (MIR_Return.hasVal(ret)) { 177 Operand symb1 = MIR_Return.getClearVal(ret); 178 TypeReference type = symb1.getType(); 179 if (type.isFloatType() || type.isDoubleType()) { 180 nSave = 1; 181 } 182 } 183 ret.insertBefore(MIR_UnaryNoRes.create(IA32_FCLEAR, IC(nSave))); 184 } 185 186 // Set the first 'Val' in the return instruction to hold an integer 187 // constant which is the number of words to pop from the stack while 188 // returning from this method. 189 MIR_Return.setPopBytes(ret, IC(ir.incomingParameterBytes())); 190 } 191 192 /** 193 * Explicitly copy the result of a call instruction from the result 194 * register to the appropriate symbolic register, 195 * as defined by the calling convention. 196 */ 197 private static void expandResultOfCall(Instruction call, boolean isSysCall, IR ir) { 198 PhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet(); 199 200 // copy the first result parameter 201 if (MIR_Call.hasResult(call)) { 202 RegisterOperand result1 = MIR_Call.getClearResult(call); 203 if (result1.getType().isFloatType() || result1.getType().isDoubleType()) { 204 if (ArchConstants.SSE2_FULL && isSysCall) { 205 byte size = (byte)(result1.getType().isFloatType() ? 4 : 8); 206 RegisterOperand st0 = new RegisterOperand(phys.getST0(), result1.getType()); 207 MIR_Call.setResult(call, st0); // result is in st0, set it to avoid extending the live range of st0 208 RegisterOperand pr = ir.regpool.makeTROp(); 209 MemoryOperand scratch = new MemoryOperand(pr, null, (byte)0, Entrypoints.scratchStorageField.getOffset(), size, new LocationOperand(Entrypoints.scratchStorageField), null); 210 211 Instruction pop = MIR_Move.create(IA32_FSTP, scratch, st0.copyRO()); 212 call.insertAfter(pop); 213 if (result1.getType().isFloatType()) { 214 pop.insertAfter(MIR_Move.create(IA32_MOVSS, result1, scratch.copy())); 215 } else /* if (result1.type.isDoubleType()) */ { 216 pop.insertAfter(MIR_Move.create(IA32_MOVSD, result1, scratch.copy())); 217 } 218 } else { 219 Register r = phys.getReturnFPR(); 220 RegisterOperand physical = new RegisterOperand(r, result1.getType()); 221 MIR_Call.setResult(call, physical.copyRO()); // result is in physical, set it to avoid extending its live range 222 Instruction tmp; 223 if (ArchConstants.SSE2_FULL) { 224 if (result1.getType().isFloatType()) { 225 tmp = MIR_Move.create(IA32_MOVSS, result1, physical); 226 } else { 227 tmp = MIR_Move.create(IA32_MOVSD, result1, physical); 228 } 229 } else { 230 tmp = MIR_Move.create(IA32_FMOV, result1, physical); 231 } 232 call.insertAfter(tmp); 233 } 234 } else { 235 // first GPR result register 236 Register r = phys.getFirstReturnGPR(); 237 RegisterOperand physical = new RegisterOperand(r, result1.getType()); 238 Instruction tmp = MIR_Move.create(IA32_MOV, result1, physical); 239 call.insertAfter(tmp); 240 MIR_Call.setResult(call, physical.copyRO()); // result is in physical, set it to avoid extending its live range 241 } 242 } 243 244 // copy the second result parameter 245 if (MIR_Call.hasResult2(call)) { 246 RegisterOperand result2 = MIR_Call.getClearResult2(call); 247 // second GPR result register 248 Register r = phys.getSecondReturnGPR(); 249 RegisterOperand physical = new RegisterOperand(r, result2.getType()); 250 Instruction tmp = MIR_Move.create(IA32_MOV, result2, physical); 251 call.insertAfter(tmp); 252 MIR_Call.setResult2(call, physical.copyRO()); // result is in physical, set it to avoid extending its live range 253 } 254 } 255 256 /** 257 * Explicitly copy parameters to a call into the appropriate physical 258 * registers as defined by the calling convention.<p> 259 * 260 * Note: Assumes that ESP points to the word before the slot where the 261 * first parameter should be stored. 262 */ 263 private static int expandParametersToCall(Instruction call, IR ir) { 264 int nGPRParams = 0; 265 int nFPRParams = 0; 266 267 PhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet(); 268 // count the number FPR parameters in a pre-pass 269 int FPRRegisterParams = countFPRParams(call); 270 FPRRegisterParams = Math.min(FPRRegisterParams, PhysicalRegisterSet.getNumberOfFPRParams()); 271 272 // offset, in bytes, from the SP, for the next parameter slot on the 273 // stack 274 int parameterBytes = 0; 275 276 // Require ESP to be at bottom of frame before a call, 277 call.insertBefore(MIR_UnaryNoRes.create(REQUIRE_ESP, IC(0))); 278 279 // walk over each parameter 280 // must count then before we start nulling them out! 281 int numParams = MIR_Call.getNumberOfParams(call); 282 int nParamsInRegisters = 0; 283 for (int i = 0; i < numParams; i++) { 284 Operand param = MIR_Call.getClearParam(call, i); 285 MIR_Call.setParam(call, i, null); 286 TypeReference paramType = param.getType(); 287 if (paramType.isFloatType() || paramType.isDoubleType()) { 288 nFPRParams++; 289 int size = paramType.isFloatType() ? 4 : 8; 290 parameterBytes -= size; 291 if (nFPRParams > PhysicalRegisterSet.getNumberOfFPRParams()) { 292 // pass the FP parameter on the stack 293 Operand M = new StackLocationOperand(false, parameterBytes, size); 294 if (ArchConstants.SSE2_FULL) { 295 if (paramType.isFloatType()) { 296 call.insertBefore(MIR_Move.create(IA32_MOVSS, M, param)); 297 } else { 298 call.insertBefore(MIR_Move.create(IA32_MOVSD, M, param)); 299 } 300 } else { 301 call.insertBefore(MIR_Move.create(IA32_FMOV, M, param)); 302 } 303 } else { 304 // Pass the parameter in a register. 305 RegisterOperand real; 306 if (ArchConstants.SSE2_FULL) { 307 real = new RegisterOperand(phys.getFPRParam(nFPRParams-1), paramType); 308 if (paramType.isFloatType()) { 309 call.insertBefore(MIR_Move.create(IA32_MOVSS, real, param)); 310 } else { 311 call.insertBefore(MIR_Move.create(IA32_MOVSD, real, param)); 312 } 313 } else { 314 // Note that if k FPRs are passed in registers, 315 // the 1st goes in F(k-1), 316 // the 2nd goes in F(k-2), etc... 317 real = new RegisterOperand(phys.getFPRParam(FPRRegisterParams - nFPRParams), paramType); 318 call.insertBefore(MIR_Move.create(IA32_FMOV, real, param)); 319 } 320 // Record that the call now has a use of the real register. 321 MIR_Call.setParam(call, nParamsInRegisters++, real.copy()); 322 } 323 } else { 324 nGPRParams++; 325 parameterBytes -= 4; 326 if (nGPRParams > PhysicalRegisterSet.getNumberOfGPRParams()) { 327 // Too many parameters to pass in registers. Write the 328 // parameter into the appropriate stack frame location. 329 call.insertBefore(MIR_UnaryNoRes.create(REQUIRE_ESP, IC(parameterBytes + 4))); 330 call.insertBefore(MIR_UnaryNoRes.create(IA32_PUSH, param)); 331 } else { 332 // Pass the parameter in a register. 333 Register phy = phys.getGPRParam(nGPRParams - 1); 334 RegisterOperand real = new RegisterOperand(phy, paramType); 335 call.insertBefore(MIR_Move.create(IA32_MOV, real, param)); 336 // Record that the call now has a use of the real register. 337 MIR_Call.setParam(call, nParamsInRegisters++, real.copy()); 338 } 339 } 340 } 341 return parameterBytes; 342 } 343 344 /** 345 * Save and restore all nonvolatile registers around a syscall. 346 * We do this in case the sys call does not respect our 347 * register conventions.<p> 348 * 349 * We save/restore all nonvolatiles and the PR, whether 350 * or not this routine uses them. This may be a tad inefficient, but if 351 * you're making a system call, you probably don't care.<p> 352 * 353 * Side effect: changes the operator of the call instruction to 354 * IA32_CALL. 355 * 356 * @param call the sys call 357 */ 358 public static void saveNonvolatilesAroundSysCall(Instruction call, IR ir) { 359 saveNonvolatilesBeforeSysCall(call, ir); 360 restoreNonvolatilesAfterSysCall(call, ir); 361 call.operator = IA32_CALL; 362 } 363 364 /** 365 * Save all nonvolatile registers before a syscall. 366 * We do this in case the sys call does not respect our 367 * register conventions.<p> 368 * 369 * We save/restore all nonvolatiles and the PR, whether 370 * or not this routine uses them. This may be a tad inefficient, but if 371 * you're making a system call, you probably don't care. 372 * 373 * @param call the sys call 374 */ 375 static void saveNonvolatilesBeforeSysCall(Instruction call, IR ir) { 376 PhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet(); 377 StackManager sm = (StackManager) ir.stackManager; 378 379 // get the offset into the stack frame of where to stash the first 380 // nonvolatile for this case. 381 int location = sm.getOffsetForSysCall(); 382 383 // save each non-volatile 384 for (Enumeration<Register> e = phys.enumerateNonvolatileGPRs(); e.hasMoreElements();) { 385 Register r = e.nextElement(); 386 Operand M = new StackLocationOperand(true, -location, (byte) WORDSIZE); 387 call.insertBefore(MIR_Move.create(IA32_MOV, M, new RegisterOperand(r, TypeReference.Int))); 388 location += WORDSIZE; 389 } 390 391 // save the thread register 392 Operand M = new StackLocationOperand(true, -location, (byte) WORDSIZE); 393 call.insertBefore(MIR_Move.create(IA32_MOV, M, ir.regpool.makeTROp())); 394 } 395 396 /** 397 * Restore all nonvolatile registers after a syscall. 398 * We do this in case the sys call does not respect our 399 * register conventions.<p> 400 * 401 * We save/restore all nonvolatiles and the PR, whether 402 * or not this routine uses them. This may be a tad inefficient, but if 403 * you're making a system call, you probably don't care. 404 * 405 * @param call the sys call 406 */ 407 static void restoreNonvolatilesAfterSysCall(Instruction call, IR ir) { 408 PhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet(); 409 StackManager sm = (StackManager) ir.stackManager; 410 411 // get the offset into the stack frame of where to stash the first 412 // nonvolatile for this case. 413 int location = sm.getOffsetForSysCall(); 414 415 // restore each non-volatile 416 for (Enumeration<Register> e = phys.enumerateNonvolatileGPRs(); e.hasMoreElements();) { 417 Register r = e.nextElement(); 418 Operand M = new StackLocationOperand(true, -location, (byte) WORDSIZE); 419 call.insertAfter(MIR_Move.create(IA32_MOV, new RegisterOperand(r, TypeReference.Int), M)); 420 location += WORDSIZE; 421 } 422 423 // restore the thread register 424 Operand M = new StackLocationOperand(true, -location, (byte) WORDSIZE); 425 call.insertAfter(MIR_Move.create(IA32_MOV, ir.regpool.makeTROp(), M)); 426 } 427 428 /** 429 * Explicitly copy parameters to a system call into the appropriate physical 430 * registers as defined by the calling convention. Note that for a system 431 * call (ie., a call to C), the order of parameters on the stack is 432 * <em> reversed </em> compared to the normal RVM calling convention<p> 433 * 434 * Note: Assumes that ESP points to the word before the slot where the 435 * first parameter should be stored.<p> 436 * 437 * TODO: much of this code is exactly the same as in expandParametersToCall(). 438 * factor out the common code. 439 * 440 */ 441 private static int expandParametersToSysCall(Instruction call, IR ir) { 442 int nGPRParams = 0; 443 int nFPRParams = 0; 444 int parameterBytes = 0; 445 446 // walk over the parameters in reverse order 447 // NOTE: All params to syscall are passed on the stack! 448 int numParams = MIR_Call.getNumberOfParams(call); 449 for (int i = numParams - 1; i >= 0; i--) { 450 Operand param = MIR_Call.getClearParam(call, i); 451 MIR_Call.setParam(call, i, null); 452 TypeReference paramType = param.getType(); 453 if (paramType.isFloatType() || paramType.isDoubleType()) { 454 nFPRParams++; 455 int size = paramType.isFloatType() ? 4 : 8; 456 parameterBytes -= size; 457 Operand M = new StackLocationOperand(false, parameterBytes, size); 458 if (ArchConstants.SSE2_FULL) { 459 if (paramType.isFloatType()) { 460 call.insertBefore(MIR_Move.create(IA32_MOVSS, M, param)); 461 } else { 462 call.insertBefore(MIR_Move.create(IA32_MOVSD, M, param)); 463 } 464 } else { 465 call.insertBefore(MIR_Move.create(IA32_FMOV, M, param)); 466 } 467 } else { 468 nGPRParams++; 469 parameterBytes -= 4; 470 call.insertBefore(MIR_UnaryNoRes.create(REQUIRE_ESP, IC(parameterBytes + 4))); 471 call.insertBefore(MIR_UnaryNoRes.create(IA32_PUSH, param)); 472 } 473 } 474 return parameterBytes; 475 } 476 477 /** 478 * We have to save/restore the non-volatile registers around syscalls, 479 * to protect ourselves from malicious C compilers and Linux kernels.<p> 480 * 481 * Although the register allocator is not yet ready to insert these 482 * spills, allocate space on the stack in preparation.<p> 483 * 484 * For now, we naively save/restore all nonvolatiles. 485 */ 486 public static void allocateSpaceForSysCall(IR ir) { 487 StackManager sm = (StackManager) ir.stackManager; 488 489 // add one to account for the processor register. 490 int nToSave = PhysicalRegisterSet.getNumberOfNonvolatileGPRs() + 1; 491 492 sm.allocateSpaceForSysCall(nToSave); 493 } 494 495 /** 496 * Calling convention to implement calls to native (C) routines 497 * using the Linux linkage conventions.<p> 498 */ 499 public static void expandSysCall(Instruction s, IR ir) { 500 Operand ip = Call.getClearAddress(s); 501 502 // Allocate space to save non-volatiles. 503 allocateSpaceForSysCall(ir); 504 505 // Make sure we allocate enough space for the parameters to this call. 506 int numberParams = Call.getNumberOfParams(s); 507 int parameterWords = 0; 508 for (int i = 0; i < numberParams; i++) { 509 parameterWords++; 510 Operand op = Call.getParam(s, i); 511 parameterWords += op.getType().getStackWords(); 512 } 513 // allocate space for each parameter, plus one word on the stack to 514 // hold the address of the callee. 515 ir.stackManager.allocateParameterSpace((1 + parameterWords) * 4); 516 517 // Convert to a SYSCALL instruction with a null method operand. 518 Call.mutate0(s, SYSCALL, Call.getClearResult(s), ip, null); 519 } 520 521 /** 522 * Count the number of FPR parameters in a call instruction. 523 */ 524 private static int countFPRParams(Instruction call) { 525 int result = 0; 526 // walk over the parameters 527 int numParams = MIR_Call.getNumberOfParams(call); 528 for (int i = 0; i < numParams; i++) { 529 Operand param = MIR_Call.getParam(call, i); 530 if (param.isRegister()) { 531 RegisterOperand symb = (RegisterOperand) param; 532 if (symb.getType().isFloatType() || symb.getType().isDoubleType()) { 533 result++; 534 } 535 } 536 } 537 return result; 538 } 539 540 /** 541 * Count the number of FPR parameters in a prologue instruction. 542 */ 543 private static int countFPRParamsInPrologue(Instruction p) { 544 int result = 0; 545 // walk over the parameters 546 for (Enumeration<Operand> e = p.getDefs(); e.hasMoreElements();) { 547 Operand param = e.nextElement(); 548 if (param.isRegister()) { 549 RegisterOperand symb = (RegisterOperand) param; 550 if (symb.getType().isFloatType() || symb.getType().isDoubleType()) { 551 result++; 552 } 553 } 554 } 555 return result; 556 } 557 558 /** 559 * Expand the prologue instruction. 560 */ 561 private static void expandPrologue(IR ir) { 562 boolean useDU = ir.options.getOptLevel() >= 1; 563 if (useDU) { 564 // set up register lists for dead code elimination. 565 DefUse.computeDU(ir); 566 } 567 568 Instruction p = ir.firstInstructionInCodeOrder(). 569 nextInstructionInCodeOrder(); 570 if (VM.VerifyAssertions) VM._assert(p.operator == IR_PROLOGUE); 571 Instruction start = p.nextInstructionInCodeOrder(); 572 PhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet(); 573 574 int gprIndex = 0; 575 int fprIndex = 0; 576 int paramByteOffset = ir.incomingParameterBytes() + 8; 577 578 // count the number of FPR params in a pre-pass 579 int FPRRegisterParams = countFPRParamsInPrologue(p); 580 FPRRegisterParams = Math.min(FPRRegisterParams, PhysicalRegisterSet.getNumberOfFPRParams()); 581 ir.MIRInfo.fpStackHeight = Math.max(ir.MIRInfo.fpStackHeight, FPRRegisterParams); 582 583 // deal with each parameter 584 for (Enumeration<Operand> e = p.getDefs(); e.hasMoreElements();) { 585 RegisterOperand symbOp = (RegisterOperand) e.nextElement(); 586 TypeReference rType = symbOp.getType(); 587 if (rType.isFloatType() || rType.isDoubleType()) { 588 int size = rType.isFloatType() ? 4 : 8; 589 paramByteOffset -= size; 590 // if optimizing, only define the register if it has uses 591 if (!useDU || symbOp.getRegister().useList != null) { 592 if (fprIndex < PhysicalRegisterSet.getNumberOfFPRParams()) { 593 // insert a MOVE symbolic register = parameter 594 // Note that if k FPRs are passed in registers, 595 // the 1st goes in F(k-1), 596 // the 2nd goes in F(k-2), etc... 597 if (ArchConstants.SSE2_FULL) { 598 Register param = phys.getFPRParam(fprIndex); 599 if (rType.isFloatType()) { 600 start.insertBefore(MIR_Move.create(IA32_MOVSS, symbOp.copyRO(), F(param))); 601 } else { 602 start.insertBefore(MIR_Move.create(IA32_MOVSD, symbOp.copyRO(), D(param))); 603 } 604 } else { 605 Register param = phys.getFPRParam(FPRRegisterParams - fprIndex - 1); 606 start.insertBefore(MIR_Move.create(IA32_FMOV, symbOp.copyRO(), D(param))); 607 } 608 } else { 609 Operand M = new StackLocationOperand(true, paramByteOffset, size); 610 if (ArchConstants.SSE2_FULL) { 611 if (rType.isFloatType()) { 612 start.insertBefore(MIR_Move.create(IA32_MOVSS, symbOp.copyRO(), M)); 613 } else { 614 start.insertBefore(MIR_Move.create(IA32_MOVSD, symbOp.copyRO(), M)); 615 } 616 } else { 617 start.insertBefore(MIR_Move.create(IA32_FMOV, symbOp.copyRO(), M)); 618 } 619 } 620 } 621 fprIndex++; 622 } else { 623 // if optimizing, only define the register if it has uses 624 paramByteOffset -= 4; 625 if (!useDU || symbOp.getRegister().useList != null) { 626 // t is object, 1/2 of a long, int, short, char, byte, or boolean 627 if (gprIndex < PhysicalRegisterSet.getNumberOfGPRParams()) { 628 // to give the register allocator more freedom, we 629 // insert two move instructions to get the physical into 630 // the symbolic. First a move from the physical to a fresh temp 631 // before start and second a move from the temp to the 632 // 'real' parameter symbolic after start. 633 RegisterOperand tmp = ir.regpool.makeTemp(TypeReference.Int); 634 Register param = phys.getGPRParam(gprIndex); 635 RegisterOperand pOp = new RegisterOperand(param, rType); 636 start.insertBefore(PhysicalRegisterTools.makeMoveInstruction(tmp, pOp)); 637 Instruction m2 = PhysicalRegisterTools.makeMoveInstruction(symbOp.copyRO(), tmp.copyD2U()); 638 start.insertBefore(m2); 639 start = m2; 640 } else { 641 Operand M = new StackLocationOperand(true, paramByteOffset, 4); 642 start.insertBefore(MIR_Move.create(IA32_MOV, symbOp.copyRO(), M)); 643 } 644 } 645 gprIndex++; 646 } 647 } 648 649 if (VM.VerifyAssertions && paramByteOffset != 8) { 650 VM._assert(VM.NOT_REACHED, "pb = " + paramByteOffset + "; expected 8"); 651 } 652 653 // Now that we've made the calling convention explicit in the prologue, 654 // set IR_PROLOGUE to have no defs. 655 p.replace(Prologue.create(IR_PROLOGUE, 0)); 656 } 657 }