* src/vm/jit/sparc64/md-asm.h: Likewise.
* src/vm/jit/sparc64/*: implemented createnativestub, added functions for param allocation following the ABI.
#include "config.h"
+
+#include "vm/jit/sparc64/md-abi.h"
#include "offsets.h"
#include "md-asm.h"
asm_vm_call_method_exception_handler:
+
mov itmp1,%o0
call builtin_throw_exception
+ nop
return %i7 + 8 /* implicit window restore */
nop
brz pv_caller,L_asm_call_jit_compiler_exception
+ nop
/* synchronise instruction cache moved somewhere else */
mov ra_caller,xpc_itmp3 /* save return address (xpc) */
call exceptions_get_and_clear_exception
+ nop
mov xpc_itmp3,ra_caller /* restore return address (xpc) */
mov %o0,xptr_itmp2 /* get exception */
sub ra_caller,4,xpc_itmp3 /* exception address is ra - 4 */
ba L_asm_handle_nat_exception
+ nop
asm_handle_nat_exception:
L_asm_handle_nat_exception: /* required for PIC code */
+L_asm_handle_exception_stack_loop:
+ /* exception handling assumes that the current java method saved */
+ /* the caller's window */
+
+ /* get ra and pv before saving the window */
+ mov ra_callee,itmp1
+ mov pv_callee,%g4
+
+ save %sp,-176,%sp
+ mov xptr_itmp2,%l0 /* save exception pointer */
+ mov xpc_itmp3,%l1 /* save exception pc */
+ mov zero,%l2 /* save maybe-leaf flag (cleared) */
+
+ mov %l0,%o0 /* pass xptr */
+ mov %l1,%o1 /* pass xpc */
+ mov %g4,%o2 /* pass PV */
+ mov %fp,%o3 /* pass Java SP */
+
asm_handle_exception:
+ mov pv_callee,%g4
+
+ /* save bigger stack frame for float args and temps */
+ save %sp,(FLT_ARG_CNT+FLT_TMP_CNT+ABICALL_OFF)*8,%sp
+
+ SAVE_FLOAT_ARGUMENT_REGISTERS(ABICALL_OFF)
+ SAVE_FLOAT_TEMPORARY_REGISTERS(ABICALL_OFF+FLT_ARG_CNT)
+
+ mov xptr_itmp2,%l0 /* save exception pointer */
+ add zero,1,%l2 /* set maybe-leaf flag */
+
+ mov %l0,%o0 /* pass xptr */
+ mov xpc_itmp3,%o1 /* pass xpc */
+ mov %g4,%o2 /* pass PV */
+ mov %fp,%o3 /* pass Java SP */
+
+L_asm_handle_exception_continue:
+ call exceptions_handle_exception
+
+ brz %o0,L_asm_handle_exception_not_caught
+
+ mov %o0,xpc_itmp3 /* move handlerpc into xpc */
+ mov %l0,xptr_itmp2 /* restore exception pointer */
+
+ brz %l2,L_asm_handle_exception_no_leaf
+
+ RESTORE_FLOAT_ARGUMENT_REGISTERS(ABICALL_OFF)
+ RESTORE_FLOAT_TEMPORARY_REGISTERS(ABICALL_OFF+FLT_ARG_CNT)
+
+L_asm_handle_exception_no_leaf:
+ /* restore java window and stackframe (ra and pv are in there) */
+ restore
+ jmpl xpc_itmp3, zero /* jump to the handler */
+
+L_asm_handle_exception_not_caught:
+ mov %l0,xptr_itmp2 /* restore xptr */
+ restore /* free our stackframe and window */
+ /* maybe leaf flag gets cleared after branch to _loop */
+
+ restore /* unwind stack and window */
+ ba L_asm_handle_exception_stack_loop
+ mov xpc_itmp3,ra_caller /* the new xpc is ra (delay) */
- /* nothing here */
- restore zero,0,zero
/* asm_abstractmethoderror *****************************************************
if (IS_INT_LNG_TYPE(t)) { /* integer args */
if (!md->params[p].inmemory) { /* register arguments */
s2 = rd->argintregs[s1];
+ s2 = REG_WINDOW_TRANSPOSE(s2);
if (!(var->flags & INMEMORY)) { /* reg arg -> register */
M_INTMOVE(s2, var->vv.regoff);
codegen_addpatchref(cd, PATCHER_athrow_areturn,
iptr->sx.s23.s2.uc, 0);
- if (opt_showdisassemble)
- M_NOP;
+ if (opt_showdisassemble) {
+ M_NOP; M_NOP;
+ }
}
#endif /* ENABLE_VERIFIER */
codegen_addpatchref(cd, PATCHER_athrow_areturn,
iptr->sx.s23.s2.uc, 0);
- if (opt_showdisassemble)
- M_NOP;
+ if (opt_showdisassemble) {
+ M_NOP; M_NOP;
+ }
}
#endif /* ENABLE_VERIFIER */
goto nowperformreturn;
- M_RETURN(REG_RA_CALLEE); /* implicit window restore */
+ M_RETURN(REG_RA_CALLEE, 8); /* implicit window restore */
M_NOP;
ALIGNCODENOP;
}
switch (iptr->opc) {
case ICMD_BUILTIN:
- /* XXX needs manual attention! */
disp = dseg_addaddress(cd, bte->fp);
- d = md->returntype.type;
-
- M_ALD(REG_ITMP3, REG_PV, disp); /* built-in-function pointer */
- M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
- M_NOP;
-/* XXX: how do builtins handle the register window? */
-/* disp = (s4) (cd->mcodeptr - cd->mcodebase);*/
-/* M_LDA(REG_PV, REG_RA, -disp);*/
+ M_ALD(REG_PV_CALLER, REG_PV, disp); /* built-in-function pointer */
+ s1 = REG_PV_CALLER;
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- M_BEQZ(REG_RESULT_CALLER, 0);
- codegen_add_fillinstacktrace_ref(cd);
- M_NOP;
- }
break;
case ICMD_INVOKESPECIAL:
- M_BEQZ(REG_A0, 0);
+ M_BEQZ(REG_OUT0, 0);
codegen_add_nullpointerexception_ref(cd);
M_NOP;
/* fall through */
case ICMD_INVOKESTATIC:
- /* XXX needs manual attention! */
if (lm == NULL) {
disp = dseg_addaddress(cd, NULL);
else
disp = dseg_addaddress(cd, lm->stubroutine);
- M_ALD(REG_PV_CALLER, REG_PV, disp); /* method pointer in callee pv */
- M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
- M_NOP;
-/* XXX no need to restore PV, when its in the regs */
+ M_ALD(REG_PV_CALLER, REG_PV, disp); /* method pointer in pv */
+ s1 = REG_PV_CALLER;
break;
case ICMD_INVOKEVIRTUAL:
- gen_nullptr_check(REG_A0);
+ gen_nullptr_check(REG_OUT0);
if (lm == NULL) {
codegen_addpatchref(cd, PATCHER_invokevirtual, um, 0);
s1 = OFFSET(vftbl_t, table[0]) +
sizeof(methodptr) * lm->vftblindex;
- M_ALD(REG_METHODPTR, REG_A0,
+ M_ALD(REG_METHODPTR, REG_OUT0,
OFFSET(java_objectheader, vftbl));
M_ALD(REG_PV_CALLER, REG_METHODPTR, s1);
- M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
- M_NOP;
-/* XXX no need to restore PV, when its in the regs */
+ s1 = REG_PV_CALLER;
break;
case ICMD_INVOKEINTERFACE:
- /* XXX needs manual attention! */
gen_nullptr_check(rd->argintregs[0]);
if (lm == NULL) {
s2 = sizeof(methodptr) * (lm - lm->class->methods);
}
- M_ALD(REG_METHODPTR, REG_A0,
+ M_ALD(REG_METHODPTR, REG_OUT0,
OFFSET(java_objectheader, vftbl));
M_ALD(REG_METHODPTR, REG_METHODPTR, s1);
M_ALD(REG_PV_CALLER, REG_METHODPTR, s2);
- M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
- M_NOP;
-/* XXX no need to restore PV, when its in the regs */
+ s1 = REG_PV_CALLER;
break;
}
- /* d contains return type */
+ /* generate the actual call */
+
+ M_JMP(REG_RA_CALLER, s1, REG_ZERO);
+ M_NOP;
+ disp = (s4) (cd->mcodeptr - cd->mcodebase);
+ /* REG_RA holds the value of the jmp instruction, therefore +8 */
+ M_LDA(REG_PV, REG_RA_CALLER, -disp + 8);
+
+ /* actually only used for ICMD_BUILTIN */
+
+ if (INSTRUCTION_MUST_CHECK(iptr)) {
+ M_BEQZ(REG_RESULT_CALLER, 0);
+ codegen_add_fillinstacktrace_ref(cd);
+ M_NOP;
+ }
+
+ /* store return value */
+
+ d = md->returntype.type;
if (d != TYPE_VOID) {
if (IS_INT_LNG_TYPE(d)) {
u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd)
{
- /* fabort("help me!"); */
- printf("createnativestub not implemented\n");
- return NULL;
+ methodinfo *m;
+ codeinfo *code;
+ codegendata *cd;
+ registerdata *rd;
+ methoddesc *md;
+ s4 nativeparams;
+ s4 i, j; /* count variables */
+ s4 t;
+ s4 s1, s2, disp;
+ s4 funcdisp; /* displacement of the function */
+
+ /* get required compiler data */
+
+ m = jd->m;
+ code = jd->code;
+ cd = jd->cd;
+ rd = jd->rd;
+
+ /* rewrite registers and params */
+ md_native_reg_setup(jd);
+ md_native_param_alloc(nmd);
+
+ /* initialize variables */
+
+ md = m->parseddesc;
+ nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
+
+ /* calculate stack frame size */
+
+ cd->stackframesize =
+ sizeof(stackframeinfo) / SIZEOF_VOID_P +
+ sizeof(localref_table) / SIZEOF_VOID_P +
+ md->paramcount + /* for saving arguments over calls */
+ nmd->memuse + /* nmd knows about the native stackframe layout */
+ WINSAVE_CNT;
+
+ /* create method header */
+
+ (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
+ (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */
+ (void) dseg_add_unique_s4(cd, 0); /* IsSync */
+ (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
+ (void) dseg_add_unique_s4(cd, 0); /* IntSave */
+ (void) dseg_add_unique_s4(cd, 0); /* FltSave */
+ (void) dseg_addlinenumbertablesize(cd);
+ (void) dseg_add_unique_s4(cd, 0); /* ExTableSize */
+
+ /* generate stub code */
+
+ M_SAVE(REG_SP, -cd->stackframesize * 8, REG_SP); /* build up stackframe */
+
+#if !defined(NDEBUG)
+ if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
+ emit_verbosecall_enter(jd);
+#endif
+
+ /* get function address (this must happen before the stackframeinfo) */
+
+ funcdisp = dseg_addaddress(cd, f);
+
+#if !defined(WITH_STATIC_CLASSPATH)
+ if (f == NULL) {
+ codegen_addpatchref(cd, PATCHER_resolve_native, m, funcdisp);
+
+ if (opt_showdisassemble) {
+ M_NOP; M_NOP;
+ }
+ }
+#endif
+
+ /* save float argument registers */
+
+ for (i = 0, j = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
+ if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
+ M_DST(rd->argfltregs[i], REG_SP, j * 8);
+ j++;
+ }
+ }
+
+ /* prepare data structures for native function call */
+
+ M_MOV(REG_FP, REG_OUT0); /* top of the stack frame */
+ M_MOV(REG_PV_CALLEE, REG_OUT1);
+ M_MOV(REG_FP, REG_OUT2); /* java sp */
+ M_MOV(REG_RA_CALLEE, REG_OUT3);
+ disp = dseg_addaddress(cd, codegen_start_native_call);
+ M_ALD(REG_ITMP3, REG_PV_CALLEE, disp);
+ M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
+ M_NOP; /* XXX fill me! */
+
+ /* restore float argument registers */
+
+ for (i = 0, j = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
+ if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
+ M_DLD(rd->argfltregs[i], REG_SP, j * 8);
+ j++;
+ }
+ }
+
+ /* copy or spill arguments to new locations */
+
+ for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
+ t = md->paramtypes[i].type;
+
+ if (IS_INT_LNG_TYPE(t)) {
+ if (!md->params[i].inmemory) {
+ s1 = rd->argintregs[md->params[i].regoff];
+ /* s1 refers to the old window, transpose */
+ s1 = REG_WINDOW_TRANSPOSE(s1);
+
+ if (!nmd->params[j].inmemory) {
+ s2 = rd->argintregs[nmd->params[j].regoff];
+ M_INTMOVE(s1, s2);
+ } else {
+ s2 = nmd->params[j].regoff;
+ M_AST(s1, REG_SP, USESTACK_PARAMS + s2 * 8);
+ }
+
+ } else {
+ s1 = md->params[i].regoff + cd->stackframesize;
+ s2 = nmd->params[j].regoff;
+ M_ALD(REG_ITMP1, REG_SP, USESTACK_PARAMS + s1 * 8);
+ M_AST(REG_ITMP1, REG_SP, USESTACK_PARAMS + s2 * 8);
+ }
+
+ } else {
+ if (!md->params[i].inmemory) {
+ s1 = rd->argfltregs[md->params[i].regoff];
+
+ if (!nmd->params[j].inmemory) {
+ s2 = rd->argfltregs[nmd->params[j].regoff];
+ if (IS_2_WORD_TYPE(t))
+ M_DMOV(s1, s2);
+ else
+ M_DMOV(s1, s2);
+
+ } else {
+ s2 = nmd->params[j].regoff;
+ if (IS_2_WORD_TYPE(t))
+ M_DST(s1, REG_SP, USESTACK_PARAMS + s2 * 8);
+ else
+ M_FST(s1, REG_SP, USESTACK_PARAMS + s2 * 8);
+ }
+
+ } else {
+ s1 = md->params[i].regoff + cd->stackframesize;
+ s2 = nmd->params[j].regoff;
+ if (IS_2_WORD_TYPE(t)) {
+ M_DLD(REG_FTMP1, REG_SP, USESTACK_PARAMS + s1 * 8);
+ M_DST(REG_FTMP1, REG_SP, USESTACK_PARAMS + s2 * 8);
+ } else {
+ M_FLD(REG_FTMP1, REG_SP, USESTACK_PARAMS + s1 * 8);
+ M_FST(REG_FTMP1, REG_SP, USESTACK_PARAMS + s2 * 8);
+ }
+ }
+ }
+ }
+
+
+ /* put class into second argument register */
+
+ if (m->flags & ACC_STATIC) {
+ disp = dseg_addaddress(cd, m->class);
+ M_ALD(REG_OUT1, REG_PV_CALLEE, disp);
+ }
+
+ /* put env into first argument register */
+
+ disp = dseg_addaddress(cd, _Jv_env);
+ M_ALD(REG_OUT0, REG_PV_CALLEE, disp);
+
+ /* do the native function call */
+
+ M_ALD(REG_ITMP3, REG_PV_CALLEE, funcdisp); /* load adress of native method */
+ M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO); /* call native method */
+ M_NOP; /* delay slot */
+
+ /* save return value */
+
+ if (md->returntype.type != TYPE_VOID) {
+ if (IS_INT_LNG_TYPE(md->returntype.type))
+ M_MOV(REG_RESULT_CALLER, REG_RESULT_CALLEE);
+ else
+ M_DST(REG_FRESULT, REG_SP, USESTACK_PARAMS);
+ }
+
+#if !defined(NDEBUG)
+ if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
+ emit_verbosecall_exit(jd);
+#endif
+
+ /* remove native stackframe info */
+
+ M_MOV(REG_FP, REG_OUT0);
+ disp = dseg_addaddress(cd, codegen_finish_native_call);
+ M_ALD(REG_ITMP3, REG_PV_CALLEE, disp);
+ M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
+ M_NOP; /* XXX fill me! */
+ M_MOV(REG_RESULT_CALLER, REG_ITMP2_XPTR);
+
+ /* restore float return value, int return value already in our return reg */
+
+ if (md->returntype.type != TYPE_VOID) {
+ if (IS_FLT_DBL_TYPE(md->returntype.type)) {
+ M_DLD(REG_FRESULT, REG_SP, USESTACK_PARAMS);
+ }
+ }
+
+ /* check for exception */
+
+ M_BNEZ(REG_ITMP2_XPTR, 4); /* if no exception then return */
+ M_RESTORE(REG_ZERO, REG_ZERO, REG_ZERO); /* restore callers window (DELAY)*/
+
+ M_RET(REG_RA_CALLER, 8); /* return to caller */
+ M_NOP; /* DELAY SLOT */
+
+ /* handle exception */
+
+ disp = dseg_addaddress(cd, asm_handle_nat_exception);
+ M_ALD(REG_ITMP3, REG_PV, disp); /* load asm exception handler address */
+ M_JMP(REG_ZERO, REG_ITMP3, REG_ZERO);/* jump to asm exception handler */
+ M_MOV(REG_RA_CALLER, REG_ITMP3_XPC); /* get exception address (DELAY) */
+
+ /* generate patcher stubs */
+
+ emit_patcher_stubs(jd);
+
+ codegen_finish(jd);
+
+ return code->entrypoint;
}
/*
#define M_SAVE(rs1,rs2,rd) M_OP3(0x02,0x3c,rd,rs1,rs2,IMM)
-#define M_REST(rs1,rs2,rd) M_OP3(0x02,0x37,rd,rs1,rs2,IMM)
+#define M_RESTORE(rs1,rs2,rd) M_OP3(0x02,0x37,rd,rs1,rs2,IMM)
#define M_JMP(rd,rs1,rs2) M_OP3(0x02,0x38,rd, rs1,rs2,REG) /* jump to rs1+rs2, adr of instr. saved to rd */
#define M_JMP_IMM(rd,rs1,rs2) M_OP3(0x02,0x38,rd, rs1,rs2,IMM)
-#define M_RET(rs) M_OP3(0x02,0x38,REG_ZERO,rs,REG_ZERO,REG)
+#define M_RET(rs1,imm) M_OP3(0x02,0x38,REG_ZERO,rs1,imm,IMM) /* a jump which discards the current pc */
-#define M_RETURN(rs) M_OP3(0x02,0x39,0,rs,REG_ZERO,REG) /* like ret, but does window restore */
+#define M_RETURN(rs1,imm) M_OP3(0x02,0x39,0,rs1,imm,IMM) /* like ret, but does window restore */
/**** floating point operations **/
M_NOP;
- M_LDA(REG_SP, REG_SP, -(1 + WINSAVE_CNT + FLT_ARG_CNT) * 8);
+ /* we're calling a c function allocate paramter array */
+ M_LDA(REG_SP, REG_SP, -(1 + FLT_ARG_CNT + ABI_PARAMARRAY_SLOTS) * 8);
/* save float argument registers */
for (i = 0; i < FLT_ARG_CNT; i++)
- M_DST(rd->argfltregs[i], REG_SP, BIAS + (WINSAVE_CNT + 1 + i) * 8);
+ M_DST(rd->argfltregs[i], REG_SP, USESTACK_PARAMS + (1 + i) * 8);
/* save temporary registers for leaf methods */
/* XXX no leaf optimization yet
M_DST(rd->tmpfltregs[i], REG_SP, (2 + ARG_CNT + INT_TMP_CNT + i) * 8);
}
*/
- /* load float arguments into integer registers */
+ /* load int/float arguments into integer argument registers */
for (i = 0; i < md->paramcount && i < INT_ARG_CNT; i++) {
t = md->paramtypes[i].type;
- if (IS_FLT_DBL_TYPE(t)) {
+ if (IS_INT_LNG_TYPE(t)) {
+ M_INTMOVE(REG_WINDOW_TRANSPOSE(rd->argintregs[i]), rd->argintregs[i]);
+ }
+ else {
if (IS_2_WORD_TYPE(t)) {
- M_DST(rd->argfltregs[i], REG_SP, USESTACK);
- M_LDX(rd->argintregs[i], REG_SP, USESTACK);
+ M_DST(rd->argfltregs[i], REG_SP, USESTACK_PARAMS);
+ M_LDX(rd->argintregs[i], REG_SP, USESTACK_PARAMS);
}
else {
- M_DST(rd->argfltregs[i], REG_SP, USESTACK);
- M_LDX(rd->argintregs[i], REG_SP, USESTACK);
+ M_DST(rd->argfltregs[i], REG_SP, USESTACK_PARAMS);
+ M_LDX(rd->argintregs[i], REG_SP, USESTACK_PARAMS);
}
}
}
-
+
+
+ /* method info pointer is passed in argument register 5 */
disp = dseg_add_address(cd, m);
- M_ALD(REG_ITMP1, REG_PV_CALLEE, disp);
- M_AST(REG_ITMP1, REG_SP, USESTACK);
+ M_ALD(REG_OUT5, REG_PV_CALLEE, disp);
disp = dseg_add_functionptr(cd, builtin_trace_args);
- M_ALD(REG_PV_CALLER, REG_PV_CALLEE, disp);
- M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
+ M_ALD(REG_ITMP1, REG_PV_CALLEE, disp);
+ M_JMP(REG_RA_CALLER, REG_ITMP1, REG_ZERO);
M_NOP;
/* restore float argument registers */
for (i = 0; i < FLT_ARG_CNT; i++)
- M_DLD(rd->argfltregs[i], REG_SP, BIAS + (WINSAVE_CNT + 1 + i) * 8);
+ M_DLD(rd->argfltregs[i], REG_SP, USESTACK_PARAMS + (1 + i) * 8);
/* restore temporary registers for leaf methods */
/* XXX no leaf optimization yet
M_DLD(rd->tmpfltregs[i], REG_SP, (2 + ARG_CNT + INT_TMP_CNT + i) * 8);
}
*/
- M_LDA(REG_SP, REG_SP, (1 + WINSAVE_CNT + FLT_ARG_CNT) * 8);
+ M_LDA(REG_SP, REG_SP, (1 + FLT_ARG_CNT + ABI_PARAMARRAY_SLOTS) * 8);
/* mark trace code */
/* mark trace code */
M_NOP;
+
+ /* we're calling a c function allocate paramter array */
+ M_LDA(REG_SP, REG_SP, -(1 + ABI_PARAMARRAY_SLOTS) * 8);
- M_LDA(REG_SP, REG_SP, -2 * 8); /* keep stack 16-byte aligned ???*/
-
- M_DST(REG_FRESULT, REG_SP, USESTACK + (1 * 8));
+ M_DST(REG_FRESULT, REG_SP, USESTACK_PARAMS);
disp = dseg_add_address(cd, m);
M_ALD(rd->argintregs[0], REG_PV_CALLEE, disp);
M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
M_NOP;
- M_DLD(REG_FRESULT, REG_SP, USESTACK + (1 * 8));
+ M_DLD(REG_FRESULT, REG_SP, USESTACK_PARAMS);
- M_LDA(REG_SP, REG_SP, 2 * 8);
+ M_LDA(REG_SP, REG_SP, (1 + ABI_PARAMARRAY_SLOTS) * 8);
/* mark trace code */
#include "vm/global.h"
#include "vm/jit/abi.h"
+/* temp */
+#include "mm/memory.h"
+#include <assert.h>
+
/* register descripton array **************************************************/
-/* callee point-of-view, after SAVE has been called */
+/* callee point-of-view, after SAVE has been called. */
s4 nregdescint[] = {
/* zero itmp1/g1 itmp2/g2 itmp3/g3 temp/g4 temp/g5 sys/g6 sys/g7 */
- REG_RES, REG_RES, REG_RES, REG_RES, REG_TMP, REG_TMP, REG_RES, REG_RES,
+ REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES,
/* o0 o1 o2 o3 o4 pv/o5 sp/o6 o7/ra */
REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_RES, REG_RES, REG_RES,
/* l0 l1 l2 l3 l4 l5 l6 l7 */
REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
- /* i0 i1 i2 i3 i4 pv/i5 fp/i6 ra/i7 */
+ /* i0/v0 i1 i2 i3 i4 pv/i5 fp/i6 ra/i7 */
REG_RET, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_RES, REG_RES, REG_RES,
REG_END
- /* XXX i1 - i4: SAV OR ARG ??? */
+
};
s4 nregdescfloat[] = {
REG_RET, REG_RES, REG_RES, REG_RES, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
- REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
+ REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
REG_END
};
/* md_param_alloc **************************************************************
- XXX
+ Allocate Arguments to Stackslots according the Calling Conventions
+
+ --- in
+ md->paramcount: Number of arguments for this method
+ md->paramtypes[].type: Argument types
+
+ --- out
+ md->params[].inmemory: Argument spilled on stack
+ md->params[].regoff: Stack offset or rd->arg[int|flt]regs index
+ md->memuse: Stackslots needed for argument spilling
+ md->argintreguse: max number of integer arguments used
+ md->argfltreguse: max number of float arguments used
*******************************************************************************/
break;
}
}
+
+ /* Since O0 is used for passing return values, this */
+ /* argument register usage has to be regarded, too */
+ if (IS_INT_LNG_TYPE(md->returntype.type)) {
+ if (reguse < 1)
+ md->argintreguse = 1;
+ }
+
+ /* fill register and stack usage */
+
+ md->memuse = stacksize;
+}
+
+/* md_native_param_alloc **************************************************************
+
+ XXX
+
+*******************************************************************************/
+
+void md_native_param_alloc(methoddesc *md)
+{
+ paramdesc *pd;
+ s4 i;
+ s4 reguse;
+ s4 stacksize;
+
+ /* set default values */
+
+ reguse = 0;
+ stacksize = 6;
+
+ /* get params field of methoddesc */
+
+ pd = md->params;
+
+ for (i = 0; i < md->paramcount; i++, pd++) {
+ switch (md->paramtypes[i].type) {
+ case TYPE_INT:
+ case TYPE_ADR:
+ case TYPE_LNG:
+ if (i < INT_NATARG_CNT) {
+ pd->inmemory = false;
+ pd->regoff = reguse;
+ reguse++;
+ md->argintreguse = reguse;
+
+ } else {
+ pd->inmemory = true;
+ pd->regoff = reguse;
+ reguse++;
+ stacksize++;
+ }
+ break;
+ case TYPE_FLT:
+ case TYPE_DBL:
+ if (i < FLT_NATARG_CNT) {
+ pd->inmemory = false;
+ pd->regoff = reguse;
+ reguse++;
+ md->argfltreguse = reguse;
+ } else {
+ pd->inmemory = true;
+ pd->regoff = reguse;
+ reguse++;
+ stacksize++;
+ }
+ break;
+ }
+ }
+
+ /* Since O0 is used for passing return values, this */
+ /* argument register usage has to be regarded, too */
+ if (IS_INT_LNG_TYPE(md->returntype.type)) {
+ if (reguse < 1)
+ md->argintreguse = 1;
+ }
/* fill register and stack usage */
md->memuse = stacksize;
}
+/* reg_setup *******************************************************************
+
+ TODO
+
+*******************************************************************************/
+
+void md_native_reg_setup(jitdata *jd)
+{
+ methodinfo *m;
+ registerdata *rd;
+ s4 i;
+
+ /* get required compiler data */
+
+ m = jd->m;
+ rd = jd->rd;
+
+ /* setup the integer register table */
+
+
+ rd->argintregs = DMNEW(s4, INT_NATARG_CNT);
+ rd->argintreguse = 0;
+
+ for (rd->argintreguse = 0, i = 8; rd->argintreguse < INT_NATARG_CNT; i++) {
+ rd->argintregs[rd->argintreguse++] = i;
+ }
+
+ assert(rd->argintreguse == INT_NATARG_CNT);
+
+ /* setup the float register table */
+
+ rd->argfltregs = DMNEW(s4, FLT_NATARG_CNT);
+
+ rd->argfltreguse = 0;
+
+
+ for (rd->argfltreguse = 0, i = 0; rd->argfltreguse < FLT_NATARG_CNT; i++) {
+ rd->argfltregs[rd->argfltreguse++] = i;
+ }
+ assert(rd->argfltreguse == FLT_NATARG_CNT);
+
+}
/* md_return_alloc *************************************************************
{
methodinfo *m;
methoddesc *md;
+
+ assert(0);
/* get required compiler data */
#define REG_FP 30 /* frame pointer */
#define REG_ZERO 0 /* always zero */
-#define REG_A0 8 /* define some argument registers */
-#define REG_A1 9
-#define REG_A2 10
-#define REG_A3 11
+#define REG_OUT0 8 /* define some argument registers */
+#define REG_OUT1 9
+#define REG_OUT2 10
+#define REG_OUT3 11
+#define REG_OUT4 12
+#define REG_OUT5 13
/* floating point registers */
/* only using the lower half of the floating registers for now */
#define INT_REG_CNT 32 /* number of integer registers */
#define INT_SAV_CNT 12 /* number of int callee saved registers */
#define INT_ARG_CNT 5 /* number of int argument registers (-1 for PV) */
-#define INT_TMP_CNT 2 /* int temp registers (%g4-%g5) */
-#define INT_RES_CNT 12 /* number of reserved integer registers */
+#define INT_TMP_CNT 0 /* int temp registers (%g4-%g5) */
+#define INT_RES_CNT 14 /* number of reserved integer registers */
/* pv, zero, %g6, %g7, sp, ra */
#define FLT_REG_CNT 16 /* number of float registers */
-#define FLT_SAV_CNT 4 /* number of flt callee saved registers */
+#define FLT_SAV_CNT 0 /* number of flt callee saved registers */
#define FLT_ARG_CNT 4 /* number of flt argument registers */
-#define FLT_TMP_CNT 4 /* number of flt temp registers */
+#define FLT_TMP_CNT 8 /* number of flt temp registers */
#define FLT_RES_CNT 3 /* number of reserved float registers */
/* the one "missing" register is the return reg */
+
+/* different argument counts when following the ABI for native functions */
+#define INT_NATARG_CNT 6
+#define FLT_NATARG_CNT 16
#define TRACE_ARGS_NUM 5
-/* helpers for stack addressing */
+/* helpers for stack addressing and window handling */
+
+/* SPARC ABI always wants argument slots on the stack, even when not used */
+#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 BIAS 2047
+#define USESTACK (WINSAVE_CNT * 8 + BIAS)
+#define USESTACK_PARAMS ((WINSAVE_CNT + ABI_PARAMARRAY_SLOTS) * 8 + BIAS)
+
+
-#define WINSAVE_CNT 16 /* number of regs that SPARC saves onto stack */
-#define BIAS 2047
-#define USESTACK (WINSAVE_CNT * 8 + BIAS)
+/* applies only when caller's window was saved */
+#define REG_WINDOW_TRANSPOSE(reg) \
+ (reg + 16)
#endif /* _MD_ABI_H */
#define fa1 %f18
#define fa2 %f20
#define fa3 %f22
-#define fs0 %f24
-#define fs1 %f26
-#define fs2 %f28
-#define fs3 %f30
+#define ft7 %f24
+#define ft8 %f26
+#define ft9 %f28
+#define ft10 %f30
#define bias 2047
std fa0,[%sp + bias + ((0+(off))*8)] ; \
std fa1,[%sp + bias + ((1+(off))*8)] ; \
std fa2,[%sp + bias + ((2+(off))*8)] ; \
- std fa3,[%sp + bias + ((3+(off))*8)]
+ std fa3,[%sp + bias + ((3+(off))*8)] ;
#define RESTORE_FLOAT_ARGUMENT_REGISTERS(off) \
ldd [%sp + bias + ((0+(off))*8)],fa0 ; \
ldd [%sp + bias + ((1+(off))*8)],fa1 ; \
ldd [%sp + bias + ((2+(off))*8)],fa2 ; \
- ldd [%sp + bias + ((3+(off))*8)],fa3 ; \
+ ldd [%sp + bias + ((3+(off))*8)],fa3 ;
+
+#define SAVE_FLOAT_TEMPORARY_REGISTERS(off) \
+ std ft0,[%sp + bias + ((0+(off))*8)] ; \
+ std ft1,[%sp + bias + ((1+(off))*8)] ; \
+ std ft2,[%sp + bias + ((2+(off))*8)] ; \
+ std ft3,[%sp + bias + ((3+(off))*8)] ; \
+ std ft4,[%sp + bias + ((4+(off))*8)] ; \
+ std ft5,[%sp + bias + ((5+(off))*8)] ; \
+ std ft6,[%sp + bias + ((6+(off))*8)] ; \
+ std ft7,[%sp + bias + ((7+(off))*8)] ; \
+ std ft8,[%sp + bias + ((8+(off))*8)] ; \
+ std ft9,[%sp + bias + ((9+(off))*8)] ; \
+ std ft10,[%sp + bias + ((10+(off))*8)] ;
+
+#define RESTORE_FLOAT_TEMPORARY_REGISTERS(off) \
+ ldd [%sp + bias + ((0+(off))*8)],ft0 ; \
+ ldd [%sp + bias + ((1+(off))*8)],ft1 ; \
+ ldd [%sp + bias + ((2+(off))*8)],ft2 ; \
+ ldd [%sp + bias + ((3+(off))*8)],ft3 ; \
+ ldd [%sp + bias + ((4+(off))*8)],ft4 ; \
+ ldd [%sp + bias + ((5+(off))*8)],ft5 ; \
+ ldd [%sp + bias + ((6+(off))*8)],ft6 ; \
+ ldd [%sp + bias + ((7+(off))*8)],ft7 ; \
+ ldd [%sp + bias + ((8+(off))*8)],ft8 ; \
+ ldd [%sp + bias + ((9+(off))*8)],ft9 ; \
+ ldd [%sp + bias + ((10+(off))*8)],ft10 ;
-
#endif /* _MD_ASM_H */
pv += offset;
}
+ else
+ {
+ assert(0);
+ }
return pv;
}
assert(mcode_masked == 0x0602fb);
+ printf("data segment: pv=0x%08x, offset=%d\n", sfi->pv, offset);
+
/* and get the final data segment address */
pa = sfi->pv + offset;
functionptr f;
bool result;
java_objectheader *e;
+
+ assert(0);
/* define the patcher function */