* codegen_createnativestub: passed wrong length to
[cacao.git] / src / vm / jit / codegen.inc
index 7db7d61eb64f16f45c71929e14fd0248d62f2bed..c42e4dcdf21ded20c24dd3a19353fd6ed301ed2e 100644 (file)
@@ -1,10 +1,9 @@
-/* jit/codegen.inc - architecture independent code generator
+/* src/vm/jit/codegen.inc - architecture independent code generator
 
-   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
-   Institut f. Computersprachen, TU Wien
-   R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser, M. Probst,
-   S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich,
-   J. Wenninger
+   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
 
    This file is part of CACAO.
 
@@ -28,8 +27,8 @@
    Authors: Reinhard Grafl
             Andreas  Krall
 
-   Changes: Michael Gschwind
-            Christian Thalinger
+   Changes: Christian Thalinger
+            Joseph Wenninger
 
    All functions assume the following code area / data area layout:
 
    memory. All functions writing values into the data area return the offset
    relative the begin of the code area (start of procedure).   
 
-   $Id: codegen.inc 1049 2004-05-05 11:43:11Z stefan $
+   $Id: codegen.inc 2734 2005-06-17 13:01:06Z twisti $
 
 */
 
 
+#include <assert.h>
 #include <string.h>
-#include "toolbox/memory.h"
-#include "toolbox/loging.h"
-#include "threads/thread.h"
-
-
-/************************* critical sections  *********************************/
-
-struct threadcritnodetemp {
-       struct threadcritnodetemp *next;
-       int mcodebegin, mcodeend, mcoderestart;
-};
-
-#define MCODEINITSIZE (1<<15)       /* 32 Kbyte code area initialization size */
-#define DSEGINITSIZE  (1<<12)       /*  4 Kbyte data area initialization size */
-
-static u1* mcodebase = NULL;        /* base pointer of code area              */
-static s4* mcodeend  = NULL;        /* pointer to end of code area            */
-static int mcodesize;               /* complete size of code area (bytes)     */
-
-static u1* dsegtop = NULL;          /* pointer to top (end) of data area      */
-static int dsegsize;                /* complete size of data area (bytes)     */
-int dseglen;                        /* used size of data area (bytes)         */
-                                    /* data area grows from top to bottom     */
-
-static jumpref *jumpreferences;     /* list of jumptable target addresses     */
-static dataref *datareferences;     /* list of data segment references        */
-static branchref *xboundrefs;       /* list of bound check branches           */
-static branchref *xcheckarefs;      /* list of array size check branches      */
-static branchref *xnullrefs;        /* list of null check branches            */
-static branchref *xcastrefs;        /* list of cast check branches            */
-static branchref *xdivrefs;         /* list of divide by zero branches        */
-static branchref *xoomrefs;         /* list of out of memory branches         */
-static linenumberref *linenumberreferences; /*list of line numbers and the program counters of their first instruction*/
-static s4 linenumbertablesizepos;
-static s4 linenumbertablestartpos;
-static s4 linenumbertab;
-
-static struct threadcritnodetemp *threadcrit;
-                                    /* List of critical code regions          */
-static struct threadcritnodetemp threadcritcurrent;
-static int threadcritcount;         /* Number of critical regions             */
-
-int parentargs_base; /* offset in stackframe for the parameter from the caller*/
-
-void codegen_init();                /* allocates code and data area           */
-void codegen_close();               /* releases temporary storage             */
-static void codegen_finish();       /* makes code and data area permanent and */
-                                    /* updates branch references to code/data */
-
-static s4 dseg_adds4(s4 value);         /* adds an int to data area           */
-static s4 dseg_adds8(s8 value);         /* adds an long to data area          */
-static s4 dseg_addfloat (float value);  /* adds an float to data area         */
-static s4 dseg_adddouble(double value); /* adds an double to data area        */
-
-#if POINTERSIZE == 8
-#define dseg_addaddress(value)      dseg_adds8((s8)(value))
-#else
-#define dseg_addaddress(value)      dseg_adds4((s4)(value))
+
+#include "config.h"
+#include "types.h"
+
+#include "disass.h"
+
+#include "mm/memory.h"
+#include "toolbox/avl.h"
+#include "toolbox/logging.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 "vm/exceptions.h"
+#include "vm/method.h"
+#include "vm/options.h"
+#include "vm/statistics.h"
+#include "vm/jit/codegen.inc.h"
+#include "vm/jit/jit.h"
+
+#undef JWDEBUG_X86
+
+#ifdef JWDEBUG_X86
+#include <execinfo.h>
 #endif
 
-static void dseg_addtarget(basicblock *target);
-static void dseg_adddata(u1 *ptr);
-static void codegen_addreference(basicblock *target, void *branchptr);
-static void codegen_addxboundrefs(void *branchptr, s4 reg);
-static void codegen_addxnullrefs(void *branchptr);
-static void codegen_addxcastrefs(void *branchptr);
-static void codegen_addxdivrefs(void *branchptr);
-static void codegen_addxoomrefs(void *branchptr);
-static void codegen_threadcritrestart(int offset);
-static void codegen_threadcritstart(int offset);
-static void codegen_threadcritstop(int offset);
+/* in this tree we store all method addresses *********************************/
+
+#if defined(__I386__) || defined(__X86_64__)
+static struct avl_table *methodtree = NULL;
+static int methodtree_comparator(const void *pc, const void *element,
+                                                                void *param);
+#endif
 
-void dseg_display(s4 *s4ptr);
 
+/* codegen_init ****************************************************************
 
+   TODO
 
-/* codegen_init allocates and initialises code area, data area and references   */
+*******************************************************************************/
 
-void codegen_init()
+void codegen_init(void)
 {
-       if (!mcodebase) {
-               mcodebase = MNEW(u1, MCODEINITSIZE);
-               mcodesize = MCODEINITSIZE;
-       }
+#if defined(__I386__) || defined(__X86_64__)
+       /* this tree is global, not method specific */
+       if (!methodtree) {
+               methodtree_element *mte;
 
-       if (!dsegtop) {
-               dsegtop = MNEW(u1, DSEGINITSIZE);
-               dsegsize = DSEGINITSIZE;
-               dsegtop += dsegsize;
-       }
+               methodtree = avl_create(methodtree_comparator, NULL, NULL);
 
-       dseglen = 0;
+               /* insert asm_calljavafunction */
 
-       linenumberreferences=NULL;
-       linenumbertablesizepos=0;
-       linenumbertablestartpos=0;
-       linenumbertab=0;
-       jumpreferences = NULL;
-       datareferences = NULL;
-       xboundrefs = NULL;
-       xnullrefs = NULL;
-       xcastrefs = NULL;
-       xdivrefs = NULL;
-       xoomrefs = NULL;
+               mte = NEW(methodtree_element);
 
-#if defined(USE_THREADS) && defined(NATIVE_THREADS)
-       threadcritcurrent.next = NULL;
-       threadcritcount = 0;
+               mte->startpc = (functionptr) asm_calljavafunction;
+               mte->endpc = (functionptr) ((ptrint) asm_calljavafunction2 - 1);
+
+               avl_insert(methodtree, mte);
+
+               /* insert asm_calljavafunction2 */
+
+               mte = NEW(methodtree_element);
+
+               mte->startpc = (functionptr) asm_calljavafunction2;
+               mte->endpc = (functionptr) ((ptrint) asm_call_jit_compiler - 1);
+
+               avl_insert(methodtree, mte);
+       }
 #endif
 }
 
 
+/* codegen_setup **************************************************************
 
-/* codegen_close releases temporary code and data area                          */
+   allocates and initialises code area, data area and references
 
-void codegen_close()
+*******************************************************************************/
+
+void codegen_setup(methodinfo *m, codegendata *cd, t_inlining_globals *id)
 {
-       if (mcodebase) {
-               MFREE(mcodebase, u1, mcodesize);
-               mcodebase = NULL;
+       cd->mcodebase = DMNEW(u1, MCODEINITSIZE);
+       cd->mcodesize = MCODEINITSIZE;
+       
+       cd->dsegtop = DMNEW(u1, DSEGINITSIZE);
+       cd->dsegsize = DSEGINITSIZE;
+       cd->dsegtop += cd->dsegsize;
+       cd->dseglen = 0;
+
+       cd->jumpreferences = NULL;
+       cd->datareferences = NULL;
+       cd->xboundrefs = NULL;
+       cd->xcheckarefs = NULL;
+       cd->xnullrefs = NULL;
+       cd->xcastrefs = NULL;
+       cd->xdivrefs = NULL;
+       cd->xexceptionrefs = NULL;
+       cd->patchrefs = NULL;
+
+       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);
+               }
+
+       } else if (id && (id->method->exceptiontablelength > 0)) {
+               cd->exceptiontablelength = m->exceptiontablelength;
+               cd->exceptiontable = DMNEW(exceptiontable, m->exceptiontablelength + 1);
        }
 
-       if (dsegtop) {
-               MFREE(dsegtop - dsegsize, u1, dsegsize);
-               dsegtop = NULL;
+       if (id) {
+               cd->maxstack = id->cummaxstack;
+               cd->maxlocals = id->cumlocals;
+       } else {
+               cd->maxstack = m->maxstack;
+               cd->maxlocals = m->maxlocals;
        }
+
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+       cd->threadcritcurrent.next = NULL;
+       cd->threadcritcount = 0;
+#endif
 }
 
 
+/* codegen_free ****************************************************************
 
-/* codegen_increase doubles code area                                           */
+   Releases temporary code and data area.
 
-static s4 *codegen_increase(u1 *codeptr)
+*******************************************************************************/
+
+void codegen_free(methodinfo *m, codegendata *cd)
 {
-       long len;
+#if 0
+       if (cd) {
+               if (cd->mcodebase) {
+                       MFREE(cd->mcodebase, u1, cd->mcodesize);
+                       cd->mcodebase = NULL;
+               }
 
-       len = codeptr - mcodebase;
-       mcodebase = MREALLOC(mcodebase, u1, mcodesize, mcodesize * 2);
-       mcodesize *= 2;
-       mcodeend = (s4*) (mcodebase + mcodesize);
-       return (s4*) (mcodebase + len);
+               if (cd->dsegtop) {
+                       MFREE(cd->dsegtop - cd->dsegsize, u1, cd->dsegsize);
+                       cd->dsegtop = NULL;
+               }
+       }
+#endif
 }
 
 
+/* codegen_close ***************************************************************
 
-/* desg_increase doubles data area                                            */
+   TODO
+
+*******************************************************************************/
 
-static void dseg_increase()
+void codegen_close(void)
 {
-       u1 *newstorage = MNEW(u1, dsegsize * 2);
-       memcpy(newstorage + dsegsize, dsegtop - dsegsize, dsegsize);
-       MFREE(dsegtop - dsegsize, u1, dsegsize);
-       dsegtop = newstorage;
-       dsegsize *= 2;
-       dsegtop += dsegsize;
+       /* TODO: release avl tree on i386 and x86_64 */
 }
 
 
+/* codegen_increase doubles code area                                         */
 
-static s4 dseg_adds4_increase(s4 value)
+static s4 *codegen_increase(codegendata *cd, u1 *codeptr)
 {
-       dseg_increase();
-       *((s4 *) (dsegtop - dseglen)) = value;
-       return -dseglen;
+       long len;
+
+       len = codeptr - cd->mcodebase;
+       cd->mcodebase = DMREALLOC(cd->mcodebase,
+                                                         u1,
+                                                         cd->mcodesize,
+                                                         cd->mcodesize * 2);
+       cd->mcodesize *= 2;
+       cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
+
+       return (s4 *) (cd->mcodebase + len);
 }
 
 
+/* desg_increase doubles data area                                            */
 
-static s4 dseg_adds4(s4 value)
+static void dseg_increase(codegendata *cd)
 {
-       s4 *dataptr;
+       u1 *newstorage;
 
-       dseglen += 4;
-       dataptr = (s4 *) (dsegtop - dseglen);
-       if (dseglen > dsegsize)
-               return dseg_adds4_increase(value);
-       *dataptr = value;
-       return -dseglen;
+       newstorage = DMNEW(u1, cd->dsegsize * 2);
+
+       MCOPY(newstorage + cd->dsegsize, cd->dsegtop - cd->dsegsize, u1,
+                 cd->dsegsize);
+
+       cd->dsegtop = newstorage;
+       cd->dsegsize *= 2;
+       cd->dsegtop += cd->dsegsize;
 }
 
 
+static s4 dseg_adds4_increase(codegendata *cd, s4 value)
+{
+       dseg_increase(cd);
+
+       *((s4 *) (cd->dsegtop - cd->dseglen)) = value;
 
-static s4 dseg_adds8_increase(s8 value)
+       return -(cd->dseglen);
+}
+
+
+static s4 dseg_adds4(codegendata *cd, s4 value)
 {
-       dseg_increase();
-       *((s8 *) (dsegtop - dseglen)) = value;
-       return -dseglen;
+       s4 *dataptr;
+
+       cd->dseglen += 4;
+       dataptr = (s4 *) (cd->dsegtop - cd->dseglen);
+
+       if (cd->dseglen > cd->dsegsize)
+               return dseg_adds4_increase(cd, value);
+
+       *dataptr = value;
+
+       return -(cd->dseglen);
 }
 
 
+#if !defined(__I386__) && !defined(__POWERPC__)
+static s4 dseg_adds8_increase(codegendata *cd, s8 value)
+{
+       dseg_increase(cd);
+
+       *((s8 *) (cd->dsegtop - cd->dseglen)) = value;
 
-static s4 dseg_adds8(s8 value)
+       return -(cd->dseglen);
+}
+
+
+static s4 dseg_adds8(codegendata *cd, s8 value)
 {
        s8 *dataptr;
 
-       dseglen = ALIGN (dseglen + 8, 8);
-       dataptr = (s8 *) (dsegtop - dseglen);
-       if (dseglen > dsegsize)
-               return dseg_adds8_increase(value);
+       cd->dseglen = ALIGN(cd->dseglen + 8, 8);
+       dataptr = (s8 *) (cd->dsegtop - cd->dseglen);
+
+       if (cd->dseglen > cd->dsegsize)
+               return dseg_adds8_increase(cd, value);
+
        *dataptr = value;
-       return -dseglen;
-}
 
+       return -(cd->dseglen);
+}
+#endif
 
 
-static s4 dseg_addfloat_increase(float value)
+#if !defined(__XDSPCORE__)
+static s4 dseg_addfloat_increase(codegendata *cd, float value)
 {
-       dseg_increase();
-       *((float *) (dsegtop - dseglen)) = value;
-       return -dseglen;
-}
+       dseg_increase(cd);
+
+       *((float *) (cd->dsegtop - cd->dseglen)) = value;
 
+       return -(cd->dseglen);
+}
 
 
-static s4 dseg_addfloat(float value)
+static s4 dseg_addfloat(codegendata *cd, float value)
 {
        float *dataptr;
 
-       dseglen += 4;
-       dataptr = (float *) (dsegtop - dseglen);
-       if (dseglen > dsegsize)
-               return dseg_addfloat_increase(value);
+       cd->dseglen += 4;
+       dataptr = (float *) (cd->dsegtop - cd->dseglen);
+
+       if (cd->dseglen > cd->dsegsize)
+               return dseg_addfloat_increase(cd, value);
+
        *dataptr = value;
-       return -dseglen;
-}
 
+       return -(cd->dseglen);
+}
 
 
-static s4 dseg_adddouble_increase(double value)
+static s4 dseg_adddouble_increase(codegendata *cd, double value)
 {
-       dseg_increase();
-       *((double *) (dsegtop - dseglen)) = value;
-       return -dseglen;
-}
+       dseg_increase(cd);
 
+       *((double *) (cd->dsegtop - cd->dseglen)) = value;
+
+       return -(cd->dseglen);
+}
 
 
-static s4 dseg_adddouble(double value)
+static s4 dseg_adddouble(codegendata *cd, double value)
 {
        double *dataptr;
 
-       dseglen = ALIGN (dseglen + 8, 8);
-       dataptr = (double *) (dsegtop - dseglen);
-       if (dseglen > dsegsize)
-               return dseg_adddouble_increase(value);
+       cd->dseglen = ALIGN(cd->dseglen + 8, 8);
+       dataptr = (double *) (cd->dsegtop - cd->dseglen);
+
+       if (cd->dseglen > cd->dsegsize)
+               return dseg_adddouble_increase(cd, value);
+
        *dataptr = value;
-       return -dseglen;
-}
 
+       return -(cd->dseglen);
+}
+#endif /* !defined(__XDSPCORE__) */
 
 
-static void dseg_addtarget(basicblock *target)
+static void dseg_addtarget(codegendata *cd, basicblock *target)
 {
-       jumpref *jr = DNEW(jumpref);
-       
-       jr->tablepos = dseg_addaddress(NULL);
+       jumpref *jr;
+
+       jr = DNEW(jumpref);
+       jr->tablepos = dseg_addaddress(cd, NULL);
        jr->target = target;
-       jr->next = jumpreferences;
-       jumpreferences = jr;
+       jr->next = cd->jumpreferences;
+       cd->jumpreferences = jr;
 }
 
 
-
-static void dseg_adddata(u1 *ptr)
+#if defined(__I386__) || defined(__X86_64__)
+static void dseg_adddata(codegendata *cd, u1 *ptr)
 {
-       dataref *dr = DNEW(dataref);
+       dataref *dr;
 
-       dr->pos = (u1 *) (ptr - mcodebase);
-       dr->next = datareferences;
-       datareferences = dr;
+       dr = DNEW(dataref);
+       dr->pos = (u1 *) (ptr - cd->mcodebase);
+       dr->next = cd->datareferences;
+       cd->datareferences = dr;
 }
+#endif
 
-static void dseg_addlinenumbertablesize() {
-#ifdef __ALPHA__
-       dseg_adds4(0); /*PADDING*/
+
+static void dseg_addlinenumbertablesize(codegendata *cd)
+{
+#if defined (__ALPHA__) || defined (__X86_64__)
+       dseg_adds4(cd, 0); /*PADDING*/
 #endif
-       linenumbertablesizepos=dseg_addaddress(NULL); /*it could be considered to use adds4 here, to avoid 1 double word padding on ALPHA */
+       cd->linenumbertablesizepos = dseg_addaddress(cd, NULL); /*it could be considered to use adds4 here, to avoid 1 double word padding on ALPHA */
 
-       linenumbertablestartpos=dseg_addaddress(NULL);
-#ifdef __ALPHA__
-       dseg_adds4(0); /*PADDING*/
+       cd->linenumbertablestartpos = dseg_addaddress(cd, NULL);
+#if defined(__ALPHA__) || defined (__X86_64__)
+       dseg_adds4(cd, 0); /*PADDING*/
 #endif
 }
 
-static void dseg_addlinenumber(u2 linenumber,u1 *ptr) {
-       linenumberref *lr=DNEW(linenumberref);
-       lr->linenumber=linenumber;
-       lr->tablepos=0;
-       lr->targetmpc=(ptr-mcodebase);
-       lr->next=linenumberreferences;
-       linenumberreferences=lr;
+
+static void dseg_addlinenumber(codegendata *cd, u2 linenumber, u1 *ptr)
+{
+       linenumberref *lr;
+
+       lr = DNEW(linenumberref);
+       lr->linenumber = linenumber;
+       lr->tablepos = 0;
+       lr->targetmpc = (ptr - cd->mcodebase);
+       lr->next = cd->linenumberreferences;
+       cd->linenumberreferences = lr;
 }
 
-static void codegen_addreference(basicblock *target, void *branchptr)
+
+/* we need this function externally on i386 and x86_64, but keep the call fast
+   on alpha... */
+
+#if defined(__I386__) || defined(__X86_64__)
+void codegen_addreference(codegendata *cd, basicblock *target, void *branchptr)
+#else
+static void codegen_addreference(codegendata *cd, basicblock *target, void *branchptr)
+#endif
 {
-       s4 branchpos = (u1*) branchptr - mcodebase;
+       s4 branchpos;
+
+       branchpos = (u1 *) branchptr - cd->mcodebase;
+
+       /* 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*) mcodebase + branchpos, branchpos, target->mpc);
-       }
-       else {
+               gen_resolvebranch((u1 *) cd->mcodebase + branchpos,
+                                                 branchpos,
+                                                 target->mpc);
+
+       } else {
                branchref *br = DNEW(branchref);
 
                br->branchpos = branchpos;
                br->next = target->branchrefs;
-               target->branchrefs= br;
+               target->branchrefs = br;
        }
 }
 
 
-
-static void codegen_addxboundrefs(void *branchptr, s4 reg)
+static void codegen_addxboundrefs(codegendata *cd, void *branchptr, s4 reg)
 {
-       s4 branchpos = (u1*) branchptr - mcodebase;
+       s4 branchpos;
+       branchref *br;
 
-       branchref *br = DNEW(branchref);
+       branchpos = (u1 *) branchptr - cd->mcodebase;
 
+       br = DNEW(branchref);
        br->branchpos = branchpos;
        br->reg = reg;
-       br->next = xboundrefs;
-       xboundrefs = br;
+       br->next = cd->xboundrefs;
+       cd->xboundrefs = br;
 }
 
 
-
-static void codegen_addxcheckarefs(void *branchptr)
+static void codegen_addxcheckarefs(codegendata *cd, void *branchptr)
 {
-       s4 branchpos = (u1*) branchptr - mcodebase;
+       s4 branchpos;
+       branchref *br;
 
-       branchref *br = DNEW(branchref);
+       branchpos = (u1 *) branchptr - cd->mcodebase;
 
+       br = DNEW(branchref);
        br->branchpos = branchpos;
-       br->next = xcheckarefs;
-       xcheckarefs = br;
+       br->next = cd->xcheckarefs;
+       cd->xcheckarefs = br;
 }
 
 
-
-static void codegen_addxnullrefs(void *branchptr)
+static void codegen_addxnullrefs(codegendata *cd, void *branchptr)
 {
-       s4 branchpos = (u1*) branchptr - mcodebase;
+       s4 branchpos;
+       branchref *br;
 
-       branchref *br = DNEW(branchref);
+       branchpos = (u1 *) branchptr - cd->mcodebase;
 
+       br = DNEW(branchref);
        br->branchpos = branchpos;
-       br->next = xnullrefs;
-       xnullrefs = br;
+       br->next = cd->xnullrefs;
+       cd->xnullrefs = br;
 }
 
 
-
-static void codegen_addxcastrefs(void *branchptr)
+static void codegen_addxcastrefs(codegendata *cd, void *branchptr)
 {
-       s4 branchpos = (u1*) branchptr - mcodebase;
+       s4 branchpos;
+       branchref *br;
 
-       branchref *br = DNEW(branchref);
+       branchpos = (u1 *) branchptr - cd->mcodebase;
 
+       br = DNEW(branchref);
        br->branchpos = branchpos;
-       br->next = xcastrefs;
-       xcastrefs = br;
+       br->next = cd->xcastrefs;
+       cd->xcastrefs = br;
 }
 
 
-
-static void codegen_addxoomrefs(void *branchptr)
+static void codegen_addxexceptionrefs(codegendata *cd, void *branchptr)
 {
-       s4 branchpos = (u1*) branchptr - mcodebase;
+       s4 branchpos;
+       branchref *br;
 
-       branchref *br = DNEW(branchref);
+       branchpos = (u1 *) branchptr - cd->mcodebase;
 
+       br = DNEW(branchref);
        br->branchpos = branchpos;
-       br->next = xoomrefs;
-       xoomrefs = br;
+       br->next = cd->xexceptionrefs;
+       cd->xexceptionrefs = br;
 }
 
 
-static void codegen_addxdivrefs(void *branchptr)
+#if defined(__I386__) || defined(__X86_64__)
+static void codegen_addxdivrefs(codegendata *cd, void *branchptr)
 {
-       s4 branchpos = (u1*) branchptr - mcodebase;
+       s4 branchpos;
+       branchref *br;
 
-       branchref *br = DNEW(branchref);
+       branchpos = (u1 *) branchptr - cd->mcodebase;
 
+       br = DNEW(branchref);
        br->branchpos = branchpos;
-       br->next = xdivrefs;
-       xdivrefs = br;
+       br->next = cd->xdivrefs;
+       cd->xdivrefs = br;
 }
+#endif
 
 
-static void codegen_createlinenumbertable() {
-#ifdef __I386__
-       /*log_text("codegen_createlinnumbertable");*/
-       {
-               linenumberref *lr;
-               for (lr=linenumberreferences;lr!=NULL;lr=lr->next) {
-                       /*log_text("Adding line number entry");*/
-                       lr->tablepos=dseg_addaddress(NULL);
-                       if (linenumbertab==0) linenumbertab=lr->tablepos;
-                       dseg_addaddress(lr->linenumber);
-               }
+static void codegen_addpatchref(codegendata *cd,
+                                                               voidptr branchptr,
+                                                               functionptr patcher,
+                                                               voidptr ref)
+{
+       patchref *pr;
+       s4        branchpos;
+
+       branchpos = (u1 *) branchptr - cd->mcodebase;
+
+       pr = DNEW(patchref);
+       pr->branchpos = branchpos;
+       pr->patcher = patcher;
+       pr->ref = ref;
+       pr->next = cd->patchrefs;
+       cd->patchrefs = pr;
+}
+
+
+static void codegen_createlinenumbertable(codegendata *cd)
+{
+#if defined(__I386__) || defined(__ALPHA__) || defined(__X86_64__)
+       linenumberref *lr;
+
+       for (lr = cd->linenumberreferences; lr != NULL; lr = lr->next) {
+               lr->tablepos = dseg_addaddress(cd, NULL);
+
+               if (cd->linenumbertab == 0)
+                       cd->linenumbertab = lr->tablepos;
+
+               dseg_addaddress(cd, lr->linenumber);
        }
 #endif
 }
 
 
-static void codegen_finish(int mcodelen)
+#if defined(__I386__) || defined(__X86_64__)
+static int methodtree_comparator(const void *pc, const void *element, void *param)
 {
-       jumpref *jr;
-       u1 *epoint;
+       methodtree_element *mte;
+       methodtree_element *mtepc;
+
+       mte = (methodtree_element *) element;
+       mtepc = (methodtree_element *) pc;
+
+       /* 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) {
+               return 0;
+
+       } else if ((long) mtepc->startpc < (long) mte->startpc) {
+               return -1;
+
+       } else {
+               return 1;
+       }
+}
+
 
-       int extralen = 0;
+void codegen_insertmethod(functionptr startpc, functionptr endpc)
+{
+       methodtree_element *mte;
+
+#if defined(USE_THREADS)
+#if defined(NATIVE_THREADS)
+       tables_lock();
+#endif
+#endif
+
+       mte = NEW(methodtree_element);
+       mte->startpc = startpc;
+       mte->endpc = endpc;
+
+       if (avl_insert(methodtree, mte)) {
+#if defined(USE_THREADS)
+#if defined(NATIVE_THREADS)
+               tables_unlock();
+#endif
+#endif
+               assert(0);
+               throw_cacao_exception_exit(string_java_lang_InternalError,
+                                                                  "duplicate entry");
+       }
+
+#if defined(USE_THREADS)
+#if defined(NATIVE_THREADS)
+       tables_unlock();
+#endif
+#endif
+}
+
+
+functionptr codegen_findmethod(functionptr pc)
+{
+       methodtree_element *mtepc;
+       methodtree_element *mte;
+
+#if defined(USE_THREADS)
+#if defined(NATIVE_THREADS)
+       tables_lock();
+#endif
+#endif
+
+       mtepc = NEW(methodtree_element);
+       mtepc->startpc = pc;
+       mtepc->endpc = pc;
+
+       mte = avl_find(methodtree, mtepc);
+
+       FREE(mtepc, methodtree_element);
+
+       if (!mte) {
+#if defined(USE_THREADS)
+#if defined(NATIVE_THREADS)
+               tables_unlock();
+#endif
+#endif
+#ifdef JWDEBUG_X86
+                       {
+                               void *bt[5];
+                               fprintf(stderr,"backtrace:");
+                               backtrace_symbols_fd(bt,5,2);
+                       }
+#endif
+               assert(0);
+               throw_cacao_exception_exit(string_java_lang_InternalError,
+                                                                  "Cannot find Java function at %p", pc);
+       }
+
+#if defined(USE_THREADS)
+#if defined(NATIVE_THREADS)
+       tables_unlock();
+#endif
+#endif
+
+       return mte->startpc;
+}
+#endif
+
+#if defined(__ALPHA__)
+/*perhaps in the end I'll have to go for the tree version on alpha too, since this is insecure for eg segfault signals in native code,
+since it will still return an adress of a datasegment, but which will not be a valid one of a java method. This version is faster though (jowenn)*/
+void *codegen_findmethod(void *returnAdress)
+ {
+        void *result;
+        s8 d;
+        void *dataseg;
+        d=*((s4*)returnAdress);
+        d=d<<48;
+        d=d>>48;
+        dataseg=returnAdress+d;
+        d=*(((s4*)returnAdress)+1);
+        d=d>>16;
+        d=d-0x177b;
+        if (d==0) {
+                d=*(((s4*)returnAdress)+1);
+                d=d<<16;
+                dataseg=dataseg+d;
+        }
+        return dataseg;
+#if 0
+        ldl     t0,0(ra)              /* load instruction LDA PV,xxx(RA)          */
+        sll     t0,48,t0
+        sra     t0,48,t0              /* isolate offset                           */
+        addq    t0,ra,pv              /* compute update address                   */
+        ldl     t0,4(ra)              /* load instruction LDAH PV,xxx(PV)         */
+        srl     t0,16,t0              /* isolate instruction code                 */
+        lda     t0,-0x177b(t0)        /* test for LDAH                            */
+        bne     t0,ex_stack_loop
+        ldl     t0,4(ra)              /* load instruction LDAH PV,xxx(RA)         */
+        sll     t0,16,t0              /* compute high offset                      */
+        addl    t0,0,t0               /* sign extend high offset                  */
+        addq    t0,pv,pv              /* compute update address                   */
+        br      ex_stack_loop
+#endif
+}
+
+#endif
+
+
+/* codegen_finish **************************************************************
+
+   Finishes the code generation. A new memory, large enough for both
+   data and code, is allocated and data and code are copied together
+   to their final layout, unresolved jumps are resolved, ...
+
+*******************************************************************************/
+
+static void codegen_finish(methodinfo *m, codegendata *cd, s4 mcodelen)
+{
+       jumpref     *jr;
+       functionptr  epoint;
+       s4           extralen;
+       s4           alignedlen;
 
 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
-       extralen += sizeof(threadcritnode) * threadcritcount;
+       extralen = sizeof(threadcritnode) * cd->threadcritcount;
+#else
+       extralen = 0;
+#endif
+
+#if defined(STATISTICS)
+       if (opt_stat) {
+               count_code_len += mcodelen;
+               count_data_len += cd->dseglen;
+       }
 #endif
 
-       count_code_len += mcodelen;
-       count_data_len += dseglen;
+       cd->dseglen = ALIGN(cd->dseglen, MAX_ALIGN);
+       alignedlen = ALIGN(mcodelen, MAX_ALIGN) + cd->dseglen;
 
-       dseglen = ALIGN(dseglen, MAX_ALIGN);
+       /* allocate new memory */
 
-       method -> mcodelength = mcodelen + dseglen;
-       method -> mcode = CNEW(u1, mcodelen + dseglen + extralen);
+       m->mcodelength = mcodelen + cd->dseglen;
+       m->mcode = (functionptr) (ptrint) CNEW(u1, alignedlen + extralen);
 
-       memcpy ( method->mcode, dsegtop - dseglen, dseglen);
-       memcpy ( method->mcode + dseglen, mcodebase, mcodelen);
+       /* copy data and code to their new location */
 
-       method -> entrypoint = epoint = (u1*) (method->mcode + dseglen);
+       MCOPY((void *) (ptrint) m->mcode, cd->dsegtop - cd->dseglen, u1,
+                 cd->dseglen);
+       MCOPY((void *) ((ptrint) m->mcode + cd->dseglen), cd->mcodebase, u1,
+                 mcodelen);
+
+       m->entrypoint = epoint = (functionptr) ((ptrint) m->mcode + cd->dseglen);
 
        /* jump table resolving */
-       jr = jumpreferences;
+
+       jr = cd->jumpreferences;
        while (jr != NULL) {
-           *((void**) (epoint + jr->tablepos)) = epoint + jr->target->mpc;
-           jr = jr->next;
+               *((functionptr *) ((ptrint) epoint + jr->tablepos)) =
+                       (functionptr) ((ptrint) epoint + (ptrint) jr->target->mpc);
+               jr = jr->next;
        }
 
-#ifdef __I386__
+#if defined(__I386__) || defined(__ALPHA__) || defined(__X86_64__)
        /* line number table resolving */
        {
                linenumberref *lr;
-               #if POINTERSIZE == 8
-                       s8  lrtlen=0;
-               #else
-                       s4  lrtlen=0;
-               #endif
+               ptrint lrtlen = 0;
 
-               for (lr=linenumberreferences;lr!=NULL;lr=lr->next) {
+               for (lr = cd->linenumberreferences; lr != NULL; lr = lr->next) {
                        lrtlen++;
-                       *((void**)(epoint+lr->tablepos))=epoint+lr->targetmpc;
-                       /*log_text("resolving line number information");*/
+                       *((functionptr *) ((ptrint) epoint + (ptrint) lr->tablepos)) =
+                               (functionptr) ((ptrint) epoint + (ptrint) lr->targetmpc);
                }
                
-               *((void**)(epoint+linenumbertablestartpos))=epoint+linenumbertab;
-#if POINTERSIZE == 8
-               *((s8*)(epoint+linenumbertablesizepos))=lrtlen;
-#else
-               *((s4*)(epoint+linenumbertablesizepos))=lrtlen;
-#endif
+               *((functionptr *) ((ptrint) epoint + cd->linenumbertablestartpos)) =
+                       (functionptr) ((ptrint) epoint + cd->linenumbertab);
 
+               *((ptrint *) ((ptrint) epoint + cd->linenumbertablesizepos)) = lrtlen;
        }
 #endif
+
 #if defined(__I386__) || defined(__X86_64__)
+       /* add method into methodtree to find the entrypoint */
+
+       codegen_insertmethod(m->entrypoint,
+                                                (functionptr) ((ptrint) m->entrypoint + mcodelen));
+#endif
+
+#if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__)
        {
                dataref *dr;
-               /* add method into datastructure to find the entrypoint */
-               addmethod(method->entrypoint, method->entrypoint + mcodelen);
-        
+
                /* data segment references resolving */
-               dr = datareferences;
+
+               dr = cd->datareferences;
                while (dr != NULL) {
-                       *((void**) ((long) epoint + (long) dr->pos - POINTERSIZE)) = epoint;
+                       *((functionptr *) ((ptrint) epoint + (ptrint) dr->pos -
+                                                          SIZEOF_VOID_P)) = epoint;
                        dr = dr->next;
                }
        }
 #endif
 
-
 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
        {
-               threadcritnode *n = (threadcritnode*) (method->mcode + mcodelen + dseglen);
-               int i;
-               struct threadcritnodetemp *nt = threadcrit;
-
-               for (i=0; i<threadcritcount; i++)
-               {
-                       n->mcodebegin = method->mcode + nt->mcodebegin;
-                       n->mcodeend = method->mcode + nt->mcodeend;
-                       n->mcoderestart = method->mcode + nt->mcoderestart;
+               threadcritnode *n = (threadcritnode *) ((ptrint) m->mcode + alignedlen);
+               s4 i;
+               threadcritnodetemp *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++;
                        nt = nt->next;
@@ -550,39 +841,208 @@ static void codegen_finish(int mcodelen)
 }
 
 
-
-void dseg_display(s4 *s4ptr)
+void dseg_display(methodinfo *m, codegendata *cd)
 {
-       int i;
+       s4 *s4ptr;
+       s4 i;
        
+       s4ptr = (s4 *) (ptrint) m->mcode;
+
        printf("  --- dump of datasegment\n");
-       for (i = dseglen; i > 0 ; i -= 4) {
-               printf("-%6x: %8x\n", i, (int)(*s4ptr++));
+       for (i = cd->dseglen; i > 0 ; i -= 4) {
+#if SIZEOF_VOID_P == 8
+               printf("0x%016lx:   -%6x (%6d): %8x\n",
+                          (ptrint) s4ptr, i, i, (s4) *s4ptr);
+#else
+               printf("0x%08x:   -%6x (%6d): %8x\n",
+                          (ptrint) s4ptr, i, i, (s4) *s4ptr);
+#endif
+               s4ptr++;
        }
-       printf("  --- begin of data segment: %p\n", s4ptr);
+
+       printf("  --- begin of data segment: %p\n", (void *) s4ptr);
+}
+
+
+
+/* codegen_createnativestub ****************************************************
+
+   Wrapper for createnativestub.
+
+*******************************************************************************/
+
+functionptr codegen_createnativestub(functionptr f, methodinfo *m)
+{
+       codegendata        *cd;
+       registerdata       *rd;
+       t_inlining_globals *id;
+       s4                  dumpsize;
+
+       /* mark dump memory */
+
+       dumpsize = dump_size();
+
+       cd = DNEW(codegendata);
+       rd = DNEW(registerdata);
+       id = DNEW(t_inlining_globals);
+
+       /* setup code generation stuff */
+
+       inlining_setup(m, id);
+       reg_setup(m, rd, id);
+       codegen_setup(m, cd, id);
+                                               
+       m->stubroutine = createnativestub(f, m, cd, rd);
+
+       /* entrypoint was set in codegen_finish, clear it */
+
+       m->entrypoint = NULL;
+
+#if defined(STATISTICS)
+       if (opt_stat)
+               count_nstub_len += m->mcodelength;
+#endif
+
+       /* release memory */
+
+       dump_release(dumpsize);
+
+
+       /* disassemble native stub */
+
+       if (showdisassemble)
+               codegen_disassemble_nativestub(m, (s4 *) (ptrint) m->stubroutine,
+                                                                          m->mcodelength - cd->dseglen);
+
+       /* show data segment */
+
+       if (showddatasegment)
+               dseg_display(m, cd);
+
+       /* return stubroutine entry point */
+
+       return m->stubroutine;
+}
+
+
+/* codegen_disassemble_nativestub **********************************************
+
+   Disassembles the generated native stub.
+
+*******************************************************************************/
+
+void codegen_disassemble_nativestub(methodinfo *m, s4 *code, s4 len)
+{
+       printf("Native stub: ");
+       utf_fprint_classname(stdout, m->class->name);
+       printf(".");
+       utf_fprint(stdout, m->name);
+       utf_fprint(stdout, m->descriptor);
+       printf("\n\nLength: %d\n\n", len);
+
+#if defined(__I386__) || defined(__X86_64__)
+       disassemble((u1 *) code, len);
+#else
+       disassemble(code, len);
+#endif
+}
+
+
+/* removecompilerstub **********************************************************
+
+   Deletes a compilerstub from memory (simply by freeing it).
+
+*******************************************************************************/
+
+void removecompilerstub(functionptr stub)
+{
+       CFREE(stub, 1);
 }
 
+
+/* removenativestub ************************************************************
+
+   Removes a previously created native-stub from memory.
+    
+*******************************************************************************/
+
+void removenativestub(functionptr stub)
+{
+       CFREE(stub, 1);
+}
+
+
+/* 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 result in
+    pseudoregister v.
+    If v is assigned to an actual register, this register will be returned.
+    Otherwise (when v is spilled) this function returns tempregnum.
+    If not already done, regoff and flags are set in the stack location.
+*/        
+
+static int reg_of_var(registerdata *rd, stackptr v, int 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))
+                       return(var->regoff);
+               break;
+
+       case ARGVAR:
+               if (!(v->flags & INMEMORY))
+                       return(v->regoff);
+               break;
+       }
+#ifdef STATISTICS
+       if (opt_stat)
+               count_spills_read++;
+#endif
+       v->flags |= INMEMORY;
+       return tempregnum;
+}
+
+
 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
-void codegen_threadcritrestart(int offset)
+static void codegen_threadcritrestart(codegendata *cd, int offset)
 {
-       threadcritcurrent.mcoderestart = offset;
+       cd->threadcritcurrent.mcoderestart = offset;
 }
 
-void codegen_threadcritstart(int offset)
+
+static void codegen_threadcritstart(codegendata *cd, int offset)
 {
-       threadcritcurrent.mcodebegin = offset;
+       cd->threadcritcurrent.mcodebegin = offset;
 }
 
-void codegen_threadcritstop(int offset)
+
+static void codegen_threadcritstop(codegendata *cd, int offset)
 {
-       threadcritcurrent.next = threadcrit;
-       threadcritcurrent.mcodeend = offset;
-       threadcrit = DNEW(struct threadcritnodetemp);
-       *threadcrit = threadcritcurrent;
-       threadcritcount++;
+       cd->threadcritcurrent.next = cd->threadcrit;
+       cd->threadcritcurrent.mcodeend = offset;
+       cd->threadcrit = DNEW(threadcritnodetemp);
+       *(cd->threadcrit) = cd->threadcritcurrent;
+       cd->threadcritcount++;
 }
 #endif
 
+
 /*
  * These are local overrides for various environment variables in Emacs.
  * Please do not remove this and leave it at the end of the file, where