* src/vm/jit/sparc64/codegen.c: Likewise.
* src/vm/jit/sparc64/md.c: Implemented md_get_method_patch_address.
* src/vm/jit/sparc64/asmpart.S(asm_call_jit_compiler): Fixed window handling
* src/vm/jit/sparc64/disass.c: Fixed disassembly printing.
* src/vm/jit/sparc64/md-abi.h: Minor changes/fixes.
* src/vm/jit/sparc64/codegen.h: Likewise.
* src/vm/jit/sparc64/md-asm.h: Likewise.
calljava_nocopy:
- mov %i0,itmp1 /* pass method pointer via itmp1 */
+ mov %i0,itmp1 /* pass method info pointer via itmp1 */
setx asm_call_jit_compiler,%l0,mptr_itmp2 /* fake virtual function call (2 instr) */
stx mptr_itmp2,[%sp + 2047 + 17*8] /* store function address */
asm_call_jit_compiler:
- /* XXX save + reserve stack space */
- /* XXX save float arg registers */
+ save %sp,-160,%sp /* regsave + 4 slots for float args */
+
+ SAVE_FLOAT_ARGUMENT_REGISTERS(16)
mov itmp1,%o0 /* pass methodinfo pointer */
mov mptr_itmp2,%o1 /* pass method pointer */
mov %fp,%o2 /* pass java sp (==fp) */
- mov ra_caller,%o3 /* pass Java ra */
+ mov ra_callee,%o3 /* pass Java ra */
mov %o3,%o4 /* xpc is equal to ra */
call jit_asm_compile /* call jit compiler */
nop
+
+ RESTORE_FLOAT_ARGUMENT_REGISTERS(16)
+
+ restore %o0,%g0,pv_caller /* restore the callers window */
+ /* the source o0 references the old window */
+ /* pv_caller references the new window */
- mov %o0,pv_callee /* save return value into callee(!) pv */
- /* the in's we have are also the in's of the*/
- /* method that will be called */
- /* XXX do a window restore here ??? */
- /* XXX restore float argument registers */
- brz pv_callee,L_asm_call_jit_compiler_exception
+ brz pv_caller,L_asm_call_jit_compiler_exception
/* synchronise instruction cache moved somewhere else */
- jmpl pv_callee,zero /* and call method, the method returns */
+ jmpl pv_caller,zero /* and call method, the method returns */
/* directly to the caller (ra). */
L_asm_call_jit_compiler_exception:
p = cd->stackframesize;
for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
- p--; M_DST(rd->savfltregs[i], REG_SP, (WINSAVE_REGS + p) * 8);
+ p--; M_DST(rd->savfltregs[i], REG_SP, (WINSAVE_CNT + p) * 8);
}
/* take arguments out of register or stack frame */
M_INTMOVE(s2, var->vv.regoff);
} else { /* reg arg -> spilled */
- M_STX(s2, REG_SP, (WINSAVE_REGS + var->vv.regoff) * 8);
+ M_STX(s2, REG_SP, (WINSAVE_CNT + var->vv.regoff) * 8);
}
} else { /* stack arguments */
M_FLTMOVE(s2, var->vv.regoff);
} else { /* reg arg -> spilled */
- M_DST(s2, REG_SP, (WINSAVE_REGS + var->vv.regoff) * 8);
+ M_DST(s2, REG_SP, (WINSAVE_CNT + var->vv.regoff) * 8);
}
} else { /* stack arguments */
} /* end for */
- /* XXX monitor enter and tracing */
+ /* XXX monitor enter */
+
+
+#if !defined(NDEBUG)
+ if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
+ emit_verbosecall_enter(jd);
+#endif
}
p = cd->stackframesize;
#if !defined(NDEBUG)
- if (opt_verbosecall) {
- M_LDA(REG_SP, REG_SP, -3 * 8);
- M_AST(REG_RA_CALLEE, REG_SP, 0 * 8); /* XXX: no need to save anything but FRES ? */
- /* M_STX(REG_RESULT, REG_SP, 1 * 8); */
- M_DST(REG_FRESULT, REG_SP, 2 * 8);
-
- disp = dseg_addaddress(cd, m);
- M_ALD(rd->argintregs[0], REG_PV, disp);
- M_MOV(REG_RESULT_CALLEE, rd->argintregs[1]);
- M_FLTMOVE(REG_FRESULT, rd->argfltregs[2]);
- M_FLTMOVE(REG_FRESULT, rd->argfltregs[3]);
-
- disp = dseg_addaddress(cd, (void *) builtin_displaymethodstop);
- M_ALD(REG_ITMP3, REG_PV, disp);
- M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
- M_NOP;
-
- M_DLD(REG_FRESULT, REG_SP, 2 * 8);
- /* M_LDX(REG_RESULT, REG_SP, 1 * 8); */
- M_ALD(REG_RA_CALLEE, REG_SP, 0 * 8);
- M_LDA(REG_SP, REG_SP, 3 * 8);
- }
+ if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
+ emit_verbosecall_exit(jd);
#endif
#if defined(ENABLE_THREADS)
#define M_ALD_INTERN(a,b,disp) M_LDX_INTERN(a,b,disp)
-#define M_ALD(a,b,disp) M_LDX(a,b,disp)
+#define M_ALD(rd,rs,disp) M_LDX(rd,rs,disp)
#define M_AST_INTERN(a,b,disp) M_STX_INTERN(a,b,disp)
#define M_AST(a,b,disp) M_STX(a,b,disp)
#define M_AADD(a,b,c) M_ADD(a,b,c)
printf("0x%08x: ", (s4) code);
+ printf("{0x%08x} -> ", *((u4*) code));
/* disass_len = 0; */
seqlen = print_insn_sparc((bfd_vma) code, &info);
+/*
for (i = 0; i < seqlen; i++, code++) {
printf("%02x ", *code);
}
for (; i < 8; i++) {
printf(" ");
}
+*/
+ printf("\n");
- /* printf(" %s\n", disass_buf); */
-
- return code;
+ return code+4;
}
#include "md-abi.h"
-#include "vm/jit/jit.h"
-#include "vm/jit/dseg.h"
-#include "vm/jit/emit-common.h"
#include "vm/jit/sparc64/codegen.h"
+#include "vm/exceptions.h"
+#include "vm/stringlocal.h" /* XXX for gen_resolvebranch */
+#include "vm/jit/abi-asm.h"
+#include "vm/jit/asmpart.h"
+#include "vm/jit/dseg.h"
+#include "vm/jit/emit-common.h"
+#include "vm/jit/jit.h"
+#include "vm/jit/replace.h"
/* emit_load *******************************************************************
{
}
+/* emit_verbosecall_enter ******************************************************
+
+ Generates the code for the call trace.
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void emit_verbosecall_enter(jitdata *jd)
+{
+ methodinfo *m;
+ codegendata *cd;
+ registerdata *rd;
+ methoddesc *md;
+ s4 disp;
+ s4 i, t;
+
+ /* get required compiler data */
+
+ m = jd->m;
+ cd = jd->cd;
+ rd = jd->rd;
+
+ md = m->parseddesc;
+
+ /* mark trace code */
+
+ M_NOP;
+
+ M_LDA(REG_SP, REG_SP, -(1 + WINSAVE_CNT + FLT_ARG_CNT) * 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);
+
+ /* save temporary registers for leaf methods */
+/* XXX no leaf optimization yet
+ if (jd->isleafmethod) {
+ for (i = 0; i < INT_TMP_CNT; i++)
+ M_LST(rd->tmpintregs[i], REG_SP, (2 + ARG_CNT + i) * 8);
+
+ for (i = 0; i < FLT_TMP_CNT; i++)
+ M_DST(rd->tmpfltregs[i], REG_SP, (2 + ARG_CNT + INT_TMP_CNT + i) * 8);
+ }
+*/
+ /* load float arguments into integer 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_2_WORD_TYPE(t)) {
+ M_DST(rd->argfltregs[i], REG_SP, USESTACK);
+ M_LDX(rd->argintregs[i], REG_SP, USESTACK);
+ }
+ else {
+ M_DST(rd->argfltregs[i], REG_SP, USESTACK);
+ M_LDX(rd->argintregs[i], REG_SP, USESTACK);
+ }
+ }
+ }
+
+ disp = dseg_add_address(cd, m);
+ M_ALD(REG_ITMP1, REG_PV_CALLEE, disp);
+ M_AST(REG_ITMP1, REG_SP, USESTACK);
+ 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_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);
+
+ /* restore temporary registers for leaf methods */
+/* XXX no leaf optimization yet
+ if (jd->isleafmethod) {
+ for (i = 0; i < INT_TMP_CNT; i++)
+ M_LLD(rd->tmpintregs[i], REG_SP, (2 + ARG_CNT + i) * 8);
+
+ for (i = 0; i < FLT_TMP_CNT; i++)
+ 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);
+
+ /* mark trace code */
+
+ M_NOP;
+}
+#endif /* !defined(NDEBUG) */
+
+
+/* emit_verbosecall_exit *******************************************************
+
+ Generates the code for the call trace.
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void emit_verbosecall_exit(jitdata *jd)
+{
+ methodinfo *m;
+ codegendata *cd;
+ registerdata *rd;
+ s4 disp;
+
+ /* get required compiler data */
+
+ m = jd->m;
+ cd = jd->cd;
+ rd = jd->rd;
+
+ /* mark trace code */
+
+ M_NOP;
+
+ M_LDA(REG_SP, REG_SP, -2 * 8); /* keep stack 16-byte aligned ???*/
+
+ M_DST(REG_FRESULT, REG_SP, USESTACK + (1 * 8));
+
+ disp = dseg_add_address(cd, m);
+ M_ALD(rd->argintregs[0], REG_PV_CALLEE, disp);
+
+ M_MOV(REG_RESULT_CALLEE, rd->argintregs[1]);
+ M_DMOV(REG_FRESULT, rd->argfltregs[2]);
+ M_FMOV(REG_FRESULT, rd->argfltregs[3]);
+
+ disp = dseg_add_functionptr(cd, builtin_displaymethodstop);
+ M_ALD(REG_ITMP3, 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_LDA(REG_SP, REG_SP, 2 * 8);
+
+ /* mark trace code */
+
+ M_NOP;
+}
+#endif /* !defined(NDEBUG) */
+
/*
* These are local overrides for various environment variables in Emacs.
#define FLT_RES_CNT 3 /* number of reserved float registers */
/* the one "missing" register is the return reg */
-/* #define TRACE_ARGS_NUM 5 */
+#define TRACE_ARGS_NUM 5
+/* helpers for stack addressing */
-#define WINSAVE_REGS 16 /* number of regs that SPARC saves onto stack */
+#define WINSAVE_CNT 16 /* number of regs that SPARC saves onto stack */
+#define BIAS 2047
+#define USESTACK (WINSAVE_CNT * 8 + BIAS)
#endif /* _MD_ABI_H */
#define pv_caller %o5
#define pv_callee %i5
+
+#define fv0 %f0
+#define ft0 %f2
+#define ft1 %f4
+#define ft2 %f6
+#define ft3 %f8
+#define ft4 %f10
+#define ft5 %f12
+#define ft6 %f14
+
+#define fa0 %f16
+#define fa1 %f18
+#define fa2 %f20
+#define fa3 %f22
+#define fs0 %f24
+#define fs1 %f26
+#define fs2 %f28
+#define fs3 %f30
+
+
+#define bias 2047
+
+
+/* save and restore macros ****************************************************/
+
+
+#define SAVE_FLOAT_ARGUMENT_REGISTERS(off) \
+ 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)]
+
+
+#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 ; \
+
+
+
+
#endif /* _MD_ASM_H */
#include "vm/jit/disass.h" /* XXX debug */
#endif
+/* shift away 13-bit immediate, mask rd and rs1 */
+#define SHIFT_AND_MASK(instr) \
+ ((instr >> 13) & 0x60fc1)
+
+#define IS_SETHI(instr) \
+ ((instr & 0xc1c00000) == 0x00800000)
+
+inline s2 decode_13bit_imm(u4 instr) {
+ s2 imm;
+
+ /* mask everything else in the instruction */
+ imm = instr & 0x00001fff;
+
+ /* sign extend 13-bit to 16-bit */
+ imm <<= 3;
+ imm >>= 3;
+
+ return imm;
+}
/* md_init *********************************************************************
/* the return address resides in register i7, the last register in the
* 16-extended-word save area
*/
- ra = *((u1 **) (sp + 120));
+ ra = *((u1 **) (sp + 120 + BIAS));
/* ra is the address of the call instr, advance to the real return address */
ra += 8;
/* check if we have 2 instructions (ldah, lda) */
- /* shift instruction word, mask rd and rs1 */
- mcode_masked = (mcode >> 13) & 0x60fc1;
+ mcode_masked = SHIFT_AND_MASK(mcode);
if (mcode_masked == 0x40001) {
#if 0
assert((mcode >> 16) == 0x237a);
#endif
/* mask and extend the negative sign for the 13 bit immediate */
- offset = (s2) ((mcode & 0x00001fff) | 0xffffe000);
+ offset = decode_13bit_imm(mcode);
pv += offset;
}
INVOKESTATIC/SPECIAL:
- dfdeffb8 ld s8,-72(s8)
- 03c0f809 jalr s8
+ dfdeffb8 ldx [i5 - 72],o5
+ 03c0f809 jmp o5
00000000 nop
INVOKEVIRTUAL:
dc990000 ld t9,0(a0)
- df3e0000 ld s8,0(t9)
- 03c0f809 jalr s8
+ df3e0000 ld [g2 + 0],o5
+ 03c0f809 jmp o5
00000000 nop
INVOKEINTERFACE:
dc990000 ld t9,0(a0)
- df39ff90 ld t9,-112(t9)
- df3e0018 ld s8,24(t9)
- 03c0f809 jalr s8
+ df39ff90 ld [g2 - 112],g2
+ df3e0018 ld [g2 + 24],o5
+ 03c0f809 jmp o5
00000000 nop
*******************************************************************************/
u1 *md_get_method_patch_address(u1 *ra, stackframeinfo *sfi, u1 *mptr)
{
- u4 mcode;
+ u4 mcode, mcode_masked;
s4 offset;
u1 *pa;
- /* go back to the actual load instruction (3 instructions on MIPS) */
-
- ra -= 3 * 4;
+ /* go back to the actual load instruction (1 instruction before jump) */
+ /* ra is the address of the jump instruction on SPARC */
+ ra -= 1 * 4;
/* get first instruction word on current PC */
mcode = *((u4 *) ra);
+
/* check if we have 2 instructions (lui) */
- if ((mcode >> 16) == 0x3c19) {
+ if (IS_SETHI(mcode)) {
/* XXX write a regression for this */
assert(0);
offset += (s2) (mcode & 0x0000ffff);
} else {
- /* get first instruction (ld) */
- mcode = *((u4 *) ra);
+ /* shift and maks rd */
+ mcode_masked = (mcode >> 13) & 0x060fff;
+
/* get the offset from the instruction */
- offset = (s2) (mcode & 0x0000ffff);
+ offset = decode_13bit_imm(mcode);
- /* check for call with REG_METHODPTR: ld s8,x(t9) */
+ /* check for call with rs1 == REG_METHODPTR: ldx [g2+x],pv_caller */
-#if SIZEOF_VOID_P == 8
- if ((mcode >> 16) == 0xdf3e) {
-#else
- if ((mcode >> 16) == 0x8f3e) {
-#endif
+ if (mcode_masked == 0x0602c5) {
/* in this case we use the passed method pointer */
pa = mptr + offset;
} else {
- /* in the normal case we check for a `ld s8,x(s8)' instruction */
+ /* in the normal case we check for a `ldx [i5+x],pv_caller' instruction */
-#if SIZEOF_VOID_P == 8
- assert((mcode >> 16) == 0xdfde);
-#else
- assert((mcode >> 16) == 0x8fde);
-#endif
+ assert(mcode_masked == 0x0602fb);
/* and get the final data segment address */