for (int i = FIRST_AIX_VOLATILE_GPR; i <= LAST_AIX_VOLATILE_GPR; i++) {
for (int i = FIRST_OS_PARAMETER_GPR; i <= LAST_OS_PARAMETER_GPR; i++) {
  static void generateGlueCodeForJNIMethod(VM_Assembler asm, VM_Method mth) {    int offset;    asm.emitSTU(FP,-JNI_GLUE_FRAME_SIZE,FP);     // buy the glue frame    // we may need to save CR in the previous frame also if CR will be used    // CR is to be saved at FP+4 in the previous frame    // Here we check if this is a JNI function that takes the vararg in the ... style    // This includes CallStatic<type>Method, Call<type>Method, CallNonVirtual<type>Method    // For these calls, the vararg starts at the 4th or 5th argument (GPR 6 or 7)    // So, we save the GPR 6-10 and FPR 1-3 in a volatile register save area     // in the glue stack frame so that the JNI function can later repackage the arguments    // based on the parameter types of target method to be invoked.    // (For long argument lists, the additional arguments, have been saved in    // the spill area of the AIX caller, and will be retrieved from there.)    //    // If we are compiling such a JNI Function, then emit the code to store    // GPR 4-10 and FPR 1-6 into the volatile save area.    String mthName = mth.getName().toString();    if ((mthName.startsWith("Call") && mthName.endsWith("Method")) ||	mthName.equals("NewObject")) {	offset = STACKFRAME_HEADER_SIZE + 12;   // skip over slots for GPR 3-5	for (int i = 6; i <= 10; i++ ) {	    asm.emitST (i, offset, FP);	    offset+=4;	}	// store FPRs 1-3 in first 3 slots of volatile FPR save area	for (int i = 1; i <= 3; i++) {	    asm.emitSTFD (i, offset, FP);	    offset+=8;	}    }    // Save AIX non-volatile GRPs and FPRs that will not be saved and restored    // by RVM. These are GPR 13-16 & FPR 14-15.    //    offset = STACKFRAME_HEADER_SIZE + 80;   // skip 20 word volatile reg save area    for (int i = 13; i <= 16; i++) {      asm.emitST (i, offset, FP);      offset += 4;    }    for (int i = 14; i <= 15; i++) {      asm.emitSTFD (i, offset, FP);      offset +=8;    }     // set the method ID for the glue frame    // and save the return address in the previous frame    //    asm.emitLVAL(S0, INVISIBLE_METHOD_ID);    asm.emitMFLR(0);    asm.emitST  (S0, STACKFRAME_METHOD_ID_OFFSET, FP);    asm.emitST  (0, JNI_GLUE_FRAME_SIZE + STACKFRAME_NEXT_INSTRUCTION_OFFSET, FP);    int CR_OFFSET = 4; // Save CR in caller's frame; see page 162 of PPC Compiler Writer's Guide    asm.emitMFCR (S0);    asm.emitST (S0, JNI_GLUE_FRAME_SIZE + CR_OFFSET, FP);    // change the vpStatus of the current Processor to "in Java", if GC has started     // and we are "blocked_in_native" then loop doing sysYields until GC done and the    // processor is unblocked.  With default jni, we can also be "blocked_in_native"    // if the running thread has been detected as "stuck" and is being moved to a    // native processor.    //    // on entry T0 = JNI Function Ptr (Handle) which should point into the array of function ptrs    // the next word in that array contains the address of the current processors vpStatus word    //    // AIX non volatile gprs 13-16 have been saved & are available (also gprs 11-13 can be used).    // S0=13, SP=14, TI=15, PROCESSOR_REGISTER=16 are available (&have labels) for changing state.    // ...it would be nice to leave the passed arguments untouched, unless we are blocked    // and have to call sysVirtualProcessorYield    int label0    = asm.getMachineCodeIndex();	                    // inst index of the following instr    asm.emitL     (TI, 4, T0);      // TI <- addr of processors vpStatus, from JNI function Ptr array    asm.emitLWARX (S0, 0, TI);      // get status for processor    asm.emitCMPI  (S0, VM_Processor.BLOCKED_IN_NATIVE);       // check if GC in progress, blocked in native mode    VM_ForwardReference frBlocked = asm.emitForwardBC(EQ);    asm.emitCAL   (S0,  VM_Processor.IN_JAVA, 0 );            // S0  <- new state value    asm.emitSTWCXr(S0,  0, TI);                               // attempt to change state to native    asm.emitBC    (NE, label0);                               // br if failure -retry lwarx by jumping to label0    VM_ForwardReference frInJava = asm.emitForwardB();        // branch around code to call sysYield    // branch to here if blocked in native, call sysVirtulaProcessorYield (AIX pthread yield)    // must save AIX volatile gprs & fprs before the call and restore after    //    frBlocked.resolve(asm);    offset = STACKFRAME_HEADER_SIZE;    // save volatile GPRS 3-10    for (int i = FIRST_AIX_VOLATILE_GPR; i <= LAST_AIX_VOLATILE_GPR; i++) {      asm.emitST (i, offset, FP);      offset+=4;    }    // save volatile FPRS 1-6    for (int i = FIRST_AIX_VOLATILE_FPR; i <= 6; i++) {      asm.emitSTFD (i, offset, FP);      offset+=8;    }    // note JTOC is the RVM JTOC, set by native code when it branched thru the    // JNI function pointer to this code    asm.emitL     (SP, VM_Entrypoints.the_boot_recordField.getOffset(), JTOC); // get boot record address    asm.emitCAL   (PROCESSOR_REGISTER, 0, JTOC);                    // save JTOC for later    asm.emitL     (JTOC, VM_Entrypoints.sysTOCField.getOffset(), SP);          // load TOC for syscalls from bootrecord    asm.emitL     (TI,   VM_Entrypoints.sysVirtualProcessorYieldIPField.getOffset(), SP);  // load addr of function    asm.emitMTLR  (TI);    asm.emitBLRL();                                                 // call sysVirtualProcessorYield in sys.C    asm.emitCAL   (JTOC, 0,PROCESSOR_REGISTER);                     // restore RVM JTOC    // restore the saved volatile GPRs 3-10 and FPRs 1-6    offset = STACKFRAME_HEADER_SIZE;    // restore volatile GPRS 3-10     for (int i = FIRST_AIX_VOLATILE_GPR; i <= LAST_AIX_VOLATILE_GPR; i++) {      asm.emitL  (i, offset, FP);      offset+=4;    }    // restore volatile FPRS 1-6      for (int i = FIRST_AIX_VOLATILE_FPR; i <= 6; i++) {      asm.emitLFD (i, offset, FP);      offset+=8;    }    asm.emitB (label0);  // br back to label0 to try lwarx again    // NOW_IN_JAVA:    // branch to here, after setting status to IN_JAVA    //    // GC is not in progress - so we can now reference moveable objects in the heap,    // such as JNIEnvironment, VM_Thread, VM_Processor.    //    // T0 = the address of running threads entry in the jnifunctionpointers array    // (as of 11/16/00 each thread gets 2 words in this array)    // compute offset into this array, use this divieded by 2 as offset in threads array,    // load VM_Thread, and from it load the jniEnv pointer.    // ...use TI and PROCESSOR_REGISTER as temps for a while    // ...JTOC is now the RVM JTOC    //    frInJava.resolve(asm);    asm.emitL  (TI, VM_Entrypoints.JNIFunctionPointersField.getOffset(), JTOC);    asm.emitSF (TI, TI, T0);                                         // TI <- byte offset into funcPtrs array    asm.emitSRAI (TI, TI, 1);                                        // divide by 2    asm.emitL  (PROCESSOR_REGISTER, VM_Entrypoints.threadsField.getOffset(), JTOC);    asm.emitA  (TI, PROCESSOR_REGISTER, TI);    asm.emitL  (TI, 0, TI);                                                  // TI <- address of VM_Thread     asm.emitL  (T0, VM_Entrypoints.jniEnvField.getOffset(), TI);                        // T0 <- JNIEnv ref (a REAL ref)    // get pointer to top java frame from JNIEnv, compute offset from current    // frame pointer (offset to avoid more interior pointers) and save offset    // in this glue frame    //    asm.emitL  (TI, VM_Entrypoints.JNITopJavaFPField.getOffset(), T0);     // get addr of top java frame from JNIEnv    asm.emitSF (TI, FP, TI);                                    // TI <- offset from current FP    asm.emitST (TI, JNI_GLUE_FRAME_SIZE-4, FP);                 // store offset at end of glue frame    // load TI & PR registers from JNIEnv before calling Java JNI Function    asm.emitL  (TI, VM_Entrypoints.JNIEnvSavedTIField.getOffset(), T0);      asm.emitL  (PROCESSOR_REGISTER, VM_Entrypoints.JNIEnvSavedPRField.getOffset(), T0);      // check if now running on a native processor, if so we have to    // transfer back to a blue/RVM processor (via call to becomeRVM)    //    asm.emitL     (S0, VM_Entrypoints.processorModeField.getOffset(), PROCESSOR_REGISTER); // get processorMode    asm.emitCMPI  (S0, VM_Processor.RVM);                // are we still on blue processor    VM_ForwardReference frBlue2 = asm.emitForwardBC(EQ); // skip transfer to blue if on blue    // save volatile GPRs 3-10 and FPRs 1-6 before calling becomeRVMThread    offset = STACKFRAME_HEADER_SIZE;    // save volatile GPRS 3-10     for (int i = FIRST_AIX_VOLATILE_GPR; i <= LAST_AIX_VOLATILE_GPR; i++) {      asm.emitST (i, offset, FP);      offset+=4;    }    // save volatile FPRS 1-6    for (int i = FIRST_AIX_VOLATILE_FPR; i <= 6; i++) {      asm.emitSTFD (i, offset, FP);      offset+=8;    }    // Branch to becomeRVMThread:  we will yield and get rescheduled to execute     // on a regular VM_Processor for Java code.  At this point PR, TI & JTOC    // are valid for executing Java    //    asm.emitLtoc  (S0, VM_Entrypoints.becomeRVMThreadMethod.getOffset());  // always 2 instructions    asm.emitMTLR  (S0);    asm.emitBLRL  ();         // At this point, we have resumed execution in a RVM VM_Processor    // The PR register now points to this VM_Processor.  TI & JTOC are still valid.    // restore the saved volatile GPRs 3-10 and FPRs 1-6    offset = STACKFRAME_HEADER_SIZE;    // restore volatile GPRS 3-10    for (int i = FIRST_AIX_VOLATILE_GPR; i <= LAST_AIX_VOLATILE_GPR; i++) {      asm.emitL  (i, offset, FP);      offset+=4;    }    // restore volatile FPRS 1-6    for (int i = FIRST_AIX_VOLATILE_FPR; i <= 6; i++) {      asm.emitLFD (i, offset, FP);      offset+=8;    }    // branch to here if making jni call on RVM/blue processor	    frBlue2.resolve(asm);    // BRANCH TO THE PROLOG FOR THE JNI FUNCTION    VM_ForwardReference frNormalPrologue = asm.emitForwardBL();    // relative branch and link past the following epilog, to the normal prolog of the method    // the normal epilog of the method will return to the epilog here to pop the glue stack frame    // RETURN TO HERE FROM EPILOG OF JNI FUNCTION    // CAUTION:  START OF EPILOG OF GLUE CODE    // The section of code from here to "END OF EPILOG OF GLUE CODE" is nestled between    // the glue code prolog and the real JNI code.    // T0 & T1 (R3 & R4) or F1 contain the return value from the function - DO NOT USE    // assume: JTOC, TI, and PROCESSOR_REG are valid, and all RVM non-volatile     // GPRs and FPRs have been restored.  Our processor state should be ...IN_JAVA so     // it is OK to use saved refs to moveable objects (ie. PROCESSOR_REG)    // establish T2 -> current threads JNIEnv structure, from activeThread field    // of current processor          asm.emitL (T2, VM_Entrypoints.activeThreadField.getOffset(), PROCESSOR_REGISTER);   // T2 <- activeThread of PR    asm.emitL (T2, VM_Entrypoints.jniEnvField.getOffset(), T2);                         // T2 <- JNIEnvironment     // before returning to C, set pointer to top java frame in JNIEnv, using offset    // saved in this glue frame during transition from C to Java.  GC will use this saved    // frame pointer if it is necessary to do GC with a processors active thread    // stuck (and blocked) in native C, ie. GC starts scanning the threads stack at that frame.    //    asm.emitL  (T3, JNI_GLUE_FRAME_SIZE-4, FP);                 // load offset from FP to top java frame    asm.emitA  (T3, FP, T3);                                    // T3 <- address of top java frame    asm.emitST (T3, VM_Entrypoints.JNITopJavaFPField.getOffset(), T2);     // store TopJavaFP back into JNIEnv    // Check if nativeAffinity is set:      // -if yes, the caller is via CreateJavaVM or AttachCurrentThread    //  from an external pthread and control must be returned to the C program there    // -If no, return to C can be done on the current processor    asm.emitL (S0, VM_Entrypoints.activeThreadField.getOffset(), PROCESSOR_REGISTER);   // T2 <- activeThread of PR    asm.emitL (S0, VM_Entrypoints.nativeAffinityField.getOffset(), S0);                 // T2 <- nativeAffinity     asm.emitCMPI (S0, 0);    VM_ForwardReference fr6 = asm.emitForwardBC(EQ);    // check to see if this frame address is the sentinal since there may be no further Java frame below    asm.emitCMPI (T3, VM_Constants.STACKFRAME_SENTINAL_FP);    VM_ForwardReference fr5 = asm.emitForwardBC(NE);        // save result GPRS 3-4  and FPRS 1    offset = STACKFRAME_HEADER_SIZE;    asm.emitST (T0, offset, FP);    asm.emitST (T1, offset+4, FP);    asm.emitST (T2, offset+8, FP);    asm.emitST (T3, offset+12, FP);    asm.emitSTFD (FIRST_AIX_VOLATILE_FPR, offset+16, FP);    // Branch to becomeNativeThread:  we will yield and get rescheduled to execute     // on a VM_Processor for the external pthread code.    //    asm.emitLtoc  (S0, VM_Entrypoints.becomeNativeThreadMethod.getOffset());  // always 2 instructions    asm.emitMTLR  (S0);    asm.emitBLRL  ();    // restore result GPRS 3-4  and FPRS 1    offset = STACKFRAME_HEADER_SIZE;    asm.emitL (T0, offset, FP);    asm.emitL (T1, offset+4, FP);    asm.emitL (T2, offset+8, FP);    asm.emitL (T3, offset+12, FP);    asm.emitLFD (FIRST_AIX_VOLATILE_FPR, offset+16, FP);    // While in Java (JNI Function), on a RVM Processor, we allow the thread to be migrated    // to a different Processor. Thus the current processor when returning from Java back    // may be different from the processor when calling the Java JNI Function. We therefore    // must update the saved processor registers, in the threads JNIEnvironment and in the    // preceeding "Java to C" transition frame.    // Note: must be done after the possible call to becomeNativeThread to pick up the right PR value    //    // update the saved PR of the frame if TopJavaFP is valid (branch here from check above)    fr6.resolve(asm);    fr5.resolve(asm);        // check to see if this frame address is the sentinal since there may be no further Java frame below    asm.emitCMPI (T3, VM_Constants.STACKFRAME_SENTINAL_FP);    VM_ForwardReference fr4 = asm.emitForwardBC(EQ);    asm.emitL  (S0, 0, T3);                   // get fp for caller of prev J to C transition frame    asm.emitST (PROCESSOR_REGISTER, -JNI_PR_OFFSET, S0);  // store PR back into transition frame    fr4.resolve(asm);    asm.emitST (PROCESSOR_REGISTER, VM_Entrypoints.JNIEnvSavedPRField.getOffset(), T2);  // store PR back into JNIEnv    // change the state of the VP to "in Native". With default jni transitions to    // native C from Java ALWAYS start on a blue/RVM Processor (status = IN_JAVA)    // and are never "BLOCKED_IN_JAVA"    //    asm.emitL     (T3, VM_Entrypoints.vpStatusAddressField.getOffset(), PROCESSOR_REGISTER); // T3 gets addr vpStatus word    asm.emitCAL   (S0,  VM_Processor.IN_NATIVE, 0 );              // S0  <- new status value    asm.emitST    (S0,  0, T3);                                   // change state to native    asm.emitL     (S0, JNI_GLUE_FRAME_SIZE + CR_OFFSET, FP);    asm.emitMTCRF (0xff, S0);    // Restore those AIX nonvolatile registers saved in the prolog above    // Here we only save & restore ONLY those registers not restored by RVM    //    offset = STACKFRAME_HEADER_SIZE + 80;   // skip 20 word volatile reg save area    for (int i = 13; i <= 16; i++) {      asm.emitL  (i, offset, FP);                     // 4 instructions      offset += 4;    }    for (int i = 14; i <= 15; i++) {      asm.emitLFD  (i, offset, FP);                   // 2 instructions      offset +=8;    }    // pop frame    asm.emitCAL(FP, JNI_GLUE_FRAME_SIZE, FP);    // load return address & return to caller    // T0 & T1 (or F1) should still contain the return value    //    asm.emitL(T2, STACKFRAME_NEXT_INSTRUCTION_OFFSET, FP);    asm.emitMTLR(T2);    asm.emitBLR (); // branch always, through link register    //END OF EPILOG OF GLUE CODE    frNormalPrologue.resolve(asm);  } 