* Removed all Id tags.
[cacao.git] / src / vm / jit / codegen-common.c
index 5a0c899362ca8e3c4ee951728bd69a9e3803ef30..aa7a158fea7f967b7691fe73183e8e0bee8017fd 100644 (file)
@@ -1,6 +1,6 @@
 /* src/vm/jit/codegen-common.c - architecture independent code generator stuff
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   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
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Reinhard Grafl
-            Andreas  Krall
-
-   Changes: Christian Thalinger
-            Joseph Wenninger
-                       Edwin Steiner
-
    All functions assume the following code area / data area layout:
 
    +-----------+
@@ -48,8 +39,6 @@
    memory. All functions writing values into the data area return the offset
    relative the begin of the code area (start of procedure).   
 
-   $Id: codegen-common.c 4898 2006-05-10 15:51:46Z twisti $
-
 */
 
 
 #include "vm/types.h"
 
 #if defined(ENABLE_JIT)
-/* this is required for gen_resolvebranch and PATCHER_CALL_SIZE */
+/* this is required PATCHER_CALL_SIZE */
 # include "codegen.h"
 #endif
 
-#if defined(__ARM__)
-/* this is required for REG_SPLIT */
-# include "md-abi.h"
-#endif
-
 #include "mm/memory.h"
+
 #include "toolbox/avl.h"
+#include "toolbox/list.h"
 #include "toolbox/logging.h"
+
 #include "native/jni.h"
+#include "native/localref.h"
 #include "native/native.h"
 
-#if defined(USE_THREADS)
-# if defined(NATIVE_THREADS)
-#  include "threads/native/threads.h"
-# else
-#  include "threads/green/threads.h"
-# endif
-#endif
+#include "threads/threads-common.h"
 
 #include "vm/exceptions.h"
-#include "vm/method.h"
-#include "vm/options.h"
-#include "vm/statistics.h"
 #include "vm/stringlocal.h"
+
+#include "vm/jit/abi.h"
 #include "vm/jit/asmpart.h"
 #include "vm/jit/codegen-common.h"
 
 #endif
 
 #include "vm/jit/dseg.h"
+#include "vm/jit/emit-common.h"
 #include "vm/jit/jit.h"
-#include "vm/jit/stacktrace.h"
+#include "vm/jit/md.h"
+#include "vm/jit/patcher-common.h"
 #include "vm/jit/replace.h"
+#if defined(ENABLE_SSA)
+# include "vm/jit/optimizing/lsra.h"
+# include "vm/jit/optimizing/ssa.h"
+#endif
+#include "vm/jit/stacktrace.h"
+
+#if defined(ENABLE_INTRP)
+#include "vm/jit/intrp/intrp.h"
+#endif
 
+#include "vmcore/method.h"
+#include "vmcore/options.h"
 
-/* in this tree we store all method addresses *********************************/
+# include "vmcore/statistics.h"
 
-#if defined(__I386__) || defined(__X86_64__) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
-static avl_tree *methodtree = NULL;
-static s4 methodtree_comparator(const void *pc, const void *element);
+#if defined(ENABLE_VMLOG)
+#include <vmlog_cacao.h>
 #endif
 
+#include "show.h"
+
+/* in this tree we store all method addresses *********************************/
+
+static avl_tree_t *methodtree = NULL;
+static s4 methodtree_comparator(const void *treenode, const void *node);
+
 
 /* codegen_init ****************************************************************
 
@@ -118,7 +118,6 @@ static s4 methodtree_comparator(const void *pc, const void *element);
 
 void codegen_init(void)
 {
-#if defined(__I386__) || defined(__X86_64__) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
        /* this tree is global, not method specific */
 
        if (!methodtree) {
@@ -134,12 +133,13 @@ void codegen_init(void)
                mte = NEW(methodtree_element);
 
                mte->startpc = (u1 *) (ptrint) asm_vm_call_method;
-               mte->endpc   = (u1 *) ((ptrint) asm_call_jit_compiler - 1);
+               mte->endpc   = (u1 *) (ptrint) asm_vm_call_method_end;
 
                avl_insert(methodtree, mte);
 #endif /* defined(ENABLE_JIT) */
+
        }
-#endif /* defined(__I386__) || defined(__X86_64__) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
+
 }
 
 
@@ -159,9 +159,13 @@ void codegen_setup(jitdata *jd)
        m  = jd->m;
        cd = jd->cd;
 
-       cd->mcodebase = DMNEW(u1, MCODEINITSIZE);
-       cd->mcodeend  = cd->mcodebase + MCODEINITSIZE;
-       cd->mcodesize = MCODEINITSIZE;
+       /* initialize members */
+
+       cd->flags        = 0;
+
+       cd->mcodebase    = DMNEW(u1, MCODEINITSIZE);
+       cd->mcodeend     = cd->mcodebase + MCODEINITSIZE;
+       cd->mcodesize    = MCODEINITSIZE;
 
        /* initialize mcode variables */
 
@@ -183,45 +187,159 @@ void codegen_setup(jitdata *jd)
                cd->superstarts = NULL;
        }
 #endif
-       
-       cd->dsegtop = DMNEW(u1, DSEGINITSIZE);
-       cd->dsegsize = DSEGINITSIZE;
-       cd->dsegtop += cd->dsegsize;
-       cd->dseglen = 0;
+
+       cd->dseg           = NULL;
+       cd->dseglen        = 0;
 
        cd->jumpreferences = NULL;
 
-#if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(ENABLE_INTRP)
+#if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
        cd->datareferences = NULL;
 #endif
 
-       cd->exceptionrefs  = NULL;
+/*     cd->patchrefs      = list_create_dump(OFFSET(patchref, linkage)); */
        cd->patchrefs      = NULL;
+       cd->brancheslabel  = list_create_dump(OFFSET(branch_label_ref_t, linkage));
+       cd->listcritical   = list_create_dump(OFFSET(critical_section_ref_t, linkage));
 
        cd->linenumberreferences = NULL;
        cd->linenumbertablesizepos = 0;
        cd->linenumbertablestartpos = 0;
        cd->linenumbertab = 0;
+}
+
+
+/* codegen_reset ***************************************************************
+
+   Resets the codegen data structure so we can recompile the method.
+
+*******************************************************************************/
+
+static void codegen_reset(jitdata *jd)
+{
+       codeinfo    *code;
+       codegendata *cd;
+       basicblock  *bptr;
+
+       /* get required compiler data */
+
+       code = jd->code;
+       cd   = jd->cd;
+
+       /* reset error flag */
+
+       cd->flags          &= ~CODEGENDATA_FLAG_ERROR;
+
+       /* reset some members, we reuse the code memory already allocated
+          as this should have almost the correct size */
+
+       cd->mcodeptr        = cd->mcodebase;
+       cd->lastmcodeptr    = cd->mcodebase;
+
+       cd->dseg            = NULL;
+       cd->dseglen         = 0;
+
+       cd->jumpreferences  = NULL;
+
+#if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
+       cd->datareferences  = NULL;
+#endif
+
+/*     cd->patchrefs       = list_create_dump(OFFSET(patchref, linkage)); */
+       cd->patchrefs       = NULL;
+       cd->brancheslabel   = list_create_dump(OFFSET(branch_label_ref_t, linkage));
+       cd->listcritical    = list_create_dump(OFFSET(critical_section_ref_t, linkage));
+
+       cd->linenumberreferences    = NULL;
+       cd->linenumbertablesizepos  = 0;
+       cd->linenumbertablestartpos = 0;
+       cd->linenumbertab           = 0;
        
-       cd->method = m;
-       cd->exceptiontable = 0;
-       cd->exceptiontablelength = 0;
+       /* We need to clear the mpc and the branch references from all
+          basic blocks as they will definitely change. */
 
-       if (m->exceptiontablelength > 0) {
-               cd->exceptiontablelength = m->exceptiontablelength;
-               cd->exceptiontable = DMNEW(exceptiontable, m->exceptiontablelength + 1);
+       for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
+               bptr->mpc        = -1;
+               bptr->branchrefs = NULL;
        }
 
-       cd->maxstack = m->maxstack;
-       cd->maxlocals = m->maxlocals;
+       /* We need to clear all the patcher references from the codeinfo
+          since they all will be regenerated */
 
-#if defined(USE_THREADS) && defined(NATIVE_THREADS)
-       cd->threadcritcurrent.next = NULL;
-       cd->threadcritcount = 0;
+       patcher_list_reset(code);
+
+#if defined(ENABLE_REPLACEMENT)
+       code->rplpoints     = NULL;
+       code->rplpointcount = 0;
+       code->regalloc      = NULL;
+       code->regalloccount = 0;
+       code->globalcount   = 0;
 #endif
 }
 
 
+/* codegen_generate ************************************************************
+
+   Generates the code for the currently compiled method.
+
+*******************************************************************************/
+
+bool codegen_generate(jitdata *jd)
+{
+       codegendata *cd;
+
+       /* get required compiler data */
+
+       cd = jd->cd;
+
+       /* call the machine-dependent code generation function */
+
+       if (!codegen_emit(jd))
+               return false;
+
+       /* check for an error */
+
+       if (CODEGENDATA_HAS_FLAG_ERROR(cd)) {
+               /* check for long-branches flag, if it is set we recompile the
+                  method */
+
+#if !defined(NDEBUG)
+        if (compileverbose)
+            log_message_method("Re-generating code: ", jd->m);
+#endif
+
+               /* XXX maybe we should tag long-branches-methods for recompilation */
+
+               if (CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
+                       /* we have to reset the codegendata structure first */
+
+                       codegen_reset(jd);
+
+                       /* and restart the compiler run */
+
+                       if (!codegen_emit(jd))
+                               return false;
+               }
+               else {
+                       vm_abort("codegen_generate: unknown error occurred during codegen_emit: flags=%x\n", cd->flags);
+               }
+
+#if !defined(NDEBUG)
+        if (compileverbose)
+            log_message_method("Re-generating code done: ", jd->m);
+#endif
+       }
+
+       /* reallocate the memory and finish the code generation */
+
+       codegen_finish(jd);
+
+       /* everything's ok */
+
+       return true;
+}
+
+
 /* codegen_close ***************************************************************
 
    TODO
@@ -261,7 +379,8 @@ void codegen_increase(codegendata *cd)
 
        cd->mcodeptr = cd->mcodebase + (cd->mcodeptr - oldmcodebase);
 
-#if defined(__I386__) || defined(__MIPS__) || defined(__X86_64__) || defined(ENABLE_INTRP)
+#if defined(__I386__) || defined(__MIPS__) || defined(__X86_64__) || defined(__M68K__) || defined(ENABLE_INTRP) \
+ || defined(__SPARC_64__)
        /* adjust the pointer to the last patcher position */
 
        if (cd->lastmcodeptr != NULL)
@@ -300,213 +419,361 @@ u1 *codegen_ncode_increase(codegendata *cd, u1 *ncodeptr)
 #endif
 
 
-void codegen_addreference(codegendata *cd, basicblock *target)
-{
-       s4 branchpos;
+/* codegen_add_branch_ref ******************************************************
 
-       branchpos = (u1 *) cd->mcodeptr - cd->mcodebase;
+   Prepends an branch to the list.
 
-#if defined(ENABLE_JIT)
-       /* Check if the target basicblock has already a start pc, so the
-          jump is backward and we can resolve it immediately. */
+*******************************************************************************/
 
-       /* The interpreter uses absolute branches, so we do branch
-          resolving after the code and data segment move. */
+void codegen_add_branch_ref(codegendata *cd, basicblock *target, s4 condition, s4 reg, u4 options)
+{
+       branchref *br;
+       s4         branchmpc;
 
-       if (target->mpc >= 0
-# if defined(ENABLE_INTRP)
-               && !opt_intrp
-# endif
-               )
-       {
-               gen_resolvebranch((u1 *) cd->mcodebase + branchpos,
-                                                 branchpos,
-                                                 target->mpc);
+       STATISTICS(count_branches_unresolved++);
 
-       } else
-#endif
-       {
-               branchref *br = DNEW(branchref);
+       /* calculate the mpc of the branch instruction */
 
-               br->branchpos = branchpos;
-               br->next      = target->branchrefs;
+       branchmpc = cd->mcodeptr - cd->mcodebase;
 
-               target->branchrefs = br;
-       }
+       br = DNEW(branchref);
+
+       br->branchmpc = branchmpc;
+       br->condition = condition;
+       br->reg       = reg;
+       br->options   = options;
+       br->next      = target->branchrefs;
+
+       target->branchrefs = br;
 }
 
 
-/* codegen_add_exception_ref ***************************************************
+/* codegen_resolve_branchrefs **************************************************
 
-   Adds an exception branch to the list.
+   Resolves and patches the branch references of a given basic block.
 
 *******************************************************************************/
 
-static void codegen_add_exception_ref(codegendata *cd, s4 reg,
-                                                                         functionptr function)
+void codegen_resolve_branchrefs(codegendata *cd, basicblock *bptr)
 {
-       s4            branchpos;
-       exceptionref *eref;
+       branchref *br;
+       u1        *mcodeptr;
 
-       branchpos = (u1 *) cd->mcodeptr - cd->mcodebase;
+       /* Save the mcodeptr because in the branch emitting functions
+          we generate code somewhere inside already generated code,
+          but we're still in the actual code generation phase. */
 
-       eref = DNEW(exceptionref);
+       mcodeptr = cd->mcodeptr;
 
-       eref->branchpos = branchpos;
-       eref->reg       = reg;
-       eref->function  = function;
-       eref->next      = cd->exceptionrefs;
+       /* just to make sure */
 
-       cd->exceptionrefs = eref;
-}
+       assert(bptr->mpc >= 0);
 
+       for (br = bptr->branchrefs; br != NULL; br = br->next) {
+               /* temporary set the mcodeptr */
 
-/* codegen_add_arithmeticexception_ref *****************************************
+               cd->mcodeptr = cd->mcodebase + br->branchmpc;
 
-   Adds an ArithmeticException branch to the list.
+               /* emit_bccz and emit_branch emit the correct code, even if we
+                  pass condition == BRANCH_UNCONDITIONAL or reg == -1. */
 
-*******************************************************************************/
+               emit_bccz(cd, bptr, br->condition, br->reg, br->options);
+       }
 
-void codegen_add_arithmeticexception_ref(codegendata *cd)
-{
-       codegen_add_exception_ref(cd, -1, STACKTRACE_inline_arithmeticexception);
+       /* restore mcodeptr */
+
+       cd->mcodeptr = mcodeptr;
 }
 
 
-/* codegen_add_arrayindexoutofboundsexception_ref ******************************
+/* codegen_branch_label_add ****************************************************
 
-   Adds an ArrayIndexOutOfBoundsException branch to the list.
+   Append an branch to the label-branch list.
 
 *******************************************************************************/
 
-void codegen_add_arrayindexoutofboundsexception_ref(codegendata *cd, s4 reg)
+void codegen_branch_label_add(codegendata *cd, s4 label, s4 condition, s4 reg, u4 options)
 {
-       codegen_add_exception_ref(cd, reg,
-                                                         STACKTRACE_inline_arrayindexoutofboundsexception);
+       list_t             *list;
+       branch_label_ref_t *br;
+       s4                  mpc;
+
+       /* get the label list */
+
+       list = cd->brancheslabel;
+       
+       /* calculate the current mpc */
+
+       mpc = cd->mcodeptr - cd->mcodebase;
+
+       br = DNEW(branch_label_ref_t);
+
+       br->mpc       = mpc;
+       br->label     = label;
+       br->condition = condition;
+       br->reg       = reg;
+       br->options   = options;
+
+       /* add the branch to the list */
+
+       list_add_last_unsynced(list, br);
 }
 
 
-/* codegen_add_arraystoreexception_ref *****************************************
+/* codegen_add_patch_ref *******************************************************
 
-   Adds an ArrayStoreException branch to the list.
+   Appends a new patcher reference to the list of patching positions.
 
 *******************************************************************************/
 
-void codegen_add_arraystoreexception_ref(codegendata *cd)
+void codegen_add_patch_ref(codegendata *cd, functionptr patcher, voidptr ref,
+                                                  s4 disp)
 {
-       codegen_add_exception_ref(cd, -1, STACKTRACE_inline_arraystoreexception);
+       patchref *pr;
+       s4        branchmpc;
+
+       branchmpc = cd->mcodeptr - cd->mcodebase;
+
+       pr = DNEW(patchref);
+
+       pr->branchpos = branchmpc;
+       pr->disp      = disp;
+       pr->patcher   = patcher;
+       pr->ref       = ref;
+
+/*     list_add_first(cd->patchrefs, pr); */
+       pr->next      = cd->patchrefs;
+       cd->patchrefs = pr;
+
+       /* Generate NOPs for opt_shownops. */
+
+       if (opt_shownops)
+               PATCHER_NOPS;
+
+#if defined(ENABLE_JIT) && (defined(__I386__) || defined(__M68K__) || defined(__MIPS__) \
+ || defined(__SPARC_64__) || defined(__X86_64__))
+
+       /* On some architectures the patcher stub call instruction might
+          be longer than the actual instruction generated.  On this
+          architectures we store the last patcher call position and after
+          the basic block code generation is completed, we check the
+          range and maybe generate some nop's. */
+       /* The nops are generated in codegen_emit in each codegen */
+
+       cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
+#endif
 }
 
 
-/* codegen_add_classcastexception_ref ******************************************
+/* codegen_critical_section_new ************************************************
 
-   Adds an ClassCastException branch to the list.
+   Allocates a new critical-section reference and adds it to the
+   critical-section list.
 
 *******************************************************************************/
 
-void codegen_add_classcastexception_ref(codegendata *cd)
+#if defined(ENABLE_THREADS)
+void codegen_critical_section_new(codegendata *cd)
 {
-       codegen_add_exception_ref(cd, -1, STACKTRACE_inline_classcastexception);
+       list_t                 *list;
+       critical_section_ref_t *csr;
+       s4                      mpc;
+
+       /* get the critical section list */
+
+       list = cd->listcritical;
+       
+       /* calculate the current mpc */
+
+       mpc = cd->mcodeptr - cd->mcodebase;
+
+       csr = DNEW(critical_section_ref_t);
+
+       /* We only can set restart right now, as start and end are set by
+          the following, corresponding functions. */
+
+       csr->start   = -1;
+       csr->end     = -1;
+       csr->restart = mpc;
+
+       /* add the branch to the list */
+
+       list_add_last_unsynced(list, csr);
 }
+#endif
 
 
-/* codegen_add_nullpointerexception_ref ****************************************
+/* codegen_critical_section_start **********************************************
 
-   Adds an NullPointerException branch to the list.
+   Set the start-point of the current critical section (which is the
+   last element of the list).
 
 *******************************************************************************/
 
-void codegen_add_nullpointerexception_ref(codegendata *cd)
+#if defined(ENABLE_THREADS)
+void codegen_critical_section_start(codegendata *cd)
 {
-       codegen_add_exception_ref(cd, -1, STACKTRACE_inline_nullpointerexception);
+       list_t                 *list;
+       critical_section_ref_t *csr;
+       s4                      mpc;
+
+       /* get the critical section list */
+
+       list = cd->listcritical;
+       
+       /* calculate the current mpc */
+
+       mpc = cd->mcodeptr - cd->mcodebase;
+
+       /* get the current critical section */
+
+       csr = list_last_unsynced(list);
+
+       /* set the start point */
+
+       assert(csr->start == -1);
+
+       csr->start = mpc;
 }
+#endif
 
 
-/* codegen_add_fillinstacktrace_ref ********************************************
+/* codegen_critical_section_end ************************************************
 
-   Adds a fillInStackTrace branch to the list.
+   Set the end-point of the current critical section (which is the
+   last element of the list).
 
 *******************************************************************************/
 
-void codegen_add_fillinstacktrace_ref(codegendata *cd)
+#if defined(ENABLE_THREADS)
+void codegen_critical_section_end(codegendata *cd)
 {
-       codegen_add_exception_ref(cd, -1, STACKTRACE_inline_fillInStackTrace);
+       list_t                 *list;
+       critical_section_ref_t *csr;
+       s4                      mpc;
+
+       /* get the critical section list */
+
+       list = cd->listcritical;
+       
+       /* calculate the current mpc */
+
+       mpc = cd->mcodeptr - cd->mcodebase;
+
+       /* get the current critical section */
+
+       csr = list_last_unsynced(list);
+
+       /* set the end point */
+
+       assert(csr->end == -1);
+
+       csr->end = mpc;
 }
+#endif
 
 
-/* codegen_addpatchref *********************************************************
+/* codegen_critical_section_finish *********************************************
 
-   Adds a new patcher reference to the list of patching positions.
+   Finish the critical sections, create the critical section nodes for
+   the AVL tree and insert them into the tree.
 
 *******************************************************************************/
 
-void codegen_addpatchref(codegendata *cd, functionptr patcher, voidptr ref,
-                                                s4 disp)
+#if defined(ENABLE_THREADS)
+static void codegen_critical_section_finish(jitdata *jd)
 {
-       patchref *pr;
-       s4        branchpos;
+       codeinfo    *code;
+       codegendata *cd;
+       list_t                  *list;
+       critical_section_ref_t  *csr;
+       critical_section_node_t *csn;
 
-       branchpos = (u1 *) cd->mcodeptr - cd->mcodebase;
+       /* get required compiler data */
 
-       pr = DNEW(patchref);
+       code = jd->code;
+       cd   = jd->cd;
 
-       pr->branchpos = branchpos;
-       pr->patcher   = patcher;
-       pr->ref       = ref;
-       pr->disp      = disp;
+       /* get the critical section list */
 
-       pr->next      = cd->patchrefs;
-       cd->patchrefs = pr;
+       list = cd->listcritical;
 
-#if defined(ENABLE_JIT) && (defined(__I386__) || defined(__MIPS__) || defined(__X86_64__))
-       /* On some architectures the patcher stub call instruction might
-          be longer than the actual instruction generated.  On this
-          architectures we store the last patcher call position and after
-          the basic block code generation is completed, we check the
-          range and maybe generate some nop's. */
+       /* iterate over all critical sections */
 
-       cd->lastmcodeptr = ((u1 *) cd->mcodeptr) + PATCHER_CALL_SIZE;
-#endif
+       for (csr = list_first_unsynced(list); csr != NULL;
+                csr = list_next_unsynced(list, csr)) {
+               /* check if all points are set */
+
+               assert(csr->start   != -1);
+               assert(csr->end     != -1);
+               assert(csr->restart != -1);
+
+               /* allocate tree node */
+
+               csn = NEW(critical_section_node_t);
+
+               csn->start   = code->entrypoint + csr->start;
+               csn->end     = code->entrypoint + csr->end;
+               csn->restart = code->entrypoint + csr->restart;
+
+               /* insert into the tree */
+
+               critical_section_register(csn);
+       }
 }
+#endif
 
 
-#if defined(__I386__) || defined(__X86_64__) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
 /* methodtree_comparator *******************************************************
 
-   XXX
+   Comparator function used for the AVL tree of methods.
+
+   ARGUMENTS:
+      treenode....the node from the tree
+      node........the node to compare to the tree-node
 
 *******************************************************************************/
 
-static s4 methodtree_comparator(const void *pc, const void *element)
+static s4 methodtree_comparator(const void *treenode, const void *node)
 {
        methodtree_element *mte;
        methodtree_element *mtepc;
 
-       mte = (methodtree_element *) element;
-       mtepc = (methodtree_element *) pc;
+       mte   = (methodtree_element *) treenode;
+       mtepc = (methodtree_element *) node;
 
        /* compare both startpc and endpc of pc, even if they have the same value,
           otherwise the avl_probe sometimes thinks the element is already in the
           tree */
 
-       if ((long) mte->startpc <= (long) mtepc->startpc &&
-               (long) mtepc->startpc <= (long) mte->endpc &&
-               (long) mte->startpc <= (long) mtepc->endpc &&
-               (long) mtepc->endpc <= (long) mte->endpc) {
+#ifdef __S390__
+       /* On S390 addresses are 31 bit. Compare only 31 bits of value.
+        */
+#      define ADDR_MASK(a) ((a) & 0x7FFFFFFF)
+#else
+#      define ADDR_MASK(a) (a)
+#endif
+
+       if (ADDR_MASK((long) mte->startpc) <= ADDR_MASK((long) mtepc->startpc) &&
+               ADDR_MASK((long) mtepc->startpc) <= ADDR_MASK((long) mte->endpc) &&
+               ADDR_MASK((long) mte->startpc) <= ADDR_MASK((long) mtepc->endpc) &&
+               ADDR_MASK((long) mtepc->endpc) <= ADDR_MASK((long) mte->endpc)) {
                return 0;
 
-       } else if ((long) mtepc->startpc < (long) mte->startpc) {
+       } else if (ADDR_MASK((long) mtepc->startpc) < ADDR_MASK((long) mte->startpc)) {
                return -1;
 
        } else {
                return 1;
        }
+
+#      undef ADDR_MASK
 }
 
 
 /* codegen_insertmethod ********************************************************
 
-   XXX
+   Insert the machine code range of a method into the AVL tree of methods.
 
 *******************************************************************************/
 
@@ -528,13 +795,14 @@ void codegen_insertmethod(u1 *startpc, u1 *endpc)
 }
 
 
-/* codegen_findmethod **********************************************************
+/* codegen_get_pv_from_pc ******************************************************
 
-   XXX
+   Find the PV for the given PC by searching in the AVL tree of
+   methods.
 
 *******************************************************************************/
 
-u1 *codegen_findmethod(u1 *pc)
+u1 *codegen_get_pv_from_pc(u1 *pc)
 {
        methodtree_element  mtepc;
        methodtree_element *mte;
@@ -546,17 +814,114 @@ u1 *codegen_findmethod(u1 *pc)
 
        mte = avl_find(methodtree, &mtepc);
 
-       if (!mte) {
-               printf("Cannot find Java function at %p\n", (void *) (ptrint) pc);
+       if (mte == NULL) {
+               /* No method was found.  Let's dump a stacktrace. */
+
+#if defined(ENABLE_VMLOG)
+               vmlog_cacao_signl("SIGSEGV");
+#endif
+
+               log_println("We received a SIGSEGV and tried to handle it, but we were");
+               log_println("unable to find a Java method at:");
+               log_println("");
+#if SIZEOF_VOID_P == 8
+               log_println("PC=0x%016lx", pc);
+#else
+               log_println("PC=0x%08x", pc);
+#endif
+               log_println("");
                assert(0);
+               log_println("Dumping the current stacktrace:");
+
+#if defined(ENABLE_THREADS)
+               /* XXX michi: This should be available even without threads! */
+               threads_print_stacktrace();
+#endif
 
-               throw_cacao_exception_exit(string_java_lang_InternalError,
-                                                                  "Cannot find Java function at %p", pc);
+               vm_abort("Exiting...");
        }
 
        return mte->startpc;
 }
-#endif /* defined(__I386__) || defined(__X86_64__) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
+
+
+/* codegen_get_pv_from_pc_nocheck **********************************************
+
+   Find the PV for the given PC by searching in the AVL tree of
+   methods.  This method does not check the return value and is used
+   by the profiler.
+
+*******************************************************************************/
+
+u1 *codegen_get_pv_from_pc_nocheck(u1 *pc)
+{
+       methodtree_element  mtepc;
+       methodtree_element *mte;
+
+       /* allocation of the search structure on the stack is much faster */
+
+       mtepc.startpc = pc;
+       mtepc.endpc   = pc;
+
+       mte = avl_find(methodtree, &mtepc);
+
+       if (mte == NULL)
+               return NULL;
+       else
+               return mte->startpc;
+}
+
+
+/* codegen_set_replacement_point_notrap ****************************************
+
+   Record the position of a non-trappable replacement point.
+
+*******************************************************************************/
+
+#if defined(ENABLE_REPLACEMENT)
+#if !defined(NDEBUG)
+void codegen_set_replacement_point_notrap(codegendata *cd, s4 type)
+#else
+void codegen_set_replacement_point_notrap(codegendata *cd)
+#endif
+{
+       assert(cd->replacementpoint);
+       assert(cd->replacementpoint->type == type);
+       assert(cd->replacementpoint->flags & RPLPOINT_FLAG_NOTRAP);
+
+       cd->replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
+
+       cd->replacementpoint++;
+}
+#endif /* defined(ENABLE_REPLACEMENT) */
+
+
+/* codegen_set_replacement_point ***********************************************
+
+   Record the position of a trappable replacement point.
+
+*******************************************************************************/
+
+#if defined(ENABLE_REPLACEMENT)
+#if !defined(NDEBUG)
+void codegen_set_replacement_point(codegendata *cd, s4 type)
+#else
+void codegen_set_replacement_point(codegendata *cd)
+#endif
+{
+       assert(cd->replacementpoint);
+       assert(cd->replacementpoint->type == type);
+       assert(!(cd->replacementpoint->flags & RPLPOINT_FLAG_NOTRAP));
+
+       cd->replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
+
+       cd->replacementpoint++;
+
+       /* XXX assert(cd->lastmcodeptr <= cd->mcodeptr); */
+
+       cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
+}
+#endif /* defined(ENABLE_REPLACEMENT) */
 
 
 /* codegen_finish **************************************************************
@@ -577,8 +942,8 @@ void codegen_finish(jitdata *jd)
 #endif
        s4           alignedmcodelen;
        jumpref     *jr;
+       patchref_t  *pr;
        u1          *epoint;
-       s4           extralen;
        s4           alignedlen;
 
        /* get required compiler data */
@@ -594,13 +959,7 @@ void codegen_finish(jitdata *jd)
 
        /* calculate the code length */
 
-       mcodelen = (s4) ((u1 *) cd->mcodeptr - cd->mcodebase);
-
-#if defined(USE_THREADS) && defined(NATIVE_THREADS)
-       extralen = sizeof(threadcritnode) * cd->threadcritcount;
-#else
-       extralen = 0;
-#endif
+       mcodelen = (s4) (cd->mcodeptr - cd->mcodebase);
 
 #if defined(ENABLE_STATISTICS)
        if (opt_stat) {
@@ -609,7 +968,7 @@ void codegen_finish(jitdata *jd)
        }
 #endif
 
-       alignedmcodelen = ALIGN(mcodelen, MAX_ALIGN);
+       alignedmcodelen = MEMORY_ALIGN(mcodelen, MAX_ALIGN);
 
 #if defined(ENABLE_INTRP)
        if (opt_intrp)
@@ -619,7 +978,7 @@ void codegen_finish(jitdata *jd)
        }
 #endif
 
-       cd->dseglen = ALIGN(cd->dseglen, MAX_ALIGN);
+       cd->dseglen = MEMORY_ALIGN(cd->dseglen, MAX_ALIGN);
        alignedlen = alignedmcodelen + cd->dseglen;
 
 #if defined(ENABLE_INTRP)
@@ -631,18 +990,21 @@ void codegen_finish(jitdata *jd)
        /* allocate new memory */
 
        code->mcodelength = mcodelen + cd->dseglen;
-       code->mcode = CNEW(u1, alignedlen + extralen);
-
-       /* copy data and code to their new location */
-
-       MCOPY((void *) code->mcode, cd->dsegtop - cd->dseglen, u1, cd->dseglen);
-       MCOPY((void *) (code->mcode + cd->dseglen), cd->mcodebase, u1, mcodelen);
+       code->mcode       = CNEW(u1, alignedlen);
 
        /* set the entrypoint of the method */
        
        assert(code->entrypoint == NULL);
        code->entrypoint = epoint = (code->mcode + cd->dseglen);
 
+       /* fill the data segment (code->entrypoint must already be set!) */
+
+       dseg_finish(jd);
+
+       /* copy code to the new location */
+
+       MCOPY((void *) code->entrypoint, cd->mcodebase, u1, mcodelen);
+
 #if defined(ENABLE_INTRP)
        /* relocate native dynamic superinstruction code (if any) */
 
@@ -700,6 +1062,16 @@ void codegen_finish(jitdata *jd)
                *((ptrint *) ((ptrint) epoint + cd->linenumbertablesizepos)) = lrtlen;
        }
 
+       /* patcher resolving */
+
+       pr = list_first_unsynced(code->patchers);
+       while (pr) {
+               pr->mpc += (ptrint) epoint;
+               pr->datap = (ptrint) (pr->disp + epoint);
+               pr = list_next_unsynced(code->patchers, pr);
+       }
+
+#if defined(ENABLE_REPLACEMENT)
        /* replacement point resolving */
        {
                int i;
@@ -708,39 +1080,24 @@ void codegen_finish(jitdata *jd)
                rp = code->rplpoints;
                for (i=0; i<code->rplpointcount; ++i, ++rp) {
                        rp->pc = (u1*) ((ptrint) epoint + (ptrint) rp->pc);
-                       rp->outcode = (u1*) ((ptrint) epoint + (ptrint) rp->outcode);
                }
        }
+#endif /* defined(ENABLE_REPLACEMENT) */
 
-#if defined(__I386__) || defined(__X86_64__) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
        /* add method into methodtree to find the entrypoint */
 
        codegen_insertmethod(code->entrypoint, code->entrypoint + mcodelen);
-#endif
-
 
-#if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(ENABLE_INTRP)
+#if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
        /* resolve data segment references */
 
        dseg_resolve_datareferences(jd);
 #endif
 
+#if defined(ENABLE_THREADS)
+       /* create cirtical sections */
 
-#if defined(USE_THREADS) && defined(NATIVE_THREADS)
-       {
-               threadcritnode *n = (threadcritnode *) ((ptrint) code->mcode + alignedlen);
-               s4 i;
-               threadcritnodetemp *nt = cd->threadcrit;
-
-               for (i = 0; i < cd->threadcritcount; i++) {
-                       n->mcodebegin = (u1 *) (ptrint) code->mcode + nt->mcodebegin;
-                       n->mcodeend = (u1 *) (ptrint) code->mcode + nt->mcodeend;
-                       n->mcoderestart = (u1 *) (ptrint) code->mcode + nt->mcoderestart;
-                       thread_registercritical(n);
-                       n++;
-                       nt = nt->next;
-               }
-       }
+       codegen_critical_section_finish(jd);
 #endif
 
        /* flush the instruction and data caches */
@@ -749,16 +1106,92 @@ void codegen_finish(jitdata *jd)
 }
 
 
-/* codegen_createnativestub ****************************************************
+/* codegen_generate_stub_compiler **********************************************
 
-   Wrapper for createnativestub.
+   Wrapper for codegen_emit_stub_compiler.
+
+   Returns:
+       pointer to the compiler stub code.
+
+*******************************************************************************/
+
+u1 *codegen_generate_stub_compiler(methodinfo *m)
+{
+       jitdata     *jd;
+       codegendata *cd;
+       ptrint      *d;                     /* pointer to data memory             */
+       u1          *c;                     /* pointer to code memory             */
+       s4           dumpsize;
+
+       /* mark dump memory */
+
+       dumpsize = dump_size();
+
+       /* allocate required data structures */
+
+       jd = DNEW(jitdata);
+
+       jd->m     = m;
+       jd->cd    = DNEW(codegendata);
+       jd->flags = 0;
+
+       /* get required compiler data */
+
+       cd = jd->cd;
+
+       /* allocate code memory */
+
+       c = CNEW(u1, 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE);
+
+       /* set pointers correctly */
+
+       d = (ptrint *) c;
+
+       cd->mcodebase = c;
+
+       c = c + 3 * SIZEOF_VOID_P;
+       cd->mcodeptr = c;
+
+       /* NOTE: The codeinfo pointer is actually a pointer to the
+          methodinfo (this fakes a codeinfo structure). */
+
+       d[0] = (ptrint) asm_call_jit_compiler;
+       d[1] = (ptrint) m;
+       d[2] = (ptrint) &d[1];                                    /* fake code->m */
+
+       /* call the emit function */
+
+       codegen_emit_stub_compiler(jd);
+
+#if defined(ENABLE_STATISTICS)
+       if (opt_stat)
+               count_cstub_len += 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE;
+#endif
+
+       /* flush caches */
+
+       md_cacheflush(cd->mcodebase, 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE);
+
+       /* release dump memory */
+
+       dump_release(dumpsize);
+
+       /* return native stub code */
+
+       return c;
+}
+
+
+/* codegen_generate_stub_native ************************************************
+
+   Wrapper for codegen_emit_stub_native.
 
    Returns:
        the codeinfo representing the stub code.
 
 *******************************************************************************/
 
-codeinfo *codegen_createnativestub(functionptr f, methodinfo *m)
+codeinfo *codegen_generate_stub_native(methodinfo *m, functionptr f)
 {
        jitdata     *jd;
        codeinfo    *code;
@@ -776,6 +1209,7 @@ codeinfo *codegen_createnativestub(functionptr f, methodinfo *m)
        jd->m     = m;
        jd->cd    = DNEW(codegendata);
        jd->rd    = DNEW(registerdata);
+       jd->flags = 0;
 
        /* Allocate codeinfo memory from the heap as we need to keep them. */
 
@@ -785,6 +1219,16 @@ codeinfo *codegen_createnativestub(functionptr f, methodinfo *m)
 
        code = jd->code;
 
+       /* set the flags for the current JIT run */
+
+#if defined(ENABLE_PROFILING)
+       if (opt_prof)
+               jd->flags |= JITDATA_FLAG_INSTRUMENT;
+#endif
+
+       if (opt_verbosecall)
+               jd->flags |= JITDATA_FLAG_VERBOSECALL;
+
        /* setup code generation stuff */
 
 #if defined(ENABLE_JIT)
@@ -821,7 +1265,9 @@ codeinfo *codegen_createnativestub(functionptr f, methodinfo *m)
 # if defined(ENABLE_INTRP)
        if (!opt_intrp)
 # endif
-               md_param_alloc(nmd);
+               /* pre-allocate the arguments for the native ABI */
+
+               md_param_alloc_native(nmd);
 #endif
 
        /* generate the code */
@@ -829,33 +1275,44 @@ codeinfo *codegen_createnativestub(functionptr f, methodinfo *m)
 #if defined(ENABLE_JIT)
 # if defined(ENABLE_INTRP)
        if (opt_intrp)
-               code->entrypoint = intrp_createnativestub(f, jd, nmd);
+               intrp_createnativestub(f, jd, nmd);
        else
 # endif
-               code->entrypoint = createnativestub(f, jd, nmd);
+               codegen_emit_stub_native(jd, nmd, f);
 #else
-       code->entrypoint = intrp_createnativestub(f, jd, nmd);
+       intrp_createnativestub(f, jd, nmd);
 #endif
 
+       /* reallocate the memory and finish the code generation */
+
+       codegen_finish(jd);
+
 #if defined(ENABLE_STATISTICS)
+       /* must be done after codegen_finish() */
+
        if (opt_stat)
-               count_nstub_len += code->mcodelength;
+               size_stub_native += code->mcodelength;
 #endif
 
 #if !defined(NDEBUG)
        /* disassemble native stub */
 
        if (opt_shownativestub) {
+#if defined(ENABLE_DEBUG_FILTER)
+               if (m->filtermatches & SHOW_FILTER_FLAG_SHOW_METHOD)
+#endif
+               {
 #if defined(ENABLE_DISASSEMBLER)
-               codegen_disassemble_nativestub(m,
-                                                                          (u1 *) (ptrint) code->entrypoint,
-                                                                          (u1 *) (ptrint) code->entrypoint + (code->mcodelength - jd->cd->dseglen));
+                       codegen_disassemble_nativestub(m,
+                                                                                  (u1 *) (ptrint) code->entrypoint,
+                                                                                  (u1 *) (ptrint) code->entrypoint + (code->mcodelength - jd->cd->dseglen));
 #endif
 
-               /* show data segment */
+                       /* show data segment */
 
-               if (opt_showddatasegment)
-                       dseg_display(jd);
+                       if (opt_showddatasegment)
+                               dseg_display(jd);
+               }
        }
 #endif /* !defined(NDEBUG) */
 
@@ -922,6 +1379,8 @@ void codegen_start_native_call(u1 *datasp, u1 *pv, u1 *sp, u1 *ra)
        stackframeinfo *sfi;
        localref_table *lrt;
 
+       STATISTICS(count_calls_java_to_native++);
+
        /* get data structures from stack */
 
        sfi = (stackframeinfo *) (datasp - sizeof(stackframeinfo));
@@ -932,74 +1391,50 @@ void codegen_start_native_call(u1 *datasp, u1 *pv, u1 *sp, u1 *ra)
 
        stacktrace_create_native_stackframeinfo(sfi, pv, sp, ra);
 
+#if defined(ENABLE_JNI)
        /* add current JNI local references table to this thread */
 
-       lrt->capacity    = LOCALREFTABLE_CAPACITY;
-       lrt->used        = 0;
-       lrt->localframes = 1;
-       lrt->prev        = LOCALREFTABLE;
-
-       /* clear the references array (memset is faster the a for-loop) */
-
-       MSET(lrt->refs, 0, java_objectheader*, LOCALREFTABLE_CAPACITY);
-
-       LOCALREFTABLE = lrt;
+       localref_table_add(lrt);
+#endif
 }
 
 
 /* codegen_finish_native_call **************************************************
 
    Removes the stuff required for a native (JNI) function call.
+   Additionally it checks for an exceptions and in case, get the
+   exception object and clear the pointer.
 
 *******************************************************************************/
 
-void codegen_finish_native_call(u1 *datasp)
+java_object_t *codegen_finish_native_call(u1 *datasp)
 {
        stackframeinfo  *sfi;
        stackframeinfo **psfi;
-       localref_table  *lrt;
-       localref_table  *plrt;
-       s4               localframes;
+       java_handle_t   *e;
 
        /* get data structures from stack */
 
        sfi = (stackframeinfo *) (datasp - sizeof(stackframeinfo));
-       lrt = (localref_table *) (datasp - sizeof(stackframeinfo) - 
-                                                         sizeof(localref_table));
 
        /* remove current stackframeinfo from chain */
 
-       psfi = STACKFRAMEINFO;
+       psfi = &STACKFRAMEINFO;
 
        *psfi = sfi->prev;
 
-       /* release JNI local references tables for this thread */
-
-       lrt = LOCALREFTABLE;
-
-       /* release all current local frames */
-
-       for (localframes = lrt->localframes; localframes >= 1; localframes--) {
-               /* get previous frame */
-
-               plrt = lrt->prev;
-
-               /* Clear all reference entries (only for tables allocated on
-                  the Java heap). */
+#if defined(ENABLE_JNI)
+       /* release JNI local references table for this thread */
 
-               if (localframes > 1)
-                       MSET(&lrt->refs[0], 0, java_objectheader*, lrt->capacity);
-
-               lrt->prev = NULL;
-
-               /* set new local references table */
+       localref_frame_pop_all();
+       localref_table_remove();
+#endif
 
-               lrt = plrt;
-       }
+       /* get the exception and return it */
 
-       /* now store the previous local frames in the thread structure */
+       e = exceptions_get_and_clear_exception();
 
-       LOCALREFTABLE = lrt;
+       return e;
 }
 
 
@@ -1040,101 +1475,133 @@ void removenativestub(u1 *stub)
    spilled) this function returns tempregnum.  If not already done,
    regoff and flags are set in the stack location.
        
-   On ARM we have to check if a long/double variable is splitted
-   across reg/stack (HIGH_REG == REG_SPLIT). We return the actual
-   register of v for LOW_REG and the tempregnum for HIGH_REG in such
-   cases.  (michi 2005/07/24)
-
 *******************************************************************************/
 
-s4 codegen_reg_of_var(registerdata *rd, u2 opcode, stackptr v, s4 tempregnum)
+s4 codegen_reg_of_var(u2 opcode, varinfo *v, s4 tempregnum)
 {
-       varinfo *var;
 
+#if 0
        /* Do we have to generate a conditional move?  Yes, then always
           return the temporary register.  The real register is identified
           during the store. */
 
        if (opcode & ICMD_CONDITION_MASK)
                return tempregnum;
-
-       switch (v->varkind) {
-       case TEMPVAR:
-               if (!(v->flags & INMEMORY))
-                       return(v->regoff);
-               break;
-
-       case STACKVAR:
-               var = &(rd->interfaces[v->varnum][v->type]);
-               v->regoff = var->regoff;
-               if (!(var->flags & INMEMORY))
-                       return(var->regoff);
-               break;
-
-       case LOCALVAR:
-               var = &(rd->locals[v->varnum][v->type]);
-               v->regoff = var->regoff;
-               if (!(var->flags & INMEMORY)) {
-#if defined(__ARM__) && defined(__ARMEL__)
-                       if (IS_2_WORD_TYPE(v->type) && (GET_HIGH_REG(var->regoff) == REG_SPLIT))
-                               return(PACK_REGS(GET_LOW_REG(var->regoff), GET_HIGH_REG(tempregnum)));
 #endif
-#if defined(__ARM__) && defined(__ARMEB__)
-                       if (IS_2_WORD_TYPE(v->type) && (GET_LOW_REG(var->regoff) == REG_SPLIT))
-                               return(PACK_REGS(GET_LOW_REG(tempregnum), GET_HIGH_REG(var->regoff)));
-#endif
-                       return(var->regoff);
-               }
-               break;
 
-       case ARGVAR:
-               if (!(v->flags & INMEMORY)) {
-#if defined(__ARM__) && defined(__ARMEL__)
-                       if (IS_2_WORD_TYPE(v->type) && (GET_HIGH_REG(v->regoff) == REG_SPLIT))
-                               return(PACK_REGS(GET_LOW_REG(v->regoff), GET_HIGH_REG(tempregnum)));
-#endif
-#if defined(__ARM__) && defined(__ARMEB__)
-                       if (IS_2_WORD_TYPE(v->type) && (GET_LOW_REG(v->regoff) == REG_SPLIT))
-                               return(PACK_REGS(GET_LOW_REG(tempregnum), GET_HIGH_REG(v->regoff)));
-#endif
-                       return(v->regoff);
-               }
-               break;
-       }
-
-#if defined(ENABLE_STATISTICS)
-       if (opt_stat)
-               count_spills_read++;
-#endif
-
-       v->flags |= INMEMORY;
+       if (!(v->flags & INMEMORY))
+               return v->vv.regoff;
 
        return tempregnum;
 }
 
 
-#if defined(USE_THREADS) && defined(NATIVE_THREADS)
-void codegen_threadcritrestart(codegendata *cd, int offset)
-{
-       cd->threadcritcurrent.mcoderestart = offset;
-}
+/* codegen_reg_of_dst **********************************************************
 
+   This function determines a register, to which the result of an
+   operation should go, when it is ultimatively intended to store the
+   result in iptr->dst.var.  If dst.var is assigned to an actual
+   register, this register will be returned.  Otherwise (when it is
+   spilled) this function returns tempregnum.  If not already done,
+   regoff and flags are set in the stack location.
+       
+*******************************************************************************/
 
-void codegen_threadcritstart(codegendata *cd, int offset)
+s4 codegen_reg_of_dst(jitdata *jd, instruction *iptr, s4 tempregnum)
 {
-       cd->threadcritcurrent.mcodebegin = offset;
+       return codegen_reg_of_var(iptr->opc, VAROP(iptr->dst), tempregnum);
 }
 
 
-void codegen_threadcritstop(codegendata *cd, int offset)
+/* codegen_emit_phi_moves ****************************************************
+
+   Emits phi moves at the end of the basicblock.
+
+*******************************************************************************/
+
+#if defined(ENABLE_SSA)
+void codegen_emit_phi_moves(jitdata *jd, basicblock *bptr)
 {
-       cd->threadcritcurrent.next = cd->threadcrit;
-       cd->threadcritcurrent.mcodeend = offset;
-       cd->threadcrit = DNEW(threadcritnodetemp);
-       *(cd->threadcrit) = cd->threadcritcurrent;
-       cd->threadcritcount++;
-}
+       int lt_d,lt_s,i;
+       lsradata *ls;
+       codegendata *cd;
+       varinfo *s, *d;
+       instruction tmp_i;
+
+       cd = jd->cd;
+       ls = jd->ls;
+
+       MCODECHECK(512);
+
+       /* Moves from phi functions with highest indices have to be */
+       /* inserted first, since this is the order as is used for   */
+       /* conflict resolution */
+
+       for(i = ls->num_phi_moves[bptr->nr] - 1; i >= 0 ; i--) {
+               lt_d = ls->phi_moves[bptr->nr][i][0];
+               lt_s = ls->phi_moves[bptr->nr][i][1];
+#if defined(SSA_DEBUG_VERBOSE)
+               if (compileverbose)
+                       printf("BB %3i Move %3i <- %3i ", bptr->nr, lt_d, lt_s);
+#endif
+               if (lt_s == UNUSED) {
+#if defined(SSA_DEBUG_VERBOSE)
+               if (compileverbose)
+                       printf(" ... not processed \n");
+#endif
+                       continue;
+               }
+                       
+               d = VAR(ls->lifetime[lt_d].v_index);
+               s = VAR(ls->lifetime[lt_s].v_index);
+               
+
+               if (d->type == -1) {
+#if defined(SSA_DEBUG_VERBOSE)
+                       if (compileverbose)
+                               printf("...returning - phi lifetimes where joined\n");
+#endif
+                       return;
+               }
+
+               if (s->type == -1) {
+#if defined(SSA_DEBUG_VERBOSE)
+                       if (compileverbose)
+                               printf("...returning - phi lifetimes where joined\n");
 #endif
+                       return;
+               }
+
+               tmp_i.opc = 0;
+               tmp_i.s1.varindex = ls->lifetime[lt_s].v_index;
+               tmp_i.dst.varindex = ls->lifetime[lt_d].v_index;
+               emit_copy(jd, &tmp_i);
+
+#if defined(SSA_DEBUG_VERBOSE)
+               if (compileverbose) {
+                       if (IS_INMEMORY(d->flags) && IS_INMEMORY(s->flags)) {
+                               /* mem -> mem */
+                               printf("M%3i <- M%3i",d->vv.regoff,s->vv.regoff);
+                       }
+                       else if (IS_INMEMORY(s->flags)) {
+                               /* mem -> reg */
+                               printf("R%3i <- M%3i",d->vv.regoff,s->vv.regoff);
+                       }
+                       else if (IS_INMEMORY(d->flags)) {
+                               /* reg -> mem */
+                               printf("M%3i <- R%3i",d->vv.regoff,s->vv.regoff);
+                       }
+                       else {
+                               /* reg -> reg */
+                               printf("R%3i <- R%3i",d->vv.regoff,s->vv.regoff);
+                       }
+                       printf("\n");
+               }
+#endif /* defined(SSA_DEBUG_VERBOSE) */
+       }
+}
+#endif /* defined(ENABLE_SSA) */
+
 
 
 /*