GNU header update.
[cacao.git] / src / vm / jit / codegen.inc
index 6f127e4946161771a7c91fef51a169986f3058cf..4124842dac57c2ee64ef1b4a22d22d82c504c432 100644 (file)
@@ -1,10 +1,9 @@
-/* jit/codegen.inc - architecture independent code generator
+/* 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 1420 2004-10-27 16:05:14Z twisti $
+   $Id: codegen.inc 1735 2004-12-07 14:33:27Z twisti $
 
 */
 
+#ifndef _CODEGEN_INC_H_
+#define _CODEGEN_INC_H_
 
 #include <string.h>
-#include "exceptions.h"
-#include "native.h"
-#include "options.h"
-#include "statistics.h"
-#include "jit/codegen.inc.h"
-#include "toolbox/memory.h"
-#include "toolbox/logging.h"
+
+#if !defined(STATIC_CLASSPATH)
+# include <dlfcn.h>
+#endif
+
+#include "mm/memory.h"
 #include "toolbox/avl.h"
-#include "threads/thread.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/options.h"
+#include "vm/statistics.h"
+#include "vm/jit/codegen.inc.h"
 
-/* in this tree we store all method addresses */
+
+/* in this tree we store all method addresses *********************************/
 
 #if defined(__I386__) || defined(__X86_64__)
 static struct avl_table *methodtree = NULL;
@@ -91,15 +105,15 @@ void codegen_init()
 
                mte = NEW(methodtree_element);
 
-               mte->startpc = asm_calljavafunction;
-               mte->endpc = asm_calljavafunction2 - 1;
+               mte->startpc = (functionptr) asm_calljavafunction;
+               mte->endpc = (functionptr) ((long) asm_calljavafunction2 - 1);
 
                avl_insert(methodtree, mte);
 
                mte = NEW(methodtree_element);
 
-               mte->startpc = asm_calljavafunction2;
-               mte->endpc = asm_call_jit_compiler - 1;
+               mte->startpc = (functionptr) asm_calljavafunction2;
+               mte->endpc = (functionptr) ((long) asm_call_jit_compiler - 1);
 
                avl_insert(methodtree, mte);
        }
@@ -113,15 +127,8 @@ void codegen_init()
 
 *******************************************************************************/
 
-void codegen_setup(methodinfo *m, t_inlining_globals * e)
+void codegen_setup(methodinfo *m, codegendata *cd, t_inlining_globals *id)
 {
-       codegendata *cd;
-
-       m->codegendata = NEW(codegendata);
-
-       /* keep code size smaller */
-       cd = m->codegendata;
-
        cd->mcodebase = MNEW(u1, MCODEINITSIZE);
        cd->mcodesize = MCODEINITSIZE;
        
@@ -138,23 +145,34 @@ void codegen_setup(methodinfo *m, t_inlining_globals * e)
        cd->xcastrefs = NULL;
        cd->xdivrefs = NULL;
        cd->xexceptionrefs = NULL;
+       cd->clinitrefs = NULL;
 
        cd->linenumberreferences = NULL;
        cd->linenumbertablesizepos = 0;
        cd->linenumbertablestartpos = 0;
        cd->linenumbertab = 0;
        
-       cd->method=m;
-       cd->exceptiontable=0;
-       cd->exceptiontablelength=0;
-       if (useinlining && e) {
-               if (e->cumextablelength>0) {
-                       cd->exceptiontablelength=e->cumextablelength;
-                       cd->exceptiontable  = MNEW(exceptiontable, e->cumextablelength + 1);
+       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 (e && (e->method->exceptiontablelength >0)) {
-                       cd->exceptiontablelength=m->exceptiontablelength;
-                       cd->exceptiontable  = MNEW(exceptiontable, m->exceptiontablelength + 1);
+
+       } 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;
        }
 
 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
@@ -164,21 +182,24 @@ void codegen_setup(methodinfo *m, t_inlining_globals * e)
 }
 
 
-/* codegen_close releases temporary code and data area                        */
+/* codegen_free ****************************************************************
 
-void codegen_close(methodinfo *m)
-{
-       codegendata *cd;
+   releases temporary code and data area
 
-       cd = m->codegendata;
+*******************************************************************************/
 
+void codegen_free(methodinfo *m, codegendata *cd)
+{
        if (cd) {
+#if 0
                if (cd->exceptiontablelength) {
-                       cd->exceptiontablelength=m->exceptiontablelength;
+                       cd->exceptiontablelength = m->exceptiontablelength;
                        MFREE(cd->exceptiontable, exceptiontable, cd->exceptiontablelength + 1);
-                       cd->exceptiontable=0;
-                       cd->exceptiontablelength=0;
+                       cd->exceptiontable = 0;
+                       cd->exceptiontablelength = 0;
                }
+#endif
+
                if (cd->mcodebase) {
                        MFREE(cd->mcodebase, u1, cd->mcodesize);
                        cd->mcodebase = NULL;
@@ -188,22 +209,28 @@ void codegen_close(methodinfo *m)
                        MFREE(cd->dsegtop - cd->dsegsize, u1, cd->dsegsize);
                        cd->dsegtop = NULL;
                }
-
-               FREE(m->codegendata, codegendata);
-               m->codegendata = NULL;
        }
 }
 
 
+/* codegen_close ***************************************************************
+
+   TODO
+
+*******************************************************************************/
+
+void codegen_close()
+{
+       /* TODO: release avl tree on i386 and x86_64 */
+}
+
+
 /* codegen_increase doubles code area                                         */
 
-static s4 *codegen_increase(methodinfo *m, u1 *codeptr)
+static s4 *codegen_increase(codegendata *cd, u1 *codeptr)
 {
-       codegendata *cd;
        long len;
 
-       cd = m->codegendata;
-
        len = codeptr - cd->mcodebase;
        cd->mcodebase = MREALLOC(cd->mcodebase,
                                                         u1,
@@ -218,13 +245,10 @@ static s4 *codegen_increase(methodinfo *m, u1 *codeptr)
 
 /* desg_increase doubles data area                                            */
 
-static void dseg_increase(methodinfo *m)
+static void dseg_increase(codegendata *cd)
 {
-       codegendata *cd;
        u1 *newstorage;
 
-       cd = m->codegendata;
-
        newstorage = MNEW(u1, cd->dsegsize * 2);
 
        memcpy(newstorage + cd->dsegsize, cd->dsegtop - cd->dsegsize, cd->dsegsize);
@@ -236,13 +260,9 @@ static void dseg_increase(methodinfo *m)
 }
 
 
-static s4 dseg_adds4_increase(methodinfo *m, s4 value)
+static s4 dseg_adds4_increase(codegendata *cd, s4 value)
 {
-       codegendata *cd;
-
-       cd = m->codegendata;
-
-       dseg_increase(m);
+       dseg_increase(cd);
 
        *((s4 *) (cd->dsegtop - cd->dseglen)) = value;
 
@@ -250,18 +270,15 @@ static s4 dseg_adds4_increase(methodinfo *m, s4 value)
 }
 
 
-static s4 dseg_adds4(methodinfo *m, s4 value)
+static s4 dseg_adds4(codegendata *cd, s4 value)
 {
-       codegendata *cd;
        s4 *dataptr;
 
-       cd = m->codegendata;
-
        cd->dseglen += 4;
        dataptr = (s4 *) (cd->dsegtop - cd->dseglen);
 
        if (cd->dseglen > cd->dsegsize)
-               return dseg_adds4_increase(m, value);
+               return dseg_adds4_increase(cd, value);
 
        *dataptr = value;
 
@@ -270,13 +287,9 @@ static s4 dseg_adds4(methodinfo *m, s4 value)
 
 
 #if !defined(__I386__)
-static s4 dseg_adds8_increase(methodinfo *m, s8 value)
+static s4 dseg_adds8_increase(codegendata *cd, s8 value)
 {
-       codegendata *cd;
-
-       cd = m->codegendata;
-
-       dseg_increase(m);
+       dseg_increase(cd);
 
        *((s8 *) (cd->dsegtop - cd->dseglen)) = value;
 
@@ -284,18 +297,15 @@ static s4 dseg_adds8_increase(methodinfo *m, s8 value)
 }
 
 
-static s4 dseg_adds8(methodinfo *m, s8 value)
+static s4 dseg_adds8(codegendata *cd, s8 value)
 {
-       codegendata *cd;
        s8 *dataptr;
 
-       cd = m->codegendata;
-
        cd->dseglen = ALIGN(cd->dseglen + 8, 8);
        dataptr = (s8 *) (cd->dsegtop - cd->dseglen);
 
        if (cd->dseglen > cd->dsegsize)
-               return dseg_adds8_increase(m, value);
+               return dseg_adds8_increase(cd, value);
 
        *dataptr = value;
 
@@ -304,13 +314,9 @@ static s4 dseg_adds8(methodinfo *m, s8 value)
 #endif
 
 
-static s4 dseg_addfloat_increase(methodinfo *m, float value)
+static s4 dseg_addfloat_increase(codegendata *cd, float value)
 {
-       codegendata *cd;
-
-       cd = m->codegendata;
-
-       dseg_increase(m);
+       dseg_increase(cd);
 
        *((float *) (cd->dsegtop - cd->dseglen)) = value;
 
@@ -318,18 +324,15 @@ static s4 dseg_addfloat_increase(methodinfo *m, float value)
 }
 
 
-static s4 dseg_addfloat(methodinfo *m, float value)
+static s4 dseg_addfloat(codegendata *cd, float value)
 {
-       codegendata *cd;
        float *dataptr;
 
-       cd = m->codegendata;
-
        cd->dseglen += 4;
        dataptr = (float *) (cd->dsegtop - cd->dseglen);
 
        if (cd->dseglen > cd->dsegsize)
-               return dseg_addfloat_increase(m, value);
+               return dseg_addfloat_increase(cd, value);
 
        *dataptr = value;
 
@@ -337,13 +340,9 @@ static s4 dseg_addfloat(methodinfo *m, float value)
 }
 
 
-static s4 dseg_adddouble_increase(methodinfo *m, double value)
+static s4 dseg_adddouble_increase(codegendata *cd, double value)
 {
-       codegendata *cd;
-
-       cd = m->codegendata;
-
-       dseg_increase(m);
+       dseg_increase(cd);
 
        *((double *) (cd->dsegtop - cd->dseglen)) = value;
 
@@ -351,18 +350,15 @@ static s4 dseg_adddouble_increase(methodinfo *m, double value)
 }
 
 
-static s4 dseg_adddouble(methodinfo *m, double value)
+static s4 dseg_adddouble(codegendata *cd, double value)
 {
-       codegendata *cd;
        double *dataptr;
 
-       cd = m->codegendata;
-
        cd->dseglen = ALIGN(cd->dseglen + 8, 8);
        dataptr = (double *) (cd->dsegtop - cd->dseglen);
 
        if (cd->dseglen > cd->dsegsize)
-               return dseg_adddouble_increase(m, value);
+               return dseg_adddouble_increase(cd, value);
 
        *dataptr = value;
 
@@ -370,28 +366,22 @@ static s4 dseg_adddouble(methodinfo *m, double value)
 }
 
 
-static void dseg_addtarget(methodinfo *m, basicblock *target)
+static void dseg_addtarget(codegendata *cd, basicblock *target)
 {
-       codegendata *cd;
        jumpref *jr;
 
-       cd = m->codegendata;
-       
        jr = DNEW(jumpref);
-       jr->tablepos = dseg_addaddress(m, NULL);
+       jr->tablepos = dseg_addaddress(cd, NULL);
        jr->target = target;
        jr->next = cd->jumpreferences;
        cd->jumpreferences = jr;
 }
 
 
-static void dseg_adddata(methodinfo *m, u1 *ptr)
+static void dseg_adddata(codegendata *cd, u1 *ptr)
 {
-       codegendata *cd;
        dataref *dr;
 
-       cd = m->codegendata;
-
        dr = DNEW(dataref);
        dr->pos = (u1 *) (ptr - cd->mcodebase);
        dr->next = cd->datareferences;
@@ -399,31 +389,24 @@ static void dseg_adddata(methodinfo *m, u1 *ptr)
 }
 
 
-static void dseg_addlinenumbertablesize(methodinfo *m)
+static void dseg_addlinenumbertablesize(codegendata *cd)
 {
-       codegendata *cd;
-
-       cd = m->codegendata;
-
 #ifdef __ALPHA__
-       dseg_adds4(m, 0); /*PADDING*/
+       dseg_adds4(cd, 0); /*PADDING*/
 #endif
-       cd->linenumbertablesizepos = dseg_addaddress(m, 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 */
 
-       cd->linenumbertablestartpos = dseg_addaddress(m, NULL);
+       cd->linenumbertablestartpos = dseg_addaddress(cd, NULL);
 #ifdef __ALPHA__
-       dseg_adds4(m, 0); /*PADDING*/
+       dseg_adds4(cd, 0); /*PADDING*/
 #endif
 }
 
 
-static void dseg_addlinenumber(methodinfo *m, u2 linenumber, u1 *ptr)
+static void dseg_addlinenumber(codegendata *cd, u2 linenumber, u1 *ptr)
 {
-       codegendata *cd;
        linenumberref *lr;
 
-       cd = m->codegendata;
-
        lr = DNEW(linenumberref);
        lr->linenumber = linenumber;
        lr->tablepos = 0;
@@ -437,16 +420,13 @@ static void dseg_addlinenumber(methodinfo *m, u2 linenumber, u1 *ptr)
    on alpha... */
 
 #if defined(__I386__) || defined(__X86_64__)
-void codegen_addreference(methodinfo *m, basicblock *target, void *branchptr)
+void codegen_addreference(codegendata *cd, basicblock *target, void *branchptr)
 #else
-static void codegen_addreference(methodinfo *m, basicblock *target, void *branchptr)
+static void codegen_addreference(codegendata *cd, basicblock *target, void *branchptr)
 #endif
 {
-       codegendata *cd;
        s4 branchpos;
 
-       cd = m->codegendata;
-
        branchpos = (u1 *) branchptr - cd->mcodebase;
 
        if (target->mpc >= 0) {
@@ -464,14 +444,11 @@ static void codegen_addreference(methodinfo *m, basicblock *target, void *branch
 }
 
 
-static void codegen_addxboundrefs(methodinfo *m, void *branchptr, s4 reg)
+static void codegen_addxboundrefs(codegendata *cd, void *branchptr, s4 reg)
 {
-       codegendata *cd;
        s4 branchpos;
        branchref *br;
 
-       cd = m->codegendata;
-
        branchpos = (u1 *) branchptr - cd->mcodebase;
 
        br = DNEW(branchref);
@@ -482,14 +459,11 @@ static void codegen_addxboundrefs(methodinfo *m, void *branchptr, s4 reg)
 }
 
 
-static void codegen_addxcheckarefs(methodinfo *m, void *branchptr)
+static void codegen_addxcheckarefs(codegendata *cd, void *branchptr)
 {
-       codegendata *cd;
        s4 branchpos;
        branchref *br;
 
-       cd = m->codegendata;
-
        branchpos = (u1 *) branchptr - cd->mcodebase;
 
        br = DNEW(branchref);
@@ -499,14 +473,11 @@ static void codegen_addxcheckarefs(methodinfo *m, void *branchptr)
 }
 
 
-static void codegen_addxnullrefs(methodinfo *m, void *branchptr)
+static void codegen_addxnullrefs(codegendata *cd, void *branchptr)
 {
-       codegendata *cd;
        s4 branchpos;
        branchref *br;
 
-       cd = m->codegendata;
-
        branchpos = (u1 *) branchptr - cd->mcodebase;
 
        br = DNEW(branchref);
@@ -516,15 +487,11 @@ static void codegen_addxnullrefs(methodinfo *m, void *branchptr)
 }
 
 
-
-static void codegen_addxcastrefs(methodinfo *m, void *branchptr)
+static void codegen_addxcastrefs(codegendata *cd, void *branchptr)
 {
-       codegendata *cd;
        s4 branchpos;
        branchref *br;
 
-       cd = m->codegendata;
-
        branchpos = (u1 *) branchptr - cd->mcodebase;
 
        br = DNEW(branchref);
@@ -534,14 +501,11 @@ static void codegen_addxcastrefs(methodinfo *m, void *branchptr)
 }
 
 
-static void codegen_addxexceptionrefs(methodinfo *m, void *branchptr)
+static void codegen_addxexceptionrefs(codegendata *cd, void *branchptr)
 {
-       codegendata *cd;
        s4 branchpos;
        branchref *br;
 
-       cd = m->codegendata;
-
        branchpos = (u1 *) branchptr - cd->mcodebase;
 
        br = DNEW(branchref);
@@ -552,14 +516,11 @@ static void codegen_addxexceptionrefs(methodinfo *m, void *branchptr)
 
 
 #if defined(__I386__) || defined(__X86_64__)
-static void codegen_addxdivrefs(methodinfo *m, void *branchptr)
+static void codegen_addxdivrefs(codegendata *cd, void *branchptr)
 {
-       codegendata *cd;
        s4 branchpos;
        branchref *br;
 
-       cd = m->codegendata;
-
        branchpos = (u1 *) branchptr - cd->mcodebase;
 
        br = DNEW(branchref);
@@ -570,21 +531,35 @@ static void codegen_addxdivrefs(methodinfo *m, void *branchptr)
 #endif
 
 
-static void codegen_createlinenumbertable(methodinfo *m)
+static void codegen_addclinitref(codegendata *cd,
+                                                                void *branchptr,
+                                                                classinfo *class)
 {
-#ifdef __I386__
-       codegendata *cd;
-       linenumberref *lr;
+       s4 branchpos;
+       clinitref *cr;
 
-       cd = m->codegendata;
+       branchpos = (u1 *) branchptr - cd->mcodebase;
+
+       cr = DNEW(clinitref);
+       cr->branchpos = branchpos;
+       cr->class = class;
+       cr->next = cd->clinitrefs;
+       cd->clinitrefs = cr;
+}
+
+
+static void codegen_createlinenumbertable(codegendata *cd)
+{
+#if defined(__I386__) || defined(__ALPHA__)
+       linenumberref *lr;
 
        for (lr = cd->linenumberreferences; lr != NULL; lr = lr->next) {
-               lr->tablepos = dseg_addaddress(m, NULL);
+               lr->tablepos = dseg_addaddress(cd, NULL);
 
                if (cd->linenumbertab == 0)
                        cd->linenumbertab = lr->tablepos;
 
-               dseg_addaddress(m, lr->linenumber);
+               dseg_addaddress(cd, lr->linenumber);
        }
 #endif
 }
@@ -602,11 +577,13 @@ static int methodtree_comparator(const void *pc, const void *element, void *para
        /* 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 (mte->startpc <= mtepc->startpc && mtepc->startpc <= mte->endpc &&
-               mte->startpc <= mtepc->endpc   && mtepc->endpc   <= mte->endpc) {
+       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 (mtepc->startpc < mte->startpc) {
+       } else if ((long) mtepc->startpc < (long) mte->startpc) {
                return -1;
 
        } else {
@@ -632,7 +609,7 @@ void *codegen_findmethod1(void *pc)
 #endif
 
 
-void codegen_insertmethod(void *startpc, void *endpc)
+void codegen_insertmethod(functionptr startpc, functionptr endpc)
 {
        methodtree_element *mte;
 
@@ -664,11 +641,17 @@ void codegen_insertmethod(void *startpc, void *endpc)
 }
 
 
-void *codegen_findmethod(void *pc)
+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;
@@ -677,27 +660,78 @@ void *codegen_findmethod(void *pc)
 
        FREE(mtepc, methodtree_element);
 
-       if (!mte)
+       if (!mte) {
+#if defined(USE_THREADS)
+#if defined(NATIVE_THREADS)
+               tables_unlock();
+#endif
+#endif
                throw_cacao_exception_exit(string_java_lang_InternalError,
                                                                   "cannot find function");
+       }
+
+#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
 
-static void codegen_finish(methodinfo *m, s4 mcodelen)
+
+static void codegen_finish(methodinfo *m, codegendata *cd, s4 mcodelen)
 {
-       codegendata *cd;
        jumpref *jr;
-       u1 *epoint;
-       s4 extralen = 0;
+       functionptr epoint;
+       s4 extralen;
        s4 alignedlen;
 
-       cd = m->codegendata;
-
 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
-       extralen += sizeof(threadcritnode) * cd->threadcritcount;
+       extralen = sizeof(threadcritnode) * cd->threadcritcount;
+#else
+       extralen = 0;
 #endif
 
 #if defined(STATISTICS)
@@ -711,21 +745,22 @@ static void codegen_finish(methodinfo *m, s4 mcodelen)
        alignedlen = ALIGN(mcodelen, MAX_ALIGN) + cd->dseglen;
 
        m->mcodelength = mcodelen + cd->dseglen;
-       m->mcode = CNEW(u1, alignedlen + extralen);
+       m->mcode = (functionptr) (long) CNEW(u1, alignedlen + extralen);
 
-       memcpy(m->mcode, cd->dsegtop - cd->dseglen, cd->dseglen);
-       memcpy(m->mcode + cd->dseglen, cd->mcodebase, mcodelen);
+       memcpy((void *) (long) m->mcode, cd->dsegtop - cd->dseglen, cd->dseglen);
+       memcpy((void *) ((long) m->mcode + cd->dseglen), cd->mcodebase, mcodelen);
 
-       m->entrypoint = epoint = (u1 *) (m->mcode + cd->dseglen);
+       m->entrypoint = epoint = (functionptr) ((long) m->mcode + cd->dseglen);
 
        /* jump table resolving */
        jr = cd->jumpreferences;
        while (jr != NULL) {
-           *((void**) (epoint + jr->tablepos)) = epoint + jr->target->mpc;
-           jr = jr->next;
+               *((functionptr *) ((long) epoint + jr->tablepos)) =
+                       (functionptr) ((long) epoint + (long) jr->target->mpc);
+               jr = jr->next;
        }
 
-#ifdef __I386__
+#if defined(__I386__) || defined(__ALPHA__)
        /* line number table resolving */
        {
                linenumberref *lr;
@@ -737,15 +772,16 @@ static void codegen_finish(methodinfo *m, s4 mcodelen)
 
                for (lr = cd->linenumberreferences; lr != NULL; lr = lr->next) {
                        lrtlen++;
-                       *((void**) (epoint + lr->tablepos)) = epoint + lr->targetmpc;
+                       *((functionptr *) ((long) epoint + (long) lr->tablepos)) =
+                               (functionptr) ((long) epoint + (long) lr->targetmpc);
                }
                
-               *((void**) (epoint + cd->linenumbertablestartpos)) =
-                       epoint + cd->linenumbertab;
+               *((functionptr *) ((long) epoint + cd->linenumbertablestartpos)) =
+                       (functionptr) ((long) epoint + cd->linenumbertab);
 #if POINTERSIZE == 8
-               *((s8*) (epoint + cd->linenumbertablesizepos)) = lrtlen;
+               *((s8 *) ((s8) epoint + cd->linenumbertablesizepos)) = lrtlen;
 #else
-               *((s4*) (epoint + cd->linenumbertablesizepos)) = lrtlen;
+               *((s4 *) ((s4) epoint + cd->linenumbertablesizepos)) = lrtlen;
 #endif
        }
 #endif
@@ -755,12 +791,14 @@ static void codegen_finish(methodinfo *m, s4 mcodelen)
                dataref *dr;
 
                /* add method into methodtree to find the entrypoint */
-               codegen_insertmethod(m->entrypoint, m->entrypoint + mcodelen);
+               codegen_insertmethod(m->entrypoint,
+                                                        (functionptr) ((long) m->entrypoint + mcodelen));
 
                /* data segment references resolving */
                dr = cd->datareferences;
                while (dr != NULL) {
-                       *((void**) ((long) epoint + (long) dr->pos - POINTERSIZE)) = epoint;
+                       *((functionptr *) ((long) epoint + (long) dr->pos - POINTERSIZE)) =
+                               epoint;
                        dr = dr->next;
                }
        }
@@ -768,14 +806,14 @@ static void codegen_finish(methodinfo *m, s4 mcodelen)
 
 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
        {
-               threadcritnode *n = (threadcritnode *) (m->mcode + alignedlen);
+               threadcritnode *n = (threadcritnode *) ((long) m->mcode + alignedlen);
                s4 i;
                threadcritnodetemp *nt = cd->threadcrit;
 
                for (i = 0; i < cd->threadcritcount; i++) {
-                       n->mcodebegin = m->mcode + nt->mcodebegin;
-                       n->mcodeend = m->mcode + nt->mcodeend;
-                       n->mcoderestart = m->mcode + nt->mcoderestart;
+                       n->mcodebegin = (u1 *) (long) m->mcode + nt->mcodebegin;
+                       n->mcodeend = (u1 *) (long) m->mcode + nt->mcodeend;
+                       n->mcoderestart = (u1 *) (long) m->mcode + nt->mcoderestart;
                        thread_registercritical(n);
                        n++;
                        nt = nt->next;
@@ -785,22 +823,21 @@ static void codegen_finish(methodinfo *m, s4 mcodelen)
 }
 
 
-void dseg_display(methodinfo *m)
+void dseg_display(methodinfo *m, codegendata *cd)
 {
        s4 *s4ptr;
        s4 i;
        
-       s4ptr = (s4 *) m->mcode;
+       s4ptr = (s4 *) (long) m->mcode;
 
        printf("  --- dump of datasegment\n");
-       for (i = m->codegendata->dseglen; i > 0 ; i -= 4) {
+       for (i = cd->dseglen; i > 0 ; i -= 4) {
                printf("-%6x: %8x\n", i, (s4) (*s4ptr++));
        }
-       printf("  --- begin of data segment: %p\n", s4ptr);
+       printf("  --- begin of data segment: %p\n", (void *) s4ptr);
 }
 
 
-#if !defined(__POWERPC__)
 /* 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
@@ -810,7 +847,7 @@ void dseg_display(methodinfo *m)
     If not already done, regoff and flags are set in the stack location.
 */        
 
-static int reg_of_var(methodinfo *m, stackptr v, int tempregnum)
+static int reg_of_var(registerdata *rd, stackptr v, int tempregnum)
 {
        varinfo *var;
 
@@ -820,13 +857,13 @@ static int reg_of_var(methodinfo *m, stackptr v, int tempregnum)
                        return(v->regoff);
                break;
        case STACKVAR:
-               var = &(m->registerdata->interfaces[v->varnum][v->type]);
+               var = &(rd->interfaces[v->varnum][v->type]);
                v->regoff = var->regoff;
                if (!(var->flags & INMEMORY))
                        return(var->regoff);
                break;
        case LOCALVAR:
-               var = &(m->registerdata->locals[v->varnum][v->type]);
+               var = &(rd->locals[v->varnum][v->type]);
                v->regoff = var->regoff;
                if (!(var->flags & INMEMORY))
                        return(var->regoff);
@@ -834,42 +871,48 @@ static int reg_of_var(methodinfo *m, stackptr v, int tempregnum)
        case ARGVAR:
                v->regoff = v->varnum;
                if (IS_FLT_DBL_TYPE(v->type)) {
-                       if (v->varnum < m->registerdata->fltreg_argnum) {
-                               v->regoff = m->registerdata->argfltregs[v->varnum];
-                               return(m->registerdata->argfltregs[v->varnum]);
+                       if (v->varnum < rd->fltreg_argnum) {
+                               v->regoff = rd->argfltregs[v->varnum];
+                               return(rd->argfltregs[v->varnum]);
                        }
-               }
-               else
-                       if (v->varnum < m->registerdata->intreg_argnum) {
-                               v->regoff = m->registerdata->argintregs[v->varnum];
-                               return(m->registerdata->argintregs[v->varnum]);
+
+               } else {
+#if defined(__POWERPC__)
+                       if (v->varnum < rd->intreg_argnum - (IS_2_WORD_TYPE(v->type) != 0)) {
+#else
+                       if (v->varnum < rd->intreg_argnum) {
+#endif
+                               v->regoff = rd->argintregs[v->varnum];
+                               return (rd->argintregs[v->varnum]);
                        }
-               v->regoff -= m->registerdata->intreg_argnum;
+               }
+#if defined(__POWERPC__)
+               v->regoff += 6;
+#else
+               v->regoff -= rd->intreg_argnum;
+#endif
                break;
        }
        v->flags |= INMEMORY;
        return tempregnum;
 }
-#endif
 
 
 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
-static void codegen_threadcritrestart(methodinfo *m, int offset)
+static void codegen_threadcritrestart(codegendata *cd, int offset)
 {
-       m->codegendata->threadcritcurrent.mcoderestart = offset;
+       cd->threadcritcurrent.mcoderestart = offset;
 }
 
-static void codegen_threadcritstart(methodinfo *m, int offset)
-{
-       m->codegendata->threadcritcurrent.mcodebegin = offset;
-}
 
-static void codegen_threadcritstop(methodinfo *m, int offset)
+static void codegen_threadcritstart(codegendata *cd, int offset)
 {
-       codegendata *cd;
+       cd->threadcritcurrent.mcodebegin = offset;
+}
 
-       cd = m->codegendata;
 
+static void codegen_threadcritstop(codegendata *cd, int offset)
+{
        cd->threadcritcurrent.next = cd->threadcrit;
        cd->threadcritcurrent.mcodeend = offset;
        cd->threadcrit = DNEW(threadcritnodetemp);
@@ -878,6 +921,188 @@ static void codegen_threadcritstop(methodinfo *m, int offset)
 }
 #endif
 
+
+#ifndef STATIC_CLASSPATH
+static size_t codegen_overloadPartLen(utf *desc) {
+        char *utf_ptr=desc->text;
+        u2 c;
+       size_t len=2;
+        while ((c=utf_nextu2(&utf_ptr))!=')') {
+                switch (c) {
+                        case 'I':
+                        case 'S':
+                        case 'B':
+                        case 'C':
+                        case 'Z':
+                        case 'J':
+                        case 'F':
+                        case 'D':
+                               len ++;
+                               break;
+                        case '[':
+                                len = len+2;
+                                break;
+                        case 'L':
+                                len++;
+                                while ( (c=utf_nextu2(&utf_ptr)) != ';')
+                                        len++;
+                                len=len+2;
+                                break;
+                        case '(':
+                                break;
+                        default: panic ("invalid method descriptor");
+                }
+        }
+       return len;
+
+}
+
+static void codegen_fillInOverloadPart(char *target,utf *desc) {
+        char *utf_ptr=desc->text;
+        u2 c;
+       char* insertpos=&target[strlen(target)];
+       *(insertpos++)='_';
+       *(insertpos++)='_';
+        while ((c=utf_nextu2(&utf_ptr))!=')') {
+                switch (c) {
+                        case 'I':
+                        case 'S':
+                        case 'B':
+                        case 'C':
+                        case 'Z':
+                        case 'J':
+                        case 'F':
+                        case 'D':
+                                *(insertpos++)=c;
+                                break;
+                        case '[':
+                               *(insertpos++)='_';
+                               *(insertpos++)='3';
+                                break;
+                        case 'L':
+                               *(insertpos++)='L';
+                                while ( (c=utf_nextu2(&utf_ptr)) != ';')
+                                       if ( ((c>='a') && (c<='z'))  ||
+                                               ((c>='A') && (c<='Z')) ||
+                                               ((c>='0') && (c<='9')) )
+                                                       *(insertpos++)=c;
+                                       else *(insertpos++)='_';
+                               *(insertpos++)='_';
+                               *(insertpos++)='2';
+                                break;
+                        case '(':
+                                break;
+                        default: panic ("invalid method descriptor");
+                }
+        }
+       *insertpos='\0';
+
+}
+
+static void codegen_resolve_native(methodinfo *m,void **insertionPoint,void *jmpTarget,void **jmpPatchTarget) {
+  char *nativeName, *nativeNameEscape;
+  size_t nativeLen;
+  size_t i;
+       void *lib;
+       void *sym;
+
+  builtin_monitorenter((java_objectheader*) m);
+#if defined(__X86_64__)
+  if ((*((s4*)jmpPatchTarget))==((s4)jmpTarget)) {
+#else
+  if ((*jmpPatchTarget)==jmpTarget) {
+#endif
+    builtin_monitorexit((java_objectheader*) m);
+    return;
+  }
+  /*log_text("trying to resolve a native method");
+  utf_display(m->class->name);
+  utf_display(m->name);*/
+  
+  lib=dlopen(0,RTLD_NOW | RTLD_GLOBAL); /* open the application execution image */
+  if (lib) { /* it did work -> good, otherwise fail with error*/
+    int ok=0;
+    /*generate the name of the native function in the form Java_package1_package2...._classname_methodname*/
+    nativeLen=/*Java_*/5+strlen(m->class->name->text)+/*_*/1+strlen(m->name->text)+/*\0*/1;
+    nativeName=MNEW(char,nativeLen);
+    sprintf(nativeName,"Java_%s/%s",m->class->name->text,m->name->text);
+       i=5;
+    while (i<nativeLen) {
+               if (nativeName[i]=='_') { /* escape underscore */
+                       nativeNameEscape = MNEW(char,nativeLen+1);
+                       memcpy(nativeNameEscape,nativeName,i+1);
+                       nativeNameEscape[i+1] = '1'; /* escape sequence for _ is _1 */
+                       memcpy(&nativeNameEscape[i+2],&nativeName[i+1],nativeLen-i-1);
+                       MFREE(nativeName,char,nativeLen);
+                       i++;
+                       nativeLen++;
+                       nativeNameEscape[nativeLen]=0;
+                       nativeName=nativeNameEscape;
+               }
+               if (nativeName[i]=='/') nativeName[i]='_';
+               i++;
+    } 
+
+/*     printf("nativename: %s\n",nativeName); */
+
+    /*try to find the symbal fo the function */
+    sym=dlsym(lib,nativeName);
+    if (sym) {
+      ok=1; /* it worked, everything fine */
+      /*log_text("resolved");*/
+      MFREE(nativeName,char,nativeLen);
+    } else { /* we didn't find the symbol yet, try to resolve an overlaoded function (having the types in it's name*/
+      size_t overloadedNativeLen=nativeLen+codegen_overloadPartLen(m->descriptor);
+      char *overloadedNative=MNEW(char,overloadedNativeLen);
+      sprintf(overloadedNative,"%s",nativeName);
+      MFREE(nativeName,char,nativeLen);
+      codegen_fillInOverloadPart(overloadedNative,m->descriptor);
+      /*log_text("symbol not found,trying harder (overloaded member ?)");*/
+      sym=dlsym(lib,overloadedNative);
+      if (sym) {
+        MFREE(overloadedNative,char,overloadedNativeLen);
+        ok=1; /* we eventually found the native function -> everything ok*/
+        /*log_text("resolved");*/
+      } else { 
+         /* we failed to find the native function within the execution image (app + loaded libraries) -> will cause an exit*/
+         MFREE(overloadedNative,char,overloadedNativeLen);
+         log_text("It was not possible to find the native function implementation. Not even in overloading case");
+      }
+   }
+    /* patch the address of the native function into the stub and make the stub jump over this function call in the future */
+    if (ok) {
+      (*insertionPoint)=sym;
+#if defined(__X86_64__)
+      (*((s4*)jmpPatchTarget))=(s4)jmpTarget;
+#else
+      (*jmpPatchTarget)=jmpTarget;
+#endif
+      builtin_monitorexit((java_objectheader *) m );
+      return;
+    }
+
+  } else log_text("library not found");
+  
+  /* There was an error, either the app image could not be opened or the native does not exist in the application and the
+     loaded libraries. Show an additional error and exit the vm*/
+  {
+    char *info;
+    size_t slen;
+    slen=2+strlen(m->class->name->text)+strlen(m->name->text)+strlen(m->descriptor->text);
+    info=(char*)MNEW(char,slen);
+    sprintf(info,"%s.%s%s",m->class->name->text,m->name->text,m->descriptor->text);
+    
+    builtin_monitorexit((java_objectheader *) m );
+    throw_cacao_exception_exit(string_java_lang_LinkageError,
+                                                       info);
+  }
+  
+}
+#endif
+
+
+#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