X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fvm%2Fjit%2Femit-common.c;h=3a167808265e151f477303cf419a2c7c6c4be292;hb=b0dfcc457440aa84e2f1ccee8bcefad72615a344;hp=02443d2515a41430b01c943eca2ee571f9e8476a;hpb=3031a78a3410bff108facf8f9a6593f1d616d5fa;p=cacao.git diff --git a/src/vm/jit/emit-common.c b/src/vm/jit/emit-common.c index 02443d251..3a1678082 100644 --- a/src/vm/jit/emit-common.c +++ b/src/vm/jit/emit-common.c @@ -1,9 +1,7 @@ /* src/vm/jit/emit-common.c - common code emitter functions - Copyright (C) 2006 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) 2006, 2007, 2008 + CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO This file is part of CACAO. @@ -22,32 +20,25 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - Contact: cacao@cacaojvm.org - - Authors: Christian Thalinger - Edwin Steiner - - $Id: emitfuncs.c 4398 2006-01-31 23:43:08Z twisti $ - */ #include "config.h" #include +#include #include "vm/types.h" +#include "arch.h" #include "codegen.h" -#include "vm/options.h" - -#if defined(ENABLE_STATISTICS) -# include "vm/statistics.h" -#endif - #include "vm/jit/emit-common.h" #include "vm/jit/jit.h" +#include "vm/jit/patcher-common.h" + +#include "vmcore/options.h" +#include "vmcore/statistics.h" /* emit_load_s1 **************************************************************** @@ -254,13 +245,61 @@ void emit_store_dst(jitdata *jd, instruction *iptr, s4 d) } -/* emit_bxx ******************************************************************** +/* emit_patcher_traps ********************************************************** + + Generates the code for the patcher traps. + +*******************************************************************************/ + +void emit_patcher_traps(jitdata *jd) +{ + codegendata *cd; + codeinfo *code; + patchref_t *pr; + u1 *savedmcodeptr; + u1 *tmpmcodeptr; + uint32_t mcode; + + /* get required compiler data */ + + cd = jd->cd; + code = jd->code; + + /* generate patcher traps code */ + + for (pr = list_first(code->patchers); pr != NULL; pr = list_next(code->patchers, pr)) { + + /* Calculate the patch position where the original machine + code is located and the trap should be placed. */ + + tmpmcodeptr = (u1 *) (cd->mcodebase + pr->mpc); + + /* Patch in the trap to call the signal handler (done at + compile time). */ + + savedmcodeptr = cd->mcodeptr; /* save current mcodeptr */ + cd->mcodeptr = tmpmcodeptr; /* set mcodeptr to patch position */ + + mcode = emit_trap(cd); + + cd->mcodeptr = savedmcodeptr; /* restore the current mcodeptr */ + + /* Remember the original machine code which is patched + back in later (done at runtime). */ + + pr->mcode = mcode; + } +} + - Wrappers for conditional branch instructions. +/* emit_bccz ******************************************************************* + + Emit conditional and unconditional branch instructions on integer + regiseters. *******************************************************************************/ -void emit_bc(codegendata *cd, basicblock *target, s4 condition) +void emit_bccz(codegendata *cd, basicblock *target, s4 condition, s4 reg, u4 options) { s4 branchmpc; s4 disp; @@ -276,89 +315,406 @@ void emit_bc(codegendata *cd, basicblock *target, s4 condition) branchmpc = cd->mcodeptr - cd->mcodebase; disp = target->mpc - branchmpc; - emit_branch(cd, disp, condition); +#if defined(ENABLE_STATISTICS) + count_emit_branch++; + if ((int8_t)disp == disp) count_emit_branch_8bit++; + else if ((int16_t)disp == disp) count_emit_branch_16bit++; + else if ((int32_t)disp == disp) count_emit_branch_32bit++; +# if SIZEOF_VOID_P == 8 + else if ((int64_t)disp == disp) count_emit_branch_64bit++; +# endif +#endif + + emit_branch(cd, disp, condition, reg, options); } else { /* current mcodeptr is the correct position, afterwards emit the NOPs */ -#if 0 - codegen_add_branch_ref(cd, target, condition); -#endif + codegen_add_branch_ref(cd, target, condition, reg, options); /* generate NOPs as placeholder for branch code */ - /* XXX if recompile-with-long-branches */ BRANCH_NOPS; } } +/* emit_bcc ******************************************************************** + + Emit conditional and unconditional branch instructions on condition + codes. + +*******************************************************************************/ + +void emit_bcc(codegendata *cd, basicblock *target, s4 condition, u4 options) +{ + emit_bccz(cd, target, condition, -1, options); +} + + +/* emit_br ********************************************************************* + + Wrapper for unconditional branches. + +*******************************************************************************/ + void emit_br(codegendata *cd, basicblock *target) { - emit_bc(cd, target, BRANCH_UNCONDITIONAL); + emit_bcc(cd, target, BRANCH_UNCONDITIONAL, BRANCH_OPT_NONE); } -void emit_beq(codegendata *cd, basicblock *target) +/* emit_bxxz ******************************************************************* + + Wrappers for branches on one integer register. + +*******************************************************************************/ + +#if SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER + +void emit_beqz(codegendata *cd, basicblock *target, s4 reg) { - emit_bc(cd, target, BRANCH_EQ); + emit_bccz(cd, target, BRANCH_EQ, reg, BRANCH_OPT_NONE); } +void emit_bnez(codegendata *cd, basicblock *target, s4 reg) +{ + emit_bccz(cd, target, BRANCH_NE, reg, BRANCH_OPT_NONE); +} -void emit_bne(codegendata *cd, basicblock *target) +void emit_bltz(codegendata *cd, basicblock *target, s4 reg) { - emit_bc(cd, target, BRANCH_NE); + emit_bccz(cd, target, BRANCH_LT, reg, BRANCH_OPT_NONE); } +void emit_bgez(codegendata *cd, basicblock *target, s4 reg) +{ + emit_bccz(cd, target, BRANCH_GE, reg, BRANCH_OPT_NONE); +} -void emit_blt(codegendata *cd, basicblock *target) +void emit_bgtz(codegendata *cd, basicblock *target, s4 reg) { - emit_bc(cd, target, BRANCH_LT); + emit_bccz(cd, target, BRANCH_GT, reg, BRANCH_OPT_NONE); } +void emit_blez(codegendata *cd, basicblock *target, s4 reg) +{ + emit_bccz(cd, target, BRANCH_LE, reg, BRANCH_OPT_NONE); +} -void emit_bge(codegendata *cd, basicblock *target) +#endif /* SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER */ + + +/* emit_bxx ******************************************************************** + + Wrappers for branches on two integer registers. + + We use PACK_REGS here, so we don't have to change the branchref + data structure and the emit_bccz function. + +*******************************************************************************/ + +#if SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS + +void emit_beq(codegendata *cd, basicblock *target, s4 s1, s4 s2) { - emit_bc(cd, target, BRANCH_GE); + emit_bccz(cd, target, BRANCH_EQ, PACK_REGS(s1, s2), BRANCH_OPT_NONE); } +void emit_bne(codegendata *cd, basicblock *target, s4 s1, s4 s2) +{ + emit_bccz(cd, target, BRANCH_NE, PACK_REGS(s1, s2), BRANCH_OPT_NONE); +} -void emit_bgt(codegendata *cd, basicblock *target) +#endif /* SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS */ + + +/* emit_bxx ******************************************************************** + + Wrappers for branches on condition codes. + +*******************************************************************************/ + +#if SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER + +void emit_beq(codegendata *cd, basicblock *target) +{ + emit_bcc(cd, target, BRANCH_EQ, BRANCH_OPT_NONE); +} + +void emit_bne(codegendata *cd, basicblock *target) +{ + emit_bcc(cd, target, BRANCH_NE, BRANCH_OPT_NONE); +} + +void emit_blt(codegendata *cd, basicblock *target) +{ + emit_bcc(cd, target, BRANCH_LT, BRANCH_OPT_NONE); +} + +void emit_bge(codegendata *cd, basicblock *target) { - emit_bc(cd, target, BRANCH_GT); + emit_bcc(cd, target, BRANCH_GE, BRANCH_OPT_NONE); } +void emit_bgt(codegendata *cd, basicblock *target) +{ + emit_bcc(cd, target, BRANCH_GT, BRANCH_OPT_NONE); +} void emit_ble(codegendata *cd, basicblock *target) { - emit_bc(cd, target, BRANCH_LE); + emit_bcc(cd, target, BRANCH_LE, BRANCH_OPT_NONE); } +#if SUPPORT_BRANCH_CONDITIONAL_UNSIGNED_CONDITIONS +void emit_bult(codegendata *cd, basicblock *target) +{ + emit_bcc(cd, target, BRANCH_ULT, BRANCH_OPT_NONE); +} + +void emit_bule(codegendata *cd, basicblock *target) +{ + emit_bcc(cd, target, BRANCH_ULE, BRANCH_OPT_NONE); +} + +void emit_buge(codegendata *cd, basicblock *target) +{ + emit_bcc(cd, target, BRANCH_UGE, BRANCH_OPT_NONE); +} + +void emit_bugt(codegendata *cd, basicblock *target) +{ + emit_bcc(cd, target, BRANCH_UGT, BRANCH_OPT_NONE); +} +#endif +#if defined(__POWERPC__) || defined(__POWERPC64__) void emit_bnan(codegendata *cd, basicblock *target) { - emit_bc(cd, target, BRANCH_NAN); + emit_bcc(cd, target, BRANCH_NAN, BRANCH_OPT_NONE); } +#endif + +#endif /* SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER */ -/* emit_array_checks *********************************************************** +/* emit_label_bccz ************************************************************* - Emit exception checks for array accesses, if they need to be - emitted. + Emit a branch to a label. Possibly emit the branch, if it is a + backward branch. *******************************************************************************/ -#if defined(__ALPHA__) || defined(__POWERPC__) -void emit_array_checks(codegendata *cd, instruction *iptr, s4 s1, s4 s2) +void emit_label_bccz(codegendata *cd, s4 label, s4 condition, s4 reg, u4 options) { - if (INSTRUCTION_MUST_CHECK(iptr)) { - emit_nullpointer_check(cd, s1); - emit_arrayindexoutofbounds_check(cd, s1, s2); + list_t *list; + branch_label_ref_t *br; + s4 mpc; + s4 disp; + + /* get the label list */ + + list = cd->brancheslabel; + + /* search if the label is already in the list */ + + for (br = list_first(list); br != NULL; br = list_next(list, br)) { + /* is this entry the correct label? */ + + if (br->label == label) + break; } + + if (br == NULL) { + /* current mcodeptr is the correct position, + afterwards emit the NOPs */ + + codegen_branch_label_add(cd, label, condition, reg, options); + + /* generate NOPs as placeholder for branch code */ + + BRANCH_NOPS; + return; + } + + /* Branch reference was found. */ + + /* calculate the mpc of the branch instruction */ + + mpc = cd->mcodeptr - cd->mcodebase; + disp = br->mpc - mpc; + +#if defined(ENABLE_STATISTICS) + count_emit_branch++; + if ((int8_t)disp == disp) count_emit_branch_8bit++; + else if ((int16_t)disp == disp) count_emit_branch_16bit++; + else if ((int32_t)disp == disp) count_emit_branch_32bit++; +# if SIZEOF_VOID_P == 8 + else if ((int64_t)disp == disp) count_emit_branch_64bit++; +# endif +#endif + + emit_branch(cd, disp, condition, reg, options); + + /* now remove the branch reference */ + + list_remove(list, br); } + + +/* emit_label ****************************************************************** + + Emit a label for a branch. Possibly emit the branch, if it is a + forward branch. + +*******************************************************************************/ + +void emit_label(codegendata *cd, s4 label) +{ + list_t *list; + branch_label_ref_t *br; + s4 mpc; + s4 disp; + u1 *mcodeptr; + + /* get the label list */ + + list = cd->brancheslabel; + + /* search if the label is already in the list */ + + for (br = list_first(list); br != NULL; br = list_next(list, br)) { + /* is this entry the correct label? */ + + if (br->label == label) + break; + } + + if (br == NULL) { + /* No branch reference found, add the label to the list (use + invalid values for condition and register). */ + + codegen_branch_label_add(cd, label, -1, -1, BRANCH_OPT_NONE ); + return; + } + + /* Branch reference was found. */ + + /* calculate the mpc of the branch instruction */ + + mpc = cd->mcodeptr - cd->mcodebase; + disp = mpc - br->mpc; + + /* temporary set the mcodeptr */ + + mcodeptr = cd->mcodeptr; + cd->mcodeptr = cd->mcodebase + br->mpc; + +#if defined(ENABLE_STATISTICS) + count_emit_branch++; + if ((int8_t)disp == disp) count_emit_branch_8bit++; + else if ((int16_t)disp == disp) count_emit_branch_16bit++; + else if ((int32_t)disp == disp) count_emit_branch_32bit++; +# if SIZEOF_VOID_P == 8 + else if ((int64_t)disp == disp) count_emit_branch_64bit++; +# endif #endif + emit_branch(cd, disp, br->condition, br->reg, br->options); + + /* restore mcodeptr */ + + cd->mcodeptr = mcodeptr; + + /* now remove the branch reference */ + + list_remove(list, br); +} + + +/* emit_label_bcc ************************************************************** + + Emit conditional and unconditional label-branch instructions on + condition codes. + +*******************************************************************************/ + +void emit_label_bcc(codegendata *cd, s4 label, s4 condition, u4 options) +{ + emit_label_bccz(cd, label, condition, -1, options); +} + + +/* emit_label_br *************************************************************** + + Wrapper for unconditional label-branches. + +*******************************************************************************/ + +void emit_label_br(codegendata *cd, s4 label) +{ + emit_label_bcc(cd, label, BRANCH_UNCONDITIONAL, BRANCH_OPT_NONE); +} + + +/* emit_label_bxxz ************************************************************* + + Wrappers for label-branches on one integer register. + +*******************************************************************************/ + +#if SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER + +void emit_label_beqz(codegendata *cd, s4 label, s4 reg) +{ + emit_label_bccz(cd, label, BRANCH_EQ, reg, BRANCH_OPT_NONE); +} + +#endif /* SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER */ + + +/* emit_label_bxx ************************************************************** + + Wrappers for label-branches on condition codes. + +*******************************************************************************/ + +#if SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER + +void emit_label_beq(codegendata *cd, s4 label) +{ + emit_label_bcc(cd, label, BRANCH_EQ, BRANCH_OPT_NONE); +} + +void emit_label_bne(codegendata *cd, s4 label) +{ + emit_label_bcc(cd, label, BRANCH_NE, BRANCH_OPT_NONE); +} + +void emit_label_blt(codegendata *cd, s4 label) +{ + emit_label_bcc(cd, label, BRANCH_LT, BRANCH_OPT_NONE); +} + +void emit_label_bge(codegendata *cd, s4 label) +{ + emit_label_bcc(cd, label, BRANCH_GE, BRANCH_OPT_NONE); +} + +void emit_label_bgt(codegendata *cd, s4 label) +{ + emit_label_bcc(cd, label, BRANCH_GT, BRANCH_OPT_NONE); +} + +void emit_label_ble(codegendata *cd, s4 label) +{ + emit_label_bcc(cd, label, BRANCH_LE, BRANCH_OPT_NONE); +} + +#endif /* SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER */ + /* * These are local overrides for various environment variables in Emacs.