* src/toolbox/list.h (listnode): Renamed to listnode_t.
[cacao.git] / src / vm / jit / codegen-common.c
index cc933b6c80f07bca5870d5fa0c6608f424d9d275..9ee08b65ab10557a7300a33a7f6ca5cf315d0a7a 100644 (file)
@@ -1,9 +1,9 @@
 /* src/vm/jit/codegen-common.c - architecture independent code generator stuff
 
-   Copyright (C) 1996-2005 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 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
 
    This file is part of CACAO.
 
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-   02111-1307, USA.
-
-   Contact: cacao@complang.tuwien.ac.at
-
-   Authors: Reinhard Grafl
-            Andreas  Krall
-
-   Changes: Christian Thalinger
-            Joseph Wenninger
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
 
    All functions assume the following code area / data area layout:
 
@@ -47,7 +39,7 @@
    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 4203 2006-01-13 19:37:17Z twisti $
+   $Id: codegen-common.c 7783 2007-04-20 13:28:27Z twisti $
 
 */
 
@@ -60,7 +52,7 @@
 #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
 
 #endif
 
 #include "mm/memory.h"
+
 #include "toolbox/avl.h"
+#include "toolbox/list.h"
 #include "toolbox/logging.h"
+
 #include "native/jni.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"
-#include "vm/jit/disass.h"
+
+#if defined(ENABLE_DISASSEMBLER)
+# include "vm/jit/disass.h"
+#endif
+
 #include "vm/jit/dseg.h"
+#include "vm/jit/emit-common.h"
 #include "vm/jit/jit.h"
+#include "vm/jit/md.h"
+#include "vm/jit/replace.h"
 #include "vm/jit/stacktrace.h"
 
+#if defined(ENABLE_INTRP)
+#include "vm/jit/intrp/intrp.h"
+#endif
+
+#include "vmcore/method.h"
+#include "vmcore/options.h"
+
+# include "vmcore/statistics.h"
+
 
 /* in this tree we store all method addresses *********************************/
 
-#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);
-#endif
 
 
 /* codegen_init ****************************************************************
@@ -112,7 +114,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) {
@@ -123,44 +124,47 @@ void codegen_init(void)
                methodtree = avl_create(&methodtree_comparator);
 
 #if defined(ENABLE_JIT)
-               /* insert asm_calljavafunction */
+               /* insert asm_vm_call_method */
 
                mte = NEW(methodtree_element);
 
-               mte->startpc = (u1 *) (ptrint) asm_calljavafunction;
-               mte->endpc   = (u1 *) ((ptrint) asm_calljavafunction2 - 1);
-
-               avl_insert(methodtree, mte);
-
-               /* insert asm_calljavafunction2 */
-
-               mte = NEW(methodtree_element);
-
-               mte->startpc = (u1 *) (ptrint) asm_calljavafunction2;
-               mte->endpc   = (u1 *) ((ptrint) asm_call_jit_compiler - 1);
+               mte->startpc = (u1 *) (ptrint) asm_vm_call_method;
+               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) */
 }
 
 
-/* codegen_setup **************************************************************
+/* codegen_setup ***************************************************************
 
-   allocates and initialises code area, data area and references
+   Allocates and initialises code area, data area and references.
 
 *******************************************************************************/
 
-void codegen_setup(methodinfo *m, codegendata *cd, t_inlining_globals *id)
+void codegen_setup(jitdata *jd)
 {
-       cd->mcodebase = DMNEW(u1, MCODEINITSIZE);
-       cd->mcodesize = MCODEINITSIZE;
+       methodinfo  *m;
+       codegendata *cd;
+
+       /* get required compiler data */
+
+       m  = jd->m;
+       cd = jd->cd;
+
+       /* initialize members */
+
+       cd->flags        = 0;
+
+       cd->mcodebase    = DMNEW(u1, MCODEINITSIZE);
+       cd->mcodeend     = cd->mcodebase + MCODEINITSIZE;
+       cd->mcodesize    = MCODEINITSIZE;
 
        /* initialize mcode variables */
-       
-       cd->mcodeptr = cd->mcodebase;
-       cd->mcodeend = (s4 *) (cd->mcodebase + MCODEINITSIZE);
+
+       cd->mcodeptr     = cd->mcodebase;
+       cd->lastmcodeptr = cd->mcodebase;
 
 #if defined(ENABLE_INTRP)
        /* native dynamic superinstructions variables */
@@ -177,83 +181,159 @@ void codegen_setup(methodinfo *m, codegendata *cd, t_inlining_globals *id)
                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->xboundrefs = NULL;
-       cd->xnullrefs = NULL;
-       cd->xcastrefs = NULL;
-       cd->xstorerefs = NULL;
-       cd->xdivrefs = NULL;
-       cd->xexceptionrefs = NULL;
-       cd->patchrefs = NULL;
+/*     cd->patchrefs      = list_create_dump(OFFSET(patchref, linkage)); */
+       cd->patchrefs      = NULL;
+       cd->brancheslabel  = list_create_dump(OFFSET(branch_label_ref_t, linkage));
 
        cd->linenumberreferences = NULL;
        cd->linenumbertablesizepos = 0;
        cd->linenumbertablestartpos = 0;
        cd->linenumbertab = 0;
        
-       cd->method = m;
-       cd->exceptiontable = 0;
-       cd->exceptiontablelength = 0;
-
-       if (useinlining && id) {
-               if (id->cumextablelength > 0) {
-                       cd->exceptiontablelength = id->cumextablelength;
-                       cd->exceptiontable =
-                               DMNEW(exceptiontable, id->cumextablelength + 1);
-               }
+#if defined(ENABLE_THREADS)
+       cd->threadcritcurrent.next = NULL;
+       cd->threadcritcount = 0;
+#endif
+}
 
-       } else if (id && (id->method->exceptiontablelength > 0)) {
-               cd->exceptiontablelength = m->exceptiontablelength;
-               cd->exceptiontable = DMNEW(exceptiontable, m->exceptiontablelength + 1);
-       }
 
-       if (id) {
-               cd->maxstack = id->cummaxstack;
-               cd->maxlocals = id->cumlocals;
-       } else {
-               cd->maxstack = m->maxstack;
-               cd->maxlocals = m->maxlocals;
-       }
+/* codegen_reset ***************************************************************
+
+   Resets the codegen data structure so we can recompile the method.
 
-#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+*******************************************************************************/
+
+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->linenumberreferences    = NULL;
+       cd->linenumbertablesizepos  = 0;
+       cd->linenumbertablestartpos = 0;
+       cd->linenumbertab           = 0;
+       
+#if defined(ENABLE_THREADS)
        cd->threadcritcurrent.next = NULL;
-       cd->threadcritcount = 0;
+       cd->threadcritcount        = 0;
+#endif
+
+       /* We need to clear the mpc and the branch references from all
+          basic blocks as they will definitely change. */
+
+       for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
+               bptr->mpc        = -1;
+               bptr->branchrefs = NULL;
+       }
+
+#if defined(ENABLE_REPLACEMENT)
+       code->rplpoints     = NULL;
+       code->rplpointcount = 0;
+       code->regalloc      = NULL;
+       code->regalloccount = 0;
+       code->globalcount   = 0;
 #endif
 }
 
 
-/* codegen_free ****************************************************************
+/* codegen_generate ************************************************************
 
-   Releases temporary code and data area.
+   Generates the code for the currently compiled method.
 
 *******************************************************************************/
 
-void codegen_free(methodinfo *m, codegendata *cd)
+bool codegen_generate(jitdata *jd)
 {
-#if 0
-       if (cd) {
-               if (cd->mcodebase) {
-                       MFREE(cd->mcodebase, u1, cd->mcodesize);
-                       cd->mcodebase = NULL;
-               }
+       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 (cd->dsegtop) {
-                       MFREE(cd->dsegtop - cd->dsegsize, u1, cd->dsegsize);
-                       cd->dsegtop = NULL;
+#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;
 }
 
 
@@ -275,7 +355,7 @@ void codegen_close(void)
 
 *******************************************************************************/
 
-s4 *codegen_increase(codegendata *cd, u1 *mcodeptr)
+void codegen_increase(codegendata *cd)
 {
        u1 *oldmcodebase;
 
@@ -290,7 +370,11 @@ s4 *codegen_increase(codegendata *cd, u1 *mcodeptr)
                                                          cd->mcodesize,
                                                          cd->mcodesize * 2);
        cd->mcodesize *= 2;
-       cd->mcodeend   = (s4 *) (cd->mcodebase + cd->mcodesize);
+       cd->mcodeend   = cd->mcodebase + cd->mcodesize;
+
+       /* set new mcodeptr */
+
+       cd->mcodeptr = cd->mcodebase + (cd->mcodeptr - oldmcodebase);
 
 #if defined(__I386__) || defined(__MIPS__) || defined(__X86_64__) || defined(ENABLE_INTRP)
        /* adjust the pointer to the last patcher position */
@@ -298,10 +382,6 @@ s4 *codegen_increase(codegendata *cd, u1 *mcodeptr)
        if (cd->lastmcodeptr != NULL)
                cd->lastmcodeptr = cd->mcodebase + (cd->lastmcodeptr - oldmcodebase);
 #endif
-
-       /* return the new mcodeptr */
-
-       return (s4 *) (cd->mcodebase + (mcodeptr - oldmcodebase));
 }
 
 
@@ -335,194 +415,137 @@ u1 *codegen_ncode_increase(codegendata *cd, u1 *ncodeptr)
 #endif
 
 
-void codegen_addreference(codegendata *cd, basicblock *target, void *branchptr)
-{
-       s4 branchpos;
-
-       branchpos = (u1 *) branchptr - cd->mcodebase;
-
-#if !defined(ENABLE_INTRP)
-       /* The interpreter uses absolute branches, so we do branch resolving */
-       /* after the code and data segment move. */
-
-       /* Check if the target basicblock has already a start pc, so the jump is  */
-       /* backward and we can resolve it immediately.                            */
-
-       if (target->mpc >= 0) {
-               gen_resolvebranch((u1 *) cd->mcodebase + branchpos,
-                                                 branchpos,
-                                                 target->mpc);
-
-       } else
-#endif
-       {
-               branchref *br = DNEW(branchref);
-
-               br->branchpos = branchpos;
-               br->next      = target->branchrefs;
-
-               target->branchrefs = br;
-       }
-}
-
+/* codegen_add_branch_ref ******************************************************
 
-/* codegen_addxboundrefs *******************************************************
-
-   Adds an ArrayIndexOutOfBoundsException branch to the list.
+   Prepends an branch to the list.
 
 *******************************************************************************/
 
-void codegen_addxboundrefs(codegendata *cd, void *branchptr, s4 reg)
+void codegen_add_branch_ref(codegendata *cd, basicblock *target, s4 condition, s4 reg, u4 options)
 {
-       s4 branchpos;
        branchref *br;
+       s4         branchmpc;
 
-       branchpos = (u1 *) branchptr - cd->mcodebase;
-
-       br = DNEW(branchref);
-
-       br->branchpos = branchpos;
-       br->reg       = reg;
-       br->next      = cd->xboundrefs;
-
-       cd->xboundrefs = br;
-}
-
-
-/* codegen_addxcastrefs ********************************************************
-
-   Adds an ClassCastException branch to the list.
+       STATISTICS(count_branches_unresolved++);
 
-*******************************************************************************/
+       /* calculate the mpc of the branch instruction */
 
-void codegen_addxcastrefs(codegendata *cd, void *branchptr)
-{
-       s4         branchpos;
-       branchref *br;
-
-       branchpos = (u1 *) branchptr - cd->mcodebase;
+       branchmpc = cd->mcodeptr - cd->mcodebase;
 
        br = DNEW(branchref);
 
-       br->branchpos = branchpos;
-       br->next      = cd->xcastrefs;
+       br->branchmpc = branchmpc;
+       br->condition = condition;
+       br->reg       = reg;
+       br->options   = options;
+       br->next      = target->branchrefs;
 
-       cd->xcastrefs = br;
+       target->branchrefs = br;
 }
 
 
-/* codegen_addxdivrefs *********************************************************
+/* codegen_resolve_branchrefs **************************************************
 
-   Adds an ArithmeticException branch to the list.
+   Resolves and patches the branch references of a given basic block.
 
 *******************************************************************************/
 
-void codegen_addxdivrefs(codegendata *cd, void *branchptr)
+void codegen_resolve_branchrefs(codegendata *cd, basicblock *bptr)
 {
-       s4         branchpos;
        branchref *br;
+       u1        *mcodeptr;
 
-       branchpos = (u1 *) branchptr - 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. */
 
-       br = DNEW(branchref);
+       mcodeptr = cd->mcodeptr;
 
-       br->branchpos = branchpos;
-       br->next      = cd->xdivrefs;
+       /* just to make sure */
 
-       cd->xdivrefs = br;
-}
+       assert(bptr->mpc >= 0);
 
+       for (br = bptr->branchrefs; br != NULL; br = br->next) {
+               /* temporary set the mcodeptr */
 
-/* codegen_addxstorerefs *******************************************************
+               cd->mcodeptr = cd->mcodebase + br->branchmpc;
 
-   Adds an ArrayStoreException branch to the list.
+               /* emit_bccz and emit_branch emit the correct code, even if we
+                  pass condition == BRANCH_UNCONDITIONAL or reg == -1. */
 
-*******************************************************************************/
-
-void codegen_addxstorerefs(codegendata *cd, void *branchptr)
-{
-       s4         branchpos;
-       branchref *br;
-
-       branchpos = (u1 *) branchptr - cd->mcodebase;
-
-       br = DNEW(branchref);
+               emit_bccz(cd, bptr, br->condition, br->reg, br->options);
+       }
 
-       br->branchpos = branchpos;
-       br->next      = cd->xstorerefs;
+       /* restore mcodeptr */
 
-       cd->xstorerefs = br;
+       cd->mcodeptr = mcodeptr;
 }
 
 
-/* codegen_addxnullrefs ********************************************************
+/* codegen_branch_label_add ****************************************************
 
-   Adds an NullPointerException branch to the list.
+   Append an branch to the label-branch list.
 
 *******************************************************************************/
 
-void codegen_addxnullrefs(codegendata *cd, void *branchptr)
+void codegen_branch_label_add(codegendata *cd, s4 label, s4 condition, s4 reg, u4 options)
 {
-       s4         branchpos;
-       branchref *br;
-
-       branchpos = (u1 *) branchptr - cd->mcodebase;
-
-       br = DNEW(branchref);
-
-       br->branchpos = branchpos;
-       br->next      = cd->xnullrefs;
+       list_t             *list;
+       branch_label_ref_t *br;
+       s4                  mpc;
 
-       cd->xnullrefs = br;
-}
-
-
-/* codegen_addxexceptionsrefs **************************************************
+       /* get the label list */
 
-   Adds an common exception branch to the list.
-
-*******************************************************************************/
+       list = cd->brancheslabel;
+       
+       /* calculate the current mpc */
 
-void codegen_addxexceptionrefs(codegendata *cd, void *branchptr)
-{
-       s4 branchpos;
-       branchref *br;
+       mpc = cd->mcodeptr - cd->mcodebase;
 
-       branchpos = (u1 *) branchptr - cd->mcodebase;
+       br = DNEW(branch_label_ref_t);
 
-       br = DNEW(branchref);
+       br->mpc       = mpc;
+       br->label     = label;
+       br->condition = condition;
+       br->reg       = reg;
+       br->options   = options;
 
-       br->branchpos = branchpos;
-       br->next      = cd->xexceptionrefs;
+       /* add the branch to the list */
 
-       cd->xexceptionrefs = br;
+       list_add_last_unsynced(list, br);
 }
 
 
-/* codegen_addpatchref *********************************************************
+/* codegen_add_patch_ref *******************************************************
 
-   Adds a new patcher reference to the list of patching positions.
+   Appends a new patcher reference to the list of patching positions.
 
 *******************************************************************************/
 
-void codegen_addpatchref(codegendata *cd, voidptr branchptr,
-                                                functionptr patcher, voidptr ref, s4 disp)
+void codegen_add_patch_ref(codegendata *cd, functionptr patcher, voidptr ref,
+                                                  s4 disp)
 {
        patchref *pr;
-       s4        branchpos;
+       s4        branchmpc;
 
-       branchpos = (u1 *) branchptr - cd->mcodebase;
+       branchmpc = cd->mcodeptr - cd->mcodebase;
 
        pr = DNEW(patchref);
 
-       pr->branchpos = branchpos;
+       pr->branchpos = branchmpc;
+       pr->disp      = disp;
        pr->patcher   = patcher;
        pr->ref       = ref;
-       pr->disp      = disp;
 
+/*     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(__MIPS__) || defined(__X86_64__))
        /* On some architectures the patcher stub call instruction might
           be longer than the actual instruction generated.  On this
@@ -530,15 +553,14 @@ void codegen_addpatchref(codegendata *cd, voidptr branchptr,
           the basic block code generation is completed, we check the
           range and maybe generate some nop's. */
 
-       cd->lastmcodeptr = ((u1 *) branchptr) + PATCHER_CALL_SIZE;
+       cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
 #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.
 
 *******************************************************************************/
 
@@ -554,24 +576,34 @@ static s4 methodtree_comparator(const void *pc, const void *element)
           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.
 
 *******************************************************************************/
 
@@ -593,13 +625,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;
@@ -611,17 +644,109 @@ u1 *codegen_findmethod(u1 *pc)
 
        mte = avl_find(methodtree, &mtepc);
 
-       if (!mte) {
-               printf("Cannot find Java function at %p\n", (void *) (ptrint) pc);
-               assert(0);
+       if (mte == NULL) {
+               /* No method was found.  Let's dump a stacktrace. */
+
+               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("");
+               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 **************************************************************
@@ -632,22 +757,37 @@ u1 *codegen_findmethod(u1 *pc)
 
 *******************************************************************************/
 
-void codegen_finish(methodinfo *m, codegendata *cd, s4 mcodelen)
+void codegen_finish(jitdata *jd)
 {
-#if 0
-       s4       mcodelen;
+       codeinfo    *code;
+       codegendata *cd;
+       s4           mcodelen;
+#if defined(ENABLE_INTRP)
+       s4           ncodelen;
 #endif
+       s4           alignedmcodelen;
+       jumpref     *jr;
+       u1          *epoint;
+       s4           extralen;
+       s4           alignedlen;
+
+       /* get required compiler data */
+
+       code = jd->code;
+       cd   = jd->cd;
+
+       /* prevent compiler warning */
+
 #if defined(ENABLE_INTRP)
-       s4       ncodelen;
+       ncodelen = 0;
 #endif
-       s4       alignedmcodelen;
-       jumpref *jr;
-       u1      *epoint;
-       s4       extralen;
-       s4       alignedlen;
-
-#if defined(USE_THREADS) && defined(NATIVE_THREADS)
-       extralen = sizeof(threadcritnode) * cd->threadcritcount;
+
+       /* calculate the code length */
+
+       mcodelen = (s4) (cd->mcodeptr - cd->mcodebase);
+
+#if defined(ENABLE_THREADS)
+       extralen = sizeof(critical_section_node_t) * cd->threadcritcount;
 #else
        extralen = 0;
 #endif
@@ -659,18 +799,17 @@ void codegen_finish(methodinfo *m, codegendata *cd, s4 mcodelen)
        }
 #endif
 
-#if 0
-       mcodelen = cd->mcodeptr - cd->mcodebase;
-#endif
-       alignedmcodelen = ALIGN(mcodelen, MAX_ALIGN);
+       alignedmcodelen = MEMORY_ALIGN(mcodelen, MAX_ALIGN);
 
 #if defined(ENABLE_INTRP)
-       if (opt_intrp) {
+       if (opt_intrp)
                ncodelen = cd->ncodeptr - cd->ncodebase;
+       else {
+               ncodelen = 0; /* avoid compiler warning */
        }
 #endif
 
-       cd->dseglen = ALIGN(cd->dseglen, MAX_ALIGN);
+       cd->dseglen = MEMORY_ALIGN(cd->dseglen, MAX_ALIGN);
        alignedlen = alignedmcodelen + cd->dseglen;
 
 #if defined(ENABLE_INTRP)
@@ -681,26 +820,37 @@ void codegen_finish(methodinfo *m, codegendata *cd, s4 mcodelen)
 
        /* allocate new memory */
 
-       m->mcodelength = mcodelen + cd->dseglen;
-       m->mcode = CNEW(u1, alignedlen + extralen);
+       code->mcodelength = mcodelen + cd->dseglen;
+       code->mcode       = CNEW(u1, alignedlen + extralen);
 
-       /* copy data and code to their new location */
+       /* set the entrypoint of the method */
+       
+       assert(code->entrypoint == NULL);
+       code->entrypoint = epoint = (code->mcode + cd->dseglen);
 
-       MCOPY((void *) m->mcode, cd->dsegtop - cd->dseglen, u1, cd->dseglen);
-       MCOPY((void *) (m->mcode + cd->dseglen), cd->mcodebase, u1, mcodelen);
+       /* fill the data segment (code->entrypoint must already be set!) */
 
-       m->entrypoint = epoint = (m->mcode + cd->dseglen);
+       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) */
 
        if (opt_intrp) {
-               cd->mcodebase = m->entrypoint;
+               cd->mcodebase = code->entrypoint;
 
                if (ncodelen > 0) {
-                       u1 *ncodebase = m->mcode + cd->dseglen + alignedmcodelen;
-                       MCOPY((void *)ncodebase, cd->ncodebase, u1, ncodelen);
-                       /* XXX cacheflush((void *)ncodebase, ncodelen); */
+                       u1 *ncodebase = code->mcode + cd->dseglen + alignedmcodelen;
+
+                       MCOPY((void *) ncodebase, cd->ncodebase, u1, ncodelen);
+
+                       /* flush the instruction and data caches */
+
+                       md_cacheflush(ncodebase, ncodelen);
+
                        /* set some cd variables for dynamic_super_rerwite */
 
                        cd->ncodebase = ncodebase;
@@ -723,11 +873,18 @@ void codegen_finish(methodinfo *m, codegendata *cd, s4 mcodelen)
        {
                linenumberref *lr;
                ptrint lrtlen = 0;
+               ptrint target;
 
                for (lr = cd->linenumberreferences; lr != NULL; lr = lr->next) {
                        lrtlen++;
-                       *((functionptr *) ((ptrint) epoint + (ptrint) lr->tablepos)) =
-                               (functionptr) ((ptrint) epoint + (ptrint) lr->targetmpc);
+                       target = lr->targetmpc;
+                       /* if the entry contains an mcode pointer (normal case), resolve it */
+                       /* (see doc/inlining_stacktrace.txt for details)                    */
+                       if (lr->linenumber >= -2) {
+                           target += (ptrint) epoint;
+                       }
+                       *((functionptr *) ((ptrint) epoint + (ptrint) lr->tablepos)) = 
+                               (functionptr) target;
                }
                
                *((functionptr *) ((ptrint) epoint + cd->linenumbertablestartpos)) =
@@ -736,76 +893,188 @@ void codegen_finish(methodinfo *m, codegendata *cd, s4 mcodelen)
                *((ptrint *) ((ptrint) epoint + cd->linenumbertablesizepos)) = lrtlen;
        }
 
-#if defined(__I386__) || defined(__X86_64__) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
-       /* add method into methodtree to find the entrypoint */
+#if defined(ENABLE_REPLACEMENT)
+       /* replacement point resolving */
+       {
+               int i;
+               rplpoint *rp;
 
-       codegen_insertmethod(m->entrypoint, m->entrypoint + mcodelen);
-#endif
+               code->replacementstubs += (ptrint) epoint;
 
+               rp = code->rplpoints;
+               for (i=0; i<code->rplpointcount; ++i, ++rp) {
+                       rp->pc = (u1*) ((ptrint) epoint + (ptrint) rp->pc);
+               }
+       }
+#endif /* defined(ENABLE_REPLACEMENT) */
+
+       /* add method into methodtree to find the entrypoint */
 
-#if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(ENABLE_INTRP)
+       codegen_insertmethod(code->entrypoint, code->entrypoint + mcodelen);
+
+#if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
        /* resolve data segment references */
 
-       dseg_resolve_datareferences(cd, m);
+       dseg_resolve_datareferences(jd);
 #endif
 
-
-#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+#if defined(ENABLE_THREADS)
        {
-               threadcritnode *n = (threadcritnode *) ((ptrint) m->mcode + alignedlen);
+               critical_section_node_t *n = (critical_section_node_t *) ((ptrint) code->mcode + alignedlen);
                s4 i;
-               threadcritnodetemp *nt = cd->threadcrit;
+               codegen_critical_section_t *nt = cd->threadcrit;
 
                for (i = 0; i < cd->threadcritcount; i++) {
-                       n->mcodebegin = (u1 *) (ptrint) m->mcode + nt->mcodebegin;
-                       n->mcodeend = (u1 *) (ptrint) m->mcode + nt->mcodeend;
-                       n->mcoderestart = (u1 *) (ptrint) m->mcode + nt->mcoderestart;
-                       thread_registercritical(n);
+                       n->mcodebegin = (u1 *) (ptrint) code->mcode + nt->mcodebegin;
+                       n->mcodeend = (u1 *) (ptrint) code->mcode + nt->mcodeend;
+                       n->mcoderestart = (u1 *) (ptrint) code->mcode + nt->mcoderestart;
+                       critical_register_critical_section(n);
                        n++;
                        nt = nt->next;
                }
        }
 #endif
+
+       /* flush the instruction and data caches */
+
+       md_cacheflush(code->mcode, code->mcodelength);
 }
 
 
-/* codegen_createnativestub ****************************************************
+/* codegen_generate_stub_compiler **********************************************
+
+   Wrapper for codegen_emit_stub_compiler.
 
-   Wrapper for createnativestub.
+   Returns:
+       pointer to the compiler stub code.
 
 *******************************************************************************/
 
-u1 *codegen_createnativestub(functionptr f, methodinfo *m)
+u1 *codegen_generate_stub_compiler(methodinfo *m)
 {
-       codegendata        *cd;
-       registerdata       *rd;
-       t_inlining_globals *id;
-       s4                  dumpsize;
-       methoddesc         *md;
-       methoddesc         *nmd;        
-       s4                  nativeparams;
+       jitdata     *jd;
+       codegendata *cd;
+       ptrint      *d;                     /* pointer to data memory             */
+       u1          *c;                     /* pointer to code memory             */
+       s4           dumpsize;
 
        /* mark dump memory */
 
        dumpsize = dump_size();
 
-       cd = DNEW(codegendata);
-       rd = DNEW(registerdata);
-       id = DNEW(t_inlining_globals);
+       /* allocate required data structures */
 
-       /* setup code generation stuff */
+       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 */
 
-       inlining_setup(m, id);
+       /* 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_generate_stub_native(methodinfo *m, functionptr f)
+{
+       jitdata     *jd;
+       codeinfo    *code;
+       s4           dumpsize;
+       methoddesc  *md;
+       methoddesc  *nmd;       
+       s4           nativeparams;
+
+       /* mark dump memory */
+
+       dumpsize = dump_size();
+
+       jd = DNEW(jitdata);
+
+       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. */
+
+       jd->code  = code_codeinfo_new(m); /* XXX check allocation */
+
+       /* get required compiler data */
+
+       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)
 # if defined(ENABLE_INTRP)
        if (!opt_intrp)
 # endif
-               reg_setup(m, rd, id);
+               reg_setup(jd);
 #endif
 
-       codegen_setup(m, cd, id);
-                                               
+       codegen_setup(jd);
+
        /* create new method descriptor with additional native parameters */
 
        md = m->parseddesc;
@@ -831,7 +1100,9 @@ u1 *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 */
@@ -839,39 +1110,47 @@ u1 *codegen_createnativestub(functionptr f, methodinfo *m)
 #if defined(ENABLE_JIT)
 # if defined(ENABLE_INTRP)
        if (opt_intrp)
-               m->entrypoint = intrp_createnativestub(f, m, cd, rd, nmd);
+               intrp_createnativestub(f, jd, nmd);
        else
 # endif
-               m->entrypoint = createnativestub(f, m, cd, rd, nmd);
+               codegen_emit_stub_native(jd, nmd, f);
 #else
-       m->entrypoint = intrp_createnativestub(f, m, cd, rd, nmd);
+       intrp_createnativestub(f, jd, nmd);
 #endif
 
 #if defined(ENABLE_STATISTICS)
        if (opt_stat)
-               count_nstub_len += m->mcodelength;
+               count_nstub_len += code->mcodelength;
 #endif
 
+       /* reallocate the memory and finish the code generation */
+
+       codegen_finish(jd);
+
+#if !defined(NDEBUG)
        /* disassemble native stub */
 
        if (opt_shownativestub) {
+#if defined(ENABLE_DISASSEMBLER)
                codegen_disassemble_nativestub(m,
-                                                                          (u1 *) (ptrint) m->entrypoint,
-                                                                          (u1 *) (ptrint) m->entrypoint + (m->mcodelength - cd->dseglen));
+                                                                          (u1 *) (ptrint) code->entrypoint,
+                                                                          (u1 *) (ptrint) code->entrypoint + (code->mcodelength - jd->cd->dseglen));
+#endif
 
                /* show data segment */
 
                if (opt_showddatasegment)
-                       dseg_display(m, cd);
+                       dseg_display(jd);
        }
+#endif /* !defined(NDEBUG) */
 
        /* release memory */
 
        dump_release(dumpsize);
 
-       /* return native stub entry point */
+       /* return native stub code */
 
-       return m->entrypoint;
+       return code;
 }
 
 
@@ -881,17 +1160,19 @@ u1 *codegen_createnativestub(functionptr f, methodinfo *m)
 
 *******************************************************************************/
 
+#if defined(ENABLE_DISASSEMBLER)
 void codegen_disassemble_nativestub(methodinfo *m, u1 *start, u1 *end)
 {
        printf("Native stub: ");
-       utf_fprint_classname(stdout, m->class->name);
+       utf_fprint_printable_ascii_classname(stdout, m->class->name);
        printf(".");
-       utf_fprint(stdout, m->name);
-       utf_fprint(stdout, m->descriptor);
+       utf_fprint_printable_ascii(stdout, m->name);
+       utf_fprint_printable_ascii(stdout, m->descriptor);
        printf("\n\nLength: %d\n\n", (s4) (end - start));
 
        DISASSEMBLE(start, end);
 }
+#endif
 
 
 /* codegen_start_native_call ***************************************************
@@ -936,6 +1217,7 @@ void codegen_start_native_call(u1 *datasp, u1 *pv, u1 *sp, u1 *ra)
 
        stacktrace_create_native_stackframeinfo(sfi, pv, sp, ra);
 
+#if defined(ENABLE_JAVASE)
        /* add current JNI local references table to this thread */
 
        lrt->capacity    = LOCALREFTABLE_CAPACITY;
@@ -948,47 +1230,74 @@ void codegen_start_native_call(u1 *datasp, u1 *pv, u1 *sp, u1 *ra)
        MSET(lrt->refs, 0, java_objectheader*, LOCALREFTABLE_CAPACITY);
 
        LOCALREFTABLE = 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_objectheader *codegen_finish_native_call(u1 *datasp)
 {
-       stackframeinfo  *sfi;
-       stackframeinfo **psfi;
-       localref_table  *lrt;
-       s4               localframes;
+       stackframeinfo     *sfi;
+       stackframeinfo    **psfi;
+#if defined(ENABLE_JAVASE)
+       localref_table     *lrt;
+       localref_table     *plrt;
+       s4                  localframes;
+#endif
+       java_objectheader  *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;
 
+#if defined(ENABLE_JAVASE)
        /* release JNI local references tables for this thread */
 
        lrt = LOCALREFTABLE;
 
-       /* got through all current local frames */
+       /* release all current local frames */
 
        for (localframes = lrt->localframes; localframes >= 1; localframes--) {
-               lrt = lrt->prev;
+               /* get previous frame */
+
+               plrt = lrt->prev;
+
+               /* Clear all reference entries (only for tables allocated on
+                  the Java heap). */
+
+               if (localframes > 1)
+                       MSET(&lrt->refs[0], 0, java_objectheader*, lrt->capacity);
+
+               lrt->prev = NULL;
+
+               /* set new local references table */
+
+               lrt = plrt;
        }
 
        /* now store the previous local frames in the thread structure */
 
        LOCALREFTABLE = lrt;
+#endif
+
+       /* get the exception and return it */
+
+       e = exceptions_get_and_clear_exception();
+
+       return e;
 }
 
 
@@ -1020,7 +1329,7 @@ void removenativestub(u1 *stub)
 }
 
 
-/* reg_of_var ******************************************************************
+/* codegen_reg_of_var **********************************************************
 
    This function determines a register, to which the result of an
    operation should go, when it is ultimatively intended to store the
@@ -1036,52 +1345,30 @@ void removenativestub(u1 *stub)
 
 *******************************************************************************/
 
-s4 reg_of_var(registerdata *rd, stackptr v, s4 tempregnum)
+s4 codegen_reg_of_var(u2 opcode, varinfo *v, s4 tempregnum)
 {
-       varinfo *var;
-
-       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)));
+
+#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;
 #endif
-                       return(var->regoff);
-               }
-               break;
 
-       case ARGVAR:
-               if (!(v->flags & INMEMORY)) {
+       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)));
+               if (IS_2_WORD_TYPE(v->type) && (GET_HIGH_REG(v->vv.regoff) == REG_SPLIT))
+                       return PACK_REGS(GET_LOW_REG(v->vv.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)));
+               if (IS_2_WORD_TYPE(v->type) && (GET_LOW_REG(v->vv.regoff) == REG_SPLIT))
+                       return PACK_REGS(GET_LOW_REG(tempregnum),
+                                                        GET_HIGH_REG(v->vv.regoff));
 #endif
-                       return(v->regoff);
-               }
-               break;
+               return v->vv.regoff;
        }
 
 #if defined(ENABLE_STATISTICS)
@@ -1089,13 +1376,32 @@ s4 reg_of_var(registerdata *rd, stackptr v, s4 tempregnum)
                count_spills_read++;
 #endif
 
-       v->flags |= INMEMORY;
-
        return tempregnum;
 }
 
+/* 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.
+       
+   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 dst.var for LOW_REG and the tempregnum for HIGH_REG in such
+   cases.  (michi 2005/07/24)
+
+*******************************************************************************/
+
+s4 codegen_reg_of_dst(jitdata *jd, instruction *iptr, s4 tempregnum)
+{
+       return codegen_reg_of_var(iptr->opc, VAROP(iptr->dst), tempregnum);
+}
+
 
-#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+#if defined(ENABLE_THREADS)
 void codegen_threadcritrestart(codegendata *cd, int offset)
 {
        cd->threadcritcurrent.mcoderestart = offset;
@@ -1112,7 +1418,7 @@ void codegen_threadcritstop(codegendata *cd, int offset)
 {
        cd->threadcritcurrent.next = cd->threadcrit;
        cd->threadcritcurrent.mcodeend = offset;
-       cd->threadcrit = DNEW(threadcritnodetemp);
+       cd->threadcrit = DNEW(codegen_critical_section_t);
        *(cd->threadcrit) = cd->threadcritcurrent;
        cd->threadcritcount++;
 }
@@ -1130,4 +1436,5 @@ void codegen_threadcritstop(codegendata *cd, int offset)
  * c-basic-offset: 4
  * tab-width: 4
  * End:
+ * vim:noexpandtab:sw=4:ts=4:
  */