asmArg.emitMR(nextOSArgReg, nextVMArgReg++);
  private static void generateParameterPassingCode(VM_Assembler asm,                                            VM_TypeReference[] types,                                            int nextVMArgReg,                                            int nextVMArgFloatReg,                                            int spillOffsetVM,                                            int nextOSArgReg,                                            int nextOSArgFloatReg,                                            int spillOffsetOS                                            ) {    // create one VM_Assembler object for each argument    // This is needed for the following reason:    //   -2 new arguments are added in front for native methods, so the normal arguments    //    need to be shifted down in addition to being moved    //   -to avoid overwriting each other, the arguments must be copied in reverse order    //   -the analysis for mapping however must be done in forward order    //   -the moving/mapping for each argument may involve a sequence of 1-3 instructions     //    which must be kept in the normal order    // To solve this problem, the instructions for each argument is generated in its    // own VM_Assembler in the forward pass, then in the reverse pass, each VM_Assembler    // emist the instruction sequence and copies it into the main VM_Assembler    int numArguments = types.length;    VM_Assembler[] asmForArgs = new VM_Assembler[numArguments];        for (int arg = 0; arg < numArguments; arg++) {      //-#if RVM_FOR_OSX      int spillSizeOSX = 0;      int nextOsxGprIncrement = 1;      //-#endif            asmForArgs[arg] = new VM_Assembler(0);      VM_Assembler asmArg = asmForArgs[arg];      // For 32-bit float arguments, must be converted to      // double       //      if (types[arg].isFloatType() || types[arg].isDoubleType()) {	boolean is32bits = types[arg].isFloatType();        //-#if RVM_FOR_OSX        if (is32bits)          spillSizeOSX = 4;        else {          spillSizeOSX = 8;          nextOsxGprIncrement = 2;        }        //-#endif       	       	// 1. check the source, the value will be in srcVMArg	int srcVMArg; // scratch fpr	if (nextVMArgFloatReg <= LAST_VOLATILE_FPR) {	  srcVMArg = nextVMArgFloatReg;	  nextVMArgFloatReg ++;	} else {	  srcVMArg = FIRST_SCRATCH_FPR;	  // VM float reg is in spill area	  if (is32bits) {	    asmArg.emitLFS(srcVMArg, spillOffsetVM, FP);	    spillOffsetVM += 4;	  } else {	    asmArg.emitLFD(srcVMArg, spillOffsetVM, FP);	    spillOffsetVM += 8;	  }	}  			// 2. check the destination, 	if (nextOSArgFloatReg <= LAST_OS_PARAMETER_FPR) {	  // leave it there	  nextOSArgFloatReg ++;	} else {          //-#if RVM_FOR_LINUX          	  // spill it, round the spill address to 8	  // assuming FP is aligned to 8	  spillOffsetOS = (spillOffsetOS + 7) & -8;	  	  asmArg.emitSTFD(srcVMArg, spillOffsetOS, FP);	  spillOffsetOS += 8;          //-#elif RVM_FOR_OSX          if (is32bits) {            asmArg.emitSTFS(srcVMArg, spillOffsetOS, FP);          } else {            asmArg.emitSTFD(srcVMArg, spillOffsetOS, FP);          }          //-#endif        }	// for 64-bit long arguments      } else if (types[arg].isLongType()) {        //-#if RVM_FOR_OSX	spillSizeOSX = 8;        nextOsxGprIncrement = 2;	//-#endif		// handle OS first	boolean dstSpilling;	int regOrSpilling = -1;  // it is register number or spilling offset	// 1. check if Linux register > 9	if (nextOSArgReg > (LAST_OS_PARAMETER_GPR - 1)) {	  // goes to spilling area	  dstSpilling = true;          //-#if RVM_FOR_LINUX	  /* NOTE: following adjustment is not stated in SVR4 ABI, but 	   * was implemented in GCC.	   * -- Feng	   */	  nextOSArgReg = LAST_OS_PARAMETER_GPR + 1;	  	  // do alignment and compute spilling offset          spillOffsetOS = (spillOffsetOS + 7) & -8;	  regOrSpilling = spillOffsetOS;	  spillOffsetOS += 8;          //-#elif RVM_FOR_OSX                    regOrSpilling = spillOffsetOS;                    //-#endif	} else {	  // use registers	  dstSpilling = false;          //-#if RVM_FOR_LINUX	  // rounds to odd	  nextOSArgReg += (nextOSArgReg + 1) & 0x01; // if gpr is even, gpr += 1	  regOrSpilling = nextOSArgReg;	  nextOSArgReg += 2;          //-#elif RVM_FOR_OSX          regOrSpilling = nextOSArgReg;          //-#endif	}		// handle RVM source	if (nextVMArgReg < LAST_VOLATILE_GPR) {	  // both parts in registers	  if (dstSpilling) {	    asmArg.emitSTW(nextVMArgReg+1, regOrSpilling+4, FP);            //-#if RVM_FOR_LINUX	    asmArg.emitSTW(nextVMArgReg, regOrSpilling, FP);            //-#elif RVM_FOR_OSX            if (nextOSArgReg == LAST_OS_PARAMETER_GPR) {              asmArg.emitMR(nextOSArgReg, nextVMArgReg);             } else {              asmArg.emitSTW(nextVMArgReg, regOrSpilling, FP);            }            //-#endif	  } else {	    asmArg.emitMR(regOrSpilling+1, nextVMArgReg+1);	    asmArg.emitMR(regOrSpilling, nextVMArgReg);	  }	  // advance register counting, Linux register number	  // already advanced 	  nextVMArgReg += 2;	} else if (nextVMArgReg == LAST_VOLATILE_GPR) {	  // VM striding	  if (dstSpilling) {	    asmArg.emitLWZ(REGISTER_ZERO, spillOffsetVM, FP);	    asmArg.emitSTW(REGISTER_ZERO, regOrSpilling+4, FP);	    asmArg.emitSTW(nextVMArgReg, regOrSpilling, FP);	  } else {	    asmArg.emitLWZ(regOrSpilling + 1, spillOffsetVM, FP);	    asmArg.emitMR(regOrSpilling, nextVMArgReg);	  }	  // advance spillOffsetVM and nextVMArgReg	  nextVMArgReg ++;	  spillOffsetVM += 4;	} else if (nextVMArgReg > LAST_VOLATILE_GPR) {	  if (dstSpilling) {	    asmArg.emitLFD(FIRST_SCRATCH_FPR, spillOffsetVM, FP);	    asmArg.emitSTFD(FIRST_SCRATCH_FPR, regOrSpilling, FP);	  } else {	    // this shouldnot happen, VM spills, OS has registers	    asmArg.emitLWZ(regOrSpilling + 1, spillOffsetVM+4, FP);	    asmArg.emitLWZ(regOrSpilling, spillOffsetVM, FP);	  }		  spillOffsetVM += 8;	}      } else if (types[arg].isReferenceType() ) {        //-#if RVM_FOR_OSX	spillSizeOSX = 4;	//-#endif		// For reference type, replace with handlers before passing to AIX	int srcreg, dstreg;	if (nextVMArgReg <= LAST_VOLATILE_GPR) {	  srcreg = nextVMArgReg++;	} else {	  srcreg = REGISTER_ZERO;	  asmArg.emitLWZ(srcreg, spillOffsetVM, FP);	  spillOffsetVM += 4;	}	asmArg.emitSTWU(srcreg, 4, KLUDGE_TI_REG);		if (nextOSArgReg <= LAST_OS_PARAMETER_GPR) {	  asmArg.emitSUBFC(nextOSArgReg++, PROCESSOR_REGISTER, KLUDGE_TI_REG);	} else {	  asmArg.emitSUBFC(REGISTER_ZERO, PROCESSOR_REGISTER, KLUDGE_TI_REG);	  asmArg.emitSTW(REGISTER_ZERO, spillOffsetOS, FP);          //-#if RVM_FOR_LINUX	  spillOffsetOS += 4;          //-#endif	}      } else {        //-#if RVM_FOR_OSX	spillSizeOSX = 4;	//-#endif		// For all other types: int, short, char, byte, boolean	// (1a) fit in AIX register, move the register	if (nextOSArgReg<=LAST_OS_PARAMETER_GPR) {	  asmArg.emitMR(nextOSArgReg++, nextVMArgReg++);	}	// (1b) spill OS register, but still fit in VM register	else if (nextVMArgReg<=LAST_VOLATILE_GPR) {	  asmArg.emitSTW(nextVMArgReg++, spillOffsetOS, FP);          //-#if RVM_FOR_LINUX          spillOffsetOS += 4;          //-#endif	} else {	  // (1c) spill VM register	  asmArg.emitLWZ(REGISTER_ZERO, spillOffsetVM, FP);        // retrieve arg from VM spill area	  asmArg.emitSTW(REGISTER_ZERO, spillOffsetOS, FP);	  spillOffsetVM+=4;          //-#if RVM_FOR_LINUX	  spillOffsetOS+=4;          //-#endif	}      }      //-#if RVM_FOR_OSX      spillOffsetOS += spillSizeOSX;      nextOSArgReg += nextOsxGprIncrement;      //-#endif    }    // Append the code sequences for parameter mapping     // to the current machine code in reverse order    // so that the move does not overwrite the parameters    for (int arg = asmForArgs.length-1; arg >= 0; arg--) {      VM_MachineCode codeForArg = asmForArgs[arg].makeMachineCode();      asm.appendInstructions(codeForArg.getInstructions());    }  }