X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fvm%2Fjit%2Fm68k%2Femit.c;h=81fc1288f2d5ac61e799535cf29cbfecaccc7ccd;hb=9407b72fb4989b4cf816b303d14890f75757658a;hp=445256bca01e2e2fa8f0906fdb80b984ff9f2f62;hpb=044105cee615a666decfe95edbfae3d8bab5b413;p=cacao.git diff --git a/src/vm/jit/m68k/emit.c b/src/vm/jit/m68k/emit.c index 445256bca..81fc1288f 100644 --- a/src/vm/jit/m68k/emit.c +++ b/src/vm/jit/m68k/emit.c @@ -1,9 +1,7 @@ /* src/vm/jit/m68k/emit.c - Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel, - C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring, - E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, - J. Wenninger, Institut f. Computersprachen - TU Wien + Copyright (C) 1996-2005, 2006, 2007, 2008 + CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO This file is part of CACAO. @@ -22,42 +20,50 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - $Id: arch.h 5330 2006-09-05 18:43:12Z edwin $ - */ + + #include "config.h" #include -#include "emit.h" -#include "vm/jit/emit-common.h" -#include "vm/exceptions.h" -#include "vm/jit/asmpart.h" +#include "vm/jit/m68k/codegen.h" +#include "vm/jit/m68k/emit.h" -#include "vm/builtin.h" #include "mm/memory.h" -#include "codegen.h" +#include "vm/jit/builtin.hpp" -/* - * Loads an immededat operand into data register - */ +#include "vm/jit/asmpart.h" +#include "vm/jit/emit-common.hpp" +#include "vm/jit/trace.hpp" +#include "vm/jit/trap.h" + + +/* emit_mov_imm_reg ************************************************************************** + * + * Loads an immededat operand into an integer data register + * + ********************************************************************************************/ void emit_mov_imm_reg (codegendata *cd, s4 imm, s4 dreg) { - if ((imm & 0x000000FF) == imm) { + /* FIXME: -1 can be used as byte form 0xff, but this ifs cascade is plain wrong it seems */ + + if ( (imm & 0x0000007F) == imm) { /* use byte form */ *((s2*)cd->mcodeptr) = 0x7000 | (dreg << 9) | imm; /* MOVEQ.L */ cd->mcodeptr += 2; - } else if ((imm & 0xFFFF0000) != 0) { + } else if ((imm & 0x00007FFF) == imm) { + /* use word form */ + OPWORD( ((7<<6) | (dreg << 3) | 5), 7, 4); /* MVS.W */ + *((s2*)cd->mcodeptr) = (s2)imm; + cd->mcodeptr += 2; + } else { /* use long form */ OPWORD( ((2<<6) | (dreg << 3) | 0), 7, 4); *((s4*)cd->mcodeptr) = (s4)imm; cd->mcodeptr += 4; - } else { - /* use word form */ - OPWORD( ((3<<6) | (dreg << 3) | 0), 7, 4); - *((s2*)cd->mcodeptr) = (s2)imm; - cd->mcodeptr += 2; + } } @@ -66,18 +72,31 @@ void emit_mov_imm_reg (codegendata *cd, s4 imm, s4 dreg) Generates a register/memory to register/memory copy. *******************************************************************************/ -void emit_copy(jitdata *jd, instruction *iptr, varinfo *src, varinfo *dst) + +void emit_copy(jitdata *jd, instruction *iptr) { - codegendata *cd; - s4 s1, d; + codegendata *cd; + varinfo *src; + varinfo *dst; + s4 s1, d; /* get required compiler data */ cd = jd->cd; + /* get source and destination variables */ + + src = VAROP(iptr->s1); + dst = VAROP(iptr->dst); + if ((src->vv.regoff != dst->vv.regoff) || (IS_INMEMORY(src->flags ^ dst->flags))) { + if ((src->type == TYPE_RET) || (dst->type == TYPE_RET)) { + /* emit nothing, as the value won't be used anyway */ + return; + } + /* If one of the variables resides in memory, we can eliminate the register move from/to the temporary register with the order of getting the destination register and the load. */ @@ -89,7 +108,8 @@ void emit_copy(jitdata *jd, instruction *iptr, varinfo *src, varinfo *dst) d = codegen_reg_of_var(iptr->opc, dst, REG_IFTMP); s1 = emit_load(jd, iptr, src, d); - } else { + } + else { if (IS_LNG_TYPE(src->type)) s1 = emit_load(jd, iptr, src, REG_ITMP12_PACKED); else @@ -100,29 +120,33 @@ void emit_copy(jitdata *jd, instruction *iptr, varinfo *src, varinfo *dst) if (s1 != d) { switch(src->type) { - case TYPE_INT: M_INTMOVE(s1, d); break; - case TYPE_ADR: M_ADRMOVE(s1, d); break; - case TYPE_LNG: M_LNGMOVE(s1, d); break; + case TYPE_INT: M_INTMOVE(s1, d); break; + case TYPE_ADR: M_ADRMOVE(s1, d); break; + case TYPE_LNG: M_LNGMOVE(s1, d); break; #if !defined(ENABLE_SOFTFLOAT) - case TYPE_FLT: M_FLTMOVE(s1, d); break; - case TYPE_DBL: M_DBLMOVE(s1, d); break; + case TYPE_FLT: M_FLTMOVE(s1, d); break; + case TYPE_DBL: M_DBLMOVE(s1, d); break; #else - case TYPE_FLT: M_INTMOVE(s1, d); break; - case TYPE_DBL: M_LNGMOVE(s1, d); break; + case TYPE_FLT: M_INTMOVE(s1, d); break; + case TYPE_DBL: M_LNGMOVE(s1, d); break; #endif - default: assert(0); + default: + vm_abort("emit_copy: unknown type %d", src->type); } } + emit_store(jd, iptr, dst, d); } } + + /* emit_store ****************************************************************** Emits a possible store of the destination operand. *******************************************************************************/ -inline void emit_store(jitdata *jd, instruction *iptr, varinfo *dst, s4 d) +void emit_store(jitdata *jd, instruction *iptr, varinfo *dst, s4 d) { codegendata *cd; @@ -138,35 +162,38 @@ inline void emit_store(jitdata *jd, instruction *iptr, varinfo *dst, s4 d) case TYPE_DBL: #endif case TYPE_LNG: - M_LST(d, REG_SP, dst->vv.regoff * 4); + M_LST(d, REG_SP, dst->vv.regoff); break; #if defined(ENABLE_SOFTFLOAT) case TYPE_FLT: #endif case TYPE_INT: - M_IST(d, REG_SP, dst->vv.regoff * 4); + M_IST(d, REG_SP, dst->vv.regoff); break; case TYPE_ADR: - M_AST(d, REG_SP, dst->vv.regoff * 4); + M_AST(d, REG_SP, dst->vv.regoff); break; #if !defined(ENABLE_SOFTFLOAT) case TYPE_DBL: - M_DST(d, REG_SP, dst->vv.regoff * 4); + M_DST(d, REG_SP, dst->vv.regoff); break; case TYPE_FLT: - M_FST(d, REG_SP, dst->vv.regoff * 4); + M_FST(d, REG_SP, dst->vv.regoff); break; #endif default: - assert(0); + vm_abort("emit_store: unknown type %d", dst->type); } } } + + /* emit_load ******************************************************************* Emits a possible load of an operand. *******************************************************************************/ + s4 emit_load(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg) { codegendata *cd; @@ -180,7 +207,7 @@ s4 emit_load(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg) if (IS_INMEMORY(src->flags)) { COUNT_SPILLS; - disp = src->vv.regoff * 4; + disp = src->vv.regoff; switch (src->type) { #if defined(ENABLE_SOFTFLOAT) @@ -206,7 +233,8 @@ s4 emit_load(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg) M_DLD(tempreg, REG_SP, disp); break; #endif - default: assert(0); + default: + vm_abort("emit_load: unknown type %d", src->type); } #if 0 if (IS_FLT_DBL_TYPE(src->type)) { @@ -232,86 +260,17 @@ s4 emit_load(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg) return reg; } - -/* emit_patcher_stubs ********************************************************** - - Generates the code for the patcher stubs. - -*******************************************************************************/ -void emit_patcher_stubs(jitdata *jd) -{ - codegendata *cd; - patchref *pref; - u8 mcode; - 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(512); - - /* Get machine code which is patched back in later. A - `bsr.l' is 6 bytes long. */ - - savedmcodeptr = cd->mcodebase + pref->branchpos; - mcode = *((u8 *) savedmcodeptr); - - /* patch in `bsr.l' to call the following code */ - - tmpmcodeptr = cd->mcodeptr; /* save current mcodeptr */ - cd->mcodeptr = savedmcodeptr; /* set mcodeptr to patch position */ - - M_BSR_IMM(tmpmcodeptr - (savedmcodeptr + PATCHER_CALL_SIZE) + 4); - - cd->mcodeptr = tmpmcodeptr; /* restore the current mcodeptr */ - - /* save REG_ITMP3 */ - M_IPUSH(REG_ITMP3); /* FIXME why, and restore where ? */ - - /* move pointer to java_objectheader onto stack */ - -#if defined(ENABLE_THREADS) - (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 */ - - assert(0); /* The next lines are wrong */ - M_MOV_IMM(0, REG_ITMP3); - dseg_adddata(cd); - M_AADD_IMM(REG_ITMP3, disp); - M_IPUSH(REG_ITMP3); -#else - M_IPUSH_IMM(0); -#endif - - /* push move machine code bytes and classinfo pointer */ - - M_IPUSH_IMM(mcode >> 32); - M_IPUSH_IMM(mcode); - M_IPUSH_IMM(pref->ref); - M_IPUSH_IMM(pref->patcher); - - M_JMP_IMM(asm_patcher_wrapper); - } -} s4 emit_load_low(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg) { codegendata *cd; s4 disp; s4 reg; +#if !defined(ENABLE_SOFTFLOAT) assert(src->type == TYPE_LNG); +#else + assert(src->type == TYPE_LNG || src->type == TYPE_DBL); +#endif /* get required compiler data */ cd = jd->cd; @@ -319,7 +278,7 @@ s4 emit_load_low(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg) if (IS_INMEMORY(src->flags)) { COUNT_SPILLS; - disp = src->vv.regoff * 4; + disp = src->vv.regoff; M_ILD(tempreg, REG_SP, disp + 4); reg = tempreg; } else { @@ -333,14 +292,17 @@ s4 emit_load_high(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg) s4 disp; s4 reg; +#if !defined(ENABLE_SOFTFLOAT) assert(src->type == TYPE_LNG); - +#else + assert(src->type == TYPE_LNG || src->type == TYPE_DBL); +#endif /* get required compiler data */ cd = jd->cd; if (IS_INMEMORY(src->flags)) { COUNT_SPILLS; - disp = src->vv.regoff * 4; + disp = src->vv.regoff; M_ILD(tempreg, REG_SP, disp); reg = tempreg; } else { @@ -455,8 +417,6 @@ void emit_verbosecall_enter(jitdata* jd) codegendata *cd; registerdata *rd; methoddesc *md; - s4 disp,i,t; - if (!JITDATA_HAS_FLAG_VERBOSECALL(jd)) return; @@ -470,55 +430,38 @@ void emit_verbosecall_enter(jitdata* jd) /* mark trace code */ M_NOP; - M_LINK(REG_FP, -16*4); - M_PUSHALL; + M_IPUSH(REG_D0); + M_IPUSH(REG_D1); + M_APUSH(REG_A0); + M_APUSH(REG_A1); + M_AMOV(REG_SP, REG_A0); /* simpyfy stack offset calculation */ - /* builtin_verbosecall_enter takes all args as s8 type */ - /* TRACE_ARGS_NUM is the number of args the builtin_verbosecall_enter expects */ - M_IPUSH_IMM(m); +#if !defined(ENABLE_SOFTFLOAT) + M_AADD_IMM(-8*2, REG_SP); + M_FSTORE(REG_F0, REG_SP, 8); + M_FSTORE(REG_F1, REG_SP, 0); +#endif + + M_AADD_IMM(4*4 + 4, REG_A0); + M_APUSH(REG_A0); /* third arg is original argument stack */ + M_IPUSH_IMM(0); /* second arg is number of argument registers (=0) */ + M_IPUSH_IMM(m); /* first arg is methodpointer */ - disp = 16*4 + 4 + 4; /* points to old argument stack initially */ + M_JSR_IMM(trace_java_call_enter); + /* pop arguments off stack */ + M_AADD_IMM(3*4, REG_SP); - /* travel up stack to the first argument of the function which needs to be copied */ - for (i=0; (i < md->paramcount) && (i < TRACE_ARGS_NUM); i++) { - disp += 4; - if (IS_2_WORD_TYPE(md->paramtypes[i].type)) { - disp += 4; - } - } +#if !defined(ENABLE_SOFTFLOAT) + M_FSTORE(REG_F1, REG_SP, 0); + M_FSTORE(REG_F0, REG_SP, 8); + M_AADD_IMM(8*2, REG_SP); +#endif - /* disp now points to the first arg which gets copied to the trace stack, relative to REG_SP! */ - for (i=TRACE_ARGS_NUM-1; i>=0; --i) { - if (i < md->paramcount) { - /* traced function has such an argument */ - t = md->paramtypes[i].type; - - if (IS_2_WORD_TYPE(t)) { - /* copy from original argument stack */ - M_ILD(REG_ITMP1, REG_SP, disp); - M_IPUSH(REG_ITMP1); - M_ILD(REG_ITMP1, REG_SP, disp); - M_IPUSH(REG_ITMP1); - } else { - /* displacment is increased as 4 byte on original stack but 8 byte on trace stack */ - M_ILD(REG_ITMP1, REG_SP, disp); - M_IPUSH(REG_ITMP1); - M_IPUSH_IMM(0); - disp += 4; - } - } else { - /* function has no arg here, push nothing and adapt displacement */ - M_IPUSH_IMM(0); - M_IPUSH_IMM(0); - disp += 8; - } - } - M_JSR_IMM(builtin_verbosecall_enter); - /* pop arguments off stack */ - M_AADD_IMM(TRACE_ARGS_NUM*8+4, REG_SP); + M_APOP(REG_A1); + M_APOP(REG_A0); + M_IPOP(REG_D1); + M_IPOP(REG_D0); - M_POPALL; - M_UNLK(REG_FP); M_NOP; } void emit_verbosecall_exit(jitdata* jd) @@ -539,39 +482,78 @@ void emit_verbosecall_exit(jitdata* jd) /* void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m); */ + /* void trace_java_call_exit(methodinfo *m, uint64_t *return_regs) */ /* mark trace code */ M_NOP; - M_LINK(REG_FP, 0); - M_IPUSH_IMM(m); /* push methodinfo */ + /* to store result on stack */ + M_AADD_IMM(-8, REG_SP); /* create space for array */ + + switch (md->returntype.type) { + case TYPE_ADR: + case TYPE_INT: + #if defined(ENABLE_SOFTFLOAT) + case TYPE_FLT: + #endif + M_IST(REG_D0, REG_SP, 0); + break; - M_IPUSH_IMM(0); /* TODO push float result */ + case TYPE_LNG: + #if defined(ENABLE_SOFTFLOAT) + case TYPE_DBL: + #endif + M_LST(REG_D1, REG_SP, 0); + break; - M_IPUSH_IMM(0); /* TODO push double result */ - M_IPUSH_IMM(0); /* TODO push double result */ + #if !defined(ENABLE_SOFTFLOAT) + case TYPE_FLT: /* FIXME */ + case TYPE_DBL: /* FIXME */ + #endif - M_IPUSH(GET_HIGH_REG(REG_RESULT_PACKED)) - M_IPUSH(GET_LOW_REG(REG_RESULT_PACKED)) /* push long result */ + case TYPE_VOID: /* nothing */ + break; + default: + assert(0); + } - M_JSR_IMM(builtin_verbosecall_exit); + M_APUSH(REG_SP); /* push address of array */ + M_IPUSH_IMM(m); /* push methodinfo */ + M_JSR_IMM(trace_java_call_exit); + M_AADD_IMM(8, REG_SP); /* remove args */ /* poping result registers from stack */ - M_IPOP(GET_LOW_REG(REG_RESULT_PACKED)) - M_IPOP(GET_HIGH_REG(REG_RESULT_PACKED)) + switch (md->returntype.type) { + case TYPE_ADR: + case TYPE_INT: + #if defined(ENABLE_SOFTFLOAT) + case TYPE_FLT: + #endif + M_ILD(REG_D0, REG_SP, 0); + break; -#if 0 - /* that is wrong of course, overwrites registers and stuff */ - M_IPOP(0); /* TODO: pop double result */ - M_IPOP(0); /* TODO: pop double result */ + case TYPE_LNG: + #if defined(ENABLE_SOFTFLOAT) + case TYPE_DBL: + #endif + M_LLD(REG_D1, REG_SP, 0); + break; + + #if !defined(ENABLE_SOFTFLOAT) + case TYPE_FLT: /* FIXME */ + case TYPE_DBL: /* FIXME */ + #endif + + case TYPE_VOID: /* nothing */ + break; + + default: + assert(0); + } + + M_AADD_IMM(8, REG_SP); /* remove space for array */ - M_IPOP(0); /* TODO: pop float result */ -#else - M_AADD_IMM(3*4, REG_SP); -#endif - M_AADD_IMM(4, REG_SP); /* remove rest of stack */ - M_UNLK(REG_FP); M_NOP; } #endif @@ -596,13 +578,13 @@ void emit_classcast_check(codegendata *cd, instruction *iptr, s4 condition, s4 r M_BLE(4); break; case BRANCH_UGT: - M_BHI(4); + M_BLS(4); break; default: vm_abort("emit_classcast_check: unknown condition %d", condition); } M_TRAP_SETREGISTER(s1); - M_TRAP(EXCEPTION_HARDWARE_CLASSCAST); + M_TRAP(TRAP_ClassCastException); } } @@ -614,28 +596,45 @@ void emit_classcast_check(codegendata *cd, instruction *iptr, s4 condition, s4 r void emit_arrayindexoutofbounds_check(codegendata *cd, instruction *iptr, s4 s1, s4 s2) { if (INSTRUCTION_MUST_CHECK(iptr)) { - M_ILD(REG_ITMP3, s1, OFFSET(java_arrayheader, size)); - M_ICMP(REG_ITMP3, s2); - M_BLT(2); - /*M_ALD_INTERN(s2, REG_ZERO, EXCEPTION_LOAD_DISP_ARRAYINDEXOUTOFBOUNDS);*/ - M_ILLEGAL; /*FIXME */ + M_ILD(REG_ITMP3, s1, OFFSET(java_array_t, size)); + M_ICMP(s2, REG_ITMP3); + M_BHI(4); + M_TRAP_SETREGISTER(s2); + M_TRAP(TRAP_ArrayIndexOutOfBoundsException); + } +} + + +/* emit_arraystore_check ******************************************************* + + Emit an ArrayStoreException check. + +*******************************************************************************/ + +void emit_arraystore_check(codegendata *cd, instruction *iptr) +{ + if (INSTRUCTION_MUST_CHECK(iptr)) { + M_ITST(REG_RESULT); + M_BNE(2); + M_TRAP(TRAP_ArrayStoreException); } } + /* emit_nullpointer_check ****************************************************** Emit a NullPointerException check. *******************************************************************************/ + void emit_nullpointer_check(codegendata *cd, instruction *iptr, s4 reg) { if (INSTRUCTION_MUST_CHECK(iptr)) { - /* did like to assert on TYPE_ADR, but not possible in here */ - /* so assert before each emit_nullpointer_check */ + /* XXX: this check is copied to call monitor_enter + * invocation at the beginning of codegen.c */ M_ATST(reg); M_BNE(2); - /*M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_LOAD_DISP_NULLPOINTER);*/ - M_ILLEGAL; + M_TRAP(TRAP_NullPointerException); } } @@ -650,41 +649,59 @@ void emit_arithmetic_check(codegendata *cd, instruction *iptr, s4 reg) if (INSTRUCTION_MUST_CHECK(iptr)) { M_ITST(reg); M_BNE(2); - /*M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_ARITHMETIC);*/ - M_ILLEGAL; /* FIXME */ + M_TRAP(TRAP_ArithmeticException); } } -/* emit_exception_check_areg ************************************************** - * - Emit an Exception check, tested register is address REG_RESULT +/* emit_exception_check_ireg ************************************************** + + Emit an Exception check. Teste register is integer REG_RESULT *******************************************************************************/ -void emit_exception_check_areg(codegendata *cd, instruction *iptr) +void emit_exception_check(codegendata *cd, instruction *iptr) { if (INSTRUCTION_MUST_CHECK(iptr)) { - M_ATST(REG_RESULT); + M_ITST(REG_RESULT); M_BNE(2); - /*M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_EXCEPTION);*/ - M_ILLEGAL; /*FIXME*/ + M_TRAP(TRAP_CHECK_EXCEPTION); } } -/* emit_exception_check_ireg ************************************************** - Emit an Exception check. Teste register is integer REG_RESULT +/* emit_trap_compiler ********************************************************** + + Emit a trap instruction which calls the JIT compiler. *******************************************************************************/ -void emit_exception_check_ireg(codegendata *cd, instruction *iptr) + +void emit_trap_compiler(codegendata *cd) { - if (INSTRUCTION_MUST_CHECK(iptr)) { - M_ITST(REG_RESULT); - M_BNE(2); - /*M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_EXCEPTION);*/ - M_ILLEGAL; /*FIXME*/ - } + M_TRAP_SETREGISTER(REG_METHODPTR); + M_TRAP(TRAP_COMPILER); } +/* emit_trap ******************************************************************* + + Emit a trap instruction and return the original machine code. + +*******************************************************************************/ + +uint32_t emit_trap(codegendata *cd) +{ + uint32_t mcode; + + /* Get machine code which is patched back in later. The + trap is 2 bytes long. */ + + mcode = *((uint32_t *) cd->mcodeptr); + + M_TRAP(TRAP_PATCHER); + + return mcode; +} + + + /* * These are local overrides for various environment variables in Emacs. * Please do not remove this and leave it at the end of the file, where