.global asm_handle_exception
.global asm_handle_nat_exception
+ .global asm_patcher_wrapper
.global asm_abstractmethoderror
/* XXX: leave the register window open for handle_exception ??? */
+/* asm_patcher_wrapper *********************************************************
+
+ XXX
+
+ Stack layout, when called from patcher stub
+ 40 return address into JIT code (patch position)
+ 32 pointer to virtual java_objectheader
+ 24 machine code (which is patched back later)
+ 16 unresolved class/method/field reference
+ 8 data segment displacement from load instructions
+ 0 patcher function pointer to call
+ -128 WINSAVE REGS (current SP)
+
+*******************************************************************************/
+
+
+asm_patcher_wrapper:
+ /* get pv and ra from current window */
+ mov ra_callee,temp4
+ mov pv_callee,temp5
+
+ /* create window and stack frame */
+ save %sp,-((FLT_ARG_CNT+FLT_TMP_CNT+ABICALL_OFF+4)*8),%sp
+
+ SAVE_FLOAT_ARGUMENT_REGISTERS(ABICALL_OFF)
+ SAVE_FLOAT_TEMPORARY_REGISTERS(ABICALL_OFF+FLT_ARG_CNT)
+
+ mov itmp1,%l0 /* save itmp1 */
+ mov itmp2,%l1 /* save itmp2 */
+
+ add %fp,USESTACK,%o0 /* pass pseudo SP */
+ mov temp5,%o1 /* pass PV */
+ mov temp4,%o2 /* pass RA (correct for leafs) */
+ call patcher_wrapper
+ nop
+
+ RESTORE_FLOAT_ARGUMENT_REGISTERS(ABICALL_OFF)
+ RESTORE_FLOAT_ARGUMENT_REGISTERS(ABICALL_OFF+FLT_ARG_CNT)
+
+ mov %l0,itmp1 /* restore itmp1 */
+ mov %l1,itmp2 /* restore itmp2 */
+
+ brnz %o0,L_asm_patcher_wrapper_exception
+
+ /* load RA (patch position from patcher data on the stack */
+ ldx [%fp+USESTACK+5*8],itmp3
+
+ /* remove window and stack frame (and stack space allocated in the stub code */
+ restore %fp,6*8,%sp /* (source regs refer to old window, rd to new window) */
+
+ jmpl itmp3,zero /* jump to newly patched code */
+
+L_asm_patcher_wrapper_exception:
+ mov itmp3,xptr_itmp2 /* get exception */
+ ldx [%fp+USESTACK+5*8],xpc_itmp3 /* xpc is RA */
+ restore %fp,6*8,%sp /* remove stack frame */
+ ba asm_handle_exception
+ nop
+
+
asm_getclassvalues_atomic:
_crit_restart:
_crit_begin:
/* prepare data structures for native function call */
- M_MOV(REG_FP, REG_OUT0); /* top of the stack frame */
+ M_ADD_IMM(REG_FP, BIAS, REG_OUT0); /* top of the stack frame, absolute*/
M_MOV(REG_PV_CALLEE, REG_OUT1);
M_MOV(REG_FP, REG_OUT2); /* java sp */
M_MOV(REG_RA_CALLEE, REG_OUT3);
#include "vm/jit/jit.h"
#include "vm/jit/replace.h"
+/* how to leaf optimization in the emitted stubs?? */
+#define REG_PV REG_PV_CALLEE
+
/* emit_load *******************************************************************
void emit_patcher_stubs(jitdata *jd)
{
+ codegendata *cd;
+ patchref *pref;
+ u4 mcode[2];
+ u1 *savedmcodeptr;
+ u1 *tmpmcodeptr;
+ s4 targetdisp;
+ s4 disp;
+
+ /* 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 2 instruction words long. */
+
+ tmpmcodeptr = (u1 *) (cd->mcodebase + pref->branchpos);
+
+ /* We use 2 loads here as an unaligned 8-byte read on 64-bit
+ SPARC causes a SIGSEGV */
+
+ mcode[0] = ((u4 *) tmpmcodeptr)[0];
+ mcode[1] = ((u4 *) tmpmcodeptr)[1];
+
+ /* 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 = ((u4 *) savedmcodeptr) - (((u4 *) tmpmcodeptr) + 1);
+/* XXX TODO imm?? */
+ if ((disp < (s4) 0xffff8000) || (disp > (s4) 0x00007fff)) {
+ *exceptionptr =
+ new_internalerror("Jump offset is out of range: %d > +/-%d",
+ disp, 0x00007fff);
+ return;
+ }
+
+ M_BR(disp);
+ M_NOP;
+
+ cd->mcodeptr = savedmcodeptr; /* restore the current mcodeptr */
+
+ /* extend stack frame for wrapper data */
+
+ M_ASUB_IMM(REG_SP, 6 * 8, REG_SP);
+
+ /* calculate return address and move it onto the stack */
+
+ M_LDA(REG_ITMP3, REG_PV, pref->branchpos);
+ M_AST(REG_ITMP3, REG_SP, USESTACK + 5 * 8);
+
+ /* move pointer to java_objectheader onto stack */
+
+#if defined(ENABLE_THREADS)
+ /* create a virtual java_objectheader */
+
+ (void) dseg_addaddress(cd, NULL); /* flcword */
+ (void) dseg_addaddress(cd, lock_get_initial_lock_word());
+ disp = dseg_addaddress(cd, NULL); /* vftbl */
+
+ M_LDA(REG_ITMP3, REG_PV, disp);
+ M_AST(REG_ITMP3, REG_SP, USESTACK + 4 * 8);
+#else
+ /* do nothing */
+#endif
+
+ /* move machine code onto stack */
+
+ disp = dseg_adds4(cd, mcode[0]);
+ M_ILD(REG_ITMP3, REG_PV, disp);
+ M_IST(REG_ITMP3, REG_SP, USESTACK + 3 * 8);
+
+ disp = dseg_adds4(cd, mcode[1]);
+ M_ILD(REG_ITMP3, REG_PV, disp);
+ M_IST(REG_ITMP3, REG_SP, USESTACK + 3 * 8 + 4);
+
+ /* move class/method/field reference onto stack */
+
+ disp = dseg_addaddress(cd, pref->ref);
+ M_ALD(REG_ITMP3, REG_PV, disp);
+ M_AST(REG_ITMP3, REG_SP, USESTACK + 2 * 8);
+
+ /* move data segment displacement onto stack */
+
+ disp = dseg_adds4(cd, pref->disp);
+ M_ILD(REG_ITMP3, REG_PV, disp);
+ M_IST(REG_ITMP3, REG_SP, USESTACK + 1 * 8);
+
+ /* move patcher function pointer onto stack */
+
+ disp = dseg_addaddress(cd, pref->patcher);
+ M_ALD(REG_ITMP3, REG_PV, disp);
+ M_AST(REG_ITMP3, REG_SP, USESTACK + 0 * 8);
+
+ if (targetdisp == 0) {
+ targetdisp = ((u4 *) cd->mcodeptr) - ((u4 *) cd->mcodebase);
+
+ disp = dseg_addaddress(cd, asm_patcher_wrapper);
+ M_ALD(REG_ITMP3, REG_PV, disp);
+ M_JMP(REG_ZERO, REG_ITMP3, REG_ZERO);
+ M_NOP;
}
+ else {
+ disp = (((u4 *) cd->mcodebase) + targetdisp) -
+ (((u4 *) cd->mcodeptr) + 1);
+
+ M_BR(disp);
+ M_NOP;
+ }
+ }
+}
+
/* emit_replacement_stubs ******************************************************
/* md_return_alloc *************************************************************
- Precolor the Java Stackelement containing the Return Value. Since
- alpha has a dedicated return register (not an reused arg or
- reserved reg), this is striaghtforward possible, as long, as this
- stackelement does not have to survive a method invokation
- (SAVEDVAR)
-
- --- in
- m: Methodinfo of current method
- return_type: Return Type of the Method (TYPE_INT.. TYPE_ADR)
- TYPE_VOID is not allowed!
- stackslot: Java Stackslot to contain the Return Value
-
- --- out
- if precoloring was possible:
- stackslot->varkind =ARGVAR
- ->varnum =-1
- ->flags =0
- ->regoff =[REG_RESULT, REG_FRESULT]
+ XXX
*******************************************************************************/
void md_return_alloc(jitdata *jd, stackptr stackslot)
{
- methodinfo *m;
- methoddesc *md;
-
- assert(0);
-
- /* get required compiler data */
-
- m = jd->m;
-
- md = m->parseddesc;
-
- /* Only precolor the stackslot, if it is not a SAVEDVAR <-> has
- not to survive method invokations. */
-
-
- if (!(stackslot->flags & SAVEDVAR)) {
- stackslot->varkind = ARGVAR;
- stackslot->varnum = -1;
- stackslot->flags = 0;
-
- if (IS_INT_LNG_TYPE(md->returntype.type)) {
- stackslot->regoff = REG_RESULT_CALLEE;
- } else { /* float/double */
- stackslot->regoff = REG_FRESULT;
- }
- }
+ /* XXX */
}
#define ABI_PARAMARRAY_SLOTS 6
#define WINSAVE_CNT 16 /* number of regs that SPARC saves onto stack */
-#define ABICALL_OFF 22 /* 8-byte slots for save regs and arg slots */
+#define ABICALL_PARAMS 6 /* param slots the ABI always requires */
+#define ABICALL_OFF 22 /* 8-byte slots for save regs and param slots */
#define BIAS 2047
#define USESTACK (WINSAVE_CNT * 8 + BIAS)
#define USESTACK_PARAMS ((WINSAVE_CNT + ABI_PARAMARRAY_SLOTS) * 8 + BIAS)
#define itmp2 %g2
#define itmp3 %g3
+/* PLT unsafe temp regs */
+#define temp4 %g4
+#define temp5 %g5
+
#define mptr_itmp2 itmp2
#define xptr_itmp2 itmp2
}
+/* md_codegen_patch_branch *****************************************************
+
+ Back-patches a branch instruction.
+
+*******************************************************************************/
+
+void md_codegen_patch_branch(codegendata *cd, s4 branchmpc, s4 targetmpc)
+{
+ s4 *mcodeptr;
+ s4 mcode;
+ s4 disp; /* branch displacement */
+
+ assert(0);
+
+ /* calculate the patch position */
+
+ mcodeptr = (s4 *) (cd->mcodebase + branchmpc);
+
+ /* get the instruction before the exception point */
+
+ mcode = mcodeptr[-1];
+
+ /* check for BPcc instruction */
+ if (((mcode >> 16) & 0xc1c0) != 0x0040)
+ assert(0);
+
+ /* Calculate the branch displacement. For branches we need a
+ displacement relative and shifted to the branch PC. */
+
+ disp = (targetmpc - branchmpc) >> 2;
+
+ /* check branch displacement */
+
+ if ((disp < (s4) 0xfffc0000) || (disp > (s4) 0x003ffff))
+ vm_abort("branch displacement is out of range: %d > +/-%d", disp, 0x003ffff);
+
+ /* patch the branch instruction before the mcodeptr */
+
+ mcodeptr[-1] |= (disp & 0x003ffff);
+}
+
+
/* md_stacktrace_get_returnaddress *********************************************
Returns the return address of the current stackframe, specified by
#include "vm/jit/asmpart.h"
#include "vm/jit/patcher.h"
+#include "vm/jit/sparc64/md-abi.h"
+
/* patcher_wrapper *************************************************************
{
stackframeinfo sfi;
u1 *xpc;
+ u1 *javasp;
java_objectheader *o;
functionptr f;
bool result;
java_objectheader *e;
- assert(0);
/* define the patcher function */
/* enter a monitor on the patching position */
PATCHER_MONITORENTER;
+
+ /* calculate sp of the current java function considering the WINSAVE regs */
+
+ javasp = sp - 16 * 8 - BIAS;
/* create the stackframeinfo */
- stacktrace_create_extern_stackframeinfo(&sfi, pv, sp + 6 * 8, ra, xpc);
+ stacktrace_create_extern_stackframeinfo(&sfi, pv, javasp, ra, xpc);
/* call the proper patcher function */
disp = *((s4 *) (sp + 1 * 8));
pv = (u1 *) *((ptrint *) (sp + 0 * 8));
- /* calculate and set the new return address */
-
- ra = ra - 2 * 4;
- *((ptrint *) (sp + 5 * 8)) = (ptrint) ra;
+ /* return address on SPARC is address of jump, therefore correct */
/* resolve native function */