int varargGPROffset = VARARG_AREA_OFFSET + (skip4Args ? BYTES_IN_ADDRESS : 0); int varargFPROffset = varargGPROffset + 5*BYTES_IN_ADDRESS ;
VM_Address gluecallerfp = VM_Magic.getMemoryAddress(gluefp.add(VM_Constants.STACKFRAME_FRAME_POINTER_OFFSET));
  private static VM_Address pushVarArgToSpillArea(int methodID, boolean skip4Args) throws Exception, VM_PragmaNoInline {    int glueFrameSize = JNI_GLUE_FRAME_SIZE;    // get the FP for this stack frame and traverse 2 frames to get to the glue frame    VM_Address gluefp = VM_Magic.getMemoryAddress(VM_Magic.getFramePointer().add(VM_Constants.STACKFRAME_FRAME_POINTER_OFFSET));    gluefp = VM_Magic.getMemoryAddress(gluefp.add(VM_Constants.STACKFRAME_FRAME_POINTER_OFFSET));    gluefp = VM_Magic.getMemoryAddress(gluefp.add(VM_Constants.STACKFRAME_FRAME_POINTER_OFFSET));    // compute the offset into the area where the vararg GPR[6-10] and FPR[1-3] are saved    // skipping the args which are not part of the arguments for the target method    // For Call<type>Method functions and NewObject, skip 3 args    // For CallNonvirtual<type>Method functions, skip 4 args    int varargGPROffset = VARARG_AREA_OFFSET + (skip4Args ? BYTES_IN_ADDRESS : 0);    int varargFPROffset = varargGPROffset + 5*BYTES_IN_ADDRESS ;    // compute the offset into the spill area of the native caller frame,     // skipping the args which are not part of the arguments for the target method    // For Call<type>Method functions, skip 3 args    // For CallNonvirtual<type>Method functions, skip 4 args    int spillAreaLimit  = glueFrameSize + NATIVE_FRAME_HEADER_SIZE + 8*BYTES_IN_ADDRESS;    int spillAreaOffset = glueFrameSize + NATIVE_FRAME_HEADER_SIZE +                           (skip4Args ? 4*BYTES_IN_ADDRESS : 3*BYTES_IN_ADDRESS);    // address to return pointing to the var arg list    VM_Address varargAddress = gluefp.add(spillAreaOffset);    // VM.sysWrite("pushVarArgToSpillArea:  var arg at " +     //             VM.intAsHexString(varargAddress) + "\n");     VM_Method targetMethod = VM_MemberReference.getMemberRef(methodID).asMethodReference().resolve();    VM_TypeReference[] argTypes = targetMethod.getParameterTypes();    int argCount = argTypes.length;    for (int i=0; i<argCount && spillAreaOffset<spillAreaLimit ; i++) {      VM_Word hiword, loword;      if (argTypes[i].isFloatType() || argTypes[i].isDoubleType()) {        // move 2 words from the vararg FPR save area into the spill area of the caller        hiword = VM_Magic.getMemoryWord(gluefp.add(varargFPROffset));        varargFPROffset+=BYTES_IN_ADDRESS;        if (VM.BuildFor32Addr) {          loword = VM_Magic.getMemoryWord(gluefp.add(varargFPROffset));          varargFPROffset+=BYTES_IN_ADDRESS;        }        VM_Magic.setMemoryWord(gluefp.add(spillAreaOffset), hiword);        spillAreaOffset+=BYTES_IN_ADDRESS;        if (VM.BuildFor32Addr) {          VM_Magic.setMemoryWord(gluefp.add(spillAreaOffset), loword);          spillAreaOffset+=BYTES_IN_ADDRESS;        }      }       else if (argTypes[i].isLongType()) {        // move 2 words from the vararg GPR save area into the spill area of the caller        hiword = VM_Magic.getMemoryWord(gluefp.add(varargGPROffset));        varargGPROffset+=BYTES_IN_ADDRESS;        VM_Magic.setMemoryWord(gluefp.add(spillAreaOffset), hiword);        spillAreaOffset+=BYTES_IN_ADDRESS;        // this covers the case when the long value straddles the spill boundary        if (VM.BuildFor32Addr && spillAreaOffset<spillAreaLimit) {          loword = VM_Magic.getMemoryWord(gluefp.add(varargGPROffset));          varargGPROffset+=BYTES_IN_ADDRESS;          VM_Magic.setMemoryWord(gluefp.add(spillAreaOffset), loword);          spillAreaOffset+=BYTES_IN_ADDRESS;        }      }      else {        hiword = VM_Magic.getMemoryWord(gluefp.add(varargGPROffset));        varargGPROffset+=BYTES_IN_ADDRESS;        VM_Magic.setMemoryWord(gluefp.add(spillAreaOffset), hiword);        spillAreaOffset+=BYTES_IN_ADDRESS;      }    }    // At this point, all the vararg values should be in the spill area in the caller frame    // return the address of the beginning of the vararg to use in invoking the target method    return varargAddress;  }