- Generates the code for the patcher stubs.
-
-*******************************************************************************/
-
-__PORTED__ void emit_patcher_stubs(jitdata *jd)
-{
-
- codegendata *cd;
- patchref *pref;
- u4 mcode;
- u1 *savedmcodeptr;
- u1 *tmpmcodeptr;
- s4 targetdisp;
- s4 disp;
- u1 *ref;
-
- /* get required compiler data */
-
- cd = jd->cd;
-
- /* generate code patching stub call code */
-
- targetdisp = 0;
-
- for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
- /* check code segment size */
-
- MCODECHECK(100);
-
- /* Get machine code which is patched back in later. The
- call is 1 instruction word long. */
-
- tmpmcodeptr = (u1 *) (cd->mcodebase + pref->branchpos);
-
- mcode = *((u4 *) tmpmcodeptr);
-
- /* Patch in the call to call the following code (done at
- compile time). */
-
- savedmcodeptr = cd->mcodeptr; /* save current mcodeptr */
- cd->mcodeptr = tmpmcodeptr; /* set mcodeptr to patch position */
-
- disp = (savedmcodeptr) - (tmpmcodeptr);
-
- if (! N_VALID_BRANCH(disp)) {
- /* Displacement overflow */
-
- /* If LONGBRANCHES is not set, the flag and the error flag */
-
- if (! CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
- cd->flags |= (CODEGENDATA_FLAG_ERROR |
- CODEGENDATA_FLAG_LONGBRANCHES);
- }
-
- /* If error flag is set, do nothing. The method has to be recompiled. */
-
- if (CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd) && CODEGENDATA_HAS_FLAG_ERROR(cd)) {
- return;
- }
- }
-
- if (CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
-
- /* Generating long branches */
-
- disp = dseg_add_s4(cd, savedmcodeptr - cd->mcodebase);
-
- M_ILD(REG_ITMP3, REG_PV, disp);
- M_AADD(REG_PV, REG_ITMP3);
-
- /* Do the branch at the end of NOP sequence.
- * This way the patch position is at a *fixed* offset
- * (PATCHER_LONGBRANCHES_NOPS_SKIP) of the return address.
- */
-
- cd->mcodeptr = tmpmcodeptr + PATCHER_LONGBRANCHES_NOPS_SKIP - SZ_BASR;
- M_JMP(REG_ITMP3, REG_ITMP3);
- } else {
-
- /* Generating short branches */
-
- M_BSR(REG_ITMP3, disp);
- }
-
- cd->mcodeptr = savedmcodeptr; /* restore the current mcodeptr */
-
- /* create stack frame */
-
- M_ASUB_IMM(6 * 4, REG_SP);
-
- /* move return address onto stack */
-
- M_AST(REG_ITMP3, REG_SP, 5 * 4);
-
- /* move pointer to java_objectheader onto stack */
-
-#if defined(ENABLE_THREADS)
- /* create a virtual java_objectheader */
-
- (void) dseg_add_unique_address(cd, NULL); /* flcword */
- (void) dseg_add_unique_address(cd, lock_get_initial_lock_word());
- disp = dseg_add_unique_address(cd, NULL); /* vftbl */
-
- M_LDA(REG_ITMP3, REG_PV, disp);
- M_AST(REG_ITMP3, REG_SP, 4 * 4);
-#else
- /* nothing to do */
-#endif
-
- /* move machine code onto stack */
-
- disp = dseg_add_s4(cd, mcode);
- M_ILD(REG_ITMP3, REG_PV, disp);
- M_IST(REG_ITMP3, REG_SP, 3 * 4);
-
- /* move class/method/field reference onto stack */
-
- disp = dseg_add_address(cd, pref->ref);
- M_ALD(REG_ITMP3, REG_PV, disp);
- M_AST(REG_ITMP3, REG_SP, 2 * 4);
-
- /* move data segment displacement onto stack */
-
- disp = dseg_add_s4(cd, pref->disp);
- M_ILD(REG_ITMP3, REG_PV, disp);
- M_IST(REG_ITMP3, REG_SP, 1 * 4);
-
- /* move patcher function pointer onto stack */
-
- disp = dseg_add_functionptr(cd, pref->patcher);
- M_ALD(REG_ITMP3, REG_PV, disp);
- M_AST(REG_ITMP3, REG_SP, 0 * 4);
-
- if (targetdisp == 0) {
- targetdisp = (cd->mcodeptr) - (cd->mcodebase);
-
- disp = dseg_add_functionptr(cd, asm_patcher_wrapper);
- M_ALD(REG_ITMP3, REG_PV, disp);
- M_JMP(RN, REG_ITMP3);
- }
- else {
- disp = ((cd->mcodebase) + targetdisp) -
- (( cd->mcodeptr) );
-
- emit_branch(cd, disp, BRANCH_UNCONDITIONAL, RN, 0);