* Merged in twisti-branch.
authortwisti <none@none>
Wed, 28 Mar 2007 21:05:53 +0000 (21:05 +0000)
committertwisti <none@none>
Wed, 28 Mar 2007 21:05:53 +0000 (21:05 +0000)
120 files changed:
AUTHORS
configure.ac
src/Makefile.am
src/cacaoh/dummy.c
src/mm/boehm-gc/include/private/gc_locks.h
src/mm/nogc.c
src/native/include/Makefile.am
src/native/jni.c
src/toolbox/list.c
src/toolbox/list.h
src/vm/builtin.c
src/vm/exceptions.c
src/vm/exceptions.h
src/vm/jit/abi.h
src/vm/jit/alpha/arch.h
src/vm/jit/alpha/asmpart.S
src/vm/jit/alpha/codegen.c
src/vm/jit/alpha/codegen.h
src/vm/jit/alpha/emit.c
src/vm/jit/alpha/linux/md-os.c
src/vm/jit/alpha/md.c
src/vm/jit/alpha/patcher.c
src/vm/jit/arm/arch.h
src/vm/jit/arm/asmpart.S
src/vm/jit/arm/codegen.c
src/vm/jit/arm/codegen.h
src/vm/jit/arm/emit.c
src/vm/jit/arm/linux/md-os.c
src/vm/jit/arm/md.c
src/vm/jit/asmpart.h
src/vm/jit/codegen-common.c
src/vm/jit/codegen-common.h
src/vm/jit/disass-common.c
src/vm/jit/disass.h
src/vm/jit/dseg.c
src/vm/jit/dseg.h
src/vm/jit/emit-common.c
src/vm/jit/emit-common.h
src/vm/jit/i386/arch.h
src/vm/jit/i386/asmpart.S
src/vm/jit/i386/codegen.c
src/vm/jit/i386/codegen.h
src/vm/jit/i386/emit.c
src/vm/jit/i386/linux/md-os.c
src/vm/jit/i386/md.c
src/vm/jit/i386/patcher.c
src/vm/jit/jit.c
src/vm/jit/jit.h
src/vm/jit/m68k/Makefile.am
src/vm/jit/m68k/arch.h
src/vm/jit/m68k/asmpart.S
src/vm/jit/m68k/codegen.c
src/vm/jit/m68k/codegen.h
src/vm/jit/m68k/emit.c
src/vm/jit/m68k/machine-instr.h
src/vm/jit/m68k/md.c
src/vm/jit/m68k/patcher.c
src/vm/jit/m68k/uclinux/Makefile.am [deleted file]
src/vm/jit/m68k/uclinux/md-abi.c [deleted file]
src/vm/jit/m68k/uclinux/md-abi.h [deleted file]
src/vm/jit/m68k/uclinux/md-asm.h [deleted file]
src/vm/jit/m68k/uclinux/md-os.c [deleted file]
src/vm/jit/mips/arch.h
src/vm/jit/mips/asmpart.S
src/vm/jit/mips/codegen.c
src/vm/jit/mips/codegen.h
src/vm/jit/mips/emit.c
src/vm/jit/mips/linux/md-os.c
src/vm/jit/mips/md.c
src/vm/jit/mips/patcher.c
src/vm/jit/parse.c
src/vm/jit/powerpc/arch.h
src/vm/jit/powerpc/asmpart.S
src/vm/jit/powerpc/codegen.c
src/vm/jit/powerpc/codegen.h
src/vm/jit/powerpc/darwin/md-os.c
src/vm/jit/powerpc/emit.c
src/vm/jit/powerpc/linux/md-os.c
src/vm/jit/powerpc/md.c
src/vm/jit/powerpc/patcher.c
src/vm/jit/powerpc64/arch.h
src/vm/jit/powerpc64/asmpart.S
src/vm/jit/powerpc64/codegen.c
src/vm/jit/powerpc64/codegen.h
src/vm/jit/powerpc64/emit.c
src/vm/jit/powerpc64/linux/md-abi.c
src/vm/jit/powerpc64/linux/md-abi.h
src/vm/jit/powerpc64/linux/md-os.c
src/vm/jit/powerpc64/md.c
src/vm/jit/powerpc64/patcher.c
src/vm/jit/reg.c
src/vm/jit/s390/asmpart.S
src/vm/jit/sparc64/arch.h
src/vm/jit/sparc64/asmpart.S
src/vm/jit/sparc64/codegen.c
src/vm/jit/sparc64/codegen.h
src/vm/jit/sparc64/emit-arch.h [new file with mode: 0644]
src/vm/jit/sparc64/emit.c
src/vm/jit/sparc64/linux/md-os.c
src/vm/jit/sparc64/md.c
src/vm/jit/sparc64/patcher.c
src/vm/jit/stacktrace.c
src/vm/jit/verify/typecheck-invoke.inc
src/vm/jit/x86_64/arch.h
src/vm/jit/x86_64/asmpart.S
src/vm/jit/x86_64/codegen.c
src/vm/jit/x86_64/codegen.h
src/vm/jit/x86_64/emit.c
src/vm/jit/x86_64/emit.h
src/vm/jit/x86_64/linux/md-os.c
src/vm/jit/x86_64/md.c
src/vm/jit/x86_64/patcher.c
src/vm/signal.c
src/vm/signallocal.h
src/vm/vm.c
src/vmcore/descriptor.h
src/vmcore/loader.c
src/vmcore/options.c
src/vmcore/options.h
tests/regression/native/Makefile.am

diff --git a/AUTHORS b/AUTHORS
index 11aa8aa060a449483d61d26b8f0c214e2d926284..bec0f3346a2efad790c09b987806a4e10c61bf0a 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -1,8 +1,9 @@
-These people contributed work to CACAO:
+These people contributed work to CACAO (keep this list alpha-sorted):
 
 Reinhard Grafl
 Andreas Krall
 Christopher Kruegel
+Roland Lezuo
 Carolyn Oates
 Roman Obermaisser
 Martin Platter
index c2ca770c0ffaab9c23037250ded6543161a94b36..57f25442f5fbdd4793b7529b5efca23c475ebf0b 100644 (file)
@@ -22,7 +22,7 @@ dnl along with this program; if not, write to the Free Software
 dnl Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 dnl 02110-1301, USA.
 dnl 
-dnl $Id: configure.ac 7434 2007-03-02 19:44:53Z edwin $
+dnl $Id: configure.ac 7596 2007-03-28 21:05:53Z twisti $
 
 dnl Process this file with autoconf to produce a configure script.
 
@@ -280,6 +280,9 @@ dnl Features
 AC_CHECK_ENABLE_JAVA
 AC_CHECK_ENABLE_JIT
 
+dnl with-options
+AC_CHECK_WITH_CACAOH
+
 dnl check for stuff that should be done in software
 AC_CHECK_SOFTFLOAT
 AC_CHECK_SOFT_FLOAT_CMP
@@ -367,6 +370,7 @@ AM_CONDITIONAL([ENABLE_GC_BOEHM], test x"${ENABLE_GC}" = "xboehm")
 AM_CONDITIONAL([ENABLE_GC_CACAO], test x"${ENABLE_GC}" = "xcacao")
 
 
+
 dnl check for dump memory usage
 AC_MSG_CHECKING(whether dump memory should be disabled)
 AC_ARG_ENABLE([dump],
@@ -437,7 +441,7 @@ if test x"${ENABLE_DISASSEMBLER}" = "xyes"; then
     dnl check for binutils headers and libraries on some architectures for the
     dnl disassembler
     case "${ARCH_DIR}" in
-        arm | i386 | powerpc | x86_64 | sparc64 | powerpc64 | s390)
+        arm | i386 | powerpc | x86_64 | sparc64 | powerpc64 | s390 | m68k)
             AC_CHECK_HEADER([ansidecl.h],, [AC_MSG_ERROR(cannot find ansidecl.h)])
             AC_CHECK_HEADER([symcat.h],, [AC_MSG_ERROR(cannot find symcat.h)])
             AC_CHECK_HEADER([bfd.h],, [AC_MSG_ERROR(cannot find bfd.h)])
@@ -1024,6 +1028,8 @@ AC_CONFIG_FILES([Makefile]
                [src/vm/jit/intrp/Makefile]
                [src/vm/jit/inline/Makefile]
                [src/vm/jit/loop/Makefile]
+               [src/vm/jit/m68k/Makefile]
+               [src/vm/jit/m68k/linux/Makefile]
                [src/vm/jit/mips/Makefile]
                [src/vm/jit/mips/irix/Makefile]
                [src/vm/jit/mips/linux/Makefile]
index 69ec6f6f808e3cc03cd29910eb53c938d82d5e7b..1681eddf5b875405bdb6538e11391e928c126c52 100644 (file)
@@ -22,7 +22,7 @@
 ## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 ## 02110-1301, USA.
 ##
-## $Id: Makefile.am 7365 2007-02-15 19:42:13Z twisti $
+## $Id: Makefile.am 7596 2007-03-28 21:05:53Z twisti $
 
 ## Process this file with automake to produce Makefile.in
 
@@ -49,13 +49,17 @@ THREADS_DIR = \
        threads
 endif
 
+if ENABLE_CACAOH
+CACAOH_DIR = \
+       cacaoh 
+endif
+
 # DON'T CHANGE THIS ORDER!!!
 
 SUBDIRS = \
        toolbox \
        vmcore \
-       cacaoh \
-       \
+       $(CACAOH_DIR) \
        $(VM_DIR) \
        native \
        fdlibm \
index dbc4430689c9ffa3c617ea2a15b8d4cbaf12e28f..7dceda8555b76573b8775eae7dd82bbe74b0790a 100644 (file)
@@ -275,6 +275,17 @@ void exceptions_throw_noclassdeffounderror(utf *name)
        abort();
 }
 
+void exceptions_throw_noclassdeffounderror_wrong_name(classinfo *c, utf *name)
+{
+       fprintf(stderr, "java.lang.NoClassDefFoundError: ");
+       utf_fprint_printable_ascii(stderr, c->name);
+       fprintf(stderr, " (wrong name: ");
+       utf_fprint_printable_ascii(stderr, name);
+       fprintf(stderr, ")\n");
+
+       abort();
+}
+
 void exceptions_throw_outofmemoryerror(void)
 {
        fprintf(stderr, "java.lang.OutOfMemoryError\n");
index 89638f6eb63e1da7f7fdc150940954f22b9a9427..aba1b46b6910ece97cb2d13d93b2af932e970c79 100644 (file)
        }
 #      define GC_TEST_AND_SET_DEFINED
 #    endif
+/* tbfg */
+#if 0          
 #    ifdef M68K
        /* Contributed by Tony Mantler.  I'm not sure how well it was   */
        /* tested.                                                      */
        }
 #      define GC_TEST_AND_SET_DEFINED
 #    endif
+#endif
 #    if defined(POWERPC)
         inline static int GC_test_and_set(volatile unsigned int *addr) {
           int oldval;
index 0f8fd7917aa345fa83a922934eb1428965ea3e3d..13ad45953135410080684bc0b538cc89d0138839 100644 (file)
@@ -1,6 +1,6 @@
 /* src/mm/nogc.c - allocates memory through malloc (no GC)
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
    J. Wenninger, Institut f. Computersprachen - TU Wien
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Christian Thalinger
-
-   Changes:
-
-   $Id: nogc.c 7516 2007-03-14 12:00:07Z michi $
+   $Id: nogc.c 7596 2007-03-28 21:05:53Z twisti $
 
 */
 
 
 #include "mm/gc-common.h"
 #include "mm/memory.h"
+
 #include "toolbox/logging.h"
+
 #include "vm/builtin.h"
 #include "vm/exceptions.h"
 #include "vm/global.h"
 #include "vm/stringlocal.h"
+
 #include "vmcore/loader.h"
 #include "vmcore/options.h"
 
@@ -73,7 +70,11 @@ void *heap_allocate(u4 size, bool references, methodinfo *finalizer)
        mmapptr = (void *) ((ptrint) mmapptr + size);
 
        if (mmapptr > mmaptop)
+<<<<<<< .working
                vm_abort("heap_allocate: out of memory");
+=======
+               exceptions_throw_outofmemoryerror();
+>>>>>>> .merge-right.r7379
 
        MSET(m, 0, u1, size);
 
@@ -113,7 +114,11 @@ void gc_init(u4 heapmaxsize, u4 heapstartsize)
                                   (off_t) 0);
 
        if (mmapptr == MAP_FAILED)
+<<<<<<< .working
                vm_abort("gc_init: out of memory");
+=======
+               exceptions_throw_outofmemoryerror();
+>>>>>>> .merge-right.r7379
 
        mmapsize = heapmaxsize;
        mmaptop = (void *) ((ptrint) mmapptr + mmapsize);
index f4bd5051bac9751ffcd2c054b7532f45724e8f25..85f09d9be35d4516e50a92bcf7f4bedb83dedc75 100644 (file)
@@ -22,7 +22,7 @@
 ## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 ## 02110-1301, USA.
 ##
-## $Id: Makefile.am 7374 2007-02-19 23:47:58Z twisti $
+## $Id: Makefile.am 7383 2007-02-21 20:26:52Z twisti $
 
 ## Process this file with automake to produce Makefile.in
 
@@ -151,8 +151,6 @@ DO_HEADER_FILES += \
        $(ADDITIONAL_STATIC_CLASSPATH_HEADER_FILES)
 endif
 
-CACAOH = $(top_builddir)/src/cacaoh/cacaoh
-
 if WITH_CLASSPATH_GNU
 CLASSPATH = $(top_builddir)/src/lib/classes/:$(CLASSPATH_CLASSES)
 VM_ZIP = $(top_builddir)/src/lib/vm.zip
index 36434e62682f4242262b3372b6ed2df63acfe445..2ada8720ae8f2fb6ae65b86ecca80defbc06504b 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: jni.c 7526 2007-03-15 09:28:56Z twisti $
+   $Id: jni.c 7550 2007-03-21 13:40:45Z twisti $
 
 */
 
@@ -4301,10 +4301,8 @@ void _Jv_JNI_SetObjectArrayElement(JNIEnv *env, jobjectArray array,
        /* check if the class of value is a subclass of the element class
           of the array */
 
-       if (!builtin_canstore(oa, o)) {
-               exceptions_throw_arraystoreexception();
+       if (!builtin_canstore(oa, o))
                return;
-       }
 
        oa->data[index] = val;
 }
index e277eb572a6c21b43f4270fec8458a173e2a2644..948ad1d5ae874c9266ed285afad3f81bf0f577c5 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: list.c 7246 2007-01-29 18:49:05Z twisti $
+   $Id: list.c 7481 2007-03-08 13:12:21Z twisti $
 
 */
 
@@ -131,7 +131,7 @@ void list_add_last(list *l, void *element)
 }
 
 
-/* list_add_list_unsynced ******************************************************
+/* list_add_last_unsynced ******************************************************
 
    Adds the element as last element but does NO locking!
 
@@ -200,14 +200,36 @@ void list_add_before(list *l, void *element, void *newelement)
 }
 
 
+/* list_remove ***************************************************************
+
+   Removes the element.
+
+*******************************************************************************/
+
 void list_remove(list *l, void *element)
+{
+       LOCK_MONITOR_ENTER(l);
+
+       list_remove_unsynced(l, element);
+
+       LOCK_MONITOR_EXIT(l);
+}
+
+
+/* list_remove_unsynced ********************************************************
+
+   Removes the element but does NO locking!
+
+   ATTENTION: Use this function with care!!!
+
+*******************************************************************************/
+
+void list_remove_unsynced(list *l, void *element)
 {
        listnode *ln;
 
        ln = (listnode *) (((u1 *) element) + l->nodeoffset);
        
-       LOCK_MONITOR_ENTER(l);
-
        if (ln->next)
                ln->next->prev = ln->prev;
        else
@@ -220,8 +242,6 @@ void list_remove(list *l, void *element)
 
        ln->next = NULL;
        ln->prev = NULL;
-
-       LOCK_MONITOR_EXIT(l);
 }
 
  
index 672751cb08afc7d74f642c661d1ec940dc9638a2..9582f7e6eacd48c035747884cd19a4f7024d1590 100644 (file)
@@ -1,6 +1,6 @@
 /* src/toolbox/list.h - synchronized linked list
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
    J. Wenninger, Institut f. Computersprachen - TU Wien
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Reinhard Grafl
-
-   Changes: Christian Thalinger
-
-   $Id: list.h 5894 2006-11-02 12:54:15Z twisti $
+   $Id: list.h 7481 2007-03-08 13:12:21Z twisti $
 
 */
 
@@ -136,6 +130,7 @@ void list_add_last_unsynced(list *l, void *element);
 void list_add_before(list *l, void *element, void *newelement);
 
 void list_remove(list *l, void *element);
+void list_remove_unsynced(list *l, void *element);
  
 void *list_first(list *l);
 void *list_first_unsynced(list *l);
index d53c7e1bd59638b155613f0c87ca6cc8d4e4abef..319aa570312b193814f792e5c99973d19f0c1b0a 100644 (file)
@@ -28,7 +28,7 @@
    calls instead of machine instructions, using the C calling
    convention.
 
-   $Id: builtin.c 7563 2007-03-23 21:33:53Z twisti $
+   $Id: builtin.c 7577 2007-03-25 20:55:06Z twisti $
 
 */
 
@@ -577,7 +577,7 @@ void *builtin_throw_exception(java_objectheader *xptr)
    Checks, if an object can be stored in an array.
 
    Return value: 1 ... possible
-                 0 ... otherwise
+                 0 ... otherwise (throws an ArrayStoreException)
 
 *******************************************************************************/
 
@@ -589,8 +589,9 @@ s4 builtin_canstore(java_objectarray *oa, java_objectheader *o)
        vftbl_t         *valuevftbl;
        s4               base;
        castinfo         classvalues;
+       s4               result;
 
-       if (!o)
+       if (o == NULL)
                return 1;
 
        /* The following is guaranteed (by verifier checks):
@@ -603,10 +604,9 @@ s4 builtin_canstore(java_objectarray *oa, java_objectheader *o)
        desc           = oa->header.objheader.vftbl->arraydesc;
        componentvftbl = desc->componentvftbl;
        valuevftbl     = o->vftbl;
+       valuedesc      = valuevftbl->arraydesc;
 
        if ((desc->dimension - 1) == 0) {
-               s4 res;
-
                /* {oa is a one-dimensional array} */
                /* {oa is an array of references} */
                
@@ -615,28 +615,41 @@ s4 builtin_canstore(java_objectarray *oa, java_objectheader *o)
 
                ASM_GETCLASSVALUES_ATOMIC(componentvftbl, valuevftbl, &classvalues);
 
-               if ((base = classvalues.super_baseval) <= 0)
+               base = classvalues.super_baseval;
+
+               if (base <= 0) {
                        /* an array of interface references */
-                       return (valuevftbl->interfacetablelength > -base &&
-                                       valuevftbl->interfacetable[base] != NULL);
-               
-               res = ((unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
-                          <= (unsigned) classvalues.super_diffval);
 
-               return res;
+                       result = ((valuevftbl->interfacetablelength > -base) &&
+                                       (valuevftbl->interfacetable[base] != NULL));
+               }
+               else {
+                       result = ((unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
+                                  <= (unsigned) classvalues.super_diffval);
+               }
        }
+       else if (valuedesc == NULL) {
+               /* {oa has dimension > 1} */
+               /* {componentvftbl->arraydesc != NULL} */
 
-       /* {oa has dimension > 1} */
-       /* {componentvftbl->arraydesc != NULL} */
-
-       /* check if o is an array */
+               /* check if o is an array */
 
-       if ((valuedesc = valuevftbl->arraydesc) == NULL)
                return 0;
+       }
+       else {
+               /* {o is an array} */
+
+               result = builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
+       }
+
+       /* if not possible, throw an exception */
 
-       /* {o is an array} */
+       if (result == 0)
+               exceptions_throw_arraystoreexception();
+
+       /* return result */
 
-       return builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
+       return result;
 }
 
 
@@ -2546,10 +2559,8 @@ bool builtin_arraycopy(java_arrayheader *src, s4 srcStart,
                        for (i = 0; i < len; i++) {
                                java_objectheader *o = oas->data[srcStart + i];
 
-                               if (!builtin_canstore(oad, o)) {
-                                       exceptions_throw_arraystoreexception();
+                               if (!builtin_canstore(oad, o))
                                        return false;
-                               }
 
                                oad->data[destStart + i] = o;
                        }
@@ -2564,10 +2575,8 @@ bool builtin_arraycopy(java_arrayheader *src, s4 srcStart,
                        for (i = len - 1; i >= 0; i--) {
                                java_objectheader *o = oas->data[srcStart + i];
 
-                               if (!builtin_canstore(oad, o)) {
-                                       exceptions_throw_arraystoreexception();
+                               if (!builtin_canstore(oad, o))
                                        return false;
-                               }
 
                                oad->data[destStart + i] = o;
                        }
index f0ea89d8383656c47014a8efd08a44b52572754d..6754a62beaa76b2034589bb217a5e32f632b066a 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: exceptions.c 7587 2007-03-28 13:29:09Z twisti $
+   $Id: exceptions.c 7596 2007-03-28 21:05:53Z twisti $
 
 */
 
@@ -36,6 +36,8 @@
 
 #include "vm/types.h"
 
+#include "md-abi.h"
+
 #include "mm/memory.h"
 
 #include "native/jni.h"
@@ -59,6 +61,7 @@
 #include "vm/vm.h"
 
 #include "vm/jit/asmpart.h"
+#include "vm/jit/disass.h"
 #include "vm/jit/jit.h"
 #include "vm/jit/methodheader.h"
 #include "vm/jit/stacktrace.h"
@@ -714,6 +717,42 @@ void exceptions_throw_noclassdeffounderror(utf *name)
 }
 
 
+/* exceptions_throw_noclassdeffounderror_wrong_name ****************************
+
+   Generates and throws a java.lang.NoClassDefFoundError with a
+   specific message:
+
+
+
+   IN:
+      name.........name of the class not found as a utf *
+
+*******************************************************************************/
+
+void exceptions_throw_noclassdeffounderror_wrong_name(classinfo *c, utf *name)
+{
+       char *msg;
+       s4    msglen;
+       utf  *u;
+
+       msglen = utf_bytes(c->name) + strlen(" (wrong name: ") +
+               utf_bytes(name) + strlen(")") + strlen("0");
+
+       msg = MNEW(char, msglen);
+
+       utf_copy_classname(msg, c->name);
+       strcat(msg, " (wrong name: ");
+       utf_cat_classname(msg, name);
+       strcat(msg, ")");
+
+       u = utf_new_char(msg);
+
+       MFREE(msg, char, msglen);
+
+       exceptions_throw_noclassdeffounderror(u);
+}
+
+
 /* classnotfoundexception_to_noclassdeffounderror ******************************
 
    Check the *exceptionptr for a ClassNotFoundException. If it is one,
@@ -1530,6 +1569,43 @@ void exceptions_clear_exception(void)
 }
 
 
+/* exceptions_fillinstacktrace *************************************************
+
+   Calls the fillInStackTrace-method of the currently thrown
+   exception.
+
+*******************************************************************************/
+
+java_objectheader *exceptions_fillinstacktrace(void)
+{
+       java_objectheader *e;
+       methodinfo        *m;
+
+       /* get exception */
+
+       e = *exceptionptr;
+       assert(e);
+
+       /* clear exception */
+
+       *exceptionptr = NULL;
+
+       /* resolve methodinfo pointer from exception object */
+
+       m = class_resolvemethod(e->vftbl->class,
+                                                       utf_fillInStackTrace,
+                                                       utf_void__java_lang_Throwable);
+
+       /* call function */
+
+       (void) vm_call_method(m, e);
+
+       /* return exception object */
+
+       return e;
+}
+
+
 /* exceptions_get_and_clear_exception ******************************************
 
    Gets the exception pointer of the current thread and clears it.
@@ -1560,6 +1636,80 @@ java_objectheader *exceptions_get_and_clear_exception(void)
 }
 
 
+/* exceptions_new_hardware_exception *******************************************
+
+   Creates the correct exception for a hardware-exception thrown and
+   caught by a signal handler.
+
+*******************************************************************************/
+
+java_objectheader *exceptions_new_hardware_exception(u1 *pv, u1 *sp, u1 *ra, u1 *xpc, s4 type, ptrint val)
+{
+       stackframeinfo     sfi;
+       java_objectheader *e;
+       java_objectheader *o;
+       s4                 index;
+
+       /* create stackframeinfo */
+
+       stacktrace_create_extern_stackframeinfo(&sfi, pv, sp, ra, xpc);
+
+       switch (type) {
+       case EXCEPTION_HARDWARE_NULLPOINTER:
+               e = exceptions_new_nullpointerexception();
+               break;
+
+       case EXCEPTION_HARDWARE_ARITHMETIC:
+               e = exceptions_new_arithmeticexception();
+               break;
+
+       case EXCEPTION_HARDWARE_ARRAYINDEXOUTOFBOUNDS:
+               index = (s4) val;
+               e = exceptions_new_arrayindexoutofboundsexception(index);
+               break;
+
+       case EXCEPTION_HARDWARE_CLASSCAST:
+               o = (java_objectheader *) val;
+               e = exceptions_new_classcastexception(o);
+               break;
+
+       case EXCEPTION_HARDWARE_EXCEPTION:
+               e = exceptions_fillinstacktrace();
+               break;
+
+       default:
+               /* let's try to get a backtrace */
+
+               codegen_get_pv_from_pc(xpc);
+
+               /* if that does not work, print more debug info */
+
+               log_println("exceptions_new_hardware_exception: unknown exception type %d", type);
+
+#if SIZEOF_VOID_P == 8
+               log_println("PC=0x%016lx", xpc);
+#else
+               log_println("PC=0x%08x", xpc);
+#endif
+
+#if defined(ENABLE_DISASSEMBLER)
+               log_println("machine instruction at PC:");
+               disassinstr(xpc);
+#endif
+
+               vm_abort("Exiting...");
+       }
+
+       /* remove stackframeinfo */
+
+       stacktrace_remove_stackframeinfo(&sfi);
+
+       /* return the exception object */
+
+       return e;
+}
+
+
 /* exceptions_handle_exception *************************************************
 
    Try to find an exception handler for the given exception and return it.
index 557a339899707181c3e8432c16ed78d9b290d780..1c48b98e15c7ad2f802c07f7870f95b6a6929c13 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: exceptions.h 7587 2007-03-28 13:29:09Z twisti $
+   $Id: exceptions.h 7596 2007-03-28 21:05:53Z twisti $
 
 */
 
 
 /* hardware-exception defines **************************************************
 
-   These defines define the load-offset which indicates the given
-   exception.
+   These defines define an internal number for the various hardware
+   exceptions.
 
-   ATTENTION: These offsets need NOT to be aligned to 4 or 8-byte
-   boundaries, since normal loads could have such offsets with a base
-   of NULL which should result in a NullPointerException.
+   ATTENTION: These values are also used as load-displacements on some
+   architectures. Thus, these values must NOT be aligned to 4 or
+   8-byte boundaries, since normal loads could have such offsets with
+   a base of NULL which should result in a NullPointerException.
 
 *******************************************************************************/
 
-#define EXCEPTION_LOAD_DISP_NULLPOINTER              0
-#define EXCEPTION_LOAD_DISP_ARITHMETIC               1
-#define EXCEPTION_LOAD_DISP_ARRAYINDEXOUTOFBOUNDS    2
-#define EXCEPTION_LOAD_DISP_CLASSCAST                3
+#define EXCEPTION_HARDWARE_NULLPOINTER              0
+#define EXCEPTION_HARDWARE_ARITHMETIC               1
+#define EXCEPTION_HARDWARE_ARRAYINDEXOUTOFBOUNDS    2
+#define EXCEPTION_HARDWARE_CLASSCAST                3
 
-#define EXCEPTION_LOAD_DISP_PATCHER                  5
+#define EXCEPTION_HARDWARE_EXCEPTION                5
+
+#define EXCEPTION_HARDWARE_PATCHER                  6
+
+
+/* exception pointer **********************************************************/
+
+#if defined(ENABLE_THREADS)
+#define exceptionptr    &(THREADOBJECT->_exceptionptr)
+#else
+#define exceptionptr    &_no_threads_exceptionptr
+#endif
+
+#if !defined(ENABLE_THREADS)
+extern java_objectheader *_no_threads_exceptionptr;
+#endif
 
 
 /* function prototypes ********************************************************/
@@ -84,6 +100,7 @@ void exceptions_throw_classcircularityerror(classinfo *c);
 void exceptions_throw_classformaterror(classinfo *c, const char *message, ...);
 void exceptions_throw_classnotfoundexception(utf *name);
 void exceptions_throw_noclassdeffounderror(utf *name);
+void exceptions_throw_noclassdeffounderror_wrong_name(classinfo *c, utf *name);
 void exceptions_throw_linkageerror(const char *message, classinfo *c);
 void exceptions_throw_nosuchfielderror(classinfo *c, utf *name);
 void exceptions_throw_nosuchmethoderror(classinfo *c, utf *name, utf *desc);
@@ -119,6 +136,8 @@ java_objectheader *exceptions_new_nullpointerexception(void);
 void exceptions_throw_nullpointerexception(void);
 void exceptions_throw_stringindexoutofboundsexception(void);
 
+java_objectheader *exceptions_fillinstacktrace(void);
+
 void classnotfoundexception_to_noclassdeffounderror(void);
 
 java_objectheader *exceptions_get_exception(void);
@@ -126,6 +145,8 @@ void               exceptions_set_exception(java_objectheader *o);
 void               exceptions_clear_exception(void);
 java_objectheader *exceptions_get_and_clear_exception(void);
 
+java_objectheader *exceptions_new_hardware_exception(u1 *pv, u1 *sp, u1 *ra, u1 *xpc, s4 type, ptrint val);
+
 void exceptions_print_exception(java_objectheader *xptr);
 void exceptions_print_current_exception(void);
 void exceptions_print_stacktrace(void);
index 8d80e7b60c09f3c42e6a63fb1155e8ca6f1bdd92..a8f51b9f0d857e47e4424d95230b2565732d51bd 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: abi.h 7329 2007-02-11 21:24:14Z twisti $
+   $Id: abi.h 7456 2007-03-05 16:13:11Z tbfg $
 
 */
 
@@ -36,6 +36,7 @@
 #include "vm/jit/abi-asm.h"
 #include "vm/jit/jit.h"
 
+#include "arch.h"
 
 /* ABI externs ****************************************************************/
 
@@ -43,6 +44,10 @@ extern s4 nregdescint[];
 extern char *regs[];
 extern s4 nregdescfloat[];
 
+#if defined(HAS_ADDRESS_REGISTER_FILE)
+extern s4 nregdescadr[];
+#endif
+
 extern const char *abi_registers_integer_name[];
 extern const s4    abi_registers_integer_argument[];
 extern const s4    abi_registers_integer_saved[];
index 757a3a7a80819e65f0c041570095f6928e76f80c..76845fc4f625c95ccb23e6c39a5089c1a70bbfa0 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: arch.h 7241 2007-01-27 15:52:01Z twisti $
+   $Id: arch.h 7479 2007-03-08 09:46:27Z twisti $
 
 */
 
 #endif
 
 
+/* branches *******************************************************************/
+
+#define SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER       0
+#define SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER     1
+#define SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS    0
+
+
 /* exceptions *****************************************************************/
 
 #define SUPPORT_HARDWARE_DIVIDE_BY_ZERO  0
index 63ca7efe59aaaa92b295459e080d2fc09d872551..3f673279e0555b124f65f13e4f1de69e7c0da0e7 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: asmpart.S 7253 2007-01-29 21:37:00Z twisti $
+   $Id: asmpart.S 7454 2007-03-05 15:40:48Z tbfg $
 
 */
 
@@ -50,6 +50,7 @@
        .globl asm_vm_call_method_float
        .globl asm_vm_call_method_double
        .globl asm_vm_call_method_exception_handler
+       .globl asm_vm_call_method_end
 
        .globl asm_call_jit_compiler
 
@@ -199,6 +200,7 @@ asm_vm_call_method_exception_handler:
        ldq     ra,0*8(sp)                /* restore return address               */
        ldq     s6,3*8(sp)
        lda     sp,5*8(sp)                /* free stack space                     */
+asm_vm_call_method_end:                                        
        jmp     zero,(ra)
 
        .end    asm_vm_call_method
index 24df4ef4a38f894c6ab65af9eeba979e3e61fc6a..2823d213413c22405469e55798a436f592c03712 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: codegen.c 7251 2007-01-29 20:24:53Z twisti $
+   $Id: codegen.c 7566 2007-03-23 23:51:10Z twisti $
 
 */
 
 #include "vmcore/options.h"
 
 
-/* codegen *********************************************************************
+/* codegen_emit ****************************************************************
 
    Generates machine code.
 
 *******************************************************************************/
 
-bool codegen(jitdata *jd)
+bool codegen_emit(jitdata *jd)
 {
        methodinfo         *m;
        codeinfo           *code;
@@ -280,8 +280,8 @@ bool codegen(jitdata *jd)
                        M_ALD(REG_A0, REG_PV, disp);
                }
                else {
-                       M_BEQZ(REG_A0, 0);
-                       codegen_add_nullpointerexception_ref(cd);
+                       M_BNEZ(REG_A0, 1);
+                       M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_NULLPOINTER);
                }
 
                M_AST(REG_A0, REG_SP, s1 * 8);
@@ -716,14 +716,13 @@ bool codegen(jitdata *jd)
                case ICMD_IDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
                case ICMD_IREM:       /* ..., val1, val2  ==> ..., val1 % val2        */
 
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+                       s1 = emit_load_s1(jd, iptr, REG_A0);
+                       s2 = emit_load_s2(jd, iptr, REG_A1);
                        d = codegen_reg_of_dst(jd, iptr, REG_RESULT);
-                       M_BEQZ(s2, 0);
-                       codegen_add_arithmeticexception_ref(cd);
+                       emit_arithmetic_check(cd, iptr, s2);
 
-                       M_MOV(s1, REG_A0);
-                       M_MOV(s2, REG_A1);
+                       M_INTMOVE(s1, REG_A0);
+                       M_INTMOVE(s2, REG_A1);
                        bte = iptr->sx.s23.s3.bte;
                        disp = dseg_add_functionptr(cd, bte->fp);
                        M_ALD(REG_PV, REG_PV, disp);
@@ -738,16 +737,14 @@ bool codegen(jitdata *jd)
                case ICMD_LDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
                case ICMD_LREM:       /* ..., val1, val2  ==> ..., val1 % val2        */
 
-                       bte = iptr->sx.s23.s3.bte;
-
                        s1 = emit_load_s1(jd, iptr, REG_A0);
                        s2 = emit_load_s2(jd, iptr, REG_A1);
                        d = codegen_reg_of_dst(jd, iptr, REG_RESULT);
-                       M_BEQZ(s2, 0);
-                       codegen_add_arithmeticexception_ref(cd);
+                       emit_arithmetic_check(cd, iptr, s2);
 
                        M_INTMOVE(s1, REG_A0);
                        M_INTMOVE(s2, REG_A1);
+                       bte = iptr->sx.s23.s3.bte;
                        disp = dseg_add_functionptr(cd, bte->fp);
                        M_ALD(REG_PV, REG_PV, disp);
                        M_JSR(REG_RA, REG_PV);
@@ -1431,7 +1428,7 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                       emit_nullpointer_check(cd, iptr, s1);
+                       /* implicit null-pointer check */
                        M_ILD(d, s1, OFFSET(java_arrayheader, size));
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1441,7 +1438,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        if (has_ext_instr_set) {
                                M_LADD(s2, s1, REG_ITMP1);
                                M_BLDU(d, REG_ITMP1, OFFSET (java_bytearray, data[0]));
@@ -1462,7 +1460,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        if (has_ext_instr_set) {
                                M_LADD(s2, s1, REG_ITMP1);
                                M_LADD(s2, REG_ITMP1, REG_ITMP1);
@@ -1483,7 +1482,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        if (has_ext_instr_set) {
                                M_LADD(s2, s1, REG_ITMP1);
                                M_LADD(s2, REG_ITMP1, REG_ITMP1);
@@ -1505,7 +1505,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_S4ADDQ(s2, s1, REG_ITMP1);
                        M_ILD(d, REG_ITMP1, OFFSET(java_intarray, data[0]));
                        emit_store_dst(jd, iptr, d);
@@ -1516,7 +1517,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_S8ADDQ(s2, s1, REG_ITMP1);
                        M_LLD(d, REG_ITMP1, OFFSET(java_longarray, data[0]));
                        emit_store_dst(jd, iptr, d);
@@ -1527,7 +1529,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_S4ADDQ(s2, s1, REG_ITMP1);
                        M_FLD(d, REG_ITMP1, OFFSET(java_floatarray, data[0]));
                        emit_store_dst(jd, iptr, d);
@@ -1538,7 +1541,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_S8ADDQ(s2, s1, REG_ITMP1);
                        M_DLD(d, REG_ITMP1, OFFSET(java_doublearray, data[0]));
                        emit_store_dst(jd, iptr, d);
@@ -1549,7 +1553,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_SAADDQ(s2, s1, REG_ITMP1);
                        M_ALD(d, REG_ITMP1, OFFSET(java_objectarray, data[0]));
                        emit_store_dst(jd, iptr, d);
@@ -1560,7 +1565,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
                        if (has_ext_instr_set) {
                                M_LADD(s2, s1, REG_ITMP1);
@@ -1581,7 +1587,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
                        if (has_ext_instr_set) {
                                M_LADD(s2, s1, REG_ITMP1);
@@ -1604,7 +1611,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
                        if (has_ext_instr_set) {
                                M_LADD(s2, s1, REG_ITMP1);
@@ -1627,7 +1635,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
                        M_S4ADDQ(s2, s1, REG_ITMP1);
                        M_IST(s3, REG_ITMP1, OFFSET(java_intarray, data[0]));
@@ -1637,7 +1646,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
                        M_S8ADDQ(s2, s1, REG_ITMP1);
                        M_LST(s3, REG_ITMP1, OFFSET(java_longarray, data[0]));
@@ -1647,7 +1657,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_FTMP3);
                        M_S4ADDQ(s2, s1, REG_ITMP1);
                        M_FST(s3, REG_ITMP1, OFFSET(java_floatarray, data[0]));
@@ -1657,7 +1668,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_FTMP3);
                        M_S8ADDQ(s2, s1, REG_ITMP1);
                        M_DST(s3, REG_ITMP1, OFFSET(java_doublearray, data[0]));
@@ -1667,7 +1679,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_A0);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_A1);
 
                        M_INTMOVE(s1, REG_A0);
@@ -1678,9 +1691,7 @@ bool codegen(jitdata *jd)
                        M_JSR(REG_RA, REG_PV);
                        disp = (s4) (cd->mcodeptr - cd->mcodebase);
                        M_LDA(REG_PV, REG_RA, -disp);
-
-                       M_BEQZ(REG_RESULT, 0);
-                       codegen_add_arraystoreexception_ref(cd);
+                       emit_exception_check(cd, iptr);
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
@@ -1694,7 +1705,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        if (has_ext_instr_set) {
                                M_LADD(s2, s1, REG_ITMP1);
                                M_BST(REG_ZERO, REG_ITMP1, OFFSET(java_bytearray, data[0]));
@@ -1714,7 +1726,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        if (has_ext_instr_set) {
                                M_LADD(s2, s1, REG_ITMP1);
                                M_LADD(s2, REG_ITMP1, REG_ITMP1);
@@ -1736,7 +1749,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        if (has_ext_instr_set) {
                                M_LADD(s2, s1, REG_ITMP1);
                                M_LADD(s2, REG_ITMP1, REG_ITMP1);
@@ -1758,7 +1772,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_S4ADDQ(s2, s1, REG_ITMP1);
                        M_IST(REG_ZERO, REG_ITMP1, OFFSET(java_intarray, data[0]));
                        break;
@@ -1767,7 +1782,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_S8ADDQ(s2, s1, REG_ITMP1);
                        M_LST(REG_ZERO, REG_ITMP1, OFFSET(java_longarray, data[0]));
                        break;
@@ -1776,7 +1792,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_SAADDQ(s2, s1, REG_ITMP1);
                        M_AST(REG_ZERO, REG_ITMP1, OFFSET(java_objectarray, data[0]));
                        break;
@@ -1916,7 +1933,6 @@ bool codegen(jitdata *jd)
                case ICMD_GETFIELD:   /* ...  ==> ..., value                          */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       emit_nullpointer_check(cd, iptr, s1);
 
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
                                uf        = iptr->sx.s23.s3.uf;
@@ -1931,6 +1947,7 @@ bool codegen(jitdata *jd)
                                disp      = fi->offset;
                        }
 
+                       /* implicit null-pointer check */
                        switch (fieldtype) {
                        case TYPE_INT:
                                d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
@@ -1959,7 +1976,6 @@ bool codegen(jitdata *jd)
                case ICMD_PUTFIELD:   /* ..., objectref, value  ==> ...               */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       emit_nullpointer_check(cd, iptr, s1);
 
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
                                uf        = iptr->sx.s23.s3.uf;
@@ -1981,6 +1997,7 @@ bool codegen(jitdata *jd)
                        if (INSTRUCTION_IS_UNRESOLVED(iptr))
                                codegen_add_patch_ref(cd, PATCHER_get_putfield, uf, 0);
 
+                       /* implicit null-pointer check */
                        switch (fieldtype) {
                        case TYPE_INT:
                                M_IST(s2, s1, disp);
@@ -2005,7 +2022,6 @@ bool codegen(jitdata *jd)
                                          /* following NOP)                           */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       emit_nullpointer_check(cd, iptr, s1);
 
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
                                uf        = iptr->sx.s23.s3.uf;
@@ -2020,6 +2036,7 @@ bool codegen(jitdata *jd)
                                disp      = fi->offset;
                        }
 
+                       /* implicit null-pointer check */
                        switch (fieldtype) {
                        case TYPE_INT:
                                M_IST(REG_ZERO, s1, disp);
@@ -2066,258 +2083,213 @@ bool codegen(jitdata *jd)
                case ICMD_GOTO:         /* ... ==> ...                                */
                case ICMD_RET:          /* ... ==> ...                                */
 
-                       M_BR(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                       emit_br(cd, iptr->dst.block);
                        ALIGNCODENOP;
                        break;
 
                case ICMD_JSR:          /* ... ==> ...                                */
 
-                       M_BR(0);
-                       codegen_add_branch_ref(cd, iptr->sx.s23.s3.jsrtarget.block);
+                       emit_br(cd, iptr->sx.s23.s3.jsrtarget.block);
                        ALIGNCODENOP;
                        break;
                        
                case ICMD_IFNULL:       /* ..., value ==> ...                         */
+               case ICMD_IFNONNULL:
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       M_BEQZ(s1, 0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IFNONNULL:    /* ..., value ==> ...                         */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       M_BNEZ(s1, 0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                       emit_bccz(cd, iptr->dst.block, iptr->opc - ICMD_IFNULL, s1, BRANCH_OPT_NONE);
                        break;
 
                case ICMD_IFEQ:         /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.i == 0) {
-                               M_BEQZ(s1, 0);
-                               }
+                       if (iptr->sx.val.i == 0)
+                               emit_beqz(cd, iptr->dst.block, s1);
                        else {
-                               if ((iptr->sx.val.i > 0) && (iptr->sx.val.i <= 255)) {
+                               if ((iptr->sx.val.i > 0) && (iptr->sx.val.i <= 255))
                                        M_CMPEQ_IMM(s1, iptr->sx.val.i, REG_ITMP1);
-                                       }
                                else {
                                        ICONST(REG_ITMP2, iptr->sx.val.i);
                                        M_CMPEQ(s1, REG_ITMP2, REG_ITMP1);
-                                       }
-                               M_BNEZ(REG_ITMP1, 0);
                                }
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                               emit_bnez(cd, iptr->dst.block, REG_ITMP1);
+                       }
                        break;
 
                case ICMD_IFLT:         /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.i == 0) {
-                               M_BLTZ(s1, 0);
-                               }
+                       if (iptr->sx.val.i == 0)
+                               emit_bltz(cd, iptr->dst.block, s1);
                        else {
-                               if ((iptr->sx.val.i > 0) && (iptr->sx.val.i <= 255)) {
+                               if ((iptr->sx.val.i > 0) && (iptr->sx.val.i <= 255))
                                        M_CMPLT_IMM(s1, iptr->sx.val.i, REG_ITMP1);
-                                       }
                                else {
                                        ICONST(REG_ITMP2, iptr->sx.val.i);
                                        M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
-                                       }
-                               M_BNEZ(REG_ITMP1, 0);
                                }
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                               emit_bnez(cd, iptr->dst.block, REG_ITMP1);
+                       }
                        break;
 
                case ICMD_IFLE:         /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.i == 0) {
-                               M_BLEZ(s1, 0);
-                               }
+                       if (iptr->sx.val.i == 0)
+                               emit_blez(cd, iptr->dst.block, s1);
                        else {
-                               if ((iptr->sx.val.i > 0) && (iptr->sx.val.i <= 255)) {
+                               if ((iptr->sx.val.i > 0) && (iptr->sx.val.i <= 255))
                                        M_CMPLE_IMM(s1, iptr->sx.val.i, REG_ITMP1);
-                                       }
                                else {
                                        ICONST(REG_ITMP2, iptr->sx.val.i);
                                        M_CMPLE(s1, REG_ITMP2, REG_ITMP1);
-                                       }
-                               M_BNEZ(REG_ITMP1, 0);
                                }
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                               emit_bnez(cd, iptr->dst.block, REG_ITMP1);
+                       }
                        break;
 
                case ICMD_IFNE:         /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.i == 0) {
-                               M_BNEZ(s1, 0);
-                               }
+                       if (iptr->sx.val.i == 0)
+                               emit_bnez(cd, iptr->dst.block, s1);
                        else {
-                               if ((iptr->sx.val.i > 0) && (iptr->sx.val.i <= 255)) {
+                               if ((iptr->sx.val.i > 0) && (iptr->sx.val.i <= 255))
                                        M_CMPEQ_IMM(s1, iptr->sx.val.i, REG_ITMP1);
-                                       }
                                else {
                                        ICONST(REG_ITMP2, iptr->sx.val.i);
                                        M_CMPEQ(s1, REG_ITMP2, REG_ITMP1);
-                                       }
-                               M_BEQZ(REG_ITMP1, 0);
                                }
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                               emit_beqz(cd, iptr->dst.block, REG_ITMP1);
+                       }
                        break;
 
                case ICMD_IFGT:         /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.i == 0) {
-                               M_BGTZ(s1, 0);
-                               }
+                       if (iptr->sx.val.i == 0)
+                               emit_bgtz(cd, iptr->dst.block, s1);
                        else {
-                               if ((iptr->sx.val.i > 0) && (iptr->sx.val.i <= 255)) {
+                               if ((iptr->sx.val.i > 0) && (iptr->sx.val.i <= 255))
                                        M_CMPLE_IMM(s1, iptr->sx.val.i, REG_ITMP1);
-                                       }
                                else {
                                        ICONST(REG_ITMP2, iptr->sx.val.i);
                                        M_CMPLE(s1, REG_ITMP2, REG_ITMP1);
-                                       }
-                               M_BEQZ(REG_ITMP1, 0);
                                }
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                               emit_beqz(cd, iptr->dst.block, REG_ITMP1);
+                       }
                        break;
 
                case ICMD_IFGE:         /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.i == 0) {
-                               M_BGEZ(s1, 0);
-                               }
+                       if (iptr->sx.val.i == 0)
+                               emit_bgez(cd, iptr->dst.block, s1);
                        else {
-                               if ((iptr->sx.val.i > 0) && (iptr->sx.val.i <= 255)) {
+                               if ((iptr->sx.val.i > 0) && (iptr->sx.val.i <= 255))
                                        M_CMPLT_IMM(s1, iptr->sx.val.i, REG_ITMP1);
-                                       }
                                else {
                                        ICONST(REG_ITMP2, iptr->sx.val.i);
                                        M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
-                                       }
-                               M_BEQZ(REG_ITMP1, 0);
                                }
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                               emit_beqz(cd, iptr->dst.block, REG_ITMP1);
+                       }
                        break;
 
                case ICMD_IF_LEQ:       /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.l == 0) {
-                               M_BEQZ(s1, 0);
-                               }
+                       if (iptr->sx.val.l == 0)
+                               emit_beqz(cd, iptr->dst.block, s1);
                        else {
-                               if ((iptr->sx.val.l > 0) && (iptr->sx.val.l <= 255)) {
+                               if ((iptr->sx.val.l > 0) && (iptr->sx.val.l <= 255))
                                        M_CMPEQ_IMM(s1, iptr->sx.val.l, REG_ITMP1);
-                                       }
                                else {
                                        LCONST(REG_ITMP2, iptr->sx.val.l);
                                        M_CMPEQ(s1, REG_ITMP2, REG_ITMP1);
-                                       }
-                               M_BNEZ(REG_ITMP1, 0);
                                }
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                               emit_bnez(cd, iptr->dst.block, REG_ITMP1);
+                       }
                        break;
 
                case ICMD_IF_LLT:       /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.l == 0) {
-                               M_BLTZ(s1, 0);
-                               }
+                       if (iptr->sx.val.l == 0)
+                               emit_bltz(cd, iptr->dst.block, s1);
                        else {
-                               if ((iptr->sx.val.l > 0) && (iptr->sx.val.l <= 255)) {
+                               if ((iptr->sx.val.l > 0) && (iptr->sx.val.l <= 255))
                                        M_CMPLT_IMM(s1, iptr->sx.val.l, REG_ITMP1);
-                                       }
                                else {
                                        LCONST(REG_ITMP2, iptr->sx.val.l);
                                        M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
-                                       }
-                               M_BNEZ(REG_ITMP1, 0);
                                }
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                               emit_bnez(cd, iptr->dst.block, REG_ITMP1);
+                       }
                        break;
 
                case ICMD_IF_LLE:       /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.l == 0) {
-                               M_BLEZ(s1, 0);
-                               }
+                       if (iptr->sx.val.l == 0)
+                               emit_blez(cd, iptr->dst.block, s1);
                        else {
-                               if ((iptr->sx.val.l > 0) && (iptr->sx.val.l <= 255)) {
+                               if ((iptr->sx.val.l > 0) && (iptr->sx.val.l <= 255))
                                        M_CMPLE_IMM(s1, iptr->sx.val.l, REG_ITMP1);
-                                       }
                                else {
                                        LCONST(REG_ITMP2, iptr->sx.val.l);
                                        M_CMPLE(s1, REG_ITMP2, REG_ITMP1);
-                                       }
-                               M_BNEZ(REG_ITMP1, 0);
                                }
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                               emit_bnez(cd, iptr->dst.block, REG_ITMP1);
+                       }
                        break;
 
                case ICMD_IF_LNE:       /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.l == 0) {
-                               M_BNEZ(s1, 0);
-                               }
+                       if (iptr->sx.val.l == 0)
+                               emit_bnez(cd, iptr->dst.block, s1);
                        else {
-                               if ((iptr->sx.val.l > 0) && (iptr->sx.val.l <= 255)) {
+                               if ((iptr->sx.val.l > 0) && (iptr->sx.val.l <= 255))
                                        M_CMPEQ_IMM(s1, iptr->sx.val.l, REG_ITMP1);
-                                       }
                                else {
                                        LCONST(REG_ITMP2, iptr->sx.val.l);
                                        M_CMPEQ(s1, REG_ITMP2, REG_ITMP1);
-                                       }
-                               M_BEQZ(REG_ITMP1, 0);
                                }
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                               emit_beqz(cd, iptr->dst.block, REG_ITMP1);
+                       }
                        break;
 
                case ICMD_IF_LGT:       /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.l == 0) {
-                               M_BGTZ(s1, 0);
-                               }
+                       if (iptr->sx.val.l == 0)
+                               emit_bgtz(cd, iptr->dst.block, s1);
                        else {
-                               if ((iptr->sx.val.l > 0) && (iptr->sx.val.l <= 255)) {
+                               if ((iptr->sx.val.l > 0) && (iptr->sx.val.l <= 255))
                                        M_CMPLE_IMM(s1, iptr->sx.val.l, REG_ITMP1);
-                                       }
                                else {
                                        LCONST(REG_ITMP2, iptr->sx.val.l);
                                        M_CMPLE(s1, REG_ITMP2, REG_ITMP1);
-                                       }
-                               M_BEQZ(REG_ITMP1, 0);
                                }
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                               emit_beqz(cd, iptr->dst.block, REG_ITMP1);
+                       }
                        break;
 
                case ICMD_IF_LGE:       /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.l == 0) {
-                               M_BGEZ(s1, 0);
-                               }
+                       if (iptr->sx.val.l == 0)
+                               emit_bgez(cd, iptr->dst.block, s1);
                        else {
-                               if ((iptr->sx.val.l > 0) && (iptr->sx.val.l <= 255)) {
+                               if ((iptr->sx.val.l > 0) && (iptr->sx.val.l <= 255))
                                        M_CMPLT_IMM(s1, iptr->sx.val.l, REG_ITMP1);
-                                       }
                                else {
                                        LCONST(REG_ITMP2, iptr->sx.val.l);
                                        M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
-                                       }
-                               M_BEQZ(REG_ITMP1, 0);
                                }
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                               emit_beqz(cd, iptr->dst.block, REG_ITMP1);
+                       }
                        break;
 
                case ICMD_IF_ICMPEQ:    /* ..., value, value ==> ...                  */
@@ -2327,8 +2299,7 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_CMPEQ(s1, s2, REG_ITMP1);
-                       M_BNEZ(REG_ITMP1, 0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                       emit_bnez(cd, iptr->dst.block, REG_ITMP1);
                        break;
 
                case ICMD_IF_ICMPNE:    /* ..., value, value ==> ...                  */
@@ -2338,8 +2309,7 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_CMPEQ(s1, s2, REG_ITMP1);
-                       M_BEQZ(REG_ITMP1, 0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                       emit_beqz(cd, iptr->dst.block, REG_ITMP1);
                        break;
 
                case ICMD_IF_ICMPLT:    /* ..., value, value ==> ...                  */
@@ -2348,8 +2318,7 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_CMPLT(s1, s2, REG_ITMP1);
-                       M_BNEZ(REG_ITMP1, 0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                       emit_bnez(cd, iptr->dst.block, REG_ITMP1);
                        break;
 
                case ICMD_IF_ICMPGT:    /* ..., value, value ==> ...                  */
@@ -2358,8 +2327,7 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_CMPLE(s1, s2, REG_ITMP1);
-                       M_BEQZ(REG_ITMP1, 0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                       emit_beqz(cd, iptr->dst.block, REG_ITMP1);
                        break;
 
                case ICMD_IF_ICMPLE:    /* ..., value, value ==> ...                  */
@@ -2368,8 +2336,7 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_CMPLE(s1, s2, REG_ITMP1);
-                       M_BNEZ(REG_ITMP1, 0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                       emit_bnez(cd, iptr->dst.block, REG_ITMP1);
                        break;
 
                case ICMD_IF_ICMPGE:    /* ..., value, value ==> ...                  */
@@ -2378,8 +2345,7 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_CMPLT(s1, s2, REG_ITMP1);
-                       M_BEQZ(REG_ITMP1, 0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                       emit_beqz(cd, iptr->dst.block, REG_ITMP1);
                        break;
 
 
@@ -2524,8 +2490,7 @@ nowperformreturn:
                                M_LDA(REG_ITMP2, REG_ZERO, i - 1);
                                M_CMPULE(REG_ITMP1, REG_ITMP2, REG_ITMP2);
                        }
-                       M_BEQZ(REG_ITMP2, 0);
-                       codegen_add_branch_ref(cd, table[0].block);
+                       emit_beqz(cd, table[0].block, REG_ITMP2);
 
                        /* build jump table top down and use address of lowest entry */
 
@@ -2571,15 +2536,11 @@ nowperformreturn:
                                        }
                                        M_CMPEQ(s1, REG_ITMP2, REG_ITMP2);
                                }
-                               M_BNEZ(REG_ITMP2, 0);
-                               codegen_add_branch_ref(cd, lookup->target.block);
+                               emit_bnez(cd, lookup->target.block, REG_ITMP2);
                                lookup++;
                        }
 
-                       M_BR(0);
-                       
-                       codegen_add_branch_ref(cd, iptr->sx.s23.s3.lookupdefault.block);
-
+                       emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
                        ALIGNCODENOP;
                        break;
                        }
@@ -2653,12 +2614,20 @@ gen_method:
                                disp = dseg_add_functionptr(cd, bte->fp);
 
                                M_ALD(REG_PV, REG_PV, disp);  /* Pointer to built-in-function */
+
+                               /* generate the actual call */
+
+                               M_JSR(REG_RA, REG_PV);
+                               REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
+                               disp = (s4) (cd->mcodeptr - cd->mcodebase);
+                               M_LDA(REG_PV, REG_RA, -disp);
+
+                               emit_exception_check(cd, iptr);
                                break;
 
                        case ICMD_INVOKESPECIAL:
-                               M_BEQZ(REG_A0, 0);
-                               codegen_add_nullpointerexception_ref(cd);
-                               /* fall through */
+                               emit_nullpointer_check(cd, iptr, REG_A0);
+                               /* fall-through */
 
                        case ICMD_INVOKESTATIC:
                                if (lm == NULL) {
@@ -2671,11 +2640,16 @@ gen_method:
                                        disp = dseg_add_address(cd, lm->stubroutine);
 
                                M_ALD(REG_PV, REG_PV, disp);         /* method pointer in r27 */
+
+                               /* generate the actual call */
+
+                               M_JSR(REG_RA, REG_PV);
+                               REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
+                               disp = (s4) (cd->mcodeptr - cd->mcodebase);
+                               M_LDA(REG_PV, REG_RA, -disp);
                                break;
 
                        case ICMD_INVOKEVIRTUAL:
-                               emit_nullpointer_check(cd, iptr, REG_A0);
-
                                if (lm == NULL) {
                                        codegen_add_patch_ref(cd, PATCHER_invokevirtual, um, 0);
 
@@ -2685,14 +2659,19 @@ gen_method:
                                        s1 = OFFSET(vftbl_t, table[0]) +
                                                sizeof(methodptr) * lm->vftblindex;
 
-                               M_ALD(REG_METHODPTR, REG_A0,
-                                         OFFSET(java_objectheader, vftbl));
+                               /* implicit null-pointer check */
+                               M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_objectheader, vftbl));
                                M_ALD(REG_PV, REG_METHODPTR, s1);
+
+                               /* generate the actual call */
+
+                               M_JSR(REG_RA, REG_PV);
+                               REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
+                               disp = (s4) (cd->mcodeptr - cd->mcodebase);
+                               M_LDA(REG_PV, REG_RA, -disp);
                                break;
 
                        case ICMD_INVOKEINTERFACE:
-                               emit_nullpointer_check(cd, iptr, REG_A0);
-
                                if (lm == NULL) {
                                        codegen_add_patch_ref(cd, PATCHER_invokeinterface, um, 0);
 
@@ -2706,25 +2685,18 @@ gen_method:
                                        s2 = sizeof(methodptr) * (lm - lm->class->methods);
                                }
                                        
-                               M_ALD(REG_METHODPTR, REG_A0,
-                                         OFFSET(java_objectheader, vftbl));    
+                               /* implicit null-pointer check */
+                               M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_objectheader, vftbl));
                                M_ALD(REG_METHODPTR, REG_METHODPTR, s1);
                                M_ALD(REG_PV, REG_METHODPTR, s2);
-                               break;
-                       }
-
-                       /* generate the actual call */
-
-                       M_JSR(REG_RA, REG_PV);
-                       REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
-                       disp = (s4) (cd->mcodeptr - cd->mcodebase);
-                       M_LDA(REG_PV, REG_RA, -disp);
 
-                       /* actually only used for ICMD_BUILTIN */
+                               /* generate the actual call */
 
-                       if (INSTRUCTION_MUST_CHECK(iptr)) {
-                               M_BEQZ(REG_RESULT, 0);
-                               codegen_add_fillinstacktrace_ref(cd);
+                               M_JSR(REG_RA, REG_PV);
+                               REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
+                               disp = (s4) (cd->mcodeptr - cd->mcodebase);
+                               M_LDA(REG_PV, REG_RA, -disp);
+                               break;
                        }
 
                        /* store the return value */
@@ -2785,22 +2757,10 @@ gen_method:
 #endif
                                s1 = emit_load_s1(jd, iptr, REG_ITMP1);
 
-                               /* calculate interface checkcast code size */
-
-                               s2 = 6;
-                               if (super == NULL)
-                                       s2 += opt_shownops ? 1 : 0;
-
-                               /* calculate class checkcast code size */
-
-                               s3 = 9 /* 8 + (s1 == REG_ITMP1) */;
-                               if (super == NULL)
-                                       s3 += opt_shownops ? 1 : 0;
-
                                /* if class is not resolved, check which code to call */
 
                                if (super == NULL) {
-                                       M_BEQZ(s1, 4 + (opt_shownops ? 1 : 0) + s2 + 1 + s3);
+                                       emit_label_beqz(cd, BRANCH_LABEL_1, s1);
 
                                        disp = dseg_add_unique_s4(cd, 0);         /* super->flags */
 
@@ -2812,7 +2772,7 @@ gen_method:
                                        disp = dseg_add_s4(cd, ACC_INTERFACE);
                                        M_ILD(REG_ITMP3, REG_PV, disp);
                                        M_AND(REG_ITMP2, REG_ITMP3, REG_ITMP2);
-                                       M_BEQZ(REG_ITMP2, s2 + 1);
+                                       emit_label_beqz(cd, BRANCH_LABEL_2, REG_ITMP2);
                                }
 
                                /* interface checkcast code */
@@ -2820,33 +2780,36 @@ gen_method:
                                if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
                                        if (super == NULL) {
                                                codegen_add_patch_ref(cd,
-                                                                                         PATCHER_checkcast_instanceof_interface,
+                                                                                         PATCHER_checkcast_interface,
                                                                                          iptr->sx.s23.s3.c.ref,
                                                                                          0);
                                        }
                                        else
-                                               M_BEQZ(s1, s2);
+                                               emit_label_beqz(cd, BRANCH_LABEL_3, s1);
 
                                        M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
                                        M_ILD(REG_ITMP3, REG_ITMP2,
                                                  OFFSET(vftbl_t, interfacetablelength));
                                        M_LDA(REG_ITMP3, REG_ITMP3, -superindex);
-                                       M_BLEZ(REG_ITMP3, 0);
-                                       codegen_add_classcastexception_ref(cd, s1);
+                                       emit_classcast_check(cd, iptr, BRANCH_LE, REG_ITMP3, s1);
+
                                        M_ALD(REG_ITMP3, REG_ITMP2,
                                                  (s4) (OFFSET(vftbl_t, interfacetable[0]) -
                                                                superindex * sizeof(methodptr*)));
-                                       M_BEQZ(REG_ITMP3, 0);
-                                       codegen_add_classcastexception_ref(cd, s1);
+                                       emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ITMP3, s1);
 
                                        if (super == NULL)
-                                               M_BR(s3);
+                                               emit_label_br(cd, BRANCH_LABEL_4);
+                                       else
+                                               emit_label(cd, BRANCH_LABEL_3);
                                }
 
                                /* class checkcast code */
 
                                if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
                                        if (super == NULL) {
+                                               emit_label(cd, BRANCH_LABEL_2);
+
                                                disp = dseg_add_unique_address(cd, NULL);
 
                                                codegen_add_patch_ref(cd,
@@ -2857,7 +2820,7 @@ gen_method:
                                        else {
                                                disp = dseg_add_address(cd, supervftbl);
 
-                                               M_BEQZ(s1, s3);
+                                               emit_label_beqz(cd, BRANCH_LABEL_5, s1);
                                        }
 
                                        M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
@@ -2884,8 +2847,15 @@ gen_method:
 #endif
                                        /*                              } */
                                        M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3);
-                                       M_BEQZ(REG_ITMP3, 0);
-                                       codegen_add_classcastexception_ref(cd, s1);
+                                       emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ITMP3, s1);
+
+                                       if (super != NULL)
+                                               emit_label(cd, BRANCH_LABEL_5);
+                               }
+
+                               if (super == NULL) {
+                                       emit_label(cd, BRANCH_LABEL_1);
+                                       emit_label(cd, BRANCH_LABEL_4);
                                }
 
                                d = codegen_reg_of_dst(jd, iptr, s1);
@@ -2915,8 +2885,7 @@ gen_method:
                                M_LDA(REG_PV, REG_RA, -disp);
 
                                s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                               M_BEQZ(REG_RESULT, 0);
-                               codegen_add_classcastexception_ref(cd, s1);
+                               emit_classcast_check(cd, iptr, BRANCH_EQ, REG_RESULT, s1);
 
                                d = codegen_reg_of_dst(jd, iptr, s1);
                        }
@@ -2963,28 +2932,17 @@ gen_method:
 #endif
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+
                        if (s1 == d) {
                                M_MOV(s1, REG_ITMP1);
                                s1 = REG_ITMP1;
                        }
 
-                       /* calculate interface instanceof code size */
-
-                       s2 = 6;
-                       if (super == NULL)
-                               s2 += (d == REG_ITMP2 ? 1 : 0) + (opt_shownops ? 1 : 0);
-
-                       /* calculate class instanceof code size */
-
-                       s3 = 7;
-                       if (super == NULL)
-                               s3 += (opt_shownops ? 1 : 0);
-
                        /* if class is not resolved, check which code to call */
 
                        if (super == NULL) {
                                M_CLR(d);
-                               M_BEQZ(s1, 4 + (opt_shownops ? 1 : 0) + s2 + 1 + s3);
+                               emit_label_beqz(cd, BRANCH_LABEL_1, s1);
 
                                disp = dseg_add_unique_s4(cd, 0);             /* super->flags */
 
@@ -2996,7 +2954,7 @@ gen_method:
                                disp = dseg_add_s4(cd, ACC_INTERFACE);
                                M_ILD(REG_ITMP2, REG_PV, disp);
                                M_AND(REG_ITMP3, REG_ITMP2, REG_ITMP3);
-                               M_BEQZ(REG_ITMP3, s2 + 1);
+                               emit_label_beqz(cd, BRANCH_LABEL_2, REG_ITMP3);
                        }
 
                        /* interface instanceof code */
@@ -3009,12 +2967,12 @@ gen_method:
                                                M_CLR(d);
 
                                        codegen_add_patch_ref(cd,
-                                                                                 PATCHER_checkcast_instanceof_interface,
+                                                                                 PATCHER_instanceof_interface,
                                                                                  iptr->sx.s23.s3.c.ref, 0);
                                }
                                else {
                                        M_CLR(d);
-                                       M_BEQZ(s1, s2);
+                                       emit_label_beqz(cd, BRANCH_LABEL_3, s1);
                                }
 
                                M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
@@ -3027,13 +2985,17 @@ gen_method:
                                M_CMPULT(REG_ZERO, REG_ITMP1, d);      /* REG_ITMP1 != 0  */
 
                                if (super == NULL)
-                                       M_BR(s3);
+                                       emit_label_br(cd, BRANCH_LABEL_4);
+                               else
+                                       emit_label(cd, BRANCH_LABEL_3);
                        }
 
                        /* class instanceof code */
 
                        if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
                                if (super == NULL) {
+                                       emit_label(cd, BRANCH_LABEL_2);
+
                                        disp = dseg_add_unique_address(cd, NULL);
 
                                        codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_vftbl,
@@ -3044,7 +3006,7 @@ gen_method:
                                        disp = dseg_add_address(cd, supervftbl);
 
                                        M_CLR(d);
-                                       M_BEQZ(s1, s3);
+                                       emit_label_beqz(cd, BRANCH_LABEL_5, s1);
                                }
 
                                M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
@@ -3060,7 +3022,16 @@ gen_method:
 #endif
                                M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
                                M_CMPULE(REG_ITMP1, REG_ITMP2, d);
+
+                               if (super != NULL)
+                                       emit_label(cd, BRANCH_LABEL_5);
+                       }
+
+                       if (super == NULL) {
+                               emit_label(cd, BRANCH_LABEL_1);
+                               emit_label(cd, BRANCH_LABEL_4);
                        }
+
                        emit_store_dst(jd, iptr, d);
                        }
                        break;
@@ -3117,8 +3088,7 @@ gen_method:
 
                        /* check for exception before result assignment */
 
-                       M_BEQZ(REG_RESULT, 0);
-                       codegen_add_fillinstacktrace_ref(cd);
+                       emit_exception_check(cd, iptr);
 
                        d = codegen_reg_of_dst(jd, iptr, REG_RESULT);
                        M_INTMOVE(REG_RESULT, d);
@@ -3140,12 +3110,9 @@ gen_method:
 
        /* generate stubs */
 
-       emit_exception_stubs(jd);
        emit_patcher_stubs(jd);
        REPLACEMENT_EMIT_STUBS(jd);
 
-       codegen_finish(jd);
-
        /* everything's ok */
 
        return true;
index a567903d1c97f8a10c05178ad2750fc0b956ef9f..b2ddc086765c85e368166db617cea2ac9b42a236 100644 (file)
@@ -1,6 +1,6 @@
 /* vm/jit/alpha/codegen.h - code generation macros and definitions for Alpha
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
    J. Wenninger, Institut f. Computersprachen - TU Wien
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Andreas Krall
-            Reinhard Grafl
-            Christian Thalinger
-
-   $Id: codegen.h 6078 2006-11-28 22:19:16Z twisti $
+   $Id: codegen.h 7479 2007-03-08 09:46:27Z twisti $
 
 */
 
         cd->mcodeptr += 4; \
     } while (0)
 
+#define M_MEM_GET_A(x)                  (((x) >> 21) & 0x1f  )
+#define M_MEM_GET_B(x)                  (((x) >> 16) & 0x1f  )
+#define M_MEM_GET_DISP(x)               ( (x)        & 0xffff)
+
 
 /* macros for all used commands (see an Alpha-manual for description) *********/
 
         } \
     } while (0)
 
+#define M_ALD_INTERN(a,b,disp)  M_LLD_INTERN(a,b,disp)
 #define M_ALD(a,b,disp)         M_LLD(a,b,disp)                 /* addr load  */
 
 #define M_BST(a,b,disp)         M_MEM(0x0e,a,b,disp)            /*  8 store   */
index a55f98efdc67fa96632132c75a32df3bbdcd8e02..0ee8f57dbd62f45d6d0999b59ae162fd4665c15f 100644 (file)
@@ -43,6 +43,7 @@
 #endif
 
 #include "vm/builtin.h"
+#include "vm/exceptions.h"
 
 #include "vm/jit/abi-asm.h"
 #include "vm/jit/asmpart.h"
@@ -225,160 +226,172 @@ void emit_lconst(codegendata *cd, s4 d, s8 value)
 }
 
 
-/* emit_arrayindexoutofbounds_check ********************************************
+/* emit_branch *****************************************************************
 
-   Emit an ArrayIndexOutOfBoundsException check.
+   Emits the code for conditional and unconditional branchs.
 
 *******************************************************************************/
 
-void emit_arrayindexoutofbounds_check(codegendata *cd, instruction *iptr, s4 s1, s4 s2)
+void emit_branch(codegendata *cd, s4 disp, s4 condition, s4 reg, u4 opt)
 {
-       if (INSTRUCTION_MUST_CHECK(iptr)) {
-               M_ILD(REG_ITMP3, s1, OFFSET(java_arrayheader, size));
-               M_CMPULT(s2, REG_ITMP3, REG_ITMP3);
-               M_BEQZ(REG_ITMP3, 0);
-               codegen_add_arrayindexoutofboundsexception_ref(cd, s2);
-       }
-}
+       s4 checkdisp;
+       s4 branchdisp;
 
+       /* calculate the different displacements */
 
-/* emit_arraystore_check *******************************************************
+       checkdisp  = (disp - 4);
+       branchdisp = (disp - 4) >> 2;
 
-   Emit an ArrayStoreException check.
+       /* check which branch to generate */
 
-*******************************************************************************/
+       if (condition == BRANCH_UNCONDITIONAL) {
+               /* check displacement for overflow */
 
-void emit_arraystore_check(codegendata *cd, instruction *iptr, s4 reg)
-{
-       M_BEQZ(reg, 0);
-       codegen_add_arraystoreexception_ref(cd);
-}
+               if ((checkdisp < (s4) 0xffe00000) || (checkdisp > (s4) 0x001fffff)) {
+                       /* if the long-branches flag isn't set yet, do it */
 
+                       if (!CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
+                               log_println("setting error");
+                               cd->flags |= (CODEGENDATA_FLAG_ERROR |
+                                                         CODEGENDATA_FLAG_LONGBRANCHES);
+                       }
 
-/* emit_classcast_check ********************************************************
+                       vm_abort("emit_branch: emit unconditional long-branch code");
+               }
+               else {
+                       M_BR(branchdisp);
+               }
+       }
+       else {
+               /* and displacement for overflow */
 
-   Emit a ClassCastException check.
+               if ((checkdisp < (s4) 0xffe00000) || (checkdisp > (s4) 0x001fffff)) {
+                       /* if the long-branches flag isn't set yet, do it */
 
-*******************************************************************************/
+                       if (!CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
+                               log_println("setting error");
+                               cd->flags |= (CODEGENDATA_FLAG_ERROR |
+                                                         CODEGENDATA_FLAG_LONGBRANCHES);
+                       }
 
-void emit_classcast_check(codegendata *cd, instruction *iptr, s4 condition, s4 reg, s4 s1)
-{
-       if (INSTRUCTION_MUST_CHECK(iptr)) {
-               M_BNEZ(reg, 0);
-               codegen_add_classcastexception_ref(cd, s1);
+                       vm_abort("emit_branch: emit conditional long-branch code");
+               }
+               else {
+                       switch (condition) {
+                       case BRANCH_EQ:
+                               M_BEQZ(reg, branchdisp);
+                               break;
+                       case BRANCH_NE:
+                               M_BNEZ(reg, branchdisp);
+                               break;
+                       case BRANCH_LT:
+                               M_BLTZ(reg, branchdisp);
+                               break;
+                       case BRANCH_GE:
+                               M_BGEZ(reg, branchdisp);
+                               break;
+                       case BRANCH_GT:
+                               M_BGTZ(reg, branchdisp);
+                               break;
+                       case BRANCH_LE:
+                               M_BLEZ(reg, branchdisp);
+                               break;
+                       default:
+                               vm_abort("emit_branch: unknown condition %d", condition);
+                       }
+               }
        }
 }
 
 
-/* emit_nullpointer_check ******************************************************
+/* emit_arithmetic_check *******************************************************
 
-   Emit a NullPointerException check.
+   Emit an ArithmeticException check.
 
 *******************************************************************************/
 
-void emit_nullpointer_check(codegendata *cd, instruction *iptr, s4 reg)
+void emit_arithmetic_check(codegendata *cd, instruction *iptr, s4 reg)
 {
        if (INSTRUCTION_MUST_CHECK(iptr)) {
-               M_BEQZ(reg, 0);
-               codegen_add_nullpointerexception_ref(cd);
+               M_BNEZ(reg, 1);
+               /* Destination register must not be REG_ZERO, because then no
+                  SIGSEGV is thrown. */
+               M_ALD_INTERN(reg, REG_ZERO, EXCEPTION_HARDWARE_ARITHMETIC);
        }
 }
 
 
-/* emit_exception_stubs ********************************************************
+/* emit_arrayindexoutofbounds_check ********************************************
 
-   Generates the code for the exception stubs.
+   Emit an ArrayIndexOutOfBoundsException check.
 
 *******************************************************************************/
 
-void emit_exception_stubs(jitdata *jd)
+void emit_arrayindexoutofbounds_check(codegendata *cd, instruction *iptr, s4 s1, s4 s2)
 {
-       codegendata  *cd;
-       registerdata *rd;
-       exceptionref *er;
-       s4            branchmpc;
-       s4            targetmpc;
-       s4            targetdisp;
-       s4            disp;
-
-       /* get required compiler data */
-
-       cd = jd->cd;
-       rd = jd->rd;
-
-       /* generate exception stubs */
-
-       targetdisp = 0;
-
-       for (er = cd->exceptionrefs; er != NULL; er = er->next) {
-               /* back-patch the branch to this exception code */
-
-               branchmpc = er->branchpos;
-               targetmpc = cd->mcodeptr - cd->mcodebase;
-
-               md_codegen_patch_branch(cd, branchmpc, targetmpc);
-
-               MCODECHECK(100);
-
-               /* move index register into REG_ITMP1 */
-
-               /* Check if the exception is an
-                  ArrayIndexOutOfBoundsException.  If so, move index register
-                  into a4. */
-
-               if (er->reg != -1)
-                       M_MOV(er->reg, rd->argintregs[4]);
+       if (INSTRUCTION_MUST_CHECK(iptr)) {
+               M_ILD(REG_ITMP3, s1, OFFSET(java_arrayheader, size));
+               M_CMPULT(s2, REG_ITMP3, REG_ITMP3);
+               M_BNEZ(REG_ITMP3, 1);
+               M_ALD_INTERN(s2, REG_ZERO, EXCEPTION_HARDWARE_ARRAYINDEXOUTOFBOUNDS);
+       }
+}
 
-               /* calcuate exception address */
 
-               M_LDA(rd->argintregs[3], REG_PV, er->branchpos - 4);
+/* emit_classcast_check ********************************************************
 
-               /* move function to call into REG_ITMP3 */
+   Emit a ClassCastException check.
 
-               disp = dseg_add_functionptr(cd, er->function);
-               M_ALD(REG_ITMP3, REG_PV, disp);
+*******************************************************************************/
 
-               if (targetdisp == 0) {
-                       targetdisp = ((u4 *) cd->mcodeptr) - ((u4 *) cd->mcodebase);
+void emit_classcast_check(codegendata *cd, instruction *iptr, s4 condition, s4 reg, s4 s1)
+{
+       if (INSTRUCTION_MUST_CHECK(iptr)) {
+               switch (condition) {
+               case BRANCH_EQ:
+                       M_BNEZ(reg, 1);
+                       break;
+               case BRANCH_LE:
+                       M_BGTZ(reg, 1);
+                       break;
+               default:
+                       vm_abort("emit_classcast_check: unknown condition %d", condition);
+               }
+               M_ALD_INTERN(s1, REG_ZERO, EXCEPTION_HARDWARE_CLASSCAST);
+       }
+}
 
-                       M_MOV(REG_PV, rd->argintregs[0]);
-                       M_MOV(REG_SP, rd->argintregs[1]);
 
-                       if (jd->isleafmethod)
-                               M_MOV(REG_RA, rd->argintregs[2]);
-                       else
-                               M_ALD(rd->argintregs[2],
-                                         REG_SP, cd->stackframesize * 8 - SIZEOF_VOID_P);
+/* emit_nullpointer_check ******************************************************
 
-                       M_LDA(REG_SP, REG_SP, -2 * 8);
-                       M_AST(rd->argintregs[3], REG_SP, 0 * 8);             /* store XPC */
+   Emit a NullPointerException check.
 
-                       if (jd->isleafmethod)
-                               M_AST(REG_RA, REG_SP, 1 * 8);
+*******************************************************************************/
 
-                       M_MOV(REG_ITMP3, REG_PV);
-                       M_JSR(REG_RA, REG_PV);
-                       disp = (s4) (cd->mcodeptr - cd->mcodebase);
-                       M_LDA(REG_PV, REG_RA, -disp);
+void emit_nullpointer_check(codegendata *cd, instruction *iptr, s4 reg)
+{
+       if (INSTRUCTION_MUST_CHECK(iptr)) {
+               M_BNEZ(reg, 1);
+               /* Destination register must not be REG_ZERO, because then no
+                  SIGSEGV is thrown. */
+               M_ALD_INTERN(reg, REG_ZERO, EXCEPTION_HARDWARE_NULLPOINTER);
+       }
+}
 
-                       M_MOV(REG_RESULT, REG_ITMP1_XPTR);
 
-                       if (jd->isleafmethod)
-                               M_ALD(REG_RA, REG_SP, 1 * 8);
+/* emit_exception_check ********************************************************
 
-                       M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
-                       M_LDA(REG_SP, REG_SP, 2 * 8);
+   Emit an Exception check.
 
-                       disp = dseg_add_functionptr(cd, asm_handle_exception);
-                       M_ALD(REG_ITMP3, REG_PV, disp);
-                       M_JMP(REG_ZERO, REG_ITMP3);
-               }
-               else {
-                       disp = (((u4 *) cd->mcodebase) + targetdisp) -
-                               (((u4 *) cd->mcodeptr) + 1);
+*******************************************************************************/
 
-                       M_BR(disp);
-               }
+void emit_exception_check(codegendata *cd, instruction *iptr)
+{
+       if (INSTRUCTION_MUST_CHECK(iptr)) {
+               M_BNEZ(REG_RESULT, 1);
+               /* Destination register must not be REG_ZERO, because then no
+                  SIGSEGV is thrown. */
+               M_ALD_INTERN(REG_RESULT, REG_ZERO, EXCEPTION_HARDWARE_EXCEPTION);
        }
 }
 
index 8bc0aec27f2dc5e739a67ca4b0d2a4d04736f5f6..466465dd63498d20a7595c97dee811d183537752 100644 (file)
@@ -1,4 +1,4 @@
-/* src/vm/jit/alpha/linux/md.c - machine dependent Alpha Linux functions
+/* src/vm/jit/alpha/linux/md-os.c - machine dependent Alpha Linux functions
 
    Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: md-os.c 7251 2007-01-29 20:24:53Z twisti $
+   $Id: md-os.c 7566 2007-03-23 23:51:10Z twisti $
 
 */
 
@@ -34,6 +34,7 @@
 
 #include "vm/types.h"
 
+#include "vm/jit/alpha/codegen.h"
 #include "vm/jit/alpha/md-abi.h"
 
 #include "vm/exceptions.h"
 
 void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
 {
-       ucontext_t  *_uc;
-       mcontext_t  *_mc;
-       u4           instr;
-       ptrint       addr;
-       u1          *pv;
-       u1          *sp;
-       u1          *ra;
-       u1          *xpc;
+       ucontext_t        *_uc;
+       mcontext_t        *_mc;
+       u1                *pv;
+       u1                *sp;
+       u1                *ra;
+       u1                *xpc;
+       u4                 mcode;
+       s4                 d;
+       s4                 s1;
+       s4                 disp;
+       ptrint             val;
+       ptrint             addr;
+       s4                 type;
+       java_objectheader *e;
 
        _uc = (ucontext_t *) _p;
        _mc = &_uc->uc_mcontext;
@@ -69,23 +76,40 @@ void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
        ra  = (u1 *) _mc->sc_regs[REG_RA];           /* this is correct for leafs */
        xpc = (u1 *) _mc->sc_pc;
 
-       instr = *((s4 *) (_mc->sc_pc));
-       addr = _mc->sc_regs[(instr >> 16) & 0x1f];
+       /* get exception-throwing instruction */
 
-       if (addr == 0) {
-               _mc->sc_regs[REG_ITMP1_XPTR] =
-                       (ptrint) stacktrace_hardware_nullpointerexception(pv, sp, ra, xpc);
+       mcode = *((u4 *) xpc);
 
-               _mc->sc_regs[REG_ITMP2_XPC] = (ptrint) xpc;
-               _mc->sc_pc = (ptrint) asm_handle_exception;
+       d    = M_MEM_GET_A(mcode);
+       s1   = M_MEM_GET_B(mcode);
+       disp = M_MEM_GET_DISP(mcode);
+
+       val   = _mc->sc_regs[d];
+
+       /* check for special-load */
+
+       if (s1 == REG_ZERO) {
+               /* we use the exception type as load displacement */
+
+               type = disp;
        }
        else {
-               codegen_get_pv_from_pc(xpc);
-
-               /* this should not happen */
+               /* This is a normal NPE: addr must be NULL and the NPE-type
+                  define is 0. */
 
-               assert(0);
+               addr = _mc->sc_regs[s1];
+               type = (s4) addr;
        }
+
+       /* generate appropriate exception */
+
+       e = exceptions_new_hardware_exception(pv, sp, ra, xpc, type, val);
+
+       /* set registers */
+
+       _mc->sc_regs[REG_ITMP1_XPTR] = (ptrint) e;
+       _mc->sc_regs[REG_ITMP2_XPC]  = (ptrint) xpc;
+       _mc->sc_pc                   = (ptrint) asm_handle_exception;
 }
 
 
index 8fdd0d3c871b6329665b0ae812c63724b616cca3..7613ebc2b6a34792cceac8b2bda5257464ff7ce8 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: md.c 7520 2007-03-14 21:16:04Z twisti $
+   $Id: md.c 7565 2007-03-23 23:48:34Z twisti $
 
 */
 
@@ -47,7 +47,6 @@ extern void ieee_set_fp_control(unsigned long fp_control);
 #include "vm/stringlocal.h"
 
 #include "vm/jit/asmpart.h"
-#include "vm/jit/codegen-common.h" /* REMOVE ME: for codegendata */
 #include "vm/jit/stacktrace.h"
 
 #if !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER)
@@ -90,42 +89,6 @@ void md_init(void)
 }
 
 
-/* md_codegen_patch_branch *****************************************************
-
-   Back-patches a branch instruction.
-
-*******************************************************************************/
-
-void md_codegen_patch_branch(codegendata *cd, s4 branchmpc, s4 targetmpc)
-{
-       s4 *mcodeptr;
-       s4  mcode;
-       s4  disp;                           /* branch displacement                */
-
-       /* calculate the patch position */
-
-       mcodeptr = (s4 *) (cd->mcodebase + branchmpc);
-
-       /* get the instruction before the exception point */
-
-       mcode = mcodeptr[-1];
-
-       /* Calculate the branch displacement.  For branches we need a
-          displacement relative and shifted to the branch PC. */
-
-       disp = (targetmpc - branchmpc) >> 2;
-
-       /* check branch displacement */
-
-       if ((disp < (s4) 0xffe00000) || (disp > (s4) 0x001fffff))
-               vm_abort("branch displacement is out of range: %d > +/-%d", disp, 0x001fffff);
-
-       /* patch the branch instruction before the mcodeptr */
-
-       mcodeptr[-1] |= (disp & 0x001fffff);
-}
-
-
 /* md_stacktrace_get_returnaddress *********************************************
 
    Returns the return address of the current stackframe, specified by
@@ -361,6 +324,7 @@ void md_patch_replacement_point(codeinfo *code, s4 index, rplpoint *rp, u1 *save
 }
 #endif /* defined(ENABLE_REPLACEMENT) */
 
+
 /*
  * 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
index 51a1190eda66aa3d428506d0bb28e09f21cfb357..ed09c8fdbd4979f2d9d908ea6bfe0c8e8dcd7ebd 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: patcher.c 7464 2007-03-06 00:26:31Z edwin $
+   $Id: patcher.c 7486 2007-03-08 13:50:07Z twisti $
 
 */
 
@@ -553,7 +553,7 @@ bool patcher_invokeinterface(u1 *sp)
 }
 
 
-/* patcher_checkcast_instanceof_interface **************************************
+/* patcher_checkcast_interface *************************************************
 
    Machine code:
 
@@ -566,7 +566,52 @@ bool patcher_invokeinterface(u1 *sp)
 
 *******************************************************************************/
 
-bool patcher_checkcast_instanceof_interface(u1 *sp)
+bool patcher_checkcast_interface(u1 *sp)
+{
+       u1                *ra;
+       constant_classref *cr;
+       classinfo         *c;
+
+       /* get stuff from the stack */
+
+       ra    = (u1 *)                *((ptrint *) (sp + 5 * 8));
+       cr    = (constant_classref *) *((ptrint *) (sp + 2 * 8));
+
+       /* get the fieldinfo */
+
+       if (!(c = resolve_classref_eager(cr)))
+               return false;
+
+       /* if we show disassembly, we have to skip the nop */
+
+       if (opt_shownops)
+               ra = ra + 4;
+
+       /* patch super class index */
+
+       *((s4 *) (ra + 2 * 4)) |= (s4) (-(c->index) & 0x0000ffff);
+
+       *((s4 *) (ra + 5 * 4)) |= (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
+                                                                        c->index * sizeof(methodptr*)) & 0x0000ffff);
+
+       return true;
+}
+
+
+/* patcher_instanceof_interface ************************************************
+
+   Machine code:
+
+   <patched call position>
+   a78e0000    ldq     at,0(s5)
+   a3bc001c    ldl     gp,28(at)
+   23bdfffd    lda     gp,-3(gp)
+   efa0002e    ble     gp,0x00000200002bf6b0
+   a7bcffe8    ldq     gp,-24(at)
+
+*******************************************************************************/
+
+bool patcher_instanceof_interface(u1 *sp)
 {
        u1                *ra;
        constant_classref *cr;
index 609debb245a0d3ac63de61868668cab6c547369c..0d50d6207e7c2dc9f885722d84fb577860a1ae76 100644 (file)
@@ -27,7 +27,7 @@
    Authors: Michael Starzinger
             Christian Thalinger
 
-   $Id: arch.h 7241 2007-01-27 15:52:01Z twisti $
+   $Id: arch.h 7540 2007-03-20 00:02:41Z michi $
 
 */
 
 /* define SUPPORT_COMBINE_INTEGER_REGISTERS                                   */
 
 
+/* branches *******************************************************************/
+
+#define SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER       1
+#define SUPPORT_BRANCH_CONDITIONAL_UNSIGNED_CONDITIONS      1
+#define SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER     0
+#define SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS    0
+
+
 /* exceptions *****************************************************************/
 
 #define SUPPORT_HARDWARE_DIVIDE_BY_ZERO  0
index a866859b2b2dd485e45deb04b2b78c220ce4ac48..ff95759430d0a2c356e854d359eab3712ccc876a 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: asmpart.S 7325 2007-02-11 20:10:35Z twisti $
+   $Id: asmpart.S 7454 2007-03-05 15:40:48Z tbfg $
 
 */
 
@@ -48,6 +48,7 @@
        .globl asm_vm_call_method_float
        .globl asm_vm_call_method_double
        .globl asm_vm_call_method_exception_handler
+       .globl asm_vm_call_method_end
 
        .globl asm_call_jit_compiler
 
@@ -196,6 +197,7 @@ asm_vm_call_method_float:
         b asm_debug
 asm_vm_call_method_double:
         mov a0,#0x52
+asm_vm_call_method_end:
         b asm_debug
 
 
index 09734d0bc142b43b2e35fb9d05eaf2e89cf00d34..62bac88528c1c520ea58c61d2c84d4cb5a6cd6b8 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: codegen.c 7554 2007-03-22 13:55:44Z michi $
+   $Id: codegen.c 7591 2007-03-28 19:07:32Z twisti $
 
 */
 
 #include "vmcore/options.h"
 
 
-/* codegen *********************************************************************
+/* codegen_emit ****************************************************************
 
    Generates machine code.
 
 *******************************************************************************/
 
-bool codegen(jitdata *jd)
+bool codegen_emit(jitdata *jd)
 {
        methodinfo         *m;
        codeinfo           *code;
@@ -319,9 +319,7 @@ bool codegen(jitdata *jd)
                        M_DSEG_LOAD(REG_A0, disp);
                }
                else {
-                       M_TST(REG_A0, REG_A0);
-                       M_BEQ(0);
-                       codegen_add_nullpointerexception_ref(cd);
+                       emit_nullpointer_check_force(cd, iptr, REG_A0);
                }
 
                M_STR(REG_A0, REG_SP, s1 * 4);
@@ -712,7 +710,7 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_A0);
                        s2 = emit_load_s2(jd, iptr, REG_A1);
-                       gen_div_check(VAROP(iptr->sx.s23.s2)->type, s2);
+                       emit_arithmetic_check(cd, iptr, s2);
 
                        /* move arguments into argument registers */
                        M_INTMOVE(s1, REG_A0);
@@ -739,12 +737,13 @@ bool codegen(jitdata *jd)
                        /* move arguments into argument registers */
 
                        s1 = emit_load_s1(jd, iptr, REG_A0_A1_PACKED);
-                       M_LNGMOVE(s1, REG_A0_A1_PACKED);
-
                        s2 = emit_load_s2(jd, iptr, REG_A2_A3_PACKED);
-                       M_LNGMOVE(s2, REG_A2_A3_PACKED);
+                       /* XXX TODO: only do this if arithmetic check is really done! */
+                       M_ORR(GET_HIGH_REG(s2), GET_LOW_REG(s2), REG_ITMP3);
+                       emit_arithmetic_check(cd, iptr, REG_ITMP3);
 
-                       gen_div_check(VAROP(iptr->sx.s23.s2)->type, s2);
+                       M_LNGMOVE(s1, REG_A0_A1_PACKED);
+                       M_LNGMOVE(s2, REG_A2_A3_PACKED);
 
                        /* call builtin function */
                        bte = iptr->sx.s23.s3.bte;
@@ -1160,48 +1159,18 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                       gen_nullptr_check(s1);
+                       /* implicit null-pointer check */
                        M_ILD_INTERN(d, s1, OFFSET(java_arrayheader, size));
                        emit_store_dst(jd, iptr, d);
                        break;
 
-               case ICMD_AALOAD:     /* ..., arrayref, index  ==> ..., value         */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
-                       if (INSTRUCTION_MUST_CHECK(iptr)) {
-                               gen_nullptr_check(s1);
-                               gen_bound_check(s1, s2);
-                       }
-                       M_ADD(REG_ITMP1, s1, REG_LSL(s2, 2)); /* REG_ITMP1 = s1 + 4 * s2 */
-                       M_LDR_INTERN(d, REG_ITMP1, OFFSET(java_objectarray, data[0]));
-                       emit_store_dst(jd, iptr, d);
-                       break;
-
-               case ICMD_IALOAD:     /* ..., arrayref, index  ==> ..., value         */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
-                       if (INSTRUCTION_MUST_CHECK(iptr)) {
-                               gen_nullptr_check(s1);
-                               gen_bound_check(s1, s2);
-                       }
-                       M_ADD(REG_ITMP1, s1, REG_LSL(s2, 2)); /* REG_ITMP1 = s1 + 4 * s2 */
-                       M_ILD_INTERN(d, REG_ITMP1, OFFSET(java_intarray, data[0]));
-                       emit_store_dst(jd, iptr, d);
-                       break;
-
                case ICMD_BALOAD:     /* ..., arrayref, index  ==> ..., value         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
-                       if (INSTRUCTION_MUST_CHECK(iptr)) {
-                               gen_nullptr_check(s1);
-                               gen_bound_check(s1, s2);
-                       }
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ADD(REG_ITMP1, s1, s2); /* REG_ITMP1 = s1 + 1 * s2 */
                        M_LDRSB(d, REG_ITMP1, OFFSET(java_bytearray, data[0]));
                        emit_store_dst(jd, iptr, d);
@@ -1212,10 +1181,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
-                       if (INSTRUCTION_MUST_CHECK(iptr)) {
-                               gen_nullptr_check(s1);
-                               gen_bound_check(s1, s2);
-                       }
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ADD(REG_ITMP1, s1, REG_LSL(s2, 1)); /* REG_ITMP1 = s1 + 2 * s2 */
                        M_LDRH(d, REG_ITMP1, OFFSET(java_chararray, data[0]));
                        emit_store_dst(jd, iptr, d);
@@ -1226,24 +1193,32 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
-                       if (INSTRUCTION_MUST_CHECK(iptr)) {
-                               gen_nullptr_check(s1);
-                               gen_bound_check(s1, s2);
-                       }
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ADD(REG_ITMP1, s1, REG_LSL(s2, 1)); /* REG_ITMP1 = s1 + 2 * s2 */
                        M_LDRSH(d, REG_ITMP1, OFFSET(java_shortarray, data[0]));
                        emit_store_dst(jd, iptr, d);
                        break;
 
+               case ICMD_IALOAD:     /* ..., arrayref, index  ==> ..., value         */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
+                       M_ADD(REG_ITMP1, s1, REG_LSL(s2, 2)); /* REG_ITMP1 = s1 + 4 * s2 */
+                       M_ILD_INTERN(d, REG_ITMP1, OFFSET(java_intarray, data[0]));
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
                case ICMD_LALOAD:     /* ..., arrayref, index  ==> ..., value         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
-                       if (INSTRUCTION_MUST_CHECK(iptr)) {
-                               gen_nullptr_check(s1);
-                               gen_bound_check(s1, s2);
-                       }
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ADD(REG_ITMP3, s1, REG_LSL(s2, 3)); /* REG_ITMP3 = s1 + 8 * s2 */
                        M_LLD_INTERN(d, REG_ITMP3, OFFSET(java_longarray, data[0]));
                        emit_store_dst(jd, iptr, d);
@@ -1253,10 +1228,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       if (INSTRUCTION_MUST_CHECK(iptr)) {
-                               gen_nullptr_check(s1);
-                               gen_bound_check(s1, s2);
-                       }
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ADD(REG_ITMP1, s1, REG_LSL(s2, 2)); /* REG_ITMP1 = s1 + 4 * s2 */
 #if !defined(ENABLE_SOFTFLOAT)
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
@@ -1272,10 +1245,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       if (INSTRUCTION_MUST_CHECK(iptr)) {
-                               gen_nullptr_check(s1);
-                               gen_bound_check(s1, s2);
-                       }
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ADD(REG_ITMP3, s1, REG_LSL(s2, 3)); /* REG_ITMP3 = s1 + 8 * s2 */
 #if !defined(ENABLE_SOFTFLOAT)
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
@@ -1287,62 +1258,24 @@ bool codegen(jitdata *jd)
                        emit_store_dst(jd, iptr, d);
                        break;
 
-               case ICMD_AASTORE:    /* ..., arrayref, index, value  ==> ...         */
-
-                       s1 = emit_load_s1(jd, iptr, REG_A0);
-                       s2 = emit_load_s2(jd, iptr, REG_ITMP1);
-                       if (INSTRUCTION_MUST_CHECK(iptr)) {
-                               gen_nullptr_check(s1);
-                               gen_bound_check(s1, s2);
-                       }
-                       s3 = emit_load_s3(jd, iptr, REG_A1);
-
-                       /* move arguments to argument registers */
-                       M_INTMOVE(s1, REG_A0);
-                       M_INTMOVE(s3, REG_A1);
-
-                       /* call builtin function */
-                       disp = dseg_add_functionptr(cd, BUILTIN_canstore);
-                       M_DSEG_BRANCH(disp);
-
-                       /* recompute pv */
-                       s1 = (s4) (cd->mcodeptr - cd->mcodebase);
-                       M_RECOMPUTE_PV(s1);
-
-                       /* check resturn value of builtin */
-                       M_TST(REG_RESULT, REG_RESULT);
-                       M_BEQ(0);
-                       codegen_add_arraystoreexception_ref(cd);
-
-                       /* finally store address into array */
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       s3 = emit_load_s3(jd, iptr, REG_ITMP3);
-                       M_ADD(REG_ITMP1, s1, REG_LSL(s2, 2)); /* REG_ITMP1 = s1 + 4 * s2 */
-                       M_STR_INTERN(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
-                       break;
-
-               case ICMD_IASTORE:    /* ..., arrayref, index, value  ==> ...         */
+               case ICMD_AALOAD:     /* ..., arrayref, index  ==> ..., value         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       if (INSTRUCTION_MUST_CHECK(iptr)) {
-                               gen_nullptr_check(s1);
-                               gen_bound_check(s1, s2);
-                       }
-                       s3 = emit_load_s3(jd, iptr, REG_ITMP3);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ADD(REG_ITMP1, s1, REG_LSL(s2, 2)); /* REG_ITMP1 = s1 + 4 * s2 */
-                       M_IST_INTERN(s3, REG_ITMP1, OFFSET(java_intarray, data[0]));
+                       M_LDR_INTERN(d, REG_ITMP1, OFFSET(java_objectarray, data[0]));
+                       emit_store_dst(jd, iptr, d);
                        break;
 
                case ICMD_BASTORE:    /* ..., arrayref, index, value  ==> ...         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       if (INSTRUCTION_MUST_CHECK(iptr)) {
-                               gen_nullptr_check(s1);
-                               gen_bound_check(s1, s2);
-                       }
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
                        M_ADD(REG_ITMP1, s1, s2); /* REG_ITMP1 = s1 + 1 * s2 */
                        M_STRB(s3, REG_ITMP1, OFFSET(java_bytearray, data[0]));
@@ -1352,10 +1285,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       if (INSTRUCTION_MUST_CHECK(iptr)) {
-                               gen_nullptr_check(s1);
-                               gen_bound_check(s1, s2);
-                       }
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
                        M_ADD(REG_ITMP1, s1, REG_LSL(s2, 1)); /* REG_ITMP1 = s1 + 2 * s2 */
                        M_STRH(s3, REG_ITMP1, OFFSET(java_chararray, data[0]));
@@ -1365,23 +1296,30 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       if (INSTRUCTION_MUST_CHECK(iptr)) {
-                               gen_nullptr_check(s1);
-                               gen_bound_check(s1, s2);
-                       }
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
                        M_ADD(REG_ITMP1, s1, REG_LSL(s2, 1)); /* REG_ITMP1 = s1 + 2 * s2 */
                        M_STRH(s3, REG_ITMP1, OFFSET(java_shortarray, data[0]));
                        break;
 
+               case ICMD_IASTORE:    /* ..., arrayref, index, value  ==> ...         */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
+                       s3 = emit_load_s3(jd, iptr, REG_ITMP3);
+                       M_ADD(REG_ITMP1, s1, REG_LSL(s2, 2)); /* REG_ITMP1 = s1 + 4 * s2 */
+                       M_IST_INTERN(s3, REG_ITMP1, OFFSET(java_intarray, data[0]));
+                       break;
+
                case ICMD_LASTORE:    /* ..., arrayref, index, value  ==> ...         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       if (INSTRUCTION_MUST_CHECK(iptr)) {
-                               gen_nullptr_check(s1);
-                               gen_bound_check(s1, s2);
-                       }
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ADD(REG_ITMP3, s1, REG_LSL(s2, 3)); /* REG_ITMP3 = s1 + 8 * s2 */
                        s3 = emit_load_s3(jd, iptr, REG_ITMP12_PACKED);
                        M_LST_INTERN(s3, REG_ITMP3, OFFSET(java_longarray, data[0]));
@@ -1391,10 +1329,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       if (INSTRUCTION_MUST_CHECK(iptr)) {
-                               gen_nullptr_check(s1);
-                               gen_bound_check(s1, s2);
-                       }
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ADD(REG_ITMP1, s1, REG_LSL(s2, 2)); /* REG_ITMP1 = s1 + 4 * s2 */
 #if !defined(ENABLE_SOFTFLOAT)
                        s3 = emit_load_s3(jd, iptr, REG_FTMP1);
@@ -1409,10 +1345,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       if (INSTRUCTION_MUST_CHECK(iptr)) {
-                               gen_nullptr_check(s1);
-                               gen_bound_check(s1, s2);
-                       }
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ADD(REG_ITMP1, s1, REG_LSL(s2, 3)); /* REG_ITMP1 = s1 + 8 * s2 */
 #if !defined(ENABLE_SOFTFLOAT)
                        s3 = emit_load_s3(jd, iptr, REG_FTMP1);
@@ -1423,6 +1357,38 @@ bool codegen(jitdata *jd)
 #endif
                        break;
 
+               case ICMD_AASTORE:    /* ..., arrayref, index, value  ==> ...         */
+
+                       s1 = emit_load_s1(jd, iptr, REG_A0);
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP1);
+                       s3 = emit_load_s3(jd, iptr, REG_A1);
+
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
+
+                       /* move arguments to argument registers */
+                       M_INTMOVE(s1, REG_A0);
+                       M_INTMOVE(s3, REG_A1);
+
+                       /* call builtin function */
+                       disp = dseg_add_functionptr(cd, BUILTIN_canstore);
+                       M_DSEG_BRANCH(disp);
+
+                       /* recompute pv */
+                       s1 = (s4) (cd->mcodeptr - cd->mcodebase);
+                       M_RECOMPUTE_PV(s1);
+
+                       /* check resturn value of builtin */
+                       emit_exception_check(cd, iptr);
+
+                       /* finally store address into array */
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+                       s3 = emit_load_s3(jd, iptr, REG_ITMP3);
+                       M_ADD(REG_ITMP1, s1, REG_LSL(s2, 2)); /* REG_ITMP1 = s1 + 4 * s2 */
+                       M_STR_INTERN(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
+                       break;
+
                case ICMD_GETSTATIC:  /* ...  ==> ..., value                          */
 
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
@@ -1549,7 +1515,8 @@ bool codegen(jitdata *jd)
                case ICMD_GETFIELD:   /* ..., objectref, value  ==> ...               */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP3);
-                       gen_nullptr_check(s1);
+                       emit_nullpointer_check(cd, iptr, s1);
+
 
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
                                unresolved_field *uf = iptr->sx.s23.s3.uf;
@@ -1565,8 +1532,8 @@ bool codegen(jitdata *jd)
 
 #if !defined(ENABLE_SOFTFLOAT)
                        /* HACK: softnull checks on floats */
-                       if (!checknull && IS_FLT_DBL_TYPE(fieldtype))
-                               gen_nullptr_check_intern(s1);
+                       if (!INSTRUCTION_MUST_CHECK(iptr) && IS_FLT_DBL_TYPE(fieldtype))
+                               emit_nullpointer_check_force(cd, iptr, s1);
 #endif
 
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
@@ -1615,7 +1582,7 @@ bool codegen(jitdata *jd)
                case ICMD_PUTFIELD:   /* ..., objectref, value  ==> ...               */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP3);
-                       gen_nullptr_check(s1);
+                       emit_nullpointer_check(cd, iptr, s1);
 
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
                                unresolved_field *uf = iptr->sx.s23.s3.uf;
@@ -1631,8 +1598,8 @@ bool codegen(jitdata *jd)
 
 #if !defined(ENABLE_SOFTFLOAT)
                        /* HACK: softnull checks on floats */
-                       if (!checknull && IS_FLT_DBL_TYPE(fieldtype))
-                               gen_nullptr_check_intern(s1);
+                       if (!INSTRUCTION_MUST_CHECK(iptr) && IS_FLT_DBL_TYPE(fieldtype))
+                               emit_nullpointer_check_force(cd, iptr, s1);
 #endif
 
                        switch (fieldtype) {
@@ -1722,30 +1689,20 @@ bool codegen(jitdata *jd)
                case ICMD_GOTO:         /* ... ==> ...                                */
                case ICMD_RET:
 
-                       M_B(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_br(cd, iptr->dst.block);
                        break;
 
                case ICMD_JSR:          /* ... ==> ...                                */
 
-                       M_B(0);
-                       codegen_addreference(cd, iptr->sx.s23.s3.jsrtarget.block);
+                       emit_br(cd, iptr->sx.s23.s3.jsrtarget.block);
                        break;
                
                case ICMD_IFNULL:       /* ..., value ==> ...                         */
+               case ICMD_IFNONNULL:
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        M_TEQ_IMM(s1, 0);
-                       M_BEQ(0);
-                       codegen_addreference(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IFNONNULL:    /* ..., value ==> ...                         */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       M_TEQ_IMM(s1, 0);
-                       M_BNE(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IFNULL, BRANCH_OPT_NONE);
                        break;
 
                case ICMD_IFLT:         /* ..., value ==> ...                         */
@@ -1757,30 +1714,7 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        M_COMPARE(s1, iptr->sx.val.i);
-
-                       switch(iptr->opc) {
-                       case ICMD_IFLT:
-                               M_BLT(0);
-                               break;
-                       case ICMD_IFLE:
-                               M_BLE(0);
-                               break;
-                       case ICMD_IFGT:
-                               M_BGT(0);
-                               break;
-                       case ICMD_IFGE:
-                               M_BGE(0);
-                               break;
-                       case ICMD_IFEQ:
-                               M_BEQ(0);
-                               break;
-                       case ICMD_IFNE:
-                               M_BNE(0);
-                               break;
-                       default:
-                               assert(0);
-                       }
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IFEQ, BRANCH_OPT_NONE);
                        break;
 
                case ICMD_IF_LEQ:       /* ..., value ==> ...                         */
@@ -1797,8 +1731,7 @@ bool codegen(jitdata *jd)
                                ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
                                M_CMPEQ(s2, REG_ITMP3);
                        }
-                       M_BEQ(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_beq(cd, iptr->dst.block);
                        break;
 
                case ICMD_IF_LLT:       /* ..., value ==> ...                         */
@@ -1808,8 +1741,7 @@ bool codegen(jitdata *jd)
                        if (iptr->sx.val.l == 0) {
                                /* if high word is less than zero, the whole long is too */
                                M_CMP_IMM(s1, 0);
-                               M_BLT(0);
-                               codegen_add_branch_ref(cd, iptr->dst.block);
+                               emit_blt(cd, iptr->dst.block);
                        }
                        else {
                                /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */
@@ -1828,8 +1760,7 @@ bool codegen(jitdata *jd)
 
                                /* branch if (x LT 1) */
                                M_CMP_IMM(REG_ITMP1, 1);
-                               M_BLT(0);
-                               codegen_add_branch_ref(cd, iptr->dst.block);
+                               emit_blt(cd, iptr->dst.block);
                        }
                        break;
 
@@ -1840,13 +1771,11 @@ bool codegen(jitdata *jd)
                        if (iptr->sx.val.l == 0) {
                                /* if high word is less than zero, the whole long is too  */
                                M_CMP_IMM(s1, 0);
-                               M_BLT(0);
-                               codegen_add_branch_ref(cd, iptr->dst.block);
+                               emit_blt(cd, iptr->dst.block);
 
                                /* ... otherwise the low word has to be zero (tricky!) */
                                M_CMPEQ_IMM(s2, 0);
-                               M_BEQ(0);
-                               codegen_add_branch_ref(cd, iptr->dst.block);
+                               emit_beq(cd, iptr->dst.block);
                        }
                        else {
                                /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */
@@ -1865,8 +1794,7 @@ bool codegen(jitdata *jd)
 
                                /* branch if (x LE 1) */
                                M_CMP_IMM(REG_ITMP1, 1);
-                               M_BLE(0);
-                               codegen_add_branch_ref(cd, iptr->dst.block);
+                               emit_ble(cd, iptr->dst.block);
                        }
                        break;
 
@@ -1877,8 +1805,7 @@ bool codegen(jitdata *jd)
                        if (iptr->sx.val.l == 0) {
                                /* if high word is greater or equal zero, the whole long is too */
                                M_CMP_IMM(s1, 0);
-                               M_BGE(0);
-                               codegen_add_branch_ref(cd, iptr->dst.block);
+                               emit_bge(cd, iptr->dst.block);
                        }
                        else {
                                /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */
@@ -1897,8 +1824,7 @@ bool codegen(jitdata *jd)
 
                                /* branch if (x GE 1) */
                                M_CMP_IMM(REG_ITMP1, 1);
-                               M_BGE(0);
-                               codegen_add_branch_ref(cd, iptr->dst.block);
+                               emit_bge(cd, iptr->dst.block);
                        }
                        break;
 
@@ -1938,8 +1864,7 @@ bool codegen(jitdata *jd)
 
                                /* branch if (x GT 1) */
                                M_CMP_IMM(REG_ITMP1, 1);
-                               M_BGT(0);
-                               codegen_add_branch_ref(cd, iptr->dst.block);
+                               emit_bgt(cd, iptr->dst.block);
 #if 0
                        }
 #endif
@@ -1959,14 +1884,11 @@ bool codegen(jitdata *jd)
                                ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
                                M_CMPEQ(s2, REG_ITMP3);
                        }
-                       M_BNE(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                       emit_bne(cd, iptr->dst.block);
                        break;
                        
                case ICMD_IF_ICMPEQ:    /* ..., value, value ==> ...                  */
-               case ICMD_IF_ACMPEQ:    /* op1 = target JavaVM pc                     */
                case ICMD_IF_ICMPNE:
-               case ICMD_IF_ACMPNE:
                case ICMD_IF_ICMPLT:
                case ICMD_IF_ICMPLE:
                case ICMD_IF_ICMPGT:
@@ -1975,31 +1897,16 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_CMP(s1, s2);
-                       switch(iptr->opc) {
-                       case ICMD_IF_ICMPLT:
-                               M_BLT(0);
-                               break;
-                       case ICMD_IF_ICMPLE:
-                               M_BLE(0);
-                               break;
-                       case ICMD_IF_ICMPGT:
-                               M_BGT(0);
-                               break;
-                       case ICMD_IF_ICMPGE:
-                               M_BGE(0);
-                               break;
-                       case ICMD_IF_ICMPEQ:
-                       case ICMD_IF_ACMPEQ:
-                               M_BEQ(0);
-                               break;
-                       case ICMD_IF_ICMPNE:
-                       case ICMD_IF_ACMPNE:
-                               M_BNE(0);
-                               break;
-                       default:
-                               assert(0);
-                       }
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IF_ICMPEQ, BRANCH_OPT_NONE);
+                       break;
+
+               case ICMD_IF_ACMPEQ:    /* ..., value, value ==> ...                  */
+               case ICMD_IF_ACMPNE:
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+                       M_CMP(s1, s2);
+                       emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IF_ACMPEQ, BRANCH_OPT_NONE);
                        break;
 
                case ICMD_IF_LCMPEQ:    /* ..., value, value ==> ...                  */
@@ -2013,8 +1920,7 @@ bool codegen(jitdata *jd)
                        s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
                        M_CMPEQ(s1, s2);
 
-                       M_BEQ(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_beq(cd, iptr->dst.block);
                        break;
 
                case ICMD_IF_LCMPNE:    /* ..., value, value ==> ...                  */
@@ -2028,8 +1934,7 @@ bool codegen(jitdata *jd)
                        s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
                        M_CMPEQ(s1, s2);
 
-                       M_BNE(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_bne(cd, iptr->dst.block);
                        break;
 
                case ICMD_IF_LCMPLT:    /* ..., value, value ==> ...                  */
@@ -2051,8 +1956,7 @@ bool codegen(jitdata *jd)
 
                        /* branch if (x LT 1) */
                        M_CMP_IMM(REG_ITMP3, 1);
-                       M_BLT(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_blt(cd, iptr->dst.block);
                        break;
 
                case ICMD_IF_LCMPLE:    /* ..., value, value ==> ...                  */
@@ -2074,8 +1978,7 @@ bool codegen(jitdata *jd)
 
                        /* branch if (x LE 1) */
                        M_CMP_IMM(REG_ITMP3, 1);
-                       M_BLE(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_ble(cd, iptr->dst.block);
                        break;
 
                case ICMD_IF_LCMPGT:    /* ..., value, value ==> ...                  */
@@ -2097,8 +2000,7 @@ bool codegen(jitdata *jd)
 
                        /* branch if (x GT 1) */
                        M_CMP_IMM(REG_ITMP3, 1);
-                       M_BGT(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_bgt(cd, iptr->dst.block);
                        break;
 
                case ICMD_IF_LCMPGE:    /* ..., value, value ==> ...                  */
@@ -2120,8 +2022,7 @@ bool codegen(jitdata *jd)
 
                        /* branch if (x GE 1) */
                        M_CMP_IMM(REG_ITMP3, 1);
-                       M_BGE(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_bge(cd, iptr->dst.block);
                        break;
 
                case ICMD_TABLESWITCH:  /* ..., index ==> ...                         */
@@ -2148,8 +2049,7 @@ bool codegen(jitdata *jd)
                        /* range check (index <= high-low) */
                        i = i - l + 1;
                        M_COMPARE(REG_ITMP1, i-1);
-                       M_BHI(0); /* unsigned greater than */
-                       codegen_addreference(cd, table[0].block);
+                       emit_bugt(cd, table[0].block);
 
                        /* build jump table top down and use address of lowest entry */
 
@@ -2182,14 +2082,12 @@ bool codegen(jitdata *jd)
 
                        while (--i >= 0) {
                                M_COMPARE(s1, lookup->value);
-                               M_BEQ(0);
-                               codegen_addreference(cd, lookup->target.block);
+                               emit_beq(cd, lookup->target.block);
                                lookup++;
                        }
 
                        /* default branch */
-                       M_B(0);
-                       codegen_addreference(cd, iptr->sx.s23.s3.lookupdefault.block);
+                       emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
                        }
                        break;
 
@@ -2390,13 +2288,20 @@ bool codegen(jitdata *jd)
                        case ICMD_BUILTIN:
                                disp = dseg_add_functionptr(cd, bte->fp);
 
-                               M_DSEG_LOAD(REG_PV, disp); /* Pointer to built-in-function */
+                               M_DSEG_LOAD(REG_PV, disp); /* pointer to built-in-function */
+
+                               /* generate the actual call */
+
+                               M_MOV(REG_LR, REG_PC);
+                               M_MOV(REG_PC, REG_PV);
+                               s1 = (s4) (cd->mcodeptr - cd->mcodebase);
+                               M_RECOMPUTE_PV(s1);
+
+                               emit_exception_check(cd, iptr);
                                break;
 
                        case ICMD_INVOKESPECIAL:
-                               M_TST(REG_A0, REG_A0);
-                               M_BEQ(0);
-                               codegen_add_nullpointerexception_ref(cd);
+                               emit_nullpointer_check(cd, iptr, REG_A0);
                                /* fall through */
 
                        case ICMD_INVOKESTATIC:
@@ -2413,11 +2318,16 @@ bool codegen(jitdata *jd)
                                        disp = dseg_add_address(cd, lm->stubroutine);
 
                                M_DSEG_LOAD(REG_PV, disp);            /* Pointer to method */
+
+                               /* generate the actual call */
+
+                               M_MOV(REG_LR, REG_PC);
+                               M_MOV(REG_PC, REG_PV);
+                               s1 = (s4) (cd->mcodeptr - cd->mcodebase);
+                               M_RECOMPUTE_PV(s1);
                                break;
 
                        case ICMD_INVOKEVIRTUAL:
-                               gen_nullptr_check(REG_A0);
-
                                if (lm == NULL) {
                                        codegen_addpatchref(cd, PATCHER_invokevirtual, um, 0);
 
@@ -2430,14 +2340,20 @@ bool codegen(jitdata *jd)
                                        s1 = OFFSET(vftbl_t, table[0]) +
                                                sizeof(methodptr) * lm->vftblindex;
 
+                               /* implicit null-pointer check */
                                M_LDR_INTERN(REG_METHODPTR, REG_A0,
                                                         OFFSET(java_objectheader, vftbl));
                                M_LDR_INTERN(REG_PV, REG_METHODPTR, s1);
+
+                               /* generate the actual call */
+
+                               M_MOV(REG_LR, REG_PC);
+                               M_MOV(REG_PC, REG_PV);
+                               s1 = (s4) (cd->mcodeptr - cd->mcodebase);
+                               M_RECOMPUTE_PV(s1);
                                break;
 
                        case ICMD_INVOKEINTERFACE:
-                               gen_nullptr_check(REG_A0);
-
                                if (lm == NULL) {
                                        codegen_addpatchref(cd, PATCHER_invokeinterface, um, 0);
 
@@ -2453,26 +2369,19 @@ bool codegen(jitdata *jd)
                                        s2 = sizeof(methodptr) * (lm - lm->class->methods);
                                }
 
+                               /* implicit null-pointer check */
                                M_LDR_INTERN(REG_METHODPTR, REG_A0,
                                                         OFFSET(java_objectheader, vftbl));
                                M_LDR_INTERN(REG_METHODPTR, REG_METHODPTR, s1);
                                M_LDR_INTERN(REG_PV, REG_METHODPTR, s2);
-                               break;
-                       }
 
-                       /* generate the actual call */
+                               /* generate the actual call */
 
-                       M_MOV(REG_LR, REG_PC);               /* save return address in LR */
-                       M_MOV(REG_PC, REG_PV);               /* branch to method          */
-                       s1 = (s4) (cd->mcodeptr - cd->mcodebase);
-                       M_RECOMPUTE_PV(s1);
-
-                       /* actually only used for ICMD_BUILTIN */
-
-                       if (INSTRUCTION_MUST_CHECK(iptr)) {
-                               M_TST(REG_RESULT, REG_RESULT);
-                               M_BEQ(0);
-                               codegen_add_fillinstacktrace_ref(cd);
+                               M_MOV(REG_LR, REG_PC);
+                               M_MOV(REG_PC, REG_PV);
+                               s1 = (s4) (cd->mcodeptr - cd->mcodebase);
+                               M_RECOMPUTE_PV(s1);
+                               break;
                        }
 
                        /* store return value */
@@ -2532,9 +2441,6 @@ bool codegen(jitdata *jd)
 
                        classinfo *super;
                        s4         superindex;
-                       u1        *branch1 = NULL;
-                       u1        *branch2 = NULL;
-                       u1        *branch3 = NULL;
 
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
                                super      = NULL;
@@ -2554,8 +2460,7 @@ bool codegen(jitdata *jd)
 
                        if (super == NULL) {
                                M_TST(s1, s1);
-                               M_BEQ(0);
-                               branch1 = cd->mcodeptr;
+                               emit_label_beq(cd, BRANCH_LABEL_1);
 
                                disp = dseg_add_unique_s4(cd, 0); /* super->flags */
                                codegen_addpatchref(cd, PATCHER_checkcast_instanceof_flags,
@@ -2568,8 +2473,7 @@ bool codegen(jitdata *jd)
                                disp = dseg_add_s4(cd, ACC_INTERFACE);
                                M_DSEG_LOAD(REG_ITMP3, disp);
                                M_TST(REG_ITMP2, REG_ITMP3);
-                               M_BEQ(0);
-                               branch2 = cd->mcodeptr;
+                               emit_label_beq(cd, BRANCH_LABEL_2);
                        }
 
                        /* interface checkcast code */
@@ -2585,40 +2489,34 @@ bool codegen(jitdata *jd)
                                }
                                else {
                                        M_TST(s1, s1);
-                                       M_BEQ(0);
-                                       branch1 = cd->mcodeptr;
+                                       emit_label_beq(cd, BRANCH_LABEL_3);
                                }
 
                                M_LDR_INTERN(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
                                M_LDR_INTERN(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
                                assert(IS_IMM(superindex));
                                M_CMP_IMM(REG_ITMP3, superindex);
-                               M_BLE(0);
-                               codegen_add_classcastexception_ref(cd, s1);
+                               emit_classcast_check(cd, iptr, BRANCH_LE, REG_ITMP3, s1);
 
                                s2 = OFFSET(vftbl_t, interfacetable[0]) -
                                        superindex * sizeof(methodptr*);
 
                                M_LDR_INTERN(REG_ITMP3, REG_ITMP2, s2);
                                M_TST(REG_ITMP3, REG_ITMP3);
-                               M_BEQ(0);
-                               codegen_add_classcastexception_ref(cd, s1);
+                               emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ITMP3, s1);
 
-                               if (super == NULL) {
-                                       M_B(0);
-                                       branch3 = cd->mcodeptr;
-                               }
-                       }
-
-                       if (branch2) {
-                               gen_resolvebranch(branch2, branch2 - cd->mcodebase,
-                                                                 cd->mcodeptr - cd->mcodebase);
+                               if (super == NULL)
+                                       emit_label_br(cd, BRANCH_LABEL_4);
+                               else
+                                       emit_label(cd, BRANCH_LABEL_3);
                        }
 
                        /* class checkcast code */
 
                        if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
                                if (super == NULL) {
+                                       emit_label(cd, BRANCH_LABEL_2);
+
                                        disp = dseg_add_unique_address(cd, NULL);
 
                                        codegen_addpatchref(cd, PATCHER_checkcast_instanceof_class,
@@ -2632,8 +2530,7 @@ bool codegen(jitdata *jd)
                                        disp = dseg_add_address(cd, super->vftbl);
 
                                        M_TST(s1, s1);
-                                       M_BEQ(0);
-                                       branch1 = cd->mcodeptr;
+                                       emit_label_beq(cd, BRANCH_LABEL_5);
                                }
 
                                M_LDR_INTERN(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
@@ -2650,18 +2547,15 @@ bool codegen(jitdata *jd)
                                codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
 #endif
                                M_CMP(REG_ITMP2, REG_ITMP3);
-                               M_BHI(0);
-                               codegen_add_classcastexception_ref(cd, s1);
-                       }
+                               emit_classcast_check(cd, iptr, BRANCH_UGT, 0, s1);
 
-                       if (branch1) {
-                               gen_resolvebranch(branch1, branch1 - cd->mcodebase,
-                                                                 cd->mcodeptr - cd->mcodebase);
+                               if (super != NULL)
+                                       emit_label(cd, BRANCH_LABEL_5);
                        }
 
-                       if (branch3) {
-                               gen_resolvebranch(branch3, branch3 - cd->mcodebase,
-                                                                 cd->mcodeptr - cd->mcodebase);
+                       if (super == NULL) {
+                               emit_label(cd, BRANCH_LABEL_1);
+                               emit_label(cd, BRANCH_LABEL_4);
                        }
 
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
@@ -2695,8 +2589,7 @@ bool codegen(jitdata *jd)
 
                                s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                                M_TST(REG_RESULT, REG_RESULT);
-                               M_BEQ(0);
-                               codegen_add_classcastexception_ref(cd, s1);
+                               emit_classcast_check(cd, iptr, BRANCH_EQ, REG_RESULT, s1);
 
                                d = codegen_reg_of_dst(jd, iptr, s1);
                        }
@@ -2710,9 +2603,6 @@ bool codegen(jitdata *jd)
                        {
                        classinfo *super;
                        s4         superindex;
-                       u1        *branch1 = NULL;
-                       u1        *branch2 = NULL;
-                       u1        *branch3 = NULL;
 
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
                                super      = NULL;
@@ -2737,9 +2627,9 @@ bool codegen(jitdata *jd)
 
                        if (super == NULL) {
                                M_EOR(d, d, d);
+
                                M_TST(s1, s1);
-                               M_BEQ(0);
-                               branch1 = cd->mcodeptr;
+                               emit_label_beq(cd, BRANCH_LABEL_1);
 
                                disp = dseg_add_unique_s4(cd, 0); /* super->flags */
                                codegen_addpatchref(cd, PATCHER_checkcast_instanceof_flags,
@@ -2752,8 +2642,7 @@ bool codegen(jitdata *jd)
                                disp = dseg_add_s4(cd, ACC_INTERFACE);
                                M_DSEG_LOAD(REG_ITMP3, disp);
                                M_TST(REG_ITMP2, REG_ITMP3);
-                               M_BEQ(0);
-                               branch2 = cd->mcodeptr;
+                               emit_label_beq(cd, BRANCH_LABEL_2);
                        }
 
                        /* interface checkcast code */
@@ -2775,8 +2664,7 @@ bool codegen(jitdata *jd)
                                else {
                                        M_EOR(d, d, d);
                                        M_TST(s1, s1);
-                                       M_BEQ(0);
-                                       branch1 = cd->mcodeptr;
+                                       emit_label_beq(cd, BRANCH_LABEL_3);
                                }
 
                                M_LDR_INTERN(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
@@ -2793,21 +2681,18 @@ bool codegen(jitdata *jd)
                                M_TST(REG_ITMP3, REG_ITMP3);
                                M_MOVNE_IMM(1, d);
 
-                               if (super == NULL) {
-                                       M_B(0);
-                                       branch3 = cd->mcodeptr;
-                               }
-                       }
-
-                       if (branch2) {
-                               gen_resolvebranch(branch2, branch2 - cd->mcodebase,
-                                                                 cd->mcodeptr - cd->mcodebase);
+                               if (super == NULL)
+                                       emit_label_br(cd, BRANCH_LABEL_4);
+                               else
+                                       emit_label(cd, BRANCH_LABEL_3);
                        }
 
                        /* class checkcast code */
 
                        if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
                                if (super == NULL) {
+                                       emit_label(cd, BRANCH_LABEL_2);
+
                                        disp = dseg_add_unique_address(cd, NULL);
 
                                        codegen_addpatchref(cd, PATCHER_checkcast_instanceof_class,
@@ -2822,8 +2707,7 @@ bool codegen(jitdata *jd)
 
                                        M_EOR(d, d, d);
                                        M_TST(s1, s1);
-                                       M_BEQ(0);
-                                       branch1 = cd->mcodeptr;
+                                       emit_label_beq(cd, BRANCH_LABEL_5);
                                }
 
                                M_LDR_INTERN(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
@@ -2843,16 +2727,14 @@ bool codegen(jitdata *jd)
                                if (d == REG_ITMP2)
                                        M_EOR(d, d, d);
                                M_MOVLS_IMM(1, d);
-                       }
 
-                       if (branch1) {
-                               gen_resolvebranch(branch1, branch1 - cd->mcodebase,
-                                                                 cd->mcodeptr - cd->mcodebase);
+                               if (super != NULL)
+                                       emit_label(cd, BRANCH_LABEL_5);
                        }
 
-                       if (branch3) {
-                               gen_resolvebranch(branch3, branch3 - cd->mcodebase,
-                                                                 cd->mcodeptr - cd->mcodebase);
+                       if (super == NULL) {
+                               emit_label(cd, BRANCH_LABEL_1);
+                               emit_label(cd, BRANCH_LABEL_4);
                        }
 
                        }
@@ -2917,9 +2799,7 @@ bool codegen(jitdata *jd)
 
                        /* check for exception before result assignment */
 
-                       M_TST(REG_RESULT, REG_RESULT);
-                       M_BEQ(0);
-                       codegen_add_fillinstacktrace_ref(cd);
+                       emit_exception_check(cd, iptr);
 
                        /* get arrayref */
 
@@ -2931,9 +2811,7 @@ bool codegen(jitdata *jd)
                case ICMD_CHECKNULL:  /* ..., objectref  ==> ..., objectref           */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       M_TST(s1, s1);
-                       M_BEQ(0);
-                       codegen_add_nullpointerexception_ref(cd);
+                       emit_nullpointer_check(cd, iptr, s1);
                        break;
 
                default:
@@ -2949,13 +2827,10 @@ bool codegen(jitdata *jd)
        dseg_createlinenumbertable(cd);
 
 
-       /* generate exception and patcher stubs */
+       /* generate stubs */
 
-       emit_exception_stubs(jd);
        emit_patcher_stubs(jd);
 
-       codegen_finish(jd);
-
        /* everything's ok */
 
        return true;
index f0caa74ab6d8ea860c5994ce8242aa1aa2e81c9d..a287809a65c8adab58a1e2f28270243bca613de0 100644 (file)
@@ -1,6 +1,6 @@
 /* src/vm/jit/arm/codegen.h - code generation macros and definitions for ARM
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
    J. Wenninger, Institut f. Computersprachen - TU Wien
@@ -27,7 +27,7 @@
    Authors: Michael Starzinger
             Christian Thalinger
 
-   $Id: codegen.h 7511 2007-03-13 16:32:56Z michi $
+   $Id: codegen.h 7557 2007-03-22 21:40:54Z michi $
 
 */
 
 
 /* helper macros for generating code ******************************************/
 
-/* load_var_to_reg_xxx:
-   this function generates code to fetch data from a pseudo-register
-   into a real register. 
-   If the pseudo-register has actually been assigned to a real 
-   register, no code will be emitted, since following operations
-   can use this register directly.
-   v:      pseudoregister to be fetched from
-   tempnr: temporary register to be used if v is actually spilled to ram
-   regnr:  the register number, where the operand can be found after 
-           fetching (this wil be either tempregnum or the register
-           number allready given to v)
-*/
-
-#if defined(__ARMEL__)
-#define load_var_to_reg_lng(regnr,v,tempnr) { \
-       if ((v)->flags & INMEMORY) { \
-               COUNT_SPILLS; \
-               M_STACK_LOAD_LNG(tempnr, (v)->regoff); \
-               regnr = tempnr; \
-       } else if (GET_HIGH_REG((v)->regoff)==REG_SPLIT) { \
-               M_LDR_INTERN(GET_HIGH_REG(tempnr), REG_SP, 0); /* TODO: where to load? */ \
-               regnr = PACK_REGS(GET_LOW_REG((v)->regoff), GET_HIGH_REG(tempnr)); \
-       } else regnr = (v)->regoff; \
-}
-#else /* defined(__ARMEB__) */
-#define load_var_to_reg_lng(regnr,v,tempnr) { \
-        if ((v)->flags & INMEMORY) { \
-                COUNT_SPILLS; \
-                M_STACK_LOAD_LNG(tempnr, (v)->regoff); \
-                regnr = tempnr; \
-        } else if (GET_LOW_REG((v)->regoff)==REG_SPLIT) { \
-                M_LDR_INTERN(GET_LOW_REG(tempnr), REG_SP, 0); /* TODO: where to load? */ \
-                regnr = PACK_REGS(GET_LOW_REG(tempnr), GET_HIGH_REG((v)->regoff)); \
-        } else regnr = (v)->regoff; \
-}
-#endif
-
-
-/* store_reg_to_var_xxx:
-   This function generates the code to store the result of an operation
-   back into a spilled pseudo-variable.
-   If the pseudo-variable has not been spilled in the first place, this 
-   function will generate nothing.
-   v:      Pseudovariable
-   tempnr: Number of the temporary registers as returned by
-           reg_of_var.
-*/
-
-#if defined(__ARMEL__)
-#define store_reg_to_var_lng(v,tempnr) { \
-       if ((v)->flags & INMEMORY) { \
-               COUNT_SPILLS; \
-               M_STACK_STORE_LNG(tempnr, (v)->regoff); \
-       } else if (GET_HIGH_REG((v)->regoff)==REG_SPLIT) { \
-               M_STR_INTERN(GET_HIGH_REG(tempnr), REG_SP, 0); /* TODO: where to store? */ \
-       } \
-}
-#else /* defined(__ARMEB__) */
-#define store_reg_to_var_lng(v,tempnr) { \
-        if ((v)->flags & INMEMORY) { \
-                COUNT_SPILLS; \
-                M_STACK_STORE_LNG(tempnr, (v)->regoff); \
-        } else if (GET_LOW_REG((v)->regoff)==REG_SPLIT) { \
-                M_STR_INTERN(GET_LOW_REG(tempnr), REG_SP, 0); /* TODO: where to store? */ \
-        } \
-}
-#endif
-
 #if defined(__ARMEL__)
 #define SPLIT_OPEN(type, reg, tmpreg) \
        if (IS_2_WORD_TYPE(type) && GET_HIGH_REG(reg)==REG_SPLIT) { \
@@ -339,6 +271,15 @@ void asm_debug_intern(int a1, int a2, int a3, int a4);
     } while (0)
 
 
+/* undefined instruction used for hardware exceptions */
+
+#define M_UNDEFINED(cond,imm,n) \
+       do { \
+               *((u4 *) cd->mcodeptr) = ((cond) << 28) | (0x7f << 20) | (((imm) & 0x0fff) << 8) | (0x0f << 4) | (n); \
+               cd->mcodeptr += 4; \
+       } while (0)
+
+
 #if !defined(ENABLE_SOFTFLOAT)
 
 /* M_CPDO **********************************************************************
@@ -664,6 +605,12 @@ void asm_debug_intern(int a1, int a2, int a3, int a4);
 #define M_DMOV(a,b)        M_MVFD(b,a)
 
 
+#define M_TRAPEQ(a,i)      M_UNDEFINED(COND_EQ,i,a);
+#define M_TRAPLE(a,i)      M_UNDEFINED(COND_LE,i,a);
+#define M_TRAPHI(a,i)      M_UNDEFINED(COND_HI,i,a);
+#define M_TRAPHS(a,i)      M_UNDEFINED(COND_CS,i,a);
+
+
 /* if we do not have double-word load/store command, we can fake them */
 /* ATTENTION: the original LDRD/STRD of ARMv5e would always use (Rd/Rd+1),
    so these faked versions are more "powerful" */
@@ -1122,17 +1069,6 @@ do { \
                M_LDR_INTERN(REG_PC, REG_ITMP3, -(-(offset) & 0x0fff)); /*TODO: this looks ugly*/ \
        }
 
-/* M_STACK_LOAD/STORE:
-   loads or stores integer values from register to stack or from stack to register
-   ATTENTION: we use M_LDR and M_STR, so the same restrictions apply to us!
-*/
-
-#define M_STACK_LOAD_LNG(reg, offset) { \
-       CHECK_INT_REG(GET_LOW_REG(reg)); \
-       CHECK_INT_REG(GET_HIGH_REG(reg)); \
-       M_LDRD(reg, REG_SP, (offset) * 4); \
-}
-
 
 #define M_ILD(a,b,c)                    M_LDR(a,b,c)
 #define M_LLD(a,b,c)                    M_LDRD(a,b,c)
@@ -1172,57 +1108,6 @@ do { \
 #endif /* !defined(ENABLE_SOFTFLOAT) */
 
 
-/* function gen_resolvebranch **************************************************
-   ip ... pointer to instruction after branch (void*)
-   so ... offset of instruction after branch  (s4)
-   to ... offset of branch target             (s4) */
-
-#define gen_resolvebranch(ip,so,to) \
-       assert((((s4*) (ip))[-1] & 0x0e000000) == 0x0a000000); \
-       ((s4*) (ip))[-1] |= ((s4) (to) - (so) - 1) >> 2 & 0x0ffffff
-
-
-/* function gen_nullptr_check *************************************************/
-
-#define gen_nullptr_check_intern(objreg) { \
-       M_TST((objreg), (objreg)); \
-       M_BEQ(0); \
-       codegen_add_nullpointerexception_ref(cd); \
-}
-
-#define gen_nullptr_check(objreg) \
-       if (checknull) \
-               gen_nullptr_check_intern(objreg)
-
-
-/* function gen_div_check *****************************************************/
-
-#define gen_div_check(type,reg) \
-    do { \
-       if (IS_2_WORD_TYPE(type)) { \
-               M_TEQ_IMM(GET_LOW_REG(reg), 0); \
-               /* M_TEQ_EQ_IMM(GET_HIGH_REG(reg), 0) */ M_DAT(COND_EQ,0x09,0,GET_HIGH_REG(reg),1,1,0); \
-               M_BEQ(0); \
-       } else { \
-               M_TEQ_IMM((reg), 0); \
-               M_BEQ(0); \
-       } \
-       codegen_add_arithmeticexception_ref(cd); \
-    } while (0)
-
-/* function gen_bound_check ***************************************************
-   ATTENTION: uses REG_ITMP3 as intermediate register */
-/* TODO: maybe use another reg instead of REG_ITMP3! */
-
-#define gen_bound_check(arrayref,index) \
-       if (checkbounds) { \
-               M_LDR_INTERN(REG_ITMP3, (arrayref), OFFSET(java_arrayheader, size)); \
-               M_CMP((index), REG_ITMP3); \
-               M_BHS(0); \
-               codegen_add_arrayindexoutofboundsexception_ref(cd, index); \
-       }
-
-
 #endif /* _CODEGEN_H */
 
 
index 20e23d9ab90e64120fb7d2652e42661009f69353..7bcb3e7543d5b3e27a54b24c9d998bf80501a230 100644 (file)
@@ -44,6 +44,7 @@
 #endif
 
 #include "vm/builtin.h"
+#include "vm/exceptions.h"
 #include "vm/global.h"
 
 #include "vm/jit/asmpart.h"
@@ -338,6 +339,101 @@ void emit_iconst(codegendata *cd, s4 d, s4 value)
 }
 
 
+/* emit_branch *****************************************************************
+
+   Emits the code for conditional and unconditional branchs.
+
+*******************************************************************************/
+
+void emit_branch(codegendata *cd, s4 disp, s4 condition, s4 reg, u4 opt)
+{
+       s4 checkdisp;
+       s4 branchdisp;
+
+       /* calculate the different displacements */
+
+       checkdisp  = (disp - 8);
+       branchdisp = (disp - 8) >> 2;
+
+       /* check which branch to generate */
+
+       if (condition == BRANCH_UNCONDITIONAL) {
+               /* check displacement for overflow */
+
+               if ((checkdisp < (s4) 0xff000000) || (checkdisp > (s4) 0x00ffffff)) {
+                       /* if the long-branches flag isn't set yet, do it */
+
+                       if (!CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
+                               cd->flags |= (CODEGENDATA_FLAG_ERROR |
+                                                         CODEGENDATA_FLAG_LONGBRANCHES);
+                       }
+
+                       vm_abort("emit_branch: emit unconditional long-branch code");
+               }
+               else {
+                       M_B(branchdisp);
+               }
+       }
+       else {
+               /* and displacement for overflow */
+
+               if ((checkdisp < (s4) 0xff000000) || (checkdisp > (s4) 0x00ffffff)) {
+                       /* if the long-branches flag isn't set yet, do it */
+
+                       if (!CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
+                               cd->flags |= (CODEGENDATA_FLAG_ERROR |
+                                                         CODEGENDATA_FLAG_LONGBRANCHES);
+                       }
+
+                       vm_abort("emit_branch: emit conditional long-branch code");
+               }
+               else {
+                       switch (condition) {
+                       case BRANCH_EQ:
+                               M_BEQ(branchdisp);
+                               break;
+                       case BRANCH_NE:
+                               M_BNE(branchdisp);
+                               break;
+                       case BRANCH_LT:
+                               M_BLT(branchdisp);
+                               break;
+                       case BRANCH_GE:
+                               M_BGE(branchdisp);
+                               break;
+                       case BRANCH_GT:
+                               M_BGT(branchdisp);
+                               break;
+                       case BRANCH_LE:
+                               M_BLE(branchdisp);
+                               break;
+                       case BRANCH_UGT:
+                               M_BHI(branchdisp);
+                               break;
+                       default:
+                               vm_abort("emit_branch: unknown condition %d", condition);
+                       }
+               }
+       }
+}
+
+
+/* emit_arithmetic_check *******************************************************
+
+   Emit an ArithmeticException check.
+
+*******************************************************************************/
+
+void emit_arithmetic_check(codegendata *cd, instruction *iptr, s4 reg)
+{
+       if (INSTRUCTION_MUST_CHECK(iptr)) {
+               CHECK_INT_REG(reg);
+               M_TEQ_IMM(reg, 0);
+               M_TRAPEQ(0, EXCEPTION_HARDWARE_ARITHMETIC);
+       }
+}
+
+
 /* emit_nullpointer_check ******************************************************
 
    Emit a NullPointerException check.
@@ -348,11 +444,16 @@ void emit_nullpointer_check(codegendata *cd, instruction *iptr, s4 reg)
 {
        if (INSTRUCTION_MUST_CHECK(iptr)) {
                M_TST(reg, reg);
-               M_BEQ(0);
-               codegen_add_nullpointerexception_ref(cd);
+               M_TRAPEQ(0, EXCEPTION_HARDWARE_NULLPOINTER);
        }
 }
 
+void emit_nullpointer_check_force(codegendata *cd, instruction *iptr, s4 reg)
+{
+       M_TST(reg, reg);
+       M_TRAPEQ(0, EXCEPTION_HARDWARE_NULLPOINTER);
+}
+
 
 /* emit_arrayindexoutofbounds_check ********************************************
 
@@ -365,8 +466,50 @@ void emit_arrayindexoutofbounds_check(codegendata *cd, instruction *iptr, s4 s1,
        if (INSTRUCTION_MUST_CHECK(iptr)) {
                M_ILD_INTERN(REG_ITMP3, s1, OFFSET(java_arrayheader, size));
                M_CMP(s2, REG_ITMP3);
-               M_BHS(0);
-               codegen_add_arrayindexoutofboundsexception_ref(cd, s2);
+               M_TRAPHS(s2, EXCEPTION_HARDWARE_ARRAYINDEXOUTOFBOUNDS);
+       }
+}
+
+
+/* emit_classcast_check ********************************************************
+
+   Emit a ClassCastException check.
+
+*******************************************************************************/
+
+void emit_classcast_check(codegendata *cd, instruction *iptr, s4 condition, s4 reg, s4 s1)
+{
+       if (INSTRUCTION_MUST_CHECK(iptr)) {
+               switch (condition) {
+               case BRANCH_EQ:
+                       M_TRAPEQ(s1, EXCEPTION_HARDWARE_CLASSCAST);
+                       break;
+
+               case BRANCH_LE:
+                       M_TRAPLE(s1, EXCEPTION_HARDWARE_CLASSCAST);
+                       break;
+
+               case BRANCH_UGT:
+                       M_TRAPHI(s1, EXCEPTION_HARDWARE_CLASSCAST);
+                       break;
+
+               default:
+                       vm_abort("emit_classcast_check: unknown condition %d", condition);
+               }
+       }
+}
+
+/* emit_exception_check ********************************************************
+
+   Emit an Exception check.
+
+*******************************************************************************/
+
+void emit_exception_check(codegendata *cd, instruction *iptr)
+{
+       if (INSTRUCTION_MUST_CHECK(iptr)) {
+               M_TST(REG_RESULT, REG_RESULT);
+               M_TRAPEQ(0, EXCEPTION_HARDWARE_EXCEPTION);
        }
 }
 
@@ -377,6 +520,7 @@ void emit_arrayindexoutofbounds_check(codegendata *cd, instruction *iptr, s4 s1,
 
 *******************************************************************************/
 
+#if 0
 void emit_exception_stubs(jitdata *jd)
 {
        codegendata  *cd;
@@ -399,7 +543,7 @@ void emit_exception_stubs(jitdata *jd)
        for (er = cd->exceptionrefs; er != NULL; er = er->next) {
                /* back-patch the branch to this exception code */
 
-               branchmpc = er->branchpos;
+               branchmpc = er->branchmpc;
                targetmpc = cd->mcodeptr - cd->mcodebase;
 
                md_codegen_patch_branch(cd, branchmpc, targetmpc);
@@ -415,8 +559,8 @@ void emit_exception_stubs(jitdata *jd)
 
                /* calcuate exception address */
 
-               assert((er->branchpos - 4) % 4 == 0);
-               M_ADD_IMM_EXT_MUL4(REG_ITMP2_XPC, REG_PV, (er->branchpos - 4) / 4);
+               assert((er->branchmpc - 4) % 4 == 0);
+               M_ADD_IMM_EXT_MUL4(REG_ITMP2_XPC, REG_PV, (er->branchmpc - 4) / 4);
 
                /* move function to call into REG_ITMP3 */
 
@@ -473,6 +617,7 @@ void emit_exception_stubs(jitdata *jd)
                }
        }
 }
+#endif
 
 
 /* emit_patcher_stubs **********************************************************
index c47708555272c5ed50b355d4db94984efaf89a57..b169ff45436b5062379cf58d97dd5aa6aa6288ca 100644 (file)
@@ -1,6 +1,6 @@
-/* src/vm/jit/arm/linux/md.c - machine dependent arm linux functions
+/* src/vm/jit/arm/linux/md-os.c - machine dependent arm linux functions
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
    J. Wenninger, Institut f. Computersprachen - TU Wien
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Michael Starzinger
-            Christian Thalinger
-
    $Id: md.c 166 2006-01-22 23:38:44Z twisti $
 
 */
@@ -66,8 +61,7 @@ typedef struct ucontext {
 
 /* md_signal_handler_sigsegv ***************************************************
 
-   NullPointerException signal handler for hardware null pointer
-   check.
+   Signal handler for hardware exceptions.
 
 *******************************************************************************/
 
@@ -116,6 +110,60 @@ void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
 }
 
 
+/* md_signal_handler_sigill ****************************************************
+
+   Illegal Instruction signal handler for hardware exception checks.
+
+*******************************************************************************/
+
+void md_signal_handler_sigill(int sig, siginfo_t *siginfo, void *_p)
+{
+       ucontext_t        *_uc;
+       scontext_t        *_sc;
+       u1                *pv;
+       u1                *sp;
+       u1                *ra;
+       u1                *xpc;
+       u4                 mcode;
+       s4                 type;
+       ptrint             val;
+       java_objectheader *o;
+
+       _uc = (ucontext_t*) _p;
+       _sc = &_uc->uc_mcontext;
+
+       /* ATTENTION: glibc included messed up kernel headers we needed a
+          workaround for the ucontext structure. */
+
+       pv  = (u1*) _sc->arm_ip;
+       sp  = (u1*) _sc->arm_sp;
+       ra  = (u1*) _sc->arm_lr;                     /* this is correct for leafs */
+       xpc = (u1*) _sc->arm_pc;
+
+       /* get exception-throwing instruction */
+
+       mcode = *((u4 *) xpc);
+
+       /* check for undefined instruction we use */
+
+       if ((mcode & 0x0ff000f0) != 0x07f000f0)
+               vm_abort("md_signal_handler_sigill: unknown illegal instruction");
+
+       type = (mcode >> 8) & 0x0fff;
+       val  = *((s4 *) _sc + OFFSET(scontext_t, arm_r0)/4 + (mcode & 0x0f));
+
+       /* generate appropriate exception */
+
+       o = exceptions_new_hardware_exception(pv, sp, ra, xpc, type, val);
+
+       /* set registers */
+
+       _sc->arm_r10 = (ptrint) o;
+       _sc->arm_fp  = (ptrint) xpc;
+       _sc->arm_pc  = (ptrint) asm_handle_exception;
+}
+
+
 /* thread_restartcriticalsection ***********************************************
 
    TODO: document me
index 61d33173929bff6a4263fe4abda2e531cd1b8688..cfdbda40dd6ae00b3572b4ed103f11d3fef4693d 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: md.c 7504 2007-03-12 13:17:07Z twisti $
+   $Id: md.c 7540 2007-03-20 00:02:41Z michi $
 
 */
 
@@ -78,6 +78,10 @@ void md_codegen_patch_branch(codegendata *cd, s4 branchmpc, s4 targetmpc)
        if ((disp < (s4) 0xff000000) || (disp > (s4) 0x00ffffff))
                vm_abort("md_codegen_patch_branch: branch displacement out of range: %d > +/-%d", disp, 0x00ffffff);
 
+       /* sanity check: are we really patching a branch instruction */
+
+       assert((mcodeptr[-1] & 0x0e000000) == 0x0a000000);
+
        /* patch the branch instruction before the mcodeptr */
 
        mcodeptr[-1] |= (disp & 0x00ffffff);
index 128ac0431ee5b495c0b7be6ef435a073c5147cf8..e1e614ccf8e00507c91b8690ff41ec1e1ea46f5a 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: asmpart.h 7563 2007-03-23 21:33:53Z twisti $
+   $Id: asmpart.h 7577 2007-03-25 20:55:06Z twisti $
 
 */
 
@@ -95,6 +95,11 @@ float  asm_vm_call_method_float(methodinfo *m, s4 vmargscount, vm_arg *vmargs);
 double asm_vm_call_method_double(methodinfo *m, s4 vmargscount, vm_arg *vmargs);
 
 void   asm_vm_call_method_exception_handler(void);
+
+/* asm_vm_call_method_end is a dummy symbol marking the end of the asm_vm_call_method
+ * function and is used to insert the coderange into the avl tree.
+ */
+void   asm_vm_call_method_end(void);
 #endif
 
 #if defined(ENABLE_INTRP)
index f46d0d9cab33ec174a5b454e736fc4d823593f6f..4e5cf7cc1bfc629b41025d15fbaae720cc549c54 100644 (file)
@@ -39,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 7403 2007-02-25 21:31:58Z pm $
+   $Id: codegen-common.c 7576 2007-03-25 20:39:17Z ajordan $
 
 */
 
@@ -86,6 +86,7 @@
 #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"
@@ -98,9 +99,7 @@
 #include "vmcore/method.h"
 #include "vmcore/options.h"
 
-#if defined(ENABLE_STATISTICS)
 # include "vmcore/statistics.h"
-#endif
 
 
 /* in this tree we store all method addresses *********************************/
@@ -132,7 +131,7 @@ void codegen_init(void)
                mte = NEW(methodtree_element);
 
                mte->startpc = (u1 *) (ptrint) asm_vm_call_method;
-               mte->endpc   = (u1 *) ((ptrint) asm_call_jit_compiler - 1);
+               mte->endpc   = (u1 *) (ptrint) asm_vm_call_method_end;
 
                avl_insert(methodtree, mte);
 #endif /* defined(ENABLE_JIT) */
@@ -156,9 +155,13 @@ void codegen_setup(jitdata *jd)
        m  = jd->m;
        cd = jd->cd;
 
-       cd->mcodebase = DMNEW(u1, MCODEINITSIZE);
-       cd->mcodeend  = cd->mcodebase + MCODEINITSIZE;
-       cd->mcodesize = MCODEINITSIZE;
+       /* initialize members */
+
+       cd->flags        = 0;
+
+       cd->mcodebase    = DMNEW(u1, MCODEINITSIZE);
+       cd->mcodeend     = cd->mcodebase + MCODEINITSIZE;
+       cd->mcodesize    = MCODEINITSIZE;
 
        /* initialize mcode variables */
 
@@ -186,21 +189,19 @@ void codegen_setup(jitdata *jd)
 
        cd->jumpreferences = NULL;
 
-#if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(ENABLE_INTRP)
+#if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
        cd->datareferences = NULL;
 #endif
 
-       cd->exceptionrefs  = NULL;
 /*     cd->patchrefs      = list_create_dump(OFFSET(patchref, linkage)); */
        cd->patchrefs      = NULL;
+       cd->brancheslabel  = list_create_dump(OFFSET(branch_label_ref_t, linkage));
 
        cd->linenumberreferences = NULL;
        cd->linenumbertablesizepos = 0;
        cd->linenumbertablestartpos = 0;
        cd->linenumbertab = 0;
        
-       cd->method = m;
-
        cd->maxstack = m->maxstack;
 
 #if defined(ENABLE_THREADS)
@@ -210,6 +211,125 @@ void codegen_setup(jitdata *jd)
 }
 
 
+/* codegen_reset ***************************************************************
+
+   Resets the codegen data structure so we can recompile the method.
+
+*******************************************************************************/
+
+static void codegen_reset(jitdata *jd)
+{
+       codeinfo    *code;
+       codegendata *cd;
+       basicblock  *bptr;
+
+       /* get required compiler data */
+
+       code = jd->code;
+       cd   = jd->cd;
+
+       /* reset error flag */
+
+       cd->flags          &= ~CODEGENDATA_FLAG_ERROR;
+
+       /* reset some members, we reuse the code memory already allocated
+          as this should have almost the correct size */
+
+       cd->mcodeptr        = cd->mcodebase;
+       cd->lastmcodeptr    = cd->mcodebase;
+
+       cd->dseg            = NULL;
+       cd->dseglen         = 0;
+
+       cd->jumpreferences  = NULL;
+
+#if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
+       cd->datareferences  = NULL;
+#endif
+
+/*     cd->patchrefs       = list_create_dump(OFFSET(patchref, linkage)); */
+       cd->patchrefs       = NULL;
+       cd->brancheslabel   = list_create_dump(OFFSET(branch_label_ref_t, linkage));
+
+       cd->linenumberreferences    = NULL;
+       cd->linenumbertablesizepos  = 0;
+       cd->linenumbertablestartpos = 0;
+       cd->linenumbertab           = 0;
+       
+#if defined(ENABLE_THREADS)
+       cd->threadcritcurrent.next = NULL;
+       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_generate ************************************************************
+
+   Generates the code for the currently compiled method.
+
+*******************************************************************************/
+
+bool codegen_generate(jitdata *jd)
+{
+       codegendata *cd;
+
+       /* get required compiler data */
+
+       cd = jd->cd;
+
+       /* call the machine-dependent code generation function */
+
+       if (!codegen_emit(jd))
+               return false;
+
+       /* check for an error */
+
+       if (CODEGENDATA_HAS_FLAG_ERROR(cd)) {
+               /* check for long-branches flag, if it is set we recompile the
+                  method */
+               /* 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);
+               }
+       }
+
+       /* reallocate the memory and finish the code generation */
+
+       codegen_finish(jd);
+
+       /* everything's ok */
+
+       return true;
+}
+
+
 /* codegen_close ***************************************************************
 
    TODO
@@ -294,39 +414,26 @@ u1 *codegen_ncode_increase(codegendata *cd, u1 *ncodeptr)
 
 *******************************************************************************/
 
-void codegen_add_branch_ref(codegendata *cd, basicblock *target)
+void codegen_add_branch_ref(codegendata *cd, basicblock *target, s4 condition, s4 reg, u4 options)
 {
-       s4 branchmpc;
+       branchref *br;
+       s4         branchmpc;
+
+       STATISTICS(count_branches_unresolved++);
 
        /* calculate the mpc of the branch instruction */
 
        branchmpc = cd->mcodeptr - cd->mcodebase;
 
-#if defined(ENABLE_JIT)
-       /* Check if the target basicblock has already a start pc, so the
-          jump is backward and we can resolve it immediately. */
+       br = DNEW(branchref);
 
-       if ((target->mpc >= 0)
-# if defined(ENABLE_INTRP)
-               /* The interpreter uses absolute branches, so we do branch
-                  resolving after the code and data segment move. */
+       br->branchmpc = branchmpc;
+       br->condition = condition;
+       br->reg       = reg;
+       br->options   = options;
+       br->next      = target->branchrefs;
 
-               && !opt_intrp
-# endif
-               )
-       {
-               md_codegen_patch_branch(cd, branchmpc, target->mpc);
-       }
-       else
-#endif
-       {
-               branchref *br = DNEW(branchref);
-
-               br->branchpos = branchmpc;
-               br->next      = target->branchrefs;
-
-               target->branchrefs = br;
-       }
+       target->branchrefs = br;
 }
 
 
@@ -339,117 +446,66 @@ void codegen_add_branch_ref(codegendata *cd, basicblock *target)
 void codegen_resolve_branchrefs(codegendata *cd, basicblock *bptr)
 {
        branchref *br;
-       s4         branchmpc;
-       s4         targetmpc;
-
-       /* set target */
-
-       targetmpc = bptr->mpc;
-
-       for (br = bptr->branchrefs; br != NULL; br = br->next) {
-               branchmpc = br->branchpos;
-
-               md_codegen_patch_branch(cd, branchmpc, targetmpc);
-       }
-}
+       u1        *mcodeptr;
 
+       /* 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. */
 
-/* codegen_add_exception_ref ***************************************************
-
-   Prepends an exception branch to the list.
-
-*******************************************************************************/
-
-static void codegen_add_exception_ref(codegendata *cd, s4 reg,
-                                                                         functionptr function)
-{
-       s4            branchmpc;
-       exceptionref *er;
-
-       branchmpc = cd->mcodeptr - cd->mcodebase;
-
-       er = DNEW(exceptionref);
+       mcodeptr = cd->mcodeptr;
 
-       er->branchpos = branchmpc;
-       er->reg       = reg;
-       er->function  = function;
+       /* just to make sure */
 
-       er->next      = cd->exceptionrefs;
+       assert(bptr->mpc >= 0);
 
-       cd->exceptionrefs = er;
-}
-
-
-/* codegen_add_arithmeticexception_ref *****************************************
-
-   Adds an ArithmeticException branch to the list.
-
-*******************************************************************************/
-
-void codegen_add_arithmeticexception_ref(codegendata *cd)
-{
-       codegen_add_exception_ref(cd, -1, STACKTRACE_inline_arithmeticexception);
-}
-
-
-/* codegen_add_arrayindexoutofboundsexception_ref ******************************
-
-   Adds an ArrayIndexOutOfBoundsException branch to the list.
-
-*******************************************************************************/
-
-void codegen_add_arrayindexoutofboundsexception_ref(codegendata *cd, s4 reg)
-{
-       codegen_add_exception_ref(cd, reg,
-                                                         STACKTRACE_inline_arrayindexoutofboundsexception);
-}
+       for (br = bptr->branchrefs; br != NULL; br = br->next) {
+               /* temporary set the mcodeptr */
 
+               cd->mcodeptr = cd->mcodebase + br->branchmpc;
 
-/* codegen_add_arraystoreexception_ref *****************************************
+               /* emit_bccz and emit_branch emit the correct code, even if we
+                  pass condition == BRANCH_UNCONDITIONAL or reg == -1. */
 
-   Adds an ArrayStoreException branch to the list.
+               emit_bccz(cd, bptr, br->condition, br->reg, br->options);
+       }
 
-*******************************************************************************/
+       /* restore mcodeptr */
 
-void codegen_add_arraystoreexception_ref(codegendata *cd)
-{
-       codegen_add_exception_ref(cd, -1, STACKTRACE_inline_arraystoreexception);
+       cd->mcodeptr = mcodeptr;
 }
 
 
-/* codegen_add_classcastexception_ref ******************************************
+/* codegen_branch_label_add ****************************************************
 
-   Adds an ClassCastException branch to the list.
+   Append an branch to the label-branch list.
 
 *******************************************************************************/
 
-void codegen_add_classcastexception_ref(codegendata *cd, s4 reg)
+void codegen_branch_label_add(codegendata *cd, s4 label, s4 condition, s4 reg, u4 options)
 {
-       codegen_add_exception_ref(cd, reg, STACKTRACE_inline_classcastexception);
-}
-
-
-/* codegen_add_nullpointerexception_ref ****************************************
+       list               *list;
+       branch_label_ref_t *br;
+       s4                  mpc;
 
-   Adds an NullPointerException branch to the list.
+       /* get the label list */
 
-*******************************************************************************/
-
-void codegen_add_nullpointerexception_ref(codegendata *cd)
-{
-       codegen_add_exception_ref(cd, -1, STACKTRACE_inline_nullpointerexception);
-}
+       list = cd->brancheslabel;
+       
+       /* calculate the current mpc */
 
+       mpc = cd->mcodeptr - cd->mcodebase;
 
-/* codegen_add_fillinstacktrace_ref ********************************************
+       br = DNEW(branch_label_ref_t);
 
-   Adds a fillInStackTrace branch to the list.
+       br->mpc       = mpc;
+       br->label     = label;
+       br->condition = condition;
+       br->reg       = reg;
+       br->options   = options;
 
-*******************************************************************************/
+       /* add the branch to the list */
 
-void codegen_add_fillinstacktrace_ref(codegendata *cd)
-{
-       codegen_add_exception_ref(cd, -1, STACKTRACE_inline_fillInStackTrace);
+       list_add_last_unsynced(list, br);
 }
 
 
@@ -478,12 +534,10 @@ void codegen_add_patch_ref(codegendata *cd, functionptr patcher, voidptr ref,
        pr->next      = cd->patchrefs;
        cd->patchrefs = pr;
 
-#if defined(ENABLE_JIT) && (defined(__ALPHA__) || defined(__MIPS__) || defined(__POWERPC__) || defined(__SPARC_64__) || defined(__X86_64__) ||  defined(__S390__))
        /* Generate NOPs for opt_shownops. */
 
        if (opt_shownops)
                PATCHER_NOPS;
-#endif
 
 #if defined(ENABLE_JIT) && (defined(__I386__) || defined(__MIPS__) || defined(__X86_64__))
        /* On some architectures the patcher stub call instruction might
@@ -848,7 +902,7 @@ void codegen_finish(jitdata *jd)
 
        codegen_insertmethod(code->entrypoint, code->entrypoint + mcodelen);
 
-#if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(ENABLE_INTRP)
+#if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
        /* resolve data segment references */
 
        dseg_resolve_datareferences(jd);
index c23ceef8b2fc7889d4dea9ab2173707ffa9bf43a..606d122c34aaaf479be4e122307909b6c89f851d 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: codegen-common.h 7283 2007-02-04 19:41:14Z pm $
+   $Id: codegen-common.h 7579 2007-03-25 22:42:13Z twisti $
 
 */
 
@@ -34,6 +34,8 @@
 
 typedef struct codegen_critical_section_t codegen_critical_section_t;
 typedef struct codegendata                codegendata;
+typedef struct branchref                  branchref;
+typedef struct branch_label_ref_t         branch_label_ref_t;
 typedef struct jumpref                    jumpref;
 typedef struct dataref                    dataref;
 typedef struct exceptionref               exceptionref;
@@ -86,7 +88,18 @@ typedef struct linenumberref              linenumberref;
 #define BRANCH_GT               (ICMD_IFGT - ICMD_IFEQ)
 #define BRANCH_LE               (ICMD_IFLE - ICMD_IFEQ)
 
-#define BRANCH_NAN              256
+#define BRANCH_ULT              256
+#define BRANCH_ULE              257
+#define BRANCH_UGE              258
+#define BRANCH_UGT              259
+
+#define BRANCH_NAN              260
+
+
+/* common branch options ******************************************************/
+
+#define BRANCH_OPT_NONE         0
+
 
 
 /************************* critical sections  *********************************/
@@ -99,7 +112,10 @@ struct codegen_critical_section_t {
 };
 
 
+/* codegendata ****************************************************************/
+
 struct codegendata {
+       u4              flags;          /* code generator flags                   */
        u1             *mcodebase;      /* base pointer of code area              */
        u1             *mcodeend;       /* pointer to end of code area            */
        s4              mcodesize;      /* complete size of code area (bytes)     */
@@ -125,13 +141,13 @@ struct codegendata {
 
        jumpref        *jumpreferences; /* list of jumptable target addresses     */
 
-#if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(ENABLE_INTRP) || defined(__S390__)
+#if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP) || defined(__S390__)
        dataref        *datareferences; /* list of data segment references        */
 #endif
 
-       exceptionref   *exceptionrefs;  /* list of exception branches             */
 /*     list           *patchrefs; */
        patchref       *patchrefs;
+       list           *brancheslabel;
 
        linenumberref  *linenumberreferences; /* list of line numbers and the     */
                                        /* program counters of their first        */
@@ -155,6 +171,40 @@ struct codegendata {
 };
 
 
+#define CODEGENDATA_FLAG_ERROR           0x00000001
+#define CODEGENDATA_FLAG_LONGBRANCHES    0x00000002
+
+
+#define CODEGENDATA_HAS_FLAG_ERROR(cd) \
+    ((cd)->flags & CODEGENDATA_FLAG_ERROR)
+
+#define CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd) \
+    ((cd)->flags & CODEGENDATA_FLAG_LONGBRANCHES)
+
+
+/* branchref *****************************************************************/
+
+struct branchref {
+       s4         branchmpc;       /* patching position in code segment          */
+       s4         condition;       /* conditional branch condition               */
+       s4         reg;             /* register number to check                   */
+       u4         options;         /* branch options                             */
+       branchref *next;            /* next element in branchref list             */
+};
+
+
+/* branch_label_ref_t *********************************************************/
+
+struct branch_label_ref_t {
+       s4         mpc;             /* position in code segment                   */
+       s4         label;           /* label number                               */
+       s4         condition;       /* conditional branch condition               */
+       s4         reg;             /* register number to check                   */
+       u4         options;         /* branch options                             */
+       listnode   linkage;
+};
+
+
 /* jumpref ********************************************************************/
 
 struct jumpref {
@@ -172,16 +222,6 @@ struct dataref {
 };
 
 
-/* exceptionref ***************************************************************/
-
-struct exceptionref {
-       s4            branchpos;    /* patching position in code segment          */
-       s4            reg;          /* used for ArrayIndexOutOfBounds index reg   */
-       functionptr   function;     /* function pointer to generate exception     */
-       exceptionref *next;         /* next element in exceptionref list          */
-};
-
-
 /* patchref *******************************************************************/
 
 struct patchref {
@@ -227,6 +267,13 @@ struct methodtree_element {
 void codegen_init(void);
 void codegen_setup(jitdata *jd);
 
+bool codegen_generate(jitdata *jd);
+bool codegen_emit(jitdata *jd);
+
+#if defined(ENABLE_INTRP)
+bool intrp_codegen(jitdata *jd);
+#endif
+
 void codegen_close(void);
 
 void codegen_increase(codegendata *cd);
@@ -235,17 +282,10 @@ void codegen_increase(codegendata *cd);
 u1 *codegen_ncode_increase(codegendata *cd, u1 *ncodeptr);
 #endif
 
-void codegen_add_branch_ref(codegendata *cd, basicblock *target);
-/* XXX REMOVE ME: don't-break-trunk macro */
-#define codegen_addreference codegen_add_branch_ref
+void codegen_add_branch_ref(codegendata *cd, basicblock *target, s4 condition, s4 reg, u4 options);
 void codegen_resolve_branchrefs(codegendata *cd, basicblock *bptr);
 
-void codegen_add_arithmeticexception_ref(codegendata *cd);
-void codegen_add_arrayindexoutofboundsexception_ref(codegendata *cd, s4 reg);
-void codegen_add_arraystoreexception_ref(codegendata *cd);
-void codegen_add_classcastexception_ref(codegendata *cd, s4 reg);
-void codegen_add_nullpointerexception_ref(codegendata *cd);
-void codegen_add_fillinstacktrace_ref(codegendata *cd);
+void codegen_branch_label_add(codegendata *cd, s4 label, s4 condition, s4 reg, u4 options);
 
 
 void codegen_add_patch_ref(codegendata *cd, functionptr patcher, voidptr ref,
@@ -298,14 +338,7 @@ void codegen_threadcritstop(codegendata *cd, int offset);
 #endif
 
 /* machine dependent functions */
-void md_codegen_patch_branch(codegendata *cd, s4 branchmpc, s4 targetmpc);
-u1  *md_codegen_get_pv_from_pc(u1 *ra);
-
-bool codegen(jitdata *jd);
-
-#if defined(ENABLE_INTRP)
-bool intrp_codegen(jitdata *jd);
-#endif
+u1 *md_codegen_get_pv_from_pc(u1 *ra);
 
 #endif /* _CODEGEN_COMMON_H */
 
index 0371ca0a2278d4ec3500ace89192ca0f590ba5ee..fd269b175ac5bba3b7771e713080fbc64e1ad192 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: disass-common.c 7382 2007-02-21 20:24:01Z twisti $
+   $Id: disass-common.c 7436 2007-03-02 20:23:46Z tbfg $
 
 */
 
@@ -51,7 +51,7 @@ bool disass_initialized = false;
 /* We need this on i386 and x86_64 since we don't know the byte length
    of currently printed instructions.  512 bytes should be enough. */
 
-#if defined(__I386__) || defined(__X86_64__) || defined(__S390__)
+#if defined(__I386__) || defined(__X86_64__) || defined(__S390__) || defined(__M68K__)
 char disass_buf[512];
 s4   disass_len;
 #endif
@@ -90,7 +90,7 @@ void disass_printf(PTR p, const char *fmt, ...)
 
        va_start(ap, fmt);
 
-#if defined(__I386__) || defined(__X86_64__) || defined(__S390__)
+#if defined(__I386__) || defined(__X86_64__) || defined(__S390__) || defined(__M68K__)
        disass_len += vsprintf(disass_buf + disass_len, fmt, ap);
 #else
        vprintf(fmt, ap);
index 5cb3de9b04a0d2dbfb5fc7bb4cac0d658f5440da..c9b39a71aa4c9ba37886c0941ba8c27f04a7fbd4 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: disass.h 7331 2007-02-11 21:41:19Z twisti $
+   $Id: disass.h 7436 2007-03-02 20:23:46Z tbfg $
 
 */
 
@@ -88,7 +88,7 @@ extern disassemble_info info;
 extern bool disass_initialized;
 #endif
 
-#if defined(__I386__) || defined(__X86_64__) || defined(__S390__)
+#if defined(__I386__) || defined(__X86_64__) || defined(__S390__) || defined(__M68K__)
 extern char disass_buf[512];
 extern s4   disass_len;
 #endif
index 9a2d3b2e6a5a9ae5ee8f4eca5e25760412ef768b..b309c0034c07fe5dd97601218cd3380c39f7ba69 100644 (file)
@@ -30,7 +30,7 @@
             Joseph Wenninger
             Edwin Steiner
 
-   $Id: dseg.c 7283 2007-02-04 19:41:14Z pm $
+   $Id: dseg.c 7556 2007-03-22 16:42:00Z tbfg $
 
 */
 
@@ -854,7 +854,7 @@ s4 dseg_get_linenumber_from_pc(methodinfo **pm, u1 *pv, u1 *pc)
 
 *******************************************************************************/
 
-#if defined(__I386__) || defined(__X86_64__) || defined(__S390__) || defined(__XDSPCORE__) || defined(ENABLE_INTRP)
+#if defined(__I386__) || defined(__X86_64__) || defined(__S390__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
 void dseg_adddata(codegendata *cd)
 {
        dataref *dr;
@@ -875,7 +875,7 @@ void dseg_adddata(codegendata *cd)
 
 *******************************************************************************/
 
-#if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(ENABLE_INTRP)
+#if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
 void dseg_resolve_datareferences(jitdata *jd)
 {
        codeinfo    *code;
index e0f6a9d4f08c79676b6d2d8838fce71a99eff94e..0181150c939717e8a926700e6a60646719663660 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: dseg.h 7246 2007-01-29 18:49:05Z twisti $
+   $Id: dseg.h 7556 2007-03-22 16:42:00Z tbfg $
 
 */
 
@@ -122,7 +122,7 @@ void dseg_createlinenumbertable(codegendata *cd);
 
 s4 dseg_get_linenumber_from_pc(methodinfo **pm, u1 *pv, u1 *pc);
 
-#if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(ENABLE_INTRP)
+#if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K___) || defined(ENABLE_INTRP)
 void dseg_adddata(codegendata *cd);
 void dseg_resolve_datareferences(jitdata *jd);
 #endif
index 2810994f58a5973d3e900710a3f99c6defff4091..243109adc6b2754a6c65a1b6fc428d252d8094de 100644 (file)
@@ -33,6 +33,7 @@
 
 #include "vm/types.h"
 
+#include "arch.h"
 #include "codegen.h"
 
 #include "vm/jit/emit-common.h"
@@ -246,13 +247,14 @@ void emit_store_dst(jitdata *jd, instruction *iptr, s4 d)
 }
 
 
-/* emit_bxx ********************************************************************
+/* emit_bccz *******************************************************************
 
-   Wrappers for conditional branch instructions.
+   Emit conditional and unconditional branch instructions on integer
+   regiseters.
 
 *******************************************************************************/
 
-void emit_bc(codegendata *cd, basicblock *target, s4 condition)
+void emit_bccz(codegendata *cd, basicblock *target, s4 condition, s4 reg, u4 options)
 {
        s4 branchmpc;
        s4 disp;
@@ -268,90 +270,379 @@ void emit_bc(codegendata *cd, basicblock *target, s4 condition)
                branchmpc = cd->mcodeptr - cd->mcodebase;
                disp      = target->mpc - branchmpc;
 
-#if 0
-               emit_branch(cd, disp, condition);
-#endif
+               emit_branch(cd, disp, condition, reg, options);
        }
        else {
                /* current mcodeptr is the correct position,
                   afterwards emit the NOPs */
 
-#if 0
-               codegen_add_branch_ref(cd, target, condition);
-#endif
+               codegen_add_branch_ref(cd, target, condition, reg, options);
 
                /* generate NOPs as placeholder for branch code */
-               /* XXX if recompile-with-long-branches */
 
                BRANCH_NOPS;
        }
 }
 
 
+/* emit_bcc ********************************************************************
+
+   Emit conditional and unconditional branch instructions on condition
+   codes.
+
+*******************************************************************************/
+
+void emit_bcc(codegendata *cd, basicblock *target, s4 condition, u4 options)
+{
+       emit_bccz(cd, target, condition, -1, options);
+}
+
+
+/* emit_br *********************************************************************
+
+   Wrapper for unconditional branches.
+
+*******************************************************************************/
+
 void emit_br(codegendata *cd, basicblock *target)
 {
-       emit_bc(cd, target, BRANCH_UNCONDITIONAL);
+       emit_bcc(cd, target, BRANCH_UNCONDITIONAL, BRANCH_OPT_NONE);
 }
 
 
-void emit_beq(codegendata *cd, basicblock *target)
+/* emit_bxxz *******************************************************************
+
+   Wrappers for branches on one integer register.
+
+*******************************************************************************/
+
+#if SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER
+
+void emit_beqz(codegendata *cd, basicblock *target, s4 reg)
+{
+       emit_bccz(cd, target, BRANCH_EQ, reg, BRANCH_OPT_NONE);
+}
+
+void emit_bnez(codegendata *cd, basicblock *target, s4 reg)
 {
-       emit_bc(cd, target, BRANCH_EQ);
+       emit_bccz(cd, target, BRANCH_NE, reg, BRANCH_OPT_NONE);
 }
 
+void emit_bltz(codegendata *cd, basicblock *target, s4 reg)
+{
+       emit_bccz(cd, target, BRANCH_LT, reg, BRANCH_OPT_NONE);
+}
 
-void emit_bne(codegendata *cd, basicblock *target)
+void emit_bgez(codegendata *cd, basicblock *target, s4 reg)
 {
-       emit_bc(cd, target, BRANCH_NE);
+       emit_bccz(cd, target, BRANCH_GE, reg, BRANCH_OPT_NONE);
 }
 
+void emit_bgtz(codegendata *cd, basicblock *target, s4 reg)
+{
+       emit_bccz(cd, target, BRANCH_GT, reg, BRANCH_OPT_NONE);
+}
 
-void emit_blt(codegendata *cd, basicblock *target)
+void emit_blez(codegendata *cd, basicblock *target, s4 reg)
 {
-       emit_bc(cd, target, BRANCH_LT);
+       emit_bccz(cd, target, BRANCH_LE, reg, BRANCH_OPT_NONE);
 }
 
+#endif /* SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER */
 
-void emit_bge(codegendata *cd, basicblock *target)
+
+/* emit_bxx ********************************************************************
+
+   Wrappers for branches on two integer registers.
+
+   We use PACK_REGS here, so we don't have to change the branchref
+   data structure and the emit_bccz function.
+
+*******************************************************************************/
+
+#if SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS
+
+void emit_beq(codegendata *cd, basicblock *target, s4 s1, s4 s2)
 {
-       emit_bc(cd, target, BRANCH_GE);
+       emit_bccz(cd, target, BRANCH_EQ, PACK_REGS(s1, s2), BRANCH_OPT_NONE);
 }
 
+void emit_bne(codegendata *cd, basicblock *target, s4 s1, s4 s2)
+{
+       emit_bccz(cd, target, BRANCH_NE, PACK_REGS(s1, s2), BRANCH_OPT_NONE);
+}
 
-void emit_bgt(codegendata *cd, basicblock *target)
+#endif /* SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS */
+
+
+/* emit_bxx ********************************************************************
+
+   Wrappers for branches on condition codes.
+
+*******************************************************************************/
+
+#if SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER
+
+void emit_beq(codegendata *cd, basicblock *target)
+{
+       emit_bcc(cd, target, BRANCH_EQ, BRANCH_OPT_NONE);
+}
+
+void emit_bne(codegendata *cd, basicblock *target)
 {
-       emit_bc(cd, target, BRANCH_GT);
+       emit_bcc(cd, target, BRANCH_NE, BRANCH_OPT_NONE);
 }
 
+void emit_blt(codegendata *cd, basicblock *target)
+{
+       emit_bcc(cd, target, BRANCH_LT, BRANCH_OPT_NONE);
+}
+
+void emit_bge(codegendata *cd, basicblock *target)
+{
+       emit_bcc(cd, target, BRANCH_GE, BRANCH_OPT_NONE);
+}
+
+void emit_bgt(codegendata *cd, basicblock *target)
+{
+       emit_bcc(cd, target, BRANCH_GT, BRANCH_OPT_NONE);
+}
 
 void emit_ble(codegendata *cd, basicblock *target)
 {
-       emit_bc(cd, target, BRANCH_LE);
+       emit_bcc(cd, target, BRANCH_LE, BRANCH_OPT_NONE);
 }
 
+#if SUPPORT_BRANCH_CONDITIONAL_UNSIGNED_CONDITIONS
+void emit_bult(codegendata *cd, basicblock *target)
+{
+       emit_bcc(cd, target, BRANCH_ULT, BRANCH_OPT_NONE);
+}
 
+void emit_bule(codegendata *cd, basicblock *target)
+{
+       emit_bcc(cd, target, BRANCH_ULE, BRANCH_OPT_NONE);
+}
+
+void emit_buge(codegendata *cd, basicblock *target)
+{
+       emit_bcc(cd, target, BRANCH_UGE, BRANCH_OPT_NONE);
+}
+
+void emit_bugt(codegendata *cd, basicblock *target)
+{
+       emit_bcc(cd, target, BRANCH_UGT, BRANCH_OPT_NONE);
+}
+#endif
+
+#if defined(__POWERPC__) || defined(__POWERPC64__)
 void emit_bnan(codegendata *cd, basicblock *target)
 {
-       emit_bc(cd, target, BRANCH_NAN);
+       emit_bcc(cd, target, BRANCH_NAN, BRANCH_OPT_NONE);
+}
+#endif
+
+#endif /* SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER */
+
+
+/* emit_label_bccz *************************************************************
+
+   Emit a branch to a label.  Possibly emit the branch, if it is a
+   backward branch.
+
+*******************************************************************************/
+
+void emit_label_bccz(codegendata *cd, s4 label, s4 condition, s4 reg, u4 options)
+{
+       list               *list;
+       branch_label_ref_t *br;
+       s4                  mpc;
+       s4                  disp;
+
+       /* get the label list */
+
+       list = cd->brancheslabel;
+
+       /* search if the label is already in the list */
+
+       for (br = list_first_unsynced(list); br != NULL;
+                br = list_next_unsynced(list, br)) {
+               /* is this entry the correct label? */
+
+               if (br->label == label)
+                       break;
+       }
+
+       /* a branch reference was found */
+
+       if (br != NULL) {
+               /* calculate the mpc of the branch instruction */
+
+               mpc  = cd->mcodeptr - cd->mcodebase;
+               disp = br->mpc - mpc;
+
+               emit_branch(cd, disp, condition, reg, options);
+
+               /* now remove the branch reference */
+
+               list_remove_unsynced(list, br);
+       }
+       else {
+               /* current mcodeptr is the correct position,
+                  afterwards emit the NOPs */
+
+               codegen_branch_label_add(cd, label, condition, reg, options);
+
+               /* generate NOPs as placeholder for branch code */
+
+               BRANCH_NOPS;
+       }
 }
 
 
-/* emit_array_checks ***********************************************************
+/* emit_label ******************************************************************
 
-   Emit exception checks for array accesses, if they need to be
-   emitted.
+   Emit a label for a branch.  Possibly emit the branch, if it is a
+   forward branch.
 
 *******************************************************************************/
 
-void emit_array_checks(codegendata *cd, instruction *iptr, s4 s1, s4 s2)
+void emit_label(codegendata *cd, s4 label)
 {
-       if (INSTRUCTION_MUST_CHECK(iptr)) {
-               emit_nullpointer_check(cd, iptr, s1);
-               emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
+       list               *list;
+       branch_label_ref_t *br;
+       s4                  mpc;
+       s4                  disp;
+       u1                 *mcodeptr;
+
+       /* get the label list */
+
+       list = cd->brancheslabel;
+
+       /* search if the label is already in the list */
+
+       for (br = list_first_unsynced(list); br != NULL;
+                br = list_next_unsynced(list, br)) {
+               /* is this entry the correct label? */
+
+               if (br->label == label)
+                       break;
+       }
+
+       /* a branch reference was found */
+
+       if (br != NULL) {
+               /* calculate the mpc of the branch instruction */
+
+               mpc  = cd->mcodeptr - cd->mcodebase;
+               disp = mpc - br->mpc;
+
+               /* temporary set the mcodeptr */
+
+               mcodeptr     = cd->mcodeptr;
+               cd->mcodeptr = cd->mcodebase + br->mpc;
+
+               emit_branch(cd, disp, br->condition, br->reg, br->options);
+
+               /* restore mcodeptr */
+
+               cd->mcodeptr = mcodeptr;
+
+               /* now remove the branch reference */
+
+               list_remove_unsynced(list, br);
+       }
+       else {
+               /* add the label to the list (use invalid values for condition
+                  and register) */
+
+               codegen_branch_label_add(cd, label, -1, -1, BRANCH_OPT_NONE );
        }
 }
 
 
+/* emit_label_bcc **************************************************************
+
+   Emit conditional and unconditional label-branch instructions on
+   condition codes.
+
+*******************************************************************************/
+
+void emit_label_bcc(codegendata *cd, s4 label, s4 condition, u4 options)
+{
+       emit_label_bccz(cd, label, condition, -1, options);
+}
+
+
+/* emit_label_br ***************************************************************
+
+   Wrapper for unconditional label-branches.
+
+*******************************************************************************/
+
+void emit_label_br(codegendata *cd, s4 label)
+{
+       emit_label_bcc(cd, label, BRANCH_UNCONDITIONAL, BRANCH_OPT_NONE);
+}
+
+
+/* emit_label_bxxz *************************************************************
+
+   Wrappers for label-branches on one integer register.
+
+*******************************************************************************/
+
+#if SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER
+
+void emit_label_beqz(codegendata *cd, s4 label, s4 reg)
+{
+       emit_label_bccz(cd, label, BRANCH_EQ, reg, BRANCH_OPT_NONE);
+}
+
+#endif /* SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER */
+
+
+/* emit_label_bxx **************************************************************
+
+   Wrappers for label-branches on condition codes.
+
+*******************************************************************************/
+
+#if SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER
+
+void emit_label_beq(codegendata *cd, s4 label)
+{
+       emit_label_bcc(cd, label, BRANCH_EQ, BRANCH_OPT_NONE);
+}
+
+void emit_label_bne(codegendata *cd, s4 label)
+{
+       emit_label_bcc(cd, label, BRANCH_NE, BRANCH_OPT_NONE);
+}
+
+void emit_label_blt(codegendata *cd, s4 label)
+{
+       emit_label_bcc(cd, label, BRANCH_LT, BRANCH_OPT_NONE);
+}
+
+void emit_label_bge(codegendata *cd, s4 label)
+{
+       emit_label_bcc(cd, label, BRANCH_GE, BRANCH_OPT_NONE);
+}
+
+void emit_label_bgt(codegendata *cd, s4 label)
+{
+       emit_label_bcc(cd, label, BRANCH_GT, BRANCH_OPT_NONE);
+}
+
+void emit_label_ble(codegendata *cd, s4 label)
+{
+       emit_label_bcc(cd, label, BRANCH_LE, BRANCH_OPT_NONE);
+}
+
+#endif /* SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER */
+
+
 /*
  * These are local overrides for various environment variables in Emacs.
  * Please do not remove this and leave it at the end of the file, where
index a3f0cac0f41a8c4b4f72d65d5c723696bc09a9be..61681eefec65b498de4fd0c47660aa0c9d1f2ebf 100644 (file)
 #include "config.h"
 #include "vm/types.h"
 
+#include "arch.h"
+
 #include "vm/jit/codegen-common.h"
 #include "vm/jit/jit.h"
 
 
+/* branch labels **************************************************************/
+
+#define BRANCH_LABEL_1    1
+#define BRANCH_LABEL_2    2
+#define BRANCH_LABEL_3    3
+#define BRANCH_LABEL_4    4
+#define BRANCH_LABEL_5    5
+
+
 /* constant range macros ******************************************************/
 
 #if SIZEOF_VOID_P == 8
@@ -90,30 +101,82 @@ void emit_copy(jitdata *jd, instruction *iptr, varinfo *src, varinfo *dst);
 void emit_iconst(codegendata *cd, s4 d, s4 value);
 void emit_lconst(codegendata *cd, s4 d, s8 value);
 
+/* branch-emitting functions */
+void emit_bccz(codegendata *cd, basicblock *target, s4 condition, s4 reg, u4 options);
+void emit_bcc(codegendata *cd, basicblock *target, s4 condition, u4 options);
+
+/* wrapper for unconditional branches */
 void emit_br(codegendata *cd, basicblock *target);
-void emit_bc(codegendata *cd, basicblock *target, s4 condition);
 
+/* wrappers for branches on one integer register */
+
+#if SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER
+void emit_beqz(codegendata *cd, basicblock *target, s4 reg);
+void emit_bnez(codegendata *cd, basicblock *target, s4 reg);
+void emit_bltz(codegendata *cd, basicblock *target, s4 reg);
+void emit_bgez(codegendata *cd, basicblock *target, s4 reg);
+void emit_bgtz(codegendata *cd, basicblock *target, s4 reg);
+void emit_blez(codegendata *cd, basicblock *target, s4 reg);
+#endif
+
+/* wrappers for branches on two integer registers */
+
+#if SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS
+void emit_beq(codegendata *cd, basicblock *target, s4 s1, s4 s2);
+void emit_bne(codegendata *cd, basicblock *target, s4 s1, s4 s2);
+#endif
+
+/* wrappers for branches on condition codes */
+
+#if SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER
 void emit_beq(codegendata *cd, basicblock *target);
 void emit_bne(codegendata *cd, basicblock *target);
 void emit_blt(codegendata *cd, basicblock *target);
 void emit_bge(codegendata *cd, basicblock *target);
 void emit_bgt(codegendata *cd, basicblock *target);
 void emit_ble(codegendata *cd, basicblock *target);
+#endif
+
+#if SUPPORT_BRANCH_CONDITIONAL_UNSIGNED_CONDITIONS
+void emit_bult(codegendata *cd, basicblock *target);
+void emit_bule(codegendata *cd, basicblock *target);
+void emit_buge(codegendata *cd, basicblock *target);
+void emit_bugt(codegendata *cd, basicblock *target);
+#endif
 
+#if defined(__POWERPC__)
 void emit_bnan(codegendata *cd, basicblock *target);
+#endif
+
+/* label-branches */
+void emit_label_bccz(codegendata *cd, s4 label, s4 condition, s4 reg, u4 options);
+void emit_label(codegendata *cd, s4 label);
+void emit_label_bcc(codegendata *cd, s4 label, s4 condition, u4 options);
 
-void emit_branch(codegendata *cd, s4 disp, s4 condition);
+void emit_label_br(codegendata *cd, s4 label);
+
+#if SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER
+void emit_label_beqz(codegendata *cd, s4 label, s4 reg);
+#endif
+
+#if SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER
+void emit_label_beq(codegendata *cd, s4 label);
+void emit_label_bne(codegendata *cd, s4 label);
+void emit_label_blt(codegendata *cd, s4 label);
+void emit_label_bge(codegendata *cd, s4 label);
+void emit_label_bgt(codegendata *cd, s4 label);
+void emit_label_ble(codegendata *cd, s4 label);
+#endif
+
+/* machine dependent branch-emitting function */
+void emit_branch(codegendata *cd, s4 disp, s4 condition, s4 reg, u4 options);
 
 void emit_arithmetic_check(codegendata *cd, instruction *iptr, s4 reg);
 void emit_arrayindexoutofbounds_check(codegendata *cd, instruction *iptr, s4 s1, s4 s2);
-void emit_arraystore_check(codegendata *cd, instruction *iptr, s4 reg);
 void emit_classcast_check(codegendata *cd, instruction *iptr, s4 condition, s4 reg, s4 s1);
 void emit_nullpointer_check(codegendata *cd, instruction *iptr, s4 reg);
 void emit_exception_check(codegendata *cd, instruction *iptr);
 
-void emit_array_checks(codegendata *cd, instruction *iptr, s4 s1, s4 s2);
-
-void emit_exception_stubs(jitdata *jd);
 void emit_patcher_stubs(jitdata *jd);
 #if defined(ENABLE_REPLACEMENT)
 void emit_replacement_stubs(jitdata *jd);
index 05472fef387baa0a4a8c132da4f019923d3ff6db..d5c677e53994d540ac8405150a2162a01a96aff8 100644 (file)
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Christian Thalinger
-
-   $Id: arch.h 7241 2007-01-27 15:52:01Z twisti $
+   $Id: arch.h 7571 2007-03-24 22:37:09Z twisti $
 
 */
 
 /* define SUPPORT_COMBINE_INTEGER_REGISTERS */
 
 
+/* branches *******************************************************************/
+
+#define SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER       1
+#define SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER     0
+#define SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS    0
+#define SUPPORT_BRANCH_CONDITIONAL_UNSIGNED_CONDITIONS      1
+
+
 /* exceptions *****************************************************************/
 
 #define SUPPORT_HARDWARE_DIVIDE_BY_ZERO  1
index 92f75974ef7cdd67ef3d2a6a6d9870ac88bb2068..4d4c8f6c2366b5b7071b28ca743c0e6f372d6637 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: asmpart.S 7310 2007-02-09 13:00:04Z twisti $
+   $Id: asmpart.S 7454 2007-03-05 15:40:48Z tbfg $
 
 */
 
@@ -52,6 +52,7 @@
        .globl asm_vm_call_method_float
        .globl asm_vm_call_method_double
        .globl asm_vm_call_method_exception_handler
+       .globl asm_vm_call_method_end
 
        .globl asm_call_jit_compiler
        .globl asm_handle_nat_exception
@@ -230,6 +231,7 @@ asm_vm_call_method_exception_handler:
        push    xptr                        /* pass exception pointer             */
        call    builtin_throw_exception
        add     $4,sp
+asm_vm_call_method_end:
        jmp     L_asm_vm_call_method_return
 
 
index c1b6637eb7238a62f9bb355ab06ad4cfb291abfb..6528c0a02f576171802ba448d0a183caa0eb3a17 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: codegen.c 7513 2007-03-13 20:31:23Z twisti $
+   $Id: codegen.c 7579 2007-03-25 22:42:13Z twisti $
 
 */
 
@@ -76,7 +76,7 @@
 #include "vmcore/utf8.h"
 
 
-/* codegen *********************************************************************
+/* codegen_emit ****************************************************************
 
    Generates machine code.
 
@@ -88,7 +88,7 @@ void cg_move(codegendata *cd, s4 type, s4 src_regoff, s4 src_flags,
 void codegen_insert_phi_moves(jitdata *jd, basicblock *bptr);
 #endif
 
-bool codegen(jitdata *jd)
+bool codegen_emit(jitdata *jd)
 {
        methodinfo         *m;
        codeinfo           *code;
@@ -103,8 +103,10 @@ bool codegen(jitdata *jd)
        methodinfo         *lm;             /* local methodinfo for ICMD_INVOKE*  */
        builtintable_entry *bte;
        methoddesc         *md;
-       s4                 fieldtype;
-       s4                 varindex;
+       fieldinfo          *fi;
+       unresolved_field   *uf;
+       s4                  fieldtype;
+       s4                  varindex;
 #if defined(ENABLE_SSA)
        lsradata *ls;
        bool last_cmd_was_goto;
@@ -377,8 +379,8 @@ bool codegen(jitdata *jd)
                else {
                        M_ALD(REG_ITMP1, REG_SP, cd->stackframesize * 4 + 4);
                        M_TEST(REG_ITMP1);
-                       M_BEQ(0);
-                       codegen_add_nullpointerexception_ref(cd);
+                       M_BNE(6);
+                       M_ALD_MEM(REG_ITMP1, EXCEPTION_HARDWARE_NULLPOINTER);
                }
 
                M_AST(REG_ITMP1, REG_SP, s1 * 4);
@@ -626,10 +628,6 @@ bool codegen(jitdata *jd)
                                codegen_addpatchref(cd, PATCHER_aconst,
                                                                        iptr->sx.val.c.ref, 0);
 
-                               if (opt_showdisassemble) {
-                                       M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
-                               }
-
                                M_MOV_IMM(NULL, d);
 
                        } else {
@@ -1920,7 +1918,7 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
-                       emit_nullpointer_check(cd, iptr, s1);
+                       /* implicit null-pointer check */
                        M_ILD(d, s1, OFFSET(java_arrayheader, size));
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1930,7 +1928,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        emit_movsbl_memindex_reg(cd, OFFSET(java_bytearray, data[0]), 
                                                                         s1, s2, 0, d);
                        emit_store_dst(jd, iptr, d);
@@ -1941,7 +1940,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        emit_movzwl_memindex_reg(cd, OFFSET(java_chararray, data[0]), 
                                                                         s1, s2, 1, d);
                        emit_store_dst(jd, iptr, d);
@@ -1952,7 +1952,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        emit_movswl_memindex_reg(cd, OFFSET(java_shortarray, data[0]), 
                                                                         s1, s2, 1, d);
                        emit_store_dst(jd, iptr, d);
@@ -1963,7 +1964,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        emit_mov_memindex_reg(cd, OFFSET(java_intarray, data[0]), 
                                                                  s1, s2, 2, d);
                        emit_store_dst(jd, iptr, d);
@@ -1974,7 +1976,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
 
                        var = VAROP(iptr->dst);
 
@@ -1992,7 +1995,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        emit_flds_memindex(cd, OFFSET(java_floatarray, data[0]), s1, s2, 2);
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -2002,7 +2006,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        emit_fldl_memindex(cd, OFFSET(java_doublearray, data[0]), s1, s2,3);
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -2012,7 +2017,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        emit_mov_memindex_reg(cd, OFFSET(java_objectarray, data[0]),
                                                                  s1, s2, 2, d);
                        emit_store_dst(jd, iptr, d);
@@ -2023,7 +2029,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
                        if (s3 >= EBP) { 
                                /* because EBP, ESI, EDI have no xH and xL nibbles */
@@ -2038,7 +2045,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
                        emit_movw_reg_memindex(cd, s3, OFFSET(java_chararray, data[0]),
                                                                   s1, s2, 1);
@@ -2048,7 +2056,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
                        emit_movw_reg_memindex(cd, s3, OFFSET(java_shortarray, data[0]),
                                                                   s1, s2, 1);
@@ -2058,7 +2067,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
                        emit_mov_reg_memindex(cd, s3, OFFSET(java_intarray, data[0]),
                                                                  s1, s2, 2);
@@ -2068,7 +2078,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
 
                        var = VAROP(iptr->sx.s23.s3);
 
@@ -2085,7 +2096,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_FTMP1);
                        emit_fstps_memindex(cd, OFFSET(java_floatarray, data[0]), s1, s2,2);
                        break;
@@ -2094,7 +2106,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_FTMP1);
                        emit_fstpl_memindex(cd, OFFSET(java_doublearray, data[0]),
                                                                s1, s2, 3);
@@ -2104,16 +2117,15 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
 
                        M_AST(s1, REG_SP, 0 * 4);
                        M_AST(s3, REG_SP, 1 * 4);
                        M_MOV_IMM(BUILTIN_canstore, REG_ITMP1);
                        M_CALL(REG_ITMP1);
-                       M_TEST(REG_RESULT);
-                       M_BEQ(0);
-                       codegen_add_arraystoreexception_ref(cd);
+                       emit_exception_check(cd, iptr);
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
@@ -2126,7 +2138,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        emit_movb_imm_memindex(cd, iptr->sx.s23.s3.constval,
                                                                   OFFSET(java_bytearray, data[0]), s1, s2, 0);
                        break;
@@ -2135,7 +2148,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        emit_movw_imm_memindex(cd, iptr->sx.s23.s3.constval,
                                                                   OFFSET(java_chararray, data[0]), s1, s2, 1);
                        break;
@@ -2144,7 +2158,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        emit_movw_imm_memindex(cd, iptr->sx.s23.s3.constval,
                                                                   OFFSET(java_shortarray, data[0]), s1, s2, 1);
                        break;
@@ -2153,7 +2168,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        emit_mov_imm_memindex(cd, iptr->sx.s23.s3.constval,
                                                                  OFFSET(java_intarray, data[0]), s1, s2, 2);
                        break;
@@ -2162,7 +2178,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        emit_mov_imm_memindex(cd, 
                                                   (u4) (iptr->sx.s23.s3.constval & 0x00000000ffffffff),
                                                   OFFSET(java_longarray, data[0]), s1, s2, 3);
@@ -2175,7 +2192,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        emit_mov_imm_memindex(cd, 0, 
                                                                  OFFSET(java_objectarray, data[0]), s1, s2, 2);
                        break;
@@ -2184,34 +2202,20 @@ bool codegen(jitdata *jd)
                case ICMD_GETSTATIC:  /* ...  ==> ..., value                          */
 
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
-                               unresolved_field *uf = iptr->sx.s23.s3.uf;
-
+                               uf        = iptr->sx.s23.s3.uf;
                                fieldtype = uf->fieldref->parseddesc.fd->type;
+                               disp      = 0;
 
-                               codegen_addpatchref(cd, PATCHER_get_putstatic,
-                                                                       iptr->sx.s23.s3.uf, 0);
-
-                               if (opt_showdisassemble) {
-                                       M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
-                               }
-
-                               disp = 0;
+                               codegen_addpatchref(cd, PATCHER_get_putstatic, uf, 0);
 
                        }
                        else {
-                               fieldinfo *fi = iptr->sx.s23.s3.fmiref->p.field;
-
+                               fi        = iptr->sx.s23.s3.fmiref->p.field;
                                fieldtype = fi->type;
+                               disp      = (ptrint) &(fi->value);
 
-                               if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
+                               if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
                                        codegen_addpatchref(cd, PATCHER_clinit, fi->class, 0);
-
-                                       if (opt_showdisassemble) {
-                                               M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
-                                       }
-                               }
-
-                               disp = (ptrint) &(fi->value);
                        }
 
                        M_MOV_IMM(disp, REG_ITMP1);
@@ -2240,34 +2244,19 @@ bool codegen(jitdata *jd)
                case ICMD_PUTSTATIC:  /* ..., value  ==> ...                          */
 
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
-                               unresolved_field *uf = iptr->sx.s23.s3.uf;
-
+                               uf        = iptr->sx.s23.s3.uf;
                                fieldtype = uf->fieldref->parseddesc.fd->type;
+                               disp      = 0;
 
-                               codegen_addpatchref(cd, PATCHER_get_putstatic,
-                                                                       iptr->sx.s23.s3.uf, 0);
-
-                               if (opt_showdisassemble) {
-                                       M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
-                               }
-
-                               disp = 0;
-
+                               codegen_addpatchref(cd, PATCHER_get_putstatic, uf, 0);
                        }
                        else {
-                               fieldinfo *fi = iptr->sx.s23.s3.fmiref->p.field;
-                               
+                               fi        = iptr->sx.s23.s3.fmiref->p.field;
                                fieldtype = fi->type;
+                               disp      = (ptrint) &(fi->value);
 
-                               if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
+                               if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
                                        codegen_addpatchref(cd, PATCHER_clinit, fi->class, 0);
-
-                                       if (opt_showdisassemble) {
-                                               M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
-                                       }
-                               }
-
-                               disp = (ptrint) &(fi->value);
                        }
 
                        M_MOV_IMM(disp, REG_ITMP1);
@@ -2297,34 +2286,19 @@ bool codegen(jitdata *jd)
                                          /* following NOP)                           */
 
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
-                               unresolved_field *uf = iptr->sx.s23.s3.uf;
-
+                               uf        = iptr->sx.s23.s3.uf;
                                fieldtype = uf->fieldref->parseddesc.fd->type;
+                               disp      = 0;
 
-                               codegen_addpatchref(cd, PATCHER_get_putstatic,
-                                                                       uf, 0);
-
-                               if (opt_showdisassemble) {
-                                       M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
-                               }
-
-                               disp = 0;
-
+                               codegen_addpatchref(cd, PATCHER_get_putstatic, uf, 0);
                        }
                        else {
-                               fieldinfo *fi = iptr->sx.s23.s3.fmiref->p.field;
-
+                               fi        = iptr->sx.s23.s3.fmiref->p.field;
                                fieldtype = fi->type;
+                               disp      = (ptrint) &(fi->value);
 
-                               if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
+                               if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
                                        codegen_addpatchref(cd, PATCHER_clinit, fi->class, 0);
-
-                                       if (opt_showdisassemble) {
-                                               M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
-                                       }
-                               }
-
-                               disp = (ptrint) &(fi->value);
                        }
 
                        M_MOV_IMM(disp, REG_ITMP1);
@@ -2355,10 +2329,6 @@ bool codegen(jitdata *jd)
                                codegen_addpatchref(cd, PATCHER_getfield,
                                                                        iptr->sx.s23.s3.uf, 0);
 
-                               if (opt_showdisassemble) {
-                                       M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
-                               }
-
                                disp = 0;
 
                        }
@@ -2423,10 +2393,6 @@ bool codegen(jitdata *jd)
 
                                codegen_addpatchref(cd, PATCHER_putfield, uf, 0);
 
-                               if (opt_showdisassemble) {
-                                       M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
-                               }
-
                                disp = 0;
 
                        }
@@ -2468,10 +2434,6 @@ bool codegen(jitdata *jd)
                                codegen_addpatchref(cd, PATCHER_putfieldconst,
                                                                        uf, 0);
 
-                               if (opt_showdisassemble) {
-                                       M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
-                               }
-
                                disp = 0;
 
                        }
@@ -2510,10 +2472,6 @@ bool codegen(jitdata *jd)
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
                                codegen_addpatchref(cd, PATCHER_athrow_areturn,
                                                                        iptr->sx.s23.s2.uc, 0);
-
-                               if (opt_showdisassemble) {
-                                       M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
-                               }
                        }
 #endif /* ENABLE_VERIFIER */
 
@@ -2535,79 +2493,34 @@ bool codegen(jitdata *jd)
                                codegen_insert_phi_moves(jd, bptr);
                        }
 #endif
-                       M_JMP_IMM(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_br(cd, iptr->dst.block);
                        ALIGNCODENOP;
                        break;
 
                case ICMD_JSR:          /* ... ==> ...                                */
 
-                       M_JMP_IMM(0);
-                       codegen_addreference(cd, iptr->sx.s23.s3.jsrtarget.block);
+                       emit_br(cd, iptr->sx.s23.s3.jsrtarget.block);
+                       ALIGNCODENOP;
                        break;
                        
                case ICMD_IFNULL:       /* ..., value ==> ...                         */
+               case ICMD_IFNONNULL:
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        M_TEST(s1);
-                       M_BEQ(0);
-                       codegen_addreference(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IFNONNULL:    /* ..., value ==> ...                         */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       M_TEST(s1);
-                       M_BNE(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IFNULL, BRANCH_OPT_NONE);
                        break;
 
                case ICMD_IFEQ:         /* ..., value ==> ...                         */
+               case ICMD_IFLT:
+               case ICMD_IFLE:
+               case ICMD_IFNE:
+               case ICMD_IFGT:
+               case ICMD_IFGE:
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        M_CMP_IMM(iptr->sx.val.i, s1);
-                       M_BEQ(0);
-                       codegen_addreference(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IFLT:         /* ..., value ==> ...                         */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       M_CMP_IMM(iptr->sx.val.i, s1);
-                       M_BLT(0);
-                       codegen_addreference(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IFLE:         /* ..., value ==> ...                         */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       M_CMP_IMM(iptr->sx.val.i, s1);
-                       M_BLE(0);
-                       codegen_addreference(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IFNE:         /* ..., value ==> ...                         */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       M_CMP_IMM(iptr->sx.val.i, s1);
-                       M_BNE(0);
-                       codegen_addreference(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IFGT:         /* ..., value ==> ...                         */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       M_CMP_IMM(iptr->sx.val.i, s1);
-                       M_BGT(0);
-                       codegen_addreference(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IFGE:         /* ..., value ==> ...                         */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       M_CMP_IMM(iptr->sx.val.i, s1);
-                       M_BGE(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IFEQ, BRANCH_OPT_NONE);
                        break;
 
                case ICMD_IF_LEQ:       /* ..., value ==> ...                         */
@@ -2623,8 +2536,7 @@ bool codegen(jitdata *jd)
                                M_XOR_IMM(iptr->sx.val.l >> 32, REG_ITMP2);
                                M_OR(REG_ITMP2, REG_ITMP1);
                        }
-                       M_BEQ(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_beq(cd, iptr->dst.block);
                        break;
 
                case ICMD_IF_LLT:       /* ..., value ==> ...                         */
@@ -2634,30 +2546,26 @@ bool codegen(jitdata *jd)
                                   are too. */
                                s1 = emit_load_s1_high(jd, iptr, REG_ITMP2);
                                M_CMP_IMM(0, s1);
-                               M_BLT(0);
+                               emit_blt(cd, iptr->dst.block);
                        }
                        else {
                                s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED);
                                M_CMP_IMM(iptr->sx.val.l >> 32, GET_HIGH_REG(s1));
-                               M_BLT(0);
-                               codegen_addreference(cd, iptr->dst.block);
+                               emit_blt(cd, iptr->dst.block);
                                M_BGT(6 + 6);
                                M_CMP_IMM32(iptr->sx.val.l, GET_LOW_REG(s1));
-                               M_BB(0);
+                               emit_bult(cd, iptr->dst.block);
                        }                       
-                       codegen_addreference(cd, iptr->dst.block);
                        break;
 
                case ICMD_IF_LLE:       /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED);
                        M_CMP_IMM(iptr->sx.val.l >> 32, GET_HIGH_REG(s1));
-                       M_BLT(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_blt(cd, iptr->dst.block);
                        M_BGT(6 + 6);
                        M_CMP_IMM32(iptr->sx.val.l, GET_LOW_REG(s1));
-                       M_BBE(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_bule(cd, iptr->dst.block);
                        break;
 
                case ICMD_IF_LNE:       /* ..., value ==> ...                         */
@@ -2673,20 +2581,17 @@ bool codegen(jitdata *jd)
                                M_XOR_IMM(iptr->sx.val.l >> 32, REG_ITMP2);
                                M_OR(REG_ITMP2, REG_ITMP1);
                        }
-                       M_BNE(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_bne(cd, iptr->dst.block);
                        break;
 
                case ICMD_IF_LGT:       /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED);
                        M_CMP_IMM(iptr->sx.val.l >> 32, GET_HIGH_REG(s1));
-                       M_BGT(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_bgt(cd, iptr->dst.block);
                        M_BLT(6 + 6);
                        M_CMP_IMM32(iptr->sx.val.l, GET_LOW_REG(s1));
-                       M_BA(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_bugt(cd, iptr->dst.block);
                        break;
 
                case ICMD_IF_LGE:       /* ..., value ==> ...                         */
@@ -2696,28 +2601,38 @@ bool codegen(jitdata *jd)
                                   64-bits are too. */
                                s1 = emit_load_s1_high(jd, iptr, REG_ITMP2);
                                M_CMP_IMM(0, s1);
-                               M_BGE(0);
+                               emit_bge(cd, iptr->dst.block);
                        }
                        else {
                                s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED);
                                M_CMP_IMM(iptr->sx.val.l >> 32, GET_HIGH_REG(s1));
-                               M_BGT(0);
-                               codegen_addreference(cd, iptr->dst.block);
+                               emit_bgt(cd, iptr->dst.block);
                                M_BLT(6 + 6);
                                M_CMP_IMM32(iptr->sx.val.l, GET_LOW_REG(s1));
-                               M_BAE(0);
+                               emit_buge(cd, iptr->dst.block);
                        }
-                       codegen_addreference(cd, iptr->dst.block);
                        break;
 
                case ICMD_IF_ICMPEQ:    /* ..., value, value ==> ...                  */
-               case ICMD_IF_ACMPEQ:    /* op1 = target JavaVM pc                     */
+               case ICMD_IF_ICMPNE:
+               case ICMD_IF_ICMPLT:
+               case ICMD_IF_ICMPGT:
+               case ICMD_IF_ICMPGE:
+               case ICMD_IF_ICMPLE:
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_CMP(s2, s1);
-                       M_BEQ(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IF_ICMPEQ, BRANCH_OPT_NONE);
+                       break;
+
+               case ICMD_IF_ACMPEQ:    /* ..., value, value ==> ...                  */
+               case ICMD_IF_ACMPNE:
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+                       M_CMP(s2, s1);
+                       emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IF_ACMPEQ, BRANCH_OPT_NONE);
                        break;
 
                case ICMD_IF_LCMPEQ:    /* ..., value, value ==> ...                  */
@@ -2731,18 +2646,7 @@ bool codegen(jitdata *jd)
                        M_INTMOVE(s1, REG_ITMP2);
                        M_XOR(s2, REG_ITMP2);
                        M_OR(REG_ITMP1, REG_ITMP2);
-                       M_BEQ(0);
-                       codegen_addreference(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IF_ICMPNE:    /* ..., value, value ==> ...                  */
-               case ICMD_IF_ACMPNE:    /* op1 = target JavaVM pc                     */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       M_CMP(s2, s1);
-                       M_BNE(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_beq(cd, iptr->dst.block);
                        break;
 
                case ICMD_IF_LCMPNE:    /* ..., value, value ==> ...                  */
@@ -2756,17 +2660,7 @@ bool codegen(jitdata *jd)
                        M_INTMOVE(s1, REG_ITMP2);
                        M_XOR(s2, REG_ITMP2);
                        M_OR(REG_ITMP1, REG_ITMP2);
-                       M_BNE(0);
-                       codegen_addreference(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IF_ICMPLT:    /* ..., value, value ==> ...                  */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       M_CMP(s2, s1);
-                       M_BLT(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_bne(cd, iptr->dst.block);
                        break;
 
                case ICMD_IF_LCMPLT:    /* ..., value, value ==> ...                  */
@@ -2774,23 +2668,12 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
                        M_CMP(s2, s1);
-                       M_BLT(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_blt(cd, iptr->dst.block);
                        s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
                        M_BGT(2 + 6);
                        M_CMP(s2, s1);
-                       M_BB(0);
-                       codegen_addreference(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IF_ICMPGT:    /* ..., value, value ==> ...                  */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       M_CMP(s2, s1);
-                       M_BGT(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_bult(cd, iptr->dst.block);
                        break;
 
                case ICMD_IF_LCMPGT:    /* ..., value, value ==> ...                  */
@@ -2798,23 +2681,12 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
                        M_CMP(s2, s1);
-                       M_BGT(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_bgt(cd, iptr->dst.block);
                        s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
                        M_BLT(2 + 6);
                        M_CMP(s2, s1);
-                       M_BA(0);
-                       codegen_addreference(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IF_ICMPLE:    /* ..., value, value ==> ...                  */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       M_CMP(s2, s1);
-                       M_BLE(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_bugt(cd, iptr->dst.block);
                        break;
 
                case ICMD_IF_LCMPLE:    /* ..., value, value ==> ...                  */
@@ -2822,23 +2694,12 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
                        M_CMP(s2, s1);
-                       M_BLT(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_blt(cd, iptr->dst.block);
                        s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
                        M_BGT(2 + 6);
                        M_CMP(s2, s1);
-                       M_BBE(0);
-                       codegen_addreference(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IF_ICMPGE:    /* ..., value, value ==> ...                  */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       M_CMP(s2, s1);
-                       M_BGE(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_bule(cd, iptr->dst.block);
                        break;
 
                case ICMD_IF_LCMPGE:    /* ..., value, value ==> ...                  */
@@ -2846,14 +2707,12 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
                        M_CMP(s2, s1);
-                       M_BGT(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_bgt(cd, iptr->dst.block);
                        s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
                        M_BLT(2 + 6);
                        M_CMP(s2, s1);
-                       M_BAE(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_buge(cd, iptr->dst.block);
                        break;
 
 
@@ -2881,10 +2740,6 @@ bool codegen(jitdata *jd)
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
                                codegen_addpatchref(cd, PATCHER_athrow_areturn,
                                                                        iptr->sx.s23.s2.uc, 0);
-
-                               if (opt_showdisassemble) {
-                                       M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
-                               }
                        }
 #endif /* ENABLE_VERIFIER */
                        goto nowperformreturn;
@@ -3007,10 +2862,9 @@ nowperformreturn:
                                i = i - l + 1;
 
                 /* range check */
-                               M_CMP_IMM(i - 1, REG_ITMP1);
-                               M_BA(0);
 
-                               codegen_addreference(cd, table[0].block); /* default target */
+                               M_CMP_IMM(i - 1, REG_ITMP1);
+                               emit_bugt(cd, table[0].block);
 
                                /* build jump table top down and use address of lowest entry */
 
@@ -3046,14 +2900,12 @@ nowperformreturn:
 
                                while (--i >= 0) {
                                        M_CMP_IMM(lookup->value, s1);
-                                       M_BEQ(0);
-                                       codegen_addreference(cd, lookup->target.block);
+                                       emit_beq(cd, lookup->target.block);
                                        lookup++;
                                }
 
-                               M_JMP_IMM(0);
-                       
-                               codegen_addreference(cd, iptr->sx.s23.s3.lookupdefault.block);
+                               emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
+                               ALIGNCODENOP;
                        }
                        break;
 
@@ -3132,20 +2984,12 @@ gen_method:
                                M_MOV_IMM(disp, REG_ITMP1);
                                M_CALL(REG_ITMP1);
 
-
-                               if (INSTRUCTION_MUST_CHECK(iptr)) {
-                                       M_TEST(REG_RESULT);
-                                       M_BEQ(0);
-                                       codegen_add_fillinstacktrace_ref(cd);
-                               }
+                               emit_exception_check(cd, iptr);
                                break;
 
                        case ICMD_INVOKESPECIAL:
-                               M_ALD(REG_ITMP1, REG_SP, 0);
-                               M_TEST(REG_ITMP1);
-                               M_BEQ(0);
-                               codegen_add_nullpointerexception_ref(cd);
-
+                               M_ALD(REG_ITMP1, REG_SP, 0 * 4);
+                               emit_nullpointer_check(cd, iptr, REG_ITMP1);
                                /* fall through */
 
                        case ICMD_INVOKESTATIC:
@@ -3155,10 +2999,6 @@ gen_method:
                                        codegen_addpatchref(cd, PATCHER_invokestatic_special,
                                                                                um, 0);
 
-                                       if (opt_showdisassemble) {
-                                               M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
-                                       }
-
                                        disp = 0;
                                        d = md->returntype.type;
                                }
@@ -3180,10 +3020,6 @@ gen_method:
 
                                        codegen_addpatchref(cd, PATCHER_invokevirtual, um, 0);
 
-                                       if (opt_showdisassemble) {
-                                               M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
-                                       }
-
                                        s1 = 0;
                                        d = md->returntype.type;
                                }
@@ -3208,10 +3044,6 @@ gen_method:
 
                                        codegen_addpatchref(cd, PATCHER_invokeinterface, um, 0);
 
-                                       if (opt_showdisassemble) {
-                                               M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
-                                       }
-
                                        s1 = 0;
                                        s2 = 0;
                                        d = md->returntype.type;
@@ -3304,64 +3136,18 @@ gen_method:
 #endif
                                s1 = emit_load_s1(jd, iptr, REG_ITMP1);
 
-                               /* calculate interface checkcast code size */
-
-                               s2 = 2; /* mov_membase_reg */
-                               CALCOFFSETBYTES(s2, s1, OFFSET(java_objectheader, vftbl));
-
-                               s2 += (2 + 4 /* mov_membase32_reg */ + 2 + 4 /* sub imm32 */ +
-                                          2 /* test */ + 6 /* jcc */ + 2 + 4 /* mov_membase32_reg */ +
-                                          2 /* test */ + 6 /* jcc */);
-
-                               if (!super)
-                                       s2 += (opt_showdisassemble ? 5 : 0);
-
-                               /* calculate class checkcast code size */
-
-                               s3 = 2; /* mov_membase_reg */
-                               CALCOFFSETBYTES(s3, s1, OFFSET(java_objectheader, vftbl));
-
-                               s3 += 5 /* mov_imm_reg */ + 2 + 4 /* mov_membase32_reg */;
-
-#if 0
-                               if (s1 != REG_ITMP1) {
-                                       a += 2;
-                                       CALCOFFSETBYTES(a, REG_ITMP3, OFFSET(vftbl_t, baseval));
-                               
-                                       a += 2;
-                                       CALCOFFSETBYTES(a, REG_ITMP3, OFFSET(vftbl_t, diffval));
-                               
-                                       a += 2;
-                               
-                               } else
-#endif
-                                       {
-                                               s3 += (2 + 4 /* mov_membase32_reg */ + 2 /* sub */ +
-                                                          5 /* mov_imm_reg */ + 2 /* mov_membase_reg */);
-                                               CALCOFFSETBYTES(s3, REG_ITMP3, OFFSET(vftbl_t, diffval));
-                                       }
-
-                               s3 += 2 /* cmp */ + 6 /* jcc */;
-
-                               if (super == NULL)
-                                       s3 += (opt_showdisassemble ? 5 : 0);
-
                                /* if class is not resolved, check which code to call */
 
                                if (super == NULL) {
                                        M_TEST(s1);
-                                       M_BEQ(5 + (opt_showdisassemble ? 5 : 0) + 6 + 6 + s2 + 5 + s3);
+                                       emit_label_beq(cd, BRANCH_LABEL_1);
 
                                        codegen_addpatchref(cd, PATCHER_checkcast_instanceof_flags,
                                                                                iptr->sx.s23.s3.c.ref, 0);
 
-                                       if (opt_showdisassemble) {
-                                               M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
-                                       }
-
                                        M_MOV_IMM(0, REG_ITMP2);                  /* super->flags */
                                        M_AND_IMM32(ACC_INTERFACE, REG_ITMP2);
-                                       M_BEQ(s2 + 5);
+                                       emit_label_beq(cd, BRANCH_LABEL_2);
                                }
 
                                /* interface checkcast code */
@@ -3369,45 +3155,45 @@ gen_method:
                                if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
                                        if (super != NULL) {
                                                M_TEST(s1);
-                                               M_BEQ(s2);
+                                               emit_label_beq(cd, BRANCH_LABEL_3);
                                        }
 
                                        M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
 
                                        if (super == NULL) {
-                                               codegen_addpatchref(cd,
-                                                                                       PATCHER_checkcast_instanceof_interface,
+                                               codegen_addpatchref(cd, PATCHER_checkcast_interface,
                                                                                        iptr->sx.s23.s3.c.ref,
                                                                                        0);
-
-                                               if (opt_showdisassemble) {
-                                                       M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
-                                               }
                                        }
 
                                        M_ILD32(REG_ITMP3,
                                                        REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
                                        M_ISUB_IMM32(superindex, REG_ITMP3);
+                                       /* XXX do we need this one? */
                                        M_TEST(REG_ITMP3);
-                                       M_BLE(0);
-                                       codegen_add_classcastexception_ref(cd, s1);
+                                       emit_classcast_check(cd, iptr, BRANCH_LE, REG_ITMP3, s1);
+
                                        M_ALD32(REG_ITMP3, REG_ITMP2,
                                                        OFFSET(vftbl_t, interfacetable[0]) -
                                                        superindex * sizeof(methodptr*));
                                        M_TEST(REG_ITMP3);
-                                       M_BEQ(0);
-                                       codegen_add_classcastexception_ref(cd, s1);
+                                       emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ITMP3, s1);
 
                                        if (super == NULL)
-                                               M_JMP_IMM(s3);
+                                               emit_label_br(cd, BRANCH_LABEL_4);
+                                       else
+                                               emit_label(cd, BRANCH_LABEL_3);
                                }
 
                                /* class checkcast code */
 
                                if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
-                                       if (super != NULL) {
+                                       if (super == NULL) {
+                                               emit_label(cd, BRANCH_LABEL_2);
+                                       }
+                                       else {
                                                M_TEST(s1);
-                                               M_BEQ(s3);
+                                               emit_label_beq(cd, BRANCH_LABEL_5);
                                        }
 
                                        M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
@@ -3416,10 +3202,6 @@ gen_method:
                                                codegen_addpatchref(cd, PATCHER_checkcast_class,
                                                                                        iptr->sx.s23.s3.c.ref,
                                                                                        0);
-
-                                               if (opt_showdisassemble) {
-                                                       M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
-                                               }
                                        }
 
                                        M_MOV_IMM(supervftbl, REG_ITMP3);
@@ -3447,8 +3229,15 @@ gen_method:
                                        /*                              } */
 
                                        M_CMP(REG_ITMP3, REG_ITMP2);
-                                       M_BA(0);         /* (u) REG_ITMP2 > (u) REG_ITMP3 -> jump */
-                                       codegen_add_classcastexception_ref(cd, s1);
+                                       emit_classcast_check(cd, iptr, BRANCH_ULE, REG_ITMP3, s1);
+
+                                       if (super != NULL)
+                                               emit_label(cd, BRANCH_LABEL_5);
+                               }
+
+                               if (super == NULL) {
+                                       emit_label(cd, BRANCH_LABEL_1);
+                                       emit_label(cd, BRANCH_LABEL_4);
                                }
 
                                d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
@@ -3462,10 +3251,6 @@ gen_method:
                                if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
                                        codegen_addpatchref(cd, PATCHER_builtin_arraycheckcast,
                                                                                iptr->sx.s23.s3.c.ref, 0);
-
-                                       if (opt_showdisassemble) {
-                                               M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
-                                       }
                                }
 
                                M_AST_IMM(iptr->sx.s23.s3.c.cls, REG_SP, 1 * 4);
@@ -3474,8 +3259,7 @@ gen_method:
 
                                s1 = emit_load_s1(jd, iptr, REG_ITMP2);
                                M_TEST(REG_RESULT);
-                               M_BEQ(0);
-                               codegen_add_classcastexception_ref(cd, s1);
+                               emit_classcast_check(cd, iptr, BRANCH_EQ, REG_RESULT, s1);
 
                                d = codegen_reg_of_dst(jd, iptr, s1);
                        }
@@ -3522,79 +3306,41 @@ gen_method:
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+
                        if (s1 == d) {
                                M_INTMOVE(s1, REG_ITMP1);
                                s1 = REG_ITMP1;
                        }
 
-                       /* calculate interface instanceof code size */
-
-                       s2 = 2; /* mov_membase_reg */
-                       CALCOFFSETBYTES(s2, s1, OFFSET(java_objectheader, vftbl));
-
-                       s2 += (2 + 4 /* mov_membase32_reg */ + 2 + 4 /* alu_imm32_reg */ +
-                                  2 /* test */ + 6 /* jcc */ + 2 + 4 /* mov_membase32_reg */ +
-                                  2 /* test */ + 6 /* jcc */ + 5 /* mov_imm_reg */);
-
-                       if (!super)
-                               s2 += (opt_showdisassemble ? 5 : 0);
-
-                       /* calculate class instanceof code size */
-
-                       s3 = 2; /* mov_membase_reg */
-                       CALCOFFSETBYTES(s3, s1, OFFSET(java_objectheader, vftbl));
-                       s3 += 5; /* mov_imm_reg */
-                       s3 += 2;
-                       CALCOFFSETBYTES(s3, REG_ITMP1, OFFSET(vftbl_t, baseval));
-                       s3 += 2;
-                       CALCOFFSETBYTES(s3, REG_ITMP2, OFFSET(vftbl_t, diffval));
-                       s3 += 2;
-                       CALCOFFSETBYTES(s3, REG_ITMP2, OFFSET(vftbl_t, baseval));
-
-                       s3 += (2 /* alu_reg_reg */ + 2 /* alu_reg_reg */ +
-                                  2 /* alu_reg_reg */ + 6 /* jcc */ + 5 /* mov_imm_reg */);
-
-                       if (!super)
-                               s3 += (opt_showdisassemble ? 5 : 0);
-
                        M_CLR(d);
 
                        /* if class is not resolved, check which code to call */
 
-                       if (!super) {
+                       if (super == NULL) {
                                M_TEST(s1);
-                               M_BEQ(5 + (opt_showdisassemble ? 5 : 0) + 6 + 6 + s2 + 5 + s3);
+                               emit_label_beq(cd, BRANCH_LABEL_1);
 
                                codegen_addpatchref(cd, PATCHER_checkcast_instanceof_flags,
                                                                        iptr->sx.s23.s3.c.ref, 0);
 
-                               if (opt_showdisassemble) {
-                                       M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
-                               }
-
                                M_MOV_IMM(0, REG_ITMP3);                      /* super->flags */
                                M_AND_IMM32(ACC_INTERFACE, REG_ITMP3);
-                               M_BEQ(s2 + 5);
+                               emit_label_beq(cd, BRANCH_LABEL_2);
                        }
 
                        /* interface instanceof code */
 
-                       if (!super || (super->flags & ACC_INTERFACE)) {
-                               if (super) {
+                       if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
+                               if (super != NULL) {
                                        M_TEST(s1);
-                                       M_BEQ(s2);
+                                       emit_label_beq(cd, BRANCH_LABEL_3);
                                }
 
                                M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
 
-                               if (!super) {
-                                       codegen_addpatchref(cd,
-                                                                               PATCHER_checkcast_instanceof_interface,
+                               if (super == NULL) {
+                                       codegen_addpatchref(cd, PATCHER_instanceof_interface,
                                                                                iptr->sx.s23.s3.c.ref, 0);
-
-                                       if (opt_showdisassemble) {
-                                               M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
-                                       }
                                }
 
                                M_ILD32(REG_ITMP3,
@@ -3615,27 +3361,28 @@ gen_method:
                                M_BEQ(5);
                                M_MOV_IMM(1, d);
 
-                               if (!super)
-                                       M_JMP_IMM(s3);
+                               if (super == NULL)
+                                       emit_label_br(cd, BRANCH_LABEL_4);
+                               else
+                                       emit_label(cd, BRANCH_LABEL_3);
                        }
 
                        /* class instanceof code */
 
-                       if (!super || !(super->flags & ACC_INTERFACE)) {
-                               if (super) {
+                       if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
+                               if (super == NULL) {
+                                       emit_label(cd, BRANCH_LABEL_2);
+                               }
+                               else {
                                        M_TEST(s1);
-                                       M_BEQ(s3);
+                                       emit_label_beq(cd, BRANCH_LABEL_5);
                                }
 
                                M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
 
-                               if (!super) {
+                               if (super == NULL) {
                                        codegen_addpatchref(cd, PATCHER_instanceof_class,
                                                                                iptr->sx.s23.s3.c.ref, 0);
-
-                                       if (opt_showdisassemble) {
-                                               M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
-                                       }
                                }
 
                                M_MOV_IMM(supervftbl, REG_ITMP2);
@@ -3653,11 +3400,18 @@ gen_method:
                                M_CMP(REG_ITMP3, REG_ITMP1);
                                M_BA(5);
                                M_MOV_IMM(1, d);
+
+                               if (super != NULL)
+                                       emit_label(cd, BRANCH_LABEL_5);
                        }
-                       emit_store_dst(jd, iptr, d);
+
+                       if (super == NULL) {
+                               emit_label(cd, BRANCH_LABEL_1);
+                               emit_label(cd, BRANCH_LABEL_4);
                        }
-                       break;
 
+                       emit_store_dst(jd, iptr, d);
+                       }
                        break;
 
                case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref  */
@@ -3687,10 +3441,6 @@ gen_method:
                                codegen_addpatchref(cd, PATCHER_builtin_multianewarray,
                                                                        iptr->sx.s23.s3.c.ref, 0);
 
-                               if (opt_showdisassemble) {
-                                       M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
-                               }
-
                                disp = 0;
 
                        }
@@ -3716,9 +3466,7 @@ gen_method:
 
                        /* check for exception before result assignment */
 
-                       M_TEST(REG_RESULT);
-                       M_BEQ(0);
-                       codegen_add_fillinstacktrace_ref(cd);
+                       emit_exception_check(cd, iptr);
 
                        s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
                        M_INTMOVE(REG_RESULT, s1);
@@ -3764,15 +3512,11 @@ gen_method:
 
        dseg_createlinenumbertable(cd);
 
+       /* generate stubs */
 
-       /* generate exception and patcher stubs */
-
-       emit_exception_stubs(jd);
        emit_patcher_stubs(jd);
        REPLACEMENT_EMIT_STUBS(jd);
 
-       codegen_finish(jd);
-
        /* everything's ok */
 
        return true;
@@ -4082,13 +3826,8 @@ u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd)
        /* get function address (this must happen before the stackframeinfo) */
 
 #if !defined(WITH_STATIC_CLASSPATH)
-       if (f == NULL) {
+       if (f == NULL)
                codegen_addpatchref(cd, PATCHER_resolve_native, m, 0);
-
-               if (opt_showdisassemble) {
-                       M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
-               }
-       }
 #endif
 
        M_AST_IMM((ptrint) f, REG_SP, 4 * 4);
index 35101a9f6f20803d31f87d0660e0399f4dc39abc..6b7b956cd88dfd82096057380f1259add6a5e555 100644 (file)
@@ -1,6 +1,6 @@
 /* src/vm/jit/i386/codegen.h - code generation macros and definitions for i386
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
    J. Wenninger, Institut f. Computersprachen - TU Wien
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Andreas Krall
-            Christian Thalinger
-
-   $Id: codegen.h 6211 2006-12-16 22:53:24Z edwin $
+   $Id: codegen.h 7571 2007-03-24 22:37:09Z twisti $
 
 */
 
 
 /* branch defines *************************************************************/
 
+#define BRANCH_UNCONDITIONAL_SIZE    5  /* size in bytes of a branch          */
+#define BRANCH_CONDITIONAL_SIZE      6  /* size in bytes of a branch          */
+
 #define BRANCH_NOPS \
     do { \
         M_NOP; \
         M_NOP; \
         M_NOP; \
         M_NOP; \
+        M_NOP; \
     } while (0)
 
 
 #define M_ALD(a,b,disp)         M_ILD(a,b,disp)
 #define M_ALD32(a,b,disp)       M_ILD32(a,b,disp)
 
+#define M_ALD_MEM(a,disp)       emit_mov_mem_reg(cd, (disp), (a))
+
+#define M_ALD_MEM_GET_OPC(p)    (*(p))
+#define M_ALD_MEM_GET_MOD(p)    (((*(p + 1)) >> 6) & 0x03)
+#define M_ALD_MEM_GET_REG(p)    (((*(p + 1)) >> 3) & 0x07)
+#define M_ALD_MEM_GET_RM(p)     (((*(p + 1))     ) & 0x07)
+#define M_ALD_MEM_GET_DISP(p)   (*((u4 *) (p + 2)))
+
 #define M_LLD(a,b,disp) \
     do { \
         M_ILD(GET_LOW_REG(a),b,disp); \
index 87ae3ada0e3dfa4812995fa1d226f15c04357169..12fa5660f4b9ca2f48959c3027999756a5d814c7 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: emit.c 7514 2007-03-13 20:31:51Z twisti $
+   $Id: emit.c 7579 2007-03-25 22:42:13Z twisti $
 
 */
 
@@ -44,6 +44,7 @@
 #endif
 
 #include "vm/builtin.h"
+#include "vm/exceptions.h"
 
 #include "vm/jit/asmpart.h"
 #include "vm/jit/dseg.h"
@@ -323,6 +324,71 @@ void emit_copy(jitdata *jd, instruction *iptr, varinfo *src, varinfo *dst)
 }
 
 
+/* emit_branch *****************************************************************
+
+   Emits the code for conditional and unconditional branchs.
+
+*******************************************************************************/
+
+void emit_branch(codegendata *cd, s4 disp, s4 condition, s4 reg, u4 options)
+{
+       s4 branchdisp;
+
+       /* ATTENTION: a displacement overflow cannot happen */
+
+       /* check which branch to generate */
+
+       if (condition == BRANCH_UNCONDITIONAL) {
+
+               /* calculate the different displacements */
+
+               branchdisp = disp - BRANCH_UNCONDITIONAL_SIZE;
+
+               M_JMP_IMM(branchdisp);
+       }
+       else {
+               /* calculate the different displacements */
+
+               branchdisp = disp - BRANCH_CONDITIONAL_SIZE;
+
+               switch (condition) {
+               case BRANCH_EQ:
+                       M_BEQ(branchdisp);
+                       break;
+               case BRANCH_NE:
+                       M_BNE(branchdisp);
+                       break;
+               case BRANCH_LT:
+                       M_BLT(branchdisp);
+                       break;
+               case BRANCH_GE:
+                       M_BGE(branchdisp);
+                       break;
+               case BRANCH_GT:
+                       M_BGT(branchdisp);
+                       break;
+               case BRANCH_LE:
+                       M_BLE(branchdisp);
+                       break;
+               case BRANCH_ULT:
+                       M_BB(branchdisp);
+                       break;
+               case BRANCH_ULE:
+                       M_BBE(branchdisp);
+                       break;
+               case BRANCH_UGE:
+                       M_BAE(branchdisp);
+                       break;
+               case BRANCH_UGT:
+                       M_BA(branchdisp);
+                       break;
+               default:
+                       vm_abort("emit_branch: unknown condition %d", condition);
+               }
+       }
+}
+
+
 /* emit_arithmetic_check *******************************************************
 
    Emit an ArithmeticException check.
@@ -333,8 +399,8 @@ void emit_arithmetic_check(codegendata *cd, instruction *iptr, s4 reg)
 {
        if (INSTRUCTION_MUST_CHECK(iptr)) {
                M_TEST(reg);
-               M_BEQ(0);
-               codegen_add_arithmeticexception_ref(cd);
+               M_BNE(6);
+               M_ALD_MEM(reg, EXCEPTION_HARDWARE_ARITHMETIC);
        }
 }
 
@@ -350,8 +416,8 @@ void emit_arrayindexoutofbounds_check(codegendata *cd, instruction *iptr, s4 s1,
        if (INSTRUCTION_MUST_CHECK(iptr)) {
         M_ILD(REG_ITMP3, s1, OFFSET(java_arrayheader, size));
         M_CMP(REG_ITMP3, s2);
-        M_BAE(0);
-        codegen_add_arrayindexoutofboundsexception_ref(cd, s2);
+        M_BB(6);
+               M_ALD_MEM(s2, EXCEPTION_HARDWARE_ARRAYINDEXOUTOFBOUNDS);
        }
 }
 
@@ -364,7 +430,22 @@ void emit_arrayindexoutofbounds_check(codegendata *cd, instruction *iptr, s4 s1,
 
 void emit_classcast_check(codegendata *cd, instruction *iptr, s4 condition, s4 reg, s4 s1)
 {
-       vm_abort("IMPLEMENT ME!");
+       if (INSTRUCTION_MUST_CHECK(iptr)) {
+               switch (condition) {
+               case BRANCH_LE:
+                       M_BGT(6);
+                       break;
+               case BRANCH_EQ:
+                       M_BNE(6);
+                       break;
+               case BRANCH_ULE:
+                       M_BBE(6);
+                       break;
+               default:
+                       vm_abort("emit_classcast_check: unknown condition %d", condition);
+               }
+               M_ALD_MEM(s1, EXCEPTION_HARDWARE_CLASSCAST);
+       }
 }
 
 
@@ -378,93 +459,24 @@ void emit_nullpointer_check(codegendata *cd, instruction *iptr, s4 reg)
 {
        if (INSTRUCTION_MUST_CHECK(iptr)) {
                M_TEST(reg);
-               M_BEQ(0);
-               codegen_add_nullpointerexception_ref(cd);
+               M_BNE(6);
+               M_ALD_MEM(reg, EXCEPTION_HARDWARE_NULLPOINTER);
        }
 }
 
 
-/* emit_exception_stubs ********************************************************
+/* emit_exception_check ********************************************************
 
-   Generates the code for the exception stubs.
+   Emit an Exception check.
 
 *******************************************************************************/
 
-void emit_exception_stubs(jitdata *jd)
+void emit_exception_check(codegendata *cd, instruction *iptr)
 {
-       codegendata  *cd;
-       registerdata *rd;
-       exceptionref *er;
-       s4            branchmpc;
-       s4            targetmpc;
-       s4            targetdisp;
-
-       /* get required compiler data */
-
-       cd = jd->cd;
-       rd = jd->rd;
-
-       /* generate exception stubs */
-
-       targetdisp = 0;
-
-       for (er = cd->exceptionrefs; er != NULL; er = er->next) {
-               /* back-patch the branch to this exception code */
-
-               branchmpc = er->branchpos;
-               targetmpc = cd->mcodeptr - cd->mcodebase;
-
-               md_codegen_patch_branch(cd, branchmpc, targetmpc);
-
-               MCODECHECK(512);
-
-               /* Check if the exception is an
-                  ArrayIndexOutOfBoundsException.  If so, move index register
-                  into REG_ITMP1. */
-
-               if (er->reg != -1)
-                       M_INTMOVE(er->reg, REG_ITMP1);
-
-               /* calcuate exception address */
-
-               M_MOV_IMM(0, REG_ITMP2_XPC);
-               dseg_adddata(cd);
-               M_AADD_IMM32(er->branchpos - 6, REG_ITMP2_XPC);
-
-               /* move function to call into REG_ITMP3 */
-
-               M_MOV_IMM(er->function, REG_ITMP3);
-
-               if (targetdisp == 0) {
-                       targetdisp = cd->mcodeptr - cd->mcodebase;
-
-                       M_ASUB_IMM(5 * 4, REG_SP);
-
-                       /* first store REG_ITMP1 so we can use it */
-
-                       M_AST(REG_ITMP1, REG_SP, 4 * 4);                    /* for AIOOBE */
-
-                       M_AST_IMM(0, REG_SP, 0 * 4);
-                       dseg_adddata(cd);
-                       M_MOV(REG_SP, REG_ITMP1);
-                       M_AADD_IMM(5 * 4, REG_ITMP1);
-                       M_AST(REG_ITMP1, REG_SP, 1 * 4);
-                       M_ALD(REG_ITMP1, REG_SP, (5 + cd->stackframesize) * 4);
-                       M_AST(REG_ITMP1, REG_SP, 2 * 4);
-                       M_AST(REG_ITMP2_XPC, REG_SP, 3 * 4);
-
-                       M_CALL(REG_ITMP3);
-
-                       M_ALD(REG_ITMP2_XPC, REG_SP, 3 * 4);
-                       M_AADD_IMM(5 * 4, REG_SP);
-
-                       M_MOV_IMM(asm_handle_exception, REG_ITMP3);
-                       M_JMP(REG_ITMP3);
-               }
-               else {
-                       M_JMP_IMM((cd->mcodebase + targetdisp) -
-                                         (cd->mcodeptr + PATCHER_CALL_SIZE));
-               }
+       if (INSTRUCTION_MUST_CHECK(iptr)) {
+               M_TEST(REG_RESULT);
+               M_BNE(6);
+               M_ALD_MEM(REG_RESULT, EXCEPTION_HARDWARE_EXCEPTION);
        }
 }
 
index 58a7afc555ad5c41b73af9f51d5e063773976e6d..16d314a21753d8e1ebe9a8b9a95c9ca1046ae8d3 100644 (file)
@@ -1,6 +1,6 @@
 /* src/vm/jit/i386/linux/md-os.c - machine dependent i386 Linux functions
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
    J. Wenninger, Institut f. Computersprachen - TU Wien
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Christian Thalinger
-
-   Changes:
-
-   $Id: md-os.c 5172 2006-07-25 15:33:58Z twisti $
+   $Id: md-os.c 7571 2007-03-24 22:37:09Z twisti $
 
 */
 
 #include "vm/exceptions.h"
 #include "vm/signallocal.h"
 #include "vm/stringlocal.h"
+
 #include "vm/jit/asmpart.h"
 #include "vm/jit/stacktrace.h"
 
+#include "vm/jit/i386/codegen.h"
+
 
 /* md_signal_handler_sigsegv ***************************************************
 
-   NullPointerException signal handler for hardware null pointer
-   check.
+   Signal handler for hardware exceptions.
 
 *******************************************************************************/
 
 void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
 {
-       ucontext_t *_uc;
-       mcontext_t *_mc;
-       u1         *sp;
-       u1         *ra;
-       u1         *xpc;
+       ucontext_t        *_uc;
+       mcontext_t        *_mc;
+       u1                *pv;
+       u1                *sp;
+       u1                *ra;
+       u1                *xpc;
+       u1                 opc;
+       u1                 mod;
+       u1                 rm;
+       s4                 d;
+       s4                 disp;
+       ptrint             val;
+       s4                 type;
+       java_objectheader *e;
 
        _uc = (ucontext_t *) _p;
        _mc = &_uc->uc_mcontext;
 
+       pv  = NULL;                 /* is resolved during stackframeinfo creation */
        sp  = (u1 *) _mc->gregs[REG_ESP];
        xpc = (u1 *) _mc->gregs[REG_EIP];
-       ra  = xpc;                          /* return address is equal to xpc     */
+       ra  = xpc;                              /* return address is equal to XPC */
 
-       _mc->gregs[REG_EAX] =
-               (ptrint) stacktrace_hardware_nullpointerexception(NULL, sp, ra, xpc);
+       /* get exception-throwing instruction */
+
+       opc = M_ALD_MEM_GET_OPC(xpc);
+       mod = M_ALD_MEM_GET_MOD(xpc);
+       rm  = M_ALD_MEM_GET_RM(xpc);
+
+       /* for values see emit_mov_mem_reg and emit_mem */
+
+       if ((opc == 0x8b) && (mod == 0) && (rm == 5)) {
+               /* this was a hardware-exception */
+
+               d    = M_ALD_MEM_GET_REG(xpc);
+               disp = M_ALD_MEM_GET_DISP(xpc);
+
+               /* we use the exception type as load displacement */
+
+               type = disp;
+
+               /* ATTENTION: The _mc->gregs layout is completely crazy!  The
+                  registers are reversed starting with number 4 for REG_EDI
+                  (see /usr/include/sys/ucontext.h).  We have to convert that
+                  here. */
+
+               val = _mc->gregs[REG_EAX - d];
+       }
+       else {
+               /* this was a normal NPE */
+
+               type = EXCEPTION_HARDWARE_NULLPOINTER;
+       }
+
+       /* generate appropriate exception */
+
+       e = exceptions_new_hardware_exception(pv, sp, ra, xpc, type, val);
+
+       /* set registers */
 
+       _mc->gregs[REG_EAX] = (ptrint) e;
        _mc->gregs[REG_ECX] = (ptrint) xpc;                      /* REG_ITMP2_XPC */
        _mc->gregs[REG_EIP] = (ptrint) asm_handle_exception;
 }
index 91aaf41286916d5334208f1e1d68afba6151e475..d083a042d438305e397165be3511d4ef313032b5 100644 (file)
@@ -1,6 +1,6 @@
 /* src/vm/jit/i386/md.c - machine dependent i386 functions
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
    J. Wenninger, Institut f. Computersprachen - TU Wien
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Christian Thalinger
-            Edwin Steiner
-
-   $Id: md.c 7255 2007-01-29 21:39:38Z twisti $
+   $Id: md.c 7571 2007-03-24 22:37:09Z twisti $
 
 */
 
@@ -62,34 +57,6 @@ void md_init(void)
 }
 
 
-/* md_codegen_patch_branch *****************************************************
-
-   Back-patches a branch instruction.
-
-*******************************************************************************/
-
-void md_codegen_patch_branch(codegendata *cd, s4 branchmpc, s4 targetmpc)
-{
-       s4 *mcodeptr;
-       s4  disp;                           /* branch displacement                */
-
-       /* calculate the patch position */
-
-       mcodeptr = (s4 *) (cd->mcodebase + branchmpc);
-
-       /* Calculate the branch displacement. */
-
-       disp = targetmpc - branchmpc;
-
-       /* I don't think we have to check for branch-displacement
-          overflow, +/-2GB should be enough. */
-
-       /* patch the branch instruction before the mcodeptr */
-
-       mcodeptr[-1] = disp;
-}
-
-
 /* md_stacktrace_get_returnaddress *********************************************
 
    Returns the return address of the current stackframe, specified by
index b92d8e3b6e665a0c1bc9dd07a3b99cf8c02c646b..93bc168faa87693c31c182dd53e436e0e3a0b135 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: patcher.c 7464 2007-03-06 00:26:31Z edwin $
+   $Id: patcher.c 7571 2007-03-24 22:37:09Z twisti $
 
 */
 
@@ -166,7 +166,7 @@ bool patcher_get_putstatic(u1 *sp)
 
        /* if we show disassembly, we have to skip the nop's */
 
-       if (opt_showdisassemble)
+       if (opt_shownops)
                ra = ra + 5;
 
        /* patch the field value's address */
@@ -211,7 +211,7 @@ bool patcher_getfield(u1 *sp)
 
        /* if we show disassembly, we have to skip the nop's */
 
-       if (opt_showdisassemble)
+       if (opt_shownops)
                ra = ra + 5;
 
        /* patch the field's offset */
@@ -261,7 +261,7 @@ bool patcher_putfield(u1 *sp)
 
        /* if we show disassembly, we have to skip the nop's */
 
-       if (opt_showdisassemble)
+       if (opt_shownops)
                ra = ra + 5;
 
        /* patch the field's offset */
@@ -318,7 +318,7 @@ bool patcher_putfieldconst(u1 *sp)
 
        /* if we show disassembly, we have to skip the nop's */
 
-       if (opt_showdisassemble)
+       if (opt_shownops)
                ra = ra + 5;
 
        /* patch the field's offset */
@@ -376,7 +376,7 @@ bool patcher_aconst(u1 *sp)
 
        /* if we show disassembly, we have to skip the nop's */
 
-       if (opt_showdisassemble)
+       if (opt_shownops)
                ra = ra + 5;
 
        /* patch the classinfo pointer */
@@ -427,7 +427,7 @@ bool patcher_builtin_multianewarray(u1 *sp)
 
        /* if we show disassembly, we have to skip the nop's */
 
-       if (opt_showdisassemble)
+       if (opt_shownops)
                ra = ra + 5;
 
        /* patch the classinfo pointer */
@@ -479,7 +479,7 @@ bool patcher_builtin_arraycheckcast(u1 *sp)
 
        /* if we show disassembly, we have to skip the nop's */
 
-       if (opt_showdisassemble)
+       if (opt_shownops)
                ra = ra + 5;
 
        /* patch the classinfo pointer */
@@ -529,7 +529,7 @@ bool patcher_invokestatic_special(u1 *sp)
 
        /* if we show disassembly, we have to skip the nop's */
 
-       if (opt_showdisassemble)
+       if (opt_shownops)
                ra = ra + 5;
 
        /* patch stubroutine */
@@ -576,7 +576,7 @@ bool patcher_invokevirtual(u1 *sp)
 
        /* if we show disassembly, we have to skip the nop's */
 
-       if (opt_showdisassemble)
+       if (opt_shownops)
                ra = ra + 5;
 
        /* patch vftbl index */
@@ -625,7 +625,7 @@ bool patcher_invokeinterface(u1 *sp)
 
        /* if we show disassembly, we have to skip the nop's */
 
-       if (opt_showdisassemble)
+       if (opt_shownops)
                ra = ra + 5;
 
        /* patch interfacetable index */
@@ -676,7 +676,7 @@ bool patcher_checkcast_instanceof_flags(u1 *sp)
 
        /* if we show disassembly, we have to skip the nop's */
 
-       if (opt_showdisassemble)
+       if (opt_shownops)
                ra = ra + 5;
 
        /* patch class flags */
@@ -687,7 +687,7 @@ bool patcher_checkcast_instanceof_flags(u1 *sp)
 }
 
 
-/* patcher_checkcast_instanceof_interface **************************************
+/* patcher_checkcast_interface *************************************************
 
    Machine code:
 
@@ -695,12 +695,13 @@ bool patcher_checkcast_instanceof_flags(u1 *sp)
    8b 91 00 00 00 00          mov    0x00000000(%ecx),%edx
    81 ea 00 00 00 00          sub    $0x00000000,%edx
    85 d2                      test   %edx,%edx
-   0f 8e 00 00 00 00          jle    0x00000000
+   0f 8f 06 00 00 00          jg     0x00000000
+   8b 35 03 00 00 00          mov    0x3,%esi
    8b 91 00 00 00 00          mov    0x00000000(%ecx),%edx
 
 *******************************************************************************/
 
-bool patcher_checkcast_instanceof_interface(u1 *sp)
+bool patcher_checkcast_interface(u1 *sp)
 {
        u1                *ra;
        u8                 mcode;
@@ -725,7 +726,60 @@ bool patcher_checkcast_instanceof_interface(u1 *sp)
 
        /* if we show disassembly, we have to skip the nop's */
 
-       if (opt_showdisassemble)
+       if (opt_shownops)
+               ra = ra + 5;
+
+       /* patch super class index */
+
+       *((s4 *) (ra + 6 + 2)) = (s4) c->index;
+
+       *((s4 *) (ra + 6 + 6 + 2 + 6 + 6 + 2)) =
+               (s4) (OFFSET(vftbl_t, interfacetable[0]) -
+                         c->index * sizeof(methodptr*));
+
+       return true;
+}
+
+
+/* patcher_instanceof_interface ************************************************
+
+   Machine code:
+
+   <patched call position>
+   8b 91 00 00 00 00          mov    0x00000000(%ecx),%edx
+   81 ea 00 00 00 00          sub    $0x00000000,%edx
+   85 d2                      test   %edx,%edx
+   0f 8e 13 00 00 00          jle    0x00000000
+   8b 91 00 00 00 00          mov    0x00000000(%ecx),%edx
+
+*******************************************************************************/
+
+bool patcher_instanceof_interface(u1 *sp)
+{
+       u1                *ra;
+       u8                 mcode;
+       constant_classref *cr;
+       classinfo         *c;
+
+       /* get stuff from the stack */
+
+       ra    = (u1 *)                *((ptrint *) (sp + 6 * 4));
+       mcode =                       *((u8 *)     (sp + 2 * 4));
+       cr    = (constant_classref *) *((ptrint *) (sp + 1 * 4));
+
+       /* get the fieldinfo */
+
+       if (!(c = resolve_classref_eager(cr)))
+               return false;
+
+       /* patch back original code */
+
+       *((u4 *) (ra + 0)) = (u4) mcode;
+       *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
+
+       /* if we show disassembly, we have to skip the nop's */
+
+       if (opt_shownops)
                ra = ra + 5;
 
        /* patch super class index */
@@ -778,7 +832,7 @@ bool patcher_checkcast_class(u1 *sp)
 
        /* if we show disassembly, we have to skip the nop's */
 
-       if (opt_showdisassemble)
+       if (opt_shownops)
                ra = ra + 5;
 
        /* patch super class' vftbl */
@@ -827,7 +881,7 @@ bool patcher_instanceof_class(u1 *sp)
 
        /* if we show disassembly, we have to skip the nop's */
 
-       if (opt_showdisassemble)
+       if (opt_shownops)
                ra = ra + 5;
 
        /* patch super class' vftbl */
@@ -948,7 +1002,7 @@ bool patcher_resolve_native(u1 *sp)
 
        /* if we show disassembly, we have to skip the nop's */
 
-       if (opt_showdisassemble)
+       if (opt_shownops)
                ra = ra + 5;
 
        /* patch native function pointer */
index 2cea02d434c6f7cf9e82fcd1c1847d2688588af9..a1fe9c20185549e969a6c51b526882e3ec254aa1 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: jit.c 7575 2007-03-25 20:30:50Z twisti $
+   $Id: jit.c 7577 2007-03-25 20:55:06Z twisti $
 
 */
 
@@ -1492,7 +1492,7 @@ static u1 *jit_compile_intern(jitdata *jd)
        } else
 # endif
                {
-                       if (!codegen(jd)) {
+                       if (!codegen_generate(jd)) {
                                DEBUG_JIT_COMPILEVERBOSE("Exception while generating code: ");
 
                                return NULL;
index b67e4ef8456072018042dad57e855fef392a46d3..c90caa1289c0b7e7aa487e1fd0cd33e979d77a03 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: jit.h 7575 2007-03-25 20:30:50Z twisti $
+   $Id: jit.h 7577 2007-03-25 20:55:06Z twisti $
 
 */
 
@@ -36,7 +36,6 @@ typedef struct jitdata jitdata;
 typedef struct stackelement stackelement;
 typedef stackelement *stackptr;
 typedef struct basicblock basicblock;
-typedef struct branchref branchref;
 typedef struct instruction instruction;
 typedef struct insinfo_inline insinfo_inline;
 typedef struct exception_entry exception_entry;
@@ -514,14 +513,6 @@ struct basicblock {
        } while (0)
                        
 
-/* branchref *****************************************************************/
-
-struct branchref {
-       s4         branchpos;       /* patching position in code segment          */
-       branchref *next;            /* next element in branchref list             */
-};
-
-
 /* data-flow constants for the ICMD table ************************************/
 
 #define DF_0_TO_0      0
index ff2bce107b9ba3de2ae27b8c001fc4d810c32130..c761839cfe0bcef4464c19844b2ebd5cf7f4fb73 100644 (file)
@@ -1,4 +1,4 @@
-DIST_SUBDIRS = uclinux
+DIST_SUBDIRS = linux
 
 SUBDIRS = $(OS_DIR)
 
index 161169db740c6ebde22f6c295ed3d02115e7306f..583c008dacf5c0e2ae5d9759c06969aa252096d8 100644 (file)
@@ -59,7 +59,7 @@
 #define SUPPORT_LONG_FCVT                0
 
 #define SUPPORT_CONST_LOGICAL            0  /* AND, OR, XOR with immediates   */
-#define SUPPORT_CONST_MUL                0  /* mutiply with immediate         */
+#define SUPPORT_CONST_MUL                1  /* mutiply with immediate         */
 
 #define SUPPORT_CONST_STORE              0  /* do we support const stores     */
 #define SUPPORT_CONST_STORE_ZERO_ONLY    0  /* on some risc machines we can   */
 #endif
 
 
+#define HAS_ADDRESS_REGISTER_FILE        1
+
+#define HAS_4BYTE_STACKSLOT            1
+
+/* coldfire has tst instruction */
+#define SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER       1
+#define SUPPORT_BRANCH_CONDITIONAL_UNSIGNED_CONDITIONS     1
+#define SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER     0
+#define SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS    0
+
+#define TRACE_ARGS_NUM                 8
+
+#warning There is no REG_ZERO
+#define REG_ZERO 666
+
 #define SPECIALMEMUSE
 /* #define HAS_4BYTE_STACKSLOT */
 /* #define SUPPORT_COMBINE_INTEGER_REGISTERS */
index 957160be9d7186bfbb8bf50056b6dfc3a4ea863d..d9152d0e13944c04a8031b3a349c87e0b0e323b1 100644 (file)
+/*     src/vm/jit/m68k/asmpart.S
+ *     for cacao 
+ *     Roland Lezuo
+ */
+
+#include "config.h"
+
+#include "vm/jit/m68k/offsets.h"
+
+.data
+call_jit_dummy:
+       .long 0xdeadbeef
+
+.text
+
 .globl asm_vm_call_method
 .globl asm_vm_call_method_int
 .globl asm_vm_call_method_long
 .globl asm_vm_call_method_float
 .globl asm_vm_call_method_double
+.globl asm_vm_call_method_end
 .globl asm_vm_call_method_exception_handler
 
 .globl asm_call_jit_compiler
+
+.globl asm_patcher_wrapper
+
 .globl asm_getclassvalues_atomic
 .globl asm_abstractmethoderror
 .globl asm_criticalsections
 
+.globl asm_handle_exception
+
+/*
+ *     This functions implement the C prototyped funtion
+ *     java_objectheader *asm_vm_call_method(methodinfo *m, s4 vmargscount,vm_arg *vmargs);
+ *     the _int, _long, _float, _double are used for different return types
+ *
+ *     The function may still be uncompiled, so the jit compiler gets invoked.
+ *
+ *
+ */
 
+       /* this is the method header see src/vm/jit/methodheader.h */
+       .align  4
+       .long   0                           /* catch type all                     */
+       .long   0                           /* handler pc                         */
+       .long   0                           /* end pc                             */
+       .long   0                           /* start pc                           */
+       .long   1                           /* extable size                       */
+       .long   0                           /* line number table start            */
+       .long   0                           /* line number table size             */
+       .long   0                           /* fltsave                            */
+       .long   0                           /* intsave                            */
+       .long   0                           /* isleaf                             */
+       .long   0                           /* IsSync                             */
+       .long   0                           /* frame size                         */
+       .long   0                           /* codeinfo pointer                   */
 asm_vm_call_method:
 asm_vm_call_method_int:
 asm_vm_call_method_long:
 asm_vm_call_method_float:
 asm_vm_call_method_double:
+       addal   #(-11*4),%sp                                            /* create stackframe to save registers */
+       moveml  %d2/%d3/%d4/%d5/%d6/%d7/%a2/%a3/%a4/%a5/%fp,%sp@        /* save registers */
+
+       /* fetch arguments from vmargs data structure */
+       movel   %sp@(11*4+1*4),%a2                              /* methodinfo argument in atmp1 */
+       movel   %sp@(11*4+3*4),%a3                              /* args block */
+       movel   %sp@(11*4+2*4),%d2                              /* arg count */
+
+       moveal  %sp, %a5                                        /* memorize stack */
+       tst     %d2                                             /* do we have arguments ? */
+       beq     L_asm_vm_call_method_copy_done
+       subql   #1,%d2                                          /* simplifies offset calulation */
+
+       movel   #(sizevmarg), %d0
+       mulsl   %d2, %d0                                        
+       moveal  %a3, %a0
+       addal   %d0, %a0                                        /* %a0 points to last vmarg block */
 
+       addql   #1, %d2
+L_asm_vm_call_copy_arg:
+       subql   #1, %d2                                         /* why wasn't that here */
+
+       movel   %a0@(offvmargdata+4), %d0
+       movel   %d0,%sp@-                                       /* push argument onto stack */
+
+       movel   %a0@(offvmargtype), %d0                         /* %d0 contains type of arg */  
+       btstl   #0, %d0                                         /* test if 2 word type */
+       beq     L_asm_vm_call_copy_1_word_type
+       movel   %a0@(offvmargdata), %d0                         /* push second word onto stack */
+       movel   %d0,%sp@-
+L_asm_vm_call_copy_1_word_type:
+
+       subl    #(sizevmarg),%a0
+       tst     %d2                                             /* arguments left ? */
+       bne     L_asm_vm_call_copy_arg
+
+L_asm_vm_call_method_copy_done:
+
+       leal    asm_call_jit_compiler,%a4                       /* we need to fake a invocation as it would happen from jit code */
+       movel   %a4, call_jit_dummy                             /* we need a writeable memory location */
+       moveal  call_jit_dummy, %a4                             /* XXX do we have a race condition here ? */
+       jsr     %a4@
+
+L_asm_vm_call_method_return:
+       movel   %a5, %sp                                                /* pop arguments off stack */
+       moveml  %sp@, %d2/%d3/%d4/%d5/%d6/%d7/%a2/%a3/%a4/%a5/%fp       /* restore registers */
+       addal   #(11*4),%sp                                             /* restore stack */
+       rts                                                             /* return to c code */
+       jsr 0   /* never come back ? */
+
+/* asm_vm_call_method_exception_handler        
+ *
+ * calls void *builtin_throw_exception(java_objectheader *xptr) when no other handler is appropiate
+ * this functions gets called indirectly from asm_handle_exception, which back then moved xptr to %a3
+ * clear software design is in the eye of the beholder.
+ */
 asm_vm_call_method_exception_handler:
+       movel   %a3, %sp@-                      /* push xptr argument */
+       jsr     builtin_throw_exception
+       lea     %sp@(4), %sp                    /* pop arg off stack */
+       bra     L_asm_vm_call_method_return
+
 
+asm_vm_call_method_end:                                                /* symbol needed to insert method into avl tree */
+       rts
+/*
+ *     Invokes compiler for untranslated java methods.
+ *     C prototype: void asm_call_jit_compiler(void);
+ *     BUT: this does not match reality, arguments _ARE_ passed via createcompilerstub and asm_vm_call_method...
+ *     arguments passed via %a2(methodinfo) == REG_ATMP1
+ *                           %a3(mptr)       == REG_ATMP2
+ */
 asm_call_jit_compiler:
+       addal   #(-4*4),%sp                                             /* create stackframe to save registers */
+       moveml  %a0/%a1/%d0/%d1,%sp@                                    /* save volatile registers */
+
+       movel   %sp@(4*4),%sp@-                                         /* push arguments onto stack (ra)*/
+       pea     %sp@(4*4+4)                                             /* the old stack pointer */
+       movel   %a3,%sp@-                                               /* mptr */
+       movel   %a2,%sp@-                                               /* methodinfo */
+
+       /* C prototype: u1 *jit_asm_compile(methodinfo *m, u1 *mptr, u1 *sp, u1 *ra); */
+       jsr     jit_asm_compile                                         /* invoke compiler */
+       lea     %sp@(4*4),%sp                                           /* pop arguments off stack */
+       moveal  %d0, %a2                                                /* to tmp register */
 
+       moveml %sp@,%a0/%a1/%d0/%d1                                     /* restore volatile registers */
+       addal   #(4*4),%sp                                              /* remove stackframe */
+
+       tstl    %a2                                                     /* check for exception */
+       beq     L_asm_call_jit_compiler_exception
+
+       jmp     %a2@                                                    /* invoke java method */
+       jsr     0                                                       /* we should not ever return here */
+
+L_asm_call_jit_compiler_exception:
+       jsr     0                                                       /* TODO */
+
+       moveml  %fp@(-4*4), %a0/%a1/%d0/%d1                             /* restore registers */
+       unlk    %fp                                                     /* FIXME: this is wrong */
+       rts
+
+/* asm_patcher_wrapper ********************************************************
+       
+  prepares arguments on stack
+  calls patcher_wrapper signature: java_objectheader *patcher_wrapper(u1 *sp, u1 *pv, u1 *ra);
+
+  Stack layout:
+     24   return address
+     20   REG_ITMP3
+     16   pointer to virtual java_objectheader
+     12   last byte of machine code (xmcode)
+      8   machine code (which is patched back later)
+      4   unresolved field reference
+      0   patcher function pointer to call
+*******************************************************************************/
+asm_patcher_wrapper:
+
+  movel %sp, %d0
+  /* save scratch registers */
+  movel %a0, %sp@-
+  movel %a1, %sp@-
+  movel %d0, %sp@-
+  movel %d1, %sp@-
+#if !defined(ENABLE_SOFTFLOAT)
+  movel %f0, %sp@-
+  movel %f1, %sp@-
+#endif
+
+  clrl %sp@-                           /* pass ra */
+  clrl %sp@-                           /* pass pv, if null use findmethod */
+  movel %d0, %sp@-                     /* pass sp of patcher stub */
+  jsr  patcher_wrapper                 /* return value in %d0 */
+
+  lea  %sp@(3*4), %sp                  /* pop arguments off stack */
+
+  tst  %d0                             /* test if exception occured */
+  bne  L_asm_patcher_wrapper_exception
+
+#if !defined(ENABLE_SOFTFLOAT)
+  movel %sp@+, %f0
+  movel %sp@+, %f1
+#endif
+  movel %sp@+, %d1
+  movel %sp@+, %d0
+  movel %sp@+, %a1
+  movel %sp@+, %a0
+
+  lea   %sp@(6*4), %sp                 /* restore stack and remove patcher stub*/
+  rts                                  /* back to jit code */
+
+L_asm_patcher_wrapper_exception:
+  /* WARNING: the stack is still disturbed, look at asm_patcher_wrapper for details */
+  jsr 0                                        /* TODO */
+
+/********************************************************************************
+       Reads a few values atomically. 
+       C signature:
+       void asm_getclassvalues_atomic(vftbl_t *super, vftbl_t *sub, castinfo *out);
+
+       super ... sp@(4)
+       sub   ... sp@(8)
+       out   ... sp@(12)
+********************************************************************************/
 asm_getclassvalues_atomic:
+_crit_restart:
+_crit_begin:
+       moveal  %sp@(4), %a0
+       movel   %a0@(offbaseval), %d0
+       movel   %a0@(offdiffval), %d1
+       
+       moveal  %sp@(8), %a0
+       moveal  %a0@(offbaseval), %a0
+_crit_end:
+       moveal  %sp@(12), %a1
+       movel   %d0, %a1@(offcast_super_baseval)
+       movel   %d1, %a1@(offcast_super_diffval)
+       movel   %a0, %a1@(offcast_sub_baseval)
+
+       rts
+.data
+asm_criticalsections:
+#if defined(ENABLE_THREADS)
+       .long _crit_begin
+       .long _crit_end
+       .long _crit_restart
+#endif
+       .long 0
+.text
 
 asm_abstractmethoderror:
 
-asm_criticalsections:
+/* asm_handle_exception ********************************************************
+*                                                                              *
+*   This function handles an exception. It does not use the usual calling      *
+*   conventions. The exception pointer is passed in REG_ATMP1 and the          *
+*   pc from the exception raising position is passed in REG_ATMP2. It searches *
+*   the local exception table for a handler. If no one is found, it unwinds    *
+*   stacks and continues searching the callers.                                *
+*                                                                              *
+*   void asm_handle_exception (void);
+*   exception object pointer...%a2   exception raising address...%a3           *
+*                                                                              *
+*******************************************************************************/
+asm_handle_exception:
+asm_handle_nat_exception:
+L_asm_handle_exception_stack_loop:
+       
+       /* we need the dseg, figure it out */
+       movel   %a3, %sp@-                              /* push ra argument */
+       jsr     md_codegen_get_pv_from_pc               /* pv in %d0 now */
+       movel   %d0, %d2                                /* move to safe register */
+       lea     %sp@(4), %sp                            /* pop args off stack */
+
+       /* now call the following c function */
+       /* u1 *exceptions_handle_exception(java_objectheader *xptr, u1 *xpc, u1 *pv, u1 *sp) */
+       movel   %sp,%sp@-
+       movel   %d2,%sp@-
+       movel   %a3,%sp@-
+       movel   %a2,%sp@-
+       jsr     exceptions_handle_exception             /* %d0 is address of handler or 0 when not catched */
+       lea     %sp@(4*4), %sp                          /* pop args off stack */
+       tstl    %d0
+       beq     L_asm_handle_exception_not_catched
+
+       /* %d0 contains address of exception handler */
+       moveal  %d0, %a0
+       jsr     %a0@
+
+L_asm_handle_exception_not_catched:
+       jsr 0
+illegal
+.long 0x23234242
index 3a93412bf2426ce2c1358c006168bd55dec20aa1..844ed7825bd377764bc1bcabd2061bd30a9325cc 100644 (file)
-void codegen(void) {}
-void createnativestub(void) {}
-void createcompilerstub(void) {}
+/* src/vm/jit/m68k/codegen.c
+
+   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.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   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., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
+
+   $Id: codegen.c 7564 2007-03-23 23:36:17Z twisti $
+*/
+
+
+#include "config.h"
+
+#include <assert.h>
+
+#include "md-abi.h"
+
+#include "vm/types.h"
+#include "vm/jit/m68k/codegen.h"
+#include "vm/jit/m68k/emit.h"
+
+#include "mm/memory.h"
+#include "native/jni.h"
+#include "native/native.h"
+
+#if defined(ENABLE_THREADS)
+# include "threads/native/lock.h"
+#endif
+
+#include "vm/builtin.h"
+#include "vm/exceptions.h"
+#include "vm/global.h"
+#include "vm/stringlocal.h"
+#include "vm/vm.h"
+
+#include "vm/jit/asmpart.h"
+#include "vm/jit/codegen-common.h"
+#include "vm/jit/dseg.h"
+#include "vm/jit/emit-common.h"
+#include "vm/jit/jit.h"
+#include "vm/jit/parse.h"
+#include "vm/jit/patcher.h"
+#include "vm/jit/reg.h"
+#include "vm/jit/replace.h"
+#include "vm/jit/stacktrace.h"
+#include "vm/jit/md.h"
+
+#include "vmcore/loader.h"
+#include "vmcore/options.h"
+#include "vmcore/utf8.h"
+
+
+bool codegen_emit(jitdata *jd) 
+{      
+       methodinfo         *m;
+       codeinfo           *code;
+       codegendata        *cd;
+       registerdata       *rd;
+       s4                  len, s1, s2, s3, d, disp;
+       ptrint              a;
+       varinfo            *var;
+       basicblock         *bptr;
+       instruction        *iptr;
+       exception_entry    *ex;
+       u2                  currentline;
+       methodinfo         *lm;             /* local methodinfo for ICMD_INVOKE*  */
+       unresolved_method  *um;
+       builtintable_entry *bte;
+       methoddesc         *md;
+       s4                  fieldtype;
+       s4                  varindex;
+       unresolved_field   *uf;
+       fieldinfo          *fi;
+
+       /* get required compiler data */
+
+       m    = jd->m;
+       code = jd->code;
+       cd   = jd->cd;
+       rd   = jd->rd;
+
+       /* prevent compiler warnings */
+
+       d = 0;
+       lm = NULL;
+       bte = NULL;
+
+       {
+               s4 i, p, t, l;
+               /* save calle saved registers */
+               s4 savedregs_num = 0;
+
+               savedregs_num += (INT_SAV_CNT - rd->savintreguse);
+               savedregs_num += (ADR_SAV_CNT - rd->savadrreguse);
+               savedregs_num += (FLT_SAV_CNT - rd->savfltreguse) * 2;
+
+               cd->stackframesize = rd->memuse + savedregs_num;
+#if defined(ENABLE_THREADS)
+               assert(0);
+#endif
+       
+               /* create method header */
+               (void) dseg_add_unique_address(cd, code);              /* CodeinfoPointer */
+               (void) dseg_add_unique_s4(cd, cd->stackframesize * 4); /* FrameSize       */
+#if defined(ENABLE_THREADS)
+               if (checksync && (m->flags & ACC_SYNCHRONIZED))
+                       (void) dseg_add_unique_s4(cd, (rd->memuse + 1) * 4);/* IsSync         */
+               else
+#endif
+                       (void) dseg_add_unique_s4(cd, 0);                  /* IsSync          */
+               (void) dseg_add_unique_s4(cd, jd->isleafmethod);       /* IsLeaf          */
+               (void) dseg_add_unique_s4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
+               (void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
+
+               dseg_addlinenumbertablesize(cd);
+
+               (void) dseg_add_unique_s4(cd, jd->exceptiontablelength); /* ExTableSize   */
+
+               /* create exception table */
+               for (ex = jd->exceptiontable; ex != NULL; ex = ex->down) {
+                       dseg_add_target(cd, ex->start);
+                       dseg_add_target(cd, ex->end);
+                       dseg_add_target(cd, ex->handler);
+                       (void) dseg_add_unique_address(cd, ex->catchtype.any);
+               }
+
+#if defined(ENABLE_PROFILING)
+               assert(0);
+#endif
+
+#if !defined(NDEBUG)
+               emit_verbosecall_enter(jd);
+#endif
+               /* create stack frame */
+               M_AADD_IMM(-(cd->stackframesize*4), REG_SP);
+
+               /* save used callee saved registers */
+               p = cd->stackframesize;
+               for (i=INT_SAV_CNT-1; i>=rd->savintreguse; --i) {
+                       p--; M_IST(rd->savintregs[i], REG_SP, p*4);
+               }
+               for (i=ADR_SAV_CNT-1; i>=rd->savadrreguse; --i) {
+                       p--; M_AST(rd->savadrregs[i], REG_SP, p*4);
+               }
+#if !defined(ENABLE_SOFTFLOAT)
+               for (i=FLT_SAV_CNT-1; i>=rd->savfltreguse; --i) {
+                       p-=2; M_FST(rd->savfltregs[i], REG_SP, p*4);    /* FIXME */
+               }       
+#else
+               assert(FLT_SAV_CNT == 0);
+               assert(rd->savfltreguse == 0);
+#endif
+               /* take arguments out of stack frame */
+               md = m->parseddesc;
+               for (p = 0, l = 0; p < md->paramcount; p++) {
+                       t = md->paramtypes[p].type;
+                       varindex = jd->local_map[l * 5 + t];
+       
+                       l++;
+                       if (IS_2_WORD_TYPE(t))    /* increment local counter for 2 word types */
+                               l++;
+
+                       if (varindex == UNUSED)
+                               continue;
+
+                       var = VAR(varindex);
+       
+                       s1 = md->params[p].regoff;
+                       assert(md->params[p].inmemory);                 /* all args are on stack */
+
+                       switch (t)      {
+#if defined(ENABLE_SOFTFLOAT)
+                       case TYPE_FLT:
+                       case TYPE_DBL:
+#endif
+                       case TYPE_LNG:
+                       case TYPE_INT:
+                               if (!IS_INMEMORY(var->flags)) {      /* stack arg -> register */
+                                       if (IS_2_WORD_TYPE(t))  {
+                                               M_LLD(var->vv.regoff, REG_SP, (cd->stackframesize + s1 + 1) * 4);
+                                       } else {
+                                               M_ILD(var->vv.regoff, REG_SP, (cd->stackframesize + s1 + 1) * 4);
+                                       }
+                               } else {                             /* stack arg -> spilled  */
+#if 1
+                                       M_ILD(REG_ITMP1, REG_SP, (cd->stackframesize + s1 + 1) * 4);
+                                       M_IST(REG_ITMP1, REG_SP, var->vv.regoff * 4);
+                                       if (IS_2_WORD_TYPE(t)) {
+                                               M_ILD(REG_ITMP1, REG_SP, (cd->stackframesize + s1 + 1) * 4 + 4);
+                                               M_IST(REG_ITMP1, REG_SP, var->vv.regoff * 4 + 4);
+                                       }
+#else
+                                       /* Reuse Memory Position on Caller Stack */
+                                       var->vv.regoff = cd->stackframesize + s1;
+#endif
+                               } 
+                               break;
+#if !defined(ENABLE_SOFTFLOAT)
+                       case TYPE_FLT:
+                       case TYPE_DBL:
+                               if (!IS_INMEMORY(var->flags)) {      /* stack-arg -> register */
+                                       if (IS_2_WORD_TYPE(t))  {
+                                               M_DLD(var->vv.regoff, REG_SP, (cd->stackframesize + s1 + 1) * 4);
+                                       } else {
+                                               M_FLD(var->vv.regoff, REG_SP, (cd->stackframesize + s1 + 1) * 4);
+                                       }
+                               } else {                             /* stack-arg -> spilled  */
+#if 1
+                                       if (IS_2_WORD_TYPE(t)) {
+                                               M_DLD(REG_FTMP1, REG_SP, (cd->stackframesize + s1 + 1) * 4);
+                                               M_DST(REG_FTMP1, REG_SP, var->vv.regoff * 4);
+                                       } else {
+                                               M_FLD(REG_FTMP1, REG_SP, (cd->stackframesize + s1 + 1) * 4);
+                                               M_FST(REG_FTMP1, REG_SP, var->vv.regoff * 4);
+                                       }
+#else
+                                       /* Reuse Memory Position on Caller Stack */
+                                       var->vv.regoff = cd->stackframesize + s1;
+#endif
+                               }
+                               break;
+#endif /* SOFTFLOAT */
+                       case TYPE_ADR:
+                               if (!IS_INMEMORY(var->flags)) {      /* stack-arg -> register */
+                                       M_ALD(var->vv.regoff, REG_SP, (cd->stackframesize + s1 + 1) * 4);
+                               } else {                             /* stack-arg -> spilled  */
+#if 1
+                                       M_ALD(REG_ATMP1, REG_SP, (cd->stackframesize + s1 + 1) * 4);
+                                       M_AST(REG_ATMP1, REG_SP, var->vv.regoff * 4);
+#else
+                               /* Reuse Memory Position on Caller Stack */
+                               var->vv.regoff = cd->stackframesize + s1;
+#endif
+                               }
+                               break;
+                       default: assert(0);
+                       }
+               } /* end for argument out of stack*/
+       }
+
+
+
+       /* create replacement points */
+       REPLACEMENT_POINTS_INIT(cd, jd);
+
+       /* foreach basic block */
+       for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
+       
+       bptr->mpc = (s4) (cd->mcodeptr - cd->mcodebase);
+
+       if (bptr->flags >= BBREACHED)   {
+       
+       /* branch resolving */
+       codegen_resolve_branchrefs(cd, bptr);
+
+       /* FIXME there are still some constrcuts to copy in here */
+
+       /* walk through all instructions */
+       len = bptr->icount;
+       currentline = 0;
+
+       for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
+               if (iptr->line != currentline) {
+                       dseg_addlinenumber(cd, iptr->line);
+                       currentline = iptr->line;
+               }
+
+               MCODECHECK(1024);                         /* 1kB should be enough */
+
+               switch (iptr->opc) {
+               case ICMD_NOP:        /* ...  ==> ...                                 */
+               case ICMD_POP:        /* ..., value  ==> ...                          */
+               case ICMD_POP2:       /* ..., value, value  ==> ...                   */
+                       break;
+
+               case ICMD_INLINE_START:
+
+                       REPLACEMENT_POINT_INLINE_START(cd, iptr);
+                       break;
+
+               case ICMD_INLINE_BODY:
+
+                       REPLACEMENT_POINT_INLINE_BODY(cd, iptr);
+                       dseg_addlinenumber_inline_start(cd, iptr);
+                       dseg_addlinenumber(cd, iptr->line);
+                       break;
+
+               case ICMD_INLINE_END:
+
+                       dseg_addlinenumber_inline_end(cd, iptr);
+                       dseg_addlinenumber(cd, iptr->line);
+                       break;
+
+               case ICMD_CHECKNULL:  /* ..., objectref  ==> ..., objectref           */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       assert(VAROP(iptr->s1)->type == TYPE_ADR);
+                       emit_nullpointer_check(cd, iptr, s1);
+                       break;
+
+
+               /* CONST **************************************************************/
+               case ICMD_ICONST:     /* ...  ==> ..., constant                       */
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+                       M_IMOV_IMM(iptr->sx.val.i, d);
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+               case ICMD_LCONST:     /* ...  ==> ..., constant                       */
+
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
+                       LCONST(iptr->sx.val.l, d);
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+               case ICMD_FCONST:     /* ...  ==> ..., constant                       */
+
+#if defined(ENABLE_SOFTFLOAT)
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+                       M_IMOV_IMM(iptr->sx.val.i, d);
+                       emit_store_dst(jd, iptr, d);
+#else
+                       d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
+                       FCONST(iptr->sx.val.f, d);
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       break;
+
+               case ICMD_DCONST:     /* ...  ==> ..., constant                       */
+
+#if defined(ENABLE_SOFTFLOAT)
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
+                       LCONST(iptr->sx.val.l, d);
+                       emit_store_dst(jd, iptr, d);
+#else
+                       d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
+                       DCONST(iptr->sx.val.d, d);
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       break;
+
+
+
+               /* integer operations ************************************************/
+               case ICMD_INEG:       /* ..., value  ==> ..., - value                 */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1); 
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+                       M_INTMOVE(s1, REG_ITMP1);
+                       M_INEG(REG_ITMP1);
+                       M_INTMOVE(REG_ITMP1, d);
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+#if 0
+               case ICMD_LNEG:       /* ..., value  ==> ..., - value                 */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
+                       M_SUBFIC(GET_LOW_REG(s1), 0, GET_LOW_REG(d));
+                       M_SUBFZE(GET_HIGH_REG(s1), GET_HIGH_REG(d));
+                       emit_store_dst(jd, iptr, d);
+                       break;
+#endif
+               case ICMD_I2L:        /* ..., value  ==> ..., value                   */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP2);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
+                       M_INTMOVE(s1, GET_LOW_REG(d));                          /* sets negativ bit */
+                       M_BPL(4);
+                       M_ISET(GET_HIGH_REG(d));
+                       M_TPFW;
+                       M_ICLR(GET_HIGH_REG(d));
+
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+               case ICMD_L2I:        /* ..., value  ==> ..., value                   */
+
+                       s1 = emit_load_s1_low(jd, iptr, REG_ITMP2);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+                       M_INTMOVE(s1, d);
+                       emit_store_dst(jd, iptr, d);
+                       break;
+               case ICMD_INT2BYTE:   /* ..., value  ==> ..., value                   */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+                       M_BSEXT(s1, d);
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+               case ICMD_INT2CHAR:   /* ..., value  ==> ..., value                   */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+                       M_CZEXT(s1, d);
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+               case ICMD_INT2SHORT:  /* ..., value  ==> ..., value                   */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+                       M_SSEXT(s1, d);
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+
+
+               case ICMD_IADD:       /* ..., val1, val2  ==> ..., val1 + val2        */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+                       M_INTMOVE(s2, REG_ITMP2);
+                       M_IADD(s1, REG_ITMP2);
+                       M_INTMOVE(REG_ITMP2, d);
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+                                     /* s1.localindex = variable, sx.val.i = constant*/
+
+               case ICMD_IINC:
+               case ICMD_IADDCONST:
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+                       M_INTMOVE(s1, REG_ITMP1);
+                       M_IADD_IMM(iptr->sx.val.i, REG_ITMP1);
+                       M_INTMOVE(REG_ITMP1, d);
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+               case ICMD_ISUB:       /* ..., val1, val2  ==> ..., val1 - val2        */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+                       M_INTMOVE(s1, REG_ITMP1);
+                       M_ISUB(s2, REG_ITMP1);
+                       M_INTMOVE(REG_ITMP1, d);
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+               case ICMD_ISUBCONST:  /* ..., value  ==> ..., value + constant        */
+                                     /* sx.val.i = constant                          */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+                       M_INTMOVE(s1, REG_ITMP1);
+                       M_IADD_IMM(-iptr->sx.val.i, REG_ITMP1);
+                       M_INTMOVE(REG_ITMP1, d);
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+               case ICMD_IDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+                       emit_arithmetic_check(cd, iptr, s2);
+
+                       M_INTMOVE(s1, REG_ITMP1);
+                       M_IDIV(s2, REG_ITMP1);
+                       M_INTMOVE(REG_ITMP1, d);
+
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+               case ICMD_IREM:       /* ..., val1, val2  ==> ..., val1 % val2        */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
+                       emit_arithmetic_check(cd, iptr, s2);
+
+                       M_IREM(s2, s1, REG_ITMP3);
+                       M_INTMOVE(REG_ITMP3, d);
+
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+               case ICMD_LDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
+               case ICMD_LREM:       /* ..., val1, val2  ==> ..., val1 % val2        */
+
+                       bte = iptr->sx.s23.s3.bte;
+                       md  = bte->md;
+
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP12_PACKED);
+                       M_INTMOVE(GET_LOW_REG(s2), REG_ITMP3);
+                       M_IOR(GET_HIGH_REG(s2), REG_ITMP3);
+                       /* XXX could be optimized */
+                       emit_arithmetic_check(cd, iptr, REG_ITMP3);
+
+                       M_LST(s2, REG_SP, 2 * 4);
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED);
+                       M_LST(s1, REG_SP, 0 * 4);
+
+                       M_JSR_IMM(bte->fp);
+
+                       d = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
+                       M_LNGMOVE(REG_RESULT_PACKED, d);
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+               case ICMD_IMUL:       /* ..., val1, val2  ==> ..., val1 * val2        */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+                       M_INTMOVE(s2, REG_ITMP2);
+                       M_IMUL(s1, REG_ITMP2);
+                       M_INTMOVE(REG_ITMP2, d);
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+               case ICMD_IMULCONST:  /* ..., value  ==> ..., value * constant        */
+                                     /* sx.val.i = constant                          */
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+                       M_IMOV_IMM(iptr->sx.val.i, REG_ITMP2);
+                       M_IMUL(s1, REG_ITMP2);
+                       M_INTMOVE(REG_ITMP2, d);
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+               case ICMD_ISHL:       /* ..., val1, val2  ==> ..., val1 << val2       */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+                       M_INTMOVE(s1, REG_ITMP1);
+                       M_INTMOVE(s2, REG_ITMP2);
+                       M_IAND_IMM(0x1f, REG_ITMP2);
+                       M_ISSL(REG_ITMP2, REG_ITMP1);
+                       M_INTMOVE(REG_ITMP1, d);
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+               case ICMD_ISHLCONST:  /* ..., value  ==> ..., value << constant       */
+                                     /* sx.val.i = constant                          */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+                       M_INTMOVE(s1, REG_ITMP1)
+                       M_ISSL_IMM(iptr->sx.val.i & 0x1f, REG_ITMP1);
+                       M_INTMOVE(REG_ITMP1, d);
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+               case ICMD_ISHR:       /* ..., val1, val2  ==> ..., val1 >> val2       */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+                       M_INTMOVE(s1, REG_ITMP1);
+                       M_INTMOVE(s2, REG_ITMP2);
+                       M_IAND_IMM(0x1f, REG_ITMP2);
+                       M_ISSR(REG_ITMP2, REG_ITMP1);
+                       M_INTMOVE(REG_ITMP1, d);
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+               case ICMD_ISHRCONST:  /* ..., value  ==> ..., value >> constant       */
+                                     /* sx.val.i = constant                          */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+                       M_INTMOVE(s1, REG_ITMP1)
+                       M_ISSR_IMM(iptr->sx.val.i & 0x1f, REG_ITMP1);
+                       M_INTMOVE(REG_ITMP1, d);
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+               case ICMD_IUSHR:      /* ..., val1, val2  ==> ..., val1 >>> val2      */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+                       M_INTMOVE(s1, REG_ITMP1);
+                       M_INTMOVE(s2, REG_ITMP2);
+                       M_IAND_IMM(0x1f, REG_ITMP2);
+                       M_IUSR(REG_ITMP2, REG_ITMP1);
+                       M_INTMOVE(REG_ITMP1, d);
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+               case ICMD_IUSHRCONST: /* ..., value  ==> ..., value >>> constant      */
+                                     /* sx.val.i = constant                          */
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+                       M_INTMOVE(s1, REG_ITMP1)
+                       M_IUSR_IMM(iptr->sx.val.i & 0x1f, REG_ITMP1);
+                       M_INTMOVE(REG_ITMP1, d);
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+               case ICMD_IAND:       /* ..., val1, val2  ==> ..., val1 & val2        */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+                       M_INTMOVE(s2, REG_ITMP2);
+                       M_IAND(s1, REG_ITMP2);
+                       M_INTMOVE(REG_ITMP2, d);
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+               case ICMD_IANDCONST:  /* ..., value  ==> ..., value & constant        */
+                                     /* sx.val.i = constant                          */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+                       M_INTMOVE(s1, REG_ITMP1);
+                       M_IAND_IMM(iptr->sx.val.i, REG_ITMP1);
+                       M_INTMOVE(REG_ITMP1, d);
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+
+
+
+               /* load/store/copy/move operations ************************************/
+
+               case ICMD_ILOAD:      /* ...  ==> ..., content of local variable      */
+               case ICMD_ALOAD:      /* s1 = local variable                          */
+               case ICMD_LLOAD:
+               case ICMD_FLOAD:  
+               case ICMD_DLOAD:  
+               case ICMD_ISTORE:     /* ..., value  ==> ...                          */
+               case ICMD_LSTORE:
+               case ICMD_FSTORE:
+               case ICMD_DSTORE: 
+               case ICMD_COPY:
+               case ICMD_MOVE:
+                       emit_copy(jd, iptr, VAROP(iptr->s1), VAROP(iptr->dst));
+                       break;
+
+               case ICMD_ASTORE:
+                       if (!(iptr->flags.bits & INS_FLAG_RETADDR))
+                               emit_copy(jd, iptr, VAROP(iptr->s1), VAROP(iptr->dst));
+                       break;
+
+
+               case ICMD_ACONST:     /* ...  ==> ..., constant                       */
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                               constant_classref *cr = iptr->sx.val.c.ref;;
+                               codegen_addpatchref(cd, PATCHER_resolve_classref_to_classinfo, cr, 0);
+                               M_AMOV_IMM(0, d);
+                       } else {
+                               M_AMOV_IMM(iptr->sx.val.anyptr, d);
+                       }
+                       emit_store_dst(jd, iptr, d);
+                       break;
+               /* BRANCH *************************************************************/
+
+               case ICMD_ATHROW:       /* ..., objectref ==> ... (, objectref)       */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ATMP1);
+                       M_ADRMOVE(s1, REG_ATMP1_XPTR);
+
+#ifdef ENABLE_VERIFIER
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                               unresolved_class *uc = iptr->sx.s23.s2.uc;
+
+                               codegen_addpatchref(cd, PATCHER_resolve_class, uc, 0);
+                       }
+#endif /* ENABLE_VERIFIER */
+                       M_JSR_PCREL(2);                         /* get current PC */
+                       M_APOP(REG_ATMP2);              
+
+                       M_AMOV_IMM(asm_handle_exception, REG_ATMP3);
+                       M_JMP(REG_ATMP3);
+                       ALIGNCODENOP;
+                       break;
+
+               case ICMD_GOTO:         /* ... ==> ...                                */
+               case ICMD_RET:          /* ... ==> ...                                */
+
+                       emit_br(cd, iptr->dst.block);
+                       ALIGNCODENOP;
+                       break;
+
+               case ICMD_JSR:          /* ... ==> ...                                */
+
+                       emit_br(cd, iptr->sx.s23.s3.jsrtarget.block);
+                       ALIGNCODENOP;
+                       break;
+
+
+
+               case ICMD_IFNULL:       /* ..., value ==> ...                         */
+               case ICMD_IFNONNULL:
+                       assert(IS_ADR_TYPE(VAROP(iptr->s1)->type));
+                       s1 = emit_load_s1(jd, iptr, REG_ATMP1);
+                       M_ATST(s1);
+                       emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IFNULL, BRANCH_OPT_NONE);
+                       break;
+
+               case ICMD_IFLT:
+               case ICMD_IFLE:
+               case ICMD_IFNE:
+               case ICMD_IFGT:
+               case ICMD_IFGE:
+               case ICMD_IFEQ:         /* ..., value ==> ...                         */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       assert (VAROP(iptr->s1)->type == TYPE_INT);
+                       M_ICMP_IMM(iptr->sx.val.i, s1); 
+                       emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IFEQ, BRANCH_OPT_NONE);
+                       break;
+
+               case ICMD_IF_ICMPEQ:    /* ..., value, value ==> ...                  */
+               case ICMD_IF_ICMPNE:
+               case ICMD_IF_ICMPLT:
+               case ICMD_IF_ICMPGT:
+               case ICMD_IF_ICMPLE:
+               case ICMD_IF_ICMPGE:
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+                       M_ICMP(s2, s1);
+                       emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IF_ICMPEQ, BRANCH_OPT_NONE);
+                       break;
+
+               case ICMD_IF_ACMPEQ:    /* op1 = target JavaVM pc                     */
+               case ICMD_IF_ACMPNE:
+
+                       s1 = emit_load_s1(jd, iptr, REG_ATMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ATMP2);
+                       M_ACMP(s1, s2);
+                       emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IF_ACMPEQ, BRANCH_OPT_NONE);
+                       break;
+
+
+               /* MEMORY *************************************************************/
+               case ICMD_GETSTATIC:
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr))    {
+                               assert(0);
+                       } else  {
+                               fieldinfo *fi = iptr->sx.s23.s3.fmiref->p.field;
+
+                               fieldtype = fi->type;
+                               if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
+                                       codegen_addpatchref(cd, PATCHER_initialize_class, fi->class, disp);
+                               }
+
+                               disp = (ptrint) &(fi->value);
+                       }
+                       M_AMOV_IMM(disp, REG_ATMP1);
+                       switch (fieldtype) {
+#if defined(ENABLE_SOFTFLOAT)
+                       case TYPE_FLT:
+#endif
+                       case TYPE_INT:
+                               d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+                               M_ILD(d, REG_ATMP1, 0);
+                               break;
+                       case TYPE_ADR:
+                               d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+                               M_ALD(d, REG_ATMP1, 0);
+                               break;
+#if defined(ENABLE_SOFTFLOAT)
+                       case TYPE_DBL:
+#endif
+                       case TYPE_LNG:
+                               d = codegen_reg_of_dst(jd, iptr, REG_ITMP23_PACKED);
+                               M_LLD(d, REG_ATMP1, 0);
+                               break;
+#if !defined(ENABLE_SOFTFLOAT)
+                       case TYPE_FLT:
+                               d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
+                               M_FLD(d, REG_ATMP1, 0);
+                               break;
+                       case TYPE_DBL:                          
+                               d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
+                               M_DLD(d, REG_ATMP1, 0);
+                               break;
+#endif
+                       }
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+               case ICMD_PUTSTATIC:  /* ..., value  ==> ...                          */
+
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                               uf        = iptr->sx.s23.s3.uf;
+                               fieldtype = uf->fieldref->parseddesc.fd->type;
+
+                               codegen_addpatchref(cd, PATCHER_get_putstatic, uf, 0);
+                       } else {
+                               fi        = iptr->sx.s23.s3.fmiref->p.field;
+                               fieldtype = fi->type;
+                               disp      = &(fi->value);
+
+                               if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
+                                       codegen_addpatchref(cd, PATCHER_initialize_class, fi->class, 0);
+                       }
+               
+                       M_AMOV_IMM(disp, REG_ATMP1);
+                       switch (fieldtype) {
+#if defined(ENABLE_SOFTFLOAT)
+                       case TYPE_FLT:
+#endif
+                       case TYPE_INT:
+                               s1 = emit_load_s1(jd, iptr, REG_ITMP2);
+                               M_IST(s1, REG_ATMP1, 0);
+                               break;
+#if defined(ENABLE_SOFTFLOAT)
+                       case TYPE_DBL:
+#endif
+                       case TYPE_LNG:
+                               s1 = emit_load_s1(jd, iptr, REG_ITMP23_PACKED);
+                               M_LST(s1, REG_ATMP1, 0);
+                               break;
+                       case TYPE_ADR:
+                               s1 = emit_load_s1(jd, iptr, REG_ITMP2);
+                               M_AST(s1, REG_ATMP1, 0);
+                               break;
+#if !defined(ENABLE_SOFTFLOAT)
+                       case TYPE_FLT:
+                               s1 = emit_load_s1(jd, iptr, REG_FTMP2);
+                               M_FST(s1, REG_ATMP1, 0);
+                               break;
+                       case TYPE_DBL:
+                               s1 = emit_load_s1(jd, iptr, REG_FTMP2);
+                               M_DST(s1, REG_ATMP1, 0);
+                               break;
+#endif
+                       default: assert(0);
+                       }
+                       break;
+
+               case ICMD_GETFIELD:   /* ...  ==> ..., value                          */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                               uf        = iptr->sx.s23.s3.uf;
+                               fieldtype = uf->fieldref->parseddesc.fd->type;
+                               disp      = 0;
+
+                               codegen_addpatchref(cd, PATCHER_get_putfield, uf, 0);
+                       }
+                       else {
+                               fi        = iptr->sx.s23.s3.fmiref->p.field;
+                               fieldtype = fi->type;
+                               disp      = fi->offset;
+                       }
+
+                       /* implicit null-pointer check */
+                       switch (fieldtype) {
+#if defined(ENABLE_SOFTFLOAT)
+                       case TYPE_FLT:
+#endif
+                       case TYPE_INT:
+                               d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+                               M_ILD(d, s1, disp);
+                               break;
+#if defined(ENABLE_SOFTFLOAT)
+                       case TYPE_DBL:
+#endif
+                       case TYPE_LNG:
+                               d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
+                               if (GET_HIGH_REG(d) == s1) {
+                                       M_ILD(GET_LOW_REG(d), s1, disp + 4);
+                                       M_ILD(GET_HIGH_REG(d), s1, disp);
+                               } else {
+                                       M_ILD(GET_HIGH_REG(d), s1, disp);
+                                       M_ILD(GET_LOW_REG(d), s1, disp + 4);
+                               }
+                               break;
+                       case TYPE_ADR:
+                               d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+                               M_ALD(d, s1, disp);
+                               break;
+#if !defined(ENABLE_SOFTFLOAT)
+                       case TYPE_FLT:
+                               d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
+                               M_FLD(d, s1, disp);
+                               break;
+                       case TYPE_DBL:                          
+                               d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
+                               M_DLD(d, s1, disp);
+                               break;
+#endif
+                       }
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+               case ICMD_PUTFIELD:   /* ..., value  ==> ...                          */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ATMP1);
+
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                               uf        = iptr->sx.s23.s3.uf;
+                               fieldtype = uf->fieldref->parseddesc.fd->type;
+                               disp      = 0;
+                       }
+                       else {
+                               fi        = iptr->sx.s23.s3.fmiref->p.field;
+                               fieldtype = fi->type;
+                               disp      = fi->offset;
+                       }
+
+                       if (IS_INT_LNG_TYPE(fieldtype)) {
+                               if (IS_2_WORD_TYPE(fieldtype)) {
+                                       s2 = emit_load_s2(jd, iptr, REG_ITMP23_PACKED);
+                               } else {
+                                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+                               }
+                       } else {
+                               s2 = emit_load_s2(jd, iptr, REG_FTMP2);
+                       }
+
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr))
+                               codegen_addpatchref(cd, PATCHER_get_putfield, uf, 0);
+
+                       /* implicit null-pointer check */
+                       switch (fieldtype) {
+#if defined(ENABLE_SOFTFLOAT)
+                       case TYPE_FLT:
+#endif
+                       case TYPE_INT:
+                               M_IST(s2, s1, disp);
+                               break;
+
+#if defined(ENABLE_SOFTFLOAT)
+                       case TYPE_DBL:
+#endif
+                       case TYPE_LNG:
+                               M_IST(GET_LOW_REG(s2), s1, disp + 4);      /* keep this order */
+                               M_IST(GET_HIGH_REG(s2), s1, disp);         /* keep this order */
+                               break;
+                       case TYPE_ADR:
+                               M_AST(s2, s1, disp);
+                               break;
+#if !defined(ENABLE_SOFTFLOAT)
+                       case TYPE_FLT:
+                               M_FST(s2, s1, disp);
+                               break;
+                       case TYPE_DBL:
+                               M_DST(s2, s1, disp);
+                               break;
+#endif
+                       }
+                       break;
+
+               case ICMD_ARRAYLENGTH: /* ..., arrayref  ==> ..., length              */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ATMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+                       /* implicit null-pointer check */
+                       M_ILD(d, s1, OFFSET(java_arrayheader, size));
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+               case ICMD_BALOAD:     /* ..., arrayref, index  ==> ..., value         */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ATMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
+                       M_INTMOVE(s2, REG_ITMP2);
+                       M_IADD_IMM(OFFSET(java_bytearray, data[0]), REG_ITMP2);
+                       M_ADRMOVE(s1, REG_ATMP1);
+                       M_AADDINT(REG_ITMP2, REG_ATMP1);
+                       /* implicit null-pointer check */
+                       M_LBZX(REG_ATMP1, d);
+                       M_BSEXT(d, d);
+                       emit_store_dst(jd, iptr, d);
+                       break;                  
+
+               case ICMD_CALOAD:     /* ..., arrayref, index  ==> ..., value         */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ATMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
+                       M_INTMOVE(s2, REG_ITMP2);
+                       M_ISSL_IMM(1, REG_ITMP2);
+                       M_IADD_IMM(OFFSET(java_chararray, data[0]), REG_ITMP2);
+                       M_ADRMOVE(s1, REG_ATMP1);
+                       M_AADDINT(REG_ITMP2, REG_ATMP1);
+                       /* implicit null-pointer check */
+                       M_LHZX(REG_ATMP1, d);
+                       /*M_CZEXT(d, d);*/
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+               case ICMD_SALOAD:     /* ..., arrayref, index  ==> ..., value         */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ATMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
+                       M_INTMOVE(s2, REG_ITMP2);
+                       M_ISSL_IMM(1, REG_ITMP2);
+                       M_IADD_IMM(OFFSET(java_shortarray, data[0]), REG_ITMP2);
+                       M_ADRMOVE(s1, REG_ATMP1);
+                       M_AADDINT(REG_ITMP2, REG_ATMP1);
+               
+                       /* implicit null-pointer check */
+                       M_LHZX(REG_ATMP1, d);
+                       M_HSEXT(d, d);
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+               case ICMD_IALOAD:     /* ..., arrayref, index  ==> ..., value         */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ATMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
+                       M_INTMOVE(s2, REG_ITMP2);
+                       M_ISSL_IMM(2, REG_ITMP2);
+                       M_IADD_IMM(OFFSET(java_intarray, data[0]), REG_ITMP2);
+                       M_ADRMOVE(s1, REG_ATMP1);
+                       M_AADDINT(REG_ITMP2, REG_ATMP1);
+       
+                       /* implicit null-pointer check */
+                       M_LWZX(REG_ATMP1, d);
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+#if 0
+               case ICMD_LALOAD:     /* ..., arrayref, index  ==> ..., value         */
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
+                       M_SLL_IMM(s2, 3, REG_ITMP2);
+                       M_IADD(s1, REG_ITMP2, REG_ITMP2);
+                       M_LLD_INTERN(d, REG_ITMP2, OFFSET(java_longarray, data[0]));
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+               case ICMD_FALOAD:     /* ..., arrayref, index  ==> ..., value         */
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+                       d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
+                       M_SLL_IMM(s2, 2, REG_ITMP2);
+                       M_IADD_IMM(REG_ITMP2, OFFSET(java_floatarray, data[0]), REG_ITMP2);
+                       /* implicit null-pointer check */
+                       M_LFSX(d, s1, REG_ITMP2);
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+               case ICMD_DALOAD:     /* ..., arrayref, index  ==> ..., value         */
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+                       d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
+                       M_SLL_IMM(s2, 3, REG_ITMP2);
+                       M_IADD_IMM(REG_ITMP2, OFFSET(java_doublearray, data[0]), REG_ITMP2);
+                       /* implicit null-pointer check */
+                       M_LFDX(d, s1, REG_ITMP2);
+                       emit_store_dst(jd, iptr, d);
+                       break;
+               #endif
+
+               case ICMD_AALOAD:     /* ..., arrayref, index  ==> ..., value         */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ATMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
+                       M_INTMOVE(s2, REG_ITMP2);
+                       M_ISSL_IMM(2, REG_ITMP2);
+                       M_IADD_IMM(OFFSET(java_objectarray, data[0]), REG_ITMP2);
+                       M_ADRMOVE(s1, REG_ATMP1);
+                       M_AADDINT(REG_ITMP2, REG_ATMP1);
+       
+                       /* implicit null-pointer check */
+                       M_LAX(REG_ATMP1, d);
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+
+               case ICMD_BASTORE:    /* ..., arrayref, index, value  ==> ...         */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
+                       s3 = emit_load_s3(jd, iptr, REG_ITMP3);
+                       M_INTMOVE(s2, REG_ITMP2);
+                       M_IADD_IMM(OFFSET(java_bytearray, data[0]), REG_ITMP2);
+                       M_ADRMOVE(s1, REG_ATMP1);
+                       M_AADDINT(REG_ITMP2, REG_ATMP1);
+       
+                       /* implicit null-pointer check */
+                       M_STBX(REG_ATMP1, s3);
+                       break;
+
+               case ICMD_CASTORE:    /* ..., arrayref, index, value  ==> ...         */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
+                       s3 = emit_load_s3(jd, iptr, REG_ITMP3);
+                       M_INTMOVE(s2, REG_ITMP2);
+                       M_ISSL_IMM(1, REG_ITMP2);
+                       M_IADD_IMM(OFFSET(java_chararray, data[0]), REG_ITMP2); 
+                       M_ADRMOVE(s1, REG_ATMP1);
+                       M_AADDINT(REG_ITMP2, REG_ATMP1);
+                       /* implicit null-pointer check */
+                       M_STHX(REG_ATMP1, s3);
+                       break;
+
+               case ICMD_SASTORE:    /* ..., arrayref, index, value  ==> ...         */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
+                       s3 = emit_load_s3(jd, iptr, REG_ITMP3);
+                       M_INTMOVE(s2, REG_ITMP2);
+                       M_ISSL_IMM(1, REG_ITMP2);
+                       M_IADD_IMM(OFFSET(java_shortarray, data[0]), REG_ITMP2);
+                       M_ADRMOVE(s1, REG_ATMP1);
+                       M_AADDINT(REG_ITMP2, REG_ATMP1);
+                       /* implicit null-pointer check */
+                       M_STHX(REG_ATMP1, s3);
+                       break;
+
+               case ICMD_IASTORE:    /* ..., arrayref, index, value  ==> ...         */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
+                       s3 = emit_load_s3(jd, iptr, REG_ITMP3);
+                       M_INTMOVE(s2, REG_ITMP2);
+                       M_ISSL_IMM(1, REG_ITMP2);
+                       M_IADD_IMM(OFFSET(java_intarray, data[0]), REG_ITMP2);
+                       M_ADRMOVE(s1, REG_ATMP1);
+                       M_AADDINT(REG_ITMP2, REG_ATMP1);
+                       /* implicit null-pointer check */
+                       M_STWX(REG_ATMP1, s3);
+                       break;
+
+#if 0
+               case ICMD_LASTORE:    /* ..., arrayref, index, value  ==> ...         */
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
+                       s3 = emit_load_s3_high(jd, iptr, REG_ITMP3);
+                       M_INTMOVE(s2, REG_ITMP2);
+                       M_IADD_IMM(OFFSET(java_bytearray, data[0]), REG_ITMP2);
+                       M_ISSL_IMM(1, REG_ITMP2);
+                       M_ADRMOVE(s1, REG_ATMP1);
+                       M_AADDINT(REG_ITMP2, REG_ATMP1);
+                       /* implicit null-pointer check */
+                       M_STWX(s3, s1, REG_ITMP2);
+                       M_IADD_IMM(REG_ITMP2, 4, REG_ITMP2);
+                       s3 = emit_load_s3_low(jd, iptr, REG_ITMP3);
+                       M_STWX(s3, s1, REG_ITMP2);
+                       break;
+
+               case ICMD_FASTORE:    /* ..., arrayref, index, value  ==> ...         */
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
+                       s3 = emit_load_s3(jd, iptr, REG_FTMP3);
+                       M_SLL_IMM(s2, 2, REG_ITMP2);
+                       M_IADD_IMM(REG_ITMP2, OFFSET(java_floatarray, data[0]), REG_ITMP2);
+                       /* implicit null-pointer check */
+                       M_STFSX(s3, s1, REG_ITMP2);
+                       break;
+
+               case ICMD_DASTORE:    /* ..., arrayref, index, value  ==> ...         */
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
+                       s3 = emit_load_s3(jd, iptr, REG_FTMP3);
+                       M_SLL_IMM(s2, 3, REG_ITMP2);
+                       M_IADD_IMM(REG_ITMP2, OFFSET(java_doublearray, data[0]), REG_ITMP2);
+                       /* implicit null-pointer check */
+                       M_STFDX(s3, s1, REG_ITMP2);
+                       break;
+
+       #endif
+               case ICMD_AASTORE:    /* ..., arrayref, index, value  ==> ...         */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ATMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP1);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
+                       s3 = emit_load_s3(jd, iptr, REG_ATMP2);
+
+                       /* XXX what if array is NULL */
+                       disp = dseg_add_functionptr(cd, BUILTIN_canstore);
+
+                       M_AST(s1, REG_SP, 0*4);
+                       M_AST(s3, REG_SP, 1*4);
+                       M_JSR_IMM(BUILTIN_canstore);    
+                       emit_exception_check_ireg(cd, iptr);
+
+                       s1 = emit_load_s1(jd, iptr, REG_ATMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP1);
+                       s3 = emit_load_s3(jd, iptr, REG_ATMP2);
+                       M_INTMOVE(s2, REG_ITMP1);
+                       M_ISSL_IMM(2, REG_ITMP1);
+                       M_IADD_IMM(OFFSET(java_objectarray, data[0]), REG_ITMP1);
+                       M_INTMOVE(s1, REG_ATMP1);
+                       M_AADDINT(REG_ITMP1, REG_ATMP1);
+                       /* implicit null-pointer check */
+                       M_STAX(REG_ATMP1, s3);
+                       break;
+
+
+
+               /* METHOD INVOCATION *********************************************************/
+               case ICMD_BUILTIN:      /* ..., [arg1, [arg2 ...]] ==> ...            */
+                       bte = iptr->sx.s23.s3.bte;
+                       md  = bte->md;
+                       goto gen_method;
+
+               case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ...            */
+               case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
+               case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer    */
+               case ICMD_INVOKEINTERFACE:
+                       REPLACEMENT_POINT_INVOKE(cd, iptr);
+
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                               lm = NULL;
+                               um = iptr->sx.s23.s3.um;
+                               md = um->methodref->parseddesc.md;
+                       }
+                       else {
+                               lm = iptr->sx.s23.s3.fmiref->p.method;
+                               um = NULL;
+                               md = lm->parseddesc;
+                       }
+       gen_method:
+                       s3 = md->paramcount;
+       
+                       MCODECHECK((s3 << 1) + 64);
+
+                       /* copy arguments to stack */
+                       for (s3 = s3 - 1; s3 >= 0; s3--)        {
+                               var = VAR(iptr->sx.s23.s2.args[s3]);
+                               /* already preallocated */
+                               if (var->flags & PREALLOC) continue;
+               
+                               if (!md->params[s3].inmemory) assert(0);
+
+                               switch (var->type)      {
+#if defined(ENABLE_SOFTFLOAT)
+                                       case TYPE_DBL:
+#endif
+                                       case TYPE_LNG:
+                                               d = emit_load(jd, iptr, var, REG_ITMP12_PACKED);
+                                               M_LST(d, REG_SP, md->params[s3].regoff*4);
+                                               break;
+#if defined(ENABLE_SOFTFLOAT)
+                                       case TYPE_FLT:
+#endif
+                                       case TYPE_INT:
+                                               d = emit_load(jd, iptr, var, REG_ITMP1);
+                                               M_IST(d, REG_SP, md->params[s3].regoff*4);
+                                               break;
+                                       case TYPE_ADR:
+                                               d = emit_load(jd, iptr, var, REG_ATMP1);
+                                               M_AST(d, REG_SP, md->params[s3].regoff*4);
+                                               break;
+#if !defined(ENABLE_SOFTFLOAT)
+                                       case TYPE_FLT:
+                                       case TYPE_DBL:
+#endif
+                                       default:
+                                               assert(0);
+                               }
+                       }
+
+                       /* arguments in place now */
+                       switch(iptr->opc)       {
+                               case ICMD_BUILTIN: 
+                                       disp = (ptrint) bte->fp;
+                                       d = md->returntype.type;
+                                       M_JSR_IMM(disp);
+
+                                       REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
+                                       /*emit_exception_check(cd, iptr); TODO */
+                                       break;
+
+                               case ICMD_INVOKESPECIAL: 
+                                       /* adress register for sure */
+                                       M_ALD(REG_ATMP1, REG_SP, 0);
+                                       emit_nullpointer_check(cd, iptr, REG_ATMP1);
+                                       /* fall through */
+                               case ICMD_INVOKESTATIC: 
+                                       if (lm == NULL) {
+                                               codegen_addpatchref(cd, PATCHER_invokestatic_special, um, 0);
+                                               disp = 0;
+                                               M_AMOV_IMM(disp, REG_ATMP1);
+                                       } else  {
+                                               disp = lm->stubroutine;
+                                               M_AMOV_IMM(disp, REG_ATMP1);
+                                       }
+
+                                       /* generate the actual call */
+                                       M_JSR(REG_ATMP1);
+                                       REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
+                                       break;
+
+
+                               case ICMD_INVOKEVIRTUAL:
+                                       if (lm == NULL) {
+                                               codegen_addpatchref(cd, PATCHER_invokevirtual, um, 0);
+                                               s1 = 0;
+                                       } else {
+                                               s1 = OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * lm->vftblindex;
+                                       }
+                                       /* load object pointer (==argument 0) */
+                                       M_ALD(REG_ATMP1, REG_SP, 0);
+                                       /* implicit null-pointer check */
+                                       M_ALD(REG_METHODPTR, REG_ATMP1, OFFSET(java_objectheader, vftbl));
+                                       M_ALD(REG_ATMP1, REG_METHODPTR, s1);
+                                       /* generate the actual call */
+                                       M_JSR(REG_ATMP1);
+                                       break;
+                               case ICMD_INVOKEINTERFACE: 
+                                       if (lm == NULL) {
+                                               codegen_addpatchref(cd, PATCHER_invokeinterface, um, 0);
+
+                                               s1 = 0;
+                                               s2 = 0;
+                                       } else {
+                                               s1 = OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr*) * lm->class->index;
+                                               s2 = sizeof(methodptr) * (lm - lm->class->methods);
+                                       }
+                                       /* load object pointer (==argument 0) */
+                                       M_ALD(REG_ATMP1, REG_SP, 0);
+
+                                       /* implicit null-pointer check */
+                                       M_ALD(REG_METHODPTR, REG_ATMP1, OFFSET(java_objectheader, vftbl));
+                                       M_ALD(REG_METHODPTR, REG_METHODPTR, s1);
+                                       M_ALD(REG_ATMP1, REG_METHODPTR, s2);
+
+                                       /* generate the actual call */
+                                       M_JSR(REG_ATMP1);
+                                       REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
+                                       break;
+
+                               default: assert(0);
+                               }       /* switch (iptr->opc) */
+
+                               REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
+                               
+                               /* store return value */
+                               d = md->returntype.type;
+
+                               switch (d)      {
+                                       case TYPE_VOID: break;
+#if defined(ENABLE_SOFTFLOAT)
+                                       case TYPE_FLT:
+#endif
+                                       case TYPE_INT:
+                                               s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
+                                               M_INTMOVE(REG_RESULT, s1);
+                                               break;
+#if defined(ENABLE_SOFTFLOAT)
+                                       case TYPE_DBL:
+#endif
+                                       case TYPE_LNG:
+                                               s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
+                                               M_LNGMOVE(REG_RESULT_PACKED, s1);
+                                               break;
+                                       case TYPE_ADR:
+                                               s1 = codegen_reg_of_dst(jd, iptr, REG_ATMP1);
+                                               /* all stuff is returned in %d0 */
+                                               M_INT2ADRMOVE(REG_RESULT, s1);
+                                               break;
+#if !defined(ENABLE_SOFTFLOAT)
+                                       case TYPE_FLT:
+                                       case TYPE_DBL:
+#endif
+                                       default:
+                                               assert(0);
+                               }
+                               if (d != TYPE_VOID) emit_store_dst(jd, iptr, s1);
+                       break; /* ICMD_INVOKE* */
+
+#if defined(ENABLE_SOFTFLOAT)
+               case ICMD_FRETURN:
+#endif
+               case ICMD_IRETURN:      /* ..., retvalue ==> ...                      */
+
+                       REPLACEMENT_POINT_RETURN(cd, iptr);
+                       s1 = emit_load_s1(jd, iptr, REG_RESULT);
+                       M_INTMOVE(s1, REG_RESULT);
+                       goto nowperformreturn;
+
+               case ICMD_ARETURN:      /* ..., retvalue ==> ...                      */
+
+                       REPLACEMENT_POINT_RETURN(cd, iptr);
+                       s1 = emit_load_s1(jd, iptr, REG_RESULT);
+                       assert(VAROP(iptr->s1)->type == TYPE_ADR);
+                       M_ADR2INTMOVE(s1, REG_RESULT);
+
+#ifdef ENABLE_VERIFIER
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                               unresolved_class *uc = iptr->sx.s23.s2.uc;
+
+                               codegen_addpatchref(cd, PATCHER_resolve_class, uc, 0);
+                       }
+#endif /* ENABLE_VERIFIER */
+                       goto nowperformreturn;
+
+#if defined(ENABLE_SOFTFLOAT)
+               case ICMD_DRETURN:
+#endif
+               case ICMD_LRETURN:      /* ..., retvalue ==> ...                      */
+
+                       REPLACEMENT_POINT_RETURN(cd, iptr);
+                       s1 = emit_load_s1(jd, iptr, REG_RESULT_PACKED);
+                       M_LNGMOVE(s1, REG_RESULT_PACKED);
+                       goto nowperformreturn;
+
+#if !defined(ENABLE_SOFTFLOAT)
+               case ICMD_FRETURN:      /* ..., retvalue ==> ...                      */
+               case ICMD_DRETURN:
+
+                       REPLACEMENT_POINT_RETURN(cd, iptr);
+                       s1 = emit_load_s1(jd, iptr, REG_FRESULT);
+                       M_FLTMOVE(s1, REG_FRESULT);
+                       goto nowperformreturn;
+#endif
+
+               case ICMD_RETURN:      /* ...  ==> ...                                */
+
+                       REPLACEMENT_POINT_RETURN(cd, iptr);
+
+nowperformreturn:
+                       {
+                       s4 i, p;
+                       
+                       p = cd->stackframesize;
+
+                       /* call trace function */
+#if !defined(NDEBUG)
+                       emit_verbosecall_exit(jd);
+#endif
+
+#if defined(ENABLE_THREADS)
+                       if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
+                               disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
+                               M_ALD(REG_ITMP3, REG_PV, disp);
+                               M_MTCTR(REG_ITMP3);
+
+                               /* we need to save the proper return value */
+
+                               switch (iptr->opc) {
+                               case ICMD_LRETURN:
+                                       M_IST(REG_RESULT2, REG_SP, rd->memuse * 4 + 8);
+                                       /* fall through */
+                               case ICMD_IRETURN:
+                               case ICMD_ARETURN:
+                                       M_IST(REG_RESULT , REG_SP, rd->memuse * 4 + 4);
+                                       break;
+                               case ICMD_FRETURN:
+                                       M_FST(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
+                                       break;
+                               case ICMD_DRETURN:
+                                       M_DST(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
+                                       break;
+                               }
+
+                               M_ALD(REG_A0, REG_SP, rd->memuse * 4);
+                               M_JSR;
+
+                               /* and now restore the proper return value */
+
+                               switch (iptr->opc) {
+                               case ICMD_LRETURN:
+                                       M_ILD(REG_RESULT2, REG_SP, rd->memuse * 4 + 8);
+                                       /* fall through */
+                               case ICMD_IRETURN:
+                               case ICMD_ARETURN:
+                                       M_ILD(REG_RESULT , REG_SP, rd->memuse * 4 + 4);
+                                       break;
+                               case ICMD_FRETURN:
+                                       M_FLD(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
+                                       break;
+                               case ICMD_DRETURN:
+                                       M_DLD(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
+                                       break;
+                               }
+                       }
+#endif
+
+
+                       /* restore return address                                         */
+#if 0
+                       if (!jd->isleafmethod) {
+                               /* ATTENTION: Don't use REG_ZERO (r0) here, as M_ALD
+                                  may have a displacement overflow. */
+
+                               M_ALD(REG_ITMP1, REG_SP, p * 4 + LA_LR_OFFSET);
+                               M_MTLR(REG_ITMP1);
+                       }
+#endif
+                       /* restore saved registers                                        */
+
+                       for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
+                               p--; M_ILD(rd->savintregs[i], REG_SP, p * 4);
+                       }
+                       for (i=ADR_SAV_CNT-1; i>=rd->savadrreguse; --i) {
+                               p--; M_ALD(rd->savadrregs[i], REG_SP, p*4);
+                       }
+#if !defined(ENABLE_SOFTFLOAT)
+                       for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
+                               p -= 2; M_DLD(rd->savfltregs[i], REG_SP, p * 4);
+                       }
+#endif
+                       /* deallocate stack                                               */
+                       M_AADD_IMM(cd->stackframesize*4, REG_SP);
+                       M_RET;
+                       }
+                       break;
+
+               /* the evil ones */
+               case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult            */
+                                     /* val.a: (classinfo*) superclass               */
+
+                       /*  superclass is an interface:
+                        *
+                        *  return (sub != NULL) &&
+                        *         (sub->vftbl->interfacetablelength > super->index) &&
+                        *         (sub->vftbl->interfacetable[-super->index] != NULL);
+                        *
+                        *  superclass is a class:
+                        *
+                        *  return ((sub != NULL) && (0
+                        *          <= (sub->vftbl->baseval - super->vftbl->baseval) <=
+                        *          super->vftbl->diffvall));
+                        */
+
+                       {
+                       classinfo *super;
+                       s4         superindex;
+
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                               super      = NULL;
+                               superindex = 0;
+                       }
+                       else {
+                               super      = iptr->sx.s23.s3.c.cls;
+                               superindex = super->index;
+                       }
+                       
+#if defined(ENABLE_THREADS)
+                       codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
+#endif
+                       s1 = emit_load_s1(jd, iptr, REG_ATMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+
+                       assert(VAROP(iptr->s1 )->type == TYPE_ADR);
+                       assert(VAROP(iptr->dst)->type == TYPE_INT);
+
+                       M_ICLR(d);
+
+                       /* if class is not resolved, check which code to call */
+
+                       if (super == NULL) {
+                               M_ATST(s1);
+                               emit_label_beq(cd, BRANCH_LABEL_1);
+
+                               codegen_addpatchref(cd, PATCHER_resolve_classref_to_flags, iptr->sx.s23.s3.c.ref, 0);
+
+                               M_IMOV_IMM32(0, REG_ITMP3);
+                               M_IAND_IMM(ACC_INTERFACE, REG_ITMP3);
+                               emit_label_beq(cd, BRANCH_LABEL_2);
+                       }
+
+                       /* interface instanceof code */
+
+                       if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
+                               if (super == NULL) {
+                                       codegen_addpatchref(cd, PATCHER_instanceof_interface, iptr->sx.s23.s3.c.ref, 0);
+                               } else {
+                                       M_ATST(s1);
+                                       emit_label_beq(cd, BRANCH_LABEL_3);
+                               }
+
+                               M_ALD(REG_ATMP1, s1, OFFSET(java_objectheader, vftbl));
+                               M_ILD(REG_ITMP3, REG_ATMP1, OFFSET(vftbl_t, interfacetablelength));
+                               M_IADD_IMM(-superindex, REG_ITMP3);     /* -superindex may be patched patched */
+                               M_ITST(REG_ITMP3);
+                               M_BLE(10);
+                               M_ALD(REG_ATMP1, REG_ATMP1, OFFSET(vftbl_t, interfacetable[0]) - superindex * sizeof(methodptr*));      /* patch here too! */
+                               M_ATST(REG_ATMP1);
+                               M_BEQ(2);
+                               M_IMOV_IMM(1, d);
+
+                               if (super == NULL)
+                                       emit_label_br(cd, BRANCH_LABEL_4);
+                               else
+                                       emit_label(cd, BRANCH_LABEL_3);
+                       }
+
+                       /* class instanceof code */
+
+                       if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
+                               if (super == NULL) {
+                                       emit_label(cd, BRANCH_LABEL_2);
+
+                                       codegen_addpatchref(cd, PATCHER_resolve_classref_to_vftbl, iptr->sx.s23.s3.c.ref, 0);
+                                       M_AMOV_IMM(0, REG_ATMP2);
+                               } else {
+                                       M_AMOV_IMM(super->vftbl, REG_ATMP2);
+                                       M_ATST(s1);
+                                       emit_label_beq(cd, BRANCH_LABEL_5);
+                               }
+
+                               M_ALD(REG_ATMP1, s1, OFFSET(java_objectheader, vftbl));
+#if defined(ENABLE_THREADS)
+                               codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
+#endif
+                               M_ILD(REG_ITMP1, REG_ATMP1, OFFSET(vftbl_t, baseval));
+                               M_ILD(REG_ITMP3, REG_ATMP2, OFFSET(vftbl_t, baseval));
+                               M_ILD(REG_ITMP2, REG_ATMP2, OFFSET(vftbl_t, diffval));
+#if defined(ENABLE_THREADS)
+                               codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
+#endif
+                               M_ISUB(REG_ITMP3, REG_ITMP1);
+                               M_ICMP(REG_ITMP1, REG_ITMP2);
+                               M_BGT(4);
+                               M_IMOV_IMM(1, d);
+                               M_TPFW;                 /* overlaps next instruction */
+                               M_ICLR(d);
+
+                               if (super != NULL)
+                                       emit_label(cd, BRANCH_LABEL_5);
+                       }
+
+                       if (super == NULL) {
+                               emit_label(cd, BRANCH_LABEL_1);
+                               emit_label(cd, BRANCH_LABEL_4);
+                       }
+
+                       emit_store_dst(jd, iptr, d);
+                       }
+                       break;
+
+               case ICMD_CHECKCAST:  /* ..., objectref ==> ..., objectref            */
+                                     /* val.a: (classinfo*) superclass               */
+
+                       /*  superclass is an interface:
+                        *
+                        *  OK if ((sub == NULL) ||
+                        *         (sub->vftbl->interfacetablelength > super->index) &&
+                        *         (sub->vftbl->interfacetable[-super->index] != NULL));
+                        *
+                        *  superclass is a class:
+                        *
+                        *  OK if ((sub == NULL) || (0
+                        *         <= (sub->vftbl->baseval - super->vftbl->baseval) <=
+                        *         super->vftbl->diffvall));
+                        */
+
+                       if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
+                               /* object type cast-check */
+
+                               classinfo *super;
+                               s4         superindex;
+
+                               if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                                       super      = NULL;
+                                       superindex = 0;
+                               }
+                               else {
+                                       super      = iptr->sx.s23.s3.c.cls;
+                                       superindex = super->index;
+                               }
+
+#if defined(ENABLE_THREADS)
+                               codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
+#endif
+
+                               s1 = emit_load_s1(jd, iptr, REG_ATMP1);
+                               assert(VAROP(iptr->s1)->type == TYPE_ADR);
+
+                               /* if class is not resolved, check which code to call */
+
+                               if (super == NULL) {
+                                       M_ATST(s1);
+                                       emit_label_beq(cd, BRANCH_LABEL_1);
+
+                                       codegen_addpatchref(cd, PATCHER_resolve_classref_to_flags, iptr->sx.s23.s3.c.ref, 0);
+                       
+                                       M_IMOV_IMM32(0, REG_ITMP2);
+                                       M_IAND_IMM(ACC_INTERFACE, REG_ITMP2);
+                                       emit_label_beq(cd, BRANCH_LABEL_2);
+                               }
+
+                               /* interface checkcast code */
+
+                               if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
+                                       if (super == NULL) {
+                                               codegen_addpatchref(cd, PATCHER_checkcast_interface, iptr->sx.s23.s3.c.ref, 0);
+                                       } else {
+                                               M_ATST(s1);
+                                               emit_label_beq(cd, BRANCH_LABEL_3);
+                                       }
+
+                                       M_ALD(REG_ATMP2, s1, OFFSET(java_objectheader, vftbl));
+                                       M_ILD(REG_ITMP3, REG_ATMP2, OFFSET(vftbl_t, interfacetablelength));
+       
+                                       M_IADD_IMM(-superindex, REG_ITMP3);     /* superindex patched */
+                                       M_ITST(REG_ITMP3);
+                                       emit_classcast_check(cd, iptr, BRANCH_LE, REG_ITMP3, s1);
+
+                                       M_ALD(REG_ATMP3, REG_ATMP2, OFFSET(vftbl_t, interfacetable[0]) - superindex * sizeof(methodptr*));      /* patched*/
+                                       M_ATST(REG_ATMP3);
+                                       emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ATMP3, s1);
+
+                                       if (super == NULL)
+                                               emit_label_br(cd, BRANCH_LABEL_4);
+                                       else
+                                               emit_label(cd, BRANCH_LABEL_3);
+                               }
+
+                               /* class checkcast code */
+
+                               if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
+                                       if (super == NULL) {
+                                               emit_label(cd, BRANCH_LABEL_2);
+
+                                               codegen_addpatchref(cd, PATCHER_resolve_classref_to_vftbl, iptr->sx.s23.s3.c.ref, 0);
+                                               M_AMOV_IMM(0, REG_ATMP3);
+                                       } else {
+                                               M_AMOV_IMM(super->vftbl, REG_ATMP3);
+                                               M_ATST(s1);
+                                               emit_label_beq(cd, BRANCH_LABEL_5);
+                                       }
+
+                                       M_ALD(REG_ATMP2, s1, OFFSET(java_objectheader, vftbl));
+#if defined(ENABLE_THREADS)
+                                       codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
+#endif
+                                       M_ILD(REG_ITMP3, REG_ATMP2, OFFSET(vftbl_t, baseval));  /* REG_ITMP3 == sub->vftbl->baseval */
+#if 0
+                                       if (s1 != REG_ATMP1) {
+#endif
+                                               M_ILD(REG_ITMP1, REG_ATMP3, OFFSET(vftbl_t, baseval));
+                                               M_ILD(REG_ITMP2, REG_ATMP3, OFFSET(vftbl_t, diffval));
+#if defined(ENABLE_THREADS)
+                                               codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
+#endif
+                                               M_ISUB(REG_ITMP1, REG_ITMP3);
+                                               M_ICMP(REG_ITMP2, REG_ITMP1);   /* XXX was CMPU */
+#if 0                                  
+                                       } else {
+                                               assert(0);
+                                               M_ILD(REG_ITMP2, REG_ATMP3, OFFSET(vftbl_t, baseval));
+                                               M_ISUB(REG_ITMP3, REG_ITMP2);
+                                               M_ILD(REG_ITMP3, REG_ATMP3, OFFSET(vftbl_t, diffval));
+                                               M_ICMP(REG_ITMP2, REG_ITMP3);   /* XXX was CMPU */
+#if defined(ENABLE_THREADS)
+                                               codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
+#endif
+                                       }
+#endif
+                                       emit_classcast_check(cd, iptr, BRANCH_UGT, REG_ITMP3, s1); /* XXX was BRANCH_GT */
+
+                                       if (super != NULL)
+                                               emit_label(cd, BRANCH_LABEL_5);
+                               }
+
+                               if (super == NULL) {
+                                       emit_label(cd, BRANCH_LABEL_1);
+                                       emit_label(cd, BRANCH_LABEL_4);
+                               }
+
+                               d = codegen_reg_of_dst(jd, iptr, s1);
+                       } else {
+                               /* array type cast-check */
+
+                               s1 = emit_load_s1(jd, iptr, REG_ATMP2);
+
+                               if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                                       codegen_addpatchref(cd, PATCHER_resolve_classref_to_classinfo, iptr->sx.s23.s3.c.ref, 0);
+                                       M_AMOV_IMM(0, REG_ATMP1);
+                               } else {
+                                       M_AMOV_IMM(iptr->sx.s23.s3.c.cls, REG_ATMP1);
+                               }
+       
+                               M_APUSH(s1);
+                               M_APUSH(REG_ATMP1);
+                               M_JSR_IMM(BUILTIN_arraycheckcast);
+                               M_AADD_IMM(2*4, REG_SP);                /* pop arguments off stack */
+                               M_ITST(REG_RESULT);
+                               emit_classcast_check(cd, iptr, BRANCH_EQ, REG_RESULT, s1);
+
+                               s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                               d = codegen_reg_of_dst(jd, iptr, s1);
+                       }
+                       assert(VAROP(iptr->dst)->type == TYPE_ADR);
+                       M_ADRMOVE(s1, d);
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+               case ICMD_TABLESWITCH:  /* ..., index ==> ...                         */
+                       {
+                       s4 i, l;
+                       branch_target_t *table;
+
+                       table = iptr->dst.table;
+
+                       l = iptr->sx.s23.s2.tablelow;
+                       i = iptr->sx.s23.s3.tablehigh;
+                       
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       M_INTMOVE(s1, REG_ITMP1);
+                       if (l != 0) M_ISUB_IMM(l, REG_ITMP1);
+
+                       i = i - l + 1;
+
+                       /* range check */
+                       M_ICMP_IMM(i - 1, REG_ITMP1);
+                       emit_bugt(cd, table[0].block);
+
+                       /* build jump table top down and use address of lowest entry */
+                       table += i;
+
+                       while (--i >= 0) {
+                               dseg_add_target(cd, table->block); 
+                               --table;
+                       }
+
+                       /* length of dataseg after last dseg_add_target is used by load */
+                       M_AMOV_IMM(0, REG_ATMP2);
+                       dseg_adddata(cd);
+
+                       M_ISSL_IMM(2, REG_ITMP1);                       /* index * 4 == offset in table */
+                       M_AADDINT(REG_ITMP1, REG_ATMP2);                /* offset in table */
+                       M_AADD_IMM(-(cd->dseglen), REG_ATMP2);          /* start of table in dseg */
+                       M_ALD(REG_ATMP1, REG_ATMP2, 0);
+
+                       M_JMP(REG_ATMP1);
+                       ALIGNCODENOP;
+                       }
+                       break;
+
+               case ICMD_LOOKUPSWITCH: /* ..., key ==> ...                           */
+                       {
+                       s4 i;
+                       lookup_target_t *lookup;
+
+                       lookup = iptr->dst.lookup;
+
+                       i = iptr->sx.s23.s2.lookupcount;
+                       
+                       MCODECHECK((i<<2)+8);
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+
+                       while (--i >= 0) {
+                               M_ICMP_IMM(lookup->value, s1);
+                               emit_beq(cd, lookup->target.block);
+                               lookup++;
+                       }
+
+                       emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
+                       ALIGNCODENOP;
+                       break;
+                       }
+
+
+               default:
+                       printf("UNKNOWN OPCODE %d\n", iptr->opc);
+                       exceptions_throw_internalerror("Unknown ICMD %d during code generation", iptr->opc);
+                       return false;
+       } /* switch */
+       M_TPF;
+       } /* for each instruction */
+       } /* if (btpre->flags >= BBREACHED) */
+       } /* for each basic block */
+
+       dseg_createlinenumbertable(cd);
+
+       /* generate stubs */
+       emit_patcher_stubs(jd);
+       REPLACEMENT_EMIT_STUBS(jd);
+
+       return true;
+}
+
+/* createnativestub ************************************************************
+
+   Creates a stub routine which calls a native method.
+
+*******************************************************************************/
+u1* createnativestub(functionptr f, jitdata *jd, methoddesc *nmd) 
+{
+       methodinfo   *m;
+       codeinfo     *code;
+       codegendata  *cd;
+       registerdata *rd;
+       methoddesc   *md;
+       s4 nativeparams, i, j, t, s1, s2;
+       
+       /* get required compiler data */
+
+       m    = jd->m;
+       code = jd->code;
+       cd   = jd->cd;
+       rd   = jd->rd;
+
+       md = m->parseddesc;
+       nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
+
+       /* calc stackframe size */
+       cd->stackframesize =    sizeof(stackframeinfo) / SIZEOF_VOID_P +
+                               sizeof(localref_table) / SIZEOF_VOID_P +
+                               nmd->memuse +
+                               4 +                                             /* %d0,%d1,%a0,%a1*/
+                               2 * 2 +                                         /* %f0,%f1 */
+                               1 +                                             /* functionptr */
+                               4;                                              /* args for codegen_start_native_call */
+
+       /* create method header */
+       (void) dseg_add_unique_address(cd, code);                      /* CodeinfoPointer */
+       (void) dseg_add_unique_s4(cd, cd->stackframesize * 4);         /* FrameSize       */
+       (void) dseg_add_unique_s4(cd, 0);                              /* IsSync          */
+       (void) dseg_add_unique_s4(cd, 0);                              /* IsLeaf          */
+       (void) dseg_add_unique_s4(cd, 0);                              /* IntSave         */
+       (void) dseg_add_unique_s4(cd, 0);                              /* FltSave         */
+       (void) dseg_addlinenumbertablesize(cd);
+       (void) dseg_add_unique_s4(cd, 0);                              /* ExTableSize     */
+
+       /* print call trace */
+#if !defined(NDEBUG)
+       if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) {
+               emit_verbosecall_enter(jd);
+       }
+#endif
+
+       /* generate code */
+       M_AADD_IMM(-(cd->stackframesize*4), REG_SP);
+
+       /* get function address (this must happen before the stackframeinfo) */
+#if !defined(WITH_STATIC_CLASSPATH)
+       if (f == NULL)  {
+               codegen_addpatchref(cd, PATCHER_resolve_native_function, m, 0);
+               /*M_AMOV_IMM(0, REG_ATMP2);*/
+       }
+#endif
+       M_AMOV_IMM(f, REG_ATMP2); /* do not move this line, the patcher is needed */
+
+       M_AST(REG_ATMP2, REG_SP, 4 * 4);
+
+       /* save integer and float temp registers */
+       /*
+       M_IST(REG_D0, REG_SP, 4*4 + 2*8 + 3*4);
+       M_IST(REG_D1, REG_SP, 4*4 + 2*8 + 2*4);
+       M_AST(REG_A0, REG_SP, 4*4 + 2*8 + 1*4);
+       M_AST(REG_A1, REG_SP, 4*4 + 2*8 + 0*4);
+       */
+
+       /* TODO */
+       /* store %f0, %f1 */
+
+       /* put arguments for codegen_start_native_call onto stack */
+       /* void codegen_start_native_call(u1 *datasp, u1 *pv, u1 *sp, u1 *ra) */
+       
+       M_AMOV(REG_SP, REG_ATMP1);
+       M_AADD_IMM(cd->stackframesize * 4, REG_ATMP1);
+
+       M_ALD(REG_ATMP3, REG_ATMP1, 0 * 4);
+       M_AST(REG_ATMP3, REG_SP, 3 * 4);                /* ra */
+
+       M_AST(REG_ATMP1, REG_SP, 0 * 4);                /* datasp */
+
+       M_AADD_IMM(1 * 4 , REG_ATMP1);                  
+       M_AST(REG_ATMP1, REG_SP, 2 * 4);                /* sp */
+
+       M_AMOV_IMM(0, REG_ATMP2);                       /* 0 needs to patched */
+       dseg_adddata(cd);                               /* this patches it */
+
+       M_AST(REG_ATMP2, REG_SP, 1 * 4);                /* pv */
+
+       M_JSR_IMM(codegen_start_native_call);
+
+       /* load function pointer */
+       M_ALD(REG_ATMP2, REG_SP, 4 * 4);
+
+       /* copy arguments into stackframe */
+       for (i = md->paramcount -1, j = i + nativeparams; i >= 0; --i, --j)     {
+               t = md->paramtypes[i].type;
+               /* all arguments via stack */
+               assert(md->params[i].inmemory);                                         
+
+               s1 = (md->params[i].regoff + cd->stackframesize + 1) * 4;
+               s2 = nmd->params[j].regoff * 4;
+
+               /* simply copy argument stack */
+               M_ILD(REG_ITMP1, REG_SP, s1);
+               M_IST(REG_ITMP1, REG_SP, s2);
+               if (IS_2_WORD_TYPE(t))  {
+                       M_ILD(REG_ITMP1, REG_SP, s1 + 4);
+                       M_IST(REG_ITMP1, REG_SP, s2 + 4);
+               }
+       }
+
+       /* for static function class as second arg */
+       if (m->flags & ACC_STATIC)      {
+               M_AMOV_IMM(m->class, REG_ATMP1);
+               M_AST(REG_ATMP1, REG_SP, 1 * 4);
+       }
+       /* env ist first argument */
+       M_AMOV_IMM(_Jv_env, REG_ATMP1);
+       M_AST(REG_ATMP1, REG_SP, 0 * 4);
+
+       /* call the native function */
+       M_JSR(REG_ATMP2);
+
+       /* save return value */
+       switch (md->returntype.type)    {
+               case TYPE_VOID: break;
+
+#if defined(ENABLE_SOFTFLOAT)
+               case TYPE_DBL:
+#endif
+               case TYPE_LNG:
+                       M_IST(REG_D1, REG_SP, 2 * 4);
+                       /* fall through */
+
+#if defined(ENABLE_SOFTFLOAT)
+               case TYPE_FLT:
+#endif
+               case TYPE_INT:
+               case TYPE_ADR:
+                       M_IST(REG_D0, REG_SP, 1 * 4);
+                       break;
+
+#if !defined(ENABLE_SOFTFLOAT)
+               case TYPE_FLT:
+               case TYPE_DBL:  /* FIXME */
+#endif
+               default: assert(0);
+       }
+       
+       /* print call trace */
+#if ! defined(NDEBUG)
+       if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) {
+               emit_verbosecall_exit(jd);
+       }
+#endif
+       /* remove native stackframe info */
+       /* therefore we call: java_objectheader *codegen_finish_native_call(u1 *datasp) */
+
+       M_AMOV(REG_SP, REG_ATMP3);
+       M_AADD_IMM(cd->stackframesize * 4, REG_ATMP3);
+       M_AST(REG_ATMP3, REG_SP, 0 * 4);                        /* datasp */
+       M_JSR_IMM(codegen_finish_native_call);
+       
+       M_INT2ADRMOVE(REG_RESULT, REG_ATMP3);
+       /* restore return value */
+       switch (md->returntype.type)    {
+               case TYPE_VOID: break;
+
+#if defined(ENABLE_SOFTFLOAT)
+               case TYPE_DBL:
+#endif
+               case TYPE_LNG:
+                       M_ILD(REG_D1, REG_SP, 2 * 4);
+                       /* fall through */
+#if defined(ENABLE_SOFTFLOAT)
+               case TYPE_FLT:
+#endif
+               case TYPE_INT:
+               case TYPE_ADR:
+                       M_ILD(REG_D0, REG_SP, 1 * 4);
+                       break;
+
+#if !defined(ENABLE_SOFTFLOAT)
+               case TYPE_FLT:
+               case TYPE_DBL:  /* FIXME */
+#endif
+               default: assert(0);
+       }
+       /* restore saved registers */
+
+       M_AADD_IMM(cd->stackframesize*4, REG_SP);
+       /* check for exception */
+       M_ATST(REG_ATMP3);
+       M_BNE(2);
+       M_RET;
+
+       /* handle exception */
+       M_JSR_IMM(0);   /* FIXME */
+
+
+       /* generate patcher stub call code */
+       emit_patcher_stubs(jd);
+       codegen_finish(jd);
+
+       return code->entrypoint;
+}
+
+/* createcompilerstub **********************************************************
+
+   Creates a stub routine which calls the compiler.
+       
+*******************************************************************************/
+
+#define COMPILERSTUB_DATASIZE (3 * SIZEOF_VOID_P)
+#define COMPILERSTUB_CODESIZE (6+6+6+2)
+#define COMPILERSTUB_SIZE (COMPILERSTUB_DATASIZE +  COMPILERSTUB_CODESIZE)
+u1* createcompilerstub(methodinfo *m) 
+{ 
+       u1          *s;
+       ptrint      *d;
+       codegendata *cd;
+       s4          dumpsize;
+
+       s = CNEW(u1, COMPILERSTUB_SIZE);
+       
+       /* set data and code pointer */
+       d = (ptrint *)s;
+       s = s + COMPILERSTUB_DATASIZE;
+
+       /* mark start of dump memory area */
+       dumpsize = dump_size();
+       cd = DNEW(codegendata);
+       cd->mcodeptr = s;
+
+       /* Store codeinfo pointer in the same place as in the
+        * methodheader for compiled methods */
+       d[0] = (ptrint) asm_call_jit_compiler;
+       d[1] = (ptrint) m;
+       d[2] = (ptrint) &d[1];          /* fake code->m */
+
+       M_AMOV_IMM(m, REG_ATMP1);
+       M_AMOV_IMM(asm_call_jit_compiler, REG_ATMP3);
+       M_JMP_IMM(asm_call_jit_compiler);
+       M_RET;
+       
+       md_cacheflush((u1 *) d, COMPILERSTUB_SIZE);
+#if defined(ENABLE_STATISTICS)
+       if (opt_stat)
+               count_cstub_len += COMPILERSTUB_SIZE;
+#endif
+
+       /* release dump area */
+       dump_release(dumpsize);
+
+       return s;
+}
index ba209f4f4847a7ea143a4bf8d28314ad7259c504..736707d573cbaf73058851bcef0cffa7c47fed33 100644 (file)
@@ -1,7 +1,379 @@
+/* src/vm/jit/m68k/codegen.h
+
+   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.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   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., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
+
+   $Id: arch.h 5330 2006-09-05 18:43:12Z edwin $
+
+*/
+
+
 #ifndef _CODEGEN_H
 #define _CODEGEN_H
 
-#define PATCHER_CALL_SIZE      1
-#define BRANCH_NOPS            0
+#include "config.h"
+
+#include <stdint.h>
+
+#include "md-abi.h"
+#include "vm/jit/m68k/emit.h"
+
+
+#define MCODECHECK(icnt) \
+    do { \
+        if ((cd->mcodeptr + (icnt) * 4) > cd->mcodeend) \
+            codegen_increase(cd); \
+    } while (0)
+
+
+#define PATCHER_NOPS \
+       do { M_TPFL; M_TPF; M_TPF } while (0);
+
+#define BRANCH_NOPS \
+    do { \
+        if (CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) { \
+           M_NOP; \
+            M_NOP; \
+            M_NOP; \
+        } else { \
+           M_NOP; \
+            M_NOP; \
+        } \
+    } while (0)
+
+
+/* coldfire instruction format:
+ * -----------------------------
+ * | Op Word                    |
+ * |____________________________|
+ * | extension word 1(optional) |
+ * |____________________________|
+ * | extension word 2(optional) |
+ * |____________________________|
+ *
+ *
+ * Opword:
+ *
+ *                     | effective addr
+ *                     |  mode |  reg.
+ * x x x x x x x x x x | M M M | R R R
+ *
+ * MMM = 000 ---> data register   direct: RRR = register
+ * MMM = 001 ---> addr register   direct: RRR = register
+ * MMM = 010 ---> addr register indirect: RRR = register
+ * MMM = 011 ---> addr reg ind postincr : RRR = register
+ * MMM = 100 ---> addr reg ind predecr  : RRR = register
+ * MMM = 101 ---> addr reg ind + displac: RRR = register + ext.wrd.1
+ * MMM = 110 ---> addr reg ind + scaled index and 8 bit displacement
+ * MMM = 111, RRR = 010 ---> PC ind. with displacement + ext.wrd.1
+ * MMM = 111, RRR = 011 ---> PC ind. with scaled inex + 8but displacement
+ * MMM = 111, RRR = 000 + ext.wrd.1 ---> absolute short
+ * MMM = 111, RRR = 001 + ext.wrd.1+2 -> absolute long
+ * MMM = 111, RRR = 100 + ext.wrd1/2 --> immediate data
+ */
+
+/* one word opcodes */
+#define OPWORD(op, mode, reg) \
+       do { \
+               *((u2*)cd->mcodeptr) = (u2) (((op) << 6) | ((mode)<<3) | (reg)); \
+               cd->mcodeptr += 2; \
+       } while(0);
+/* opword + one extension word */
+/* usage of int16_t instead of s2 as is clashes with variable name */
+#define OPWORD_IMM16(op, mode, reg, imm) \
+       do { \
+               *((u2*)cd->mcodeptr) = (u2) (((op) << 6) | ((mode)<<3) | (reg)); \
+               cd->mcodeptr += 2; \
+               *((int16_t*)(cd->mcodeptr)) = imm; \
+               cd->mcodeptr += 2; \
+       } while(0);
+
+/* opword + two extension words */
+/* usage of int32_t instead of s4 as is clashes with variable name */
+#define OPWORD_IMM32(op, mode, reg, imm) \
+       do { \
+               *((u2*)cd->mcodeptr) = (u2) (((op) << 6) | ((mode)<<3) | (reg)); \
+               cd->mcodeptr += 2; \
+               *((int32_t*)(cd->mcodeptr)) = imm; \
+               cd->mcodeptr += 4; \
+       } while(0);
+
+/* create NOPS to align basicblock boundaries 
+ * using real nops here as they are not executed, so no performance penalty
+ **/
+#define ALIGNCODENOP \
+    do { \
+        for (s1 = 0; s1 < (s4) (((ptrint) cd->mcodeptr) & 7); s1++) \
+            M_NOP; \
+    } while (0)
+
+
+
+#define PATCHER_CALL_SIZE      6
+
+#define M_NOP          OPWORD(0x139,6,1)                               /* 0x4371 do not use as it syncs pipeline */
+#define M_ILLEGAL      OPWORD(0x12b,7,4)                               /* 0x4afc */
+#define M_TPF          OPWORD(0x147,7,4)                               /* tfp with no  ext. word use instead of NOP*/
+#define M_TPFW         OPWORD(0x147,7,2)                               /* tfp with one ext. word */
+#define M_TPFL         OPWORD(0x147,7,3)                               /* tfp with two ext. word */
+
+/*M_XMOVX....M_XMOVX(source, destination) */
+#define M_IMOV(a,b)    OPWORD( ( (2<<6) | ((b) << 3) | 0), 0, (a))     /* move.l */
+#define M_AMOV(a,b)    OPWORD( ( (2<<6) | ((b) << 3) | 1), 1, (a))     /* movea.l */
+#define M_IMOV_IMM(a,b)        emit_mov_imm_reg(cd, (a), (b))
+#define M_AMOV_IMM(a,b)        OPWORD_IMM32( ( (2<<6) | ((b) << 3) | 1), 7, 4, (a))
+
+/* for sure generates a 32 bit immedeate form, needed when there are patchers involved */
+#define M_IMOV_IMM32(a,b)      OPWORD_IMM32(((2<<6) | ((b) << 3) | 0), 7, 4, (a))
+
+#define        M_ICLR(a)       OPWORD(0x10a, 0, (a))                           /* clr.l */
+#define M_ISET(a)      OPWORD( ( (0xa <<6) | (0 << 3) | 5), 0, (a))    /* mov3q #-1 */
+
+#define M_JMP(a)       OPWORD(0x13b,2,(a))                             /* jmp %aX@ */
+#define M_JMP_IMM(a)   OPWORD_IMM32(0x13b,7,1,(a))                     /* jmp.l */
+#define M_JSR(a)       OPWORD(0x13a,2,(a))                             /* jsr %aX@ */
+#define M_JSR_IMM(a)   OPWORD_IMM32(0x13a,7,1,(a))                     /* jsr.l */
+#define M_BSR_IMM(a)   OPWORD_IMM32(0x187,7,7,(a))                     /* bsr.l */
+#define M_JSR_PCREL(a) OPWORD_IMM16(0x13a,7,2,(a))                     /* jsr.l (d16,PC) */
+
+#define M_RET          OPWORD(0x139,6,5)                               /* 0x4375 */
+#define M_LINK(a,b)    OPWORD_IMM16(0x139,2,(a), (b))                  /* link */
+#define M_UNLK(a)      OPWORD(0x139, 3, (a))                           /* unlk */
+
+/* push and pop are implemented using move.l */
+/* we need 3 variants, data, address and float registers */
+/* also a POPALL and PUSHALL for verbose:call code, use them only there! */
+#define M_IPUSH(a)             OPWORD(0xbc,0,(a))
+#define M_APUSH(a)             OPWORD(0xbc,1,(a))
+
+#define M_IPOP(a)              OPWORD( ( (2<<6) | ((a) << 3) | 0 ), 3, REG_SP)
+#define M_APOP(a)              OPWORD( ( (2<<6) | ((a) << 3) | 1 ), 3, REG_SP)         /* movea.l acutally */
+
+
+#define M_IPUSH_IMM(a)         OPWORD_IMM32(0x121,7,1, (a))                            /* pea.l */
+
+#define        M_PUSHALL               OPWORD_IMM16(0x123,2,REG_SP,0xFFFF)                     /* A0-A7, D0-D7 pushed onto stack */
+#define M_POPALL               OPWORD_IMM16(0x133,2,REG_SP,0xFFFF)                     /* A0-A7, D0-D7 poped off stack */
+
+/* M_XLD(a,b,c)....M_XLD(destinationreg, addressbase, offset)  */
+#define M_ILD(a,b,c)           OPWORD_IMM16( ( (2<<6) | ((a) << 3) | 0), 5, (b), (c))
+#define M_ALD(a,b,c)           OPWORD_IMM16( ( (2<<6) | ((a) << 3) | 1), 5, (b), (c))
+#define M_LLD(a,b,c)           do {\
+                                       M_ILD(GET_HIGH_REG(a), (b), (c));\
+                                       M_ILD(GET_LOW_REG (a), (b), (c)+4);\
+                               } while(0);
+
+#if !defined(ENABLE_SOFTFLOAT)
+       #define M_FLD(a,b,c)            M_ILLEGAL
+       #define M_DLD(a,b,c)            M_ILLEGAL
+#endif
+
+/* M_XST(a,b,c)....M_XST(sourceregister, addressbase, offset)   */
+#define M_IST(a,b,c)           OPWORD_IMM16( ( (2<<6) | ((b) << 3) | 5), 0, (a), (c))
+#define M_AST(a,b,c)           OPWORD_IMM16( ( (2<<6) | ((b) << 3) | 5), 1, (a), (c))
+#define M_LST(a,b,c)           do      {\
+                                       M_IST(GET_HIGH_REG(a), (b), (c));\
+                                       M_IST(GET_LOW_REG (a), (b), (c)+4);\
+                               } while(0);
 
+#if !defined(ENABLE_SOFTFLOAT)
+       #define M_FST(a,b,c)            M_ILLEGAL
+       #define M_DST(a,b,c)            M_ILLEGAL
 #endif
+
+/*M_XADD_IMM(a,b)...M_XADD_IMM(offset, reg) */
+#define M_AADD_IMM(a,b)                OPWORD_IMM32( ( (0xd<<6) | ((b)<<3) | 7), 7, 4, (a))
+#define M_IADD_IMM(a,b)                OPWORD_IMM32( ( (0xd<<6) | ((b)<<3) | 2), 7, 4, (a))
+#define M_ISUB_IMM(a,b)                M_IADD_IMM(-(a), (b))
+
+/* M_OP(source, dest) ...  dest (OP) source -> dest*/
+#define M_ISUB(a,b)            OPWORD ( ( (9<<6)   | ((b)<<3) | 2), 0, (a))                    /* sub.l */
+#define M_IADD(a,b)            OPWORD ( ( (0xd<<6) | ((b)<<3) | 2), 0, (a))                    /* add.l */
+
+#define M_IMUL(a,b)            OPWORD_IMM16 ( 0x130, 0, (a), ( ((b) << 12) | (1 << 11)))       /* muls.l */
+#define M_IDIV(a,b)            OPWORD_IMM16 ( 0x131, 0, (a), ( ((b) << 12) | (1 << 11) | (b))) /* divs.l */
+
+#define M_ISSL(a,b)            OPWORD ( ( (0xe<<6) | ((a) << 3) | 6), 4, (b))                  /* asl.l */
+#define M_ISSR(a,b)            OPWORD ( ( (0xe<<6) | ((a) << 3) | 2), 4, (b))                  /* asr.l */
+#define M_IUSR(a,b)            OPWORD ( ( (0xe<<6) | ((a) << 3) | 2), 5, (b))                  /* lsr.l */
+
+#define M_IAND(a,b)            OPWORD ( ( (0xc<<6) | ((b) << 3) | 2), 0, (a))                  /* and.l */
+
+#define M_IOR(a,b)             OPWORD ( ( (0x8<<6) | ((b) << 3) | 2), 0, (a))                  /* or.l */
+
+
+/* ultra sepcial 3 register form, b%a = c, (a!=c) */
+#define M_IREM(a,b,c)          OPWORD_IMM16 ( 0x131, 0, (a), ( ((b) << 12) | (1 << 11) | (c))) /* rems.l */
+
+/* M_OP(dest) */
+#define M_INEG(a)              OPWORD(0x112, 0, (a))                                           /* neg.l */
+
+/* only generate opcode when condition true */
+#define OPWORD_COND(c, u,v,w)  \
+       do { \
+               if ( (c) ) { OPWORD( (u),(v),(w) ) }  \
+       } while(0);
+/* assert on the opcode */
+#define OPWORD_ASSERT(a, u,v,w)        \
+       do { \
+               assert((a)); \
+               OPWORD( (u),(v),(w) )  \
+       } while(0);
+
+/* M_XMOVE....M_XMOVE(sourcereg, destreg) */
+#define M_INTMOVE(a,b)         OPWORD_COND(((a) != (b)), ( ( 2<<6) | ((b) << 3) | 0), 0, (a));
+#define M_ADRMOVE(a,b)         OPWORD_COND(((a) != (b)), ( ( 2<<6) | ((b) << 3) | 1), 1, (a));
+#define M_INT2ADRMOVE(a,b)     OPWORD( ( (2<<6) | ((b) << 3) | 1), 0, (a));
+#define M_ADR2INTMOVE(a,b)     OPWORD( ( (2<<6) | ((b) << 3) | 0), 1, (a));
+#define M_LNGMOVE(a,b)         do      {\
+                                       M_INTMOVE(GET_LOW_REG (a), GET_LOW_REG (b));\
+                                       M_INTMOVE(GET_HIGH_REG(a), GET_HIGH_REG(b));\
+                               } while(0);
+
+#if !defined(ENABLE_SOFTLFOAT)
+       #define M_FLTMOVE(a,b)          M_ILLEGAL
+       #define M_DBLMOVE(a,b)          M_ILLEGAL
+#endif
+/* M_XTST....M_XTST(register) */
+#define M_ITST(a)              OPWORD(0x12a, 0, (a))                   /* tst.l */
+#define M_ATST(a)              OPWORD(0x12a, 1, (a))                   /* tst.l */
+
+/* M_XCMPI....M_XMCPI(immideate, register) */
+#define M_ICMP_IMM(a,b)                OPWORD_IMM32( 0x32, 0, (b), (a))
+#if 0
+#define M_ACMPI(a,b)           OPWORD_IMM32( ( (0xb << 6) | ((b) << 3) | 7), 7, 4, (a))        /* cmpa.l # */
+#endif
+/* M_XCMP....M_XCMP(reg1, reg2) */
+#define M_ICMP(b,a)            OPWORD( ( (0xb << 6) | ((a) << 3) | 2), 0, (b))                 /* cmp.l */
+#define M_ACMP(b,a)            OPWORD( ( (0xb << 6) | ((a) << 3) | 7), 1, (b))                 /* cmpa.l */
+
+/* M_AND_IMM(imm, register)    */
+#define M_IAND_IMM(a,b)                OPWORD_IMM32( 0xa, 0, (b), (a))                                 /* andi.l # */
+
+/* All kind of branches one could ever possibly need, each with 16 and 32 bit displacement */
+/* BRANCH16 and BRANCH32 are helpers */
+#define BRANCH8(cond,imm) \
+       do { \
+               *((u2*)cd->mcodeptr) = (u2) (((0x6) << 12) | ((cond)<<8) | (int8_t)imm); \
+               cd->mcodeptr += 2; \
+       } while(0);
+
+#define BRANCH16(cond,imm) \
+       do { \
+               *((u2*)cd->mcodeptr) = (u2) (((0x6) << 12) | ((cond)<<8) | 0x00); \
+               cd->mcodeptr += 2; \
+               *((int16_t*)(cd->mcodeptr)) = imm; \
+               cd->mcodeptr += 2; \
+       } while(0);
+#define BRANCH32(cond,imm) \
+       do { \
+               *((u2*)cd->mcodeptr) = (u2) (((0x6) << 12) | ((cond)<<8) | 0xff); \
+               cd->mcodeptr += 2; \
+               *((int32_t*)(cd->mcodeptr)) = imm; \
+               cd->mcodeptr += 4; \
+       } while(0);
+
+#define M_BR_16(a)                     BRANCH16(0x0, (a))      /* branch always */
+#define M_BR_32(a)                     BRANCH32(0x0, (a))
+
+#define M_BEQ(a)                       BRANCH8 (0x7, (a))
+#define M_BEQ_16(a)                    BRANCH16(0x7, (a))
+#define M_BEQ_32(a)                    BRANCH32(0x7, (a))
+
+#define M_BNE(a)                       BRANCH8 (0x6, (a))
+#define M_BNE_16(a)                    BRANCH16(0x6, (a))
+#define M_BNE_32(a)                    BRANCH32(0x6, (a))
+
+#define M_BLT(a)                       BRANCH8 (0xd, (a))
+#define M_BLT_16(a)                    BRANCH16(0xd, (a))
+#define M_BLT_32(a)                    BRANCH32(0xd, (a))
+
+#define M_BGE(a)                       BRANCH8 (0xc, (a))
+#define M_BGE_16(a)                    BRANCH16(0xc, (a))
+#define M_BGE_32(a)                    BRANCH32(0xc, (a))
+
+#define M_BGT(a)                       BRANCH8 (0xe, (a))
+#define M_BGT_16(a)                    BRANCH16(0xe, (a))
+#define M_BGT_32(a)                    BRANCH32(0xe, (a))
+
+#define M_BLE(a)                       BRANCH8 (0xf, (a))
+#define M_BLE_16(a)                    BRANCH16(0xf, (a))
+#define M_BLE_32(a)                    BRANCH32(0xf, (a))
+
+#define M_BHI(a)                       BRANCH8 (0x2, (a))
+#define M_BHI_16(a)                    BRANCH16(0x2, (a))
+#define M_BHI_32(a)                    BRANCH32(0x2, (a))
+
+#define        M_BMI(a)                        BRANCH8(0xb, (a))
+#define M_BPL(a)                       BRANCH8(0xa, (a))
+
+#define M_BNAN_16(a)                   M_ILLEGAL               /* TODO */
+#define M_BNAN_32(a)                   M_ILLEGAL
+
+/* array store/load stuff */
+/* M_LXXX(baseaddressregister, targetregister) */
+/* M_SXXX(baseaddressregsiter, sourceregister)  */
+#define M_LBZX(a,c)                    OPWORD( ( (1<<6) | ((c) << 3) | 0), 2, (a))     /* move.l */
+#define M_LHZX(a,c)                    OPWORD( ( (3<<6) | ((c) << 3) | 0), 2, (a))
+#define        M_LWZX(a,c)                     OPWORD( ( (2<<6) | ((c) << 3) | 0), 2, (a))
+#define M_LAX(a,c)                     OPWORD( ( (2<<6) | ((c) << 3) | 1), 2, (a))     /* movea.l */
+
+#define M_STBX(a,c)                    OPWORD( ( (1<<6) | ((a) << 3) | 2), 0, (c))     /* move.l */
+#define M_STHX(a,c)                    OPWORD( ( (3<<6) | ((a) << 3) | 2), 0, (c))
+#define M_STWX(a,c)                    OPWORD( ( (2<<6) | ((a) << 3) | 2), 0, (c))
+#define M_STAX(a,c)                    OPWORD( ( (2<<6) | ((a) << 3) | 2), 1, (c))     /* movea.l */
+
+#define M_BSEXT(a,b)                   OPWORD( ( (7<<6) | ((b) << 3) | 4), 0, (a))     /* mvs.b */
+#define M_CZEXT(a,b)                   OPWORD( ( (7<<6) | ((b) << 3) | 7), 0, (a))     /* mvz.w */
+#define M_SSEXT(a,b)                   OPWORD( ( (7<<6) | ((b) << 3) | 5), 0, (a))     /* mvs.w */
+#define M_HSEXT(a,b)                   M_ILLEGAL
+
+/* adds content of integer reg a to address register b, result is b */
+#define M_AADDINT(a,b)                 OPWORD( ( (0xd<<6) | ((b) << 3) | 7), 0, (a))   /* adda.l */
+#define M_ASUBINT(a,b)                 OPWORD( ( (0x9<<6) | ((b) << 3) | 7), 0, (a))   /* suba.l */
+
+/* immideate a shift left int register b, immideate has 3 bits */
+#define M_ISSL_IMM(a,b)                        OPWORD_ASSERT( ((a)<=7), ( (0xe<<6) | ((a) << 3) | 6), 1, (b))  /* lsl */
+#define M_ISSR_IMM(a,b)                        OPWORD_ASSERT( ((a)<=7), ( (0xe<<6) | ((a) << 3) | 2), 0, (b))  /* lsl */
+#define M_IUSR_IMM(a,b)                        OPWORD_ASSERT( ((a)<=7), ( (0xe<<6) | ((a) << 3) | 2), 1, (b))  /* lsl */
+
+
+/* constant handling */
+/* XCONST(constant value, register) */
+#define LCONST(a,b)                    do {\
+                                               M_IMOV_IMM(((uint32_t)(a)), GET_LOW_REG((b)));\
+                                               M_IMOV_IMM(((uint32_t)(a>>32)), GET_HIGH_REG((b)));\
+                                       } while(0);
+
+#if !defined(ENABLE_SOFTFLOAT)
+       #define FCONST(a,b)             M_ILLEGAL
+       #define DCONST(a,b)             M_ILLEGAL
+#endif
+
+#define M_TRAP_SETREGISTER(a)          OPWORD( 0x128, 0, (a))          /* tst.b */
+#define M_TRAP(a) \
+       do { \
+               *((u2*)cd->mcodeptr) = (u2) ( 0x4e40 | (a) ); \
+               cd->mcodeptr += 2; \
+       } while(0);
+
+#endif /* _CODEGEN_H */
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..807ba412813a2fe3c883987925f40bb267950008 100644 (file)
@@ -0,0 +1,686 @@
+/* src/vm/jit/m68k/emit.c
+
+   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.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   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., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
+
+   $Id: arch.h 5330 2006-09-05 18:43:12Z edwin $
+
+*/
+#include "config.h"
+
+#include <assert.h>
+
+#include "emit.h"
+#include "vm/jit/emit-common.h"
+#include "vm/exceptions.h"
+#include "vm/jit/asmpart.h"
+
+#include "vm/builtin.h"
+#include "mm/memory.h"
+
+#include "codegen.h"
+
+/*
+ *     Loads an immededat operand into data register
+ */
+void emit_mov_imm_reg (codegendata *cd, s4 imm, s4 dreg)
+{
+       if ((imm & 0x000000FF) == imm)  {
+               /* use byte form */
+               *((s2*)cd->mcodeptr) = 0x7000 | (dreg << 9) | imm;      /* MOVEQ.L */
+               cd->mcodeptr += 2;
+       } else if ((imm  & 0xFFFF0000) != 0)    {
+               /* use long form */
+               OPWORD( ((2<<6) | (dreg << 3) | 0), 7, 4);
+               *((s4*)cd->mcodeptr) = (s4)imm;
+               cd->mcodeptr += 4;
+       } else {
+               /* use word form */
+               OPWORD( ((3<<6) | (dreg << 3) | 0), 7, 4);
+               *((s2*)cd->mcodeptr) = (s2)imm;
+               cd->mcodeptr += 2;
+       }
+}
+
+/* emit_copy *******************************************************************
+
+   Generates a register/memory to register/memory copy.
+
+*******************************************************************************/
+void emit_copy(jitdata *jd, instruction *iptr, varinfo *src, varinfo *dst)
+{
+       codegendata  *cd;
+       s4            s1, d;
+
+       /* get required compiler data */
+
+       cd = jd->cd;
+
+       if ((src->vv.regoff != dst->vv.regoff) ||
+               (IS_INMEMORY(src->flags ^ dst->flags))) {
+
+               /* If one of the variables resides in memory, we can eliminate
+                  the register move from/to the temporary register with the
+                  order of getting the destination register and the load. */
+
+               if (IS_INMEMORY(src->flags)) {
+                       if (IS_LNG_TYPE(src->type))
+                               d = codegen_reg_of_var(iptr->opc, dst, REG_ITMP12_PACKED);
+                       else
+                               d = codegen_reg_of_var(iptr->opc, dst, REG_IFTMP);
+
+                       s1 = emit_load(jd, iptr, src, d);
+               } else {
+                       if (IS_LNG_TYPE(src->type))
+                               s1 = emit_load(jd, iptr, src, REG_ITMP12_PACKED);
+                       else
+                               s1 = emit_load(jd, iptr, src, REG_IFTMP);
+
+                       d = codegen_reg_of_var(iptr->opc, dst, s1);
+               }
+
+               if (s1 != d) {
+                       switch(src->type)       {
+                               case TYPE_INT: M_INTMOVE(s1, d); break;
+                               case TYPE_ADR: M_ADRMOVE(s1, d); break;
+                               case TYPE_LNG: M_LNGMOVE(s1, d); break;
+#if !defined(ENABLE_SOFTFLOAT)
+                               case TYPE_FLT: M_FLTMOVE(s1, d); break;
+                               case TYPE_DBL: M_DBLMOVE(s1, d); break;
+#else
+                               case TYPE_FLT: M_INTMOVE(s1, d); break;
+                               case TYPE_DBL: M_LNGMOVE(s1, d); break;
+#endif
+                               default: assert(0);
+                       }
+               }
+               emit_store(jd, iptr, dst, d);
+       }
+}
+/* emit_store ******************************************************************
+
+   Emits a possible store of the destination operand.
+
+*******************************************************************************/
+
+inline void emit_store(jitdata *jd, instruction *iptr, varinfo *dst, s4 d)
+{
+       codegendata  *cd;
+
+       /* get required compiler data */
+
+       cd = jd->cd;
+
+       if (IS_INMEMORY(dst->flags)) {
+               COUNT_SPILLS;
+       
+               switch(dst->type)       {
+#if defined(ENABLE_SOFTFLOAT)
+                       case TYPE_DBL:
+#endif
+                       case TYPE_LNG:
+                               M_LST(d, REG_SP, dst->vv.regoff * 4);
+                               break;
+#if defined(ENABLE_SOFTFLOAT)
+                       case TYPE_FLT:
+#endif
+                       case TYPE_INT:
+                               M_IST(d, REG_SP, dst->vv.regoff * 4);
+                               break;
+                       case TYPE_ADR:
+                               M_AST(d, REG_SP, dst->vv.regoff * 4);
+                               break;
+#if !defined(ENABLE_SOFTFLOAT)
+                       case TYPE_DBL:
+                               M_DST(d, REG_SP, dst->vv.regoff * 4);
+                               break;
+                       case TYPE_FLT:
+                               M_FST(d, REG_SP, dst->vv.regoff * 4);
+                               break;
+#endif
+                       default:
+                               assert(0);
+               }
+       }
+}
+/* emit_load *******************************************************************
+
+   Emits a possible load of an operand.
+
+*******************************************************************************/
+s4 emit_load(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
+{
+       codegendata *cd;
+       s4           disp;
+       s4           reg;
+
+       /* get required compiler data */
+
+       cd = jd->cd;
+
+       if (IS_INMEMORY(src->flags)) {
+               COUNT_SPILLS;
+
+               disp = src->vv.regoff * 4;
+       
+               switch (src->type)      {
+#if defined(ENABLE_SOFTFLOAT)
+                       case TYPE_FLT:
+#endif
+                       case TYPE_INT: 
+                               M_ILD(tempreg, REG_SP, disp);
+                               break;
+#if defined(ENABLE_SOFTFLOAT)
+                       case TYPE_DBL:
+#endif
+                       case TYPE_LNG:
+                               M_LLD(tempreg, REG_SP, disp);
+                               break;
+                       case TYPE_ADR:
+                               M_ALD(tempreg, REG_SP, disp);
+                               break;
+#if !defined(ENABLE_SOFTFLOAT)
+                       case TYPE_FLT:
+                               M_FLD(tempreg, REG_SP, disp);
+                               break;
+                       case TYPE_DBL:
+                               M_DLD(tempreg, REG_SP, disp);
+                               break;
+#endif
+                       default: assert(0);
+               }
+               #if 0
+               if (IS_FLT_DBL_TYPE(src->type)) {
+                       if (IS_2_WORD_TYPE(src->type)) {
+                               M_DLD(tempreg, REG_SP, disp);
+                        } else {
+                               M_FLD(tempreg, REG_SP, disp);
+                       }
+               } else {
+                       if (IS_2_WORD_TYPE(src->type)) {
+                               M_LLD(tempreg, REG_SP, disp);
+                       } else {
+                               M_ILD(tempreg, REG_SP, disp);
+                       }
+               }
+               #endif
+
+               reg = tempreg;
+       }
+       else
+               reg = src->vv.regoff;
+
+       return reg;
+}
+
+
+/* emit_patcher_stubs **********************************************************
+
+   Generates the code for the patcher stubs.
+
+*******************************************************************************/
+void emit_patcher_stubs(jitdata *jd)
+{
+       codegendata *cd;
+       patchref    *pref;
+       u8           mcode;
+       u1          *savedmcodeptr;
+       u1          *tmpmcodeptr;
+       s4           targetdisp;
+       s4           disp;
+
+       /* get required compiler data */
+
+       cd = jd->cd;
+
+       /* generate code patching stub call code */
+
+       targetdisp = 0;
+
+       for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
+               /* check code segment size */
+
+               MCODECHECK(512);
+
+               /* Get machine code which is patched back in later. A
+                  `bsr.l' is 6 bytes long. */
+
+               savedmcodeptr = cd->mcodebase + pref->branchpos;
+               mcode = *((u8 *) savedmcodeptr);
+
+               /* patch in `bsr.l' to call the following code */
+
+               tmpmcodeptr  = cd->mcodeptr;    /* save current mcodeptr              */
+               cd->mcodeptr = savedmcodeptr;   /* set mcodeptr to patch position     */
+
+               M_BSR_IMM(tmpmcodeptr - (savedmcodeptr + PATCHER_CALL_SIZE) + 4);
+
+               cd->mcodeptr = tmpmcodeptr;     /* restore the current mcodeptr       */
+
+               /* save REG_ITMP3 */
+               M_IPUSH(REG_ITMP3);     /* FIXME why, and restore where ? */
+
+               /* move pointer to java_objectheader onto stack */
+
+#if defined(ENABLE_THREADS)
+               (void) dseg_add_unique_address(cd, NULL);                  /* flcword */
+               (void) dseg_add_unique_address(cd, lock_get_initial_lock_word());
+               disp = dseg_add_unique_address(cd, NULL);                  /* vftbl   */
+
+               assert(0); /* The next lines are wrong */
+               M_MOV_IMM(0, REG_ITMP3);
+               dseg_adddata(cd);
+               M_AADD_IMM(REG_ITMP3, disp);
+               M_IPUSH(REG_ITMP3);
+#else
+               M_IPUSH_IMM(0);
+#endif
+
+               /* push move machine code bytes and classinfo pointer */
+
+               M_IPUSH_IMM(mcode >> 32);
+               M_IPUSH_IMM(mcode);
+               M_IPUSH_IMM(pref->ref);
+               M_IPUSH_IMM(pref->patcher);
+
+               M_JMP_IMM(asm_patcher_wrapper);
+       }
+}
+s4 emit_load_low(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg) 
+{
+       codegendata  *cd;
+       s4            disp;
+       s4            reg;
+
+       assert(src->type == TYPE_LNG);
+
+       /* get required compiler data */
+       cd = jd->cd;
+
+       if (IS_INMEMORY(src->flags)) {
+               COUNT_SPILLS;
+
+               disp = src->vv.regoff * 4;
+               M_ILD(tempreg, REG_SP, disp + 4);
+               reg = tempreg;
+       } else {
+               reg = GET_LOW_REG(src->vv.regoff);
+       }
+       return reg;
+}
+s4 emit_load_high(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
+{
+       codegendata  *cd;
+       s4            disp;
+       s4            reg;
+
+       assert(src->type == TYPE_LNG);
+
+       /* get required compiler data */
+       cd = jd->cd;
+
+       if (IS_INMEMORY(src->flags)) {
+               COUNT_SPILLS;
+               disp = src->vv.regoff * 4;
+               M_ILD(tempreg, REG_SP, disp);
+               reg = tempreg;
+       } else {
+               reg = GET_HIGH_REG(src->vv.regoff);
+       }
+       return reg;
+}
+/* emit_branch *****************************************************************
+
+   Emits the code for conditional and unconditional branchs.
+
+*******************************************************************************/
+void emit_branch(codegendata *cd, s4 disp, s4 condition, s4 reg, u4 opt) 
+{ 
+       /* calculate the different displacements */
+       /* PC is a at branch instruction + 2 */
+       /* coditional and uncondition branching work the same way */
+       /* short branches have signed 16 bit offset */
+       /* long branches are signed 32 bit */
+       /* the 8 bit offset branching instructions are not used */
+
+       disp  =  disp - 2;
+
+       /* check displacement for overflow */
+       if ((disp & 0x0000FFFF) != disp)        {
+               if (!CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
+                       cd->flags |= (CODEGENDATA_FLAG_ERROR | CODEGENDATA_FLAG_LONGBRANCHES);
+               }
+       }
+
+       /* check which branch to generate */
+
+       if (condition == BRANCH_UNCONDITIONAL) {
+               if (CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd))      {
+                       M_BR_32(disp);
+               } else  {
+                       M_BR_16(disp);
+               }
+       } else {
+               if (CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
+                       switch (condition) {
+                       case BRANCH_EQ:
+                               M_BEQ_32(disp);
+                               break;
+                       case BRANCH_NE:
+                               M_BNE_32(disp);
+                               break;
+                       case BRANCH_LT:
+                               M_BLT_32(disp);
+                               break;
+                       case BRANCH_GE:
+                               M_BGE_32(disp);
+                               break;
+                       case BRANCH_GT:
+                               M_BGT_32(disp);
+                               break;
+                       case BRANCH_LE:
+                               M_BLE_32(disp);
+                               break;
+                       case BRANCH_NAN:
+                               M_BNAN_32(disp);
+                               break;
+                       case BRANCH_UGT:
+                               M_BHI_32(disp);
+                               break;
+
+                       default:
+                               vm_abort("emit_branch: unknown condition %d", condition);
+                       }
+               } else {
+                       switch (condition) {
+                       case BRANCH_EQ:
+                               M_BEQ_16(disp);
+                               break;
+                       case BRANCH_NE:
+                               M_BNE_16(disp);
+                               break;
+                       case BRANCH_LT:
+                               M_BLT_16(disp);
+                               break;
+                       case BRANCH_GE:
+                               M_BGE_16(disp);
+                               break;
+                       case BRANCH_GT:
+                               M_BGT_16(disp);
+                               break;
+                       case BRANCH_LE:
+                               M_BLE_16(disp);
+                               break;
+                       case BRANCH_NAN:
+                               M_BNAN_16(disp);
+                               break;
+                       case BRANCH_UGT:
+                               M_BHI_16(disp);
+                               break;
+                       default:
+                               vm_abort("emit_branch: unknown condition %d", condition);
+                       }
+               }
+       }
+}
+
+
+#if !defined(NDEBUG)
+/*
+ *     Trace functions. Implement -verbose:call flag
+ *     code marked by real NOP, but performance is no matter when using -verbose:call :)
+ */
+void emit_verbosecall_enter(jitdata* jd) 
+{ 
+       methodinfo   *m;
+       codegendata  *cd;
+       registerdata *rd;
+       methoddesc   *md;
+       s4      disp,i,t;
+
+
+       if (!JITDATA_HAS_FLAG_VERBOSECALL(jd))
+               return;
+       
+       /* get required compiler data */
+       m  = jd->m;
+       cd = jd->cd;
+       rd = jd->rd;
+       md = m->parseddesc;
+
+       /* mark trace code */
+       M_NOP;
+
+       M_LINK(REG_FP, -16*4);  
+       M_PUSHALL;
+
+       /* builtin_verbosecall_enter takes all args as s8 type */
+       /* TRACE_ARGS_NUM is the number of args the builtin_verbosecall_enter expects */
+       M_IPUSH_IMM(m);
+       
+       disp = 16*4 + 4 + 4;    /* points to old argument stack initially */
+
+       /* travel up stack to the first argument of the function which needs to be copied */
+       for (i=0; (i < md->paramcount) && (i < TRACE_ARGS_NUM); i++)    {
+               disp += 4;
+               if (IS_2_WORD_TYPE(md->paramtypes[i].type)) {   
+                       disp += 4;
+               }
+       }
+
+       /* disp now points to the first arg which gets copied to the trace stack, relative to REG_SP! */
+       for (i=TRACE_ARGS_NUM-1; i>=0; --i) {
+               if (i < md->paramcount) {
+                       /* traced function has such an argument */
+                       t = md->paramtypes[i].type;
+                       
+                       if (IS_2_WORD_TYPE(t))  {
+                               /* copy from original argument stack */
+                               M_ILD(REG_ITMP1, REG_SP, disp);
+                               M_IPUSH(REG_ITMP1);
+                               M_ILD(REG_ITMP1, REG_SP, disp);
+                               M_IPUSH(REG_ITMP1);
+                       } else  {
+                               /* displacment is increased as 4 byte on original stack but 8 byte on trace stack */
+                               M_ILD(REG_ITMP1, REG_SP, disp);
+                               M_IPUSH(REG_ITMP1);
+                               M_IPUSH_IMM(0);
+                               disp += 4;
+                       }
+               } else  {
+                       /* function has no arg here, push nothing and adapt displacement */
+                       M_IPUSH_IMM(0);
+                       M_IPUSH_IMM(0);
+                       disp += 8;
+               }
+       }
+       M_JSR_IMM(builtin_verbosecall_enter);
+       /* pop arguments off stack */
+       M_AADD_IMM(TRACE_ARGS_NUM*8+4, REG_SP);
+
+       M_POPALL;
+       M_UNLK(REG_FP);
+       M_NOP;
+}
+void emit_verbosecall_exit(jitdata* jd) 
+{ 
+       methodinfo   *m;
+       codegendata  *cd;
+       registerdata *rd;
+       methoddesc   *md;
+
+       if (!JITDATA_HAS_FLAG_VERBOSECALL(jd))
+               return;
+
+       /* get required compiler data */
+       m  = jd->m;
+       cd = jd->cd;
+       rd = jd->rd;
+       md = m->parseddesc;
+
+       /* void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m); */
+
+
+       /* mark trace code */
+       M_NOP;
+       M_LINK(REG_FP, 0);
+
+       M_IPUSH_IMM(m);                                 /* push methodinfo */
+
+       M_IPUSH_IMM(0);                                 /* TODO push float result */
+
+       M_IPUSH_IMM(0);                                 /* TODO push double result */
+       M_IPUSH_IMM(0);                                 /* TODO push double result */
+
+       M_IPUSH(GET_HIGH_REG(REG_RESULT_PACKED))
+       M_IPUSH(GET_LOW_REG(REG_RESULT_PACKED))         /* push long result */
+
+
+       M_JSR_IMM(builtin_verbosecall_exit);
+
+       /* poping result registers from stack */
+       M_IPOP(GET_LOW_REG(REG_RESULT_PACKED))
+       M_IPOP(GET_HIGH_REG(REG_RESULT_PACKED))
+
+#if 0
+       /* that is wrong of course, overwrites registers and stuff */
+       M_IPOP(0);      /* TODO: pop double result */
+       M_IPOP(0);      /* TODO: pop double result */
+
+       M_IPOP(0);      /* TODO: pop float result */
+#else
+       M_AADD_IMM(3*4, REG_SP);
+#endif
+       M_AADD_IMM(4, REG_SP);                          /* remove rest of stack */
+       M_UNLK(REG_FP);
+       M_NOP;
+}
+#endif
+
+/* emit_classcast_check ********************************************************
+
+   Emit a ClassCastException check.
+
+*******************************************************************************/
+
+void emit_classcast_check(codegendata *cd, instruction *iptr, s4 condition, s4 reg, s4 s1)
+{
+       if (INSTRUCTION_MUST_CHECK(iptr)) {
+               switch (condition) {
+               case BRANCH_LE:
+                       M_BGT(4);
+                       break;
+               case BRANCH_EQ:
+                       M_BNE(4);
+                       break;
+               case BRANCH_GT:
+                       M_BLE(4);
+                       break;
+               case BRANCH_UGT:
+                       M_BHI(4);
+                       break;
+               default:
+                       vm_abort("emit_classcast_check: unknown condition %d", condition);
+               }
+               M_TRAP_SETREGISTER(s1);
+               M_TRAP(EXCEPTION_HARDWARE_CLASSCAST);
+       }
+}
+
+/* emit_arrayindexoutofbounds_check ********************************************
+
+   Emit a ArrayIndexOutOfBoundsException check.
+
+*******************************************************************************/
+void emit_arrayindexoutofbounds_check(codegendata *cd, instruction *iptr, s4 s1, s4 s2)
+{
+       if (INSTRUCTION_MUST_CHECK(iptr)) {
+               M_ILD(REG_ITMP3, s1, OFFSET(java_arrayheader, size));
+               M_ICMP(REG_ITMP3, s2);
+               M_BLT(2);
+               /*M_ALD_INTERN(s2, REG_ZERO, EXCEPTION_LOAD_DISP_ARRAYINDEXOUTOFBOUNDS);*/
+               M_ILLEGAL; /*FIXME */
+       }
+}
+
+/* emit_nullpointer_check ******************************************************
+
+   Emit a NullPointerException check.
+
+*******************************************************************************/
+void emit_nullpointer_check(codegendata *cd, instruction *iptr, s4 reg)
+{
+       if (INSTRUCTION_MUST_CHECK(iptr)) {
+               /* did like to assert on TYPE_ADR, but not possible in here */
+               /* so assert before each emit_nullpointer_check */
+               M_ATST(reg);
+               M_BNE(2);
+               /*M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_LOAD_DISP_NULLPOINTER);*/
+               M_ILLEGAL;
+       }
+}
+
+/* emit_arithmetic_check *******************************************************
+
+   Emit an ArithmeticException check.
+
+*******************************************************************************/
+
+void emit_arithmetic_check(codegendata *cd, instruction *iptr, s4 reg)
+{
+       if (INSTRUCTION_MUST_CHECK(iptr)) {
+               M_ITST(reg);
+               M_BNE(2);
+               /*M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_ARITHMETIC);*/
+               M_ILLEGAL; /* FIXME */
+       }
+}
+
+/* emit_exception_check_areg **************************************************
+ *
+   Emit an Exception check, tested register is address REG_RESULT
+
+*******************************************************************************/
+void emit_exception_check_areg(codegendata *cd, instruction *iptr)
+{
+       if (INSTRUCTION_MUST_CHECK(iptr)) {
+               M_ATST(REG_RESULT);
+               M_BNE(2);
+               /*M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_EXCEPTION);*/
+               M_ILLEGAL; /*FIXME*/
+       }
+}
+/* emit_exception_check_ireg **************************************************
+
+   Emit an Exception check. Teste register is integer REG_RESULT
+
+*******************************************************************************/
+void emit_exception_check_ireg(codegendata *cd, instruction *iptr)
+{
+       if (INSTRUCTION_MUST_CHECK(iptr)) {
+               M_ITST(REG_RESULT);
+               M_BNE(2);
+               /*M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_EXCEPTION);*/
+               M_ILLEGAL; /*FIXME*/
+       }
+}
+
index d920d138d30306b702d48a2cfd78a4ba0cb6bf30..7d939407eeab88afeb08fd7f8858af4bf38e7c74 100644 (file)
@@ -1,15 +1,50 @@
+/* src/vm/jit/m68k/machine-instr.h  
+
+   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.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   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., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
+
+   $Id: arch.h 5330 2006-09-05 18:43:12Z edwin $
+
+*/
+
+
 #ifndef _MACHINE_INSTR_H
 #define _MACHINE_INSTR_H
 
 static inline long compare_and_swap(long *p, long oldval, long newval)
 {
-       assert(0);
-       return 0;
+       /* XXX, coldifre has no atomic compare and swap instrcution */
+       #warning "compare_and_swap is not atmically"
+       if (*p == oldval)       {
+               *p = newval;
+               return oldval;
+       } 
+       return *p;
 }
 
-#define STORE_ORDER_BARRIER()                          assert(0);
-#define MEMORY_BARRIER_BEFORE_ATOMIC()                 assert(0); 
-#define MEMORY_BARRIER_AFTER_ATOMIC()                  assert(0);
-#define MEMORY_BARRIER()                               assert(0);
+
+#define STORE_ORDER_BARRIER() __asm__ __volatile__ ("" : : : "memory");
+#define MEMORY_BARRIER_BEFORE_ATOMIC() __asm__ __volatile__ ("" : : : "memory");
+#define MEMORY_BARRIER_AFTER_ATOMIC() __asm__ __volatile__ ("" : : : "memory");
+#define MEMORY_BARRIER() __asm__ __volatile__ ( "" : : : "memory" );
 
 #endif
index 43bbdb1337f0215d8c7972e828daf7843bdb98e5..4214fad1b1668b5f78a1350a0ad268ec49c6dab0 100644 (file)
-void md_init(void) {}
+/*     src/vm/jit/m68k/md.c
 
-void md_get_method_patch_address(void) {}
-void md_icacheflush(void) {}
-void md_stacktrace_get_returnaddress(void) {}
-void md_codegen_get_pv_from_pc(void) {}
-void md_signal_handler_sigsegv(void) {}
-void md_codegen_patch_branch(void) {}
-void md_cacheflush(void) {}
-void md_param_alloc(void) {}
-void md_return_alloc(void) {}
+   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.
 
-int nregdescint;
-int nregdescfloat;
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   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., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
+
+   $Id: arch.h 5330 2006-09-05 18:43:12Z edwin $
+
+*/
+#include "config.h"
+
+#include <assert.h>
+
+#include "md-os.h"
+
+#include "vm/types.h"
+#include "vm/jit/codegen-common.h"
+#include "vm/jit/md.h"
+
+#include "offsets.h"
+#include "vm/vm.h"
+#include "vmcore/class.h"
+#include "vmcore/linker.h"
+#include "vmcore/method.h"
+#include "mm/memory.h"
+#include "vm/jit/asmpart.h"
+/*
+ *     As a sanity measuremnt we assert the offset.h values in here as m68k gets
+ *     crosscompiled for sure and noone thinks of offset.h wen changing compile flags
+ *     and subtile bugs will result...
+ *
+ *     m68k uses the trap instruction for hardware exceptions, need to register
+ *     according signal handler
+ */
+void md_init(void) 
+{
+       assert(sizeof(vm_arg) == sizevmarg);
+       assert(OFFSET(java_objectheader, vftbl) == offobjvftbl);
+       assert(OFFSET(vftbl_t, baseval) == offbaseval);
+       assert(OFFSET(vftbl_t, diffval) == offdiffval);
+       assert(OFFSET(vm_arg, type) == offvmargtype);
+       assert(OFFSET(vm_arg, data) == offvmargdata);
+       assert(OFFSET(castinfo, super_baseval) == offcast_super_baseval);
+       assert(OFFSET(castinfo, super_diffval) == offcast_super_diffval);
+       assert(OFFSET(castinfo, sub_baseval) == offcast_sub_baseval);
+
+#if defined(ENABLE_REPLACEMENT)
+       assert(sizeof(executionstate_t) = sizeexecutionstate);
+       assert(OFFSET(executionstate_t, pc) == offes_pc);
+       assert(OFFSET(executionstate_t, sp) == offes_sp);
+       assert(OFFSET(executionstate_t, pv) == offes_pv);
+       assert(OFFSET(executionstate_t, intregs) == offes_intregs);
+       assert(OFFSET(executionstate_t, fltregs) == offes_fltregs);
+#endif
+
+#ifdef __LINUX__
+       md_init_linux();
+#endif
+}
+
+/* md_codegen_get_pv_from_pc ***************************************************
+
+   On this architecture just a wrapper function to
+   codegen_get_pv_from_pc.
+
+*******************************************************************************/
+u1* md_codegen_get_pv_from_pc(u1 *ra) 
+{ 
+       u1 *pv;
+       pv = codegen_get_pv_from_pc(ra);
+
+       return pv;
+}
+
+/* md_get_method_patch_address *************************************************
+   Gets the patch address of the currently compiled method. Has to be 
+   extracted from the load instructions which lead to the jump.
+
+from asmpart.S (asm_vm_call_method):
+84:   2879 0000 0000  moveal 0 <asm_vm_call_method-0x34>,%a4
+8a:   4e94            jsr %a4@
+
+
+from invokestatic / invokespecial
+0x40290882:   247c 4029 03b4    moveal #1076429748,%a2
+0x40290888:   4e92              jsr %a2@
+
+from invokevirtual
+0x40297eca:   266a 0000         moveal %a2@(0),%a3
+0x40297ece:   246b 002c         moveal %a3@(44),%a2
+0x40297ed2:   4e92              jsr %a2@
+
+
+
+*******************************************************************************/
+
+u1* md_get_method_patch_address(u1 *ra, stackframeinfo *sfi, u1 *mptr) 
+{
+       u1 * pa;
+       s2   offset;
+
+       if (*((u2*)(ra - 2)) == 0x4e94) {               /* jsr %a4@ */
+               /* we had a moveal XXX, %a3 which is a 3 word opcode */
+               /* 2679 0000 0000 */
+               assert(*(u2*)(ra - 8) == 0x2879);               /* moveal */
+               pa = *((u4*)(ra - 6));                          /* another indirection ! */
+       } else if (*((u2*)(ra - 2)) == 0x4e92)  {               /* jsr %a2@ */
+               if (*(u2*)(ra - 8) == 0x247c)   {
+                       /* found a invokestatic/invokespecial */
+                       pa = ((u4*)(ra - 6));                   /* no indirection ! */
+               } else if (*((u2*)(ra - 6)) == 0x246b)  {
+                       /* found an invokevirtual */
+                       /* get offset of load instruction 246b XXXX */
+                       offset = *((s2*)(ra - 4));
+                       pa = mptr + offset;                     /* mptr contains the magic we want */
+               } else  {
+                       assert(0);
+               }
+       } else {
+               assert(0);
+       }
+
+       return pa;
+}
+
+/* XXX i can't find a definition of cacheflush in any installed header files but i can find the symbol in libc */
+/* lets extract the signature from the assembler code*/
+/*
+    000e7158 <cacheflush>:
+    e7158:       707b            moveq #123,%d0
+    e715a:       2f04            movel %d4,%sp@-
+    e715c:       282f 0014       movel %sp@(20),%d4                    arg 
+    e7160:       2243            moveal %d3,%a1
+    e7162:       262f 0010       movel %sp@(16),%d3                    arg 
+    e7166:       2042            moveal %d2,%a0
+    e7168:       242f 000c       movel %sp@(12),%d2                    arg 
+    e716c:       222f 0008       movel %sp@(8),%d1                     arg 
+    e7170:       4e40            trap #0                               traps into system i guess
+    e7172:       2408            movel %a0,%d2
+    e7174:       2609            movel %a1,%d3
+    e7176:       281f            movel %sp@+,%d4
+    e7178:       223c ffff f001  movel #-4095,%d1
+    e717e:       b081            cmpl %d1,%d0
+    e7180:       6402            bccs e7184 <cacheflush+0x2c>
+    e7182:       4e75            rts
+    e7184:       4480            negl %d0
+    e7186:       2f00            movel %d0,%sp@-
+    e7188:       61ff fff3 82e2  bsrl 1f46c <D_MAX_EXP+0x1ec6d>
+    e718e:       209f            movel %sp@+,%a0@
+    e7190:       70ff            moveq #-1,%d0
+    e7192:       2040            moveal %d0,%a0
+    e7194:       4e75            rts
+    e7196:       4e75            rts
+                                                                       */
+
+/* seems to have 4 arguments */
+/* best guess: it is this syscall */
+/* asmlinkage int sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len) */
+/* kernel 2.6.10 with freescale patches (the one I develop against) needs a patch of */
+/* arch/m68k/kernel/sys_m68k.c(sys_cacheflush) */
+/* evil hack: */
+/*
+void DcacheFlushInvalidateCacheBlock(void *start, unsigned long size);
+void IcacheInvalidateCacheBlock(void *start, unsigned long size);
+
+asmlinkage int
+sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
+{
+       lock_kernel();
+       DcacheFlushInvalidateCacheBlock(addr, len);
+       IcacheInvalidateCacheBlock(addr, len);
+       unlock_kernel();
+       return 0;
+}
+*/
+extern int cacheflush(unsigned long addr, int scope, int cache, unsigned long len);
+
+#include "asm/cachectl.h"      /* found more traces of the cacheflush function */
+#include "errno.h"
+
+void md_cacheflush(u1 *addr, s4 nbytes)  { cacheflush(addr, FLUSH_SCOPE_PAGE, FLUSH_CACHE_BOTH, nbytes); }
+void md_dcacheflush(u1 *addr, s4 nbytes) { cacheflush(addr, FLUSH_SCOPE_PAGE, FLUSH_CACHE_DATA, nbytes); }
+void md_icacheflush(u1* addr, s4 nbytes) { cacheflush(addr, FLUSH_SCOPE_LINE, FLUSH_CACHE_INSN, nbytes); }
+
+/* md_stacktrace_get_returnaddress *********************************************
+
+   Returns the return address of the current stackframe, specified by
+   the passed stack pointer and the stack frame size.
+
+*******************************************************************************/
+u1* md_stacktrace_get_returnaddress(u1* sp, u4 framesize) 
+{ 
+       /* return address is above stackpointer */
+       u1 *ra = *((u1**)(sp + framesize));
+       return ra;
+}
+
+
+void md_codegen_patch_branch(void) { assert(0); }
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..8e00d734fc9a1441d973aa162711769cc3f26238 100644 (file)
@@ -0,0 +1,694 @@
+/* src/vm/jit/m68k/patcher.c - m68k patcher functions
+
+   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.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   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., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
+
+   $Id: arch.h 5330 2006-09-05 18:43:12Z edwin $
+
+*/
+
+#include "config.h"
+
+#include <assert.h>
+
+#include "vm/types.h"
+
+#include "mm/memory.h"
+#include "native/native.h"
+
+#include "vm/builtin.h"
+#include "vm/exceptions.h"
+#include "vm/initialize.h"
+#include "vm/resolve.h"
+
+#include "vm/jit/asmpart.h"
+#include "vm/jit/patcher.h"
+#include "vm/jit/md.h"
+#include "vm/jit/methodheader.h"
+#include "vm/jit/stacktrace.h"
+
+#include "vmcore/class.h"
+#include "vmcore/field.h"
+#include "vmcore/options.h"
+#include "vmcore/references.h"
+
+#include "codegen.h"
+
+/* patcher_wrapper *************************************************************
+
+   Wrapper for all patchers.  It also creates the stackframe info
+   structure.
+
+   If the return value of the patcher function is false, it gets the
+   exception object, clears the exception pointer and returns the
+   exception.
+
+*******************************************************************************/
+
+java_objectheader *patcher_wrapper(u1 *sp, u1 *pv, u1 *ra)
+{
+       stackframeinfo     sfi;
+       u1                *xpc;
+       java_objectheader *o;
+       functionptr        f;
+       bool               result;
+       java_objectheader *e;
+       u4                 mcode, xmcode;
+
+       /* define the patcher function */
+
+       bool (*patcher_function)(u1 *);
+
+       /* get stuff from the stack */
+
+       xpc = (u1 *)                *((ptrint *) (sp + 6 * 4));
+       /* REG_ITMP3                              sp + 5 * 4 */
+       o   = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
+       mcode =                     *((u4*)      (sp + 3 * 4));
+       xmcode =                    *((u4*)      (sp + 2 * 4));
+       /* unresolved file                        sp + 1 * 4 */
+       f   = (functionptr)         *((ptrint *) (sp + 0 * 4));
+
+
+       /* calculate and set the new return address */
+
+       xpc = xpc - PATCHER_CALL_SIZE;
+       *((ptrint *) (sp + 6 * 4)) = (ptrint) xpc;
+
+       /* patch back original code */
+
+       *((u4*)(xpc))   = mcode;
+       *((u4*)(xpc+4)) = xmcode;
+       md_icacheflush(xpc, 8);
+
+       /* cast the passed function to a patcher function */
+
+       patcher_function = (bool (*)(u1 *)) (ptrint) f;
+
+       /* enter a monitor on the patching position */
+
+       PATCHER_MONITORENTER;
+
+       /* create the stackframeinfo */
+
+       /* RA is passed as NULL, but the XPC is correct and can be used in
+          stacktrace_create_extern_stackframeinfo for
+          md_codegen_get_pv_from_pc. */
+
+       stacktrace_create_extern_stackframeinfo(&sfi, pv, sp + 7 * 4, xpc, xpc);
+
+       /* call the proper patcher function */
+
+       result = (patcher_function)(sp);
+
+       /* remove the stackframeinfo */
+
+       stacktrace_remove_stackframeinfo(&sfi);
+
+       /* check for return value and exit accordingly */
+
+       if (result == false) {
+               e = exceptions_get_and_clear_exception();
+
+               PATCHER_MONITOREXIT;
+
+               return e;
+       }
+       PATCHER_MARK_PATCHED_MONITOREXIT;
+
+       return NULL;
+}
+
+/* patcher_initialize_class ****************************************************
+
+   Initalizes a given classinfo pointer.  This function does not patch
+   any data.
+
+*******************************************************************************/
+
+bool patcher_initialize_class(u1 *sp)
+{
+       classinfo *c;
+
+       /* get stuff from the stack */
+
+       c = (classinfo *) *((ptrint *) (sp + 1 * 4));
+
+       /* check if the class is initialized */
+
+       if (!(c->state & CLASS_INITIALIZED))
+               if (!initialize_class(c))
+                       return false;
+
+       return true;
+}
+
+/* patcher_invokevirtual *******************************************************
+
+   Machine code:
+0x4029bc46:   61ff 0000 00ba    bsrl 0x4029bd02
+0x4029bc4c:   246f 0000         moveal %sp@(0),%a2
+0x4029bc50:   266a 0000         moveal %a2@(0),%a3
+0x4029bc54:   246b 0000         moveal %a3@(0),%a2     <-- patch this (0) offset
+0x4029bc58:   4e92              jsr %a2@
+
+*******************************************************************************/
+
+bool patcher_invokevirtual(u1 *sp)
+{
+       u1                *ra;
+       unresolved_method *um;
+       methodinfo        *m;
+       s2                 disp;
+
+       /* get stuff from the stack */
+       ra = (u1 *)                *((ptrint *) (sp + 6 * 4));
+       um = (unresolved_method *) *((ptrint *) (sp + 1 * 4));
+
+       /* get the fieldinfo */
+       if (!(m = resolve_method_eager(um)))
+               return false;
+
+       /* if we show NOPs, we have to skip them */
+       if (opt_shownops) ra += PATCHER_CALL_SIZE;
+
+       assert( *((u2*)(ra+8)) == 0x246b);
+
+       /* patch vftbl index */
+       disp = (OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex);
+       *((s2 *) (ra + 10)) = disp;
+
+       /* synchronize instruction cache */
+       md_icacheflush(ra + 10, 2);
+
+       return true;
+}
+
+/* patcher_invokestatic_special ************************************************
+
+   Machine code:
+
+   INVOKESPECIAL
+0x402902bc:   61ff 0000 0076    bsrl 0x40290334
+0x402902c2:   247c 0000 0000    moveal #0,%a2          <-- this #0
+0x402902c8:   4e92              jsr %a2@
+
+******************************************************************************/
+
+bool patcher_invokestatic_special(u1 *sp)
+{
+       unresolved_method *um;
+       s4                 disp;
+       methodinfo        *m;
+
+       /* get stuff from the stack */
+
+       disp =                       *((s4 *)     (sp + 6 * 4));
+       um   = (unresolved_method *) *((ptrint *) (sp + 1 * 4));
+
+       /* get the fieldinfo */
+
+       if (!(m = resolve_method_eager(um)))
+               return false;
+
+       /* patch stubroutine */
+
+       if (opt_shownops) disp += PATCHER_CALL_SIZE;
+
+       *((ptrint *) (disp+2)) = (ptrint) m->stubroutine;
+
+       /* synchronize inst cache */
+
+       md_icacheflush(disp+2, SIZEOF_VOID_P);
+
+       return true;
+}
+
+
+/* patcher_resolve_class *******************************************************
+
+   Resolves a given unresolved_class pointer.  This function does not
+   patch any data.
+
+*******************************************************************************/
+
+#ifdef ENABLE_VERIFIER
+bool patcher_resolve_class(u1 *sp)
+{
+       unresolved_class *uc;
+       classinfo        *c;
+
+       /* get stuff from the stack */
+
+       uc = (unresolved_class *) *((ptrint *) (sp + 2 * 4));
+
+       /* resolve the class */
+       assert(0);
+
+       if (!resolve_class(uc, resolveEager, false, &c))
+               return false;
+
+       return true;
+}
+#endif /* ENABLE_VERIFIER */
+
+/* patcher_resolve_classref_to_classinfo ***************************************
+  ACONST:
+       0x4028f2ca:   2479 0000 0000    moveal 0x00000000,%a2
+*******************************************************************************/
+bool patcher_resolve_classref_to_classinfo(u1 *sp)
+{
+       constant_classref *cr;
+       s4                 disp;
+       u1                *pv;
+       classinfo         *c;
+
+       /* get stuff from the stack */
+
+       cr   = (constant_classref *) *((ptrint *) (sp + 1 * 4));
+       disp =                       *((s4 *)     (sp + 6 * 4));
+
+       /* get the classinfo */
+
+       if (!(c = resolve_classref_eager(cr)))
+               return false;
+
+       /* patch the classinfo pointer */
+
+       if (opt_shownops) disp += PATCHER_CALL_SIZE;
+
+       *((ptrint *) (disp+2)) = (ptrint) c;
+
+       /* synchronize inst cache */
+
+       md_icacheflush(disp+2, SIZEOF_VOID_P);
+
+       return true;
+}
+
+/* patcher_get_putstatic *******************************************************
+
+   Machine code:
+
+*******************************************************************************/
+
+bool patcher_get_putstatic(u1 *sp)
+{
+       u1               *ra;
+       u4                mcode;
+       unresolved_field *uf;
+       s4                disp;
+       u1               *pv;
+       fieldinfo        *fi;
+
+       /* get stuff from the stack */
+
+       ra    = (u1 *)                *((ptrint *) (sp + 5 * 4));
+       mcode =                       *((u4 *)     (sp + 3 * 4));
+       uf    = (unresolved_field *)  *((ptrint *) (sp + 2 * 4));
+       disp  =                       *((s4 *)     (sp + 1 * 4));
+       pv    = (u1 *)                *((ptrint *) (sp + 0 * 4));
+
+       /* get the fieldinfo */
+
+       assert(0);
+
+       if (!(fi = resolve_field_eager(uf)))
+               return false;
+
+       /* check if the field's class is initialized */
+
+       if (!(fi->class->state & CLASS_INITIALIZED))
+               if (!initialize_class(fi->class))
+                       return false;
+
+       /* patch the field value's address */
+
+       *((ptrint *) (pv + disp)) = (ptrint) &(fi->value);
+
+       /* synchronize data cache */
+
+       md_dcacheflush(pv + disp, SIZEOF_VOID_P);
+
+       return true;
+}
+
+/* patcher_get_putfield ********************************************************
+
+   Machine code:
+
+   <patched call position>
+
+*******************************************************************************/
+
+bool patcher_get_putfield(u1 *sp)
+{
+       u1               *ra;
+       unresolved_field *uf;
+       fieldinfo        *fi;
+       s2                disp;
+
+       ra = (u1 *)               *((ptrint *) (sp + 6 * 4));
+       uf = (unresolved_field *) *((ptrint *) (sp + 1 * 4));
+
+       /* get the fieldinfo */
+
+       assert(0);
+
+       if (!(fi = resolve_field_eager(uf)))
+               return false;
+
+       /* if we show NOPs, we have to skip them */
+
+       if (opt_shownops) {
+               /* patch the field's offset */
+
+               if (IS_LNG_TYPE(fi->type)) {
+                       /* If the field has type long, we have to patch two
+                          instructions.  But we have to check which instruction
+                          is first.  We do that with the offset of the first
+                          instruction. */
+
+                       disp = *((u4 *) (ra + 1 * 4));
+
+                       if (disp == 4) {
+                               *((u4 *) (ra + 1 * 4)) |= (s2) ((fi->offset + 4) & 0x0000ffff);
+                               *((u4 *) (ra + 2 * 4)) |= (s2) ((fi->offset + 0) & 0x0000ffff);
+                       }
+                       else {
+                               *((u4 *) (ra + 1 * 4)) |= (s2) ((fi->offset + 0) & 0x0000ffff);
+                               *((u4 *) (ra + 2 * 4)) |= (s2) ((fi->offset + 4) & 0x0000ffff);
+                       }
+               }
+               else
+                       *((u4 *) (ra + 1 * 4)) |= (s2) (fi->offset & 0x0000ffff);
+       }
+       else {
+               if (IS_LNG_TYPE(fi->type)) {
+
+                       disp = *((u4 *) (sp + 3 * 4));
+
+                       /* We patch the first instruction in the patcher stub
+                          stack and the second in the code.  The first
+                          instruction is patched back later in
+                          patcher_wrapper. */
+
+                       if (disp == 4) {
+                               *((u4 *) (sp + 3 * 4)) |= (s2) ((fi->offset + 4) & 0x0000ffff);
+                               *((u4 *) (ra + 1 * 4)) |= (s2) ((fi->offset + 0) & 0x0000ffff);
+                       }
+                       else {
+                               *((u4 *) (sp + 3 * 4)) |= (s2) ((fi->offset + 0) & 0x0000ffff);
+                               *((u4 *) (ra + 1 * 4)) |= (s2) ((fi->offset + 4) & 0x0000ffff);
+                       }
+               }
+               else
+                       *((u4 *) (sp + 3 * 4)) |= (s2) (fi->offset & 0x0000ffff);
+       }
+
+       /* synchronize instruction cache */
+
+       md_icacheflush(ra + 1 * 4, 2 * 4);
+
+       return true;
+}
+/* patcher_resolve_classref_to_flags *******************************************
+
+   CHECKCAST/INSTANCEOF:
+
+
+CHECKCAST:
+0x4029b056:   61ff 0000 013e    bsrl 0x4029b196
+0x4029b05c:   263c 0000 0000    movel #0,%d3           <-- patch this #0
+0x4029b062:   0283 0000 0200    andil #512,%d3
+
+INSTANCEOF:
+0x402a4aa8:   61ff 0000 05c4    bsrl 0x402a506e
+0x402a4aae:   283c 0000 0000    movel #0,%d4           <-- same here
+0x402a4ab4:   0284 0000 0200    andil #512,%d4
+
+
+*******************************************************************************/
+
+bool patcher_resolve_classref_to_flags(u1 *sp)
+{
+       constant_classref *cr;
+       s4                 disp;
+       classinfo         *c;
+
+       /* get stuff from the stack */
+       cr   = (constant_classref *) *((ptrint *) (sp + 1 * 4));
+       disp =                       *((s4 *)     (sp + 6 * 4));
+
+       /* get the fieldinfo */
+       if (!(c = resolve_classref_eager(cr)))
+               return false;
+
+       /* patch class flags */
+       if (opt_shownops) disp += PATCHER_CALL_SIZE;
+       assert( (*((u2*)(disp)) == 0x263c) || (*((u2*)(disp)) == 0x283c) );
+       *((s4 *) (disp + 2)) = (s4) c->flags;
+
+       /* synchronize insn cache */
+       md_icacheflush(disp + 2, SIZEOF_VOID_P);
+
+       return true;
+}
+
+/* patcher_resolve_classref_to_vftbl *******************************************
+
+   CHECKCAST (class):
+0x4029b094:   61ff 0000 00b4    bsrl 0x4029b14a
+0x4029b09a:   287c 0000 0000    moveal #0,%a4          <-- patch this #0
+0x4029b0a0:   2668 0000         moveal %a0@(0),%a3
+
+   INSTANCEOF (class):
+0x402a9300:   61ff 0000 0574    bsrl 0x402a9876
+0x402a9306:   267c 0000 0000    moveal #0,%a3
+0x402a930c:   246a 0000         moveal %a2@(0),%a2
+
+
+*******************************************************************************/
+
+bool patcher_resolve_classref_to_vftbl(u1 *sp)
+{
+       constant_classref *cr;
+       s4                 disp;
+       classinfo         *c;
+
+       /* get stuff from the stack */
+       cr   = (constant_classref *) *((ptrint *) (sp + 1 * 4));
+       disp =                       *((s4 *)     (sp + 6 * 4));
+
+       /* get the fieldinfo */
+       if (!(c = resolve_classref_eager(cr)))
+               return false;
+
+       /* patch super class' vftbl */
+       if (opt_shownops) disp += PATCHER_CALL_SIZE;
+       assert( (*((u2*)disp) == 0x287c) || (*((u2*)disp)== 0x267c) );
+
+       *((s4 *) (disp+2)) = (s4) c->vftbl;
+
+       /* synchronize insin cache */
+       md_icacheflush(disp+2, SIZEOF_VOID_P);
+
+       return true;
+}
+
+/* patcher_instanceof_interface ************************************************
+
+   Machine code:
+
+0x402a92da:   61ff 0000 05c0    bsrl 0x402a989c
+0x402a92e0:   246a 0000         moveal %a2@(0),%a2
+0x402a92e4:   282a 0010         movel %a2@(16),%d4
+0x402a92e8:   d8bc 0000 0000    addl #0,%d4            <-- this const
+0x402a92ee:   4a84              tstl %d4
+0x402a92f0:   6e0a              bles 0x402a92fc
+0x402a92f2:   246a 0000         moveal %a2@(0),%a2     <-- this offset
+
+*******************************************************************************/
+
+bool patcher_instanceof_interface(u1 *sp)
+{
+       u1                *ra;
+       constant_classref *cr;
+       classinfo         *c;
+       s4                 disp;
+
+       /* get stuff from the stack */
+
+       ra = (u1 *)                *((ptrint *) (sp + 6 * 4));
+       cr = (constant_classref *) *((ptrint *) (sp + 1 * 4));
+
+       /* get the fieldinfo */
+       if (!(c = resolve_classref_eager(cr)))
+               return false;
+
+       /* if we show NOPs, we have to skip them */
+       if (opt_shownops) ra += PATCHER_CALL_SIZE;
+               
+       /* patch super class index */
+       disp = -(c->index);
+       assert( *((u2*)(ra + 8)) == 0xd8bc );
+       *((s4 *) (ra + 10 )) = disp;
+
+       disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
+
+       assert( (s2)disp  == disp);
+       assert ( *((s2*)(ra+18)) == 0x246a );
+
+       *((s2 *) (ra + 20)) = disp;
+
+       /* synchronize instruction cache */
+       md_icacheflush(ra + 10, 12);
+
+       return true;
+}
+
+/* patcher_checkcast_interface *************************************************
+
+0x402a9400:   61ff 0000 03b6    bsrl 0x402a97b8
+0x402a9406:   266a 0000         moveal %a2@(0),%a3
+0x402a940a:   282b 0010         movel %a3@(16),%d4
+0x402a940e:   d8bc 0000 0000    addl #0,%d4            <-- this 0
+0x402a9414:   4a84              tstl %d4
+0x402a9416:   6e02              bgts 0x402a941a
+             1234              tstb %d0
+0x402a9418:   4afc              illegal
+0x402a941a:   286b 0000         moveal %a3@(0),%a4     <-- and this 0 offset
+
+*******************************************************************************/
+
+bool patcher_checkcast_interface(u1 *sp)
+{
+       u1                *ra;
+       constant_classref *cr;
+       classinfo         *c;
+       s4                 disp;
+
+       /* get stuff from the stack */
+       ra = (u1 *)                *((ptrint *) (sp + 6 * 4));
+       cr = (constant_classref *) *((ptrint *) (sp + 1 * 4));
+
+       /* get the fieldinfo */
+       if (!(c = resolve_classref_eager(cr)))
+               return false;
+
+       /* if we show NOPs, we have to skip them */
+       if (opt_shownops) ra += PATCHER_CALL_SIZE;
+
+       /* patch super class index */
+       disp = -(c->index);
+       assert ( *((u2 *)(ra + 8)) == 0xd8bc );
+       *((s4 *) (ra + 10)) = disp;
+
+       disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
+       assert( *((u2 *)(ra + 22)) == 0x286b );
+       assert( (s2)disp == disp);
+       *((s2 *) (ra + 24)) = disp;
+       
+       /* synchronize instruction cache */
+       md_icacheflush(ra + 10, 16);
+
+       return true;
+}
+
+/* patcher_resolve_native_function *********************************************
+
+   XXX
+
+*******************************************************************************/
+
+#if !defined(WITH_STATIC_CLASSPATH)
+bool patcher_resolve_native_function(u1 *sp)
+{
+       methodinfo  *m;
+       s4           disp;
+       functionptr  f;
+
+       /* get stuff from the stack */
+       m    = (methodinfo *) *((ptrint *) (sp + 1 * 4));
+       disp =                *((s4 *)     (sp + 6 * 4));
+
+       /* resolve native function */
+       if (!(f = native_resolve_function(m)))
+               return false;
+
+       /* patch native function pointer */
+       if (opt_shownops) disp += PATCHER_CALL_SIZE;
+       *((ptrint *) (disp + 2)) = (ptrint) f;
+
+       /* synchronize data cache */
+       md_icacheflush(disp + 2, SIZEOF_VOID_P);
+
+       return true;
+}
+#endif /* !defined(WITH_STATIC_CLASSPATH) */
+
+
+/* patcher_invokeinterface *****************************************************
+
+   Machine code:
+
+
+*******************************************************************************/
+
+bool patcher_invokeinterface(u1 *sp)
+{
+       u1                *ra;
+       unresolved_method *um;
+       methodinfo        *m;
+       s4                 disp;
+
+       /* get stuff from the stack */
+       ra = (u1 *)                *((ptrint *) (sp + 6 * 4));
+       um = (unresolved_method *) *((ptrint *) (sp + 1 * 4));
+
+       assert(0);
+
+       /* get the fieldinfo */
+       if (!(m = resolve_method_eager(um)))
+               return false;
+
+       /* if we show NOPs, we have to skip them */
+       if (opt_shownops) ra = ra + PATCHER_CALL_SIZE;
+
+       /* patch interfacetable index (first #0) */
+       disp = OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr*) * m->class->index;
+
+       /* XXX TWISTI: check displacement */
+       *((s4 *) (ra + 1 * 4)) |= (disp & 0x0000ffff);
+
+       /* patch method offset (second #0) */
+       disp = sizeof(methodptr) * (m - m->class->methods);
+
+       /* XXX TWISTI: check displacement */
+       *((s4 *) (ra + 2 * 4)) |= (disp & 0x0000ffff);
+
+       /* synchronize instruction cache */
+       md_icacheflush(ra + 1 * 4, 2 * 4);
+
+       return true;
+}
+
diff --git a/src/vm/jit/m68k/uclinux/Makefile.am b/src/vm/jit/m68k/uclinux/Makefile.am
deleted file mode 100644 (file)
index 5207e3d..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-## src/vm/jit/powerpc64/linux/Makefile.am
-##
-## Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
-## C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
-## E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
-## J. Wenninger, Institut f. Computersprachen - TU Wien
-##
-## This file is part of CACAO.
-##
-## This program is free software; you can redistribute it and/or
-## modify it under the terms of the GNU General Public License as
-## published by the Free Software Foundation; either version 2, or (at
-## your option) any later version.
-##
-## This program is distributed in the hope that it will be useful, but
-## WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-## General Public License for more details.
-##
-## 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., 51 Franklin Street, Fifth Floor, Boston, MA
-## 02110-1301, USA.
-##
-## Contact: cacao@cacaojvm.org
-##
-## Authors: Christian Thalinger
-##
-## Changes:
-##
-## $Id: Makefile.am 5081 2006-07-06 13:59:01Z tbfg $
-
-## Process this file with automake to produce Makefile.in
-
-AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/src/vm/jit/$(ARCH_DIR)
-
-LIBS =
-
-noinst_HEADERS = \
-       md-asm.h
-
-noinst_LTLIBRARIES = libmd.la
-
-libmd_la_SOURCES = \
-       md-abi.c \
-       md-abi.h \
-       md-os.c
-
-
-## Local variables:
-## mode: Makefile
-## indent-tabs-mode: t
-## c-basic-offset: 4
-## tab-width: 8
-## compile-command: "automake --add-missing"
-## End:
diff --git a/src/vm/jit/m68k/uclinux/md-abi.c b/src/vm/jit/m68k/uclinux/md-abi.c
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/src/vm/jit/m68k/uclinux/md-abi.h b/src/vm/jit/m68k/uclinux/md-abi.h
deleted file mode 100644 (file)
index aefc1a8..0000000
+++ /dev/null
@@ -1,109 +0,0 @@
-/* src/vm/jit/m68k/linux/md-abi.h - defines for PowerPC64 Linux ABI
-
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
-   C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
-   E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
-   J. Wenninger, Institut f. Computersprachen - TU Wien
-
-   This file is part of CACAO.
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2, or (at
-   your option) any later version.
-
-   This program is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-   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., 51 Franklin Street, Fifth Floor, Boston, MA
-   02110-1301, USA.
-
-   Contact: cacao@cacaojvm.org
-
-   Authors: Roland Lezuo
-
-   Changes:
-
-   $Id: md-abi.h 5940 2006-11-09 09:59:28Z tbfg $
-
-*/
-
-
-#ifndef _MD_ABI_H
-#define _MD_ABI_H
-
-/* preallocated registers *****************************************************/
-
-/* integer registers */
-
-#define REG_TOC                 2   /* TOC (see function descriptors ELF ABI)        */
-#define REG_RESULT       3   /* to deliver method results                     */
-
-#define REG_PV          14   /* procedure vector, must be provided by caller  */
-#define REG_METHODPTR   12   /* pointer to the place from where the procedure */
-                             /* vector has been fetched                       */
-#define REG_ITMP1       11   /* temporary register                            */
-#define REG_ITMP2       12   /* temporary register and method pointer         */
-#define REG_ITMP3       16   /* temporary register                            */
-
-#define REG_ITMP1_XPTR  11   /* exception pointer = temporary register 1      */
-#define REG_ITMP2_XPC   12   /* exception pc = temporary register 2           */
-
-#define REG_SP           1   /* stack pointer                                 */
-#define REG_ZERO         0   /* almost always zero: only in address calc.     */
-
-/* floating point registers */
-
-#define REG_FRESULT      1   /* to deliver floating point method results      */
-#define REG_FTMP1       16   /* temporary floating point register             */
-#define REG_FTMP2       17   /* temporary floating point register             */
-#define REG_FTMP3        0   /* temporary floating point register             */
-
-#define REG_IFTMP       16   /* temporary integer and floating point register */
-
-
-#define INT_REG_CNT     32   /* number of integer registers                   */
-#define INT_SAV_CNT      9   /* number of int callee saved registers          */
-#define INT_ARG_CNT      8   /* number of int argument registers              */
-#define INT_TMP_CNT      7   /* number of integer temporary registers         */
-#define INT_RES_CNT      8   /* number of integer reserved registers          */
-
-#define FLT_REG_CNT     32   /* number of float registers                     */
-#define FLT_SAV_CNT     16   /* number of float callee saved registers        */
-#define FLT_ARG_CNT     13   /* number of float argument registers            */
-#define FLT_TMP_CNT      0   /* number of float temporary registers           */
-#define FLT_RES_CNT      3   /* number of float reserved registers            */
-
-#define TRACE_ARGS_NUM   8
-
-
-/* ABI defines ****************************************************************/
-
-#define LA_SIZE         48   /* linkage area size                             */
-#define LA_SIZE_ALIGNED 16   /* linkage area size aligned to 16-byte          */
-#define LA_SIZE_IN_POINTERS    (LA_SIZE / SIZEOF_VOID_P)
-#define LA_LR_OFFSET    16   /* link register offset in linkage area          */
-#define PA_SIZE                (PA_SIZE_IN_POINTERS*8) 
-#define PA_SIZE_IN_POINTERS    8 /* linux/ppc64 has a minimun parameter save area size, XXX:darwin? */
-
-/* #define ALIGN_FRAME_SIZE(sp)       (sp) */
-
-#endif /* _MD_ABI_H */
-
-
-/*
- * 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
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- */
diff --git a/src/vm/jit/m68k/uclinux/md-asm.h b/src/vm/jit/m68k/uclinux/md-asm.h
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/src/vm/jit/m68k/uclinux/md-os.c b/src/vm/jit/m68k/uclinux/md-os.c
deleted file mode 100644 (file)
index e69de29..0000000
index 40c95d529bdf7aa24d2ba1702cbf2b5fa8a1ec56..5f22fc55e747bda8a81c5e877ce7be95193d1dd3 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: arch.h 7241 2007-01-27 15:52:01Z twisti $
+   $Id: arch.h 7363 2007-02-15 14:57:04Z twisti $
 
 */
 
 #endif /* SIZEOF_VOID_P == 8 */
 
 
+/* branches *******************************************************************/
+
+#define SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER       0
+#define SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER     1
+#define SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS    1
+
+
 /* exceptions *****************************************************************/
 
 #define SUPPORT_HARDWARE_DIVIDE_BY_ZERO  0
index 80d94d8f28195c3a6e8338b2b284b319d14719cf..5689543b10ecc21e386c30ff3c5533df6bed626e 100644 (file)
@@ -29,7 +29,7 @@
    Changes: Christian Thalinger
             Edwin Steiner
 
-   $Id: asmpart.S 7224 2007-01-18 11:43:03Z twisti $
+   $Id: asmpart.S 7455 2007-03-05 15:46:53Z tbfg $
 
 */
 
@@ -56,6 +56,7 @@
        .globl asm_vm_call_method_float
        .globl asm_vm_call_method_double
        .globl asm_vm_call_method_exception_handler
+       .globl asm_vm_call_method_end
 
        .globl asm_call_jit_compiler
 
@@ -344,6 +345,7 @@ asm_vm_call_method_exception_handler:
 #if SIZEOF_VOID_P == 4
        aaddiu  sp,sp,4*4
 #endif
+asm_vm_call_method_end:
        b       calljava_return2
 
        .end    asm_vm_call_method
index c2817a0b1ea0b26d8383e116461a330ca75d406d..15dd71e2678a34897ff32ebe47dbea188e8ff0d7 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: codegen.c 7252 2007-01-29 21:09:01Z twisti $
+   $Id: codegen.c 7570 2007-03-24 22:20:09Z twisti $
 
 */
 
 #include "vmcore/options.h"
 
 
-/* codegen *********************************************************************
+/* codegen_emit ****************************************************************
 
    Generates machine code.
 
 *******************************************************************************/
 
-bool codegen(jitdata *jd)
+bool codegen_emit(jitdata *jd)
 {
        methodinfo         *m;
        codeinfo           *code;
@@ -353,24 +353,19 @@ bool codegen(jitdata *jd)
                if (m->flags & ACC_STATIC) {
                        disp = dseg_add_address(cd, &m->class->object.header);
                        M_ALD(REG_A0, REG_PV, disp);
+                       disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
+                       M_ALD(REG_ITMP3, REG_PV, disp);
                }
                else {
 /*                     emit_nullpointer_check(cd, iptr, REG_A0); */
-                       M_BNEZ(REG_A0, 6);
-                       M_NOP;
-
-                       M_LUI(REG_ITMP3, 0);
-                       M_OR_IMM(REG_ITMP3, 0, REG_ITMP3);
-                       codegen_add_nullpointerexception_ref(cd);
-                       M_AADD(REG_PV, REG_ITMP3, REG_ITMP3);
-                       M_JMP(REG_ITMP3);
-                       M_NOP;
+                       M_BNEZ(REG_A0, 2);
+                       disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
+                       M_ALD(REG_ITMP3, REG_PV, disp);                   /* branch delay */
+                       M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_NULLPOINTER);
                }
 
-               disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
-               M_ALD(REG_ITMP3, REG_PV, disp);
                M_JSR(REG_RA, REG_ITMP3);
-               M_AST(REG_A0, REG_SP, s1 * 8);         /* branch delay */
+               M_AST(REG_A0, REG_SP, s1 * 8);                        /* branch delay */
 
 # if !defined(NDEBUG)
                if (opt_verbosecall) {
@@ -1760,7 +1755,7 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                       emit_nullpointer_check(cd, iptr, s1);
+                       /* implicit null-pointer check */
                        M_ILD(d, s1, OFFSET(java_arrayheader, size));
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1770,8 +1765,9 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_AADD(s2, s1, REG_ITMP3);
+                       /* implicit null-pointer check */
                        M_BLDS(d, REG_ITMP3, OFFSET(java_bytearray, data[0]));
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1781,9 +1777,10 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_AADD(s2, s1, REG_ITMP3);
                        M_AADD(s2, REG_ITMP3, REG_ITMP3);
+                       /* implicit null-pointer check */
                        M_SLDU(d, REG_ITMP3, OFFSET(java_chararray, data[0]));
                        emit_store_dst(jd, iptr, d);
                        break;                  
@@ -1793,9 +1790,10 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_AADD(s2, s1, REG_ITMP3);
                        M_AADD(s2, REG_ITMP3, REG_ITMP3);
+                       /* implicit null-pointer check */
                        M_SLDS(d, REG_ITMP3, OFFSET(java_shortarray, data[0]));
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1805,10 +1803,11 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ASLL_IMM(s2, 2, REG_ITMP3);
                        M_AADD(REG_ITMP3, s1, REG_ITMP3);
-                       M_ILD(d, REG_ITMP3, OFFSET(java_intarray, data[0]));
+                       /* implicit null-pointer check */
+                       M_ILD_INTERN(d, REG_ITMP3, OFFSET(java_intarray, data[0]));
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -1821,10 +1820,11 @@ bool codegen(jitdata *jd)
 #else
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
 #endif
-                       emit_array_checks(cd, iptr, s1, s2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ASLL_IMM(s2, 3, REG_ITMP3);
                        M_AADD(REG_ITMP3, s1, REG_ITMP3);
-                       M_LLD(d, REG_ITMP3, OFFSET(java_longarray, data[0]));
+                       /* implicit null-pointer check */
+                       M_LLD_INTERN(d, REG_ITMP3, OFFSET(java_longarray, data[0]));
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -1833,10 +1833,11 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ASLL_IMM(s2, 2, REG_ITMP3);
                        M_AADD(REG_ITMP3, s1, REG_ITMP3);
-                       M_FLD(d, REG_ITMP3, OFFSET(java_floatarray, data[0]));
+                       /* implicit null-pointer check */
+                       M_FLD_INTERN(d, REG_ITMP3, OFFSET(java_floatarray, data[0]));
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -1845,10 +1846,11 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ASLL_IMM(s2, 3, REG_ITMP3);
                        M_AADD(REG_ITMP3, s1, REG_ITMP3);
-                       M_DLD(d, REG_ITMP3, OFFSET(java_doublearray, data[0]));
+                       /* implicit null-pointer check */
+                       M_DLD_INTERN(d, REG_ITMP3, OFFSET(java_doublearray, data[0]));
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -1857,10 +1859,11 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP3);
                        M_AADD(REG_ITMP3, s1, REG_ITMP3);
-                       M_ALD(d, REG_ITMP3, OFFSET(java_objectarray, data[0]));
+                       /* implicit null-pointer check */
+                       M_ALD_INTERN(d, REG_ITMP3, OFFSET(java_objectarray, data[0]));
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -1869,9 +1872,10 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_AADD(s2, s1, REG_ITMP1);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
+                       /* implicit null-pointer check */
                        M_BST(s3, REG_ITMP1, OFFSET(java_bytearray, data[0]));
                        break;
 
@@ -1880,10 +1884,11 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_AADD(s2, s1, REG_ITMP1);
                        M_AADD(s2, REG_ITMP1, REG_ITMP1);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
+                       /* implicit null-pointer check */
                        M_SST(s3, REG_ITMP1, OFFSET(java_chararray, data[0]));
                        break;
 
@@ -1891,10 +1896,11 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ASLL_IMM(s2, 2, REG_ITMP2);
                        M_AADD(REG_ITMP2, s1, REG_ITMP1);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
+                       /* implicit null-pointer check */
                        M_IST_INTERN(s3, REG_ITMP1, OFFSET(java_intarray, data[0]));
                        break;
 
@@ -1902,7 +1908,7 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ASLL_IMM(s2, 3, REG_ITMP2);
                        M_AADD(REG_ITMP2, s1, REG_ITMP1);
 #if SIZEOF_VOID_P == 8
@@ -1910,6 +1916,7 @@ bool codegen(jitdata *jd)
 #else
                        s3 = emit_load_s3(jd, iptr, REG_ITMP23_PACKED);
 #endif
+                       /* implicit null-pointer check */
                        M_LST_INTERN(s3, REG_ITMP1, OFFSET(java_longarray, data[0]));
                        break;
 
@@ -1917,10 +1924,11 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ASLL_IMM(s2, 2, REG_ITMP2);
                        M_AADD(REG_ITMP2, s1, REG_ITMP1);
                        s3 = emit_load_s3(jd, iptr, REG_FTMP1);
+                       /* implicit null-pointer check */
                        M_FST_INTERN(s3, REG_ITMP1, OFFSET(java_floatarray, data[0]));
                        break;
 
@@ -1928,10 +1936,11 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ASLL_IMM(s2, 3, REG_ITMP2);
                        M_AADD(REG_ITMP2, s1, REG_ITMP1);
                        s3 = emit_load_s3(jd, iptr, REG_FTMP1);
+                       /* implicit null-pointer check */
                        M_DST_INTERN(s3, REG_ITMP1, OFFSET(java_doublearray, data[0]));
                        break;
 
@@ -1940,26 +1949,23 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
 
-                       M_MOV(s1, REG_A0);
-                       M_MOV(s3, REG_A1);
+                       M_INTMOVE(s1, REG_A0);
+                       M_INTMOVE(s3, REG_A1);
                        disp = dseg_add_functionptr(cd, BUILTIN_canstore);
                        M_ALD(REG_ITMP3, REG_PV, disp);
                        M_JSR(REG_RA, REG_ITMP3);
                        M_NOP;
-
-/*                     M_BEQZ(REG_RESULT, 0); */
-/*                     codegen_add_arraystoreexception_ref(cd); */
-/*                     M_NOP; */
-                       emit_arraystore_check(cd, iptr, REG_RESULT);
+                       emit_exception_check(cd, iptr);
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
                        M_AADD(REG_ITMP2, s1, REG_ITMP1);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
+                       /* implicit null-pointer check */
                        M_AST_INTERN(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
                        break;
 
@@ -1968,8 +1974,9 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_AADD(s2, s1, REG_ITMP1);
+                       /* implicit null-pointer check */
                        M_BST(REG_ZERO, REG_ITMP1, OFFSET(java_bytearray, data[0]));
                        break;
 
@@ -1978,9 +1985,10 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_AADD(s2, s1, REG_ITMP1);
                        M_AADD(s2, REG_ITMP1, REG_ITMP1);
+                       /* implicit null-pointer check */
                        M_SST(REG_ZERO, REG_ITMP1, OFFSET(java_chararray, data[0]));
                        break;
 
@@ -1988,9 +1996,10 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ASLL_IMM(s2, 2, REG_ITMP2);
                        M_AADD(REG_ITMP2, s1, REG_ITMP1);
+                       /* implicit null-pointer check */
                        M_IST_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_intarray, data[0]));
                        break;
 
@@ -1998,9 +2007,10 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ASLL_IMM(s2, 3, REG_ITMP2);
                        M_AADD(REG_ITMP2, s1, REG_ITMP1);
+                       /* implicit null-pointer check */
 #if SIZEOF_VOID_P == 8
                        M_LST_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_longarray, data[0]));
 #else
@@ -2012,9 +2022,10 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
                        M_AADD(REG_ITMP2, s1, REG_ITMP1);
+                       /* implicit null-pointer check */
                        M_AST_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_objectarray, data[0]));
                        break;
 
@@ -2326,143 +2337,120 @@ bool codegen(jitdata *jd)
                case ICMD_GOTO:         /* ... ==> ...                                */
                case ICMD_RET:          /* ... ==> ...                                */
 
-                       M_BR(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_br(cd, iptr->dst.block);
                        ALIGNCODENOP;
                        break;
 
                case ICMD_JSR:          /* ... ==> ...                                */
 
-                       M_BR(0);
-                       codegen_add_branch_ref(cd, iptr->sx.s23.s3.jsrtarget.block);
-                       M_NOP;
+                       emit_br(cd, iptr->sx.s23.s3.jsrtarget.block);
                        ALIGNCODENOP;
                        break;
                        
                case ICMD_IFNULL:       /* ..., value ==> ...                         */
+               case ICMD_IFNONNULL:
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       M_BEQZ(s1, 0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
-                       break;
-
-               case ICMD_IFNONNULL:    /* ..., value ==> ...                         */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       M_BNEZ(s1, 0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_bccz(cd, iptr->dst.block, iptr->opc - ICMD_IFNULL, s1, BRANCH_OPT_NONE);
                        break;
 
                case ICMD_IFEQ:         /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.i == 0) {
-                               M_BEQZ(s1, 0);
-                       else {
+                       if (iptr->sx.val.i == 0)
+                               emit_beqz(cd, iptr->dst.block, s1);
+                       else {
                                ICONST(REG_ITMP2, iptr->sx.val.i);
-                               M_BEQ(s1, REG_ITMP2, 0);
+                               emit_beq(cd, iptr->dst.block, s1, REG_ITMP2);
                        }
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
                        break;
 
                case ICMD_IFLT:         /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.i == 0) {
-                               M_BLTZ(s1, 0);
-                       else {
-                               if ((iptr->sx.val.i >= -32768) && (iptr->sx.val.i <= 32767)) {
+                       if (iptr->sx.val.i == 0)
+                               emit_bltz(cd, iptr->dst.block, s1);
+                       else {
+                               if ((iptr->sx.val.i >= -32768) && (iptr->sx.val.i <= 32767))
                                        M_CMPLT_IMM(s1, iptr->sx.val.i, REG_ITMP1);
-                               else {
+                               else {
                                        ICONST(REG_ITMP2, iptr->sx.val.i);
                                        M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
                                }
-                               M_BNEZ(REG_ITMP1, 0);
+                               emit_bnez(cd, iptr->dst.block, REG_ITMP1);
                        }
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
                        break;
 
                case ICMD_IFLE:         /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.i == 0) {
-                               M_BLEZ(s1, 0);
-                       else {
+                       if (iptr->sx.val.i == 0)
+                               emit_blez(cd, iptr->dst.block, s1);
+                       else {
                                if ((iptr->sx.val.i >= -32769) && (iptr->sx.val.i <= 32766)) {
                                        M_CMPLT_IMM(s1, iptr->sx.val.i + 1, REG_ITMP1);
-                                       M_BNEZ(REG_ITMP1, 0);
-                               } else {
+                                       emit_bnez(cd, iptr->dst.block, REG_ITMP1);
+                               }
+                               else {
                                        ICONST(REG_ITMP2, iptr->sx.val.i);
                                        M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
-                                       M_BEQZ(REG_ITMP1, 0);
+                                       emit_beqz(cd, iptr->dst.block, REG_ITMP1);
                                }
                        }
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
                        break;
 
                case ICMD_IFNE:         /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.i == 0) {
-                               M_BNEZ(s1, 0);
-                       else {
+                       if (iptr->sx.val.i == 0)
+                               emit_bnez(cd, iptr->dst.block, s1);
+                       else {
                                ICONST(REG_ITMP2, iptr->sx.val.i);
-                               M_BNE(s1, REG_ITMP2, 0);
+                               emit_bne(cd, iptr->dst.block, s1, REG_ITMP2);
                        }
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
                        break;
 
                case ICMD_IFGT:         /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.i == 0) {
-                               M_BGTZ(s1, 0);
-                       else {
+                       if (iptr->sx.val.i == 0)
+                               emit_bgtz(cd, iptr->dst.block, s1);
+                       else {
                                if ((iptr->sx.val.i >= -32769) && (iptr->sx.val.i <= 32766)) {
                                        M_CMPLT_IMM(s1, iptr->sx.val.i + 1, REG_ITMP1);
-                                       M_BEQZ(REG_ITMP1, 0);
-                               } else {
+                                       emit_beqz(cd, iptr->dst.block, REG_ITMP1);
+                               }
+                               else {
                                        ICONST(REG_ITMP2, iptr->sx.val.i);
                                        M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
-                                       M_BNEZ(REG_ITMP1, 0);
+                                       emit_bnez(cd, iptr->dst.block, REG_ITMP1);
                                }
                        }
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
                        break;
 
                case ICMD_IFGE:         /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.i == 0) {
-                               M_BGEZ(s1, 0);
-                       else {
-                               if ((iptr->sx.val.i >= -32768) && (iptr->sx.val.i <= 32767)) {
+                       if (iptr->sx.val.i == 0)
+                               emit_bgez(cd, iptr->dst.block, s1);
+                       else {
+                               if ((iptr->sx.val.i >= -32768) && (iptr->sx.val.i <= 32767))
                                        M_CMPLT_IMM(s1, iptr->sx.val.i, REG_ITMP1);
-                               else {
+                               else {
                                        ICONST(REG_ITMP2, iptr->sx.val.i);
                                        M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
                                }
-                               M_BEQZ(REG_ITMP1, 0);
+                               emit_beqz(cd, iptr->dst.block, REG_ITMP1);
                        }
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
                        break;
 
                case ICMD_IF_LEQ:       /* ..., value ==> ...                         */
 
 #if SIZEOF_VOID_P == 8
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.l == 0) {
+                       if (iptr->sx.val.l == 0)
                                M_BEQZ(s1, 0);
-                       else {
+                       else {
                                LCONST(REG_ITMP2, iptr->sx.val.l);
                                M_BEQ(s1, REG_ITMP2, 0);
                        }
@@ -2470,7 +2458,7 @@ bool codegen(jitdata *jd)
                        if (iptr->sx.val.l == 0) {
                                s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED);
                                M_OR(GET_LOW_REG(s1), GET_HIGH_REG(s1), REG_ITMP3);
-                               M_BEQZ(REG_ITMP3, 0);
+                               emit_beqz(cd, iptr->dst.block, REG_ITMP3);
                        }
                        else {
                                s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
@@ -2480,11 +2468,9 @@ bool codegen(jitdata *jd)
                                ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
                                M_XOR(s1, REG_ITMP3, REG_ITMP3);
                                M_OR(REG_ITMP2, REG_ITMP3, REG_ITMP3);
-                               M_BEQZ(REG_ITMP3, 0);
+                               emit_beqz(cd, iptr->dst.block, REG_ITMP3);
                        }
 #endif
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
                        break;
 
                case ICMD_IF_LLT:       /* ..., value ==> ...                         */
@@ -2506,25 +2492,21 @@ bool codegen(jitdata *jd)
                        if (iptr->sx.val.l == 0) {
                                /* if high word is less than zero, the whole long is too */
                                s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
-                               M_BLTZ(s1, 0);
+                               emit_bltz(cd, iptr->dst.block, s1);
                        }
                        else {
                                s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
                                ICONST(REG_ITMP2, iptr->sx.val.l >> 32);
                                M_CMPLT(s1, REG_ITMP2, REG_ITMP3);
-                               M_BNEZ(REG_ITMP3, 0);
-                               codegen_add_branch_ref(cd, iptr->dst.block);
-                               M_NOP;
+                               emit_bnez(cd, iptr->dst.block, REG_ITMP3);
                                s2 = emit_load_s1_low(jd, iptr, REG_ITMP3);
-                               M_BNE(s1, REG_ITMP2, 5);
+                               M_BNE(s1, REG_ITMP2, 5); /* XXX */
                                M_NOP;
                                ICONST(REG_ITMP2, iptr->sx.val.l & 0xffffffff);
                                M_CMPULT(s2, REG_ITMP2, REG_ITMP3);
-                               M_BNEZ(REG_ITMP3, 0);
+                               emit_bnez(cd, iptr->dst.block, REG_ITMP3);
                        }
 #endif
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
                        break;
 
                case ICMD_IF_LLE:       /* ..., value ==> ...                         */
@@ -2546,30 +2528,24 @@ bool codegen(jitdata *jd)
 #else
                        if (iptr->sx.val.l == 0) {
                                s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED);
-                               M_BGTZ(GET_HIGH_REG(s1), 5);
+                               M_BGTZ(GET_HIGH_REG(s1), 5); /* XXX */
                                M_NOP;
-                               M_BLTZ(GET_HIGH_REG(s1), 0);
-                               codegen_add_branch_ref(cd, iptr->dst.block);
-                               M_NOP;
-                               M_BEQZ(GET_LOW_REG(s1), 0);
+                               emit_bltz(cd, iptr->dst.block, GET_HIGH_REG(s1));
+                               emit_beqz(cd, iptr->dst.block, GET_LOW_REG(s1));
                        }
                        else {
                                s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
                                ICONST(REG_ITMP2, iptr->sx.val.l >> 32);
                                M_CMPLT(s1, REG_ITMP2, REG_ITMP3);
-                               M_BNEZ(REG_ITMP3, 0);
-                               codegen_add_branch_ref(cd, iptr->dst.block);
-                               M_NOP;
+                               emit_bnez(cd, iptr->dst.block, REG_ITMP3);
                                s2 = emit_load_s1_low(jd, iptr, REG_ITMP3);
-                               M_BNE(s1, REG_ITMP2, 5);
+                               M_BNE(s1, REG_ITMP2, 5); /* XXX */
                                M_NOP;
                                ICONST(REG_ITMP2, iptr->sx.val.l & 0xffffffff);
                                M_CMPUGT(s2, REG_ITMP2, REG_ITMP3);
-                               M_BEQZ(REG_ITMP3, 0);
+                               emit_beqz(cd, iptr->dst.block, REG_ITMP3);
                        }
 #endif
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
                        break;
 
                case ICMD_IF_LNE:       /* ..., value ==> ...                         */
@@ -2586,7 +2562,7 @@ bool codegen(jitdata *jd)
                        if (iptr->sx.val.l == 0) {
                                s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED);
                                M_OR(GET_LOW_REG(s1), GET_HIGH_REG(s1), REG_ITMP3);
-                               M_BNEZ(REG_ITMP3, 0);
+                               emit_bnez(cd, iptr->dst.block, REG_ITMP3);
                        }
                        else {
                                s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
@@ -2596,11 +2572,9 @@ bool codegen(jitdata *jd)
                                ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
                                M_XOR(s1, REG_ITMP3, REG_ITMP3);
                                M_OR(REG_ITMP2, REG_ITMP3, REG_ITMP3);
-                               M_BNEZ(REG_ITMP3, 0);
+                               emit_bnez(cd, iptr->dst.block, REG_ITMP3);
                        }
 #endif
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
                        break;
 
                case ICMD_IF_LGT:       /* ..., value ==> ...                         */
@@ -2622,30 +2596,24 @@ bool codegen(jitdata *jd)
 #else
                        if (iptr->sx.val.l == 0) {
                                s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED);
-                               M_BGTZ(GET_HIGH_REG(s1), 0);
-                               codegen_add_branch_ref(cd, iptr->dst.block);
-                               M_NOP;
-                               M_BLTZ(GET_HIGH_REG(s1), 3);
+                               emit_bgtz(cd, iptr->dst.block, GET_HIGH_REG(s1));
+                               M_BLTZ(GET_HIGH_REG(s1), 3); /* XXX */
                                M_NOP;
-                               M_BNEZ(GET_LOW_REG(s1), 0);
+                               emit_bnez(cd, iptr->dst.block, GET_LOW_REG(s1));
                        }
                        else {
                                s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
                                ICONST(REG_ITMP2, iptr->sx.val.l >> 32);
                                M_CMPGT(s1, REG_ITMP2, REG_ITMP3);
-                               M_BNEZ(REG_ITMP3, 0);
-                               codegen_add_branch_ref(cd, iptr->dst.block);
-                               M_NOP;
+                               emit_bnez(cd, iptr->dst.block, REG_ITMP3);
                                s2 = emit_load_s1_low(jd, iptr, REG_ITMP3);
-                               M_BNE(s1, REG_ITMP2, 5);
+                               M_BNE(s1, REG_ITMP2, 5); /* XXX */
                                M_NOP;
                                ICONST(REG_ITMP2, iptr->sx.val.l & 0xffffffff);
                                M_CMPUGT(s2, REG_ITMP2, REG_ITMP3);
-                               M_BNEZ(REG_ITMP3, 0);
+                               emit_bnez(cd, iptr->dst.block, REG_ITMP3);
                        }
 #endif
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
                        break;
 
                case ICMD_IF_LGE:       /* ..., value ==> ...                         */
@@ -2667,25 +2635,21 @@ bool codegen(jitdata *jd)
                        if (iptr->sx.val.l == 0) {
                                /* if high word is greater equal zero, the whole long is too */
                                s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
-                               M_BGEZ(s1, 0);
+                               emit_bgez(cd, iptr->dst.block, s1);
                        }
                        else {
                                s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
                                ICONST(REG_ITMP2, iptr->sx.val.l >> 32);
                                M_CMPGT(s1, REG_ITMP2, REG_ITMP3);
-                               M_BNEZ(REG_ITMP3, 0);
-                               codegen_add_branch_ref(cd, iptr->dst.block);
-                               M_NOP;
+                               emit_bnez(cd, iptr->dst.block, REG_ITMP3);
                                s2 = emit_load_s1_low(jd, iptr, REG_ITMP3);
-                               M_BNE(s1, REG_ITMP2, 5);
+                               M_BNE(s1, REG_ITMP2, 5); /* XXX */
                                M_NOP;
                                ICONST(REG_ITMP2, iptr->sx.val.l & 0xffffffff);
                                M_CMPULT(s2, REG_ITMP2, REG_ITMP3);
-                               M_BEQZ(REG_ITMP3, 0);
+                               emit_beqz(cd, iptr->dst.block, REG_ITMP3);
                        }
 #endif
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
                        break;
 
                case ICMD_IF_ICMPEQ:    /* ..., value, value ==> ...                  */
@@ -2696,9 +2660,7 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       M_BEQ(s1, s2, 0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_beq(cd, iptr->dst.block, s1, s2);
                        break;
 
 #if SIZEOF_VOID_P == 4
@@ -2707,13 +2669,11 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
-                       M_BNE(s1, s2, 3);
+                       M_BNE(s1, s2, 3); /* XXX TWISTI: uff, that is a problem */
                        M_NOP;
                        s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
-                       M_BEQ(s1, s2, 0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_beq(cd, iptr->dst.block, s1, s2);
                        break;
 #endif
 
@@ -2725,24 +2685,19 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       M_BNE(s1, s2, 0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_bne(cd, iptr->dst.block, s1, s2);
                        break;
 
 #if SIZEOF_VOID_P == 4
                case ICMD_IF_LCMPNE:    /* ..., value, value ==> ...                  */
 
+                       /* TODO: could be optimized (XOR or SUB) */
                        s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
-                       M_BNE(s1, s2, 0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_bne(cd, iptr->dst.block, s1, s2);
                        s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
-                       M_BNE(s1, s2, 0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_bne(cd, iptr->dst.block, s1, s2);
                        break;
 #endif
 
@@ -2754,9 +2709,7 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_CMPLT(s1, s2, REG_ITMP3);
-                       M_BNEZ(REG_ITMP3, 0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_bnez(cd, iptr->dst.block, REG_ITMP3);
                        break;
 
 #if SIZEOF_VOID_P == 4
@@ -2765,19 +2718,15 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
                        M_CMPLT(s1, s2, REG_ITMP3);
-                       M_BNEZ(REG_ITMP3, 0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_bnez(cd, iptr->dst.block, REG_ITMP3);
                        M_CMPGT(s1, s2, REG_ITMP3);
                        /* load low-bits before the branch, so we know the distance */
                        s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
-                       M_BNEZ(REG_ITMP3, 4);
+                       M_BNEZ(REG_ITMP3, 4); /* XXX */
                        M_NOP;
                        M_CMPULT(s1, s2, REG_ITMP3);
-                       M_BNEZ(REG_ITMP3, 0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_bnez(cd, iptr->dst.block, REG_ITMP3);
                        break;
 #endif
 
@@ -2789,9 +2738,7 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_CMPGT(s1, s2, REG_ITMP3);
-                       M_BNEZ(REG_ITMP3, 0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_bnez(cd, iptr->dst.block, REG_ITMP3);
                        break;
 
 #if SIZEOF_VOID_P == 4
@@ -2800,19 +2747,15 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
                        M_CMPGT(s1, s2, REG_ITMP3);
-                       M_BNEZ(REG_ITMP3, 0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_bnez(cd, iptr->dst.block, REG_ITMP3);
                        M_CMPLT(s1, s2, REG_ITMP3);
                        /* load low-bits before the branch, so we know the distance */
                        s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
-                       M_BNEZ(REG_ITMP3, 4);
+                       M_BNEZ(REG_ITMP3, 4); /* XXX */
                        M_NOP;
                        M_CMPUGT(s1, s2, REG_ITMP3);
-                       M_BNEZ(REG_ITMP3, 0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_bnez(cd, iptr->dst.block, REG_ITMP3);
                        break;
 #endif
 
@@ -2824,9 +2767,7 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_CMPGT(s1, s2, REG_ITMP3);
-                       M_BEQZ(REG_ITMP3, 0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_beqz(cd, iptr->dst.block, REG_ITMP3);
                        break;
 
 #if SIZEOF_VOID_P == 4
@@ -2835,19 +2776,15 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
                        M_CMPLT(s1, s2, REG_ITMP3);
-                       M_BNEZ(REG_ITMP3, 0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_bnez(cd, iptr->dst.block, REG_ITMP3);
                        M_CMPGT(s1, s2, REG_ITMP3);
                        /* load low-bits before the branch, so we know the distance */
                        s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
-                       M_BNEZ(REG_ITMP3, 4);
+                       M_BNEZ(REG_ITMP3, 4); /* XXX */
                        M_NOP;
                        M_CMPUGT(s1, s2, REG_ITMP3);
-                       M_BEQZ(REG_ITMP3, 0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_beqz(cd, iptr->dst.block, REG_ITMP3);
                        break;
 #endif
 
@@ -2859,9 +2796,7 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_CMPLT(s1, s2, REG_ITMP3);
-                       M_BEQZ(REG_ITMP3, 0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_beqz(cd, iptr->dst.block, REG_ITMP3);
                        break;
 
 #if SIZEOF_VOID_P == 4
@@ -2870,19 +2805,15 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
                        M_CMPGT(s1, s2, REG_ITMP3);
-                       M_BNEZ(REG_ITMP3, 0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_bnez(cd, iptr->dst.block, REG_ITMP3);
                        M_CMPLT(s1, s2, REG_ITMP3);
                        /* load low-bits before the branch, so we know the distance */
                        s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
-                       M_BNEZ(REG_ITMP3, 4);
+                       M_BNEZ(REG_ITMP3, 4); /* XXX */
                        M_NOP;
                        M_CMPULT(s1, s2, REG_ITMP3);
-                       M_BEQZ(REG_ITMP3, 0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_beqz(cd, iptr->dst.block, REG_ITMP3);
                        break;
 #endif
 
@@ -3078,9 +3009,7 @@ nowperformreturn:
                        /* range check */
 
                        M_CMPULT_IMM(REG_ITMP1, i, REG_ITMP2);
-                       M_BEQZ(REG_ITMP2, 0);
-                       codegen_add_branch_ref(cd, table[0].block); /* default target */
-                       M_ASLL_IMM(REG_ITMP1, POINTERSHIFT, REG_ITMP1);     /* delay slot */
+                       emit_beqz(cd, table[0].block, REG_ITMP2);
 
                        /* build jump table top down and use address of lowest entry */
 
@@ -3094,6 +3023,7 @@ nowperformreturn:
 
                        /* length of dataseg after last dseg_add_target is used by load */
 
+                       M_ASLL_IMM(REG_ITMP1, POINTERSHIFT, REG_ITMP1);
                        M_AADD(REG_ITMP1, REG_PV, REG_ITMP2);
                        M_ALD(REG_ITMP2, REG_ITMP2, -(cd->dseglen));
                        M_JMP(REG_ITMP2);
@@ -3116,15 +3046,11 @@ nowperformreturn:
 
                        while (--i >= 0) {
                                ICONST(REG_ITMP2, lookup->value);
-                               M_BEQ(s1, REG_ITMP2, 0);
-                               codegen_add_branch_ref(cd, lookup->target.block); 
-                               M_NOP;
+                               emit_beq(cd, lookup->target.block, s1, REG_ITMP2);
                                ++lookup;
                        }
 
-                       M_BR(0);
-                       codegen_add_branch_ref(cd, iptr->sx.s23.s3.lookupdefault.block);
-                       M_NOP;
+                       emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
                        ALIGNCODENOP;
                        break;
                        }
@@ -3260,23 +3186,22 @@ gen_method:
 
                                M_ALD(REG_ITMP3, REG_PV, disp);  /* built-in-function pointer */
 
+                               /* generate the actual call */
+
                                /* TWISTI: i actually don't know the reason for using
                                   REG_ITMP3 here instead of REG_PV. */
-                               s1 = REG_ITMP3;
-                               break;
 
-                       case ICMD_INVOKESPECIAL:
-/*                             emit_nullpointer_check(cd, REG_A0); */
-                               M_BNEZ(REG_A0, 6);
+                               M_JSR(REG_RA, REG_ITMP3);
                                M_NOP;
+                               REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
+                               disp = (s4) (cd->mcodeptr - cd->mcodebase);
+                               M_LDA(REG_PV, REG_RA, -disp);
 
-                               M_LUI(REG_ITMP3, 0);
-                               M_OR_IMM(REG_ITMP3, 0, REG_ITMP3);
-                               codegen_add_nullpointerexception_ref(cd);
-                               M_AADD(REG_PV, REG_ITMP3, REG_ITMP3);
-                               M_JMP(REG_ITMP3);
-                               M_NOP;
+                               emit_exception_check(cd, iptr);
+                               break;
 
+                       case ICMD_INVOKESPECIAL:
+                               emit_nullpointer_check(cd, iptr, REG_A0);
                                /* fall through */
 
                        case ICMD_INVOKESTATIC:
@@ -3290,7 +3215,14 @@ gen_method:
                                        disp = dseg_add_address(cd, lm->stubroutine);
 
                                M_ALD(REG_PV, REG_PV, disp);          /* method pointer in pv */
-                               s1 = REG_PV;
+
+                               /* generate the actual call */
+
+                               M_JSR(REG_RA, REG_PV);
+                               M_NOP;
+                               REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
+                               disp = (s4) (cd->mcodeptr - cd->mcodebase);
+                               M_LDA(REG_PV, REG_RA, -disp);
                                break;
 
                        case ICMD_INVOKEVIRTUAL:
@@ -3305,9 +3237,17 @@ gen_method:
                                        s1 = OFFSET(vftbl_t, table[0]) +
                                                sizeof(methodptr) * lm->vftblindex;
 
+                               /* implicit null-pointer check */
                                M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_objectheader, vftbl));
                                M_ALD(REG_PV, REG_METHODPTR, s1);
-                               s1 = REG_PV;
+
+                               /* generate the actual call */
+
+                               M_JSR(REG_RA, REG_PV);
+                               M_NOP;
+                               REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
+                               disp = (s4) (cd->mcodeptr - cd->mcodebase);
+                               M_LDA(REG_PV, REG_RA, -disp);
                                break;
 
                        case ICMD_INVOKEINTERFACE:
@@ -3326,24 +3266,20 @@ gen_method:
                                        s2 = sizeof(methodptr) * (lm - lm->class->methods);
                                }
 
+                               /* implicit null-pointer check */
                                M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_objectheader, vftbl));
                                M_ALD(REG_METHODPTR, REG_METHODPTR, s1);
                                M_ALD(REG_PV, REG_METHODPTR, s2);
-                               s1 = REG_PV;
-                               break;
-                       }
 
-                       /* generate the actual call */
-
-                       M_JSR(REG_RA, s1);
-                       M_NOP;
-                       REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
-                       disp = (s4) (cd->mcodeptr - cd->mcodebase);
-                       M_LDA(REG_PV, REG_RA, -disp);
+                               /* generate the actual call */
 
-                       /* actually only used for ICMD_BUILTIN */
-
-                       emit_exception_check(cd, iptr);
+                               M_JSR(REG_RA, REG_PV);
+                               M_NOP;
+                               REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
+                               disp = (s4) (cd->mcodeptr - cd->mcodebase);
+                               M_LDA(REG_PV, REG_RA, -disp);
+                               break;
+                       }
 
                        /* store return value */
 
@@ -3412,25 +3348,10 @@ gen_method:
 
                                s1 = emit_load_s1(jd, iptr, REG_ITMP1);
 
-                               /* calculate interface checkcast code size */
-
-/*                             s2 = 3 + 2 + 1 + 2; */
-                               s2 = 3 + 7 + 1 + 7;
-                               if (super == NULL)
-                                       s2 += (opt_shownops ? PATCHER_CALL_INSTRUCTIONS : 0);
-
-                               /* calculate class checkcast code size */
-
-/*                             s3 = 2 + 1 + 4 + 1 + 2 /\* 10 + (s1 == REG_ITMP1) *\/; */
-                               s3 = 2 + 1 + 4 + 1 + 7;
-                               if (super == NULL)
-                                       s3 += (opt_shownops ? PATCHER_CALL_INSTRUCTIONS : 0);
-
                                /* if class is not resolved, check which code to call */
 
                                if (super == NULL) {
-                                       M_BEQZ(s1, 5 + (opt_shownops ? PATCHER_CALL_INSTRUCTIONS : 0) + s2 + 2 + s3);
-                                       M_NOP;
+                                       emit_label_beqz(cd, BRANCH_LABEL_1, s1);
 
                                        cr   = iptr->sx.s23.s3.c.ref;
                                        disp = dseg_add_unique_s4(cd, 0);         /* super->flags */
@@ -3438,11 +3359,9 @@ gen_method:
                                        codegen_add_patch_ref(cd, PATCHER_checkcast_instanceof_flags,
                                                                                  cr, disp);
 
-                                       /* XXX TWISTI M_ILD can be 2 instructions long (jump offset) */
                                        M_ILD(REG_ITMP2, REG_PV, disp);
                                        M_AND_IMM(REG_ITMP2, ACC_INTERFACE, REG_ITMP2);
-                                       M_BEQZ(REG_ITMP2, 1 + s2 + 2);
-                                       M_NOP;
+                                       emit_label_beqz(cd, BRANCH_LABEL_2, REG_ITMP2);
                                }
 
                                /* interface checkcast code */
@@ -3455,8 +3374,7 @@ gen_method:
                                                                                          cr, 0);
                                        }
                                        else {
-                                               M_BEQZ(s1, 1 + s2);
-                                               M_NOP;
+                                               emit_label_beqz(cd, BRANCH_LABEL_3, s1);
                                        }
 
                                        M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
@@ -3470,16 +3388,18 @@ gen_method:
                                                  superindex * sizeof(methodptr*));
                                        emit_classcast_check(cd, iptr, ICMD_IFEQ, REG_ITMP3, s1);
 
-                                       if (super == NULL) {
-                                               M_BR(1 + s3);
-                                               M_NOP;
-                                       }
+                                       if (super == NULL)
+                                               emit_label_br(cd, BRANCH_LABEL_4);
+                                       else
+                                               emit_label(cd, BRANCH_LABEL_3);
                                }
 
                                /* class checkcast code */
 
                                if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
                                        if (super == NULL) {
+                                               emit_label(cd, BRANCH_LABEL_2);
+
                                                cr   = iptr->sx.s23.s3.c.ref;
                                                disp = dseg_add_unique_address(cd, NULL);
 
@@ -3490,8 +3410,7 @@ gen_method:
                                        else {
                                                disp = dseg_add_address(cd, super->vftbl);
 
-                                               M_BEQZ(s1, 1 + s3);
-                                               M_NOP;
+                                               emit_label_beqz(cd, BRANCH_LABEL_5, s1);
                                        }
 
                                        M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
@@ -3518,6 +3437,14 @@ gen_method:
                                        /*                              } */
                                        M_CMPULT(REG_ITMP3, REG_ITMP2, REG_ITMP3);
                                        emit_classcast_check(cd, iptr, ICMD_IFNE, REG_ITMP3, s1);
+
+                                       if (super != NULL)
+                                               emit_label(cd, BRANCH_LABEL_5);
+                               }
+
+                               if (super == NULL) {
+                                       emit_label(cd, BRANCH_LABEL_1);
+                                       emit_label(cd, BRANCH_LABEL_4);
                                }
 
                                d = codegen_reg_of_dst(jd, iptr, s1);
@@ -3589,30 +3516,18 @@ gen_method:
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+
                        if (s1 == d) {
                                M_MOV(s1, REG_ITMP1);
                                s1 = REG_ITMP1;
                        }
 
-                       /* calculate interface instanceof code size */
-
-                       s2 = 7;
-                       if (super == NULL)
-                               s2 += (opt_shownops ? PATCHER_CALL_INSTRUCTIONS : 0);
-
-                       /* calculate class instanceof code size */
-
-                       s3 = 8;
-                       if (super == NULL)
-                               s3 += (opt_shownops ? PATCHER_CALL_INSTRUCTIONS : 0);
-
                        M_CLR(d);
 
                        /* if class is not resolved, check which code to call */
 
                        if (super == NULL) {
-                               M_BEQZ(s1, 5 + (opt_shownops ? PATCHER_CALL_INSTRUCTIONS : 0) + s2 + 2 + s3);
-                               M_NOP;
+                               emit_label_beqz(cd, BRANCH_LABEL_1, s1);
 
                                cr   = iptr->sx.s23.s3.c.ref;
                                disp = dseg_add_unique_s4(cd, 0);             /* super->flags */
@@ -3620,11 +3535,9 @@ gen_method:
                                codegen_add_patch_ref(cd, PATCHER_checkcast_instanceof_flags,
                                                                          cr, disp);
 
-                               /* XXX TWISTI M_ILD can be 2 instructions long (jump offset) */
                                M_ILD(REG_ITMP3, REG_PV, disp);
                                M_AND_IMM(REG_ITMP3, ACC_INTERFACE, REG_ITMP3);
-                               M_BEQZ(REG_ITMP3, 1 + s2 + 2);
-                               M_NOP;
+                               emit_label_beqz(cd, BRANCH_LABEL_2, REG_ITMP3);
                        }
 
                        /* interface instanceof code */
@@ -3637,8 +3550,7 @@ gen_method:
                                                                                  cr, 0);
                                }
                                else {
-                                       M_BEQZ(s1, 1 + s2);
-                                       M_NOP;
+                                       emit_label_beqz(cd, BRANCH_LABEL_3, s1);
                                }
 
                                M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
@@ -3652,16 +3564,18 @@ gen_method:
                                          superindex * sizeof(methodptr*));
                                M_CMPULT(REG_ZERO, REG_ITMP1, d);      /* REG_ITMP1 != 0  */
 
-                               if (super == NULL) {
-                                       M_BR(1 + s3);
-                                       M_NOP;
-                               }
+                               if (super == NULL)
+                                       emit_label_br(cd, BRANCH_LABEL_4);
+                               else
+                                       emit_label(cd, BRANCH_LABEL_3);
                        }
 
                        /* class instanceof code */
 
                        if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
                                if (super == NULL) {
+                                       emit_label(cd, BRANCH_LABEL_2);
+
                                        cr   = iptr->sx.s23.s3.c.ref;
                                        disp = dseg_add_unique_address(cd, NULL);
 
@@ -3671,8 +3585,7 @@ gen_method:
                                else {
                                        disp = dseg_add_address(cd, super->vftbl);
 
-                                       M_BEQZ(s1, 1 + s3);
-                                       M_NOP;
+                                       emit_label_beqz(cd, BRANCH_LABEL_5, s1);
                                }
 
                                M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
@@ -3689,7 +3602,16 @@ gen_method:
                                M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1); 
                                M_CMPULT(REG_ITMP2, REG_ITMP1, d);
                                M_XOR_IMM(d, 1, d);
+
+                               if (super != NULL)
+                                       emit_label(cd, BRANCH_LABEL_5);
                        }
+
+                       if (super == NULL) {
+                               emit_label(cd, BRANCH_LABEL_1);
+                               emit_label(cd, BRANCH_LABEL_4);
+                       }
+
                        emit_store_dst(jd, iptr, d);
                        }
                        break;
@@ -3783,14 +3705,11 @@ gen_method:
 
        dseg_createlinenumbertable(cd);
 
-       /* generate exception and patcher stubs */
+       /* generate stubs */
 
-       emit_exception_stubs(jd);
        emit_patcher_stubs(jd);
        REPLACEMENT_EMIT_STUBS(jd);
 
-       codegen_finish(jd);
-
        /* everything's ok */
 
        return true;
index d02ee11000cb93d7924cbaec96f7d858a975f25c..9e73fd05701721db98e449e6994130170c7e8190 100644 (file)
@@ -1,6 +1,6 @@
 /* src/vm/jit/mips/codegen.h - code generation macros and definitions for MIPS
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
    J. Wenninger, Institut f. Computersprachen - TU Wien
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Andreas Krall
-            Christian Thalinger
-
-   $Id: codegen.h 7206 2007-01-11 22:39:52Z twisti $
+   $Id: codegen.h 7363 2007-02-15 14:57:04Z twisti $
 
 */
 
     do { \
         M_NOP; \
         M_NOP; \
-        M_NOP; \
-        M_NOP; \
-        M_NOP; \
     } while (0)
 
 
         cd->mcodeptr += 4; \
     } while (0)
 
+#define M_ITYPE_GET_RS(x)               (((x) >> 21) & 0x1f  )
+#define M_ITYPE_GET_RT(x)               (((x) >> 16) & 0x1f  )
+#define M_ITYPE_GET_IMM(x)              ( (x)        & 0xffff)
+
+
 #define M_JTYPE(op,imm) \
     do { \
         *((u4 *) cd->mcodeptr) = (((op) << 26) | ((off) & 0x3ffffff)); \
 #define M_BGEZ(a,disp)          M_ITYPE(0x01,a,1,disp)          /* br a >= 0  */
 #define M_BGTZ(a,disp)          M_ITYPE(0x07,a,0,disp)          /* br a >  0  */
 
+#if 0
 #define M_BEQL(a,b,disp)        M_ITYPE(0x14,a,b,disp)          /* br a == b  */
 #define M_BNEL(a,b,disp)        M_ITYPE(0x15,a,b,disp)          /* br a != b  */
 #define M_BEQZL(a,disp)         M_ITYPE(0x14,a,0,disp)          /* br a == 0  */
 #define M_BNEZL(a,disp)         M_ITYPE(0x15,a,0,disp)          /* br a != 0  */
 #define M_BGEZL(a,disp)         M_ITYPE(0x01,a,3,disp)          /* br a >= 0  */
 #define M_BGTZL(a,disp)         M_ITYPE(0x17,a,0,disp)          /* br a >  0  */
+#endif
 
 #define M_BR(disp)              M_ITYPE(0x04,0,0,disp)          /* branch     */
 #define M_BRS(disp)             M_ITYPE(0x01,0,17,disp)         /* branch sbr */
index cc06397e9a9901ac8214a059fd19a1c4e7fa83f3..6e7f7f61d5af6f8dfdd648f5c842406bc2f65cfc 100644 (file)
@@ -334,89 +334,118 @@ void emit_lconst(codegendata *cd, s4 d, s8 value)
 }
 
 
-/* emit_arithmetic_check *******************************************************
+/* emit_branch *****************************************************************
 
-   Emit an ArithmeticException check.
+   Emits the code for conditional and unconditional branchs.
+
+   NOTE: The reg argument may contain two packed registers.
 
 *******************************************************************************/
 
-void emit_arithmetic_check(codegendata *cd, instruction *iptr, s4 reg)
+void emit_branch(codegendata *cd, s4 disp, s4 condition, s4 reg, u4 opt)
 {
-       if (INSTRUCTION_MUST_CHECK(iptr)) {
-#if 0
-               M_BEQZ(reg, 0);
-               codegen_add_arithmeticexception_ref(cd);
-               M_NOP;
-#else
-               M_BNEZ(reg, 6);
-               M_NOP;
+       s4 checkdisp;
+       s4 branchdisp;
 
-               M_LUI(REG_ITMP3, 0);
-               M_OR_IMM(REG_ITMP3, 0, REG_ITMP3);
-               codegen_add_arithmeticexception_ref(cd);
-               M_AADD(REG_PV, REG_ITMP3, REG_ITMP3);
-               M_JMP(REG_ITMP3);
-               M_NOP;
-#endif
+       /* calculate the different displacements */
+
+       checkdisp  = (disp - 4);
+       branchdisp = (disp - 4) >> 2;
+
+       /* check which branch to generate */
+
+       if (condition == BRANCH_UNCONDITIONAL) {
+               /* check displacement for overflow */
+
+               if ((checkdisp < (s4) 0xffff8000) || (checkdisp > (s4) 0x00007fff)) {
+                       /* if the long-branches flag isn't set yet, do it */
+
+                       if (!CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
+                               cd->flags |= (CODEGENDATA_FLAG_ERROR |
+                                                         CODEGENDATA_FLAG_LONGBRANCHES);
+                       }
+
+                       vm_abort("emit_branch: emit unconditional long-branch code");
+               }
+               else {
+                       M_BR(branchdisp);
+                       M_NOP;
+               }
+       }
+       else {
+               /* and displacement for overflow */
+
+               if ((checkdisp < (s4) 0xffff8000) || (checkdisp > (s4) 0x00007fff)) {
+                       /* if the long-branches flag isn't set yet, do it */
+
+                       if (!CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
+                               cd->flags |= (CODEGENDATA_FLAG_ERROR |
+                                                         CODEGENDATA_FLAG_LONGBRANCHES);
+                       }
+
+                       vm_abort("emit_branch: emit conditional long-branch code");
+               }
+               else {
+                       switch (condition) {
+                       case BRANCH_EQ:
+                               M_BEQ(GET_HIGH_REG(reg), GET_LOW_REG(reg), branchdisp);
+                               break;
+                       case BRANCH_NE:
+                               M_BNE(GET_HIGH_REG(reg), GET_LOW_REG(reg), branchdisp);
+                               break;
+                       case BRANCH_LT:
+                               M_BLTZ(reg, branchdisp);
+                               break;
+                       case BRANCH_GE:
+                               M_BGEZ(reg, branchdisp);
+                               break;
+                       case BRANCH_GT:
+                               M_BGTZ(reg, branchdisp);
+                               break;
+                       case BRANCH_LE:
+                               M_BLEZ(reg, branchdisp);
+                               break;
+                       default:
+                               vm_abort("emit_branch: unknown condition %d", condition);
+                       }
+
+                       /* branch delay */
+                       M_NOP;
+               }
        }
 }
 
 
-/* emit_arrayindexoutofbounds_check ********************************************
+/* emit_arithmetic_check *******************************************************
 
-   Emit an ArrayIndexOutOfBoundsException check.
+   Emit an ArithmeticException check.
 
 *******************************************************************************/
 
-void emit_arrayindexoutofbounds_check(codegendata *cd, instruction *iptr, s4 s1, s4 s2)
+void emit_arithmetic_check(codegendata *cd, instruction *iptr, s4 reg)
 {
        if (INSTRUCTION_MUST_CHECK(iptr)) {
-               M_ILD(REG_ITMP3, s1, OFFSET(java_arrayheader, size));
-               M_CMPULT(s2, REG_ITMP3, REG_ITMP3);
-
-#if 0
-               M_BEQZ(REG_ITMP3, 0);
-               codegen_add_arrayindexoutofboundsexception_ref(cd, s2);
-               M_NOP;
-#else
-               M_BNEZ(REG_ITMP3, 6);
-               M_NOP;
-
-               M_LUI(REG_ITMP3, 0);
-               M_OR_IMM(REG_ITMP3, 0, REG_ITMP3);
-               codegen_add_arrayindexoutofboundsexception_ref(cd, s2);
-               M_AADD(REG_PV, REG_ITMP3, REG_ITMP3);
-               M_JMP(REG_ITMP3);
+               M_BNEZ(reg, 2);
                M_NOP;
-#endif
+               M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_ARITHMETIC);
        }
 }
 
 
-/* emit_arraystore_check *******************************************************
+/* emit_arrayindexoutofbounds_check ********************************************
 
-   Emit an ArrayStoreException check.
+   Emit an ArrayIndexOutOfBoundsException check.
 
 *******************************************************************************/
 
-void emit_arraystore_check(codegendata *cd, instruction *iptr, s4 reg)
+void emit_arrayindexoutofbounds_check(codegendata *cd, instruction *iptr, s4 s1, s4 s2)
 {
        if (INSTRUCTION_MUST_CHECK(iptr)) {
-#if 0
-               M_BEQZ(reg, 0);
-               codegen_add_arraystoreexception_ref(cd);
-               M_NOP;
-#else
-               M_BNEZ(reg, 6);
-               M_NOP;
-
-               M_LUI(REG_ITMP3, 0);
-               M_OR_IMM(REG_ITMP3, 0, REG_ITMP3);
-               codegen_add_arraystoreexception_ref(cd);
-               M_AADD(REG_PV, REG_ITMP3, REG_ITMP3);
-               M_JMP(REG_ITMP3);
+               M_ILD_INTERN(REG_ITMP3, s1, OFFSET(java_arrayheader, size));
+               M_CMPULT(s2, REG_ITMP3, REG_ITMP3);
+               M_BNEZ(REG_ITMP3, 2);
                M_NOP;
-#endif
+               M_ALD_INTERN(s2, REG_ZERO, EXCEPTION_HARDWARE_ARRAYINDEXOUTOFBOUNDS);
        }
 }
 
@@ -430,37 +459,25 @@ void emit_arraystore_check(codegendata *cd, instruction *iptr, s4 reg)
 void emit_classcast_check(codegendata *cd, instruction *iptr, s4 condition, s4 reg, s4 s1)
 {
        if (INSTRUCTION_MUST_CHECK(iptr)) {
-#if 0
-               M_BNEZ(reg, 0);
-               codegen_add_classcastexception_ref(cd, s1);
-               M_NOP;
-#else
                switch (condition) {
                case ICMD_IFEQ:
-                       M_BNEZ(reg, 6);
+                       M_BNEZ(reg, 2);
                        break;
 
                case ICMD_IFNE:
-                       M_BEQZ(reg, 6);
+                       M_BEQZ(reg, 2);
                        break;
 
                case ICMD_IFLE:
-                       M_BGTZ(reg, 6);
+                       M_BGTZ(reg, 2);
                        break;
 
                default:
-                       vm_abort("emit_classcast_check: condition %d not found", condition);
+                       vm_abort("emit_classcast_check: unknown condition %d", condition);
                }
 
                M_NOP;
-
-               M_LUI(REG_ITMP3, 0);
-               M_OR_IMM(REG_ITMP3, 0, REG_ITMP3);
-               codegen_add_classcastexception_ref(cd, s1);
-               M_AADD(REG_PV, REG_ITMP3, REG_ITMP3);
-               M_JMP(REG_ITMP3);
-               M_NOP;
-#endif
+               M_ALD_INTERN(s1, REG_ZERO, EXCEPTION_HARDWARE_CLASSCAST);
        }
 }
 
@@ -474,21 +491,9 @@ void emit_classcast_check(codegendata *cd, instruction *iptr, s4 condition, s4 r
 void emit_nullpointer_check(codegendata *cd, instruction *iptr, s4 reg)
 {
        if (INSTRUCTION_MUST_CHECK(iptr)) {
-#if 0
-               M_BEQZ(reg, 0);
-               codegen_add_nullpointerexception_ref(cd);
-               M_NOP;
-#else
-               M_BNEZ(reg, 6);
+               M_BNEZ(reg, 2);
                M_NOP;
-
-               M_LUI(REG_ITMP3, 0);
-               M_OR_IMM(REG_ITMP3, 0, REG_ITMP3);
-               codegen_add_nullpointerexception_ref(cd);
-               M_AADD(REG_PV, REG_ITMP3, REG_ITMP3);
-               M_JMP(REG_ITMP3);
-               M_NOP;
-#endif
+               M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_NULLPOINTER);
        }
 }
 
@@ -502,138 +507,9 @@ void emit_nullpointer_check(codegendata *cd, instruction *iptr, s4 reg)
 void emit_exception_check(codegendata *cd, instruction *iptr)
 {
        if (INSTRUCTION_MUST_CHECK(iptr)) {
-#if 0
-               M_BEQZ(REG_RESULT, 0);
-               codegen_add_fillinstacktrace_ref(cd);
-               M_NOP;
-#else
-               M_BNEZ(REG_RESULT, 6);
+               M_BNEZ(REG_RESULT, 2);
                M_NOP;
-
-               M_LUI(REG_ITMP3, 0);
-               M_OR_IMM(REG_ITMP3, 0, REG_ITMP3);
-               codegen_add_fillinstacktrace_ref(cd);
-               M_AADD(REG_PV, REG_ITMP3, REG_ITMP3);
-               M_JMP(REG_ITMP3);
-               M_NOP;
-#endif
-       }
-}
-
-
-/* emit_exception_stubs ********************************************************
-
-   Generates the code for the exception stubs.
-
-*******************************************************************************/
-
-void emit_exception_stubs(jitdata *jd)
-{
-       codegendata  *cd;
-       registerdata *rd;
-       exceptionref *er;
-       s4            branchmpc;
-       s4            targetmpc;
-       s4            targetdisp;
-       s4            disp;
-
-       /* get required compiler data */
-
-       cd = jd->cd;
-       rd = jd->rd;
-
-       /* generate exception stubs */
-
-       targetdisp = 0;
-
-       for (er = cd->exceptionrefs; er != NULL; er = er->next) {
-               /* back-patch the branch to this exception code */
-
-               branchmpc = er->branchpos;
-               targetmpc = cd->mcodeptr - cd->mcodebase;
-
-               md_codegen_patch_branch(cd, branchmpc, targetmpc);
-
-               MCODECHECK(100);
-
-               /* Check if the exception is an
-                  ArrayIndexOutOfBoundsException.  If so, move index register
-                  into REG_ITMP1. */
-
-               if (er->reg != -1)
-                       M_MOV(er->reg, REG_ITMP1);
-
-               /* calcuate exception address */
-
-               M_LDA(REG_ITMP2_XPC, REG_PV, er->branchpos - 4);
-
-               /* move function to call into REG_ITMP3 */
-
-               disp = dseg_add_functionptr(cd, er->function);
-               M_ALD(REG_ITMP3, REG_PV, disp);
-
-               if (targetdisp == 0) {
-                       targetdisp = ((u4 *) cd->mcodeptr) - ((u4 *) cd->mcodebase);
-
-                       M_MOV(REG_PV, REG_A0);
-                       M_MOV(REG_SP, REG_A1);
-
-                       if (jd->isleafmethod)
-                               M_MOV(REG_RA, REG_A2);
-                       else
-                               M_ALD(REG_A2, REG_SP, (cd->stackframesize - 1) * 8);
-
-                       M_MOV(REG_ITMP2_XPC, REG_A3);
-
-#if SIZEOF_VOID_P == 8
-                       /* XXX */
-                       M_MOV(REG_ITMP1, REG_A4);
-
-                       M_ASUB_IMM(REG_SP, 2 * 8, REG_SP);
-                       M_AST(REG_ITMP2_XPC, REG_SP, 0 * 8);
-
-                       if (jd->isleafmethod)
-                               M_AST(REG_RA, REG_SP, 1 * 8);
-#else
-                       M_ASUB_IMM(REG_SP, 5*4 + 2 * 8, REG_SP);
-                       M_AST(REG_ITMP2_XPC, REG_SP, 5*4 + 0 * 8);
-
-                       if (jd->isleafmethod)
-                               M_AST(REG_RA, REG_SP, 5*4 + 1 * 8);
-
-                       M_AST(REG_ITMP1, REG_SP, 4 * 4);
-#endif
-
-                       M_JSR(REG_RA, REG_ITMP3);
-                       M_NOP;
-                       M_MOV(REG_RESULT, REG_ITMP1_XPTR);
-
-#if SIZEOF_VOID_P == 8
-                       if (jd->isleafmethod)
-                               M_ALD(REG_RA, REG_SP, 1 * 8);
-
-                       M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
-                       M_AADD_IMM(REG_SP, 2 * 8, REG_SP);
-#else
-                       if (jd->isleafmethod)
-                               M_ALD(REG_RA, REG_SP, 5*4 + 1 * 8);
-
-                       M_ALD(REG_ITMP2_XPC, REG_SP, 5*4 + 0 * 8);
-                       M_AADD_IMM(REG_SP, 5*4 + 2 * 8, REG_SP);
-#endif
-
-                       disp = dseg_add_functionptr(cd, asm_handle_exception);
-                       M_ALD(REG_ITMP3, REG_PV, disp);
-                       M_JMP(REG_ITMP3);
-                       M_NOP;
-               }
-               else {
-                       disp = (((u4 *) cd->mcodebase) + targetdisp) -
-                               (((u4 *) cd->mcodeptr) + 1);
-
-                       M_BR(disp);
-                       M_NOP;
-               }
+               M_ALD_INTERN(REG_RESULT, REG_ZERO, EXCEPTION_HARDWARE_EXCEPTION);
        }
 }
 
index cb8e2639e0aa3dc7d3184e4ac0fd3691c969b918..71b4f0c25d0ab158b4bb0182dc2de471fc8f1395 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: md-os.c 7252 2007-01-29 21:09:01Z twisti $
+   $Id: md-os.c 7570 2007-03-24 22:20:09Z twisti $
 
 */
 
@@ -36,6 +36,7 @@
 
 #include "vm/types.h"
 
+#include "vm/jit/mips/codegen.h"
 #include "vm/jit/mips/md-abi.h"
 
 #include "mm/gc-common.h"
@@ -84,15 +85,22 @@ void md_init(void)
 
 void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
 {
-       ucontext_t  *_uc;
-       mcontext_t  *_mc;
-       greg_t      *_gregs;
-       u4           instr;
-       ptrint       addr;
-       u1          *pv;
-       u1          *sp;
-       u1          *ra;
-       u1          *xpc;
+       ucontext_t        *_uc;
+       mcontext_t        *_mc;
+       greg_t            *_gregs;
+       u1                *pv;
+       u1                *sp;
+       u1                *ra;
+       u1                *xpc;
+       unsigned int       cause;
+       u4                 mcode;
+       s4                 d;
+       s4                 s1;
+       s4                 disp;
+       ptrint             val;
+       ptrint             addr;
+       s4                 type;
+       java_objectheader *o;
 
        _uc    = (struct ucontext *) _p;
        _mc    = &_uc->uc_mcontext;
@@ -113,32 +121,69 @@ void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
 
 #if defined(__UCLIBC__)
        xpc = (u1 *) (ptrint) _gregs[CTX_EPC];
+
+#error how to get the cause?
 #else
        xpc = (u1 *) (ptrint) _mc->pc;
+
+       /* get the cause of this exception */
+
+       cause = _mc->cause;
 #endif
 
-       instr = *((u4 *) xpc);
-       addr  = _gregs[(instr >> 21) & 0x1f];
+       /* check the cause to find the faulting instruction */
 
-       if (addr == 0) {
-               _gregs[REG_ITMP1_XPTR] =
-                       (ptrint) stacktrace_hardware_nullpointerexception(pv, sp, ra, xpc);
+       /* TODO: use defines for that stuff */
 
-               _gregs[REG_ITMP2_XPC] = (ptrint) xpc;
+       switch (cause & 0x0000003c) {
+       case 0x00000008:
+               /* TLBL: XPC is ok */
+               break;
 
-#if defined(__UCLIBC__)
-               _gregs[CTX_EPC] = (ptrint) asm_handle_exception;
-#else
-               _mc->pc         = (ptrint) asm_handle_exception;
-#endif
+       case 0x00000010:
+               /* AdEL: XPC is of the following instruction */
+               xpc = xpc - 4;
        }
-       else {
-               codegen_get_pv_from_pc(xpc);
 
-               /* this should not happen */
+       /* get exception-throwing instruction */
+
+       mcode = *((u4 *) xpc);
+
+       d    = M_ITYPE_GET_RT(mcode);
+       s1   = M_ITYPE_GET_RS(mcode);
+       disp = M_ITYPE_GET_IMM(mcode);
+
+       val   = _gregs[d];
+
+       /* check for special-load */
+
+       if (s1 == REG_ZERO) {
+               /* we use the exception type as load displacement */
 
-               assert(0);
+               type = disp;
        }
+       else {
+               /* This is a normal NPE: addr must be NULL and the NPE-type
+                  define is 0. */
+
+               addr = _gregs[s1];
+               type = (s4) addr;
+       }
+
+       /* generate appropriate exception */
+
+       o = exceptions_new_hardware_exception(pv, sp, ra, xpc, type, val);
+
+       /* set registers */
+
+       _gregs[REG_ITMP1_XPTR] = (ptrint) o;
+       _gregs[REG_ITMP2_XPC]  = (ptrint) xpc;
+
+#if defined(__UCLIBC__)
+       _gregs[CTX_EPC]        = (ptrint) asm_handle_exception;
+#else
+       _mc->pc                = (ptrint) asm_handle_exception;
+#endif
 }
 
 
index fedd7447247df8b0ce314a228ec0aea10858bbb7..b28f0bd26653321f34e9048e6752ecbdaf569f5a 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: md.c 7477 2007-03-07 14:05:04Z twisti $
+   $Id: md.c 7486 2007-03-08 13:50:07Z twisti $
 
 */
 
 #endif
 
 
-/* md_codegen_patch_branch *****************************************************
-
-   Back-patches a branch instruction.
-
-*******************************************************************************/
-
-void md_codegen_patch_branch(codegendata *cd, s4 branchmpc, s4 targetmpc)
-{
-       s4 *mcodeptr;
-       s4  mcode;
-       s4  disp;                           /* branch displacement                */
-       s4  lo;
-       s4  hi;
-
-       /* calculate the patch position */
-
-       mcodeptr = (s4 *) (cd->mcodebase + branchmpc);
-
-       /* get the instruction before the exception point */
-
-       mcode = mcodeptr[-1];
-
-       /* check for: ori t9,t9,0 */
-
-       if ((mcode >> 16) == 0x3739) {
-               /* Calculate the branch displacement.  For jumps we need a
-                  displacement relative to PV. */
-
-               disp = targetmpc;
-
-        lo = (short) disp;
-        hi = (short) ((disp - lo) >> 16);
-
-               /* patch the two instructions before the mcodeptr */
-
-               mcodeptr[-2] |= (hi & 0x0000ffff);
-               mcodeptr[-1] |= (lo & 0x0000ffff);
-       }
-       else {
-               /* Calculate the branch displacement.  For branches we need a
-                  displacement relative and shifted to the branch PC. */
-
-               disp = (targetmpc - branchmpc) >> 2;
-
-               /* On the MIPS we can only branch signed 16-bit instruction words
-                  (signed 18-bit = 32KB = +/- 16KB). Check this! */
-
-               if ((disp < (s4) 0xffff8000) || (disp > (s4) 0x00007fff))
-                       vm_abort("jump displacement is out of range: %d > +/-%d", disp, 0x00007fff);
-
-               /* patch the branch instruction before the mcodeptr */
-
-               mcodeptr[-1] |= (disp & 0x0000ffff);
-       }
-}
-
-
 /* md_stacktrace_get_returnaddress *********************************************
 
    Returns the return address of the current stackframe, specified by
index b45876cd7478810db48fde10531d54b4d4b893e4..cf6782e8287e5db2b0ba75e59d9294d38a89ad0d 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: patcher.c 7464 2007-03-06 00:26:31Z edwin $
+   $Id: patcher.c 7486 2007-03-08 13:50:07Z twisti $
 
 */
 
@@ -593,7 +593,7 @@ bool patcher_checkcast_instanceof_flags(u1 *sp)
 }
 
 
-/* patcher_checkcast_instanceof_interface **************************************
+/* patcher_checkcast_interface *************************************************
 
    Machine code:
 
@@ -633,13 +633,13 @@ bool patcher_checkcast_interface(u1 *sp)
                *((s4 *) (ra + 2 * 4)) |= (s4) (-(c->index) & 0x0000ffff);
                /*      *((s4 *) (ra + 5 * 4)) |= (s4) ((OFFSET(vftbl_t, interfacetable[0]) - */
                /*                                                                       c->index * sizeof(methodptr*)) & 0x0000ffff); */
-               *((s4 *) (ra + 10 * 4)) |=
+               *((s4 *) (ra + 6 * 4)) |=
                        (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
                                   c->index * sizeof(methodptr*)) & 0x0000ffff);
 
                /* synchronize instruction cache */
 
-               md_icacheflush(ra + 2 * 4, 7 * 4);
+               md_icacheflush(ra + 2 * 4, 5 * 4);
        }
        else {
                /* patch super class index */
@@ -647,13 +647,13 @@ bool patcher_checkcast_interface(u1 *sp)
                *((s4 *) (sp + 2 * 4)) |= (s4) (-(c->index) & 0x0000ffff);
                /*      *((s4 *) (ra + 5 * 4)) |= (s4) ((OFFSET(vftbl_t, interfacetable[0]) - */
                /*                                                                       c->index * sizeof(methodptr*)) & 0x0000ffff); */
-               *((s4 *) (ra + 10 * 4)) |=
+               *((s4 *) (ra + 6 * 4)) |=
                        (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
                                   c->index * sizeof(methodptr*)) & 0x0000ffff);
 
                /* synchronize instruction cache */
 
-               md_icacheflush(ra + 10 * 4, 1 * 4);
+               md_icacheflush(ra + 6 * 4, 1 * 4);
        }
 
        return true;
index b8cb836b11912fb8ea320ef0cf36c5ec6365a4f6..56431f5e444546fc207d86f7da61c08dee2a78ab 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: parse.c 7464 2007-03-06 00:26:31Z edwin $
+   $Id: parse.c 7486 2007-03-08 13:50:07Z twisti $
 
 */
 
@@ -1139,6 +1139,8 @@ jsr_tail:
                /* method invocation **************************************************/
 
                case JAVA_INVOKESTATIC:
+                       OP_PREPARE_ZEROFLAGS(opcode);
+
                        i = SUCK_BE_U2(m->jcode + p + 1);
                        mr = class_getconstant(m->class, i, CONSTANT_Methodref);
 
@@ -1153,15 +1155,25 @@ jsr_tail:
 
                        goto invoke_method;
 
-               case JAVA_INVOKEINTERFACE:
+               case JAVA_INVOKESPECIAL:
+                       OP_PREPARE_FLAGS(opcode, INS_FLAG_CHECK);
+
                        i = SUCK_BE_U2(m->jcode + p + 1);
+                       mr = class_getconstant(m->class, i, CONSTANT_Methodref);
+
+                       goto invoke_nonstatic_method;
 
+               case JAVA_INVOKEINTERFACE:
+                       OP_PREPARE_ZEROFLAGS(opcode);
+
+                       i = SUCK_BE_U2(m->jcode + p + 1);
                        mr = class_getconstant(m->class, i, CONSTANT_InterfaceMethodref);
 
                        goto invoke_nonstatic_method;
 
-               case JAVA_INVOKESPECIAL:
                case JAVA_INVOKEVIRTUAL:
+                       OP_PREPARE_ZEROFLAGS(opcode);
+
                        i = SUCK_BE_U2(m->jcode + p + 1);
                        mr = class_getconstant(m->class, i, CONSTANT_Methodref);
 
@@ -1178,7 +1190,6 @@ invoke_nonstatic_method:
 invoke_method:
                        jd->isleafmethod = false;
 
-                       OP_PREPARE_ZEROFLAGS(opcode);
                        iptr->sx.s23.s3.fmiref = mr;
 
                        /* only with -noverify, otherwise the typechecker does this */
@@ -1194,14 +1205,16 @@ invoke_method:
                                if (result == resolveSucceeded) {
                                        methodinfo *mi = iptr->sx.s23.s3.fmiref->p.method;
 
-                                       /* if this call is monomorphic, turn it into an INVOKESPECIAL */
+                                       /* if this call is monomorphic, turn it into an
+                                          INVOKESPECIAL */
 
                                        assert(IS_FMIREF_RESOLVED(iptr->sx.s23.s3.fmiref));
 
                                        if ((iptr->opc == ICMD_INVOKEVIRTUAL)
                                                && (mi->flags & (ACC_FINAL | ACC_PRIVATE)))
                                        {
-                                               iptr->opc = ICMD_INVOKESPECIAL;
+                                               iptr->opc         = ICMD_INVOKESPECIAL;
+                                               iptr->flags.bits |= INS_FLAG_CHECK;
                                        }
                                }
                                else {
index efc5f2a4b1b41391b41c09a66f494fdbb124913f..cecc1034c88c4c4f68fdc644073049f2d62f3f93 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: arch.h 7241 2007-01-27 15:52:01Z twisti $
+   $Id: arch.h 7364 2007-02-15 16:34:45Z twisti $
 
 */
 
 #define SUPPORT_COMBINE_INTEGER_REGISTERS
 
 
+/* branches *******************************************************************/
+
+#define SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER       1
+#define SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER     0
+#define SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS    0
+
+
 /* exceptions *****************************************************************/
 
 #define SUPPORT_HARDWARE_DIVIDE_BY_ZERO  0
index a81f9220bee3c9f0ad1a6f66da0e86f518e1f485..6b4dd2d6d777910d417a7ba6275c4b4a00eeaf09 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: asmpart.S 7225 2007-01-18 12:55:53Z twisti $
+   $Id: asmpart.S 7454 2007-03-05 15:40:48Z tbfg $
 
 */
 
@@ -51,6 +51,7 @@
        .globl asm_vm_call_method_double
 
        .globl asm_vm_call_method_exception_handler
+       .globl asm_vm_call_method_end
 
        .globl asm_call_jit_compiler
 
@@ -679,6 +680,8 @@ L_handle_fda12:
        b       L_register_copy
 #endif
 
+asm_vm_call_method_end:
+       nop
 
 /* asm_call_jit_compiler *******************************************************
 
index 3b9a60d40b0fe68174a6892832520fe8290eeb50..3ddecc3542c93d00ca005bec3cc7129d347fa718 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: codegen.c 7293 2007-02-06 08:58:32Z twisti $
+   $Id: codegen.c 7564 2007-03-23 23:36:17Z twisti $
 
 */
 
@@ -81,7 +81,7 @@
 
 *******************************************************************************/
 
-bool codegen(jitdata *jd)
+bool codegen_emit(jitdata *jd)
 {
        methodinfo         *m;
        codeinfo           *code;
@@ -365,8 +365,8 @@ bool codegen(jitdata *jd)
                }
                else {
                        M_TST(REG_A0);
-                       M_BEQ(0);
-                       codegen_add_nullpointerexception_ref(cd);
+                       M_BNE(1);
+                       M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_NULLPOINTER);
                }
 
                M_AST(REG_A0, REG_SP, s1 * 4);
@@ -787,9 +787,7 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
-                       M_TST(s2);
-                       M_BEQ(0);
-                       codegen_add_arithmeticexception_ref(cd);
+                       emit_arithmetic_check(cd, iptr, s2);
                        M_LDAH(REG_ITMP3, REG_ZERO, 0x8000);
                        M_CMP(REG_ITMP3, s1);
                        M_BNE(3 + (s1 != d));
@@ -806,9 +804,7 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                       M_TST(s2);
-                       M_BEQ(0);
-                       codegen_add_arithmeticexception_ref(cd);
+                       emit_arithmetic_check(cd, iptr, s2);
                        M_LDAH(REG_ITMP3, REG_ZERO, 0x8000);
                        M_CMP(REG_ITMP3, s1);
                        M_BNE(4);
@@ -830,8 +826,8 @@ bool codegen(jitdata *jd)
 
                        s2 = emit_load_s2(jd, iptr, REG_ITMP12_PACKED);
                        M_OR_TST(GET_HIGH_REG(s2), GET_LOW_REG(s2), REG_ITMP3);
-                       M_BEQ(0);
-                       codegen_add_arithmeticexception_ref(cd);
+                       /* XXX could be optimized */
+                       emit_arithmetic_check(cd, iptr, REG_ITMP3);
 
                        disp = dseg_add_functionptr(cd, bte->fp);
                        M_ALD(REG_ITMP3, REG_PV, disp);
@@ -1325,8 +1321,7 @@ bool codegen(jitdata *jd)
                        s2 = emit_load_s2(jd, iptr, REG_FTMP2);
                        M_FCMPU(s1, s2);
                        M_BNAN(1);
-                       M_BEQ(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                       emit_beq(cd, iptr->dst.block);
                        break;
 
                case ICMD_IF_FCMPNE:    /* ..., value, value ==> ...                  */
@@ -1335,10 +1330,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_FTMP1);
                        s2 = emit_load_s2(jd, iptr, REG_FTMP2);
                        M_FCMPU(s1, s2);
-                       M_BNAN(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_BNE(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                       emit_bnan(cd, iptr->dst.block);
+                       emit_bne(cd, iptr->dst.block);
                        break;
 
 
@@ -1348,10 +1341,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_FTMP1);
                        s2 = emit_load_s2(jd, iptr, REG_FTMP2);
                        M_FCMPU(s1, s2);
-                       M_BNAN(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_BLT(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                       emit_bnan(cd, iptr->dst.block);
+                       emit_blt(cd, iptr->dst.block);
                        break;
 
                case ICMD_IF_FCMPL_GT:  /* ..., value, value ==> ...                  */
@@ -1361,8 +1352,7 @@ bool codegen(jitdata *jd)
                        s2 = emit_load_s2(jd, iptr, REG_FTMP2);
                        M_FCMPU(s1, s2);
                        M_BNAN(1);
-                       M_BGT(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                       emit_bgt(cd, iptr->dst.block);
                        break;
 
                case ICMD_IF_FCMPL_LE:  /* ..., value, value ==> ...                  */
@@ -1371,10 +1361,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_FTMP1);
                        s2 = emit_load_s2(jd, iptr, REG_FTMP2);
                        M_FCMPU(s1, s2);
-                       M_BNAN(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_BLE(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                       emit_bnan(cd, iptr->dst.block);
+                       emit_ble(cd, iptr->dst.block);
                        break;
 
                case ICMD_IF_FCMPL_GE:  /* ..., value, value ==> ...                  */
@@ -1384,8 +1372,7 @@ bool codegen(jitdata *jd)
                        s2 = emit_load_s2(jd, iptr, REG_FTMP2);
                        M_FCMPU(s1, s2);
                        M_BNAN(1);
-                       M_BGE(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                       emit_bge(cd, iptr->dst.block);
                        break;
 
                case ICMD_IF_FCMPG_LT:  /* ..., value, value ==> ...                  */
@@ -1395,8 +1382,7 @@ bool codegen(jitdata *jd)
                        s2 = emit_load_s2(jd, iptr, REG_FTMP2);
                        M_FCMPU(s1, s2);
                        M_BNAN(1);
-                       M_BLT(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                       emit_blt(cd, iptr->dst.block);
                        break;
 
                case ICMD_IF_FCMPG_GT:  /* ..., value, value ==> ...                  */
@@ -1405,10 +1391,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_FTMP1);
                        s2 = emit_load_s2(jd, iptr, REG_FTMP2);
                        M_FCMPU(s1, s2);
-                       M_BNAN(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_BGT(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                       emit_bnan(cd, iptr->dst.block);
+                       emit_bgt(cd, iptr->dst.block);
                        break;
 
                case ICMD_IF_FCMPG_LE:  /* ..., value, value ==> ...                  */
@@ -1418,8 +1402,7 @@ bool codegen(jitdata *jd)
                        s2 = emit_load_s2(jd, iptr, REG_FTMP2);
                        M_FCMPU(s1, s2);
                        M_BNAN(1);
-                       M_BLE(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                       emit_ble(cd, iptr->dst.block);
                        break;
 
                case ICMD_IF_FCMPG_GE:  /* ..., value, value ==> ...                  */
@@ -1428,10 +1411,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_FTMP1);
                        s2 = emit_load_s2(jd, iptr, REG_FTMP2);
                        M_FCMPU(s1, s2);
-                       M_BNAN(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_BGE(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                       emit_bnan(cd, iptr->dst.block);
+                       emit_bge(cd, iptr->dst.block);
                        break;
 
 
@@ -1441,7 +1422,7 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                       emit_nullpointer_check(cd, iptr, s1);
+                       /* implicit null-pointer check */
                        M_ILD(d, s1, OFFSET(java_arrayheader, size));
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1451,8 +1432,9 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_IADD_IMM(s2, OFFSET(java_bytearray, data[0]), REG_ITMP2);
+                       /* implicit null-pointer check */
                        M_LBZX(d, s1, REG_ITMP2);
                        M_BSEXT(d, d);
                        emit_store_dst(jd, iptr, d);
@@ -1463,9 +1445,10 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_SLL_IMM(s2, 1, REG_ITMP2);
                        M_IADD_IMM(REG_ITMP2, OFFSET(java_chararray, data[0]), REG_ITMP2);
+                       /* implicit null-pointer check */
                        M_LHZX(d, s1, REG_ITMP2);
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1475,9 +1458,10 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_SLL_IMM(s2, 1, REG_ITMP2);
                        M_IADD_IMM(REG_ITMP2, OFFSET(java_shortarray, data[0]), REG_ITMP2);
+                       /* implicit null-pointer check */
                        M_LHAX(d, s1, REG_ITMP2);
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1487,9 +1471,10 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_SLL_IMM(s2, 2, REG_ITMP2);
                        M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray, data[0]), REG_ITMP2);
+                       /* implicit null-pointer check */
                        M_LWZX(d, s1, REG_ITMP2);
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1499,7 +1484,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_SLL_IMM(s2, 3, REG_ITMP2);
                        M_IADD(s1, REG_ITMP2, REG_ITMP2);
                        M_LLD_INTERN(d, REG_ITMP2, OFFSET(java_longarray, data[0]));
@@ -1511,9 +1497,10 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_SLL_IMM(s2, 2, REG_ITMP2);
                        M_IADD_IMM(REG_ITMP2, OFFSET(java_floatarray, data[0]), REG_ITMP2);
+                       /* implicit null-pointer check */
                        M_LFSX(d, s1, REG_ITMP2);
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1523,9 +1510,10 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_SLL_IMM(s2, 3, REG_ITMP2);
                        M_IADD_IMM(REG_ITMP2, OFFSET(java_doublearray, data[0]), REG_ITMP2);
+                       /* implicit null-pointer check */
                        M_LFDX(d, s1, REG_ITMP2);
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1535,9 +1523,10 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_SLL_IMM(s2, 2, REG_ITMP2);
                        M_IADD_IMM(REG_ITMP2, OFFSET(java_objectarray, data[0]), REG_ITMP2);
+                       /* implicit null-pointer check */
                        M_LWZX(d, s1, REG_ITMP2);
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1547,9 +1536,10 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
                        M_IADD_IMM(s2, OFFSET(java_bytearray, data[0]), REG_ITMP2);
+                       /* implicit null-pointer check */
                        M_STBX(s3, s1, REG_ITMP2);
                        break;
 
@@ -1557,10 +1547,11 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
                        M_SLL_IMM(s2, 1, REG_ITMP2);
                        M_IADD_IMM(REG_ITMP2, OFFSET(java_chararray, data[0]), REG_ITMP2);
+                       /* implicit null-pointer check */
                        M_STHX(s3, s1, REG_ITMP2);
                        break;
 
@@ -1568,10 +1559,11 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
                        M_SLL_IMM(s2, 1, REG_ITMP2);
                        M_IADD_IMM(REG_ITMP2, OFFSET(java_shortarray, data[0]), REG_ITMP2);
+                       /* implicit null-pointer check */
                        M_STHX(s3, s1, REG_ITMP2);
                        break;
 
@@ -1579,10 +1571,11 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
                        M_SLL_IMM(s2, 2, REG_ITMP2);
                        M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray, data[0]), REG_ITMP2);
+                       /* implicit null-pointer check */
                        M_STWX(s3, s1, REG_ITMP2);
                        break;
 
@@ -1590,10 +1583,11 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3_high(jd, iptr, REG_ITMP3);
                        M_SLL_IMM(s2, 3, REG_ITMP2);
                        M_IADD_IMM(REG_ITMP2, OFFSET(java_longarray, data[0]), REG_ITMP2);
+                       /* implicit null-pointer check */
                        M_STWX(s3, s1, REG_ITMP2);
                        M_IADD_IMM(REG_ITMP2, 4, REG_ITMP2);
                        s3 = emit_load_s3_low(jd, iptr, REG_ITMP3);
@@ -1604,10 +1598,11 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_FTMP3);
                        M_SLL_IMM(s2, 2, REG_ITMP2);
                        M_IADD_IMM(REG_ITMP2, OFFSET(java_floatarray, data[0]), REG_ITMP2);
+                       /* implicit null-pointer check */
                        M_STFSX(s3, s1, REG_ITMP2);
                        break;
 
@@ -1615,10 +1610,11 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_FTMP3);
                        M_SLL_IMM(s2, 3, REG_ITMP2);
                        M_IADD_IMM(REG_ITMP2, OFFSET(java_doublearray, data[0]), REG_ITMP2);
+                       /* implicit null-pointer check */
                        M_STFDX(s3, s1, REG_ITMP2);
                        break;
 
@@ -1626,9 +1622,10 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_A0);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_A1);
 
+                       /* XXX what if array is NULL */
                        disp = dseg_add_functionptr(cd, BUILTIN_canstore);
                        M_ALD(REG_ITMP3, REG_PV, disp);
                        M_MTCTR(REG_ITMP3);
@@ -1637,15 +1634,14 @@ bool codegen(jitdata *jd)
                        M_INTMOVE(s3, REG_A1);
 
                        M_JSR;
-                       M_TST(REG_RESULT);
-                       M_BEQ(0);
-                       codegen_add_arraystoreexception_ref(cd);
+                       emit_exception_check(cd, iptr);
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
                        M_SLL_IMM(s2, 2, REG_ITMP2);
                        M_IADD_IMM(REG_ITMP2, OFFSET(java_objectarray, data[0]), REG_ITMP2);
+                       /* implicit null-pointer check */
                        M_STWX(s3, s1, REG_ITMP2);
                        break;
 
@@ -1744,7 +1740,6 @@ bool codegen(jitdata *jd)
                case ICMD_GETFIELD:   /* ...  ==> ..., value                          */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       emit_nullpointer_check(cd, iptr, s1);
 
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
                                uf        = iptr->sx.s23.s3.uf;
@@ -1759,6 +1754,7 @@ bool codegen(jitdata *jd)
                                disp      = fi->offset;
                        }
 
+                       /* implicit null-pointer check */
                        switch (fieldtype) {
                        case TYPE_INT:
                                d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
@@ -1794,7 +1790,6 @@ bool codegen(jitdata *jd)
                case ICMD_PUTFIELD:   /* ..., value  ==> ...                          */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       emit_nullpointer_check(cd, iptr, s1);
 
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
                                uf        = iptr->sx.s23.s3.uf;
@@ -1819,6 +1814,7 @@ bool codegen(jitdata *jd)
                        if (INSTRUCTION_IS_UNRESOLVED(iptr))
                                codegen_addpatchref(cd, PATCHER_get_putfield, uf, 0);
 
+                       /* implicit null-pointer check */
                        switch (fieldtype) {
                        case TYPE_INT:
                                M_IST(s2, s1, disp);
@@ -1875,32 +1871,22 @@ bool codegen(jitdata *jd)
                case ICMD_GOTO:         /* ... ==> ...                                */
                case ICMD_RET:          /* ... ==> ...                                */
 
-                       M_BR(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                       emit_br(cd, iptr->dst.block);
                        ALIGNCODENOP;
                        break;
 
                case ICMD_JSR:          /* ... ==> ...                                */
 
-                       M_BR(0);
-                       codegen_add_branch_ref(cd, iptr->sx.s23.s3.jsrtarget.block);
+                       emit_br(cd, iptr->sx.s23.s3.jsrtarget.block);
                        ALIGNCODENOP;
                        break;
 
                case ICMD_IFNULL:       /* ..., value ==> ...                         */
+               case ICMD_IFNONNULL:
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        M_TST(s1);
-                       M_BEQ(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IFNONNULL:    /* ..., value ==> ...                         */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       M_TST(s1);
-                       M_BNE(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                       emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IFNULL, BRANCH_OPT_NONE);
                        break;
 
                case ICMD_IFLT:
@@ -1917,27 +1903,7 @@ bool codegen(jitdata *jd)
                                ICONST(REG_ITMP2, iptr->sx.val.i);
                                M_CMP(s1, REG_ITMP2);
                        }
-                       switch (iptr->opc) {
-                       case ICMD_IFLT:
-                               M_BLT(0);
-                               break;
-                       case ICMD_IFLE:
-                               M_BLE(0);
-                               break;
-                       case ICMD_IFNE:
-                               M_BNE(0);
-                               break;
-                       case ICMD_IFGT:
-                               M_BGT(0);
-                               break;
-                       case ICMD_IFGE:
-                               M_BGE(0);
-                               break;
-                       case ICMD_IFEQ:
-                               M_BEQ(0);
-                               break;
-                       }
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                       emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IFEQ, BRANCH_OPT_NONE);
                        break;
 
 
@@ -1960,35 +1926,36 @@ bool codegen(jitdata *jd)
                                M_XOR(s2, REG_ITMP3, REG_ITMP2);
                                M_OR_TST(REG_ITMP1, REG_ITMP2, REG_ITMP3);
                        }
-                       M_BEQ(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                       emit_beq(cd, iptr->dst.block);
                        break;
                        
                case ICMD_IF_LLT:       /* ..., value ==> ...                         */
+
                        s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s1_high(jd, iptr, REG_ITMP2);
                        if (iptr->sx.val.l == 0) {
                                /* if high word is less than zero, the whole long is too */
                                M_CMPI(s2, 0);
+                               emit_blt(cd, iptr->dst.block);
                        }
                        else if ((iptr->sx.val.l >= 0) && (iptr->sx.val.l <= 0xffff)) {
                                M_CMPI(s2, 0);
-                               M_BLT(0);
-                               codegen_add_branch_ref(cd, iptr->dst.block);
-                               M_BGT(2);
+                               emit_blt(cd, iptr->dst.block);
+                               emit_label_bgt(cd, BRANCH_LABEL_1);
                                M_CMPUI(s1, iptr->sx.val.l & 0xffff);
+                               emit_blt(cd, iptr->dst.block);
+                               emit_label(cd, BRANCH_LABEL_1);
                        }
                        else {
                                ICONST(REG_ITMP3, iptr->sx.val.l >> 32);
                                M_CMP(s2, REG_ITMP3);
-                               M_BLT(0);
-                               codegen_add_branch_ref(cd, iptr->dst.block);
-                               M_BGT(3);
+                               emit_blt(cd, iptr->dst.block);
+                               emit_label_bgt(cd, BRANCH_LABEL_1);
                                ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
                                M_CMPU(s1, REG_ITMP3);
+                               emit_blt(cd, iptr->dst.block);
+                               emit_label(cd, BRANCH_LABEL_1);
                        }
-                       M_BLT(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
                        break;
                        
                case ICMD_IF_LLE:       /* ..., value ==> ...                         */
@@ -2002,22 +1969,20 @@ bool codegen(jitdata *jd)
 /*                     } else  */
                        if ((iptr->sx.val.l >= 0) && (iptr->sx.val.l <= 0xffff)) {
                                M_CMPI(s2, 0);
-                               M_BLT(0);
-                               codegen_add_branch_ref(cd, iptr->dst.block);
-                               M_BGT(2);
+                               emit_blt(cd, iptr->dst.block);
+                               emit_label_bgt(cd, BRANCH_LABEL_1);
                                M_CMPUI(s1, iptr->sx.val.l & 0xffff);
                        }
                        else {
                                ICONST(REG_ITMP3, iptr->sx.val.l >> 32);
                                M_CMP(s2, REG_ITMP3);
-                               M_BLT(0);
-                               codegen_add_branch_ref(cd, iptr->dst.block);
-                               M_BGT(3);
+                               emit_blt(cd, iptr->dst.block);
+                               emit_label_bgt(cd, BRANCH_LABEL_1);
                                ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
                                M_CMPU(s1, REG_ITMP3);
                        }
-                       M_BLE(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                       emit_ble(cd, iptr->dst.block);
+                       emit_label(cd, BRANCH_LABEL_1);
                        break;
                        
                case ICMD_IF_LNE:       /* ..., value ==> ...                         */
@@ -2039,8 +2004,7 @@ bool codegen(jitdata *jd)
                                M_XOR(s2, REG_ITMP3, REG_ITMP2);
                                M_OR_TST(REG_ITMP1, REG_ITMP2, REG_ITMP3);
                        }
-                       M_BNE(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                       emit_bne(cd, iptr->dst.block);
                        break;
                        
                case ICMD_IF_LGT:       /* ..., value ==> ...                         */
@@ -2054,22 +2018,20 @@ bool codegen(jitdata *jd)
 /*                     } else  */
                        if ((iptr->sx.val.l >= 0) && (iptr->sx.val.l <= 0xffff)) {
                                M_CMPI(s2, 0);
-                               M_BGT(0);
-                               codegen_add_branch_ref(cd, iptr->dst.block);
-                               M_BLT(2);
+                               emit_bgt(cd, iptr->dst.block);
+                               emit_label_blt(cd, BRANCH_LABEL_1);
                                M_CMPUI(s1, iptr->sx.val.l & 0xffff);
                        }
                        else {
                                ICONST(REG_ITMP3, iptr->sx.val.l >> 32);
                                M_CMP(s2, REG_ITMP3);
-                               M_BGT(0);
-                               codegen_add_branch_ref(cd, iptr->dst.block);
-                               M_BLT(3);
+                               emit_bgt(cd, iptr->dst.block);
+                               emit_label_blt(cd, BRANCH_LABEL_1);
                                ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
                                M_CMPU(s1, REG_ITMP3);
                        }
-                       M_BGT(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                       emit_bgt(cd, iptr->dst.block);
+                       emit_label(cd, BRANCH_LABEL_1);
                        break;
                        
                case ICMD_IF_LGE:       /* ..., value ==> ...                         */
@@ -2079,35 +2041,48 @@ bool codegen(jitdata *jd)
                        if (iptr->sx.val.l == 0) {
                                /* if high word is greater equal zero, the whole long is too */
                                M_CMPI(s2, 0);
+                               emit_bge(cd, iptr->dst.block);
                        }
                        else if ((iptr->sx.val.l >= 0) && (iptr->sx.val.l <= 0xffff)) {
                                M_CMPI(s2, 0);
-                               M_BGT(0);
-                               codegen_add_branch_ref(cd, iptr->dst.block);
-                               M_BLT(2);
+                               emit_bgt(cd, iptr->dst.block);
+                               emit_label_blt(cd, BRANCH_LABEL_1);
                                M_CMPUI(s1, iptr->sx.val.l & 0xffff);
+                               emit_bge(cd, iptr->dst.block);
+                               emit_label(cd, BRANCH_LABEL_1);
                        }
                        else {
                                ICONST(REG_ITMP3, iptr->sx.val.l >> 32);
                                M_CMP(s2, REG_ITMP3);
-                               M_BGT(0);
-                               codegen_add_branch_ref(cd, iptr->dst.block);
-                               M_BLT(3);
+                               emit_bgt(cd, iptr->dst.block);
+                               emit_label_blt(cd, BRANCH_LABEL_1);
                                ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
                                M_CMPU(s1, REG_ITMP3);
+                               emit_bge(cd, iptr->dst.block);
+                               emit_label(cd, BRANCH_LABEL_1);
                        }
-                       M_BGE(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
                        break;
 
                case ICMD_IF_ICMPEQ:    /* ..., value, value ==> ...                  */
+               case ICMD_IF_ICMPNE:
+               case ICMD_IF_ICMPLT:
+               case ICMD_IF_ICMPGT:
+               case ICMD_IF_ICMPLE:
+               case ICMD_IF_ICMPGE:
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+                       M_CMP(s1, s2);
+                       emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IF_ICMPEQ, BRANCH_OPT_NONE);
+                       break;
+
                case ICMD_IF_ACMPEQ:    /* op1 = target JavaVM pc                     */
+               case ICMD_IF_ACMPNE:
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_CMP(s1, s2);
-                       M_BEQ(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                       emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IF_ACMPEQ, BRANCH_OPT_NONE);
                        break;
 
                case ICMD_IF_LCMPEQ:    /* ..., value, value ==> ...                  */
@@ -2115,23 +2090,12 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
                        M_CMP(s1, s2);
-                       /* load low-bits before the branch, so we know the distance */
+                       emit_label_bne(cd, BRANCH_LABEL_1);
                        s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
-                       M_BNE(2);
                        M_CMP(s1, s2);
-                       M_BEQ(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IF_ICMPNE:    /* ..., value, value ==> ...                  */
-               case ICMD_IF_ACMPNE:    /* op1 = target JavaVM pc                     */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       M_CMP(s1, s2);
-                       M_BNE(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                       emit_beq(cd, iptr->dst.block);
+                       emit_label(cd, BRANCH_LABEL_1);
                        break;
 
                case ICMD_IF_LCMPNE:    /* ..., value, value ==> ...                  */
@@ -2139,22 +2103,11 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
                        M_CMP(s1, s2);
-                       M_BNE(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                       emit_bne(cd, iptr->dst.block);
                        s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
                        M_CMP(s1, s2);
-                       M_BNE(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IF_ICMPLT:    /* ..., value, value ==> ...                  */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       M_CMP(s1, s2);
-                       M_BLT(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                       emit_bne(cd, iptr->dst.block);
                        break;
 
                case ICMD_IF_LCMPLT:    /* ..., value, value ==> ...                  */
@@ -2162,24 +2115,13 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
                        M_CMP(s1, s2);
-                       M_BLT(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       /* load low-bits before the branch, so we know the distance */
+                       emit_blt(cd, iptr->dst.block);
+                       emit_label_bgt(cd, BRANCH_LABEL_1);
                        s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
-                       M_BGT(2);
                        M_CMPU(s1, s2);
-                       M_BLT(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IF_ICMPGT:    /* ..., value, value ==> ...                  */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       M_CMP(s1, s2);
-                       M_BGT(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                       emit_blt(cd, iptr->dst.block);
+                       emit_label(cd, BRANCH_LABEL_1);
                        break;
 
                case ICMD_IF_LCMPGT:    /* ..., value, value ==> ...                  */
@@ -2187,24 +2129,13 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
                        M_CMP(s1, s2);
-                       M_BGT(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       /* load low-bits before the branch, so we know the distance */  
+                       emit_bgt(cd, iptr->dst.block);
+                       emit_label_blt(cd, BRANCH_LABEL_1);
                        s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
-                       M_BLT(2);
                        M_CMPU(s1, s2);
-                       M_BGT(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IF_ICMPLE:    /* ..., value, value ==> ...                  */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       M_CMP(s1, s2);
-                       M_BLE(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                       emit_bgt(cd, iptr->dst.block);
+                       emit_label(cd, BRANCH_LABEL_1);
                        break;
 
                case ICMD_IF_LCMPLE:    /* ..., value, value ==> ...                  */
@@ -2212,24 +2143,13 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
                        M_CMP(s1, s2);
-                       M_BLT(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       /* load low-bits before the branch, so we know the distance */
+                       emit_blt(cd, iptr->dst.block);
+                       emit_label_bgt(cd, BRANCH_LABEL_1);
                        s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
-                       M_BGT(2);
                        M_CMPU(s1, s2);
-                       M_BLE(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IF_ICMPGE:    /* ..., value, value ==> ...                  */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       M_CMP(s1, s2);
-                       M_BGE(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                       emit_ble(cd, iptr->dst.block);
+                       emit_label(cd, BRANCH_LABEL_1);
                        break;
 
                case ICMD_IF_LCMPGE:    /* ..., value, value ==> ...                  */
@@ -2237,15 +2157,13 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
                        M_CMP(s1, s2);
-                       M_BGT(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       /* load low-bits before the branch, so we know the distance */
+                       emit_bgt(cd, iptr->dst.block);
+                       emit_label_blt(cd, BRANCH_LABEL_1);
                        s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
-                       M_BLT(2);
                        M_CMPU(s1, s2);
-                       M_BGE(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                       emit_bge(cd, iptr->dst.block);
+                       emit_label(cd, BRANCH_LABEL_1);
                        break;
 
                case ICMD_IRETURN:      /* ..., retvalue ==> ...                      */
@@ -2401,8 +2319,7 @@ nowperformreturn:
                        /* range check */
 
                        M_CMPUI(REG_ITMP1, i - 1);
-                       M_BGT(0);
-                       codegen_add_branch_ref(cd, table[0].block);
+                       emit_bgt(cd, table[0].block);
 
                        /* build jump table top down and use address of lowest entry */
 
@@ -2446,14 +2363,11 @@ nowperformreturn:
                                        M_ILD(REG_ITMP2, REG_PV, disp);
                                        M_CMP(s1, REG_ITMP2);
                                }
-                               M_BEQ(0);
-                               codegen_add_branch_ref(cd, lookup->target.block); 
+                               emit_beq(cd, lookup->target.block);
                                lookup++;
                        }
 
-                       M_BR(0);
-                       codegen_add_branch_ref(cd, iptr->sx.s23.s3.lookupdefault.block);
-
+                       emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
                        ALIGNCODENOP;
                        break;
                        }
@@ -2545,12 +2459,22 @@ gen_method:
                                disp = dseg_add_functionptr(cd, bte->fp);
 
                                M_ALD(REG_PV, REG_PV, disp);  /* pointer to built-in-function */
+
+                               /* generate the actual call */
+
+                               M_MTCTR(REG_PV);
+                               M_JSR;
+                               REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
+                               disp = (s4) (cd->mcodeptr - cd->mcodebase);
+                               M_MFLR(REG_ITMP1);
+                               M_LDA(REG_PV, REG_ITMP1, -disp);
+
+                               emit_exception_check(cd, iptr);
                                break;
 
                        case ICMD_INVOKESPECIAL:
                                emit_nullpointer_check(cd, iptr, REG_A0);
-                               M_ILD(REG_ITMP1, REG_A0, 0); /* hardware nullptr   */
-                               /* fall through */
+                               /* fall-through */
 
                        case ICMD_INVOKESTATIC:
                                if (lm == NULL) {
@@ -2563,11 +2487,18 @@ gen_method:
                                        disp = dseg_add_address(cd, lm->stubroutine);
 
                                M_ALD(REG_PV, REG_PV, disp);
+
+                               /* generate the actual call */
+
+                               M_MTCTR(REG_PV);
+                               M_JSR;
+                               REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
+                               disp = (s4) (cd->mcodeptr - cd->mcodebase);
+                               M_MFLR(REG_ITMP1);
+                               M_LDA(REG_PV, REG_ITMP1, -disp);
                                break;
 
                        case ICMD_INVOKEVIRTUAL:
-                               emit_nullpointer_check(cd, iptr, REG_A0);
-
                                if (lm == NULL) {
                                        codegen_addpatchref(cd, PATCHER_invokevirtual, um, 0);
 
@@ -2578,13 +2509,21 @@ gen_method:
                                                sizeof(methodptr) * lm->vftblindex;
                                }
 
+                               /* implicit null-pointer check */
                                M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_objectheader, vftbl));
                                M_ALD(REG_PV, REG_METHODPTR, s1);
+
+                               /* generate the actual call */
+
+                               M_MTCTR(REG_PV);
+                               M_JSR;
+                               REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
+                               disp = (s4) (cd->mcodeptr - cd->mcodebase);
+                               M_MFLR(REG_ITMP1);
+                               M_LDA(REG_PV, REG_ITMP1, -disp);
                                break;
 
                        case ICMD_INVOKEINTERFACE:
-                               emit_nullpointer_check(cd, iptr, REG_A0);
-
                                if (lm == NULL) {
                                        codegen_addpatchref(cd, PATCHER_invokeinterface, um, 0);
 
@@ -2598,27 +2537,20 @@ gen_method:
                                        s2 = sizeof(methodptr) * (lm - lm->class->methods);
                                }
 
+                               /* implicit null-pointer check */
                                M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_objectheader, vftbl));
                                M_ALD(REG_METHODPTR, REG_METHODPTR, s1);
                                M_ALD(REG_PV, REG_METHODPTR, s2);
-                               break;
-                       }
 
-                       /* generate the actual call */
+                               /* generate the actual call */
 
-                       M_MTCTR(REG_PV);
-                       M_JSR;
-                       REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
-                       disp = (s4) (cd->mcodeptr - cd->mcodebase);
-                       M_MFLR(REG_ITMP1);
-                       M_LDA(REG_PV, REG_ITMP1, -disp);
-                       
-                       /* actually only used for ICMD_BUILTIN */
-
-                       if (INSTRUCTION_MUST_CHECK(iptr)) {
-                               M_CMPI(REG_RESULT, 0);
-                               M_BEQ(0);
-                               codegen_add_fillinstacktrace_ref(cd);
+                               M_MTCTR(REG_PV);
+                               M_JSR;
+                               REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
+                               disp = (s4) (cd->mcodeptr - cd->mcodebase);
+                               M_MFLR(REG_ITMP1);
+                               M_LDA(REG_PV, REG_ITMP1, -disp);
+                               break;
                        }
 
                        /* store return value */
@@ -2668,37 +2600,25 @@ gen_method:
                                s4         superindex;
 
                                if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
-                                       super = NULL;
+                                       super      = NULL;
                                        superindex = 0;
                                }
                                else {
-                                       super = iptr->sx.s23.s3.c.cls;
+                                       super      = iptr->sx.s23.s3.c.cls;
                                        superindex = super->index;
                                }
-                       
+
 #if defined(ENABLE_THREADS)
                                codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
 #endif
 
                                s1 = emit_load_s1(jd, iptr, REG_ITMP1);
 
-                               /* calculate interface checkcast code size */
-
-                               s2 = 7;
-                               if (super == NULL)
-                                       s2 += (opt_shownops ? 1 : 0);
-
-                               /* calculate class checkcast code size */
-
-                               s3 = 8 + (s1 == REG_ITMP1);
-                               if (super == NULL)
-                                       s3 += (opt_shownops ? 1 : 0);
-
                                /* if class is not resolved, check which code to call */
 
                                if (super == NULL) {
                                        M_TST(s1);
-                                       M_BEQ(3 + (opt_shownops ? 1 : 0) + s2 + 1 + s3);
+                                       emit_label_beq(cd, BRANCH_LABEL_1);
 
                                        disp = dseg_add_unique_s4(cd, 0);         /* super->flags */
 
@@ -2709,7 +2629,7 @@ gen_method:
 
                                        M_ILD(REG_ITMP2, REG_PV, disp);
                                        M_AND_IMM(REG_ITMP2, ACC_INTERFACE, REG_ITMP2);
-                                       M_BEQ(s2 + 1);
+                                       emit_label_beq(cd, BRANCH_LABEL_2);
                                }
 
                                /* interface checkcast code */
@@ -2717,35 +2637,38 @@ gen_method:
                                if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
                                        if (super == NULL) {
                                                codegen_addpatchref(cd,
-                                                                                       PATCHER_checkcast_instanceof_interface,
+                                                                                       PATCHER_checkcast_interface,
                                                                                        iptr->sx.s23.s3.c.ref,
                                                                                        0);
                                        }
                                        else {
                                                M_TST(s1);
-                                               M_BEQ(s2);
+                                               emit_label_beq(cd, BRANCH_LABEL_3);
                                        }
 
                                        M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
                                        M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
                                        M_LDATST(REG_ITMP3, REG_ITMP3, -superindex);
-                                       M_BLE(0);
-                                       codegen_add_classcastexception_ref(cd, s1);
+                                       emit_classcast_check(cd, iptr, BRANCH_LE, REG_ITMP3, s1);
+
                                        M_ALD(REG_ITMP3, REG_ITMP2,
                                                  OFFSET(vftbl_t, interfacetable[0]) -
                                                  superindex * sizeof(methodptr*));
                                        M_TST(REG_ITMP3);
-                                       M_BEQ(0);
-                                       codegen_add_classcastexception_ref(cd, s1);
+                                       emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ITMP3, s1);
 
                                        if (super == NULL)
-                                               M_BR(s3);
+                                               emit_label_br(cd, BRANCH_LABEL_4);
+                                       else
+                                               emit_label(cd, BRANCH_LABEL_3);
                                }
 
                                /* class checkcast code */
 
                                if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
                                        if (super == NULL) {
+                                               emit_label(cd, BRANCH_LABEL_2);
+
                                                disp = dseg_add_unique_address(cd, NULL);
 
                                                codegen_addpatchref(cd, PATCHER_resolve_classref_to_vftbl,
@@ -2756,7 +2679,7 @@ gen_method:
                                                disp = dseg_add_address(cd, super->vftbl);
 
                                                M_TST(s1);
-                                               M_BEQ(s3);
+                                               emit_label_beq(cd, BRANCH_LABEL_5);
                                        }
 
                                        M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
@@ -2772,7 +2695,8 @@ gen_method:
                                                codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
 #endif
                                                M_ISUB(REG_ITMP3, REG_ITMP1, REG_ITMP3);
-                                       } else {
+                                       }
+                                       else {
                                                M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
                                                M_ISUB(REG_ITMP3, REG_ITMP2, REG_ITMP3);
                                                M_ALD(REG_ITMP2, REG_PV, disp);
@@ -2782,9 +2706,17 @@ gen_method:
 #endif
                                        }
                                        M_CMPU(REG_ITMP3, REG_ITMP2);
-                                       M_BGT(0);
-                                       codegen_add_classcastexception_ref(cd, s1);
+                                       emit_classcast_check(cd, iptr, BRANCH_GT, REG_ITMP3, s1);
+
+                                       if (super != NULL)
+                                               emit_label(cd, BRANCH_LABEL_5);
                                }
+
+                               if (super == NULL) {
+                                       emit_label(cd, BRANCH_LABEL_1);
+                                       emit_label(cd, BRANCH_LABEL_4);
+                               }
+
                                d = codegen_reg_of_dst(jd, iptr, s1);
                        }
                        else {
@@ -2809,8 +2741,7 @@ gen_method:
                                M_MTCTR(REG_ITMP2);
                                M_JSR;
                                M_TST(REG_RESULT);
-                               M_BEQ(0);
-                               codegen_add_classcastexception_ref(cd, s1);
+                               emit_classcast_check(cd, iptr, BRANCH_EQ, REG_RESULT, s1);
 
                                s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                                d = codegen_reg_of_dst(jd, iptr, s1);
@@ -2840,43 +2771,32 @@ gen_method:
                        s4         superindex;
 
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
-                               super = NULL;
+                               super      = NULL;
                                superindex = 0;
                        }
                        else {
-                               super = iptr->sx.s23.s3.c.cls;
+                               super      = iptr->sx.s23.s3.c.cls;
                                superindex = super->index;
                        }
                        
 #if defined(ENABLE_THREADS)
-            codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
+                       codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
 #endif
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
                        if (s1 == d) {
                                M_MOV(s1, REG_ITMP1);
                                s1 = REG_ITMP1;
                        }
 
-                       /* calculate interface instanceof code size */
-
-                       s2 = 8;
-                       if (super == NULL)
-                               s2 += (opt_shownops ? 1 : 0);
-
-                       /* calculate class instanceof code size */
-
-                       s3 = 10;
-                       if (super == NULL)
-                               s3 += (opt_shownops ? 1 : 0);
-
                        M_CLR(d);
 
                        /* if class is not resolved, check which code to call */
 
                        if (super == NULL) {
                                M_TST(s1);
-                               M_BEQ(3 + (opt_shownops ? 1 : 0) + s2 + 1 + s3);
+                               emit_label_beq(cd, BRANCH_LABEL_1);
 
                                disp = dseg_add_unique_s4(cd, 0);             /* super->flags */
 
@@ -2885,7 +2805,7 @@ gen_method:
 
                                M_ILD(REG_ITMP3, REG_PV, disp);
                                M_AND_IMM(REG_ITMP3, ACC_INTERFACE, REG_ITMP3);
-                               M_BEQ(s2 + 1);
+                               emit_label_beq(cd, BRANCH_LABEL_2);
                        }
 
                        /* interface instanceof code */
@@ -2893,12 +2813,12 @@ gen_method:
                        if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
                                if (super == NULL) {
                                        codegen_addpatchref(cd,
-                                                                               PATCHER_checkcast_instanceof_interface,
+                                                                               PATCHER_instanceof_interface,
                                                                                iptr->sx.s23.s3.c.ref, 0);
                                }
                                else {
                                        M_TST(s1);
-                                       M_BEQ(s2);
+                                       emit_label_beq(cd, BRANCH_LABEL_3);
                                }
 
                                M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
@@ -2913,13 +2833,17 @@ gen_method:
                                M_IADD_IMM(REG_ZERO, 1, d);
 
                                if (super == NULL)
-                                       M_BR(s3);
+                                       emit_label_br(cd, BRANCH_LABEL_4);
+                               else
+                                       emit_label(cd, BRANCH_LABEL_3);
                        }
 
                        /* class instanceof code */
 
                        if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
                                if (super == NULL) {
+                                       emit_label(cd, BRANCH_LABEL_2);
+
                                        disp = dseg_add_unique_address(cd, NULL);
 
                                        codegen_addpatchref(cd, PATCHER_resolve_classref_to_vftbl,
@@ -2930,7 +2854,7 @@ gen_method:
                                        disp = dseg_add_address(cd, super->vftbl);
 
                                        M_TST(s1);
-                                       M_BEQ(s3);
+                                       emit_label_beq(cd, BRANCH_LABEL_5);
                                }
 
                                M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
@@ -2949,7 +2873,16 @@ gen_method:
                                M_CLR(d);
                                M_BGT(1);
                                M_IADD_IMM(REG_ZERO, 1, d);
+
+                               if (super != NULL)
+                                       emit_label(cd, BRANCH_LABEL_5);
                        }
+
+                       if (super == NULL) {
+                               emit_label(cd, BRANCH_LABEL_1);
+                               emit_label(cd, BRANCH_LABEL_4);
+                       }
+
                        emit_store_dst(jd, iptr, d);
                        }
                        break;
@@ -3010,9 +2943,7 @@ gen_method:
 
                        /* check for exception before result assignment */
 
-                       M_CMPI(REG_RESULT, 0);
-                       M_BEQ(0);
-                       codegen_add_fillinstacktrace_ref(cd);
+                       emit_exception_check(cd, iptr);
 
                        d = codegen_reg_of_dst(jd, iptr, REG_RESULT);
                        M_INTMOVE(REG_RESULT, d);
@@ -3034,12 +2965,9 @@ gen_method:
 
        /* generate stubs */
 
-       emit_exception_stubs(jd);
        emit_patcher_stubs(jd);
        REPLACEMENT_EMIT_STUBS(jd);
 
-       codegen_finish(jd);
-
        /* everything's ok */
 
        return true;
index 1b6a3f82257c689f78428265624d2f95077bf1a5..fdfbae8953ffffce2120002a3400876f93f39b24 100644 (file)
@@ -1,7 +1,7 @@
 /* src/vm/jit/powerpc/codegen.h - code generation macros and definitions for
                                   32-bit PowerPC
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
    J. Wenninger, Institut f. Computersprachen - TU Wien
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Andreas Krall
-            Stefan Ring
-            Christian Thalinger
-            Christian Ullrich
-
-   $Id: codegen.h 6078 2006-11-28 22:19:16Z twisti $
+   $Id: codegen.h 7592 2007-03-28 20:12:33Z twisti $
 
 */
 
 
 #define BRANCH_NOPS \
     do { \
-        M_NOP; \
+        if (CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) { \
+            M_NOP; \
+            M_NOP; \
+        } \
+        else { \
+            M_NOP; \
+        } \
     } while (0)
 
 
         cd->mcodeptr += 4; \
     } while (0)
 
+#define M_OP3_GET_A(x)                (((x) >> 16) & 0x1f  )
+#define M_OP3_GET_B(x)                (((x) >> 11) & 0x1f  )
+
+
 #define M_OP4(x,y,rc,d,a,b,c) \
     do { \
         *((u4 *) cd->mcodeptr) = (((x) << 26) | ((d) << 21) | ((a) << 16) | ((b) << 11) | ((c) << 6) | ((y) << 1) | (rc)); \
         cd->mcodeptr += 4; \
     } while (0)
 
+
 #define M_OP2_IMM(x,d,a,i) \
     do { \
         *((u4 *) cd->mcodeptr) = (((x) << 26) | ((d) << 21) | ((a) << 16) | ((i) & 0xffff)); \
         cd->mcodeptr += 4; \
     } while (0)
 
+#define M_INSTR_OP2_IMM_D(x)            (((x) >> 21) & 0x1f  )
+#define M_INSTR_OP2_IMM_A(x)            (((x) >> 16) & 0x1f  )
+#define M_INSTR_OP2_IMM_I(x)            ( (x)        & 0xffff)
+
+
 #define M_BMASK     0x03fffffc                      /* (((1 << 26) - 1) & ~3) */
 #define M_BCMASK    0x0000fffc                      /* (((1 << 16) - 1) & ~3) */
 
 #define M_STWUX(a,b,c)                  M_OP3(31,183,0,0,a,b,c)
 
 #define M_LDAH(a,b,c)                   M_ADDIS(b, c, a)
+
 #define M_TRAP                          M_OP3(31, 4, 0, 0, 31, 0, 0)
+#define M_TRAPGEU(a,b)                  M_OP3(31, 4, 0, 0, 5, a, b)
 
 #define M_NOP                           M_OR_IMM(0, 0, 0)
 #define M_MOV(a,b)                      M_OR(a, a, b)
index c90f8d8bea1c947be76cf63d39f6929fecb51b9d..955979fc39165442943a7e76082a2c4b58d2bd5a 100644 (file)
@@ -26,9 +26,7 @@
 
    Authors: Christian Thalinger
 
-   Changes:
-
-   $Id: md-os.c 6123 2006-12-05 21:10:54Z twisti $
+   $Id: md-os.c 6186 2006-12-12 22:35:31Z twisti $
 
 */
 
@@ -41,6 +39,7 @@
 
 #include "vm/types.h"
 
+#include "vm/jit/powerpc/codegen.h"
 #include "vm/jit/powerpc/darwin/md-abi.h"
 
 #include "vm/exceptions.h"
@@ -63,72 +62,47 @@ void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
        ucontext_t         *_uc;
        mcontext_t          _mc;
        ppc_thread_state_t *_ss;
-       ptrint             *gregs;
-       u4                  instr;
-       s4                  reg;
-       s4                  disp;
-       ptrint              addr;
        u1                 *pv;
        u1                 *sp;
        u1                 *ra;
        u1                 *xpc;
-       stackframeinfo      sfi;
-       java_objectheader  *o;
+       u4                  mcode;
+       s4                  s1;
+       s4                  disp;
+       s4                  d;
+       ptrint             *gregs;
+       ptrint              addr;
+       ptrint              val;
+       java_objectheader  *e;
 
        _uc = (ucontext_t *) _p;
        _mc = _uc->uc_mcontext;
        _ss = &_mc->ss;
 
-       /* check for NullPointerException */
-
-       gregs = &_ss->r0;
-
-       instr = *((u4 *) _ss->srr0);
-       reg   = (instr >> 16) & 31;
-       disp  = (instr & 0xffff);
-       addr  = gregs[reg];
+       /* get register values */
 
        pv  = (u1 *) _ss->r13;
        sp  = (u1 *) _ss->r1;
        ra  = (u1 *) _ss->lr;                    /* this is correct for leafs */
        xpc = (u1 *) _ss->srr0;
 
-       /* create stackframeinfo */
-
-       stacktrace_create_extern_stackframeinfo(&sfi, pv, sp, ra, xpc);
-
-       if (reg == REG_ZERO) {
-               switch (disp) {
-               case EXCEPTION_LOAD_DISP_ARITHMETIC:
-                       vm_abort("ArithmeticException");
-                       break;
-               case EXCEPTION_LOAD_DISP_ARRAYINDEXOUTOFBOUNDS:
-                       log_println("ArrayIndexOutOfBoundsException");
-                       o = new_arrayindexoutofboundsexception(0);
-                       break;
-               case EXCEPTION_LOAD_DISP_CLASSCAST:
-                       vm_abort("ClassCastException");
-                       break;
-               default:
-                       vm_abort("unknown exception %d", disp);
-               }
-       }
-       else if (addr == 0) {
-               o = exceptions_new_nullpointerexception();
-       }
-       else {
-               codegen_get_pv_from_pc(xpc);
-
-               /* this should not happen */
-
-               assert(0);
-       }
-
-       /* remove stackframeinfo */
-
-       stacktrace_remove_stackframeinfo(&sfi);
-
-       _ss->r11  = (ptrint) o;
+       /* get exception-throwing instruction */
+
+       mcode = *((u4 *) xpc);
+
+       s1   = M_INSTR_OP2_IMM_A(mcode);
+       disp = M_INSTR_OP2_IMM_I(mcode);
+       d    = M_INSTR_OP2_IMM_D(mcode);
+
+       gregs = &_ss->r0;
+       addr  = gregs[s1];
+       val   = gregs[d];
+
+       e = exceptions_new_hardware_exception(pv, sp, ra, xpc, s1, disp, addr, val);
+
+       /* set registers */
+
+       _ss->r11  = (ptrint) e;
        _ss->r12  = (ptrint) xpc;
        _ss->srr0 = (ptrint) asm_handle_exception;
 }
index 6c149ff173de2fb2214b5b5c6e792c7707b109b3..1b77a9f0c67591444869a5e9546ba3529b8e3652 100644 (file)
@@ -47,6 +47,7 @@
 #include "vm/exceptions.h"
 
 #include "vm/jit/asmpart.h"
+#include "vm/jit/codegen-common.h"
 #include "vm/jit/dseg.h"
 #include "vm/jit/emit-common.h"
 #include "vm/jit/jit.h"
@@ -294,137 +295,201 @@ void emit_iconst(codegendata *cd, s4 d, s4 value)
 }
 
 
-/* emit_nullpointer_check ******************************************************
+/* emit_branch *****************************************************************
 
-   Emit a NullPointerException check.
+   Emits the code for conditional and unconditional branchs.
 
 *******************************************************************************/
 
-void emit_nullpointer_check(codegendata *cd, instruction *iptr, s4 reg)
+void emit_branch(codegendata *cd, s4 disp, s4 condition, s4 reg, u4 opt)
 {
-       if (INSTRUCTION_MUST_CHECK(iptr)) {
-               M_TST(reg);
-               M_BEQ(0);
-               codegen_add_nullpointerexception_ref(cd);
-       }
-}
+       s4 checkdisp;
+       s4 branchdisp;
 
+       /* calculate the different displacements */
 
-/* emit_arrayindexoutofbounds_check ********************************************
+       checkdisp  =  disp + 4;
+       branchdisp = (disp - 4) >> 2;
 
-   Emit a ArrayIndexOutOfBoundsException check.
+       /* check which branch to generate */
 
-*******************************************************************************/
+       if (condition == BRANCH_UNCONDITIONAL) {
+               /* check displacement for overflow */
 
-void emit_arrayindexoutofbounds_check(codegendata *cd, instruction *iptr, s4 s1, s4 s2)
-{
-       if (INSTRUCTION_MUST_CHECK(iptr)) {
-               M_ILD(REG_ITMP3, s1, OFFSET(java_arrayheader, size));
-               M_CMPU(s2, REG_ITMP3);
-               M_BGE(0);
-               codegen_add_arrayindexoutofboundsexception_ref(cd, s2);
-       }
-}
+               if ((checkdisp < (s4) 0xfe000000) || (checkdisp > (s4) 0x01fffffc)) {
+                       /* if the long-branches flag isn't set yet, do it */
 
+                       if (!CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
+                               cd->flags |= (CODEGENDATA_FLAG_ERROR |
+                                                         CODEGENDATA_FLAG_LONGBRANCHES);
+                       }
 
-/* emit_exception_stubs ********************************************************
+                       vm_abort("emit_branch: emit unconditional long-branch code");
+               }
+               else {
+                       M_BR(branchdisp);
+               }
+       }
+       else {
+               /* and displacement for overflow */
 
-   Generates the code for the exception stubs.
+               if ((checkdisp < (s4) 0xffff8000) || (checkdisp > (s4) 0x00007fff)) {
+                       /* if the long-branches flag isn't set yet, do it */
 
-*******************************************************************************/
+                       if (!CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
+                               cd->flags |= (CODEGENDATA_FLAG_ERROR |
+                                                         CODEGENDATA_FLAG_LONGBRANCHES);
+                       }
 
-void emit_exception_stubs(jitdata *jd)
-{
-       codegendata  *cd;
-       registerdata *rd;
-       exceptionref *er;
-       s4            branchmpc;
-       s4            targetmpc;
-       s4            targetdisp;
-       s4            disp;
+                       switch (condition) {
+                       case BRANCH_EQ:
+                               M_BNE(1);
+                               M_BR(branchdisp);
+                               break;
+                       case BRANCH_NE:
+                               M_BEQ(1);
+                               M_BR(branchdisp);
+                               break;
+                       case BRANCH_LT:
+                               M_BGE(1);
+                               M_BR(branchdisp);
+                               break;
+                       case BRANCH_GE:
+                               M_BLT(1);
+                               M_BR(branchdisp);
+                               break;
+                       case BRANCH_GT:
+                               M_BLE(1);
+                               M_BR(branchdisp);
+                               break;
+                       case BRANCH_LE:
+                               M_BGT(1);
+                               M_BR(branchdisp);
+                               break;
+                       case BRANCH_NAN:
+                               vm_abort("emit_branch: long BRANCH_NAN");
+                               break;
+                       default:
+                               vm_abort("emit_branch: unknown condition %d", condition);
+                       }
+               }
+               else {
+                       switch (condition) {
+                       case BRANCH_EQ:
+                               M_BEQ(branchdisp);
+                               break;
+                       case BRANCH_NE:
+                               M_BNE(branchdisp);
+                               break;
+                       case BRANCH_LT:
+                               M_BLT(branchdisp);
+                               break;
+                       case BRANCH_GE:
+                               M_BGE(branchdisp);
+                               break;
+                       case BRANCH_GT:
+                               M_BGT(branchdisp);
+                               break;
+                       case BRANCH_LE:
+                               M_BLE(branchdisp);
+                               break;
+                       case BRANCH_NAN:
+                               M_BNAN(branchdisp);
+                               break;
+                       default:
+                               vm_abort("emit_branch: unknown condition %d", condition);
+                       }
+               }
+       }
+}
 
-       /* get required compiler data */
 
-       cd = jd->cd;
-       rd = jd->rd;
+/* emit_arithmetic_check *******************************************************
 
-       /* generate exception stubs */
+   Emit an ArithmeticException check.
 
-       targetdisp = 0;
+*******************************************************************************/
 
-       for (er = cd->exceptionrefs; er != NULL; er = er->next) {
-               /* back-patch the branch to this exception code */
+void emit_arithmetic_check(codegendata *cd, instruction *iptr, s4 reg)
+{
+       if (INSTRUCTION_MUST_CHECK(iptr)) {
+               M_TST(reg);
+               M_BNE(1);
+               M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_ARITHMETIC);
+       }
+}
 
-               branchmpc = er->branchpos;
-               targetmpc = cd->mcodeptr - cd->mcodebase;
 
-               md_codegen_patch_branch(cd, branchmpc, targetmpc);
+/* emit_arrayindexoutofbounds_check ********************************************
 
-               MCODECHECK(100);
+   Emit a ArrayIndexOutOfBoundsException check.
 
-               /* Move the value register to a temporary register, if
-                  there is the need for it. */
+*******************************************************************************/
 
-               if (er->reg != -1)
-                       M_MOV(er->reg, REG_ITMP1);
+void emit_arrayindexoutofbounds_check(codegendata *cd, instruction *iptr, s4 s1, s4 s2)
+{
+       if (INSTRUCTION_MUST_CHECK(iptr)) {
+               M_ILD(REG_ITMP3, s1, OFFSET(java_arrayheader, size));
+               M_TRAPGEU(s2, REG_ITMP3);
+       }
+}
 
-               /* calcuate exception address */
 
-               M_LDA(REG_ITMP2_XPC, REG_PV, er->branchpos - 4);
+/* emit_classcast_check ********************************************************
 
-               /* move function to call into REG_ITMP3 */
+   Emit a ClassCastException check.
 
-               disp = dseg_add_functionptr(cd, er->function);
-               M_ALD(REG_ITMP3, REG_PV, disp);
+*******************************************************************************/
 
-               if (targetdisp == 0) {
-                   targetdisp = ((u4 *) cd->mcodeptr) - ((u4 *) cd->mcodebase);
+void emit_classcast_check(codegendata *cd, instruction *iptr, s4 condition, s4 reg, s4 s1)
+{
+       if (INSTRUCTION_MUST_CHECK(iptr)) {
+               switch (condition) {
+               case BRANCH_LE:
+                       M_BGT(1);
+                       break;
+               case BRANCH_EQ:
+                       M_BNE(1);
+                       break;
+               case BRANCH_GT:
+                       M_BLE(1);
+                       break;
+               default:
+                       vm_abort("emit_classcast_check: unknown condition %d", condition);
+               }
+               M_ALD_INTERN(s1, REG_ZERO, EXCEPTION_HARDWARE_CLASSCAST);
+       }
+}
 
-                       if (jd->isleafmethod) {
-                               M_MFLR(REG_ZERO);
-                               M_AST(REG_ZERO, REG_SP, cd->stackframesize * 4 + LA_LR_OFFSET);
-                       }
 
-                       M_MOV(REG_PV, rd->argintregs[0]);
-                       M_MOV(REG_SP, rd->argintregs[1]);
+/* emit_nullpointer_check ******************************************************
 
-                       if (jd->isleafmethod)
-                               M_MOV(REG_ZERO, rd->argintregs[2]);
-                       else
-                               M_ALD(rd->argintregs[2],
-                                         REG_SP, cd->stackframesize * 4 + LA_LR_OFFSET);
+   Emit a NullPointerException check.
 
-                       M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
-                       M_MOV(REG_ITMP1, rd->argintregs[4]);
+*******************************************************************************/
 
-                       M_STWU(REG_SP, REG_SP, -(LA_SIZE + 6 * 4));
-                       M_AST(REG_ITMP2_XPC, REG_SP, LA_SIZE + 5 * 4);
+void emit_nullpointer_check(codegendata *cd, instruction *iptr, s4 reg)
+{
+       if (INSTRUCTION_MUST_CHECK(iptr)) {
+               M_TST(reg);
+               M_BNE(1);
+               M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_NULLPOINTER);
+       }
+}
 
-                       M_MTCTR(REG_ITMP3);
-                       M_JSR;
-                       M_MOV(REG_RESULT, REG_ITMP1_XPTR);
 
-                       M_ALD(REG_ITMP2_XPC, REG_SP, LA_SIZE + 5 * 4);
-                       M_IADD_IMM(REG_SP, LA_SIZE + 6 * 4, REG_SP);
+/* emit_exception_check ********************************************************
 
-                       if (jd->isleafmethod) {
-                               /* XXX FIXME: REG_ZERO can cause problems here! */
-                               assert(cd->stackframesize * 4 <= 32767);
+   Emit an Exception check.
 
-                               M_ALD(REG_ZERO, REG_SP, cd->stackframesize * 4 + LA_LR_OFFSET);
-                               M_MTLR(REG_ZERO);
-                       }
+*******************************************************************************/
 
-                       disp = dseg_add_functionptr(cd, asm_handle_exception);
-                       M_ALD(REG_ITMP3, REG_PV, disp);
-                       M_MTCTR(REG_ITMP3);
-                       M_RTS;
-               }
-               else {
-                       disp = (((u4 *) cd->mcodebase) + targetdisp) -
-                               (((u4 *) cd->mcodeptr) + 1);
-                       M_BR(disp);
-               }
+void emit_exception_check(codegendata *cd, instruction *iptr)
+{
+       if (INSTRUCTION_MUST_CHECK(iptr)) {
+               M_TST(REG_RESULT);
+               M_BNE(1);
+               M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_EXCEPTION);
        }
 }
 
index c3f5ad36a9a6453c954804e48af2c0b6db5072a4..89ccfe8f96aee87cbd81a29394ef3d27581517ba 100644 (file)
@@ -1,6 +1,6 @@
 /* src/vm/jit/powerpc/linux/md-os.c - machine dependent PowerPC Linux functions
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
    J. Wenninger, Institut f. Computersprachen - TU Wien
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Christian Thalinger
-
-   $Id: md-os.c 5939 2006-11-09 09:54:00Z twisti $
+   $Id: md-os.c 7592 2007-03-28 20:12:33Z twisti $
 
 */
 
@@ -38,6 +34,7 @@
 
 #include "vm/types.h"
 
+#include "vm/jit/powerpc/codegen.h"
 #include "vm/jit/powerpc/linux/md-abi.h"
 
 #if defined(ENABLE_THREADS)
 
 /* md_signal_handler_sigsegv ***************************************************
 
-   NullPointerException signal handler for hardware null pointer
-   check.
+   Signal handler for hardware-exceptions.
 
 *******************************************************************************/
 
 void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
 {
-       ucontext_t  *_uc;
-       mcontext_t  *_mc;
-       u4           instr;
-       s4           reg;
-       ptrint       addr;
-       u1          *pv;
-       u1          *sp;
-       u1          *ra;
-       u1          *xpc;
+       ucontext_t        *_uc;
+       mcontext_t        *_mc;
+       u1                *pv;
+       u1                *sp;
+       u1                *ra;
+       u1                *xpc;
+       u4                 mcode;
+       s4                 s1;
+       s4                 disp;
+       s4                 d;
+       ptrint             addr;
+       ptrint             val;
+       s4                 type;
+       java_objectheader *o;
 
        _uc = (ucontext_t *) _p;
        _mc = _uc->uc_mcontext.uc_regs;
 
-       instr = *((u4 *) _mc->gregs[PT_NIP]);
-       reg = (instr >> 16) & 0x1f;
-       addr = _mc->gregs[reg];
-
        pv  = (u1 *) _mc->gregs[REG_PV];
        sp  = (u1 *) _mc->gregs[REG_SP];
        ra  = (u1 *) _mc->gregs[PT_LNK];         /* this is correct for leafs */
        xpc = (u1 *) _mc->gregs[PT_NIP];
 
-       if (addr == 0) {
-               _mc->gregs[REG_ITMP1_XPTR] =
-                       (ptrint) stacktrace_hardware_nullpointerexception(pv, sp, ra, xpc);
+       /* get exception-throwing instruction */
+
+       mcode = *((u4 *) xpc);
+
+       s1   = M_INSTR_OP2_IMM_A(mcode);
+       disp = M_INSTR_OP2_IMM_I(mcode);
+       d    = M_INSTR_OP2_IMM_D(mcode);
 
-               _mc->gregs[REG_ITMP2_XPC] = (ptrint) xpc;
-               _mc->gregs[PT_NIP] = (ptrint) asm_handle_exception;
+       val  = _mc->gregs[d];
+
+       /* check for special-load */
+
+       if (s1 == REG_ZERO) {
+               /* we use the exception type as load displacement */
+
+               type = disp;
        }
        else {
-               codegen_get_pv_from_pc(xpc);
+               /* This is a normal NPE: addr must be NULL and the NPE-type
+                  define is 0. */
+
+               addr = _mc->gregs[s1];
+               type = (s4) addr;
+       }
+
+       /* generate appropriate exception */
+
+       o = exceptions_new_hardware_exception(pv, sp, ra, xpc, type, val);
+
+       /* set registers */
+
+       _mc->gregs[REG_ITMP1_XPTR] = (ptrint) o;
+       _mc->gregs[REG_ITMP2_XPC]  = (ptrint) xpc;
+       _mc->gregs[PT_NIP]         = (ptrint) asm_handle_exception;
+}
+
+
+/* md_signal_handler_sigtrap ***************************************************
+
+   Signal handler for hardware-traps.
+
+*******************************************************************************/
+
+void md_signal_handler_sigtrap(int sig, siginfo_t *siginfo, void *_p)
+{
+       ucontext_t        *_uc;
+       mcontext_t        *_mc;
+       u1                *pv;
+       u1                *sp;
+       u1                *ra;
+       u1                *xpc;
+       u4                 mcode;
+       s4                 s1;
+       ptrint             val;
+       s4                 type;
+       java_objectheader *o;
+
+       _uc = (ucontext_t *) _p;
+       _mc = _uc->uc_mcontext.uc_regs;
+
+       pv  = (u1 *) _mc->gregs[REG_PV];
+       sp  = (u1 *) _mc->gregs[REG_SP];
+       ra  = (u1 *) _mc->gregs[PT_LNK];         /* this is correct for leafs */
+       xpc = (u1 *) _mc->gregs[PT_NIP];
+
+       /* get exception-throwing instruction */
+
+       mcode = *((u4 *) xpc);
+
+       s1 = M_OP3_GET_A(mcode);
+
+       /* for now we only handle ArrayIndexOutOfBoundsException */
+
+       type = EXCEPTION_HARDWARE_ARRAYINDEXOUTOFBOUNDS;
+       val  = _mc->gregs[s1];
+
+       /* generate appropriate exception */
+
+       o = exceptions_new_hardware_exception(pv, sp, ra, xpc, type, val);
 
-               /* this should not happen */
+       /* set registers */
 
-               assert(0);
-       }               
+       _mc->gregs[REG_ITMP1_XPTR] = (ptrint) o;
+       _mc->gregs[REG_ITMP2_XPC]  = (ptrint) xpc;
+       _mc->gregs[PT_NIP]         = (ptrint) asm_handle_exception;
 }
 
 
index 3ec67f0211e7bf1e3ea4eabfb86424480ede2ae7..d1c5a681bf3ee888728709c3767cd781a0959262 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: md.c 7246 2007-01-29 18:49:05Z twisti $
+   $Id: md.c 7297 2007-02-07 14:59:56Z twisti $
 
 */
 
@@ -59,60 +59,6 @@ void md_init(void)
 }
 
 
-/* md_codegen_patch_branch *****************************************************
-
-   Back-patches a branch instruction.
-
-*******************************************************************************/
-
-void md_codegen_patch_branch(codegendata *cd, s4 branchmpc, s4 targetmpc)
-{
-       s4 *mcodeptr;
-       s4  mcode;
-       s4  disp;                           /* branch displacement                */
-
-       /* calculate the patch position */
-
-       mcodeptr = (s4 *) (cd->mcodebase + branchmpc);
-
-       /* get the instruction before the exception point */
-
-       mcode = mcodeptr[-1];
-
-       /* Calculate the branch displacement. */
-
-       disp = targetmpc - branchmpc + 4;
-
-       /* Check which branch instruction we have.  Then mask it and patch
-          the displacement. */
-
-       if ((mcode & 0xfc000000) == 0x48000000) {
-               /* bx  (0x48000000) */
-
-               if ((disp < (s4) 0xfe000000) || (disp > (s4) 0x01fffffc))
-                       vm_abort("md_codegen_patch_branch: branch displacement out of range: %d > +/-%d", disp, 0x03fffffc);
-
-               mcode &= ~M_BMASK;     /* mask out previous displacement, probably +4 */
-               mcode |= (disp & M_BMASK);
-       }
-       else if ((mcode & 0xfc000000) == 0x40000000) {
-               /* bcx (0x40000000) */
-
-               if ((disp < (s4) 0xffff8000) || (disp > (s4) 0x00007fff))
-                       vm_abort("md_codegen_patch_branch: branch displacement out of range: %d > +/-%d", disp, 0x00007fff);
-
-               mcode &= ~M_BCMASK;    /* mask out previous displacement, probably +4 */
-               mcode |= (disp & M_BCMASK);
-       }
-       else
-               vm_abort("md_codegen_patch_branch: unknown instruction 0x%08x", mcode);
-
-       /* patch the branch instruction before the mcodeptr */
-
-       mcodeptr[-1] = mcode;
-}
-
-
 /* md_stacktrace_get_returnaddress *********************************************
 
    Returns the return address of the current stackframe, specified by
index 11f4438f9ab24873bd9cd2c0da6877a2ff8442ea..67b0d34db989a9b233f716db79631f439121941d 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: patcher.c 7464 2007-03-06 00:26:31Z edwin $
+   $Id: patcher.c 7486 2007-03-08 13:50:07Z twisti $
 
 */
 
@@ -657,20 +657,75 @@ bool patcher_invokeinterface(u1 *sp)
 }
 
 
-/* patcher_checkcast_instanceof_interface **************************************
+/* patcher_checkcast_interface *************************************************
 
    Machine code:
 
    <patched call position>
-   81870000    lwz   r12,0(r7)
-   800c0010    lwz   r0,16(r12)
-   34000000    addic.        r0,r0,0
-   408101fc    ble-  0x3002e518
-   800c0000    lwz   r0,0(r12)
+   81870000    lwz     r12,0(r7)
+   800c0010    lwz     r0,16(r12)
+   34000000    addic.  r0,r0,0
+   41810008    bgt-    0x014135d8
+   83c00003    lwz     r30,3(0)
+   800c0000    lwz     r0,0(r12)
+
+*******************************************************************************/
+
+bool patcher_checkcast_interface(u1 *sp)
+{
+       u1                *ra;
+       constant_classref *cr;
+       classinfo         *c;
+       s4                 disp;
+
+       /* get stuff from the stack */
+
+       ra = (u1 *)                *((ptrint *) (sp + 5 * 4));
+       cr = (constant_classref *) *((ptrint *) (sp + 2 * 4));
+
+       /* get the fieldinfo */
+
+       if (!(c = resolve_classref_eager(cr)))
+               return false;
+
+       /* if we show NOPs, we have to skip them */
+
+       if (opt_shownops)
+               ra = ra + 1 * 4;
+
+       /* patch super class index */
+
+       disp = -(c->index);
+
+       *((s4 *) (ra + 2 * 4)) |= (disp & 0x0000ffff);
+
+       disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
+
+       *((s4 *) (ra + 5 * 4)) |= (disp & 0x0000ffff);
+
+       /* synchronize instruction cache */
+
+       md_icacheflush(ra + 2 * 4, 4 * 4);
+
+       return true;
+}
+
+
+/* patcher_instanceof_interface ************************************************
+
+   Machine code:
+
+   <patched call position>
+   81870000    lwz     r12,0(r7)
+   800c0010    lwz     r0,16(r12)
+   34000000    addic.  r0,r0,0
+   41810008    bgt-    0x014135d8
+   83c00003    lwz     r30,3(0)
+   800c0000    lwz     r0,0(r12)
 
 *******************************************************************************/
 
-bool patcher_checkcast_instanceof_interface(u1 *sp)
+bool patcher_instanceof_interface(u1 *sp)
 {
        u1                *ra;
        constant_classref *cr;
index 9231f2116194fab65a84851c9714724242427aca..f82ccedc1b2731665b98d8ef6a22124b18b82ce7 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: arch.h 7241 2007-01-27 15:52:01Z twisti $
+   $Id: arch.h 7452 2007-03-04 23:32:24Z twisti $
 
 */
 
 /* #define SUPPORT_COMBINE_INTEGER_REGISTERS */
 
 
+/* branches *******************************************************************/
+
+#define SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER       1
+#define SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER     0
+#define SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS    0
+
+
 /* exceptions *****************************************************************/
 
 #define SUPPORT_HARDWARE_DIVIDE_BY_ZERO  0
index 6ab2a0be04a6a916cee98f76c185aa20760ed8a9..a9fea3385a046fbdcf3ef01b9b881a397a47ebf3 100644 (file)
    Changes: Christian Thalinger
             Edwin Steiner
 
-   $Id: asmpart.S 6265 2007-01-02 20:40:57Z edwin $
+   $Id: asmpart.S 7533 2007-03-16 17:55:36Z tbfg $
 
 */
 
 
 #include "config.h"
 
+#define __ASSEMBLY__
+
 #include "md-abi.h"
 #include "md-asm.h"
 
 
 /* export functions ***********************************************************/
 
-#ifdef ENABLE_LIBJVM
-       .globl asm_vm_call_method
-       .globl asm_vm_call_method_int
-       .globl asm_vm_call_method_long
-       .globl asm_vm_call_method_float
-       .globl asm_vm_call_method_double
-#else
-       .globl .asm_vm_call_method
-       .globl .asm_vm_call_method_int
-       .globl .asm_vm_call_method_long
-       .globl .asm_vm_call_method_float
-       .globl .asm_vm_call_method_double
-#endif
        .globl asm_vm_call_method_exception_handler
+       .globl asm_vm_call_method_end
 
        .globl asm_call_jit_compiler
 
@@ -80,9 +70,9 @@
        .globl .asm_replacement_in
 #endif
 
-       .globl .asm_cacheflush          /* no function descriptor needed, only called direct */
+       .globl asm_cacheflush
        .globl asm_criticalsections
-       .globl .asm_getclassvalues_atomic
+       .globl asm_getclassvalues_atomic
 
 
 /* asm_vm_call_method **********************************************************
        .quad   0                           /* codeinfo pointer                   */
 
 #ifdef ENABLE_LIBJVM
+       
+       .globl asm_vm_call_method
+       .globl asm_vm_call_method_int
+       .globl asm_vm_call_method_long
+       .globl asm_vm_call_method_float
+       .globl asm_vm_call_method_double
        .section ".opd","aw"
        .align 3
 
 #else
        asm_vm_call_method:
        .globl asm_vm_call_method
+       asm_vm_call_method_int:
+       .globl asm_vm_call_method_int
+       asm_vm_call_method_long:
+       .globl asm_vm_call_method_long
+       asm_vm_call_method_float:
+       .globl asm_vm_call_method_float
+       asm_vm_call_method_double:
+       .globl asm_vm_call_method_double
 #endif
 
 .asm_vm_call_method:
@@ -632,6 +636,8 @@ L_handle_fda12:
        lfd     fa12,offvmargdata(itmp1)
        b       L_register_copy
 
+asm_vm_call_method_end:
+       nop
 
 /* asm_call_jit_compiler *******************************************************
 
@@ -1293,7 +1299,17 @@ asm_replacement_out:
 /* asm_cacheflush **************************************************************
        copied from linux/arch/ppc64/kernel/vdso64/cacheflush.S
        assumes 128 byte cache line size.
+       All registers used may be trashed for fun and profit.
 *******************************************************************************/
+
+       .section ".opd","aw"
+       .align 3
+asm_cacheflush:
+               .quad   .asm_cacheflush,.TOC.@tocbase,0
+               .previous
+               .size asm_cacheflush, 24
+               .type .asm_cacheflush,@function
+               .globl .asm_cacheflush 
 .asm_cacheflush:
        /* construct the AND mask */
        li      r6,   0xffffffffffff8000
@@ -1323,7 +1339,19 @@ asm_replacement_out:
        isync
        blr
 
+/*
+               asm_getclassvalues_atomic 
+*/
+       .section ".opd","aw"
+       .align 3
+asm_getclassvalues_atomic:
+               .quad   .asm_getclassvalues_atomic,.TOC.@tocbase,0
+               .previous
+               .size asm_getclassvalues_atomic, 24
+               .type .asm_getclassvalues_atomic,@function
+               .globl .asm_getclassvalues_atomic
 .asm_getclassvalues_atomic:
+
 _crit_restart:
 _crit_begin:
        lwz     r6,offbaseval(r3)
index 7f49dc864a8e0c7bb6d2a8dfcbbd11162e6bb257..954f72d0113187f0c24b041c90e6883fb0f4f62f 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: codegen.c 7311 2007-02-09 13:20:27Z twisti $
+   $Id: codegen.c 7582 2007-03-26 09:27:10Z tbfg $
 
 */
 
@@ -36,7 +36,6 @@
 #include "vm/types.h"
 
 #include "md-abi.h"
-#include "vm/jit/abi-asm.h"
 
 #include "vm/jit/powerpc64/arch.h"
 #include "vm/jit/powerpc64/codegen.h"
 #include "vm/stringlocal.h"
 #include "vm/vm.h"
 
+#include "vm/jit/abi-asm.h"
+#include "vm/jit/md.h"
 #include "vm/jit/asmpart.h"
 #include "vm/jit/codegen-common.h"
 #include "vm/jit/dseg.h"
 #include "vm/jit/emit-common.h"
 #include "vm/jit/jit.h"
-#include "vm/jit/md.h"
 #include "vm/jit/parse.h"
 #include "vm/jit/patcher.h"
 #include "vm/jit/reg.h"
 #include "vm/jit/replace.h"
+#include "vm/jit/stacktrace.h"
+
+#include "vmcore/loader.h"
+#include "vmcore/options.h"
 
 #if defined(ENABLE_LSRA)
 # include "vm/jit/allocator/lsra.h"
 #endif
 
-#include "vmcore/loader.h"
-#include "vmcore/options.h"
+#if defined(ENABLE_THREADS)
+# include "threads/native/lock.h"
+#endif
 
 
-/* codegen *********************************************************************
+/* codegen_emit ****************************************************************
 
    Generates machine code.
 
 *******************************************************************************/
 
-bool codegen(jitdata *jd)
+bool codegen_emit(jitdata *jd)
 {
        methodinfo         *m;
        codeinfo           *code;
@@ -90,6 +95,7 @@ bool codegen(jitdata *jd)
        exception_entry    *ex;
        u2                  currentline;
        methodinfo         *lm;             /* local methodinfo for ICMD_INVOKE*  */
+       unresolved_method  *um;
        builtintable_entry *bte;
        methoddesc         *md;
        s4                  fieldtype;
@@ -236,11 +242,7 @@ bool codegen(jitdata *jd)
                                if (!IS_INMEMORY(var->flags)) {      /* reg arg -> register   */
                                        M_FLTMOVE(s2, var->vv.regoff);
                                } else {                                         /* reg arg -> spilled    */
-                                       if (IS_2_WORD_TYPE(t)) {
-                                               M_DST(s2, REG_SP, var->vv.regoff * 8);
-                                       } else {
-                                               M_DST(s2, REG_SP, var->vv.regoff * 8);  /*  F XXX */
-                                       }
+                                       M_DST(s2, REG_SP, var->vv.regoff * 8);
                                }
 
                        } else {                                 /* stack arguments       */
@@ -292,8 +294,8 @@ bool codegen(jitdata *jd)
                }
                else {
                        M_TST(rd->argintregs[0]);
-                       M_BEQ(0);
-                       codegen_add_nullpointerexception_ref(cd);
+                       M_BNE(1);
+                       M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_NULLPOINTER);
                }
 
                M_AST(rd->argintregs[0], REG_SP, s1 * 8);       /* rd->memuse * 8 */
@@ -335,13 +337,7 @@ bool codegen(jitdata *jd)
                if (bptr->flags >= BBREACHED) {
 
                /* branch resolving */
-
-               {
-               branchref *brefs;
-               for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
-                       md_codegen_patch_branch(cd, brefs->branchpos, bptr->mpc);
-                       }
-               }
+               codegen_resolve_branchrefs(cd, bptr);
 
                /* handle replacement points */
 
@@ -428,7 +424,7 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        M_TST(s1);
                        M_BEQ(0);
-                       codegen_add_nullpointerexception_ref(cd);
+                       emit_nullpointer_check(cd, iptr, s1);
                        break;
 
                /* constant operations ************************************************/
@@ -466,17 +462,15 @@ bool codegen(jitdata *jd)
                case ICMD_ACONST:     /* ...  ==> ..., constant                       */
 
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
-                       disp = dseg_add_address(cd, iptr->sx.val.anyptr);
 
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                               disp = dseg_add_unique_address(cd, iptr->sx.val.c.ref);
                                codegen_addpatchref(cd, PATCHER_aconst,
                                                                        iptr->sx.val.c.ref,
                                                                    disp);
-
-                               if (opt_showdisassemble)
-                                       M_NOP;
+                       } else  {
+                               disp = dseg_add_address(cd, iptr->sx.val.anyptr);
                        }
-
                        M_ALD(d, REG_PV, disp);
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -663,9 +657,7 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
-                       M_TST(s2);
-                       M_BEQ(0);
-                       codegen_add_arithmeticexception_ref(cd);
+                       emit_arithmetic_check(cd, iptr, s2);
 
                        M_DIV(s1, s2, d);
                        /* we need to test if divident was 0x8000000000000, bit OV is set in XER in this case */
@@ -685,9 +677,7 @@ bool codegen(jitdata *jd)
                case ICMD_LREM:       /* ..., val1, val2  ==> ..., val1 % val2        */
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       M_TST(s2);
-                       M_BEQ(0);
-                       codegen_add_arithmeticexception_ref(cd);
+                       emit_arithmetic_check(cd, iptr, s2);
 
                        M_DIV(s1, s2,  REG_ITMP3);      
                        /* we need to test if divident was 0x8000000000000, bit OV is set in XER in this case */
@@ -974,6 +964,7 @@ bool codegen(jitdata *jd)
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
                        /* XXX implement me!!! */
+                       vm_abort("codegen: implement ICMD_LCMP!");
                        emit_store_dst(jd, iptr, d);
                        break;
                        break;
@@ -1143,8 +1134,7 @@ bool codegen(jitdata *jd)
                        s2 = emit_load_s2(jd, iptr, REG_FTMP2);
                        M_FCMPU(s1, s2);
                        M_BNAN(1);
-                       M_BEQ(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_beq(cd, iptr->dst.block);
                        break;
 
                case ICMD_IF_FCMPNE:    /* ..., value, value ==> ...                  */
@@ -1153,10 +1143,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_FTMP1);
                        s2 = emit_load_s2(jd, iptr, REG_FTMP2);
                        M_FCMPU(s1, s2);
-                       M_BNAN(0);
-                       codegen_addreference(cd, iptr->dst.block);
-                       M_BNE(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_bnan(cd, iptr->dst.block);
+                       emit_bne(cd, iptr->dst.block);
                        break;
 
 
@@ -1166,10 +1154,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_FTMP1);
                        s2 = emit_load_s2(jd, iptr, REG_FTMP2);
                        M_FCMPU(s1, s2);
-                       M_BNAN(0);
-                       codegen_addreference(cd, iptr->dst.block);
-                       M_BLT(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_bnan(cd, iptr->dst.block);
+                       emit_blt(cd, iptr->dst.block);
                        break;
 
                case ICMD_IF_FCMPL_GT:  /* ..., value, value ==> ...                  */
@@ -1179,8 +1165,7 @@ bool codegen(jitdata *jd)
                        s2 = emit_load_s2(jd, iptr, REG_FTMP2);
                        M_FCMPU(s1, s2);
                        M_BNAN(1);
-                       M_BGT(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_bgt(cd, iptr->dst.block);
                        break;
 
                case ICMD_IF_FCMPL_LE:  /* ..., value, value ==> ...                  */
@@ -1189,10 +1174,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_FTMP1);
                        s2 = emit_load_s2(jd, iptr, REG_FTMP2);
                        M_FCMPU(s1, s2);
-                       M_BNAN(0);
-                       codegen_addreference(cd, iptr->dst.block);
-                       M_BLE(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_bnan(cd, iptr->dst.block);
+                       emit_ble(cd, iptr->dst.block);
                        break;
 
                case ICMD_IF_FCMPL_GE:  /* ..., value, value ==> ...                  */
@@ -1202,8 +1185,7 @@ bool codegen(jitdata *jd)
                        s2 = emit_load_s2(jd, iptr, REG_FTMP2);
                        M_FCMPU(s1, s2);
                        M_BNAN(1);
-                       M_BGE(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_bge(cd, iptr->dst.block);
                        break;
 
                case ICMD_IF_FCMPG_LT:  /* ..., value, value ==> ...                  */
@@ -1213,8 +1195,7 @@ bool codegen(jitdata *jd)
                        s2 = emit_load_s2(jd, iptr, REG_FTMP2);
                        M_FCMPU(s1, s2);
                        M_BNAN(1);
-                       M_BLT(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_blt(cd, iptr->dst.block);
                        break;
 
                case ICMD_IF_FCMPG_GT:  /* ..., value, value ==> ...                  */
@@ -1223,10 +1204,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_FTMP1);
                        s2 = emit_load_s2(jd, iptr, REG_FTMP2);
                        M_FCMPU(s1, s2);
-                       M_BNAN(0);
-                       codegen_addreference(cd, iptr->dst.block);
-                       M_BGT(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_bnan(cd, iptr->dst.block);
+                       emit_bgt(cd, iptr->dst.block);
                        break;
 
                case ICMD_IF_FCMPG_LE:  /* ..., value, value ==> ...                  */
@@ -1236,8 +1215,7 @@ bool codegen(jitdata *jd)
                        s2 = emit_load_s2(jd, iptr, REG_FTMP2);
                        M_FCMPU(s1, s2);
                        M_BNAN(1);
-                       M_BLE(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_ble(cd, iptr->dst.block);
                        break;
 
                case ICMD_IF_FCMPG_GE:  /* ..., value, value ==> ...                  */
@@ -1246,10 +1224,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_FTMP1);
                        s2 = emit_load_s2(jd, iptr, REG_FTMP2);
                        M_FCMPU(s1, s2);
-                       M_BNAN(0);
-                       codegen_addreference(cd, iptr->dst.block);
-                       M_BGE(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_bnan(cd, iptr->dst.block);
+                       emit_bge(cd, iptr->dst.block);
                        break;
 
 
@@ -1259,7 +1235,7 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                       gen_nullptr_check(s1);
+                       emit_nullpointer_check(cd, iptr, s1);
                        M_ILD(d, s1, OFFSET(java_arrayheader, size));
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1269,11 +1245,9 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                       if (INSTRUCTION_MUST_CHECK(iptr)) {
-                               gen_nullptr_check(s1);
-                               gen_bound_check;
-                       }
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_IADD_IMM(s2, OFFSET(java_bytearray, data[0]), REG_ITMP2);
+                       /* implicit null-pointer check */
                        M_LBZX(d, s1, REG_ITMP2);
                        M_BSEXT(d, d);
                        emit_store_dst(jd, iptr, d);
@@ -1284,13 +1258,11 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                       if (INSTRUCTION_MUST_CHECK(iptr)) {
-                               gen_nullptr_check(s1);
-                               gen_bound_check;
-                       }
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_SLL_IMM(s2, 1, REG_ITMP2);
                        M_IADD_IMM(REG_ITMP2, OFFSET(java_chararray, data[0]), REG_ITMP2);
-                       M_LHAX(d, s1, REG_ITMP2);
+                       /* implicit null-pointer check */
+                       M_LHZX(d, s1, REG_ITMP2);
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -1299,12 +1271,10 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                       if (INSTRUCTION_MUST_CHECK(iptr)) {
-                               gen_nullptr_check(s1);
-                               gen_bound_check;
-                       }
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_SLL_IMM(s2, 1, REG_ITMP2);
                        M_IADD_IMM(REG_ITMP2, OFFSET(java_shortarray, data[0]), REG_ITMP2);
+                       /* implicit null-pointer check */
                        M_LHAX(d, s1, REG_ITMP2);
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1314,13 +1284,11 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                       if (INSTRUCTION_MUST_CHECK(iptr)) {
-                               gen_nullptr_check(s1);
-                               gen_bound_check;
-                       }
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_SLL_IMM(s2, 2, REG_ITMP2);
                        M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray, data[0]), REG_ITMP2);
-                       M_LWZX(d, s1, REG_ITMP2);
+                       /* implicit null-pointer check */
+                       M_LWAX(d, s1, REG_ITMP2);
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -1329,12 +1297,10 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, PACK_REGS(REG_ITMP2, REG_ITMP1));
-                       if (INSTRUCTION_MUST_CHECK(iptr)) {
-                               gen_nullptr_check(s1);
-                               gen_bound_check;
-                       }
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_SLL_IMM(s2, 3, REG_ITMP2);
                        M_IADD(s1, REG_ITMP2, REG_ITMP2);
+                       /* implicit null-pointer check */
                        M_LLD_INTERN(d, REG_ITMP2, OFFSET(java_longarray, data[0]));
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1344,12 +1310,10 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
-                       if (INSTRUCTION_MUST_CHECK(iptr)) {
-                               gen_nullptr_check(s1);
-                               gen_bound_check;
-                       }
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_SLL_IMM(s2, 2, REG_ITMP2);
                        M_IADD_IMM(REG_ITMP2, OFFSET(java_floatarray, data[0]), REG_ITMP2);
+                       /* implicit null-pointer check */
                        M_LFSX(d, s1, REG_ITMP2);
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1359,12 +1323,10 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
-                       if (INSTRUCTION_MUST_CHECK(iptr)) {
-                               gen_nullptr_check(s1);
-                               gen_bound_check;
-                       }
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_SLL_IMM(s2, 3, REG_ITMP2);
                        M_IADD_IMM(REG_ITMP2, OFFSET(java_doublearray, data[0]), REG_ITMP2);
+                       /* implicit null-pointer check */
                        M_LFDX(d, s1, REG_ITMP2);
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1374,12 +1336,10 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                       if (INSTRUCTION_MUST_CHECK(iptr)) {
-                               gen_nullptr_check(s1);
-                               gen_bound_check;
-                       }
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_SLL_IMM(s2, 3, REG_ITMP2);
                        M_IADD_IMM(REG_ITMP2, OFFSET(java_objectarray, data[0]), REG_ITMP2);
+                       /* implicit null-pointer check */
                        M_ALDX(d, s1, REG_ITMP2);
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1389,12 +1349,10 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       if (INSTRUCTION_MUST_CHECK(iptr)) {
-                               gen_nullptr_check(s1);
-                               gen_bound_check;
-                       }
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
                        M_IADD_IMM(s2, OFFSET(java_bytearray, data[0]), REG_ITMP2);
+                       /* implicit null-pointer check */
                        M_STBX(s3, s1, REG_ITMP2);
                        break;
 
@@ -1402,13 +1360,11 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       if (INSTRUCTION_MUST_CHECK(iptr)) {
-                               gen_nullptr_check(s1);
-                               gen_bound_check;
-                       }
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
                        M_SLL_IMM(s2, 1, REG_ITMP2);
                        M_IADD_IMM(REG_ITMP2, OFFSET(java_chararray, data[0]), REG_ITMP2);
+                       /* implicit null-pointer check */
                        M_STHX(s3, s1, REG_ITMP2);
                        break;
 
@@ -1416,10 +1372,7 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       if (INSTRUCTION_MUST_CHECK(iptr)) {
-                               gen_nullptr_check(s1);
-                               gen_bound_check;
-                       }
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
                        M_SLL_IMM(s2, 1, REG_ITMP2);
                        M_IADD_IMM(REG_ITMP2, OFFSET(java_shortarray, data[0]), REG_ITMP2);
@@ -1430,13 +1383,11 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       if (INSTRUCTION_MUST_CHECK(iptr)) {
-                               gen_nullptr_check(s1);
-                               gen_bound_check;
-                       }
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
                        M_SLL_IMM(s2, 2, REG_ITMP2);
                        M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray, data[0]), REG_ITMP2);
+                       /* implicit null-pointer check */
                        M_STWX(s3, s1, REG_ITMP2);
                        break;
 
@@ -1444,13 +1395,11 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       if (INSTRUCTION_MUST_CHECK(iptr)) {
-                               gen_nullptr_check(s1);
-                               gen_bound_check;
-                       }
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
                        M_SLL_IMM(s2, 3, REG_ITMP2);
                        M_IADD_IMM(REG_ITMP2, OFFSET(java_longarray, data[0]), REG_ITMP2);
+                       /* implicit null-pointer check */
                        M_LSTX(s3, s1, REG_ITMP2);
                        break;
 
@@ -1458,13 +1407,11 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       if (INSTRUCTION_MUST_CHECK(iptr)) {
-                               gen_nullptr_check(s1);
-                               gen_bound_check;
-                       }
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_FTMP3);
                        M_SLL_IMM(s2, 2, REG_ITMP2);
                        M_IADD_IMM(REG_ITMP2, OFFSET(java_floatarray, data[0]), REG_ITMP2);
+                       /* implicit null-pointer check */
                        M_STFSX(s3, s1, REG_ITMP2);
                        break;
 
@@ -1472,44 +1419,38 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       if (INSTRUCTION_MUST_CHECK(iptr)) {
-                               gen_nullptr_check(s1);
-                               gen_bound_check;
-                       }
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_FTMP3);
                        M_SLL_IMM(s2, 3, REG_ITMP2);
                        M_IADD_IMM(REG_ITMP2, OFFSET(java_doublearray, data[0]), REG_ITMP2);
+                       /* implicit null-pointer check */
                        M_STFDX(s3, s1, REG_ITMP2);
                        break;
 
                case ICMD_AASTORE:    /* ..., arrayref, index, value  ==> ...         */
 
-                       s1 = emit_load_s1(jd, iptr, rd->argintregs[0]);
+                       s1 = emit_load_s1(jd, iptr, REG_A0);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       if (INSTRUCTION_MUST_CHECK(iptr)) {
-                               gen_nullptr_check(s1);
-                               gen_bound_check;
-                       }
-                       s3 = emit_load_s3(jd, iptr, rd->argintregs[1]);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
+                       s3 = emit_load_s3(jd, iptr, REG_A1);
 
                        disp = dseg_add_functionptr(cd, BUILTIN_canstore);
                        M_ALD(REG_ITMP3, REG_PV, disp);
                        M_ALD(REG_ITMP3, REG_ITMP3, 0); /* TOC */
                        M_MTCTR(REG_ITMP3);
 
-                       M_INTMOVE(s1, rd->argintregs[0]);
-                       M_INTMOVE(s3, rd->argintregs[1]);
+                       M_INTMOVE(s1, REG_A0);
+                       M_INTMOVE(s3, REG_A1);
 
                        M_JSR;
-                       M_TST(REG_RESULT);
-                       M_BEQ(0);
-                       codegen_add_arraystoreexception_ref(cd);
+                       emit_exception_check(cd, iptr);
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
                        M_SLL_IMM(s2, 3, REG_ITMP2);
                        M_IADD_IMM(REG_ITMP2, OFFSET(java_objectarray, data[0]), REG_ITMP2);
+                       /* implicit null-pointer check */
                        M_ASTX(s3, s1, REG_ITMP2);
                        break;
 
@@ -1613,7 +1554,6 @@ bool codegen(jitdata *jd)
                case ICMD_GETFIELD:   /* ...  ==> ..., value                          */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       gen_nullptr_check(s1);
 
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
                                uf = iptr->sx.s23.s3.uf;
@@ -1621,16 +1561,13 @@ bool codegen(jitdata *jd)
                                disp = 0;
 
                                codegen_addpatchref(cd, PATCHER_get_putfield, uf, 0);
-
-                               if (opt_showdisassemble)
-                                       M_NOP;
-
                        } else {
                                fi = iptr->sx.s23.s3.fmiref->p.field;
                                fieldtype = fi->type;
                                disp = fi->offset;
                        }
 
+                       /* implicit null-pointer check */
                        switch (fieldtype) {
                        case TYPE_INT:
                                d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
@@ -1659,7 +1596,6 @@ bool codegen(jitdata *jd)
                case ICMD_PUTFIELD:   /* ..., value  ==> ...                          */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       gen_nullptr_check(s1);
 
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
                                uf        = iptr->sx.s23.s3.uf;
@@ -1680,12 +1616,10 @@ bool codegen(jitdata *jd)
 
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
                                codegen_addpatchref(cd, PATCHER_get_putfield, uf, 0);
-
-                               if (opt_showdisassemble)
-                                       M_NOP;
                        }
 
 
+                       /* implicit null-pointer check */
                        switch (fieldtype) {
                        case TYPE_INT:
                                M_IST(s2, s1, disp);
@@ -1717,9 +1651,6 @@ bool codegen(jitdata *jd)
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
                                codegen_addpatchref(cd, PATCHER_athrow_areturn,
                                                                        iptr->sx.s23.s2.uc, 0);
-
-                               if (opt_showdisassemble)
-                                       M_NOP;
                        }
 #endif /* ENABLE_VERIFIER */
 
@@ -1739,15 +1670,13 @@ bool codegen(jitdata *jd)
                case ICMD_GOTO:         /* ... ==> ...                                */
                case ICMD_RET:          /* ... ==> ...                                */
 
-                       M_BR(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_br(cd, iptr->dst.block);
                        ALIGNCODENOP;
                        break;
 
                case ICMD_JSR:          /* ... ==> ...                                */
 
-                       M_BR(0);
-                       codegen_addreference(cd, iptr->sx.s23.s3.jsrtarget.block);
+                       emit_br(cd, iptr->sx.s23.s3.jsrtarget.block);
                        ALIGNCODENOP;
                        break;
 
@@ -1755,16 +1684,14 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        M_TST(s1);
-                       M_BEQ(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_beq(cd, iptr->dst.block);
                        break;
 
                case ICMD_IFNONNULL:    /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        M_TST(s1);
-                       M_BNE(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_bne(cd, iptr->dst.block);
                        break;
 
                case ICMD_IFLT:
@@ -1781,71 +1708,45 @@ bool codegen(jitdata *jd)
                                ICONST(REG_ITMP2, iptr->sx.val.i);
                                M_CMP(s1, REG_ITMP2);
                        }
-                       switch (iptr->opc) {
-                       case ICMD_IFLT:
-                               M_BLT(0);
-                               break;
-                       case ICMD_IFLE:
-                               M_BLE(0);
-                               break;
-                       case ICMD_IFNE:
-                               M_BNE(0);
-                               break;
-                       case ICMD_IFGT:
-                               M_BGT(0);
-                               break;
-                       case ICMD_IFGE:
-                               M_BGE(0);
-                               break;
-                       case ICMD_IFEQ:
-                               M_BEQ(0);
-                               break;
-                       }
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IFEQ, BRANCH_OPT_NONE);
                        break;
                        
                case ICMD_IF_LEQ:       /* ..., value ==> ...                         */
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        LCONST(REG_ITMP2, iptr->sx.val.l);
                        M_CMP(s1, REG_ITMP2);
-                       M_BEQ(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_beq(cd, iptr->dst.block);
                        break;
                case ICMD_IF_LLT:       /* ..., value ==> ...                         */
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        LCONST(REG_ITMP2, iptr->sx.val.l);
                        M_CMP(s1, REG_ITMP2);
-                       M_BLT(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_blt(cd, iptr->dst.block);
                        break;
                case ICMD_IF_LLE:       /* ..., value ==> ...                         */
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        LCONST(REG_ITMP2, iptr->sx.val.l);
                        M_CMP(s1, REG_ITMP2);
-                       M_BLE(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_ble(cd, iptr->dst.block);
                        break;
 
                case ICMD_IF_LNE:       /* ..., value ==> ... */
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        LCONST(REG_ITMP2, iptr->sx.val.l);
                        M_CMP(s1, REG_ITMP2);
-                       M_BNE(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_bne(cd, iptr->dst.block);
                        break;
                case ICMD_IF_LGE:       /* ..., value ==> ... */
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        LCONST(REG_ITMP2, iptr->sx.val.l);
                        M_CMP(s1, REG_ITMP2);
-                       M_BGE(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_bge(cd, iptr->dst.block);
                        break;
                case ICMD_IF_LGT:       /* ..., value ==> ...                         */
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        LCONST(REG_ITMP2, iptr->sx.val.l);
                        M_CMP(s1, REG_ITMP2);
-                       M_BGT(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_bgt(cd, iptr->dst.block);
                        break;
                case ICMD_IF_ICMPEQ:    /* ..., value, value ==> ...                  */
                case ICMD_IF_ACMPEQ:    /* op1 = target JavaVM pc                     */
@@ -1854,8 +1755,7 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_CMP(s1, s2);
-                       M_BEQ(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_beq(cd, iptr->dst.block);
                        break;
 
                case ICMD_IF_ICMPNE:    /* ..., value, value ==> ...                  */
@@ -1865,8 +1765,7 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_CMP(s1, s2);
-                       M_BNE(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_bne(cd, iptr->dst.block);
                        break;
 
 
@@ -1876,8 +1775,7 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_CMP(s1, s2);
-                       M_BLT(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_blt(cd, iptr->dst.block);
                        break;
 
                case ICMD_IF_ICMPGT:    /* ..., value, value ==> ...                  */
@@ -1886,8 +1784,7 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_CMP(s1, s2);
-                       M_BGT(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_bgt(cd, iptr->dst.block);
                        break;
 
                case ICMD_IF_ICMPLE:    /* ..., value, value ==> ...                  */
@@ -1896,8 +1793,7 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_CMP(s1, s2);
-                       M_BLE(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_ble(cd, iptr->dst.block);
                        break;
 
                case ICMD_IF_ICMPGE:    /* ..., value, value ==> ...                  */
@@ -1906,8 +1802,7 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_CMP(s1, s2);
-                       M_BGE(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_bge(cd, iptr->dst.block);
                        break;
 
 
@@ -1929,9 +1824,6 @@ bool codegen(jitdata *jd)
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
                                codegen_addpatchref(cd, PATCHER_athrow_areturn,
                                                                        iptr->sx.s23.s2.uc, 0);
-
-                               if (opt_showdisassemble)
-                                       M_NOP;
                        }
 #endif /* ENABLE_VERIFIER */
 
@@ -2065,8 +1957,7 @@ nowperformreturn:
                        /* range check */
 
                        M_CMPUI(REG_ITMP1, i - 1);
-                       M_BGT(0);
-                       codegen_addreference(cd, table[0].block);
+                       emit_bgt(cd, table[0].block);
 
                        /* build jump table top down and use address of lowest entry */
 
@@ -2075,7 +1966,6 @@ nowperformreturn:
                        while (--i >= 0) {
                                dseg_add_target(cd, table->block); 
                                --table;
-                               }
                        }
 
                        /* length of dataseg after last dseg_add_unique_target is used by load */
@@ -2086,6 +1976,7 @@ nowperformreturn:
                        M_MTCTR(REG_ITMP2);
                        M_RTS;
                        ALIGNCODENOP;
+                       }
                        break;
 
 
@@ -2104,18 +1995,17 @@ nowperformreturn:
                                val = lookup->value;
                                if ((val >= -32768) && (val <= 32767)) {
                                        M_CMPI(s1, val);
+                       
                                } else {
                                        a = dseg_add_s4(cd, val);
                                        M_ILD(REG_ITMP2, REG_PV, a);
                                        M_CMP(s1, REG_ITMP2);
                                }
-                               M_BEQ(0);
-                               codegen_addreference(cd, lookup->target.block);
+                               emit_beq(cd, lookup->target.block);
                                ++lookup;
                        }
 
-                       M_BR(0);
-                       codegen_addreference(cd, iptr->sx.s23.s3.lookupdefault.block);
+                       emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
 
                        ALIGNCODENOP;
                        break;
@@ -2136,11 +2026,13 @@ nowperformreturn:
                        REPLACEMENT_POINT_INVOKE(cd, iptr);
 
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
-                               md = iptr->sx.s23.s3.um->methodref->parseddesc.md;
                                lm = NULL;
+                               um = iptr->sx.s23.s3.um;
+                               md = um->methodref->parseddesc.md;
                        }
                        else {
                                lm = iptr->sx.s23.s3.fmiref->p.method;
+                               um = NULL;
                                md = lm->parseddesc;
                        }
 
@@ -2173,10 +2065,7 @@ gen_method:
                                                M_FLTMOVE(d, s1);
                                        } else {
                                                d = emit_load(jd, iptr, var, REG_FTMP1);
-                                               if (IS_2_WORD_TYPE(var->type))
-                                                       M_DST(d, REG_SP, md->params[s3].regoff * 8);
-                                               else
-                                                       M_DST(d, REG_SP, md->params[s3].regoff * 8);    /* F XXX */
+                                               M_DST(d, REG_SP, md->params[s3].regoff * 8);
                                        }
                                }
                        } /* end of for */
@@ -2184,81 +2073,62 @@ gen_method:
                        switch (iptr->opc) {
                        case ICMD_BUILTIN:
                                disp = dseg_add_functionptr(cd, bte->fp);
-                               d = md->returntype.type;
+                               M_ALD(REG_PV, REG_PV, disp);
+                               M_ALD(REG_PV, REG_PV, 0);       /* TOC */
 
-                               M_ALD(REG_PV, REG_PV, disp);    /* pointer to built-in-function descriptor */
-                               M_ALD(REG_ITMP1, REG_PV, 0);    /* function entry point address, what about TOC */
-                               M_MTCTR(REG_ITMP1);
+                               /* generate the actual call */
+                               REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
+                               M_MTCTR(REG_PV);
                                M_JSR;
                                REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
                                disp = (s4) (cd->mcodeptr - cd->mcodebase);
                                M_MFLR(REG_ITMP1);
                                M_LDA(REG_PV, REG_ITMP1, -disp);
 
-                               if (INSTRUCTION_MUST_CHECK(iptr)) {
-                                       M_CMPI(REG_RESULT, 0);
-                                       M_BEQ(0);
-                                       codegen_add_fillinstacktrace_ref(cd);
-                               }
+                               emit_exception_check(cd, iptr);
                                break;
 
+
                        case ICMD_INVOKESPECIAL:
-                               gen_nullptr_check(rd->argintregs[0]);
-                               M_ILD(REG_ITMP1, rd->argintregs[0], 0); /* hardware nullptr   */
+                               emit_nullpointer_check(cd, iptr, REG_A0);
                                /* fall through */
 
                        case ICMD_INVOKESTATIC:
                                if (lm == NULL) {
-                                       unresolved_method *um = iptr->sx.s23.s3.um;
-
-                                       disp = dseg_add_unique_address(cd, NULL);
+                                       disp = dseg_add_unique_address(cd, um);
 
                                        codegen_addpatchref(cd, PATCHER_invokestatic_special,
                                                                                um, disp);
-
-                                       if (opt_showdisassemble)
-                                               M_NOP;
-
-                                       d = md->returntype.type;
-
                                } else {
                                        disp = dseg_add_address(cd, lm->stubroutine);
-                                       d = md->returntype.type;
                                }
-
-                               M_NOP;
                                M_ALD(REG_PV, REG_PV, disp);
+
+                               /* generate the actual call */
+
                                M_MTCTR(REG_PV);
                                M_JSR;
                                REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
                                disp = (s4) (cd->mcodeptr - cd->mcodebase);
                                M_MFLR(REG_ITMP1);
                                M_LDA(REG_PV, REG_ITMP1, -disp);
-                               break;
 
+                               break;
                        case ICMD_INVOKEVIRTUAL:
-                               gen_nullptr_check(rd->argintregs[0]);
-
                                if (lm == NULL) {
-                                       unresolved_method *um = iptr->sx.s23.s3.um;
-
                                        codegen_addpatchref(cd, PATCHER_invokevirtual, um, 0);
-
-                                       if (opt_showdisassemble)
-                                               M_NOP;
-
                                        s1 = 0;
-                                       d = md->returntype.type;
-
                                } else {
                                        s1 = OFFSET(vftbl_t, table[0]) +
                                                sizeof(methodptr) * lm->vftblindex;
-                                       d = md->returntype.type;
                                }
 
-                               M_ALD(REG_METHODPTR, rd->argintregs[0],
-                                         OFFSET(java_objectheader, vftbl));
+                               /* implicit null-pointer check */
+                               M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_objectheader, vftbl));
                                M_ALD(REG_PV, REG_METHODPTR, s1);
+
+                               /* generate the actual call */
+
                                M_MTCTR(REG_PV);
                                M_JSR;
                                REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
@@ -2268,43 +2138,38 @@ gen_method:
                                break;
 
                        case ICMD_INVOKEINTERFACE:
-                               gen_nullptr_check(rd->argintregs[0]);
-
                                if (lm == NULL) {
-                                       unresolved_method *um = iptr->sx.s23.s3.um;
-
                                        codegen_addpatchref(cd, PATCHER_invokeinterface, um, 0);
 
-                                       if (opt_showdisassemble)
-                                               M_NOP;
-
                                        s1 = 0;
                                        s2 = 0;
-                                       d = md->returntype.type;
 
                                } else {
                                        s1 = OFFSET(vftbl_t, interfacetable[0]) -
                                                sizeof(methodptr*) * lm->class->index;
 
                                        s2 = sizeof(methodptr) * (lm - lm->class->methods);
-
-                                       d = md->returntype.type;
                                }
 
-                               M_ALD(REG_METHODPTR, rd->argintregs[0],
-                                         OFFSET(java_objectheader, vftbl));    
+                               /* implicit null-pointer check */
+                               M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_objectheader, vftbl));    
                                M_ALD(REG_METHODPTR, REG_METHODPTR, s1);
                                M_ALD(REG_PV, REG_METHODPTR, s2);
+
+                               /* generate the actual call */
+
                                M_MTCTR(REG_PV);
                                M_JSR;
                                REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
                                disp = (s4) (cd->mcodeptr - cd->mcodebase);
                                M_MFLR(REG_ITMP1);
                                M_LDA(REG_PV, REG_ITMP1, -disp);
+
                                break;
                        }
+                       /* store return value */
 
-                       /* d contains return type */
+                       d = md->returntype.type;
 
                        if (d != TYPE_VOID) {
                                if (IS_INT_LNG_TYPE(d)) {
@@ -2319,7 +2184,6 @@ gen_method:
                        }
                        break;
 
-
                case ICMD_CHECKCAST:  /* ..., objectref ==> ..., objectref            */
                                      /* val.a: (classinfo*) superclass               */
 
@@ -2357,32 +2221,35 @@ gen_method:
 
                                /* calculate interface checkcast code size */
 
-                               s2 = 7;
+                               s2 = 9;
+#if defined(SOFTEX)
+                               s2 += CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd) ? 2 : 0;
+#endif
                                if (super == NULL)
-                                       s2 += (opt_showdisassemble ? 1 : 0);
+                                       s2 += (opt_shownops ? 1 : 0);
 
                                /* calculate class checkcast code size */
 
-                               s3 = 9 + (s1 == REG_ITMP1);
+                               s3 = 10 + (s1 == REG_ITMP1);
+#if defined(SOFTEX)
+                               s3 += CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd) ? 1 : 0;
+#endif
                                if (super == NULL)
-                                       s3 += (opt_showdisassemble ? 1 : 0);
+                                       s3 += (opt_shownops ? 1 : 0);
 
                                /* if class is not resolved, check which code to call */
 
                                if (super == NULL) {
                                        M_TST(s1);
-                                       M_BEQ(3 + (opt_showdisassemble ? 1 : 0) + s2 + 1 + s3);
+                                       M_BEQ(3 + (opt_shownops ? 1 : 0) + s2 + 1 + s3);
 
-                                       disp = dseg_add_s4(cd, 0);                     /* super->flags */
+                                       disp = dseg_add_unique_s4(cd, 0);                     /* super->flags */
 
                                        codegen_addpatchref(cd,
                                                                                PATCHER_checkcast_instanceof_flags,
                                                                                iptr->sx.s23.s3.c.ref,
                                                                                disp);
 
-                                       if (opt_showdisassemble)
-                                               M_NOP;
-
                                        M_ILD(REG_ITMP2, REG_PV, disp);
                                        M_AND_IMM(REG_ITMP2, ACC_INTERFACE, REG_ITMP2);
                                        M_BEQ(s2 + 1);
@@ -2393,12 +2260,9 @@ gen_method:
                                if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
                                        if (super == NULL) {
                                                codegen_addpatchref(cd,
-                                                                                       PATCHER_checkcast_instanceof_interface,
+                                                                                       PATCHER_checkcast_interface,
                                                                                        iptr->sx.s23.s3.c.ref,
                                                                                        0);
-                                               if (opt_showdisassemble)
-                                                       M_NOP;
-
                                        } else {
                                                M_TST(s1);
                                                M_BEQ(s2);
@@ -2407,14 +2271,12 @@ gen_method:
                                        M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
                                        M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
                                        M_LDATST(REG_ITMP3, REG_ITMP3, -superindex);
-                                       M_BLE(0);
-                                       codegen_add_classcastexception_ref(cd, s1);     /*XXX s1?? */
+                                       emit_classcast_check(cd, iptr, BRANCH_LE, REG_ITMP3, s1);
                                        M_ALD(REG_ITMP3, REG_ITMP2,
                                                  OFFSET(vftbl_t, interfacetable[0]) -
                                                  superindex * sizeof(methodptr*));
                                        M_TST(REG_ITMP3);
-                                       M_BEQ(0);
-                                       codegen_add_classcastexception_ref(cd, s1);     /*XXX s1??*/
+                                       emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ITMP3, s1);
 
                                        if (!super)
                                                M_BR(s3);
@@ -2424,12 +2286,10 @@ gen_method:
 
                                if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
                                        if (super == NULL) {
-                                               disp = dseg_add_address(cd, NULL);
+                                               disp = dseg_add_unique_address(cd, NULL);
                                                codegen_addpatchref(cd, PATCHER_checkcast_class,
                                                                                        iptr->sx.s23.s3.c.ref,
                                                                                        disp);
-                                               if (opt_showdisassemble)
-                                                       M_NOP;
                                        } else {
                                                disp = dseg_add_address(cd, super->vftbl);
                                                M_TST(s1);
@@ -2461,8 +2321,7 @@ gen_method:
 #endif
                                        }
                                        M_CMPU(REG_ITMP3, REG_ITMP2);
-                                       M_BGT(0);
-                                       codegen_add_classcastexception_ref(cd, s1); /* XXX s1? */
+                                       emit_classcast_check(cd, iptr, BRANCH_GT, REG_ITMP3, s1);
                                }
                                d = codegen_reg_of_dst(jd, iptr, s1);
 
@@ -2474,13 +2333,10 @@ gen_method:
 
 
                                if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
-                                       disp = dseg_add_address(cd, NULL);
+                                       disp = dseg_add_unique_address(cd, NULL);
                                        codegen_addpatchref(cd, PATCHER_builtin_arraycheckcast,
                                                                                iptr->sx.s23.s3.c.ref,
                                                                                disp);
-
-                                       if (opt_showdisassemble)
-                                               M_NOP;
                                } else {
                                        disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
                                }
@@ -2492,8 +2348,7 @@ gen_method:
                                M_MTCTR(REG_ITMP2);
                                M_JSR;
                                M_TST(REG_RESULT);
-                               M_BEQ(0);
-                               codegen_add_classcastexception_ref(cd, s1); /* XXX s1? */
+                               emit_classcast_check(cd, iptr, BRANCH_EQ, REG_RESULT, s1);
 
                                s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                                d = codegen_reg_of_dst(jd, iptr, s1);
@@ -2502,6 +2357,7 @@ gen_method:
                        emit_store_dst(jd, iptr, d);
                        break;
 
+
                case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult            */
                                      /* val.a: (classinfo*) superclass               */
 
@@ -2548,30 +2404,27 @@ gen_method:
 
                        s2 = 8;
                        if (!super)
-                               s2 += (opt_showdisassemble ? 1 : 0);
+                               s2 += (opt_shownops ? 1 : 0);
 
                        /* calculate class instanceof code size */
 
-                       s3 = 10;
-                       if (!super)
-                               s3 += (opt_showdisassemble ? 1 : 0);
+                       s3 = 11;
+                       if (super == NULL)
+                               s3 += (opt_shownops ? 1 : 0);
 
                        M_CLR(d);
 
                        /* if class is not resolved, check which code to call */
 
-                       if (!super) {
+                       if (super == NULL) {
                                M_TST(s1);
-                               M_BEQ(3 + (opt_showdisassemble ? 1 : 0) + s2 + 1 + s3);
+                               M_BEQ(3 + (opt_shownops ? 1 : 0) + s2 + 1 + s3);
 
                                disp = dseg_add_unique_s4(cd, 0);                     /* super->flags */
 
                                codegen_addpatchref(cd, PATCHER_checkcast_instanceof_flags,
                                                                        iptr->sx.s23.s3.c.ref, disp);
 
-                               if (opt_showdisassemble)
-                                       M_NOP;
-
                                M_ILD(REG_ITMP3, REG_PV, disp);
                                M_AND_IMM(REG_ITMP3, ACC_INTERFACE, REG_ITMP3);
                                M_BEQ(s2 + 1);
@@ -2586,11 +2439,8 @@ gen_method:
 
                                } else {
                                        codegen_addpatchref(cd,
-                                                                               PATCHER_checkcast_instanceof_interface,
+                                                                               PATCHER_instanceof_interface,
                                                                                iptr->sx.s23.s3.c.ref, 0);
-
-                                       if (opt_showdisassemble)
-                                               M_NOP;
                                }
 
                                M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
@@ -2604,27 +2454,24 @@ gen_method:
                                M_BEQ(1);
                                M_IADD_IMM(REG_ZERO, 1, d);
 
-                               if (!super)
+                               if (super == NULL)
                                        M_BR(s3);
                        }
 
                        /* class instanceof code */
 
-                       if (!super || !(super->flags & ACC_INTERFACE)) {
-                               disp = dseg_add_address(cd, supervftbl);
+                       if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
 
                                if (super) {
+                                       disp = dseg_add_address(cd, supervftbl);
                                        M_TST(s1);
                                        M_BEQ(s3);
 
                                } else {
+                                       disp = dseg_add_unique_address(cd, NULL);
                                        codegen_addpatchref(cd, PATCHER_instanceof_class,
                                                                                iptr->sx.s23.s3.c.ref,
                                                                                disp);
-
-                                       if (opt_showdisassemble) {
-                                               M_NOP;
-                                       }
                                }
 
                                M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
@@ -2639,6 +2486,7 @@ gen_method:
                                codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
 #endif
                                M_SUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
+                               M_EXTSW(REG_ITMP1, REG_ITMP1);
                                M_CMPU(REG_ITMP1, REG_ITMP2);
                                M_CLR(d);
                                M_BGT(1);
@@ -2677,14 +2525,10 @@ gen_method:
                        /* is patcher function set? */
 
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
-                               disp = dseg_add_address(cd, NULL);
+                               disp = dseg_add_unique_address(cd, NULL);
 
                                codegen_addpatchref(cd, PATCHER_builtin_multianewarray,
                                                                        iptr->sx.s23.s3.c.ref, disp);
-
-                               if (opt_showdisassemble)
-                                       M_NOP;
-
                        } else {
                                disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
                        }
@@ -2708,10 +2552,7 @@ gen_method:
                        M_JSR;
 
                        /* check for exception before result assignment */
-
-                       M_CMPI(REG_RESULT, 0);
-                       M_BEQ(0);
-                       codegen_add_fillinstacktrace_ref(cd);
+                       emit_exception_check(cd, iptr);
 
                        d = codegen_reg_of_dst(jd, iptr, REG_RESULT);
                        M_INTMOVE(REG_RESULT, d);
@@ -2731,220 +2572,10 @@ gen_method:
 
        dseg_createlinenumbertable(cd);
 
+       /* generate stubs */
 
-       /* generate exception and patcher stubs */
-
-       {
-               exceptionref *eref;
-               patchref     *pref;
-               u4            mcode;
-               u1           *savedmcodeptr;
-               u1           *tmpmcodeptr;
-
-               savedmcodeptr = NULL;
-
-               /* generate exception stubs */
-
-               for (eref = cd->exceptionrefs; eref != NULL; eref = eref->next) {
-                       md_codegen_patch_branch(cd, eref->branchpos, cd->mcodeptr - cd->mcodebase);
-
-                       MCODECHECK(100);
-
-                       /* Check if the exception is an
-                          ArrayIndexOutOfBoundsException.  If so, move index register
-                          into REG_ITMP1. */
-
-                       if (eref->reg != -1)
-                               M_MOV(eref->reg, REG_ITMP1);
-
-                       /* calcuate exception address */
-
-                       M_LDA(REG_ITMP2_XPC, REG_PV, eref->branchpos - 4);
-
-                       /* move function to call into REG_ITMP3 */
-
-                       disp = dseg_add_functionptr(cd, eref->function);
-                       M_ALD(REG_ITMP3, REG_PV, disp);
-                       M_ALD(REG_ITMP3, REG_ITMP3, 0); /* TOC */
-
-                       if (savedmcodeptr != NULL) {
-                               disp = ((u4 *) savedmcodeptr) - (((u4 *) cd->mcodeptr) + 1);
-                               M_BR(disp);
-
-                       } else {
-                               savedmcodeptr = cd->mcodeptr;
-
-                               if (jd->isleafmethod) {
-                                       M_MFLR(REG_ZERO);
-                                       M_AST(REG_ZERO, REG_SP, cd->stackframesize * 8 + LA_LR_OFFSET);
-                               }
-
-                               M_MOV(REG_PV, rd->argintregs[0]);
-                               M_MOV(REG_SP, rd->argintregs[1]);
-
-                               if (jd->isleafmethod)
-                                       M_MOV(REG_ZERO, rd->argintregs[2]);
-                               else
-                                       M_ALD(rd->argintregs[2],
-                                                 REG_SP, cd->stackframesize * 8 + LA_LR_OFFSET);
-
-                               M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
-                               M_MOV(REG_ITMP1, rd->argintregs[4]);
-
-                               M_STDU(REG_SP, REG_SP, -(LA_SIZE + 6 * 8));
-                               M_AST(REG_ITMP2_XPC, REG_SP, LA_SIZE + 5 * 8);
-
-                               M_MTCTR(REG_ITMP3);
-                               M_JSR;
-                               M_MOV(REG_RESULT, REG_ITMP1_XPTR);
-
-                               M_ALD(REG_ITMP2_XPC, REG_SP, LA_SIZE + 5 * 8);
-                               M_LADD_IMM(REG_SP, LA_SIZE + 6 * 8, REG_SP);
-
-                               if (jd->isleafmethod) {
-                                       /* XXX FIXME: REG_ZERO can cause problems here! */
-                                       assert(cd->stackframesize * 8 <= 32767);
-
-                                       M_ALD(REG_ZERO, REG_SP, cd->stackframesize * 8 + LA_LR_OFFSET);
-                                       M_MTLR(REG_ZERO);
-                               }
-
-                               disp = dseg_add_functionptr(cd, asm_handle_exception);
-                               M_ALD(REG_ITMP3, REG_PV, disp);
-                               M_MTCTR(REG_ITMP3);
-                               M_RTS;
-                       }
-               }
-
-
-               /* generate code patching stub call code */
-
-               for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
-                       /* check code segment size */
-
-                       MCODECHECK(16);
-
-                       /* Get machine code which is patched back in later. The
-                          call is 1 instruction word long. */
-
-                       tmpmcodeptr = (u1 *) (cd->mcodebase + pref->branchpos);
-
-                       mcode = *((u4 *) tmpmcodeptr);
-
-                       /* Patch in the call to call the following code (done at
-                          compile time). */
-
-                       savedmcodeptr = cd->mcodeptr;   /* save current mcodeptr          */
-                       cd->mcodeptr  = tmpmcodeptr;    /* set mcodeptr to patch position */
-
-                       disp = ((u4 *) savedmcodeptr) - (((u4 *) tmpmcodeptr) + 1);
-                       M_BR(disp);
-
-                       cd->mcodeptr = savedmcodeptr;   /* restore the current mcodeptr   */
-
-                       /* create stack frame - keep stack 16-byte aligned */
-
-                       M_AADD_IMM(REG_SP, -8 * 8, REG_SP);
-
-                       /* calculate return address and move it onto the stack */
-
-                       M_LDA(REG_ITMP3, REG_PV, pref->branchpos);
-                       M_AST_INTERN(REG_ITMP3, REG_SP, 5 * 8);
-
-                       /* move pointer to java_objectheader onto stack */
-
-#if defined(ENABLE_THREADS)
-                       /* order reversed because of data segment layout */
-
-                       (void) dseg_add_unique_address(cd, NULL);                         /* flcword    */
-                       (void) dseg_add_unique_address(cd, lock_get_initial_lock_word()); /* monitorPtr */
-                       disp = dseg_add_unique_address(cd, NULL);                         /* vftbl      */
-
-                       M_LDA(REG_ITMP3, REG_PV, disp);
-                       M_AST_INTERN(REG_ITMP3, REG_SP, 4 * 8);
-#else
-                       /* do nothing */
-#endif
-
-                       /* move machine code onto stack */
-
-                       disp = dseg_add_unique_s4(cd, mcode);
-                       M_ILD(REG_ITMP3, REG_PV, disp);
-                       M_IST_INTERN(REG_ITMP3, REG_SP, 3 * 8);
-
-                       /* move class/method/field reference onto stack */
-
-                       disp = dseg_add_unique_address(cd, pref->ref);
-                       M_ALD(REG_ITMP3, REG_PV, disp);
-                       M_AST_INTERN(REG_ITMP3, REG_SP, 2 * 8);
-
-                       /* move data segment displacement onto stack */
-
-                       disp = dseg_add_functionptr(cd, pref->disp);
-                       M_LLD(REG_ITMP3, REG_PV, disp);
-                       M_IST_INTERN(REG_ITMP3, REG_SP, 1 * 8);
-
-                       /* move patcher function pointer onto stack */
-
-                       disp = dseg_add_functionptr(cd, pref->patcher);
-                       M_ALD(REG_ITMP3, REG_PV, disp);
-                       M_AST_INTERN(REG_ITMP3, REG_SP, 0 * 8);
-
-                       disp = dseg_add_functionptr(cd, asm_patcher_wrapper);
-                       M_ALD(REG_ITMP3, REG_PV, disp);
-                       M_MTCTR(REG_ITMP3);
-                       M_RTS;
-               }
-
-               /* generate replacement-out stubs */
-
-#if 0
-               {
-                       int i;
-
-                       replacementpoint = jd->code->rplpoints;
-
-                       for (i = 0; i < jd->code->rplpointcount; ++i, ++replacementpoint) {
-                               /* check code segment size */
-
-                               MCODECHECK(100);
-
-                               /* note start of stub code */
-
-                               replacementpoint->outcode = (u1 *) (cd->mcodeptr - cd->mcodebase);
-
-                               /* make machine code for patching */
-
-                               tmpmcodeptr  = cd->mcodeptr;
-                               cd->mcodeptr = (u1 *) &(replacementpoint->mcode) + 1 /* big-endian */;
-
-                               disp = (ptrint)((s4*)replacementpoint->outcode - (s4*)replacementpoint->pc) - 1;
-                               M_BR(disp);
-
-                               cd->mcodeptr = tmpmcodeptr;
-
-                               /* create stack frame - keep 16-byte aligned */
-
-                               M_AADD_IMM(REG_SP, -4 * 4, REG_SP);
-
-                               /* push address of `rplpoint` struct */
-
-                               disp = dseg_add_unique_address(cd, replacementpoint);
-                               M_ALD(REG_ITMP3, REG_PV, disp);
-                               M_AST_INTERN(REG_ITMP3, REG_SP, 0 * 4);
-
-                               /* jump to replacement function */
-
-                               disp = dseg_add_unique_address(cd, asm_replacement_out);
-                               M_ALD(REG_ITMP3, REG_PV, disp);
-                               M_MTCTR(REG_ITMP3);
-                               M_RTS;
-                       }
-               }
-#endif
-       }
-
-       codegen_finish(jd);
+       emit_patcher_stubs(jd);
+       REPLACEMENT_EMIT_STUBS(jd);
 
        /* everything's ok */
 
@@ -3083,9 +2714,6 @@ u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd)
 #if !defined(WITH_STATIC_CLASSPATH)
        if (f == NULL) {
                codegen_addpatchref(cd, PATCHER_resolve_native, m, funcdisp);
-
-               if (opt_showdisassemble)
-                       M_NOP;
        }
 #endif
 
@@ -3228,11 +2856,7 @@ u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd)
                        M_LST(REG_RESULT, REG_SP, LA_SIZE + PA_SIZE + 1 * 8);
                }
                else {
-/*                     if (IS_2_WORD_TYPE(md->returntype.type)) */
-                               M_DST(REG_FRESULT, REG_SP, LA_SIZE + PA_SIZE + 1 * 8);
-/*                     else
-                               M_FST(REG_FRESULT, REG_SP, LA_SIZE + PA_SIZE + 1 * 8);  */ /* FIXME, needed F XXX?*/
-                       
+                       M_DST(REG_FRESULT, REG_SP, LA_SIZE + PA_SIZE + 1 * 8);
                }
        }
 
index efe7bb1367db95e9f21555605b8c47c4bc40d357..4d3d4aef4acce1845424805b83b792f9e6bb3789 100644 (file)
@@ -30,7 +30,7 @@
             Christian Thalinger
             Christian Ullrich
 
-   $Id: codegen.h 6078 2006-11-28 22:19:16Z twisti $
+   $Id: codegen.h 6199 2006-12-15 14:27:37Z tbfg $
 
 */
 
 
 /* additional functions and macros to generate code ***************************/
 
-/* gen_nullptr_check(objreg) */
-
-#define gen_nullptr_check(objreg) \
-    if (checknull) { \
-        M_TST((objreg)); \
-        M_BEQ(0); \
-        codegen_add_nullpointerexception_ref(cd); \
-    }
-
-#define gen_bound_check \
-    if (checkbounds) { \
-        M_ILD(REG_ITMP3, s1, OFFSET(java_arrayheader, size));\
-        M_CMPU(s2, REG_ITMP3);\
-        M_BGE(0);\
-        codegen_add_arrayindexoutofboundsexception_ref(cd, s2); \
-    }
-
-
 /* MCODECHECK(icnt) */
 
 #define MCODECHECK(icnt) \
 
 
 /* branch defines *************************************************************/
-
+/* and additional branch is needed when generating long branches */
 #define BRANCH_NOPS \
     do { \
+       if (CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {\
+               M_NOP; \
+       } \
         M_NOP; \
     } while (0)
 
         cd->mcodeptr += 4; \
     } while (0)
 
+/* for instruction decodeing */
+#define M_INSTR_OP2_IMM_D(x)            (((x) >> 21) & 0x1f  )
+#define M_INSTR_OP2_IMM_A(x)            (((x) >> 16) & 0x1f  )
+#define M_INSTR_OP2_IMM_I(x)            ( (x)        & 0xffff)
+
 #define M_BCMASK     0x0000fffc                     /* (((1 << 16) - 1) & ~3) */
 #define M_BMASK    0x03fffffc                     /* (((1 << 26) - 1) & ~3) */
 
 #define M_ADDIS(a,b,c)                  M_OP2_IMM(15, c, a, b)
 #define M_STFIWX(a,b,c)                 M_OP3(31, 983, 0, 0, a, b, c)
 
-#define M_LWZX(a,b,c)                   M_OP3(31, 23, 0, 0, a, b, c)
+#define M_LWAX(a,b,c)                   M_OP3(31, 341, 0, 0, a, b, c)
 #define M_LHZX(a,b,c)                   M_OP3(31, 279, 0, 0, a, b, c)
 #define M_LHAX(a,b,c)                   M_OP3(31, 343, 0, 0, a, b, c)
 #define M_LHAX(a,b,c)                   M_OP3(31, 343, 0, 0, a, b, c)
 #define M_ILD_INTERN(a,b,disp)          M_OP2_IMM(32,a,b,disp) /* LWZ */
 #endif
 
-#define M_ILD_INTERN(a,b,disp)         M_OP2_IMM(58, a, b, (((disp) & 0xfffe) | 0x0002))
+#define M_LWZ(a,b,disp)                        M_OP2_IMM(32,a,b,disp)  /* needed for hardware exceptions */
+
+#define M_ILD_INTERN(a,b,disp)         M_OP2_IMM(58, a, b, (((disp) & 0xfffe) | 0x0002))       /* this is LWA actually */
 
 #define M_ILD(a,b,disp) \
     do { \
index f4fc1cd7968215d195afff13f0cac0ad4d030d48..43fd7ed74c0a8daacc877a58a85c23eb9690c5a3 100644 (file)
@@ -1,6 +1,6 @@
-/* src/vm/jit/powerpc64/emit.c - PowerPC code emitter functions
+/* src/vm/jit/powerpc64/emit.c - PowerPC64 code emitter functions
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
    J. Wenninger, Institut f. Computersprachen - TU Wien
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Christian Thalinger
-
-   Changes:
-
    $Id: emitfuncs.c 4398 2006-01-31 23:43:08Z twisti $
 
 */
 
 #include "vm/types.h"
 
+#include "mm/memory.h"
+
 #include "md-abi.h"
 #include "vm/jit/powerpc64/codegen.h"
 
+#include "vmcore/options.h"
+
 #include "vm/builtin.h"
 #include "vm/jit/emit-common.h"
 #include "vm/jit/jit.h"
+#include "vm/vm.h"
+#include "vm/jit/asmpart.h"
+#include "vm/exceptions.h"
+
+#if defined(ENABLE_THREADS)
+# include "threads/native/lock.h"
+#endif
 
 
 /* emit_load *******************************************************************
@@ -69,10 +74,7 @@ s4 emit_load(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
                disp = src->vv.regoff * 8;
 
                if (IS_FLT_DBL_TYPE(src->type)) {
-                       if (IS_2_WORD_TYPE(src->type))
-                               M_DLD(tempreg, REG_SP, disp);
-                       else
-                               M_FLD(tempreg, REG_SP, disp);
+                       M_DLD(tempreg, REG_SP, disp);
                }
                else {
                        M_LLD(tempreg, REG_SP, disp);
@@ -105,10 +107,7 @@ void emit_store(jitdata *jd, instruction *iptr, varinfo *dst, s4 d)
                COUNT_SPILLS;
 
                if (IS_FLT_DBL_TYPE(dst->type)) {
-/*                     if (IS_2_WORD_TYPE(dst->type))*/
-                               M_DST(d, REG_SP, dst->vv.regoff * 8);
-/*                     else
-                               M_DST(d, REG_SP, dst->vv.regoff * 8); F XXX */
+                       M_DST(d, REG_SP, dst->vv.regoff * 8);
                }
                else {
                        M_LST(d, REG_SP, dst->vv.regoff * 8);
@@ -193,10 +192,10 @@ void emit_lconst(codegendata *cd, s4 d, s8 value)
 
 
 /* emit_verbosecall_enter ******************************************************
- *
*    Generates the code for the call trace.
- *
- ********************************************************************************/
+
+   Generates the code for the call trace.
+
+*******************************************************************************/
 
 void emit_verbosecall_enter (jitdata *jd)
 {
@@ -299,7 +298,7 @@ void emit_verbosecall_enter (jitdata *jd)
 #endif
        /* call via function descriptor */
        /* XXX: what about TOC? */
-       p = dseg_add_functionptr(cd, builtin_trace_args);
+       p = dseg_add_functionptr(cd, builtin_verbosecall_enter);
        M_ALD(REG_ITMP2, REG_PV, p);
        M_ALD(REG_ITMP1, REG_ITMP2, 0);
        M_MTCTR(REG_ITMP1);
@@ -338,17 +337,26 @@ void emit_verbosecall_enter (jitdata *jd)
 
 
 /* emit_verbosecall_exit ******************************************************
- *
- *    Generates the code for the call trace.
- *
- ********************************************************************************/
+
+   Generates the code for the call trace.
+
+   void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m);
+
+*******************************************************************************/
 
 void emit_verbosecall_exit(jitdata *jd)
 {
-       codegendata *cd = jd->cd;
-       s4 disp;
+       methodinfo   *m;
+       codegendata  *cd;
+       s4            disp;
+
+       /* get required compiler data */
+
+       m  = jd->m;
+       cd = jd->cd;
 
        /* mark trace code */
+
        M_NOP;
 
        M_MFLR(REG_ZERO);
@@ -357,18 +365,15 @@ void emit_verbosecall_exit(jitdata *jd)
        M_LST(REG_RESULT, REG_SP, LA_SIZE+PA_SIZE+1*8);
        M_AST(REG_ZERO, REG_SP, LA_SIZE+PA_SIZE+2*8);
 
-#if defined(__DARWIN__)
-       M_MOV(REG_RESULT, jd->rd->argintregs[1]);
-#else
-       M_MOV(REG_RESULT, jd->rd->argintregs[1]);
-#endif
+       M_MOV(REG_RESULT, REG_A0);
+
+       M_FLTMOVE(REG_FRESULT, REG_FA0);
+       M_FLTMOVE(REG_FRESULT, REG_FA1);
 
-       disp = dseg_add_address(cd, jd->m);
-       M_ALD(jd->rd->argintregs[0], REG_PV, disp);
+       disp = dseg_add_address(cd, m);
+       M_ALD(REG_A3, REG_PV, disp);
 
-       M_FLTMOVE(REG_FRESULT, jd->rd->argfltregs[0]);
-       M_FLTMOVE(REG_FRESULT, jd->rd->argfltregs[1]);
-       disp = dseg_add_functionptr(cd, builtin_displaymethodstop);
+       disp = dseg_add_functionptr(cd, builtin_verbosecall_exit);
        /* call via function descriptor, XXX: what about TOC ? */
        M_ALD(REG_ITMP2, REG_PV, disp);
        M_ALD(REG_ITMP2, REG_ITMP2, 0);
@@ -382,21 +387,482 @@ void emit_verbosecall_exit(jitdata *jd)
        M_MTLR(REG_ZERO);
 
        /* mark trace code */
+
        M_NOP;
 }
 
+/* emit_branch *****************************************************************
+
+   Emits the code for conditional and unconditional branchs.
+
+*******************************************************************************/
+
+void emit_branch(codegendata *cd, s4 disp, s4 condition, s4 reg, u4 opt)
+{
+       s4 checkdisp;
+       s4 branchdisp;
+
+       /* calculate the different displacements */
+
+       checkdisp  =  disp + 4;
+       branchdisp = (disp - 4) >> 2;
+
+       /* check which branch to generate */
+
+       if (condition == BRANCH_UNCONDITIONAL) {
+               /* check displacement for overflow */
+
+               if ((checkdisp < (s4) 0xfe000000) || (checkdisp > (s4) 0x01fffffc)) {
+                       /* if the long-branches flag isn't set yet, do it */
+
+                       if (!CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
+                               log_println("setting error");
+                               cd->flags |= (CODEGENDATA_FLAG_ERROR |
+                                                         CODEGENDATA_FLAG_LONGBRANCHES);
+                       }
+
+                       vm_abort("emit_branch: emit unconditional long-branch code");
+               }
+               else {
+                       M_BR(branchdisp);
+               }
+       }
+       else {
+               /* and displacement for overflow */
+
+               if ((checkdisp < (s4) 0xffff8000) || (checkdisp > (s4) 0x00007fff)) {
+                       /* if the long-branches flag isn't set yet, do it */
+
+                       if (!CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
+                               log_println("setting error");
+                               cd->flags |= (CODEGENDATA_FLAG_ERROR |
+                                                         CODEGENDATA_FLAG_LONGBRANCHES);
+                       }
+                       log_println("generating long-branch");
+
+                       branchdisp --;          /* we jump from the second instruction */
+                       switch (condition) {
+                       case BRANCH_EQ:
+                               M_BNE(1);
+                               M_BR(branchdisp);
+                               break;
+                       case BRANCH_NE:
+                               M_BEQ(1);
+                               M_BR(branchdisp);
+                               break;
+                       case BRANCH_LT:
+                               M_BGE(1);
+                               M_BR(branchdisp);
+                               break;
+                       case BRANCH_GE:
+                               M_BLT(1);
+                               M_BR(branchdisp);
+                               break;
+                       case BRANCH_GT:
+                               M_BLE(1);
+                               M_BR(branchdisp);
+                               break;
+                       case BRANCH_LE:
+                               M_BGT(1);
+                               M_BR(branchdisp);
+                               break;
+                       case BRANCH_NAN:
+                               vm_abort("emit_branch: long BRANCH_NAN");
+                               break;
+                       default:
+                               vm_abort("emit_branch: unknown condition %d", condition);
+                       }
+
+               }
+               else {
+                       switch (condition) {
+                       case BRANCH_EQ:
+                               M_BEQ(branchdisp);
+                               break;
+                       case BRANCH_NE:
+                               M_BNE(branchdisp);
+                               break;
+                       case BRANCH_LT:
+                               M_BLT(branchdisp);
+                               break;
+                       case BRANCH_GE:
+                               M_BGE(branchdisp);
+                               break;
+                       case BRANCH_GT:
+                               M_BGT(branchdisp);
+                               break;
+                       case BRANCH_LE:
+                               M_BLE(branchdisp);
+                               break;
+                       case BRANCH_NAN:
+                               M_BNAN(branchdisp);
+                               break;
+                       default:
+                               vm_abort("emit_branch: unknown condition %d", condition);
+                       }
+               }
+       }
+}
+
+/* emit_arrayindexoutofbounds_check ********************************************
+
+   Emit a ArrayIndexOutOfBoundsException check.
+
+*******************************************************************************/
+
+void emit_arrayindexoutofbounds_check(codegendata *cd, instruction *iptr, s4 s1, s4 s2)
+{
+       if (checkbounds) {
+#define SOFTEX 0
+#if SOFTEX
+               M_ILD(REG_ITMP3, s1, OFFSET(java_arrayheader, size));
+               M_CMPU(s2, REG_ITMP3);
+               codegen_add_arrayindexoutofboundsexception_ref(cd, s2);
+               BRANCH_NOPS;
+#else
+               M_ILD(REG_ITMP3, s1, OFFSET(java_arrayheader, size));
+               M_CMPU(s2, REG_ITMP3);
+               M_BLT(1);
+               /* ALD is 4 byte aligned, ILD 2, onyl LWZ is byte aligned */
+               M_LWZ(s2, REG_ZERO, EXCEPTION_HARDWARE_ARRAYINDEXOUTOFBOUNDS);
+#endif
+       }
+}
+
+
+/* emit_arithmetic_check *******************************************************
+
+   Emit an ArithmeticException check.
+
+*******************************************************************************/
+
+void emit_arithmetic_check(codegendata *cd, instruction *iptr, s4 reg)
+{
+       if (INSTRUCTION_MUST_CHECK(iptr))       {
+       #if SOFTEX
+               M_TST(reg);
+               codegen_add_arithmeticexception_ref(cd);
+               BRANCH_NOPS;
+       #else
+               M_TST(reg);
+               M_BNE(1);
+               /* ALD is 4 byte aligned, ILD 2, onyl LWZ is byte aligned */
+               M_LWZ(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_ARITHMETIC);
+       #endif
+       }
+}
+
+#if 0
+/* emit_arraystore_check *******************************************************
+
+   Emit an ArrayStoreException check.
+
+*******************************************************************************/
+
+void emit_arraystore_check(codegendata *cd, instruction *iptr, s4 reg)
+{
+       if (INSTRUCTION_MUST_CHECK(iptr))       {
+               M_TST(REG_RESULT);
+               codegen_add_arraystoreexception_ref(cd);
+               BRANCH_NOPS;
+       }
+}
+#endif
+
+/* emit_classcast_check ********************************************************
+
+   Emit a ClassCastException check.
+
+*******************************************************************************/
+
+void emit_classcast_check(codegendata *cd, instruction *iptr, s4 condition, s4 reg, s4 s1)
+{
+       if (INSTRUCTION_MUST_CHECK(iptr))       {
+       #if SOFTEX
+               codegen_add_classcastexception_ref(cd, condition, s1);
+               BRANCH_NOPS;
+               M_NOP;
+       #else
+               switch(condition)       {
+                       case BRANCH_LE:
+                               M_BGT(1);
+                               break;
+                       case BRANCH_EQ:
+                               M_BNE(1);
+                               break;
+                       case BRANCH_GT:
+                               M_BLE(1);
+                               break;
+                       default:
+                               vm_abort("emit_classcast_check: unknown condition %d", condition);
+               }
+               /* ALD is 4 byte aligned, ILD 2, onyl LWZ is byte aligned */
+               M_LWZ(s1, REG_ZERO, EXCEPTION_HARDWARE_CLASSCAST);
+       #endif
+       }
+}
+
+
+/* emit_nullpointer_check ******************************************************
+
+   Emit a NullPointerException check.
+
+*******************************************************************************/
+
+void emit_nullpointer_check(codegendata *cd, instruction *iptr, s4 reg)
+{
+       if (INSTRUCTION_MUST_CHECK(iptr))       {
+               M_TST(reg);
+               M_BNE(1);
+               /* ALD is 4 byte aligned, ILD 2, onyl LWZ is byte aligned */
+               M_LWZ(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_NULLPOINTER);
+       }
+}
+
+/* emit_exception_check ********************************************************
+
+   Emit an Exception check.
+
+*******************************************************************************/
+
+void emit_exception_check(codegendata *cd, instruction *iptr)
+{
+       if (INSTRUCTION_MUST_CHECK(iptr))       {
+       #if SOFTEX
+               M_CMPI(REG_RESULT, 0);
+               codegen_add_fillinstacktrace_ref(cd);
+               BRANCH_NOPS;
+       #else
+               M_TST(REG_RESULT);
+               M_BNE(1);
+               /* ALD is 4 byte aligned, ILD 2, onyl LWZ is byte aligned */
+               M_LWZ(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_EXCEPTION);
+       #endif
+       }
+}
+
+
+/* emit_patcher_stubs **********************************************************
+
+   Generates the code for the patcher stubs.
+
+*******************************************************************************/
+void emit_patcher_stubs(jitdata *jd)
+{
+       codegendata *cd;
+       patchref    *pref;
+       u4           mcode;
+       u1          *savedmcodeptr;
+       u1          *tmpmcodeptr;
+       s4           targetdisp;
+       s4           disp;
+
+       cd = jd->cd;
+
+       /* generate code patching stub call code */
+
+       targetdisp = 0;
+
+       for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
+               /* check code segment size */
+
+               MCODECHECK(16);
 
+               /* Get machine code which is patched back in later. The
+                  call is 1 instruction word long. */
+
+               tmpmcodeptr = (u1 *) (cd->mcodebase + pref->branchpos);
+
+               mcode = *((u4 *) tmpmcodeptr);
+
+               /* Patch in the call to call the following code (done at
+                  compile time). */
+
+               savedmcodeptr = cd->mcodeptr;   /* save current mcodeptr          */
+               cd->mcodeptr  = tmpmcodeptr;    /* set mcodeptr to patch position */
+
+               disp = ((u4 *) savedmcodeptr) - (((u4 *) tmpmcodeptr) + 1);
+               M_BR(disp);
+
+               cd->mcodeptr = savedmcodeptr;   /* restore the current mcodeptr   */
+
+               /* create stack frame - keep stack 16-byte aligned */
+
+               M_AADD_IMM(REG_SP, -8 * 8, REG_SP);
+
+               /* calculate return address and move it onto the stack */
+
+               M_LDA(REG_ITMP3, REG_PV, pref->branchpos);
+               M_AST_INTERN(REG_ITMP3, REG_SP, 5 * 8);
+
+               /* move pointer to java_objectheader onto stack */
+
+#if defined(ENABLE_THREADS)
+               /* order reversed because of data segment layout */
+
+               (void) dseg_add_unique_address(cd, NULL);                         /* flcword    */
+               (void) dseg_add_unique_address(cd, lock_get_initial_lock_word()); /* monitorPtr */
+               disp = dseg_add_unique_address(cd, NULL);                         /* vftbl      */
+
+               M_LDA(REG_ITMP3, REG_PV, disp);
+               M_AST_INTERN(REG_ITMP3, REG_SP, 4 * 8);
+#else
+               /* do nothing */
+#endif
+
+               /* move machine code onto stack */
+
+               disp = dseg_add_s4(cd, mcode);
+               M_ILD(REG_ITMP3, REG_PV, disp);
+               M_IST_INTERN(REG_ITMP3, REG_SP, 3 * 8);
+
+               /* move class/method/field reference onto stack */
+
+               disp = dseg_add_address(cd, pref->ref);
+               M_ALD(REG_ITMP3, REG_PV, disp);
+               M_AST_INTERN(REG_ITMP3, REG_SP, 2 * 8);
+
+               /* move data segment displacement onto stack */
+
+               disp = dseg_add_s4(cd, pref->disp);
+               M_ILD(REG_ITMP3, REG_PV, disp);
+               M_IST_INTERN(REG_ITMP3, REG_SP, 1 * 8);
+               M_NOP;
+
+               /* move patcher function pointer onto stack */
+
+               disp = dseg_add_functionptr(cd, pref->patcher);
+               M_ALD(REG_ITMP3, REG_PV, disp);
+               M_AST_INTERN(REG_ITMP3, REG_SP, 0 * 8);
+
+#if 0
+               disp = dseg_add_functionptr(cd, asm_patcher_wrapper);
+               M_ALD(REG_ITMP3, REG_PV, disp);
+               M_MTCTR(REG_ITMP3);
+               M_RTS;
+#else
+               if (targetdisp == 0) {
+                       targetdisp = ((u4 *) cd->mcodeptr) - ((u4 *) cd->mcodebase);
+
+                       disp = dseg_add_functionptr(cd, asm_patcher_wrapper);
+                       M_ALD(REG_ITMP3, REG_PV, disp);
+                       M_MTCTR(REG_ITMP3);
+                       M_RTS;
+               }
+               else {
+                       disp = (((u4 *) cd->mcodebase) + targetdisp) -
+                               (((u4 *) cd->mcodeptr) + 1);
+                       M_BR(disp);
+               }
+#endif
+       }
+}
+
+
+/* emit_replacement_stubs ******************************************************
+
+   Generates the code for the replacement stubs.
+
+*******************************************************************************/
+
+#if defined(ENABLE_REPLACEMENT)
+void emit_replacement_stubs(jitdata *jd)
+{
+       codegendata *cd;
+       codeinfo    *code;
+       rplpoint    *replacementpoint;
+       s4           disp;
+       s4           i;
+#if !defined(NDEBUG)
+       u1          *savedmcodeptr;
+#endif
+
+       /* get required compiler data */
+
+       cd   = jd->cd;
+       code = jd->code;
+
+       replacementpoint = jd->code->rplpoints;
+
+       for (i = 0; i < code->rplpointcount; ++i, ++replacementpoint) {
+               /* do not generate stubs for non-trappable points */
+
+               if (replacementpoint->flags & RPLPOINT_FLAG_NOTRAP)
+                       continue;
+
+
+               /* check code segment size */
+
+               MCODECHECK(100);
+
+#if !defined(NDEBUG)
+               savedmcodeptr = cd->mcodeptr;
+#endif
+               /* create stack frame - keep 16-byte aligned */
+
+               M_AADD_IMM(REG_SP, -4 * 8, REG_SP);
+
+               /* push address of `rplpoint` struct */
+
+               disp = dseg_add_address(cd, replacementpoint);
+               M_ALD(REG_ITMP3, REG_PV, disp);
+               M_AST_INTERN(REG_ITMP3, REG_SP, 0 * 8);
+
+               /* jump to replacement function */
+
+               disp = dseg_add_functionptr(cd, asm_replacement_out);
+               M_ALD(REG_ITMP3, REG_PV, disp);
+               M_MTCTR(REG_ITMP3);
+               M_RTS;
+
+               assert((cd->mcodeptr - savedmcodeptr) == 4*REPLACEMENT_STUB_SIZE);
+
+#if 0
+               /* note start of stub code */
+
+               replacementpoint->outcode = (u1 *) (cd->mcodeptr - cd->mcodebase);
+
+               /* make machine code for patching */
+
+               savedmcodeptr  = cd->mcodeptr;
+               cd->mcodeptr = (u1 *) &(replacementpoint->mcode) + 1 /* big-endian */;
+
+               disp = (ptrint)((s4*)replacementpoint->outcode - (s4*)replacementpoint->pc) - 1;
+               M_BR(disp);
+
+               cd->mcodeptr = savedmcodeptr;
+
+               /* create stack frame - keep 16-byte aligned */
+
+               M_AADD_IMM(REG_SP, -4 * 4, REG_SP);
+
+               /* push address of `rplpoint` struct */
+
+               disp = dseg_add_unique_address(cd, replacementpoint);
+               M_ALD(REG_ITMP3, REG_PV, disp);
+               M_AST_INTERN(REG_ITMP3, REG_SP, 0 * 4);
+
+               /* jump to replacement function */
+
+               disp = dseg_add_functionptr(cd, asm_replacement_out);
+               M_ALD(REG_ITMP3, REG_PV, disp);
+               M_MTCTR(REG_ITMP3);
+               M_RTS;
+#endif
+       }
+}
+#endif /* define(ENABLE_REPLACEMENT) */
 
 /*
- * 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
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
+* 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
+* Emacs will automagically detect them.
+* ---------------------------------------------------------------------
+* Local variables:
+* mode: c
+* indent-tabs-mode: t
+* c-basic-offset: 4
+* tab-width: 4
+* End:
+* vim:noexpandtab:sw=4:ts=4:
+*/
index 57da21e518ceb64300f452f2a4273a3d870e1b11..de93995d94d6ed3b0d755a332c7a5ec55805d78a 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: md-abi.c 7311 2007-02-09 13:20:27Z twisti $
+   $Id: md-abi.c 7452 2007-03-04 23:32:24Z twisti $
 
 */
 
@@ -41,6 +41,7 @@
 
 #include "vmcore/descriptor.h"
 
+
 #define CACAO_ALIGN(a)    do { if ((a) & 1) (a)++; } while (0)
 
 
@@ -62,7 +63,7 @@ s4 nregdescint[] = {
        REG_END
 };
 
-char *regs[] = {
+const char *abi_registers_integer_name[] = {
        "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7",
        "r8",  "r9",  "r10", "r11", "r12", "r13", "r14", "r15",
        "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
@@ -179,6 +180,21 @@ void md_param_alloc(methoddesc *md)
 }
 
 
+/* md_param_alloc_native *******************************************************
+
+   Pre-allocate arguments according the native ABI.
+
+*******************************************************************************/
+
+void md_param_alloc_native(methoddesc *md)
+{
+       /* On PowerPC64 we use the same ABI for JIT method calls as for
+          native method calls. */
+
+       md_param_alloc(md);
+}
+
+
 /* md_return_alloc *************************************************************
 
    Precolor the Java Stackelement containing the Return Value, if
index 9d6b365d79fbc900b0a69f7d2af1ba5402d8ad8e..a267cd540279c26ec54d6dc6ab4f40bd274db826 100644 (file)
@@ -1,6 +1,6 @@
 /* src/vm/jit/powerpc64/linux/md-abi.h - defines for PowerPC64 Linux ABI
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
    J. Wenninger, Institut f. Computersprachen - TU Wien
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Christian Thalinger
-
-   Changes:
-
-   $Id: md-abi.h 5940 2006-11-09 09:59:28Z tbfg $
+   $Id: md-abi.h 7515 2007-03-13 22:39:15Z twisti $
 
 */
 
@@ -40,6 +34,7 @@
 
 /* integer registers */
 
+#define REG_ZERO        0   /* almost always zero (in address caluclation)   */
 #define REG_TOC                 2   /* TOC (see function descriptors ELF ABI)        */
 #define REG_RESULT       3   /* to deliver method results                     */
 
 #define REG_SP           1   /* stack pointer                                 */
 #define REG_ZERO         0   /* almost always zero: only in address calc.     */
 
+#define REG_A0           3   /* define some argument registers                */
+#define REG_A1           4
+#define REG_A2           5
+#define REG_A3           6
+
 /* floating point registers */
 
 #define REG_FRESULT      1   /* to deliver floating point method results      */
@@ -65,6 +65,9 @@
 
 #define REG_IFTMP       16   /* temporary integer and floating point register */
 
+#define REG_FA0          1   /* define some argument registers                */
+#define REG_FA1          2
+
 
 #define INT_REG_CNT     32   /* number of integer registers                   */
 #define INT_SAV_CNT      9   /* number of int callee saved registers          */
index 671301d4ef93c94f7da812d315fd4a3058c32a8c..ef265d2c44f87a2010d9ee25e3b99f60ae830b28 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: md-os.c 7311 2007-02-09 13:20:27Z twisti $
+   $Id: md-os.c 7582 2007-03-26 09:27:10Z tbfg $
 
 */
 
@@ -34,6 +34,7 @@
 
 #include "vm/types.h"
 
+#include "vm/jit/powerpc64/codegen.h"
 #include "vm/jit/powerpc64/linux/md-abi.h"
 
 #if defined(ENABLE_THREADS)
 
 
 /* md_signal_handler_sigsegv ***************************************************
-
-   NullPointerException signal handler for hardware null pointer
-   check.
+       Signal handler for hardware-exceptions.
 
 *******************************************************************************/
 
 void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
 {
-       ucontext_t  *_uc;
-       mcontext_t  *_mc;
-       u4           instr;
-       s4           reg;
-       ptrint       addr;
-       u1          *pv;
-       u1          *sp;
-       u1          *ra;
-       u1          *xpc;
+       ucontext_t      *_uc;
+       mcontext_t      *_mc;
+       u1              *pv;
+       u1              *sp;
+       u1              *ra;
+       u1              *xpc;
+       u4              mcode;
+       s4              s1;
+       s4              disp;
+       s4              d;
+       s4              type;
+       ptrint          addr;
+       ptrint          val;
+       java_objectheader *e;
 
        _uc = (ucontext_t *) _p;
        _mc = &(_uc->uc_mcontext);
-       
-       pv  = (u1 *) _mc->gp_regs[REG_PV];
-       sp  = (u1 *) _mc->gp_regs[REG_SP];
-       ra  = (u1 *) _mc->gp_regs[PT_LNK];           /* this is correct for leafs */
-       xpc = (u1 *) _mc->gp_regs[PT_NIP];
-
-       instr = *((u4 *) xpc);
-       reg   = (instr >> 16) & 0x1f;
-       addr  = _mc->gp_regs[reg];
-
-       if (addr == 0) {
-               _mc->gp_regs[REG_ITMP1_XPTR] =
-                       (ptrint) stacktrace_hardware_nullpointerexception(pv, sp, ra, xpc);
-
-               _mc->gp_regs[REG_ITMP2_XPC] = (ptrint) xpc;
-               _mc->gp_regs[PT_NIP] = (ptrint) asm_handle_exception;
-       }
-       else {
-               codegen_get_pv_from_pc(xpc);
 
-               /* this should not happen */
+       /* get register values */
+       pv = (u1*) _mc->gp_regs[REG_PV];
+       sp = (u1*) _mc->gp_regs[REG_SP];
+       ra = (u1*) _mc->gp_regs[PT_LNK];                     /* correct for leafs */
+       xpc =(u1*) _mc->gp_regs[PT_NIP];
+
+       /* get the throwing instruction */
+       mcode = *((u4*)xpc);
+
+       s1   = M_INSTR_OP2_IMM_A(mcode);
+       disp = M_INSTR_OP2_IMM_I(mcode);
+       d    = M_INSTR_OP2_IMM_D(mcode);
+
+       val  = _mc->gp_regs[d];
+
+       if (s1 == REG_ZERO)     {
+               /* we use the exception type as load displacement */
+               type = disp;
+       } else  {
+               /* normal NPE */
+               addr = _mc->gp_regs[s1];
+               type = (s4) addr;
+       }
+       e = exceptions_new_hardware_exception(pv, sp, ra, xpc, type, val);
 
-               assert(0);
-       }               
+       _mc->gp_regs[REG_ITMP1]     = (ptrint) e;
+       _mc->gp_regs[REG_ITMP2_XPC] = (ptrint) xpc;
+       _mc->gp_regs[PT_NIP]        = (ptrint) asm_handle_exception;
 }
 
 
index d3940d833a5aa12e569d7e4a3bcbae9e374c19d0..289f8e9047f70d4940befcb7aef448e8c51696cc 100644 (file)
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: md.c 7311 2007-02-09 13:20:27Z twisti $
+   $Id: md.c 7355 2007-02-14 10:57:32Z twisti $
 
 */
 
+
 #include "config.h"
 
 #include <assert.h>
index f1b0e595fea123ece354f62320983fbd20493b79..34b2109c55827ca9f3854bee241e8d48093c55c7 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: patcher.c 7464 2007-03-06 00:26:31Z edwin $
+   $Id: patcher.c 7527 2007-03-15 15:54:06Z tbfg $
 
 */
 
@@ -34,6 +34,7 @@
 #include "vm/types.h"
 
 #include "mm/memory.h"
+
 #include "native/native.h"
 
 #include "vm/builtin.h"
@@ -41,9 +42,9 @@
 #include "vm/initialize.h"
 
 #include "vm/jit/asmpart.h"
-#include "vm/jit/patcher.h"
 #include "vm/jit/md.h"
 #include "vm/jit/methodheader.h"
+#include "vm/jit/patcher.h"
 #include "vm/jit/stacktrace.h"
 
 #include "vmcore/class.h"
@@ -216,7 +217,7 @@ bool patcher_get_putfield(u1 *sp)
 
        /* if we show disassembly, we have to skip the nop */
 
-       if (opt_showdisassemble)
+       if (opt_shownops)
                ra = ra + 4;
 
        /* patch the field's offset */
@@ -484,7 +485,7 @@ bool patcher_invokevirtual(u1 *sp)
 
        /* if we show disassembly, we have to skip the nop */
 
-       if (opt_showdisassemble)
+       if (opt_shownops)
                ra = ra + 4;
 
        /* patch vftbl index */
@@ -539,7 +540,7 @@ bool patcher_invokeinterface(u1 *sp)
 
        /* if we show disassembly, we have to skip the nop */
 
-       if (opt_showdisassemble)
+       if (opt_shownops)
                ra = ra + 4;
 
        /* patch interfacetable index */
@@ -616,9 +617,62 @@ bool patcher_checkcast_instanceof_flags(u1 *sp)
 
        return true;
 }
+/* patcher_checkcast_interface **************************************
+
+   Machine code:
+
+   <patched call position>
+   81870000    lwz   r12,0(r7)
+   800c0010    lwz   r0,16(r12)
+   34000000    addic.        r0,r0,0
+   408101fc    bgt-  0x3002e518                FIXME
+   83c00003    lwz   r30,3(0)          FIXME
+   800c0000    lwz   r0,0(r12)
+
+*******************************************************************************/
+bool patcher_checkcast_interface(u1 *sp)
+{
+       u1 *ra;
+       constant_classref *cr;
+       classinfo *c;
+       s4 disp;
+       u4 mcode;
+
+       /* get stuff from stack */
+       ra = (u1*)                      *((ptrint *)(sp + 5*8));
+       mcode =                         *((u4*) (sp + 3*8));
+       cr = (constant_classref*)       *((ptrint*)(sp+2*8));
+
+       /* get the fieldinfo */
+       if (!(c = resolve_classref_eager(cr)))  {
+               return false;
+       }
+
+       /* patch back original code */
+       *((u4 *) ra) = mcode;
+
+       /* if we show NOPs, we have to skip them */
+       if (opt_shownops)       {
+               ra = ra +4;
+       }
+
+       /* patch super class index */
+       disp = -(c->index);
+
+       *((s4*)(ra + 2*4)) |= (disp & 0x0000ffff);
+
+       disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
+
+       *((s4 *)(ra + 5*4)) |= (disp & 0x0000ffff);
+
+       /* sync instruction cache */
+       md_icacheflush(ra, 5*4);
+
+       return true;
+}
 
 
-/* patcher_checkcast_instanceof_interface **************************************
+/* patcher_instanceof_interface **************************************
 
    Machine code:
 
@@ -631,7 +685,7 @@ bool patcher_checkcast_instanceof_flags(u1 *sp)
 
 *******************************************************************************/
 
-bool patcher_checkcast_instanceof_interface(u1 *sp)
+bool patcher_instanceof_interface(u1 *sp)
 {
        u1                *ra;
        u4                 mcode;
@@ -656,7 +710,7 @@ bool patcher_checkcast_instanceof_interface(u1 *sp)
 
        /* if we show disassembly, we have to skip the nop */
 
-       if (opt_showdisassemble)
+       if (opt_shownops)
                ra = ra + 4;
 
        /* patch super class index */
@@ -729,6 +783,67 @@ bool patcher_checkcast_class(u1 *sp)
        return true;
 }
 
+/* patcher_resolve_classref_to_classinfo ***************************************
+
+   ACONST:
+
+   <patched call postition>
+   806dffc4    lwz   r3,-60(r13)
+   81adffc0    lwz   r13,-64(r13)
+   7da903a6    mtctr r13
+   4e800421    bctrl
+
+
+   MULTIANEWARRAY:
+
+   <patched call position>
+   808dffc0    lwz   r4,-64(r13)
+   38a10038    addi  r5,r1,56
+   81adffbc    lwz   r13,-68(r13)
+   7da903a6    mtctr r13
+   4e800421    bctrl
+
+
+   ARRAYCHECKCAST:
+
+   <patched call position>
+   808dffd8    lwz   r4,-40(r13)
+   81adffd4    lwz   r13,-44(r13)
+   7da903a6    mtctr r13
+   4e800421    bctrl
+
+*******************************************************************************/
+
+bool patcher_resolve_classref_to_classinfo(u1 *sp)
+{
+       constant_classref *cr;
+       s4                 disp;
+       u1                *pv;
+       classinfo         *c;
+
+       /* get stuff from the stack */
+
+       cr   = (constant_classref *) *((ptrint *) (sp + 2 * 8));
+       disp =                       *((s4 *)     (sp + 1 * 8));
+       pv   = (u1 *)                *((ptrint *) (sp + 0 * 8));
+
+       /* get the classinfo */
+
+       if (!(c = resolve_classref_eager(cr)))
+               return false;
+
+       /* patch the classinfo pointer */
+
+       *((ptrint *) (pv + disp)) = (ptrint) c;
+
+       /* synchronize data cache */
+
+       md_dcacheflush(pv + disp, SIZEOF_VOID_P);
+
+       return true;
+}
+
+
 
 /* patcher_instanceof_class ****************************************************
 
@@ -781,6 +896,90 @@ bool patcher_instanceof_class(u1 *sp)
        return true;
 }
 
+/* patcher_resolve_classref_to_vftbl *******************************************
+
+   CHECKCAST (class):
+
+   <patched call position>
+   81870000    lwz   r12,0(r7)
+   800c0014    lwz   r0,20(r12)
+   818dff78    lwz   r12,-136(r13)
+
+
+   INSTANCEOF (class):
+
+   <patched call position>
+   817d0000    lwz   r11,0(r29)
+   818dff8c    lwz   r12,-116(r13)
+
+*******************************************************************************/
+
+bool patcher_resolve_classref_to_vftbl(u1 *sp)
+{
+       constant_classref *cr;
+       s4                 disp;
+       u1                *pv;
+       classinfo         *c;
+
+       /* get stuff from the stack */
+
+       cr   = (constant_classref *) *((ptrint *) (sp + 2 * 8));
+       disp =                       *((s4 *)     (sp + 1 * 8));
+       pv   = (u1 *)                *((ptrint *) (sp + 0 * 8));
+
+       /* get the fieldinfo */
+
+       if (!(c = resolve_classref_eager(cr)))
+               return false;
+
+       /* patch super class' vftbl */
+
+       *((ptrint *) (pv + disp)) = (ptrint) c->vftbl;
+
+       /* synchronize data cache */
+
+       md_dcacheflush(pv + disp, SIZEOF_VOID_P);
+
+       return true;
+}
+
+/* patcher_resolve_classref_to_flags *******************************************
+
+   CHECKCAST/INSTANCEOF:
+
+   <patched call position>
+   818dff7c    lwz   r12,-132(r13)
+
+*******************************************************************************/
+
+bool patcher_resolve_classref_to_flags(u1 *sp)
+{
+       constant_classref *cr;
+       s4                 disp;
+       u1                *pv;
+       classinfo         *c;
+
+       /* get stuff from the stack */
+
+       cr   = (constant_classref *) *((ptrint *) (sp + 2 * 8));
+       disp =                       *((s4 *)     (sp + 1 * 8));
+       pv   = (u1 *)                *((ptrint *) (sp + 0 * 8));
+
+       /* get the fieldinfo */
+
+       if (!(c = resolve_classref_eager(cr)))
+               return false;
+
+       /* patch class flags */
+
+       *((s4 *) (pv + disp)) = (s4) c->flags;
+
+       /* synchronize data cache */
+
+       md_dcacheflush(pv + disp, SIZEOF_VOID_P);
+
+       return true;
+}
 
 /* patcher_clinit **************************************************************
 
index 4673c5ab373958692f1ee22f22f2bdb8e211bd5b..8454d355ac98aec1a182c51052bf412338b78c9a 100644 (file)
@@ -32,7 +32,7 @@
             Michael Starzinger
             Edwin Steiner
 
-   $Id: reg.c 5435 2006-09-08 18:14:50Z edwin $
+   $Id: reg.c 7456 2007-03-05 16:13:11Z tbfg $
 
 */
 
@@ -133,7 +133,7 @@ void reg_setup(jitdata *jd)
        rd->freetmpadrregs = DMNEW(s4, ADR_TMP_CNT);
        rd->freesavadrregs = DMNEW(s4, ADR_SAV_CNT);
 
-       rd->adrreg_argnum = 0;
+       /*rd->adrreg_argnum = 0; XXX ask twisti */
        rd->argadrreguse = 0;
        rd->tmpadrreguse = 0;
        rd->savadrreguse = 0;
index 9da2c79b4e89ef978e84141118fb5e511891ac82..0dcd911fdaf4f5d19781964f6ddb20ee95bb8251 100644 (file)
@@ -30,7 +30,7 @@
 
    Changes: Edwin Steiner
 
-   $Id: asmpart.S 7442 2007-03-02 23:28:37Z pm $
+   $Id: asmpart.S 7486 2007-03-08 13:50:07Z twisti $
 
 */
 
@@ -73,6 +73,7 @@ L_##magic##_lp_end:                                         ; \
        .globl asm_vm_call_method_float
        .globl asm_vm_call_method_double
        .globl asm_vm_call_method_exception_handler
+       .globl asm_vm_call_method_end
 
        .globl asm_call_jit_compiler
 
@@ -458,6 +459,8 @@ L_handle_d1:
        ld    fa1, offvmargdata(itmp1)
        j     L_register_copy
 
+asm_vm_call_method_end:
+       nop
 
 /****************** function asm_call_jit_compiler *****************************
 *                                                                              *
index 0708fc2d0256fa9cdbbc83efa6916d6a3e4953e9..459ad892a8be55b2ef9dbb47c4fb658c7032f8f7 100644 (file)
 #endif
 
 
+/* branches *******************************************************************/
+
+#define SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER       1
+#define SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER     1
+#define SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS    0
+#define SUPPORT_BRANCH_CONDITIONAL_UNSIGNED_CONDITIONS      1
+
+
 /* exceptions *****************************************************************/
 
 #define SUPPORT_HARDWARE_DIVIDE_BY_ZERO  0
index 6567e1da392e0a839b698eb49b84c4cf0369a7f9..cfaf31e2ab3b5742a7e43ff4ce3c093559864248 100644 (file)
@@ -53,6 +53,7 @@
        .global asm_vm_call_method_float  
        .global asm_vm_call_method_double 
        .global asm_vm_call_method_exception_handler
+       .global asm_vm_call_method_end
 
        .global asm_call_jit_compiler
 
@@ -181,6 +182,7 @@ asm_vm_call_method_exception_handler:
        call    builtin_throw_exception
        nop
        return  %i7 + 8                          /* implicit window restore */
+asm_vm_call_method_end:
        nop
        
 
index f399b6c00b1e8a740982b31991e2b08a5f6ef7f2..e26d96df76259646ba4348ce680be105fc1b3254 100644 (file)
@@ -29,9 +29,8 @@
 
 #include "config.h"
 
-#include <stdio.h>
 #include <assert.h>
-
+#include <stdio.h>
 
 #include "vm/types.h"
 
@@ -52,6 +51,7 @@
 #include "vm/jit/codegen-common.h"
 #include "vm/jit/dseg.h"
 #include "vm/jit/emit-common.h"
+#include "vm/jit/sparc64/emit.h"
 #include "vm/jit/jit.h"
 #include "vm/jit/parse.h"
 #include "vm/jit/patcher.h"
 
 bool fits_13(s4 disp)
 {
-       /*  printf("fits disp %d?\n", disp); */
+       /*
+       if ((disp < -4096) || (disp > 4095))
+               printf("disp %d\n", disp);
+       */
 
        return (disp >= -4096) && (disp <= 4095);
 }
 
-/* codegen *********************************************************************
+s4 get_lopart_disp(disp)
+{
+       s4 lodisp;
+       
+       if (disp > 0)
+               lodisp = setlo_part(disp);
+       else {
+               if (setlo_part(disp) == 0)
+                       lodisp = 0;
+               else
+                       lodisp = setlo_part(disp) | 0x1c00;
+       }
+               
+       return lodisp;
+}
+       
+
+/* codegen_emit ****************************************************************
 
    Generates machine code.
 
 *******************************************************************************/
 
-bool codegen(jitdata *jd)
+bool codegen_emit(jitdata *jd)
 {
        methodinfo         *m;
        codeinfo           *code;
@@ -254,7 +274,7 @@ bool codegen(jitdata *jd)
 
                                } else {                             /* stack arg -> spilled  */
                                        /* add the callers window save registers */
-                                       var->vv.regoff = cd->stackframesize + JITSTACK_CNT + s1;
+                                       var->vv.regoff = cd->stackframesize + s1;
                                }
                        }
                
@@ -273,7 +293,7 @@ bool codegen(jitdata *jd)
                                        M_DLD(var->vv.regoff, REG_FP, JITSTACK + (s1 * 8));
 
                                } else {                             /* stack-arg -> spilled  */
-                                       var->vv.regoff = cd->stackframesize + JITSTACK_CNT + s1;
+                                       var->vv.regoff = cd->stackframesize + s1;
                                }
                        }
                }
@@ -674,9 +694,9 @@ bool codegen(jitdata *jd)
                        emit_arithmetic_check(cd, iptr, s2);
                        M_ISEXT(s1, s1);
                        /* XXX trim s2 like s1 ? */
-                       M_DIVX(s1, s2, d);
-                       M_MULX(s2, d, d);
-                       M_SUB(s1, d, d);
+                       M_DIVX(s1, s2, REG_ITMP3);
+                       M_MULX(s2, REG_ITMP3, REG_ITMP3);
+                       M_SUB(s1, REG_ITMP3, d);
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -686,9 +706,9 @@ bool codegen(jitdata *jd)
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
                        emit_arithmetic_check(cd, iptr, s2);
-                       M_DIVX(s1, s2, d);
-                       M_MULX(s2, d, d);
-                       M_SUB(s1, d, d);
+                       M_DIVX(s1, s2, REG_ITMP3);
+                       M_MULX(s2, REG_ITMP3, REG_ITMP3);
+                       M_SUB(s1, REG_ITMP3, d);
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -705,7 +725,15 @@ bool codegen(jitdata *jd)
                        break;
 
                case ICMD_ISHL:       /* ..., val1, val2  ==> ..., val1 << val2       */
-               case ICMD_LSHL:
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+                       M_SLL(s1, s2, d);
+                       emit_store_dst(jd, iptr, d);
+                       break;
+                       
+               case ICMD_LSHL:       /* ..., val1, val2  ==> ..., val1 << val2       */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
@@ -715,7 +743,16 @@ bool codegen(jitdata *jd)
                        break;
 
                case ICMD_ISHLCONST:  /* ..., value  ==> ..., value << constant       */
-               case ICMD_LSHLCONST:  /* val.i = constant                             */
+                                     /* val.i = constant                             */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+                       M_SLL_IMM(s1, iptr->sx.val.i, d);
+                       emit_store_dst(jd, iptr, d);
+                       break;
+                       
+               case ICMD_LSHLCONST:  /* ..., value  ==> ..., value << constant       */
+                                     /* val.i = constant                             */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
@@ -1211,7 +1248,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_AADD(s2, s1, REG_ITMP3);
                        M_BLDS(d, REG_ITMP3, OFFSET(java_bytearray, data[0]));
                        emit_store_dst(jd, iptr, d);
@@ -1222,7 +1260,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_AADD(s2, s1, REG_ITMP3);
                        M_AADD(s2, REG_ITMP3, REG_ITMP3);
                        M_SLDU(d, REG_ITMP3, OFFSET(java_chararray, data[0]));
@@ -1234,7 +1273,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_AADD(s2, s1, REG_ITMP3);
                        M_AADD(s2, REG_ITMP3, REG_ITMP3);
                        M_SLDS(d, REG_ITMP3, OFFSET(java_shortarray, data[0]));
@@ -1246,7 +1286,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ASLL_IMM(s2, 2, REG_ITMP3);
                        M_AADD(REG_ITMP3, s1, REG_ITMP3);
                        M_ILD(d, REG_ITMP3, OFFSET(java_intarray, data[0]));
@@ -1258,7 +1299,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ASLL_IMM(s2, 3, REG_ITMP3);
                        M_AADD(REG_ITMP3, s1, REG_ITMP3);
                        M_LDX(d, REG_ITMP3, OFFSET(java_longarray, data[0]));
@@ -1270,7 +1312,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ASLL_IMM(s2, 2, REG_ITMP3);
                        M_AADD(REG_ITMP3, s1, REG_ITMP3);
                        M_FLD(d, REG_ITMP3, OFFSET(java_floatarray, data[0]));
@@ -1282,7 +1325,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ASLL_IMM(s2, 3, REG_ITMP3);
                        M_AADD(REG_ITMP3, s1, REG_ITMP3);
                        M_DLD(d, REG_ITMP3, OFFSET(java_doublearray, data[0]));
@@ -1294,7 +1338,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP3);
                        M_AADD(REG_ITMP3, s1, REG_ITMP3);
                        M_ALD(d, REG_ITMP3, OFFSET(java_objectarray, data[0]));
@@ -1306,7 +1351,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_AADD(s2, s1, REG_ITMP1);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
                        M_BST(s3, REG_ITMP1, OFFSET(java_bytearray, data[0]));
@@ -1317,7 +1363,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_AADD(s2, s1, REG_ITMP1);
                        M_AADD(s2, REG_ITMP1, REG_ITMP1);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
@@ -1328,7 +1375,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ASLL_IMM(s2, 2, REG_ITMP2);
                        M_AADD(REG_ITMP2, s1, REG_ITMP1);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
@@ -1339,7 +1387,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ASLL_IMM(s2, 3, REG_ITMP2);
                        M_AADD(REG_ITMP2, s1, REG_ITMP1);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
@@ -1350,7 +1399,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ASLL_IMM(s2, 2, REG_ITMP2);
                        M_AADD(REG_ITMP2, s1, REG_ITMP1);
                        s3 = emit_load_s3(jd, iptr, REG_FTMP1);
@@ -1361,7 +1411,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ASLL_IMM(s2, 3, REG_ITMP2);
                        M_AADD(REG_ITMP2, s1, REG_ITMP1);
                        s3 = emit_load_s3(jd, iptr, REG_FTMP1);
@@ -1373,7 +1424,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
 
                        M_MOV(s1, rd->argintregs[0]);
@@ -1382,16 +1434,14 @@ bool codegen(jitdata *jd)
                        M_ALD(REG_ITMP3, REG_PV, disp);
                        M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
                        M_NOP;
-
-                       M_BEQZ(REG_RESULT_CALLER, 0);
-                       codegen_add_arraystoreexception_ref(cd);
-                       M_NOP;
+                       emit_exception_check(cd, iptr);
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
                        M_AADD(REG_ITMP2, s1, REG_ITMP1);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
+                       /* implicit null-pointer check */
                        M_AST_INTERN(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
                        break;
 
@@ -1400,7 +1450,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_AADD(s2, s1, REG_ITMP1);
                        M_BST(REG_ZERO, REG_ITMP1, OFFSET(java_bytearray, data[0]));
                        break;
@@ -1410,7 +1461,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_AADD(s2, s1, REG_ITMP1);
                        M_AADD(s2, REG_ITMP1, REG_ITMP1);
                        M_SST(REG_ZERO, REG_ITMP1, OFFSET(java_chararray, data[0]));
@@ -1420,7 +1472,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ASLL_IMM(s2, 2, REG_ITMP2);
                        M_AADD(REG_ITMP2, s1, REG_ITMP1);
                        M_IST_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_intarray, data[0]));
@@ -1430,7 +1483,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ASLL_IMM(s2, 3, REG_ITMP2);
                        M_AADD(REG_ITMP2, s1, REG_ITMP1);
                        M_STX_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_longarray, data[0]));
@@ -1440,7 +1494,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
                        M_AADD(REG_ITMP2, s1, REG_ITMP1);
                        M_AST_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_objectarray, data[0]));
@@ -1750,158 +1805,115 @@ bool codegen(jitdata *jd)
                case ICMD_GOTO:         /* ... ==> ...                                */
                case ICMD_RET:          /* ... ==> ...                                */
 
-                       M_BR(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_br(cd, iptr->dst.block);
                        ALIGNCODENOP;
                        break;
 
                case ICMD_JSR:          /* ... ==> ...                                */
 
-                       M_BR(0);
-                       codegen_add_branch_ref(cd, iptr->sx.s23.s3.jsrtarget.block);
-                       M_NOP;
+                       emit_br(cd, iptr->sx.s23.s3.jsrtarget.block);
                        ALIGNCODENOP;
                        break;
 
                case ICMD_IFNULL:       /* ..., value ==> ...                         */
+               case ICMD_IFNONNULL:
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       M_BEQZ(s1, 0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
-                       break;
-
-               case ICMD_IFNONNULL:    /* ..., value ==> ...                         */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       M_BNEZ(s1, 0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_bccz(cd, iptr->dst.block, iptr->opc - ICMD_IFNULL, s1, BRANCH_OPT_NONE);
                        break;
+                       
+               /* Note: int compares must not branch on the register directly.       */
+               /* Reason is, that register content is not 32-bit clean.              */
 
                case ICMD_IFEQ:         /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.i == 0) {
-                               M_BEQZ(s1, 0);
-                       } else {
-                               if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
-                                       M_CMP_IMM(s1, iptr->sx.val.i);
-                                       }
-                               else {
-                                       ICONST(REG_ITMP2, iptr->sx.val.i);
-                                       M_CMP(s1, REG_ITMP2);
-                                       }
-                               M_BEQ(0);
-                               }
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       
+                       if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
+                               M_CMP_IMM(s1, iptr->sx.val.i);
+                       }
+                       else {
+                               ICONST(REG_ITMP2, iptr->sx.val.i);
+                               M_CMP(s1, REG_ITMP2);
+                       }
+                       emit_beq(cd, iptr->dst.block);
                        break;
 
                case ICMD_IFLT:         /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.i == 0) {
-                               M_BLTZ(s1, 0);
-                       } else {
-                               if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
-                                       M_CMP_IMM(s1, iptr->sx.val.i);
-                               } else {
-                                       ICONST(REG_ITMP2, iptr->sx.val.i);
-                                       M_CMP(s1, REG_ITMP2);
-                               }
-                               M_BLT(0);
+                       
+                       if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
+                               M_CMP_IMM(s1, iptr->sx.val.i);
+                       } 
+                       else {
+                               ICONST(REG_ITMP2, iptr->sx.val.i);
+                               M_CMP(s1, REG_ITMP2);
                        }
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_blt(cd, iptr->dst.block);
                        break;
 
                case ICMD_IFLE:         /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.i == 0) {
-                               M_BLEZ(s1, 0);
-                               }
+
+                       if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
+                               M_CMP_IMM(s1, iptr->sx.val.i);
+                       }
                        else {
-                               if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
-                                       M_CMP_IMM(s1, iptr->sx.val.i);
-                                       }
-                               else {
-                                       ICONST(REG_ITMP2, iptr->sx.val.i);
-                                       M_CMP(s1, REG_ITMP2);
-                               }
-                               M_BLE(0);
+                               ICONST(REG_ITMP2, iptr->sx.val.i);
+                               M_CMP(s1, REG_ITMP2);
                        }
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_ble(cd, iptr->dst.block);
                        break;
 
                case ICMD_IFNE:         /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.i == 0) {
-                               M_BNEZ(s1, 0);
-                               }
+               
+                       if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
+                               M_CMP_IMM(s1, iptr->sx.val.i);
+                       }
                        else {
-                               if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
-                                       M_CMP_IMM(s1, iptr->sx.val.i);
-                               }
-                               else {
-                                       ICONST(REG_ITMP2, iptr->sx.val.i);
-                                       M_CMP(s1, REG_ITMP2);
-                               }
-                               M_BNE(0);
+                               ICONST(REG_ITMP2, iptr->sx.val.i);
+                               M_CMP(s1, REG_ITMP2);
                        }
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_bne(cd, iptr->dst.block);
                        break;
                                                
                case ICMD_IFGT:         /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.i == 0) {
-                               M_BGTZ(s1, 0);
+               
+                       if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
+                               M_CMP_IMM(s1, iptr->sx.val.i);
                        } 
                        else {
-                               if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
-                                       M_CMP_IMM(s1, iptr->sx.val.i);
-                               } else {
-                                       ICONST(REG_ITMP2, iptr->sx.val.i);
-                                       M_CMP(s1, REG_ITMP2);
-                               }
-                               M_BGT(0);
+                               ICONST(REG_ITMP2, iptr->sx.val.i);
+                               M_CMP(s1, REG_ITMP2);
                        }
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_bgt(cd, iptr->dst.block);          
                        break;
 
                case ICMD_IFGE:         /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.i == 0) {
-                               M_BGEZ(s1, 0);
-                               }
+
+                       if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
+                               M_CMP_IMM(s1, iptr->sx.val.i);
+                       }
                        else {
-                               if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
-                                       M_CMP_IMM(s1, iptr->sx.val.i);
-                                       }
-                               else {
-                                       ICONST(REG_ITMP2, iptr->sx.val.i);
-                                       M_CMP(s1, REG_ITMP2);
-                               }
-                               M_BGE(0);
+                               ICONST(REG_ITMP2, iptr->sx.val.i);
+                               M_CMP(s1, REG_ITMP2);
                        }
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_bge(cd, iptr->dst.block);
                        break;
                        
                case ICMD_IF_LEQ:       /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.l == 0) {
-                               M_BEQZ(s1, 0);
-                       }
+                       if (iptr->sx.val.l == 0)
+                               emit_beqz(cd, iptr->dst.block, s1);
                        else {
                                if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
                                        M_CMP_IMM(s1, iptr->sx.val.l);
@@ -1910,18 +1922,15 @@ bool codegen(jitdata *jd)
                                        LCONST(REG_ITMP2, iptr->sx.val.l);
                                        M_CMP(s1, REG_ITMP2);
                                }
-                               M_XBEQ(0);
+                               emit_beq_xcc(cd, iptr->dst.block);
                        }
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
                        break;
                        
                case ICMD_IF_LLT:       /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.l == 0) {
-                               M_BLTZ(s1, 0);
-                       } 
+                       if (iptr->sx.val.l == 0)
+                               emit_bltz(cd, iptr->dst.block, s1);
                        else {
                                if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
                                        M_CMP_IMM(s1, iptr->sx.val.l);
@@ -1930,76 +1939,66 @@ bool codegen(jitdata *jd)
                                        ICONST(REG_ITMP2, iptr->sx.val.l);
                                        M_CMP(s1, REG_ITMP2);
                                }
-                               M_XBLT(0);
+                               emit_blt_xcc(cd, iptr->dst.block);
                        }
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
                        break;
 
                case ICMD_IF_LLE:       /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.l == 0) {
-                               M_BLEZ(s1, 0);
-                               }
+                       if (iptr->sx.val.l == 0)
+                               emit_blez(cd, iptr->dst.block, s1);
                        else {
                                if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
                                        M_CMP_IMM(s1, iptr->sx.val.l);
-                                       }
+                               }
                                else {
                                        ICONST(REG_ITMP2, iptr->sx.val.l);
                                        M_CMP(s1, REG_ITMP2);
                                }
-                               M_XBLE(0);
+                               emit_ble_xcc(cd, iptr->dst.block);
                        }
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
                        break;
                        
                case ICMD_IF_LNE:       /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.l == 0) {
-                               M_BNEZ(s1, 0);
-                               }
+                       if (iptr->sx.val.l == 0)
+                               emit_bnez(cd, iptr->dst.block, s1);
                        else {
                                if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
-                                       M_CMP_IMM(s1, iptr->sx.val.i);
+                                       M_CMP_IMM(s1, iptr->sx.val.l);
                                }
                                else {
                                        ICONST(REG_ITMP2, iptr->sx.val.l);
                                        M_CMP(s1, REG_ITMP2);
                                }
-                               M_XBNE(0);
+                               emit_bne_xcc(cd, iptr->dst.block);
                        }
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
                        break;
                                                
                case ICMD_IF_LGT:       /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.l == 0) {
-                               M_BGTZ(s1, 0);
-                       else {
+                       if (iptr->sx.val.l == 0)
+                               emit_bgtz(cd, iptr->dst.block, s1);
+                       else {
                                if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
                                        M_CMP_IMM(s1, iptr->sx.val.l);
-                               } else {
+                               } 
+                               else {
                                        ICONST(REG_ITMP2, iptr->sx.val.l);
                                        M_CMP(s1, REG_ITMP2);
                                }
-                               M_XBGT(0);
+                               emit_bgt_xcc(cd, iptr->dst.block);
                        }
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
                        break;
 
                case ICMD_IF_LGE:       /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.l == 0) {
-                               M_BGEZ(s1, 0);
-                       }
+                       if (iptr->sx.val.l == 0)
+                               emit_bgez(cd, iptr->dst.block, s1);
                        else {
                                if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
                                        M_CMP_IMM(s1, iptr->sx.val.l);
@@ -2008,10 +2007,8 @@ bool codegen(jitdata *jd)
                                        ICONST(REG_ITMP2, iptr->sx.val.l);
                                        M_CMP(s1, REG_ITMP2);
                                }
-                               M_XBGE(0);
+                               emit_bge_xcc(cd, iptr->dst.block);
                        }
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
                        break;                  
                        
 
@@ -2021,9 +2018,7 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_CMP(s1, s2);
-                       M_XBEQ(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_beq_xcc(cd, iptr->dst.block);
                        break;
 
                case ICMD_IF_ICMPEQ:    /* 32-bit compare                             */
@@ -2031,9 +2026,7 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_CMP(s1, s2);
-                       M_BEQ(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_beq(cd, iptr->dst.block);
                        break;
 
                case ICMD_IF_ACMPNE:    /* ..., value, value ==> ...                  */
@@ -2042,9 +2035,7 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_CMP(s1, s2);
-                       M_XBNE(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_bne_xcc(cd, iptr->dst.block);
                        break;
                        
                case ICMD_IF_ICMPNE:    /* 32-bit compare                             */
@@ -2052,9 +2043,7 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_CMP(s1, s2);
-                       M_BNE(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_bne(cd, iptr->dst.block);
                        break;
 
                case ICMD_IF_LCMPLT:    /* ..., value, value ==> ...                  */
@@ -2062,9 +2051,7 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_CMP(s1, s2);
-                       M_XBLT(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_blt_xcc(cd, iptr->dst.block);
                        break;
                        
                case ICMD_IF_ICMPLT:    /* 32-bit compare                             */
@@ -2072,9 +2059,7 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_CMP(s1, s2);
-                       M_BLT(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_blt(cd, iptr->dst.block);
                        break;
 
                case ICMD_IF_LCMPGT:    /* ..., value, value ==> ...                  */
@@ -2082,9 +2067,7 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_CMP(s1, s2);
-                       M_XBGT(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_bgt_xcc(cd, iptr->dst.block);
                        break;
                        
                case ICMD_IF_ICMPGT:    /* 32-bit compare                             */
@@ -2092,9 +2075,7 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_CMP(s1, s2);
-                       M_BGT(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_bgt(cd, iptr->dst.block);
                        break;
 
                case ICMD_IF_LCMPLE:    /* ..., value, value ==> ...                  */
@@ -2102,9 +2083,7 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_CMP(s1, s2);
-                       M_BLE(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_ble_xcc(cd, iptr->dst.block);
                        break;
                        
                case ICMD_IF_ICMPLE:    /* 32-bit compare                             */
@@ -2112,9 +2091,7 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_CMP(s1, s2);
-                       M_BLE(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_ble(cd, iptr->dst.block);
                        break;                  
        
 
@@ -2123,9 +2100,7 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_CMP(s1, s2);
-                       M_BGE(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_bge_xcc(cd, iptr->dst.block);
                        break;
                        
                case ICMD_IF_ICMPGE:    /* 32-bit compare                             */
@@ -2133,9 +2108,7 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_CMP(s1, s2);
-                       M_BGE(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_bge(cd, iptr->dst.block);
                        break;
 
 
@@ -2247,9 +2220,7 @@ nowperformreturn:
                                ICONST(REG_ITMP2, i - 1);
                                M_CMP(REG_ITMP1, REG_ITMP2);
                        }               
-                       M_XBUGT(0);
-                       codegen_add_branch_ref(cd, table[0].block); /* default target */
-                       M_ASLL_IMM(REG_ITMP1, POINTERSHIFT, REG_ITMP1);      /* delay slot*/
+                       emit_bugt(cd, table[0].block); /* default target */
 
                        /* build jump table top down and use address of lowest entry */
 
@@ -2263,6 +2234,7 @@ nowperformreturn:
 
                        /* length of dataseg after last dseg_addtarget is used by load */
 
+                       M_ASLL_IMM(REG_ITMP1, POINTERSHIFT, REG_ITMP1);
                        M_AADD(REG_ITMP1, REG_PV, REG_ITMP2);
                        M_ALD(REG_ITMP2, REG_ITMP2, -(cd->dseglen));
                        M_JMP(REG_ZERO, REG_ITMP2, REG_ZERO);
@@ -2289,15 +2261,11 @@ nowperformreturn:
                                        ICONST(REG_ITMP2, lookup->value);
                                        M_CMP(s1, REG_ITMP2);
                                }
-                               M_BEQ(0);
-                               codegen_add_branch_ref(cd, lookup->target.block); 
-                               M_NOP;
+                               emit_beq(cd, lookup->target.block);
                                ++lookup;
                        }
 
-                       M_BR(0);
-                       codegen_add_branch_ref(cd, iptr->sx.s23.s3.lookupdefault.block);
-                       M_NOP;
+                       emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
                        ALIGNCODENOP;
                        break;
                        }
@@ -2378,17 +2346,22 @@ gen_method:
                                disp = dseg_add_functionptr(cd, bte->fp);
 
                                M_ALD(REG_PV_CALLER, REG_PV, disp);  /* built-in-function pointer */
-                               s1 = REG_PV_CALLER;
 
                                /* XXX jit-c-call */
-
+                               /* generate the actual call */
+    
+                           M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
+                           M_NOP;
+                           disp = (s4) (cd->mcodeptr - cd->mcodebase);
+                           /* REG_RA holds the value of the jmp instruction, therefore +8 */
+                           M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8); 
+
+                               emit_exception_check(cd, iptr);
                                break;
 
                        case ICMD_INVOKESPECIAL:
-                               M_BEQZ(REG_OUT0, 0);
-                               codegen_add_nullpointerexception_ref(cd);
-                               M_NOP;
-                               /* fall through */
+                               emit_nullpointer_check(cd, iptr, REG_OUT0);
+                               /* fall-through */
 
                        case ICMD_INVOKESTATIC:
                                if (lm == NULL) {
@@ -2401,7 +2374,14 @@ gen_method:
                                        disp = dseg_add_address(cd, lm->stubroutine);
 
                                M_ALD(REG_PV_CALLER, REG_PV, disp);          /* method pointer in pv */
-                               s1 = REG_PV_CALLER;
+                               
+                               /* generate the actual call */
+    
+                           M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
+                           M_NOP;
+                           disp = (s4) (cd->mcodeptr - cd->mcodebase);
+                           /* REG_RA holds the value of the jmp instruction, therefore +8 */
+                           M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8); 
                                break;
 
                        case ICMD_INVOKEVIRTUAL:
@@ -2416,10 +2396,17 @@ gen_method:
                                        s1 = OFFSET(vftbl_t, table[0]) +
                                                sizeof(methodptr) * lm->vftblindex;
 
-                               M_ALD(REG_METHODPTR, REG_OUT0,
-                                         OFFSET(java_objectheader, vftbl));
+                               /* implicit null-pointer check */
+                               M_ALD(REG_METHODPTR, REG_OUT0,OFFSET(java_objectheader, vftbl));
                                M_ALD(REG_PV_CALLER, REG_METHODPTR, s1);
-                               s1 = REG_PV_CALLER;
+                               
+                               /* generate the actual call */
+    
+                           M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
+                           M_NOP;
+                           disp = (s4) (cd->mcodeptr - cd->mcodebase);
+                           /* REG_RA holds the value of the jmp instruction, therefore +8 */
+                           M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8); 
                                break;
 
                        case ICMD_INVOKEINTERFACE:
@@ -2438,29 +2425,19 @@ gen_method:
                                        s2 = sizeof(methodptr) * (lm - lm->class->methods);
                                }
 
-                               M_ALD(REG_METHODPTR, REG_OUT0,
-                                         OFFSET(java_objectheader, vftbl));
+                               /* implicit null-pointer check */
+                               M_ALD(REG_METHODPTR, REG_OUT0, OFFSET(java_objectheader, vftbl));
                                M_ALD(REG_METHODPTR, REG_METHODPTR, s1);
                                M_ALD(REG_PV_CALLER, REG_METHODPTR, s2);
-                               s1 = REG_PV_CALLER;
-                               break;
-                       }
-
-                       /* generate the actual call */
 
-                       M_JMP(REG_RA_CALLER, s1, REG_ZERO);
-                       M_NOP;
-                       disp = (s4) (cd->mcodeptr - cd->mcodebase);
-                       /* REG_RA holds the value of the jmp instruction, therefore +8 */
-                       M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8); 
-
-
-                       /* actually only used for ICMD_BUILTIN */
-
-                       if (INSTRUCTION_MUST_CHECK(iptr)) {
-                               M_BEQZ(REG_RESULT_CALLER, 0);
-                               codegen_add_fillinstacktrace_ref(cd);
-                               M_NOP;
+                           /* generate the actual call */
+    
+                           M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
+                           M_NOP;
+                           disp = (s4) (cd->mcodeptr - cd->mcodebase);
+                           /* REG_RA holds the value of the jmp instruction, therefore +8 */
+                           M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8);
+                               break;
                        }
 
                        /* store return value */
@@ -2520,23 +2497,10 @@ gen_method:
 
                                s1 = emit_load_s1(jd, iptr, REG_ITMP1);
 
-                               /* calculate interface checkcast code size */
-
-                               s2 = 8;
-                               if (super == NULL)
-                                       s2 += (opt_shownops ? PATCHER_CALL_INSTRUCTIONS : 0);
-
-                               /* calculate class checkcast code size */
-
-                               s3 = 10;
-                               if (super == NULL)
-                                       s3 += (opt_shownops ? PATCHER_CALL_INSTRUCTIONS : 0);
-
                                /* if class is not resolved, check which code to call */
 
                                if (super == NULL) {
-                                       M_BEQZ(s1, 5 + (opt_shownops ? PATCHER_CALL_INSTRUCTIONS : 0) + s2 + 2 + s3 + 1);
-                                       M_NOP;
+                                       emit_label_beqz(cd, BRANCH_LABEL_1, s1);
 
                                        cr   = iptr->sx.s23.s3.c.ref;
                                        disp = dseg_add_unique_s4(cd, 0);         /* super->flags */
@@ -2546,8 +2510,7 @@ gen_method:
 
                                        M_ILD(REG_ITMP2, REG_PV, disp);
                                        M_AND_IMM(REG_ITMP2, ACC_INTERFACE, REG_ITMP2);
-                                       M_BEQZ(REG_ITMP2, s2 + 2 + 2);
-                                       M_NOP;
+                                       emit_label_beqz(cd, BRANCH_LABEL_2, REG_ITMP2);
                                }
 
                                /* interface checkcast code */
@@ -2560,37 +2523,32 @@ gen_method:
                                                                                          cr, 0);
                                        }
                                        else {
-                                               M_BEQZ(s1, s2 + 2);
-                                               M_NOP;
+                                               emit_label_beqz(cd, BRANCH_LABEL_3, s1);
                                        }
 
                                        M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
                                        M_ILD(REG_ITMP3, REG_ITMP2,
                                                        OFFSET(vftbl_t, interfacetablelength));
                                        M_ADD_IMM(REG_ITMP3, -superindex, REG_ITMP3);
-                                       M_BLEZ(REG_ITMP3, 0);
-                                       codegen_add_classcastexception_ref(cd, s1);
-                                       M_NOP;
+                                       emit_classcast_check(cd, iptr, ICMD_IFLE, REG_ITMP3, s1);
+
                                        M_ALD(REG_ITMP3, REG_ITMP2,
                                                  OFFSET(vftbl_t, interfacetable[0]) -
                                                  superindex * sizeof(methodptr*));
-                                       M_BEQZ(REG_ITMP3, 0);
-                                       codegen_add_classcastexception_ref(cd, s1);
-                                       M_NOP;
+                                       emit_classcast_check(cd, iptr, ICMD_IFEQ, REG_ITMP3, s1);
 
-                                       if (super == NULL) {
-                                   /* on sparc we always add 2 to the size of the code we want  */
-                                   /* branch over. (1 for branch delay nop, 1 since the base is */
-                                   /* the address of the branch instruction */
-                                               M_BR(s3 + 2);
-                                               M_NOP;
-                                       }
+                                       if (super == NULL)
+                                               emit_label_br(cd, BRANCH_LABEL_4);
+                                       else
+                                               emit_label(cd, BRANCH_LABEL_3);
                                }
 
                                /* class checkcast code */
 
                                if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
                                        if (super == NULL) {
+                                               emit_label(cd, BRANCH_LABEL_2);
+
                                                cr   = iptr->sx.s23.s3.c.ref;
                                                disp = dseg_add_unique_address(cd, NULL);
 
@@ -2601,8 +2559,7 @@ gen_method:
                                        else {
                                                disp = dseg_add_address(cd, super->vftbl);
 
-                                               M_BEQZ(s1, s3 + 2);
-                                               M_NOP;
+                                               emit_label_beqz(cd, BRANCH_LABEL_5, s1);
                                        }
 
                                        M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
@@ -2620,9 +2577,15 @@ gen_method:
 #endif
                                        /*                              } */
                                        M_CMP(REG_ITMP3, REG_ITMP2);
-                                       M_BULT(0);                         /* branch if ITMP3 < ITMP2 */ 
-                                       codegen_add_classcastexception_ref(cd, s1);
-                                       M_NOP;
+                                       emit_classcast_check(cd, iptr, BRANCH_ULT, REG_ITMP3, s1);
+
+                                       if (super != NULL)
+                                               emit_label(cd, BRANCH_LABEL_5);
+                               }
+
+                               if (super == NULL) {
+                                       emit_label(cd, BRANCH_LABEL_1);
+                                       emit_label(cd, BRANCH_LABEL_4);
                                }
 
                                d = codegen_reg_of_dst(jd, iptr, s1);
@@ -2653,9 +2616,7 @@ gen_method:
                                M_NOP;
 
                                s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                               M_BEQZ(REG_RESULT_CALLER, 0);
-                               codegen_add_classcastexception_ref(cd, s1);
-                               M_NOP;
+                               emit_classcast_check(cd, iptr, ICMD_IFEQ, REG_RESULT_CALLER, s1);
 
                                d = codegen_reg_of_dst(jd, iptr, s1);
                        }
@@ -2665,6 +2626,7 @@ gen_method:
                        break;
 
                case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult            */
+                                     /* val.a: (classinfo*) superclass               */
 
                        /*  superclass is an interface:
                         *      
@@ -2705,25 +2667,12 @@ gen_method:
                                s1 = REG_ITMP1;
                        }
 
-                       /* calculate interface instanceof code size */
-
-                       s2 = 7;
-                       if (super == NULL)
-                               s2 += (opt_shownops ? PATCHER_CALL_INSTRUCTIONS : 0);
-
-                       /* calculate class instanceof code size */
-
-                       s3 = 8;
-                       if (super == NULL)
-                               s3 += (opt_shownops ? PATCHER_CALL_INSTRUCTIONS : 0);
-
                        M_CLR(d);
 
                        /* if class is not resolved, check which code to call */
 
                        if (super == NULL) {
-                               M_BEQZ(s1, 5 + (opt_shownops ? PATCHER_CALL_INSTRUCTIONS : 0) + s2 + 2 + s3);
-                               M_NOP;
+                               emit_label_beqz(cd, BRANCH_LABEL_1, s1);
 
                                cr   = iptr->sx.s23.s3.c.ref;
                                disp = dseg_add_unique_s4(cd, 0);             /* super->flags */
@@ -2733,8 +2682,7 @@ gen_method:
 
                                M_ILD(REG_ITMP3, REG_PV, disp);
                                M_AND_IMM(REG_ITMP3, ACC_INTERFACE, REG_ITMP3);
-                               M_BEQZ(REG_ITMP3, s2 + 2 + 2);
-                               M_NOP;
+                               emit_label_beqz(cd, BRANCH_LABEL_2, REG_ITMP3);
                        }
 
                        /* interface instanceof code */
@@ -2747,8 +2695,7 @@ gen_method:
                                                                                  cr, 0);
                                }
                                else {
-                                       M_BEQZ(s1, s2 + 2);
-                                       M_NOP;
+                                       emit_label_beqz(cd, BRANCH_LABEL_3, s1);
                                }
 
                                M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
@@ -2761,16 +2708,18 @@ gen_method:
                                                        superindex * sizeof(methodptr*)));
                                M_CMOVRNE_IMM(REG_ITMP1, 1, d);      /* REG_ITMP1 != 0  */
 
-                               if (super == NULL) {
-                                       M_BR(s3 + 2);
-                                       M_NOP;
-                               }
+                               if (super == NULL)
+                                       emit_label_br(cd, BRANCH_LABEL_4);
+                               else
+                                       emit_label(cd, BRANCH_LABEL_3);
                        }
 
                        /* class instanceof code */
 
                        if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
                                if (super == NULL) {
+                                       emit_label(cd, BRANCH_LABEL_2);
+
                                        cr   = iptr->sx.s23.s3.c.ref;
                                        disp = dseg_add_unique_address(cd, NULL);
 
@@ -2780,8 +2729,7 @@ gen_method:
                                else {
                                        disp = dseg_add_address(cd, supervftbl);
 
-                                       M_BEQZ(s1, s3 + 2);
-                                       M_NOP;
+                                       emit_label_beqz(cd, BRANCH_LABEL_5, s1);
                                }
 
                                M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
@@ -2798,7 +2746,16 @@ gen_method:
                                M_SUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
                                M_CMP(REG_ITMP1, REG_ITMP2);
                                M_XCMOVULE_IMM(1, d);
+
+                               if (super != NULL)
+                                       emit_label(cd, BRANCH_LABEL_5);
+                       }
+
+                       if (super == NULL) {
+                               emit_label(cd, BRANCH_LABEL_1);
+                               emit_label(cd, BRANCH_LABEL_4);
                        }
+
                        emit_store_dst(jd, iptr, d);
                        }
                        break;
@@ -2855,9 +2812,7 @@ gen_method:
 
                        /* check for exception before result assignment */
 
-                       M_BEQZ(REG_RESULT_CALLER, 0);
-                       codegen_add_fillinstacktrace_ref(cd);
-                       M_NOP;
+                       emit_exception_check(cd, iptr);
 
                        d = codegen_reg_of_dst(jd, iptr, REG_RESULT_CALLER);
                        M_INTMOVE(REG_RESULT_CALLER, d);
@@ -2880,15 +2835,10 @@ gen_method:
        
        dseg_createlinenumbertable(cd);
 
-       /* generate exception and patcher stubs */
+       /* generate stubs */
 
-       emit_exception_stubs(jd);
        emit_patcher_stubs(jd);
-#if defined(ENABLE_REPLACEMENT)
-       emit_replacement_stubs(jd);
-#endif /* defined(ENABLE_REPLACEMENT) */
-
-       codegen_finish(jd);
+       REPLACEMENT_EMIT_STUBS(jd);
        
        /* everything's ok */
 
@@ -2896,9 +2846,6 @@ gen_method:
 }
 
 
-
-
-
 /* createcompilerstub **********************************************************
 
    Creates a stub routine which calls the compiler.
index 447718d76b08f88579a83a959e7e77424b2a04fe..6edfa3b1bfffb625e44affa31b2689fe2d1d4337 100644 (file)
@@ -63,6 +63,9 @@ s4 nat_argintregs[INT_NATARG_CNT];
 #define PATCHER_CALL_INSTRUCTIONS    2     /* number of instructions          */
 #define PATCHER_CALL_SIZE            2 * 4 /* size in bytes of a patcher call */
 
+#define EXCEPTION_CHECK_INSTRUCTIONS 3     /* number of instructions          */
+#define EXCEPTION_CHECK_SIZE         3 * 4 /* byte size of an exception check */
+
 #define PATCHER_NOPS \
     do { \
         M_NOP; \
@@ -142,6 +145,10 @@ s4 nat_argintregs[INT_NATARG_CNT];
        } while (0)
 
 
+#define M_OP3_GET_RD(x)               (((x) >> 25) & 0x1f)
+#define M_OP3_GET_RS(x)               (((x) >> 14) & 0x1f)
+#define M_OP3_GET_IMM(x)              ( (x)        & 0x1fff)
+
 /* 3-address-operations: M_OP3C
  *       rcond ... condition opcode
  *       rs2 ..... register number or 10bit signed immediate
@@ -166,8 +173,8 @@ s4 nat_argintregs[INT_NATARG_CNT];
  */
 #define M_SHFT(op,op3,rs1,rs2,rd,imm,x) \
        do { \
-               *((u4 *) cd->mcodeptr) =  ( (((s4)(op)) << 30) | ((op3) << 19) | ((rd) << 25) | ((rs1) << 14) | ((rs2) << 0) | \
-                     ((imm) << 13) | ((x) << 12) ); \
+               *((u4 *) cd->mcodeptr) =  ( (((s4)(op)) << 30) | ((op3) << 19) | ((rd) << 25) | ((rs1) << 14) | ((imm) << 13) | \
+                       ((x) << 12) | (((imm) && (x))?((rs2) & 0x3f):((rs2) & 0x1f)) ); \
                cd->mcodeptr += 4; \
        } while (0)
 
@@ -306,13 +313,15 @@ s4 nat_argintregs[INT_NATARG_CNT];
 
 #define M_SLLX(rs1,rs2,rd)             M_SHFT(0x02,0x25,rs1,rs2,rd,REG,1)      /* 64b rd = rs << rs2 */
 #define M_SLLX_IMM(rs1,rs2,rd) M_SHFT(0x02,0x25,rs1,rs2,rd,IMM,1)
+#define M_SLL(rs1,rs2,rd)              M_SHFT(0x02,0x25,rs1,rs2,rd,REG,0)      /* 32b rd = rs << rs2 */
+#define M_SLL_IMM(rs1,rs2,rd)  M_SHFT(0x02,0x25,rs1,rs2,rd,IMM,0)
 #define M_SRLX(rs1,rs2,rd)             M_SHFT(0x02,0x26,rs1,rs2,rd,REG,1)      /* 64b rd = rs >>>rs2 */
 #define M_SRLX_IMM(rs1,rs2,rd) M_SHFT(0x02,0x26,rs1,rs2,rd,IMM,1)
 #define M_SRL(rs1,rs2,rd)              M_SHFT(0x02,0x26,rs1,rs2,rd,REG,0)      /* 32b rd = rs >>>rs2 */
 #define M_SRL_IMM(rs1,rs2,rd)  M_SHFT(0x02,0x26,rs1,rs2,rd,IMM,0)
 #define M_SRAX(rs1,rs2,rd)             M_SHFT(0x02,0x27,rs1,rs2,rd,REG,1)      /* 64b rd = rs >> rs2 */
 #define M_SRAX_IMM(rs1,rs2,rd) M_SHFT(0x02,0x27,rs1,rs2,rd,IMM,1)
-#define M_SRA(rs1,rs2,rd)     M_SHFT(0x02,0x27,rs1,rs2,rd,REG,0)  /* 32b rd = rs >> rs2 */
+#define M_SRA(rs1,rs2,rd)       M_SHFT(0x02,0x27,rs1,rs2,rd,REG,0)  /* 32b rd = rs >> rs2 */
 #define M_SRA_IMM(rs1,rs2,rd)  M_SHFT(0x02,0x27,rs1,rs2,rd,IMM,0)
 
 #define M_ISEXT(rs,rd)                         M_SRA(rs,REG_ZERO,rd)                 /* sign extend 32 bits*/
@@ -386,7 +395,10 @@ s4 nat_argintregs[INT_NATARG_CNT];
 
 /* #define FITS_13BIT_IMM(x)       ((x >= -4096) && (x <= 4095)) */
 
-bool fits13(s4 disp);
+bool fits_13(s4 disp);
+s4   get_lopart_disp(s4 disp);
+
+#define abs(x) ((x) < 0 ? (-(x)) : (x))
 
 #define sethi_part(x) ((x)>>10)
 #define setlo_part(x) ((x) & 0x3ff)
@@ -407,14 +419,18 @@ bool fits13(s4 disp);
        
 #define DO_SETHI_PART(c,rs,rd) \
        do { \
-               M_SETHI(sethi_part(c), rd); \
                if (c > 0) { \
+                       M_SETHI(sethi_part(c), rd); \
                        M_ADD(rs,rd,rd); \
                } \
                else { \
+                       M_SETHI(sethi_part(-c), rd); \
                        M_SUB(rs,rd,rd); \
+                       assert(sethi_part(c) != 0xf); \
                } \
        } while (0)
+       
+
                
 
 #define M_LDA(rd,rs,disp) \
@@ -442,10 +458,8 @@ bool fits13(s4 disp);
             M_LDX_INTERN(rd,rs,disp); \
         } \
         else { \
-                       printf("ldx imm = %d\n", disp); \
-            DO_SETHI_PART(disp,rs,rd); \
-            M_LDX_INTERN(rd,rd,setlo_part(disp)); \
-                       assert(0); \
+               DO_SETHI_PART(disp,rs,rd); \
+               M_LDX_INTERN(rd,rd,get_lopart_disp(disp)); \
         } \
     } while (0)
 
@@ -457,8 +471,7 @@ bool fits13(s4 disp);
        } \
         else { \
             DO_SETHI_PART(disp,rs,rd); \
-            M_ILD_INTERN(rd,rd,setlo_part(disp)); \
-                       assert(0); \
+            M_ILD_INTERN(rd,rd,get_lopart_disp(disp)); \
         } \
     } while (0)
 
diff --git a/src/vm/jit/sparc64/emit-arch.h b/src/vm/jit/sparc64/emit-arch.h
new file mode 100644 (file)
index 0000000..3fa6468
--- /dev/null
@@ -0,0 +1,78 @@
+/* src/vm/jit/sparc64/emit-arch.h - sparc64 code emitter functions
+
+   Copyright (C) 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.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   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., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
+
+   $Id: emitfuncs.c 4398 2006-01-31 23:43:08Z twisti $
+
+*/
+
+
+#ifndef _EMIT_ARCH_H
+#define _EMIT_ARCH_H
+
+#include "config.h"
+#include "vm/types.h"
+
+/* SPARC branch options */
+
+#define BRANCH_OPT_XCC      0x1
+#define BRANCH_OPT_PREDICT  0x2
+#define BRANCH_OPT_ANNULL   0x4
+
+#define BRANCH_CHECKS_XCC(options) \
+       ((options) & BRANCH_OPT_XCC)
+       
+#define BRANCH_WITH_PREDICT(options) \
+       ((options) & BRANCH_OPT_PREDICT)
+       
+#define BRANCH_WITH_ANNULL(options) \
+       ((options) & BRANCH_OPT_ANNULL)
+
+
+
+/* wrappers for branches on 64-bit condition codes */
+
+void emit_beq_xcc(codegendata *cd, basicblock *target);
+void emit_bne_xcc(codegendata *cd, basicblock *target);
+void emit_blt_xcc(codegendata *cd, basicblock *target);
+void emit_bge_xcc(codegendata *cd, basicblock *target);
+void emit_bgt_xcc(codegendata *cd, basicblock *target);
+void emit_ble_xcc(codegendata *cd, basicblock *target);
+
+
+#endif /* _EMIT_ARCH_H */
+
+
+/*
+ * 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
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
index b015d17be61370f78832673b12e95cd03dd41d54..2595d79e8ad52c581e819d17d2ebb992e449a020 100644 (file)
@@ -1,4 +1,4 @@
-/* src/vm/jit/sparc64/emit.c - Sparc code emitter functions
+/* src/vm/jit/sparc64/emit.c - SPARC code emitter functions
 
    Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
 
 
 #include "config.h"
+
+#include <assert.h>
+
 #include "vm/types.h"
 
 #include "vm/jit/sparc64/codegen.h"
 #include "vm/jit/sparc64/md-abi.h"
+#include "vm/jit/sparc64/emit.h"
 
 #include "mm/memory.h"
 
+#include "vm/exceptions.h"
 #include "vm/stringlocal.h" /* XXX for gen_resolvebranch */
 #include "vm/jit/abi-asm.h"
 #include "vm/jit/asmpart.h"
@@ -228,6 +233,212 @@ void emit_lconst(codegendata *cd, s4 d, s8 value)
        }
 }
 
+/* emit_branch *****************************************************************
+
+   Emits the code for conditional and unconditional branchs.
+
+*******************************************************************************/
+
+void emit_branch(codegendata *cd, s4 disp, s4 condition, s4 reg, u4 opt)
+{
+       s4 branchdisp;
+
+       /* calculate the different displacements */
+
+       branchdisp = disp >> 2;
+
+       /* check which branch to generate */
+
+       if (condition == BRANCH_UNCONDITIONAL) {
+               /* check displacement for overflow (19-bit)*/
+
+               if ((branchdisp < (s4) 0xfffc0000) || (branchdisp > (s4) 0x003ffff)) {
+                       /* if the long-branches flag isn't set yet, do it */
+
+                       if (!CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
+                               cd->flags |= (CODEGENDATA_FLAG_ERROR |
+                                                         CODEGENDATA_FLAG_LONGBRANCHES);
+                       }
+
+                       vm_abort("emit_branch: emit unconditional long-branch code");
+               }
+               else {
+                       M_BR(branchdisp);
+                       M_NOP;
+               }
+       }
+       else if (reg == -1) {
+               /* branch on condition codes */
+
+               /* check displacement for overflow (19-bit)*/
+
+               if ((branchdisp < (s4) 0xfffc0000) || (branchdisp > (s4) 0x003ffff)) {
+                       /* if the long-branches flag isn't set yet, do it */
+
+                       if (!CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
+                               log_println("setting error");
+                               cd->flags |= (CODEGENDATA_FLAG_ERROR |
+                                                         CODEGENDATA_FLAG_LONGBRANCHES);
+                       }
+
+                       vm_abort("emit_branch: emit long-branch on cc code");
+               }
+               else {
+                       /* check whether to branch on 64-bit condition code */
+                       if (BRANCH_CHECKS_XCC(opt)) {
+                               switch (condition) {
+                               case BRANCH_EQ:
+                                       M_XBEQ(branchdisp);
+                                       break;
+                               case BRANCH_NE:
+                                       M_XBNE(branchdisp);
+                                       break;
+                               case BRANCH_LT:
+                                       M_XBLT(branchdisp);
+                                       break;
+                               case BRANCH_GE:
+                                       M_XBGE(branchdisp);
+                                       break;
+                               case BRANCH_GT:
+                                       M_XBGT(branchdisp);
+                                       break;
+                               case BRANCH_LE:
+                                       M_XBLE(branchdisp);
+                                       break;
+                               case BRANCH_UGT:
+                                       M_XBUGT(branchdisp);
+                                       break;
+                               case BRANCH_ULT:
+                                       M_XBULT(branchdisp);
+                                       break;
+                               default:
+                                       vm_abort("emit_branch: unknown condition %d", condition);
+                               }
+                               
+                               /* branch delay */
+                               M_NOP;
+                       }
+                       else {
+                               switch (condition) {
+                               case BRANCH_EQ:
+                                       M_BEQ(branchdisp);
+                                       break;
+                               case BRANCH_NE:
+                                       M_BNE(branchdisp);
+                                       break;
+                               case BRANCH_LT:
+                                       M_BLT(branchdisp);
+                                       break;
+                               case BRANCH_GE:
+                                       M_BGE(branchdisp);
+                                       break;
+                               case BRANCH_GT:
+                                       M_BGT(branchdisp);
+                                       break;
+                               case BRANCH_LE:
+                                       M_BLE(branchdisp);
+                                       break;
+                               case BRANCH_UGT:
+                                       M_BUGT(branchdisp);
+                                       break;
+                               case BRANCH_ULT:
+                                       M_BULT(branchdisp);
+                                       break;
+                               default:
+                                       vm_abort("emit_branch: unknown condition %d", condition);
+                               }
+
+                               /* branch delay */
+                               M_NOP;
+                       }
+               }
+       }
+       else {
+               /* branch on register */
+
+               /* check displacement for overflow (16-bit) */
+
+               if ((branchdisp < (s4) 0xffff8000) || (branchdisp > (s4) 0x0007fff)) {
+                       /* if the long-branches flag isn't set yet, do it */
+
+                       if (!CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
+                               log_println("setting error");
+                               cd->flags |= (CODEGENDATA_FLAG_ERROR |
+                                                         CODEGENDATA_FLAG_LONGBRANCHES);
+                       }
+
+                       vm_abort("emit_branch: emit long-branch on reg code");
+               }
+               else {
+                       switch (condition) {
+                       case BRANCH_EQ:
+                               M_BEQZ(reg, branchdisp);
+                               break;
+                       case BRANCH_NE:
+                               M_BNEZ(reg, branchdisp);
+                               break;
+                       case BRANCH_LT:
+                               M_BLTZ(reg, branchdisp);
+                               break;
+                       case BRANCH_GE:
+                               M_BGEZ(reg, branchdisp);
+                               break;
+                       case BRANCH_GT:
+                               M_BGTZ(reg, branchdisp);
+                               break;
+                       case BRANCH_LE:
+                               M_BLEZ(reg, branchdisp);
+                               break;
+                       default:
+                               vm_abort("emit_branch: unknown condition %d", condition);
+                       }
+
+                       /* branch delay */
+                       M_NOP;
+               }
+       }
+}
+
+
+/* emit_bxx_xcc*****************************************************************
+
+   Wrappers for branches on 64-bit condition codes (SPARC specific).
+
+*******************************************************************************/
+
+void emit_beq_xcc(codegendata *cd, basicblock *target)
+{
+       emit_bcc(cd, target, BRANCH_EQ, BRANCH_OPT_XCC);
+}
+
+void emit_bne_xcc(codegendata *cd, basicblock *target)
+{
+       emit_bcc(cd, target, BRANCH_NE, BRANCH_OPT_XCC);
+}
+
+void emit_blt_xcc(codegendata *cd, basicblock *target)
+{
+       emit_bcc(cd, target, BRANCH_LT, BRANCH_OPT_XCC);
+}
+
+void emit_bge_xcc(codegendata *cd, basicblock *target)
+{
+       emit_bcc(cd, target, BRANCH_GE, BRANCH_OPT_XCC);
+}
+
+void emit_bgt_xcc(codegendata *cd, basicblock *target)
+{
+       emit_bcc(cd, target, BRANCH_GT, BRANCH_OPT_XCC);
+}
+
+void emit_ble_xcc(codegendata *cd, basicblock *target)
+{
+       emit_bcc(cd, target, BRANCH_LE, BRANCH_OPT_XCC);
+}
+
+
+
+
 
 /* emit_arithmetic_check *******************************************************
 
@@ -238,9 +449,9 @@ void emit_lconst(codegendata *cd, s4 d, s8 value)
 void emit_arithmetic_check(codegendata *cd, instruction *iptr, s4 reg)
 {
        if (INSTRUCTION_MUST_CHECK(iptr)) {
-               M_BEQZ(reg, 0);
-               codegen_add_arithmeticexception_ref(cd);
+               M_BNEZ(reg, 3);
                M_NOP;
+               M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_ARITHMETIC);
        }
 }
 
@@ -256,12 +467,47 @@ void emit_arrayindexoutofbounds_check(codegendata *cd, instruction *iptr, s4 s1,
        if (INSTRUCTION_MUST_CHECK(iptr)) {
                M_ILD(REG_ITMP3, s1, OFFSET(java_arrayheader, size));
                M_CMP(s2, REG_ITMP3);
-               M_XBUGE(0);
-               codegen_add_arrayindexoutofboundsexception_ref(cd, s2);
+               M_XBULT(3);
                M_NOP;
+               M_ALD_INTERN(s2, REG_ZERO, EXCEPTION_HARDWARE_ARRAYINDEXOUTOFBOUNDS);
        }
 }
 
+
+/* emit_classcast_check ********************************************************
+
+   Emit a ClassCastException check.
+
+*******************************************************************************/
+
+void emit_classcast_check(codegendata *cd, instruction *iptr, s4 condition, s4 reg, s4 s1)
+{
+/* XXX: use 64-bit or 32-bit compares??? */
+
+       if (INSTRUCTION_MUST_CHECK(iptr)) {
+               switch (condition) {
+               case ICMD_IFEQ:
+                       M_BNEZ(reg, 3);
+                       break;
+
+               case ICMD_IFLE:
+                       M_BGTZ(reg, 3);
+                       break;
+
+               case BRANCH_ULT:
+                       M_XBUGE(3);
+                       break;
+
+               default:
+                       vm_abort("emit_classcast_check: unknown condition %d", condition);
+               }
+
+               M_NOP;
+               M_ALD_INTERN(s1, REG_ZERO, EXCEPTION_HARDWARE_CLASSCAST);
+       }
+}
+
+
 /* emit_nullpointer_check ******************************************************
 
    Emit a NullPointerException check.
@@ -271,22 +517,29 @@ void emit_arrayindexoutofbounds_check(codegendata *cd, instruction *iptr, s4 s1,
 void emit_nullpointer_check(codegendata *cd, instruction *iptr, s4 reg)
 {
        if (INSTRUCTION_MUST_CHECK(iptr)) {
-               M_BEQZ(reg, 0);
-               codegen_add_nullpointerexception_ref(cd);
+               M_BNEZ(reg, 3);
                M_NOP;
+               M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_NULLPOINTER);
        }
 }
 
-/* emit_exception_stubs ********************************************************
 
-   Generates the code for the exception stubs.
+/* emit_exception_check ********************************************************
+
+   Emit an Exception check.
 
 *******************************************************************************/
 
-void emit_exception_stubs(jitdata *jd)
+void emit_exception_check(codegendata *cd, instruction *iptr)
 {
+       if (INSTRUCTION_MUST_CHECK(iptr)) {
+               M_BNEZ(REG_RESULT_CALLER, 3);
+               M_NOP;
+               M_ALD_INTERN(REG_RESULT_CALLER, REG_ZERO, EXCEPTION_HARDWARE_EXCEPTION);
+       }
 }
 
+
 /* emit_patcher_stubs **********************************************************
 
    Generates the code for the patcher stubs.
index a2eed3eb726d11596db814508b31de200bef1b05..5f50a10b2df345512a31c81eea9d6732833ba824 100644 (file)
@@ -1,4 +1,4 @@
-/* src/vm/jit/alpha/linux/md.c - machine dependent Alpha Linux functions
+/* src/vm/jit/sparc64/linux/md-os.c - machine dependent SPARC Linux functions
 
    Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Christian Thalinger
-
-   Changes:
-
-   $Id: md-os.c 4357 2006-01-22 23:33:38Z twisti $
+   $Id: md-os.c 7363 2007-02-15 14:57:04Z twisti $
 
 */
 
+
 #include "config.h"
 
 #include <assert.h>
-#include <ucontext.h>
+#include <signal.h>
 
 #include "vm/types.h"
 
+#include "vm/jit/sparc64/codegen.h"
 #include "vm/jit/sparc64/md-abi.h"
 
 #include "vm/exceptions.h"
 #include "vm/jit/stacktrace.h"
 
 
+typedef struct sigcontext sigcontext;
+
+ptrint md_get_reg_from_context(sigcontext *ctx, u4 rindex)
+{
+       ptrint val;     
+       s8     *window;
+       
+       
+       /* return 0 for REG_ZERO */
+       
+       if (rindex == 0)
+               return 0;
+               
+       
+       if (rindex <= 15) {
+               
+               /* register is in global or out range, available in context */
+               
+               val = ctx->sigc_regs.u_regs[rindex];
+       }
+       else {
+               assert(rindex <= 31);
+               
+               /* register is local or in, need to fetch from regsave area on stack */
+               
+               window = ctx->sigc_regs.u_regs[REG_SP] + BIAS;
+               val = window[rindex - 16];
+       }
+       
+       return val;
+}
+       
+       
+
 /* md_signal_handler_sigsegv ***************************************************
 
    NullPointerException signal handler for hardware null pointer
 
 *******************************************************************************/
 
-void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
+void md_signal_handler_sigsegv(int sig, siginfo_t *info , void *_p)
 {
+       /*
        ucontext_t  *_uc;
        mcontext_t  *_mc;
-       u4           instr;
-       ptrint       addr;
+       */
+       sigcontext *ctx;
        u1          *pv;
        u1          *sp;
        u1          *ra;
        u1          *xpc;
+       u4          mcode;
+       s4                 d;
+       s4                 s1;
+       s4                 disp;
+       ptrint             val;
+       ptrint             addr;
+       s4                 type;
+       java_objectheader *e;
 
-       _uc = (ucontext_t *) _p;
-       _mc = &_uc->uc_mcontext;
+       ctx = (sigcontext *) info;
+
+
+       pv  = (u1 *) md_get_reg_from_context(ctx, REG_PV_CALLEE);
+       sp  = (u1 *) md_get_reg_from_context(ctx, REG_SP);
+       ra  = (u1 *) md_get_reg_from_context(ctx, REG_RA_CALLEE);  /* this is correct for leafs */
+       xpc = (u1 *) ctx->sigc_regs.tpc;
+
+       /* get exception-throwing instruction */        
 
-       instr = *((s4 *) (_mc->mc_gregs[MC_PC]));
-       /*addr = _mc->sc_regs[(instr >> 16) & 0x1f];*/
-       addr = 0;
+       mcode = *((u4 *) xpc);
 
-       if (addr == 0) {
-               pv  = (u1 *) _mc->mc_gregs[MC_G2];
-               sp  = (u1 *) _mc->mc_fp;
-               ra  = (u1 *) _mc->mc_i7;       /* this is correct for leafs */
-               xpc = (u1 *) _mc->mc_gregs[MC_PC];
+       d    = M_OP3_GET_RD(mcode);
+       s1   = M_OP3_GET_RS(mcode);
+       disp = M_OP3_GET_IMM(mcode);
 
-               _mc->mc_gregs[MC_G4] =
-                       (ptrint) stacktrace_hardware_nullpointerexception(pv, sp, ra, xpc);
+       /* flush register windows? */
+       
+       val   = md_get_reg_from_context(ctx, d);
+
+       /* check for special-load */
 
-               _mc->mc_gregs[MC_G5] = (ptrint) xpc;
-               _mc->mc_gregs[MC_PC] = (ptrint) asm_handle_exception;
+       if (s1 == REG_ZERO) {
+               /* we use the exception type as load displacement */
 
-       } else {
-               addr += (long) ((instr << 16) >> 16);
+               type = disp;
+       }
+       else {
+               /* This is a normal NPE: addr must be NULL and the NPE-type
+                  define is 0. */
 
-               /*
-               throw_cacao_exception_exit(string_java_lang_InternalError,
-                                                                  "Segmentation fault: 0x%016lx at 0x%016lx\n",
-                                                                  addr, _mc->mc_gregs[MC_PC]);
-                                                                  */
-               assert(0);
+               addr  = md_get_reg_from_context(ctx, s1);
+               type = (s4) addr;
        }
+
+
+       e = exceptions_new_hardware_exception(pv, sp, ra, xpc, type, val);
+
+       /* set registers */
+
+       ctx->sigc_regs.u_regs[REG_ITMP2_XPTR] = (ptrint) e;
+       ctx->sigc_regs.u_regs[REG_ITMP3_XPC]  = (ptrint) xpc;
+       ctx->sigc_regs.tpc                    = (ptrint) asm_handle_exception;
+       ctx->sigc_regs.tnpc                   = (ptrint) asm_handle_exception + 4;
 }
 
 
@@ -153,4 +207,5 @@ void md_icacheflush(u1 *addr, s4 nbytes)
  * c-basic-offset: 4
  * tab-width: 4
  * End:
+ * vim:noexpandtab:sw=4:ts=4:
  */
index ee1bdfe29ab8164ce5231fec7dba95a423282399..9a55c36954fe44cb8973025baba23e975b4091ae 100644 (file)
 #define SHIFT_AND_MASK(instr) \
        ((instr >> 13) & 0x60fc1)
 
+/* NOP is defined as a SETHI instruction with rd and imm. set to zero */
+/* therefore we check if the 22-bit immediate is zero */
 #define IS_SETHI(instr) \
-       ((instr & 0xc1c00000)  == 0x00800000)
+       (((instr & 0xc1c00000)  == 0x01000000) \
+       && ((instr & 0x3fffff) != 0x0))
+       
+#define IS_LDX_IMM(instr) \
+       (((instr >> 13) & 0x60fc1) == 0x602c1)
+       
+#define IS_SUB(instr) \
+       (((instr >> 13) & 0x60fc0) == 0x40100)
 
 inline s2 decode_13bit_imm(u4 instr) {
        s2 imm;
@@ -74,64 +83,6 @@ void md_init(void)
 }
 
 
-/* md_codegen_patch_branch *****************************************************
-
-   Back-patches a branch instruction.
-
-*******************************************************************************/
-
-void md_codegen_patch_branch(codegendata *cd, s4 branchmpc, s4 targetmpc)
-{
-       s4 *mcodeptr;
-       s4  mcode;
-       s4  disp;                           /* branch displacement                */
-
-       /* calculate the patch position */
-
-       mcodeptr = (s4 *) (cd->mcodebase + branchmpc);
-
-       /* get the instruction before the exception point */
-
-       mcode = mcodeptr[-1];
-       
-       /* Calculate the branch displacement.  SPARC displacements regard current
-          PC as base => (branchmpc - 4 */
-       
-       disp = (targetmpc - (branchmpc - 4)) >> 2;
-       
-
-       /* check for BPcc or FBPfcc instruction */
-       if (((mcode >> 16) & 0xc1c0) == 0x0040) {
-       
-               /* check branch displacement (19-bit)*/
-       
-               if ((disp < (s4) 0xfffc0000) || (disp > (s4) 0x003ffff))
-                       vm_abort("branch displacement is out of range: %d > +/-%d", disp, 0x003ffff);
-       
-               /* patch the branch instruction before the mcodeptr */
-       
-               mcodeptr[-1] |= (disp & 0x007ffff);
-       }
-       /* check for BPr instruction */
-       else if (((mcode >> 16) & 0xd1c0) == 0x00c0) {
-
-               /* check branch displacement (16-bit)*/
-       
-               if ((disp < (s4) 0xffff8000) || (disp > (s4) 0x0007fff))
-                       vm_abort("branch displacement is out of range: %d > +/-%d", disp, 0x0007fff);
-                       
-               /* patch the upper 2-bit of the branch displacement */
-               mcodeptr[-1] |= ((disp & 0xc000) << 6);
-                       
-               /* patch the lower 14-bit of the branch displacement */
-               mcodeptr[-1] |= (disp & 0x003fff);
-               
-       }
-       else
-               assert(0);
-}
-
-
 /* md_stacktrace_get_returnaddress *********************************************
 
    Returns the return address of the current stackframe, specified by
@@ -274,67 +225,81 @@ u1 *md_get_method_patch_address(u1 *ra, stackframeinfo *sfi, u1 *mptr)
 {
        u4  mcode, mcode_masked;
        s4  offset;
-       u1 *pa;
+       u1 *pa, *iptr;
 
-       /* go back to the actual load instruction (1 instruction before jump) */
-       /* ra is the address of the jump instruction on SPARC                 */
-       ra -= 1 * 4;
+       /* go back to the location of a possible sethi (3 instruction before jump) */
+       /* note: ra is the address of the jump instruction on SPARC                */
+       iptr = ra - 3 * 4;
 
        /* get first instruction word on current PC */
 
-       mcode = *((u4 *) ra);
-
+       mcode = *((u4 *) iptr);
 
-       /* check if we have 2 instructions (lui) */
+       /* check for sethi instruction */
 
        if (IS_SETHI(mcode)) {
                /* XXX write a regression for this */
-               assert(0);
 
-               /* get displacement of first instruction (lui) */
+               /* get 22-bit displacement of sethi instruction */
 
-               offset = (s4) (mcode << 16);
+               offset = (s4) (mcode & 0x3fffff);
+               offset = offset << 10;
+               
+               /* goto next instruction */
+               iptr += 4;
+               mcode = *((u4 *) iptr);
+               
+               /* make sure it's a sub instruction (pv - big_disp) */
+               assert(IS_SUB(mcode));
+               offset = -offset;
 
-               /* get displacement of second instruction (daddiu) */
+               /* get displacement of load instruction */
 
-               mcode = *((u4 *) (ra + 1 * 4));
+               mcode = *((u4 *) (ra - 1 * 4));
+               assert(IS_LDX_IMM(mcode));
 
-               assert((mcode >> 16) != 0x6739);
+               offset += decode_13bit_imm(mcode);
+               
+               pa = sfi->pv + offset;
 
-               offset += (s2) (mcode & 0x0000ffff);
+               return pa;
+       }
 
-       } else {
 
-               /* shift and maks rd */
+       /* simple (one-instruction) load */
+       iptr = ra - 1 * 4;
+       mcode = *((u4 *) iptr);
 
-               mcode_masked = (mcode >> 13) & 0x060fff;
-               
-               /* get the offset from the instruction */
+       /* shift and mask rd */
 
-               offset = decode_13bit_imm(mcode);
+       mcode_masked = (mcode >> 13) & 0x060fff;
+       
+       /* get the offset from the instruction */
 
-               /* check for call with rs1 == REG_METHODPTR: ldx [g2+x],pv_caller */
+       offset = decode_13bit_imm(mcode);
 
-               if (mcode_masked == 0x0602c5) {
-                       /* in this case we use the passed method pointer */
+       /* check for call with rs1 == REG_METHODPTR: ldx [g2+x],pv_caller */
 
-                       /* return NULL if no mptr was specified (used for replacement) */
+       if (mcode_masked == 0x0602c5) {
+               /* in this case we use the passed method pointer */
 
-                       if (mptr == NULL)
-                               return NULL;
+               /* return NULL if no mptr was specified (used for replacement) */
 
-                       pa = mptr + offset;
+               if (mptr == NULL)
+                       return NULL;
 
-               } else {
-                       /* in the normal case we check for a `ldx [i5+x],pv_caller' instruction */
+               pa = mptr + offset;
 
-                       assert(mcode_masked  == 0x0602fb);
+       } else {
+               /* in the normal case we check for a `ldx [i5+x],pv_caller' instruction */
 
-                       /* and get the final data segment address */
+               assert(mcode_masked  == 0x0602fb);
 
-                       pa = sfi->pv + offset;
-               }
+               /* and get the final data segment address */
+
+               pa = sfi->pv + offset;
        }
+       
 
        return pa;
 }
index 9f76e1ffeab6d065d71f98629b7414643390df66..e9467d192a458a845388223da9c84351e8ff2c54 100644 (file)
@@ -614,12 +614,6 @@ bool patcher_checkcast_interface(u1 *sp)
 
        /* if we show disassembly, we have to skip the nop's */
 
-       if (opt_shownops)
-               ra = ra + PATCHER_CALL_SIZE;
-
-
-       /* if we show disassembly, we have to skip the nop's */
-
        if (opt_shownops)
                ra = ra + PATCHER_CALL_SIZE;
 
@@ -627,15 +621,16 @@ bool patcher_checkcast_interface(u1 *sp)
 
        *((s4 *) (ra + 2 * 4)) |= (s4) (-(c->index) & 0x00001fff);
 
-       *((s4 *) (ra + 5 * 4)) |= (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
-                                                                        c->index * sizeof(methodptr*)) & 0x00001fff);
+       *((s4 *) (ra + (3 + EXCEPTION_CHECK_INSTRUCTIONS) * 4)) |= 
+               (s4) ((OFFSET(vftbl_t, interfacetable[0])
+               - c->index * sizeof(methodptr*)) & 0x00001fff);
 
        /* synchronize instruction cache */
 
        if (opt_shownops)
-               md_icacheflush(ra - 2 * 4, 8 * 4);
+               md_icacheflush(ra - 2 * 4, (6 + EXCEPTION_CHECK_INSTRUCTIONS) * 4);
        else
-               md_icacheflush(ra, 6 * 4);
+               md_icacheflush(ra, (4 + EXCEPTION_CHECK_INSTRUCTIONS) * 4);
 
        return true;
 }
@@ -660,8 +655,6 @@ bool patcher_instanceof_interface(u1 *sp)
        constant_classref *cr;
        classinfo         *c;
 
-       assert(0); /* test this one !!! */
-
        /* get stuff from the stack */
 
        ra = (u1 *)                *((ptrint *) (sp + 5 * 8));
index 0e3e4df10794a726d9d935bb0f2e52eca0545847..4052676e1e8a5eaa7a546f9d30e33b5861a5229e 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: stacktrace.c 7343 2007-02-13 02:36:29Z ajordan $
+   $Id: stacktrace.c 7584 2007-03-27 18:17:27Z tbfg $
 
 */
 
@@ -943,7 +943,7 @@ stacktracebuffer *stacktrace_create(threadobject* thread)
                        else
 #endif
                                {
-#if defined(__I386__) || defined (__X86_64__)
+#if defined(__I386__) || defined (__X86_64__) || defined (__M68K__)
                                        sp += framesize + SIZEOF_VOID_P;
 #elif defined(__SPARC_64__)
                                        /* already has the new sp */
index bad9f4af6d2d29f9d41cb5c2cf4b72ea4ac8e67d..1e4ee26ddcab552e2883adb471a7ddd41d49c7dd 100644 (file)
@@ -26,8 +26,6 @@
 
    Authors: Edwin Steiner
 
-   Changes: 
-
    $Id$
 
 */
                if ((state->iptr->opc == ICMD_INVOKEVIRTUAL)
                        && (mi->flags & (ACC_FINAL | ACC_PRIVATE)))
                {
-                       state->iptr->opc = ICMD_INVOKESPECIAL;
+                       state->iptr->opc         = ICMD_INVOKESPECIAL;
+                       state->iptr->flags.bits |= INS_FLAG_CHECK;
                }
        }
        else {
index 25f8a0747509920a68e3e305d7c78048ea04d30a..d8182627325a47204f67734d4755fa0d3dc4ecb4 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: arch.h 7241 2007-01-27 15:52:01Z twisti $
+   $Id: arch.h 7590 2007-03-28 18:54:02Z twisti $
 
 */
 
 #define CONSECUTIVE_FLOAT_ARGS
 
 
+/* branches *******************************************************************/
+
+#define SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER       1
+#define SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER     0
+#define SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS    0
+#define SUPPORT_BRANCH_CONDITIONAL_UNSIGNED_CONDITIONS      1
+
+
 /* exceptions *****************************************************************/
 
 #define SUPPORT_HARDWARE_DIVIDE_BY_ZERO  1
index 0cac95447e6b37dbf00fa41ef461992f643b73bd..83da57bef44c240079e13fa7f691a60524d644fe 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: asmpart.S 7475 2007-03-07 12:37:34Z twisti $
+   $Id: asmpart.S 7486 2007-03-08 13:50:07Z twisti $
 
 */
 
@@ -49,6 +49,7 @@
        .globl asm_vm_call_method_float
        .globl asm_vm_call_method_double
        .globl asm_vm_call_method_exception_handler
+       .globl asm_vm_call_method_end
 
        .globl asm_call_jit_compiler
 
@@ -291,6 +292,8 @@ handle_fa7:
        movq    offvmargdata(itmp2),fa7
        jmp     L_register_copy
 
+asm_vm_call_method_end:
+       nop
 
 /****************** function asm_call_jit_compiler *****************************
 *                                                                              *
index d6915b2a071462d0edc444cb5058e04edcd649c1..ea8410bede9498b0d70d2cd5c07c9b7e8cdbc66b 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: codegen.c 7281 2007-02-03 19:51:36Z twisti $
+   $Id: codegen.c 7590 2007-03-28 18:54:02Z twisti $
 
 */
 
 #include "vmcore/statistics.h"
 
 
-/* codegen *********************************************************************
+/* codegen_emit ****************************************************************
 
    Generates machine code.
 
 *******************************************************************************/
 
-bool codegen(jitdata *jd)
+bool codegen_emit(jitdata *jd)
 {
        methodinfo         *m;
        codeinfo           *code;
@@ -297,8 +297,8 @@ bool codegen(jitdata *jd)
                }
                else {
                        M_TEST(REG_A0);
-                       M_BEQ(0);
-                       codegen_add_nullpointerexception_ref(cd);
+                       M_BNE(8);
+                       M_ALD_MEM(REG_A0, EXCEPTION_HARDWARE_NULLPOINTER);
                }
 
                M_AST(REG_A0, REG_SP, s1 * 8);
@@ -1448,8 +1448,8 @@ bool codegen(jitdata *jd)
                        M_MOV_IMM(1, REG_ITMP1);
                        M_MOV_IMM(-1, REG_ITMP2);
                        emit_ucomiss_reg_reg(cd, s1, s2);
-                       M_CMOVB(REG_ITMP1, d);
-                       M_CMOVA(REG_ITMP2, d);
+                       M_CMOVULT(REG_ITMP1, d);
+                       M_CMOVUGT(REG_ITMP2, d);
                        M_CMOVP(REG_ITMP2, d);                   /* treat unordered as GT */
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1464,8 +1464,8 @@ bool codegen(jitdata *jd)
                        M_MOV_IMM(1, REG_ITMP1);
                        M_MOV_IMM(-1, REG_ITMP2);
                        emit_ucomiss_reg_reg(cd, s1, s2);
-                       M_CMOVB(REG_ITMP1, d);
-                       M_CMOVA(REG_ITMP2, d);
+                       M_CMOVULT(REG_ITMP1, d);
+                       M_CMOVUGT(REG_ITMP2, d);
                        M_CMOVP(REG_ITMP1, d);                   /* treat unordered as LT */
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1480,8 +1480,8 @@ bool codegen(jitdata *jd)
                        M_MOV_IMM(1, REG_ITMP1);
                        M_MOV_IMM(-1, REG_ITMP2);
                        emit_ucomisd_reg_reg(cd, s1, s2);
-                       M_CMOVB(REG_ITMP1, d);
-                       M_CMOVA(REG_ITMP2, d);
+                       M_CMOVULT(REG_ITMP1, d);
+                       M_CMOVUGT(REG_ITMP2, d);
                        M_CMOVP(REG_ITMP2, d);                   /* treat unordered as GT */
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1496,8 +1496,8 @@ bool codegen(jitdata *jd)
                        M_MOV_IMM(1, REG_ITMP1);
                        M_MOV_IMM(-1, REG_ITMP2);
                        emit_ucomisd_reg_reg(cd, s1, s2);
-                       M_CMOVB(REG_ITMP1, d);
-                       M_CMOVA(REG_ITMP2, d);
+                       M_CMOVULT(REG_ITMP1, d);
+                       M_CMOVUGT(REG_ITMP2, d);
                        M_CMOVP(REG_ITMP1, d);                   /* treat unordered as LT */
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1509,7 +1509,7 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
-                       emit_nullpointer_check(cd, iptr, s1);
+                       /* implicit null-pointer check */
                        M_ILD(d, s1, OFFSET(java_arrayheader, size));
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1519,7 +1519,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        emit_movsbq_memindex_reg(cd, OFFSET(java_bytearray, data[0]), s1, s2, 0, d);
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1529,7 +1530,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        emit_movzwq_memindex_reg(cd, OFFSET(java_chararray, data[0]), s1, s2, 1, d);
                        emit_store_dst(jd, iptr, d);
                        break;                  
@@ -1539,7 +1541,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        emit_movswq_memindex_reg(cd, OFFSET(java_shortarray, data[0]), s1, s2, 1, d);
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1549,7 +1552,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        emit_movl_memindex_reg(cd, OFFSET(java_intarray, data[0]), s1, s2, 2, d);
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1559,7 +1563,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        emit_mov_memindex_reg(cd, OFFSET(java_longarray, data[0]), s1, s2, 3, d);
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1569,7 +1574,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        emit_movss_memindex_reg(cd, OFFSET(java_floatarray, data[0]), s1, s2, 2, d);
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1579,7 +1585,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        emit_movsd_memindex_reg(cd, OFFSET(java_doublearray, data[0]), s1, s2, 3, d);
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1589,7 +1596,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        emit_mov_memindex_reg(cd, OFFSET(java_objectarray, data[0]), s1, s2, 3, d);
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1599,7 +1607,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
                        emit_movb_reg_memindex(cd, s3, OFFSET(java_bytearray, data[0]), s1, s2, 0);
                        break;
@@ -1608,7 +1617,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
                        emit_movw_reg_memindex(cd, s3, OFFSET(java_chararray, data[0]), s1, s2, 1);
                        break;
@@ -1617,7 +1627,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
                        emit_movw_reg_memindex(cd, s3, OFFSET(java_shortarray, data[0]), s1, s2, 1);
                        break;
@@ -1626,7 +1637,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
                        emit_movl_reg_memindex(cd, s3, OFFSET(java_intarray, data[0]), s1, s2, 2);
                        break;
@@ -1635,7 +1647,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
                        emit_mov_reg_memindex(cd, s3, OFFSET(java_longarray, data[0]), s1, s2, 3);
                        break;
@@ -1644,7 +1657,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_FTMP3);
                        emit_movss_reg_memindex(cd, s3, OFFSET(java_floatarray, data[0]), s1, s2, 2);
                        break;
@@ -1653,7 +1667,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_FTMP3);
                        emit_movsd_reg_memindex(cd, s3, OFFSET(java_doublearray, data[0]), s1, s2, 3);
                        break;
@@ -1662,16 +1677,15 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
 
                        M_MOV(s1, REG_A0);
                        M_MOV(s3, REG_A1);
                        M_MOV_IMM(BUILTIN_canstore, REG_ITMP1);
                        M_CALL(REG_ITMP1);
-                       M_TEST(REG_RESULT);
-                       M_BEQ(0);
-                       codegen_add_arraystoreexception_ref(cd);
+                       emit_exception_check(cd, iptr);
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
@@ -1684,7 +1698,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        emit_movb_imm_memindex(cd, iptr->sx.s23.s3.constval, OFFSET(java_bytearray, data[0]), s1, s2, 0);
                        break;
 
@@ -1692,7 +1707,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        emit_movw_imm_memindex(cd, iptr->sx.s23.s3.constval, OFFSET(java_chararray, data[0]), s1, s2, 1);
                        break;
 
@@ -1700,7 +1716,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        emit_movw_imm_memindex(cd, iptr->sx.s23.s3.constval, OFFSET(java_shortarray, data[0]), s1, s2, 1);
                        break;
 
@@ -1708,7 +1725,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        emit_movl_imm_memindex(cd, iptr->sx.s23.s3.constval, OFFSET(java_intarray, data[0]), s1, s2, 2);
                        break;
 
@@ -1716,11 +1734,13 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
 
                        if (IS_IMM32(iptr->sx.s23.s3.constval)) {
                                emit_mov_imm_memindex(cd, (u4) (iptr->sx.s23.s3.constval & 0x00000000ffffffff), OFFSET(java_longarray, data[0]), s1, s2, 3);
-                       } else {
+                       }
+                       else {
                                emit_movl_imm_memindex(cd, (u4) (iptr->sx.s23.s3.constval & 0x00000000ffffffff), OFFSET(java_longarray, data[0]), s1, s2, 3);
                                emit_movl_imm_memindex(cd, (u4) (iptr->sx.s23.s3.constval >> 32), OFFSET(java_longarray, data[0]) + 4, s1, s2, 3);
                        }
@@ -1730,7 +1750,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        emit_mov_imm_memindex(cd, 0, OFFSET(java_objectarray, data[0]), s1, s2, 3);
                        break;
 
@@ -1741,7 +1762,7 @@ bool codegen(jitdata *jd)
                                uf        = iptr->sx.s23.s3.uf;
                                fieldtype = uf->fieldref->parseddesc.fd->type;
                                disp      = dseg_add_unique_address(cd, NULL);
-                               disp      = -((cd->mcodeptr + 7) - cd->mcodebase) + disp;
+                               disp      = disp + -((cd->mcodeptr + 7) - cd->mcodebase);
 
                                /* must be calculated before codegen_add_patch_ref */
 
@@ -1758,17 +1779,17 @@ bool codegen(jitdata *jd)
                                fi        = iptr->sx.s23.s3.fmiref->p.field;
                                fieldtype = fi->type;
                                disp      = dseg_add_address(cd, &(fi->value));
-                               disp      = -((cd->mcodeptr + 7) - cd->mcodebase) + disp;
+                               disp      = disp + -((cd->mcodeptr + 7) - cd->mcodebase);
 
                                if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
                                        PROFILE_CYCLE_STOP;
 
                                        codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, 0);
 
+                                       PROFILE_CYCLE_START;
+
                                        if (opt_shownops)
                                                disp -= PATCHER_CALL_SIZE;
-
-                                       PROFILE_CYCLE_START;
                                }
                        }
 
@@ -1805,7 +1826,7 @@ bool codegen(jitdata *jd)
                                uf        = iptr->sx.s23.s3.uf;
                                fieldtype = uf->fieldref->parseddesc.fd->type;
                                disp      = dseg_add_unique_address(cd, NULL);
-                               disp      = -((cd->mcodeptr + 7) - cd->mcodebase) + disp;
+                               disp      = disp + -((cd->mcodeptr + 7) - cd->mcodebase);
 
                                /* must be calculated before codegen_add_patch_ref */
 
@@ -1822,17 +1843,17 @@ bool codegen(jitdata *jd)
                                fi        = iptr->sx.s23.s3.fmiref->p.field;
                                fieldtype = fi->type;
                                disp      = dseg_add_address(cd, &(fi->value));
-                               disp      = -((cd->mcodeptr + 7) - cd->mcodebase) + disp;
+                               disp      = disp + -((cd->mcodeptr + 7) - cd->mcodebase);
 
                                if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
                                        PROFILE_CYCLE_STOP;
 
                                        codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, 0);
 
+                                       PROFILE_CYCLE_START;
+
                                        if (opt_shownops)
                                                disp -= PATCHER_CALL_SIZE;
-
-                                       PROFILE_CYCLE_START;
                                }
                        }
 
@@ -1870,14 +1891,13 @@ bool codegen(jitdata *jd)
                                uf        = iptr->sx.s23.s3.uf;
                                fieldtype = uf->fieldref->parseddesc.fd->type;
                                disp      = dseg_add_unique_address(cd, NULL);
-                               disp      = -((cd->mcodeptr + 7) - cd->mcodebase) + disp;
+                               disp      = disp + -((cd->mcodeptr + 7) - cd->mcodebase);
 
                                /* must be calculated before codegen_add_patch_ref */
 
                                if (opt_shownops)
                                        disp -= PATCHER_CALL_SIZE;
 
-
 /*                             PROFILE_CYCLE_STOP; */
 
                                codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp);
@@ -1888,17 +1908,17 @@ bool codegen(jitdata *jd)
                                fi        = iptr->sx.s23.s3.fmiref->p.field;
                                fieldtype = fi->type;
                                disp      = dseg_add_address(cd, &(fi->value));
-                               disp      = -((cd->mcodeptr + 7) - cd->mcodebase) + disp;
+                               disp      = disp + -((cd->mcodeptr + 7) - cd->mcodebase);
 
                                if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
                                        PROFILE_CYCLE_STOP;
 
                                        codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, 0);
 
+                                       PROFILE_CYCLE_START;
+
                                        if (opt_shownops)
                                                disp -= PATCHER_CALL_SIZE;
-
-                                       PROFILE_CYCLE_START;
                                }
                        }
 
@@ -1928,7 +1948,6 @@ bool codegen(jitdata *jd)
                case ICMD_GETFIELD:   /* ...  ==> ..., value                          */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       emit_nullpointer_check(cd, iptr, s1);
 
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
                                uf        = iptr->sx.s23.s3.uf;
@@ -1947,6 +1966,7 @@ bool codegen(jitdata *jd)
                                disp      = fi->offset;
                        }
 
+                       /* implicit null-pointer check */
                        switch (fieldtype) {
                        case TYPE_INT:
                                d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
@@ -1973,7 +1993,6 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_IFTMP); /* REG_IFTMP == REG_ITMP2 */
-                       emit_nullpointer_check(cd, iptr, s1);
 
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
                                uf        = iptr->sx.s23.s3.uf;
@@ -1992,6 +2011,7 @@ bool codegen(jitdata *jd)
                                disp      = fi->offset;
                        }
 
+                       /* implicit null-pointer check */
                        switch (fieldtype) {
                        case TYPE_INT:
                                M_IST32(s2, s1, disp);
@@ -2014,7 +2034,6 @@ bool codegen(jitdata *jd)
                                          /* following NOP)                           */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       emit_nullpointer_check(cd, iptr, s1);
 
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
                                uf        = iptr->sx.s23.s3.uf;
@@ -2033,6 +2052,7 @@ bool codegen(jitdata *jd)
                                disp      = fi->offset;
                        }
 
+                       /* implicit null-pointer check */
                        switch (fieldtype) {
                        case TYPE_INT:
                        case TYPE_FLT:
@@ -2074,83 +2094,44 @@ bool codegen(jitdata *jd)
                        break;
 
                case ICMD_GOTO:         /* ... ==> ...                                */
-               case ICMD_RET:          /* ... ==> ...                                */
+               case ICMD_RET:
 
-                       M_JMP_IMM(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                       emit_br(cd, iptr->dst.block);
+                       ALIGNCODENOP;
                        break;
 
                case ICMD_JSR:          /* ... ==> ...                                */
 
-                       M_JMP_IMM(0);
-                       codegen_add_branch_ref(cd, iptr->sx.s23.s3.jsrtarget.block);
+                       emit_br(cd, iptr->sx.s23.s3.jsrtarget.block);
+                       ALIGNCODENOP;
                        break;
                        
                case ICMD_IFNULL:       /* ..., value ==> ...                         */
+               case ICMD_IFNONNULL:
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        M_TEST(s1);
-                       M_BEQ(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IFNONNULL:    /* ..., value ==> ...                         */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       M_TEST(s1);
-                       M_BNE(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                       emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IFNULL, BRANCH_OPT_NONE);
                        break;
 
                case ICMD_IFEQ:         /* ..., value ==> ...                         */
+               case ICMD_IFLT:
+               case ICMD_IFLE:
+               case ICMD_IFNE:
+               case ICMD_IFGT:
+               case ICMD_IFGE:
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        M_ICMP_IMM(iptr->sx.val.i, s1);
-                       M_BEQ(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IFLT:         /* ..., value ==> ...                         */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       M_ICMP_IMM(iptr->sx.val.i, s1);
-                       M_BLT(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IFLE:         /* ..., value ==> ...                         */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       M_ICMP_IMM(iptr->sx.val.i, s1);
-                       M_BLE(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IFNE:         /* ..., value ==> ...                         */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       M_ICMP_IMM(iptr->sx.val.i, s1);
-                       M_BNE(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IFGT:         /* ..., value ==> ...                         */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       M_ICMP_IMM(iptr->sx.val.i, s1);
-                       M_BGT(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IFGE:         /* ..., value ==> ...                         */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       M_ICMP_IMM(iptr->sx.val.i, s1);
-                       M_BGE(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                       emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IFEQ, BRANCH_OPT_NONE);
                        break;
 
                case ICMD_IF_LEQ:       /* ..., value ==> ...                         */
+               case ICMD_IF_LNE:
+               case ICMD_IF_LLT:
+               case ICMD_IF_LGE:
+               case ICMD_IF_LGT:
+               case ICMD_IF_LLE:
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        if (IS_IMM32(iptr->sx.val.l))
@@ -2159,183 +2140,42 @@ bool codegen(jitdata *jd)
                                M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
                                M_LCMP(REG_ITMP2, s1);
                        }
-                       M_BEQ(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IF_LLT:       /* ..., value ==> ...                         */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (IS_IMM32(iptr->sx.val.l))
-                               M_LCMP_IMM(iptr->sx.val.l, s1);
-                       else {
-                               M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
-                               M_LCMP(REG_ITMP2, s1);
-                       }
-                       M_BLT(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IF_LLE:       /* ..., value ==> ...                         */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (IS_IMM32(iptr->sx.val.l))
-                               M_LCMP_IMM(iptr->sx.val.l, s1);
-                       else {
-                               M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
-                               M_LCMP(REG_ITMP2, s1);
-                       }
-                       M_BLE(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IF_LNE:       /* ..., value ==> ...                         */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (IS_IMM32(iptr->sx.val.l))
-                               M_LCMP_IMM(iptr->sx.val.l, s1);
-                       else {
-                               M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
-                               M_LCMP(REG_ITMP2, s1);
-                       }
-                       M_BNE(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IF_LGT:       /* ..., value ==> ...                         */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (IS_IMM32(iptr->sx.val.l))
-                               M_LCMP_IMM(iptr->sx.val.l, s1);
-                       else {
-                               M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
-                               M_LCMP(REG_ITMP2, s1);
-                       }
-                       M_BGT(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IF_LGE:       /* ..., value ==> ...                         */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (IS_IMM32(iptr->sx.val.l))
-                               M_LCMP_IMM(iptr->sx.val.l, s1);
-                       else {
-                               M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
-                               M_LCMP(REG_ITMP2, s1);
-                       }
-                       M_BGE(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                       emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IF_LEQ, BRANCH_OPT_NONE);
                        break;
 
                case ICMD_IF_ICMPEQ:    /* ..., value, value ==> ...                  */
+               case ICMD_IF_ICMPNE:
+               case ICMD_IF_ICMPLT:
+               case ICMD_IF_ICMPGE:
+               case ICMD_IF_ICMPGT:
+               case ICMD_IF_ICMPLE:
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_ICMP(s2, s1);
-                       M_BEQ(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                       emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IF_ICMPEQ, BRANCH_OPT_NONE);
                        break;
 
-               case ICMD_IF_LCMPEQ:    /* ..., value, value ==> ...                  */
-               case ICMD_IF_ACMPEQ:    /* op1 = target JavaVM pc                     */
+               case ICMD_IF_ACMPEQ:    /* ..., value, value ==> ...                  */
+               case ICMD_IF_ACMPNE:
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_LCMP(s2, s1);
-                       M_BEQ(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                       emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IF_ACMPEQ, BRANCH_OPT_NONE);
                        break;
 
-               case ICMD_IF_ICMPNE:    /* ..., value, value ==> ...                  */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       M_ICMP(s2, s1);
-                       M_BNE(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IF_LCMPNE:    /* ..., value, value ==> ...                  */
-               case ICMD_IF_ACMPNE:    /* op1 = target JavaVM pc                     */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       M_LCMP(s2, s1);
-                       M_BNE(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IF_ICMPLT:    /* ..., value, value ==> ...                  */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       M_ICMP(s2, s1);
-                       M_BLT(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IF_LCMPLT:    /* ..., value, value ==> ...                  */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       M_LCMP(s2, s1);
-                       M_BLT(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IF_ICMPGT:    /* ..., value, value ==> ...                  */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       M_ICMP(s2, s1);
-                       M_BGT(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IF_LCMPGT:    /* ..., value, value ==> ...                  */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       M_LCMP(s2, s1);
-                       M_BGT(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IF_ICMPLE:    /* ..., value, value ==> ...                  */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       M_ICMP(s2, s1);
-                       M_BLE(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IF_LCMPLE:    /* ..., value, value ==> ...                  */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       M_LCMP(s2, s1);
-                       M_BLE(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IF_ICMPGE:    /* ..., value, value ==> ...                  */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       M_ICMP(s2, s1);
-                       M_BGE(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IF_LCMPGE:    /* ..., value, value ==> ...                  */
+               case ICMD_IF_LCMPEQ:    /* ..., value, value ==> ...                  */
+               case ICMD_IF_LCMPNE:
+               case ICMD_IF_LCMPLT:
+               case ICMD_IF_LCMPGE:
+               case ICMD_IF_LCMPGT:
+               case ICMD_IF_LCMPLE:
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_LCMP(s2, s1);
-                       M_BGE(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                       emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IF_LCMPEQ, BRANCH_OPT_NONE);
                        break;
 
                case ICMD_IRETURN:      /* ..., retvalue ==> ...                      */
@@ -2466,10 +2306,9 @@ nowperformreturn:
                                i = i - l + 1;
 
                 /* range check */
-                               M_ICMP_IMM(i - 1, REG_ITMP1);
-                               M_BA(0);
 
-                               codegen_add_branch_ref(cd, table[0].block); /* default target */
+                               M_ICMP_IMM(i - 1, REG_ITMP1);
+                               emit_bugt(cd, table[0].block);
 
                                /* build jump table top down and use address of lowest entry */
 
@@ -2505,14 +2344,12 @@ nowperformreturn:
 
                                while (--i >= 0) {
                                        M_ICMP_IMM(lookup->value, s1);
-                                       M_BEQ(0);
-                                       codegen_add_branch_ref(cd, lookup->target.block);
+                                       emit_beq(cd, lookup->target.block);
                                        lookup++;
                                }
 
-                               M_JMP_IMM(0);
-                       
-                               codegen_add_branch_ref(cd, iptr->sx.s23.s3.lookupdefault.block);
+                               emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
+                               ALIGNCODENOP;
                        }
                        break;
 
@@ -2593,24 +2430,17 @@ gen_method:
                                M_MOV_IMM(bte->fp, REG_ITMP1);
                                M_CALL(REG_ITMP1);
 
-                               if (INSTRUCTION_MUST_CHECK(iptr)) {
-                                       M_TEST(REG_RESULT);
-                                       M_BEQ(0);
-                                       codegen_add_fillinstacktrace_ref(cd);
-                               }
+                               emit_exception_check(cd, iptr);
                                break;
 
                        case ICMD_INVOKESPECIAL:
-                               M_TEST(REG_A0);
-                               M_BEQ(0);
-                               codegen_add_nullpointerexception_ref(cd);
-
+                               emit_nullpointer_check(cd, iptr, REG_A0);
                                /* fall through */
 
                        case ICMD_INVOKESTATIC:
                                if (lm == NULL) {
                                        disp = dseg_add_unique_address(cd, NULL);
-                                       disp = -((cd->mcodeptr + 7) - cd->mcodebase) + disp;
+                                       disp = disp + -((cd->mcodeptr + 7) - cd->mcodebase);
 
                                        /* must be calculated before codegen_add_patch_ref */
 
@@ -2624,7 +2454,7 @@ gen_method:
                                }
                                else {
                                        disp = dseg_add_functionptr(cd, lm->stubroutine);
-                                       disp = -((cd->mcodeptr + 7) - cd->mcodebase) + disp;
+                                       disp = disp + -((cd->mcodeptr + 7) - cd->mcodebase);
 
 /*                                     a = (ptrint) lm->stubroutine; */
                                }
@@ -2635,26 +2465,23 @@ gen_method:
                                break;
 
                        case ICMD_INVOKEVIRTUAL:
-                               emit_nullpointer_check(cd, iptr, REG_A0);
-
                                if (lm == NULL) {
                                        codegen_add_patch_ref(cd, PATCHER_invokevirtual, um, 0);
 
                                        s1 = 0;
                                }
-                               else
+                               else {
                                        s1 = OFFSET(vftbl_t, table[0]) +
                                                sizeof(methodptr) * lm->vftblindex;
+                               }
 
-                               M_ALD(REG_METHODPTR, REG_A0,
-                                         OFFSET(java_objectheader, vftbl));
+                               /* implicit null-pointer check */
+                               M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_objectheader, vftbl));
                                M_ALD32(REG_ITMP3, REG_METHODPTR, s1);
                                M_CALL(REG_ITMP3);
                                break;
 
                        case ICMD_INVOKEINTERFACE:
-                               emit_nullpointer_check(cd, iptr, REG_A0);
-
                                if (lm == NULL) {
                                        codegen_add_patch_ref(cd, PATCHER_invokeinterface, um, 0);
 
@@ -2668,8 +2495,8 @@ gen_method:
                                        s2 = sizeof(methodptr) * (lm - lm->class->methods);
                                }
 
-                               M_ALD(REG_METHODPTR, REG_A0,
-                                         OFFSET(java_objectheader, vftbl));
+                               /* implicit null-pointer check */
+                               M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_objectheader, vftbl));
                                M_ALD32(REG_METHODPTR, REG_METHODPTR, s1);
                                M_ALD32(REG_ITMP3, REG_METHODPTR, s2);
                                M_CALL(REG_ITMP3);
@@ -2686,39 +2513,29 @@ gen_method:
 
                        /* store return value */
 
-                       d = md->returntype.type;
-
-                       if (d != TYPE_VOID) {
-                               if (IS_INT_LNG_TYPE(d)) {
-                                       s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
-                                       M_INTMOVE(REG_RESULT, s1);
-                               }
-                               else {
-                                       s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
-                                       M_FLTMOVE(REG_FRESULT, s1);
-                               }
+                       switch (md->returntype.type) {
+                       case TYPE_INT:
+                       case TYPE_LNG:
+                       case TYPE_ADR:
+                               s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
+                               M_INTMOVE(REG_RESULT, s1);
+                               emit_store_dst(jd, iptr, s1);
+                               break;
+                       case TYPE_FLT:
+                       case TYPE_DBL:
+                               s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
+                               M_FLTMOVE(REG_FRESULT, s1);
                                emit_store_dst(jd, iptr, s1);
+                               break;
+                       default:
+                               /* TYPE_VOID */
+                               break;
                        }
                        break;
 
 
                case ICMD_CHECKCAST:  /* ..., objectref ==> ..., objectref            */
 
-                                     /* val.a: (classinfo *) superclass              */
-
-                       /*  superclass is an interface:
-                        *      
-                        *  OK if ((sub == NULL) ||
-                        *         (sub->vftbl->interfacetablelength > super->index) &&
-                        *         (sub->vftbl->interfacetable[-super->index] != NULL));
-                        *      
-                        *  superclass is a class:
-                        *      
-                        *  OK if ((sub == NULL) || (0
-                        *         <= (sub->vftbl->baseval - super->vftbl->baseval) <=
-                        *         super->vftbl->diffval));
-                        */
-
                        if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
                                /* object type cast-check */
 
@@ -2727,12 +2544,12 @@ gen_method:
                                s4         superindex;
 
                                if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
-                                       super = NULL;
+                                       super      = NULL;
                                        superindex = 0;
                                        supervftbl = NULL;
                                }
                                else {
-                                       super = iptr->sx.s23.s3.c.cls;
+                                       super      = iptr->sx.s23.s3.c.cls;
                                        superindex = super->index;
                                        supervftbl = super->vftbl;
                                }
@@ -2742,57 +2559,18 @@ gen_method:
 #endif
                                s1 = emit_load_s1(jd, iptr, REG_ITMP1);
 
-                               /* calculate interface checkcast code size */
-
-                               s2 = 3; /* mov_membase_reg */
-                               CALCOFFSETBYTES(s2, s1, OFFSET(java_objectheader, vftbl));
-
-                               s2 += 3 + 4 /* movl_membase32_reg */ + 3 + 4 /* sub imm32 */ +
-                                       3 /* test */ + 6 /* jcc */ + 3 + 4 /* mov_membase32_reg */ +
-                                       3 /* test */ + 6 /* jcc */;
-
-                               if (super == NULL)
-                                       s2 += (opt_shownops ? 5 : 0);
-
-                               /* calculate class checkcast code size */
-
-                               s3 = 3; /* mov_membase_reg */
-                               CALCOFFSETBYTES(s3, s1, OFFSET(java_objectheader, vftbl));
-                               s3 += 10 /* mov_imm_reg */ + 3 + 4 /* movl_membase32_reg */;
-
-#if 0
-                               if (s1 != REG_ITMP1) {
-                                       a += 3;    /* movl_membase_reg - only if REG_ITMP3 == R11 */
-                                       CALCOFFSETBYTES(a, REG_ITMP3, OFFSET(vftbl_t, baseval));
-                                       a += 3;    /* movl_membase_reg - only if REG_ITMP3 == R11 */
-                                       CALCOFFSETBYTES(a, REG_ITMP3, OFFSET(vftbl_t, diffval));
-                                       a += 3;    /* sub */
-                               
-                               } else
-#endif
-                                       {
-                                               s3 += 3 + 4 /* movl_membase32_reg */ + 3 /* sub */ +
-                                                       10 /* mov_imm_reg */ + 3 /* movl_membase_reg */;
-                                               CALCOFFSETBYTES(s3, REG_ITMP3, OFFSET(vftbl_t, diffval));
-                                       }
-                       
-                               s3 += 3 /* cmp */ + 6 /* jcc */;
-
-                               if (super == NULL)
-                                       s3 += (opt_shownops ? 5 : 0);
-
                                /* if class is not resolved, check which code to call */
 
                                if (super == NULL) {
                                        M_TEST(s1);
-                                       M_BEQ(6 + (opt_shownops ? 5 : 0) + 7 + 6 + s2 + 5 + s3);
+                                       emit_label_beq(cd, BRANCH_LABEL_1);
 
                                        codegen_add_patch_ref(cd, PATCHER_checkcast_instanceof_flags,
                                                                                  iptr->sx.s23.s3.c.ref, 0);
 
                                        M_IMOV_IMM(0, REG_ITMP2);                 /* super->flags */
                                        M_IAND_IMM(ACC_INTERFACE, REG_ITMP2);
-                                       M_BEQ(s2 + 5);
+                                       emit_label_beq(cd, BRANCH_LABEL_2);
                                }
 
                                /* interface checkcast code */
@@ -2800,44 +2578,43 @@ gen_method:
                                if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
                                        if (super != NULL) {
                                                M_TEST(s1);
-                                               M_BEQ(s2);
+                                               emit_label_beq(cd, BRANCH_LABEL_3);
                                        }
 
                                        M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
 
                                        if (super == NULL) {
-                                               codegen_add_patch_ref(cd,
-                                                                                         PATCHER_checkcast_instanceof_interface,
+                                               codegen_add_patch_ref(cd, PATCHER_checkcast_interface,
                                                                                          iptr->sx.s23.s3.c.ref,
                                                                                          0);
                                        }
 
-                                       emit_movl_membase32_reg(cd, REG_ITMP2,
-                                                                                         OFFSET(vftbl_t, interfacetablelength),
-                                                                                         REG_ITMP3);
-                                       /* XXX TWISTI: should this be int arithmetic? */
-                                       M_LSUB_IMM32(superindex, REG_ITMP3);
-                                       M_TEST(REG_ITMP3);
-                                       M_BLE(0);
-                                       codegen_add_classcastexception_ref(cd, s1);
-                                       emit_mov_membase32_reg(cd, REG_ITMP2,
-                                                                                        OFFSET(vftbl_t, interfacetable[0]) -
-                                                                                        superindex * sizeof(methodptr*),
-                                                                                        REG_ITMP3);
+                                       M_ILD32(REG_ITMP3,
+                                                       REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
+                                       M_ICMP_IMM32(superindex, REG_ITMP3);
+                                       emit_classcast_check(cd, iptr, BRANCH_LE, REG_ITMP3, s1);
+
+                                       M_ALD32(REG_ITMP3, REG_ITMP2, 
+                                                       OFFSET(vftbl_t, interfacetable[0]) -
+                                                       superindex * sizeof(methodptr*));
                                        M_TEST(REG_ITMP3);
-                                       M_BEQ(0);
-                                       codegen_add_classcastexception_ref(cd, s1);
+                                       emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ITMP3, s1);
 
                                        if (super == NULL)
-                                               M_JMP_IMM(s3);
+                                               emit_label_br(cd, BRANCH_LABEL_4);
+                                       else
+                                               emit_label(cd, BRANCH_LABEL_3);
                                }
 
                                /* class checkcast code */
 
                                if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
-                                       if (super != NULL) {
+                                       if (super == NULL) {
+                                               emit_label(cd, BRANCH_LABEL_2);
+                                       }
+                                       else {
                                                M_TEST(s1);
-                                               M_BEQ(s3);
+                                               emit_label_beq(cd, BRANCH_LABEL_5);
                                        }
 
                                        M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
@@ -2852,9 +2629,8 @@ gen_method:
 #if defined(ENABLE_THREADS)
                                        codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
 #endif
-                                       emit_movl_membase32_reg(cd, REG_ITMP2,
-                                                                                         OFFSET(vftbl_t, baseval),
-                                                                                         REG_ITMP2);
+                                       M_ILD32(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
+
                                        /*                                      if (s1 != REG_ITMP1) { */
                                        /*                                              emit_movl_membase_reg(cd, REG_ITMP3, */
                                        /*                                                                                              OFFSET(vftbl_t, baseval), */
@@ -2868,19 +2644,25 @@ gen_method:
                                        /*                                              emit_alu_reg_reg(cd, ALU_SUB, REG_ITMP1, REG_ITMP2); */
 
                                        /*                                      } else { */
-                                       emit_movl_membase32_reg(cd, REG_ITMP3,
-                                                                                         OFFSET(vftbl_t, baseval),
-                                                                                         REG_ITMP3);
-                                       M_LSUB(REG_ITMP3, REG_ITMP2);
+
+                                       M_ILD32(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
+                                       M_ISUB(REG_ITMP3, REG_ITMP2);
                                        M_MOV_IMM(supervftbl, REG_ITMP3);
                                        M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
                                        /*                                      } */
 #if defined(ENABLE_THREADS)
                                        codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
 #endif
-                                       M_LCMP(REG_ITMP3, REG_ITMP2);
-                                       M_BA(0);         /* (u) REG_ITMP1 > (u) REG_ITMP2 -> jump */
-                                       codegen_add_classcastexception_ref(cd, s1);
+                                       M_ICMP(REG_ITMP3, REG_ITMP2);
+                                       emit_classcast_check(cd, iptr, BRANCH_UGT, REG_ITMP3, s1);
+
+                                       if (super != NULL)
+                                               emit_label(cd, BRANCH_LABEL_5);
+                               }
+
+                               if (super == NULL) {
+                                       emit_label(cd, BRANCH_LABEL_1);
+                                       emit_label(cd, BRANCH_LABEL_4);
                                }
 
                                d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
@@ -2903,8 +2685,7 @@ gen_method:
                                /* s1 may have been destroyed over the function call */
                                s1 = emit_load_s1(jd, iptr, REG_ITMP2);
                                M_TEST(REG_RESULT);
-                               M_BEQ(0);
-                               codegen_add_classcastexception_ref(cd, s1);
+                               emit_classcast_check(cd, iptr, BRANCH_EQ, REG_RESULT, s1);
 
                                d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
                        }
@@ -2915,33 +2696,18 @@ gen_method:
 
                case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult            */
 
-                                     /* val.a: (classinfo *) superclass              */
-
-                       /*  superclass is an interface:
-                        *      
-                        *  return (sub != NULL) &&
-                        *         (sub->vftbl->interfacetablelength > super->index) &&
-                        *         (sub->vftbl->interfacetable[-super->index] != NULL);
-                        *      
-                        *  superclass is a class:
-                        *      
-                        *  return ((sub != NULL) && (0
-                        *          <= (sub->vftbl->baseval - super->vftbl->baseval) <=
-                        *          super->vftbl->diffvall));
-                        */
-
                        {
                        classinfo *super;
                        vftbl_t   *supervftbl;
                        s4         superindex;
 
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
-                               super = NULL;
+                               super      = NULL;
                                superindex = 0;
                                supervftbl = NULL;
 
                        } else {
-                               super = iptr->sx.s23.s3.c.cls;
+                               super      = iptr->sx.s23.s3.c.cls;
                                superindex = super->index;
                                supervftbl = super->vftbl;
                        }
@@ -2952,131 +2718,108 @@ gen_method:
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+
                        if (s1 == d) {
                                M_INTMOVE(s1, REG_ITMP1);
                                s1 = REG_ITMP1;
                        }
 
-                       /* calculate interface instanceof code size */
-
-                       s2 = 3; /* mov_membase_reg */
-                       CALCOFFSETBYTES(s2, s1, OFFSET(java_objectheader, vftbl));
-                       s2 += 3 + 4 /* movl_membase32_reg */ + 3 + 4 /* sub_imm32 */ +
-                               3 /* test */ + 6 /* jcc */ + 3 + 4 /* mov_membase32_reg */ +
-                               3 /* test */ + 4 /* setcc */;
-
-                       if (!super)
-                               s2 += (opt_shownops ? 5 : 0);
-
-                       /* calculate class instanceof code size */
-                       
-                       s3 = 3; /* mov_membase_reg */
-                       CALCOFFSETBYTES(s3, s1, OFFSET(java_objectheader, vftbl));
-                       s3 += 10; /* mov_imm_reg */
-                       s3 += 2; /* movl_membase_reg - only if REG_ITMP1 == RAX */
-                       CALCOFFSETBYTES(s3, REG_ITMP1, OFFSET(vftbl_t, baseval));
-                       s3 += 3; /* movl_membase_reg - only if REG_ITMP2 == R10 */
-                       CALCOFFSETBYTES(s3, REG_ITMP2, OFFSET(vftbl_t, baseval));
-                       s3 += 3; /* movl_membase_reg - only if REG_ITMP2 == R10 */
-                       CALCOFFSETBYTES(s3, REG_ITMP2, OFFSET(vftbl_t, diffval));
-                       s3 += 3 /* sub */ + 3 /* xor */ + 3 /* cmp */ + 4 /* setcc */;
-
-                       if (super == NULL)
-                               s3 += (opt_shownops ? 5 : 0);
-
-                       emit_alu_reg_reg(cd, ALU_XOR, d, d);
+                       M_CLR(d);
 
                        /* if class is not resolved, check which code to call */
 
                        if (super == NULL) {
-                               emit_test_reg_reg(cd, s1, s1);
-                               emit_jcc(cd, CC_Z, (6 + (opt_shownops ? 5 : 0) +
-                                                                                        7 + 6 + s2 + 5 + s3));
+                               M_TEST(s1);
+                               emit_label_beq(cd, BRANCH_LABEL_1);
 
                                codegen_add_patch_ref(cd, PATCHER_checkcast_instanceof_flags,
                                                                          iptr->sx.s23.s3.c.ref, 0);
 
-                               emit_movl_imm_reg(cd, 0, REG_ITMP3); /* super->flags */
-                               emit_alul_imm_reg(cd, ALU_AND, ACC_INTERFACE, REG_ITMP3);
-                               emit_jcc(cd, CC_Z, s2 + 5);
+                               M_IMOV_IMM(0, REG_ITMP3);                     /* super->flags */
+                               M_IAND_IMM(ACC_INTERFACE, REG_ITMP3);
+                               emit_label_beq(cd, BRANCH_LABEL_2);
                        }
 
                        /* interface instanceof code */
 
                        if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
                                if (super != NULL) {
-                                       emit_test_reg_reg(cd, s1, s1);
-                                       emit_jcc(cd, CC_Z, s2);
+                                       M_TEST(s1);
+                                       emit_label_beq(cd, BRANCH_LABEL_3);
                                }
 
-                               emit_mov_membase_reg(cd, s1,
-                                                                        OFFSET(java_objectheader, vftbl),
-                                                                        REG_ITMP1);
+                               M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
 
                                if (super == NULL) {
-                                       codegen_add_patch_ref(cd,
-                                                                                 PATCHER_checkcast_instanceof_interface,
+                                       codegen_add_patch_ref(cd, PATCHER_instanceof_interface,
                                                                                  iptr->sx.s23.s3.c.ref, 0);
                                }
 
-                               emit_movl_membase32_reg(cd, REG_ITMP1,
-                                                                                 OFFSET(vftbl_t, interfacetablelength),
-                                                                                 REG_ITMP3);
-                               emit_alu_imm32_reg(cd, ALU_SUB, superindex, REG_ITMP3);
-                               emit_test_reg_reg(cd, REG_ITMP3, REG_ITMP3);
+                               M_ILD32(REG_ITMP3,
+                                               REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
+                               M_ICMP_IMM32(superindex, REG_ITMP3);
 
                                a = 3 + 4 /* mov_membase32_reg */ + 3 /* test */ + 4 /* setcc */;
 
-                               emit_jcc(cd, CC_LE, a);
-                               emit_mov_membase32_reg(cd, REG_ITMP1,
-                                                                                OFFSET(vftbl_t, interfacetable[0]) -
-                                                                                superindex * sizeof(methodptr*),
-                                                                                REG_ITMP1);
-                               emit_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
-                               emit_setcc_reg(cd, CC_NE, d);
+                               M_BLE(a);
+                               M_ALD32(REG_ITMP1, REG_ITMP1,
+                                               OFFSET(vftbl_t, interfacetable[0]) -
+                                               superindex * sizeof(methodptr*));
+                               M_TEST(REG_ITMP1);
+                               M_SETNE(d);
 
-                               if (!super)
-                                       emit_jmp_imm(cd, s3);
+                               if (super == NULL)
+                                       emit_label_br(cd, BRANCH_LABEL_4);
+                               else
+                                       emit_label(cd, BRANCH_LABEL_3);
                        }
 
                        /* class instanceof code */
 
                        if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
-                               if (super != NULL) {
-                                       emit_test_reg_reg(cd, s1, s1);
-                                       emit_jcc(cd, CC_E, s3);
+                               if (super == NULL) {
+                                       emit_label(cd, BRANCH_LABEL_2);
+                               }
+                               else {
+                                       M_TEST(s1);
+                                       emit_label_beq(cd, BRANCH_LABEL_5);
                                }
 
-                               emit_mov_membase_reg(cd, s1,
-                                                                          OFFSET(java_objectheader, vftbl),
-                                                                          REG_ITMP1);
+                               M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
 
                                if (super == NULL) {
                                        codegen_add_patch_ref(cd, PATCHER_instanceof_class,
                                                                                  iptr->sx.s23.s3.c.ref, 0);
                                }
 
-                               emit_mov_imm_reg(cd, (ptrint) supervftbl, REG_ITMP2);
+                               M_MOV_IMM(supervftbl, REG_ITMP2);
+
 #if defined(ENABLE_THREADS)
                                codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
 #endif
-                               emit_movl_membase_reg(cd, REG_ITMP1,
-                                                                               OFFSET(vftbl_t, baseval),
-                                                                               REG_ITMP1);
-                               emit_movl_membase_reg(cd, REG_ITMP2,
-                                                                               OFFSET(vftbl_t, diffval),
-                                                                               REG_ITMP3);
-                               emit_movl_membase_reg(cd, REG_ITMP2,
-                                                                               OFFSET(vftbl_t, baseval),
-                                                                               REG_ITMP2);
+
+                               M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
+                               M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, diffval));
+                               M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
+
 #if defined(ENABLE_THREADS)
                                codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
 #endif
-                               emit_alu_reg_reg(cd, ALU_SUB, REG_ITMP2, REG_ITMP1);
-                               emit_alu_reg_reg(cd, ALU_XOR, d, d); /* may be REG_ITMP2 */
-                               emit_alu_reg_reg(cd, ALU_CMP, REG_ITMP3, REG_ITMP1);
-                               emit_setcc_reg(cd, CC_BE, d);
+
+                               M_ISUB(REG_ITMP2, REG_ITMP1);
+                               M_CLR(d); /* may be REG_ITMP2 */
+                               M_ICMP(REG_ITMP3, REG_ITMP1);
+                               M_SETULE(d);
+
+                               if (super != NULL)
+                                       emit_label(cd, BRANCH_LABEL_5);
+                       }
+
+                       if (super == NULL) {
+                               emit_label(cd, BRANCH_LABEL_1);
+                               emit_label(cd, BRANCH_LABEL_4);
                        }
+
                        emit_store_dst(jd, iptr, d);
                        }
                        break;
@@ -3123,9 +2866,7 @@ gen_method:
 
                        /* check for exception before result assignment */
 
-                       M_TEST(REG_RESULT);
-                       M_BEQ(0);
-                       codegen_add_fillinstacktrace_ref(cd);
+                       emit_exception_check(cd, iptr);
 
                        s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
                        M_INTMOVE(REG_RESULT, s1);
@@ -3160,12 +2901,9 @@ gen_method:
 
        /* generate stubs */
 
-       emit_exception_stubs(jd);
        emit_patcher_stubs(jd);
        REPLACEMENT_EMIT_STUBS(jd);
 
-       codegen_finish(jd);
-
        /* everything's ok */
 
        return true;
index 8b9e96a310382e7b19ea96bb5001aa2a727cf7eb..a612e2b263e1466bef8c85f741ae854688851328 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: codegen.h 7281 2007-02-03 19:51:36Z twisti $
+   $Id: codegen.h 7590 2007-03-28 18:54:02Z twisti $
 
 */
 
 
 /* additional functions and macros to generate code ***************************/
 
-#define CALCOFFSETBYTES(var, reg, val) \
-    if ((s4) (val) < -128 || (s4) (val) > 127) (var) += 4; \
-    else if ((s4) (val) != 0) (var) += 1; \
-    else if ((reg) == RBP || (reg) == RSP || (reg) == R12 || (reg) == R13) (var) += 1;
-
-
-#define CALCIMMEDIATEBYTES(var, val) \
-    if ((s4) (val) < -128 || (s4) (val) > 127) (var) += 4; \
-    else (var) += 1;
-
-
 /* MCODECHECK(icnt) */
 
 #define MCODECHECK(icnt) \
 
 
 #define ALIGNCODENOP \
-    if ((s4) (((ptrint) cd->mcodeptr) & 7)) { \
-        M_NOP; \
-    }
+    do { \
+        for (s1 = 0; s1 < (s4) (((ptrint) cd->mcodeptr) & 7); s1++) \
+            M_NOP; \
+    } while (0)
 
 
 /* M_INTMOVE:
 
 /* branch defines *************************************************************/
 
+#define BRANCH_UNCONDITIONAL_SIZE    5  /* size in bytes of a branch          */
+#define BRANCH_CONDITIONAL_SIZE      6  /* size in bytes of a branch          */
+
 #define BRANCH_NOPS \
     do { \
         M_NOP; \
         M_NOP; \
         M_NOP; \
         M_NOP; \
+        M_NOP; \
     } while (0)
 
 
 #define M_ALD(a,b,disp)         M_LLD(a,b,disp)
 #define M_ALD32(a,b,disp)       M_LLD32(a,b,disp)
 
+#define M_ALD_MEM(a,disp)       emit_mov_mem_reg(cd, (disp), (a))
+
+#define M_ALD_MEM_GET_OPC(p)     (  *(        (p) + 1))
+#define M_ALD_MEM_GET_MOD(p)     (((*(        (p) + 2)) >> 6) & 0x03)
+#define M_ALD_MEM_GET_REG(p)    ((((*(        (p) + 2)) >> 3) & 0x07) + (((*(p) >> 2) & 0x01) << 3))
+#define M_ALD_MEM_GET_RM(p)      (((*(        (p) + 2))     ) & 0x07)
+#define M_ALD_MEM_GET_DISP(p)    (  *((u4 *) ((p) + 4)))
+
 #define M_AST(a,b,c)            M_LST(a,b,c)
 #define M_AST_IMM32(a,b,c)      M_LST_IMM32(a,b,c)
 
 #define M_AADD_IMM(a,b)         M_LADD_IMM(a,b)
 #define M_ASUB_IMM(a,b)         M_LSUB_IMM(a,b)
 
+#define M_ISUB_IMM32(a,b)       emit_alul_imm32_reg(cd, ALU_SUB, (a), (b))
+
 #define M_LADD_IMM32(a,b)       emit_alu_imm32_reg(cd, ALU_ADD, (a), (b))
-#define M_AADD_IMM32(a,b)       M_LADD_IMM32(a,b)
 #define M_LSUB_IMM32(a,b)       emit_alu_imm32_reg(cd, ALU_SUB, (a), (b))
 
+#define M_AADD_IMM32(a,b)       M_LADD_IMM32(a,b)
+
 #define M_ILEA(a,b,c)           emit_leal_membase_reg(cd, (a), (b), (c))
 #define M_LLEA(a,b,c)           emit_lea_membase_reg(cd, (a), (b), (c))
 #define M_ALEA(a,b,c)           M_LLEA(a,b,c)
 
 #define M_ICMP(a,b)             emit_alul_reg_reg(cd, ALU_CMP, (a), (b))
 #define M_ICMP_IMM(a,b)         emit_alul_imm_reg(cd, ALU_CMP, (a), (b))
+#define M_ICMP_IMM32(a,b)       emit_alul_imm32_reg(cd, ALU_CMP, (a), (b))
 #define M_ICMP_IMM_MEMBASE(a,b,c) emit_alul_imm_membase(cd, ALU_CMP, (a), (b), (c))
 #define M_ICMP_MEMBASE(a,b,c)   emit_alul_membase_reg(cd, ALU_CMP, (a), (b), (c))
 
 #define M_BLE(disp)             emit_jcc(cd, CC_LE, (disp))
 #define M_BGE(disp)             emit_jcc(cd, CC_GE, (disp))
 #define M_BGT(disp)             emit_jcc(cd, CC_G, (disp))
-#define M_BAE(disp)             emit_jcc(cd, CC_AE, (disp))
-#define M_BA(disp)              emit_jcc(cd, CC_A, (disp))
+
+#define M_BULT(disp)            emit_jcc(cd, CC_B, (disp))
+#define M_BULE(disp)            emit_jcc(cd, CC_BE, (disp))
+#define M_BUGE(disp)            emit_jcc(cd, CC_AE, (disp))
+#define M_BUGT(disp)            emit_jcc(cd, CC_A, (disp))
+
+#define M_SETNE(a)              emit_setcc_reg(cd, CC_NE, (a))
+#define M_SETULE(a)             emit_setcc_reg(cd, CC_BE, (a))
 
 #define M_CMOVEQ(a,b)           emit_cmovcc_reg_reg(cd, CC_E, (a), (b))
 #define M_CMOVNE(a,b)           emit_cmovcc_reg_reg(cd, CC_NE, (a), (b))
 #define M_CMOVGE(a,b)           emit_cmovcc_reg_reg(cd, CC_GE, (a), (b))
 #define M_CMOVGT(a,b)           emit_cmovcc_reg_reg(cd, CC_G, (a), (b))
 
-#define M_CMOVEQ_MEMBASE(a,b,c) emit_cmovcc_reg_membase(cd, CC_E, (a), (b))
-#define M_CMOVNE_MEMBASE(a,b,c) emit_cmovcc_reg_membase(cd, CC_NE, (a), (b))
-#define M_CMOVLT_MEMBASE(a,b,c) emit_cmovcc_reg_membase(cd, CC_L, (a), (b))
-#define M_CMOVLE_MEMBASE(a,b,c) emit_cmovcc_reg_membase(cd, CC_LE, (a), (b))
-#define M_CMOVGE_MEMBASE(a,b,c) emit_cmovcc_reg_membase(cd, CC_GE, (a), (b))
-#define M_CMOVGT_MEMBASE(a,b,c) emit_cmovcc_reg_membase(cd, CC_G, (a), (b))
-
-#define M_CMOVB(a,b)            emit_cmovcc_reg_reg(cd, CC_B, (a), (b))
-#define M_CMOVA(a,b)            emit_cmovcc_reg_reg(cd, CC_A, (a), (b))
+#define M_CMOVULT(a,b)          emit_cmovcc_reg_reg(cd, CC_B, (a), (b))
+#define M_CMOVUGT(a,b)          emit_cmovcc_reg_reg(cd, CC_A, (a), (b))
 #define M_CMOVP(a,b)            emit_cmovcc_reg_reg(cd, CC_P, (a), (b))
 
 #define M_PUSH(a)               emit_push_reg(cd, (a))
index 448d30dadb65e1bd98a3463be3d6bef0fb23c9ff..e926a19c3927af5ed716b56579cc9c455d10ae75 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: emit.c 7486 2007-03-08 13:50:07Z twisti $
+   $Id: emit.c 7590 2007-03-28 18:54:02Z twisti $
 
 */
 
@@ -44,6 +44,7 @@
 #endif
 
 #include "vm/builtin.h"
+#include "vm/exceptions.h"
 
 #include "vm/jit/abi-asm.h"
 #include "vm/jit/asmpart.h"
@@ -251,6 +252,71 @@ void emit_cmovxx(codegendata *cd, instruction *iptr, s4 s, s4 d)
 }
 
 
+/* emit_branch *****************************************************************
+
+   Emits the code for conditional and unconditional branchs.
+
+*******************************************************************************/
+
+void emit_branch(codegendata *cd, s4 disp, s4 condition, s4 reg, u4 options)
+{
+       s4 branchdisp;
+
+       /* NOTE: A displacement overflow cannot happen. */
+
+       /* check which branch to generate */
+
+       if (condition == BRANCH_UNCONDITIONAL) {
+
+               /* calculate the different displacements */
+
+               branchdisp = disp - BRANCH_UNCONDITIONAL_SIZE;
+
+               M_JMP_IMM(branchdisp);
+       }
+       else {
+               /* calculate the different displacements */
+
+               branchdisp = disp - BRANCH_CONDITIONAL_SIZE;
+
+               switch (condition) {
+               case BRANCH_EQ:
+                       M_BEQ(branchdisp);
+                       break;
+               case BRANCH_NE:
+                       M_BNE(branchdisp);
+                       break;
+               case BRANCH_LT:
+                       M_BLT(branchdisp);
+                       break;
+               case BRANCH_GE:
+                       M_BGE(branchdisp);
+                       break;
+               case BRANCH_GT:
+                       M_BGT(branchdisp);
+                       break;
+               case BRANCH_LE:
+                       M_BLE(branchdisp);
+                       break;
+               case BRANCH_ULT:
+                       M_BULT(branchdisp);
+                       break;
+               case BRANCH_ULE:
+                       M_BULE(branchdisp);
+                       break;
+               case BRANCH_UGE:
+                       M_BUGE(branchdisp);
+                       break;
+               case BRANCH_UGT:
+                       M_BUGT(branchdisp);
+                       break;
+               default:
+                       vm_abort("emit_branch: unknown condition %d", condition);
+               }
+       }
+}
+
+
 /* emit_arithmetic_check *******************************************************
 
    Emit an ArithmeticException check.
@@ -261,8 +327,8 @@ void emit_arithmetic_check(codegendata *cd, instruction *iptr, s4 reg)
 {
        if (INSTRUCTION_MUST_CHECK(iptr)) {
                M_TEST(reg);
-               M_BEQ(0);
-               codegen_add_arithmeticexception_ref(cd);
+               M_BNE(8);
+               M_ALD_MEM(reg, EXCEPTION_HARDWARE_ARITHMETIC);
        }
 }
 
@@ -278,8 +344,8 @@ void emit_arrayindexoutofbounds_check(codegendata *cd, instruction *iptr, s4 s1,
        if (INSTRUCTION_MUST_CHECK(iptr)) {
         M_ILD(REG_ITMP3, s1, OFFSET(java_arrayheader, size));
         M_ICMP(REG_ITMP3, s2);
-        M_BAE(0);
-        codegen_add_arrayindexoutofboundsexception_ref(cd, s2);
+               M_BULT(8);
+               M_ALD_MEM(s2, EXCEPTION_HARDWARE_ARRAYINDEXOUTOFBOUNDS);
        }
 }
 
@@ -292,7 +358,22 @@ void emit_arrayindexoutofbounds_check(codegendata *cd, instruction *iptr, s4 s1,
 
 void emit_classcast_check(codegendata *cd, instruction *iptr, s4 condition, s4 reg, s4 s1)
 {
-       vm_abort("IMPLEMENT ME!");
+       if (INSTRUCTION_MUST_CHECK(iptr)) {
+               switch (condition) {
+               case BRANCH_LE:
+                       M_BGT(8);
+                       break;
+               case BRANCH_EQ:
+                       M_BNE(8);
+                       break;
+               case BRANCH_UGT:
+                       M_BULE(8);
+                       break;
+               default:
+                       vm_abort("emit_classcast_check: unknown condition %d", condition);
+               }
+               M_ALD_MEM(s1, EXCEPTION_HARDWARE_CLASSCAST);
+       }
 }
 
 
@@ -306,85 +387,24 @@ void emit_nullpointer_check(codegendata *cd, instruction *iptr, s4 reg)
 {
        if (INSTRUCTION_MUST_CHECK(iptr)) {
                M_TEST(reg);
-               M_BEQ(0);
-               codegen_add_nullpointerexception_ref(cd);
+               M_BNE(8);
+               M_ALD_MEM(reg, EXCEPTION_HARDWARE_NULLPOINTER);
        }
 }
 
 
-/* emit_exception_stubs ********************************************************
+/* emit_exception_check ********************************************************
 
-   Generates the code for the exception stubs.
+   Emit an Exception check.
 
 *******************************************************************************/
 
-void emit_exception_stubs(jitdata *jd)
+void emit_exception_check(codegendata *cd, instruction *iptr)
 {
-       codegendata  *cd;
-       registerdata *rd;
-       exceptionref *er;
-       s4            branchmpc;
-       s4            targetmpc;
-       s4            targetdisp;
-
-       /* get required compiler data */
-
-       cd = jd->cd;
-       rd = jd->rd;
-
-       /* generate exception stubs */
-
-       targetdisp = 0;
-
-       for (er = cd->exceptionrefs; er != NULL; er = er->next) {
-               /* back-patch the branch to this exception code */
-
-               branchmpc = er->branchpos;
-               targetmpc = cd->mcodeptr - cd->mcodebase;
-
-               md_codegen_patch_branch(cd, branchmpc, targetmpc);
-
-               MCODECHECK(512);
-
-               /* Check if the exception is an
-                  ArrayIndexOutOfBoundsException.  If so, move index register
-                  into a4. */
-
-               if (er->reg != -1)
-                       M_MOV(er->reg, rd->argintregs[4]);
-
-               /* calcuate exception address */
-
-               M_MOV_IMM(0, rd->argintregs[3]);
-               dseg_adddata(cd);
-               M_AADD_IMM32(er->branchpos - 6, rd->argintregs[3]);
-
-               /* move function to call into REG_ITMP3 */
-
-               M_MOV_IMM(er->function, REG_ITMP3);
-
-               if (targetdisp == 0) {
-                       targetdisp = cd->mcodeptr - cd->mcodebase;
-
-                       emit_lea_membase_reg(cd, RIP, -((cd->mcodeptr + 7) - cd->mcodebase), rd->argintregs[0]);
-                       M_MOV(REG_SP, rd->argintregs[1]);
-                       M_ALD(rd->argintregs[2], REG_SP, cd->stackframesize * 8);
-
-                       M_ASUB_IMM(2 * 8, REG_SP);
-                       M_AST(rd->argintregs[3], REG_SP, 0 * 8);             /* store XPC */
-
-                       M_CALL(REG_ITMP3);
-
-                       M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
-                       M_AADD_IMM(2 * 8, REG_SP);
-
-                       M_MOV_IMM(asm_handle_exception, REG_ITMP3);
-                       M_JMP(REG_ITMP3);
-               }
-               else {
-                       M_JMP_IMM((cd->mcodebase + targetdisp) -
-                                         (cd->mcodeptr + PATCHER_CALL_SIZE));
-               }
+       if (INSTRUCTION_MUST_CHECK(iptr)) {
+               M_TEST(REG_RESULT);
+               M_BNE(8);
+               M_ALD_MEM(REG_RESULT, EXCEPTION_HARDWARE_EXCEPTION);
        }
 }
 
@@ -1290,6 +1310,15 @@ void emit_movb_imm_memindex(codegendata *cd, s4 imm, s4 disp, s4 basereg, s4 ind
 }
 
 
+void emit_mov_mem_reg(codegendata *cd, s4 disp, s4 dreg)
+{
+       emit_rex(1, dreg, 0, 0);
+       *(cd->mcodeptr++) = 0x8b;
+       emit_address_byte(0, dreg, 4);
+       emit_mem(4, disp);
+}
+
+
 /*
  * alu operations
  */
@@ -1356,7 +1385,8 @@ void emit_alu_imm_reg(codegendata *cd, s8 opc, s8 imm, s8 dreg) {
 }
 
 
-void emit_alu_imm32_reg(codegendata *cd, s8 opc, s8 imm, s8 dreg) {
+void emit_alu_imm32_reg(codegendata *cd, s4 opc, s4 imm, s4 dreg)
+{
        emit_rex(1,0,0,(dreg));
        *(cd->mcodeptr++) = 0x81;
        emit_reg((opc),(dreg));
@@ -1364,6 +1394,15 @@ void emit_alu_imm32_reg(codegendata *cd, s8 opc, s8 imm, s8 dreg) {
 }
 
 
+void emit_alul_imm32_reg(codegendata *cd, s4 opc, s4 imm, s4 dreg)
+{
+       emit_rex(0,0,0,(dreg));
+       *(cd->mcodeptr++) = 0x81;
+       emit_reg((opc),(dreg));
+       emit_imm32((imm));
+}
+
+
 void emit_alul_imm_reg(codegendata *cd, s8 opc, s8 imm, s8 dreg) {
        if (IS_IMM8(imm)) {
                emit_rex(0,0,0,(dreg));
@@ -1726,7 +1765,8 @@ void emit_jcc(codegendata *cd, s8 opc, s8 imm) {
  */
 
 /* we need the rex byte to get all low bytes */
-void emit_setcc_reg(codegendata *cd, s8 opc, s8 reg) {
+void emit_setcc_reg(codegendata *cd, s4 opc, s4 reg)
+{
        *(cd->mcodeptr++) = (0x40 | (((reg) >> 3) & 0x01));
        *(cd->mcodeptr++) = 0x0f;
        *(cd->mcodeptr++) = (0x90 + (opc));
@@ -1735,7 +1775,8 @@ void emit_setcc_reg(codegendata *cd, s8 opc, s8 reg) {
 
 
 /* we need the rex byte to get all low bytes */
-void emit_setcc_membase(codegendata *cd, s8 opc, s8 basereg, s8 disp) {
+void emit_setcc_membase(codegendata *cd, s4 opc, s4 basereg, s4 disp)
+{
        *(cd->mcodeptr++) = (0x40 | (((basereg) >> 3) & 0x01));
        *(cd->mcodeptr++) = 0x0f;
        *(cd->mcodeptr++) = (0x90 + (opc));
@@ -1743,7 +1784,7 @@ void emit_setcc_membase(codegendata *cd, s8 opc, s8 basereg, s8 disp) {
 }
 
 
-void emit_cmovcc_reg_reg(codegendata *cd, s8 opc, s8 reg, s8 dreg)
+void emit_cmovcc_reg_reg(codegendata *cd, s4 opc, s4 reg, s4 dreg)
 {
        emit_rex(1,(dreg),0,(reg));
        *(cd->mcodeptr++) = 0x0f;
@@ -1752,7 +1793,7 @@ void emit_cmovcc_reg_reg(codegendata *cd, s8 opc, s8 reg, s8 dreg)
 }
 
 
-void emit_cmovccl_reg_reg(codegendata *cd, s8 opc, s8 reg, s8 dreg)
+void emit_cmovccl_reg_reg(codegendata *cd, s4 opc, s4 reg, s4 dreg)
 {
        emit_rex(0,(dreg),0,(reg));
        *(cd->mcodeptr++) = 0x0f;
@@ -1761,7 +1802,6 @@ void emit_cmovccl_reg_reg(codegendata *cd, s8 opc, s8 reg, s8 dreg)
 }
 
 
-
 void emit_neg_reg(codegendata *cd, s8 reg)
 {
        emit_rex(1,0,0,(reg));
index ab92d410dc3caf18d7eca7d85a9c19d21cd2d076..e1d4727d8f75565bfbbff7555739fa7ada324b0a 100644 (file)
@@ -1,6 +1,6 @@
-/* src/vm/jit/x86_64/md-emit.h - machine dependent emit function prototypes
+/* src/vm/jit/x86_64/emit.h - machine dependent emit function prototypes
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
    J. Wenninger, Institut f. Computersprachen - TU Wien
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Christian Thalinger
-
-   Changes:
-
-   $Id: emit.h 6090 2006-11-29 20:40:10Z twisti $
+   $Id: emit.h 7590 2007-03-28 18:54:02Z twisti $
 
 */
 
@@ -236,6 +230,9 @@ void emit_mov_imm_memindex(codegendata *cd, s4 imm, s4 disp, s4 basereg, s4 inde
 void emit_movl_imm_memindex(codegendata *cd, s4 imm, s4 disp, s4 basereg, s4 indexreg, s4 scale);
 void emit_movw_imm_memindex(codegendata *cd, s4 imm, s4 disp, s4 basereg, s4 indexreg, s4 scale);
 void emit_movb_imm_memindex(codegendata *cd, s4 imm, s4 disp, s4 basereg, s4 indexreg, s4 scale);
+
+void emit_mov_mem_reg(codegendata *cd, s4 disp, s4 dreg);
+
 void emit_alu_reg_reg(codegendata *cd, s8 opc, s8 reg, s8 dreg);
 void emit_alul_reg_reg(codegendata *cd, s8 opc, s8 reg, s8 dreg);
 void emit_alu_reg_membase(codegendata *cd, s8 opc, s8 reg, s8 basereg, s8 disp);
@@ -243,7 +240,8 @@ void emit_alul_reg_membase(codegendata *cd, s8 opc, s8 reg, s8 basereg, s8 disp)
 void emit_alu_membase_reg(codegendata *cd, s8 opc, s8 basereg, s8 disp, s8 reg);
 void emit_alul_membase_reg(codegendata *cd, s8 opc, s8 basereg, s8 disp, s8 reg);
 void emit_alu_imm_reg(codegendata *cd, s8 opc, s8 imm, s8 dreg);
-void emit_alu_imm32_reg(codegendata *cd, s8 opc, s8 imm, s8 dreg);
+void emit_alu_imm32_reg(codegendata *cd, s4 opc, s4 imm, s4 dreg);
+void emit_alul_imm32_reg(codegendata *cd, s4 opc, s4 imm, s4 dreg);
 void emit_alul_imm_reg(codegendata *cd, s8 opc, s8 imm, s8 dreg);
 void emit_alu_imm_membase(codegendata *cd, s8 opc, s8 imm, s8 basereg, s8 disp);
 void emit_alul_imm_membase(codegendata *cd, s8 opc, s8 imm, s8 basereg, s8 disp);
@@ -282,10 +280,13 @@ void emit_shiftl_imm_membase(codegendata *cd, s8 opc, s8 imm, s8 basereg, s8 dis
 void emit_jmp_imm(codegendata *cd, s8 imm);
 void emit_jmp_reg(codegendata *cd, s8 reg);
 void emit_jcc(codegendata *cd, s8 opc, s8 imm);
-void emit_setcc_reg(codegendata *cd, s8 opc, s8 reg);
-void emit_setcc_membase(codegendata *cd, s8 opc, s8 basereg, s8 disp);
-void emit_cmovcc_reg_reg(codegendata *cd, s8 opc, s8 reg, s8 dreg);
-void emit_cmovccl_reg_reg(codegendata *cd, s8 opc, s8 reg, s8 dreg);
+
+void emit_setcc_reg(codegendata *cd, s4 opc, s4 reg);
+void emit_setcc_membase(codegendata *cd, s4 opc, s4 basereg, s4 disp);
+
+void emit_cmovcc_reg_reg(codegendata *cd, s4 opc, s4 reg, s4 dreg);
+void emit_cmovccl_reg_reg(codegendata *cd, s4 opc, s4 reg, s4 dreg);
+
 void emit_neg_reg(codegendata *cd, s8 reg);
 void emit_negl_reg(codegendata *cd, s8 reg);
 void emit_neg_membase(codegendata *cd, s8 basereg, s8 disp);
index 298c8586676ca654ec7401603a570c735c16cfd9..c8ec58b42ea59aa505851de338839cb9ff30be89 100644 (file)
 #include <stdlib.h>
 #include <ucontext.h>
 
+#include "vm/types.h"
+
+#include "vm/jit/x86_64/codegen.h"
+
 #if defined(ENABLE_THREADS)
 # include "threads/native/threads.h"
 #endif
 
+#include "vm/exceptions.h"
 #include "vm/signallocal.h"
 
 #include "vm/jit/asmpart.h"
 
 /* md_signal_handler_sigsegv ***************************************************
 
-   NullPointerException signal handler for hardware null pointer
-   check.
+   Signal handler for hardware exception.
 
 *******************************************************************************/
 
 void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
 {
-       ucontext_t *_uc;
-       mcontext_t *_mc;
-       u1         *sp;
-       u1         *ra;
-       u1         *xpc;
+       ucontext_t        *_uc;
+       mcontext_t        *_mc;
+       u1                *sp;
+       u1                *ra;
+       u1                *xpc;
+       u1                 opc;
+       u1                 mod;
+       u1                 rm;
+       s4                 d;
+       s4                 disp;
+       ptrint             val;
+       s4                 type;
+       java_objectheader *o;
 
        _uc = (ucontext_t *) _p;
        _mc = &_uc->uc_mcontext;
@@ -76,9 +88,82 @@ void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
        threads_check_stackoverflow(sp);
 #endif
 
-       _mc->gregs[REG_RAX] =
-               (ptrint) stacktrace_hardware_nullpointerexception(NULL, sp, ra, xpc);
-
+       /* get exception-throwing instruction */
+
+       opc = M_ALD_MEM_GET_OPC(xpc);
+       mod = M_ALD_MEM_GET_MOD(xpc);
+       rm  = M_ALD_MEM_GET_RM(xpc);
+
+       /* for values see emit_mov_mem_reg and emit_mem */
+
+       if ((opc == 0x8b) && (mod == 0) && (rm == 4)) {
+               /* this was a hardware-exception */
+
+               d    = M_ALD_MEM_GET_REG(xpc);
+               disp = M_ALD_MEM_GET_DISP(xpc);
+
+               /* we use the exception type as load displacement */
+
+               type = disp;
+
+               /* XXX FIX ME! */
+
+               /* ATTENTION: The _mc->gregs layout is even worse than on
+                  i386! See /usr/include/sys/ucontext.h.  We need a
+                  switch-case here... */
+
+               switch (d) {
+               case 0:  /* REG_RAX == 13 */
+                       d = REG_RAX;
+                       break;
+               case 1:  /* REG_RCX == 14 */
+                       d = REG_RCX;
+                       break;
+               case 2:  /* REG_RDX == 12 */
+                       d = REG_RDX;
+                       break;
+               case 3:  /* REG_RBX == 11 */
+                       d = REG_RBX;
+                       break;
+               case 4:  /* REG_RSP == 15 */
+                       d = REG_RSP;
+                       break;
+               case 5:  /* REG_RBP == 10 */
+                       d = REG_RBP;
+                       break;
+               case 6:  /* REG_RSI == 9  */
+                       d = REG_RSI;
+                       break;
+               case 7:  /* REG_RDI == 8  */
+                       d = REG_RDI;
+                       break;
+               case 8:  /* REG_R8  == 0  */
+               case 9:  /* REG_R9  == 1  */
+               case 10: /* REG_R10 == 2  */
+               case 11: /* REG_R11 == 3  */
+               case 12: /* REG_R12 == 4  */
+               case 13: /* REG_R13 == 5  */
+               case 14: /* REG_R14 == 6  */
+               case 15: /* REG_R15 == 7  */
+                       d = d - 8;
+                       break;
+               }
+
+               val = _mc->gregs[d];
+       }
+       else {
+               /* this was a normal NPE */
+
+               type = EXCEPTION_HARDWARE_NULLPOINTER;
+       }
+
+       /* generate appropriate exception */
+
+       o = exceptions_new_hardware_exception(NULL, sp, ra, xpc, type, val);
+
+       /* set registers */
+
+       _mc->gregs[REG_RAX] = (ptrint) o;
        _mc->gregs[REG_R10] = (ptrint) xpc;                      /* REG_ITMP2_XPC */
        _mc->gregs[REG_RIP] = (ptrint) asm_handle_exception;
 }
index 816a5c8bc24e8469f3220ce858f2efb45b36ece1..3abd268f8987e9f7e4fe695d922f3eb9b2a454c0 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: md.c 7486 2007-03-08 13:50:07Z twisti $
+   $Id: md.c 7590 2007-03-28 18:54:02Z twisti $
 
 */
 
@@ -60,34 +60,6 @@ void md_init(void)
 }
 
 
-/* md_codegen_patch_branch *****************************************************
-
-   Back-patches a branch instruction.
-
-*******************************************************************************/
-
-void md_codegen_patch_branch(codegendata *cd, s4 branchmpc, s4 targetmpc)
-{
-       s4 *mcodeptr;
-       s4  disp;                           /* branch displacement                */
-
-       /* calculate the patch position */
-
-       mcodeptr = (s4 *) (cd->mcodebase + branchmpc);
-
-       /* Calculate the branch displacement. */
-
-       disp = targetmpc - branchmpc;
-
-       /* I don't think we have to check for branch-displacement
-          overflow.  +/-2GB should be enough. */
-
-       /* patch the branch instruction before the mcodeptr */
-
-       mcodeptr[-1] = disp;
-}
-
-
 /* md_stacktrace_get_returnaddress *********************************************
 
    Returns the return address of the current stackframe, specified by
index a4c54135a146e9800be37bb9efa5f95a763c3865..ef812b982cd2936121450e8ce45ff876d12c3d5a 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: patcher.c 7486 2007-03-08 13:50:07Z twisti $
+   $Id: patcher.c 7590 2007-03-28 18:54:02Z twisti $
 
 */
 
@@ -483,7 +483,7 @@ bool patcher_invokestatic_special(u1 *sp)
        /* if we show disassembly, we have to skip the nop's */
 
        if (opt_shownops)
-               ra = ra + 5;
+               ra = ra + PATCHER_CALL_SIZE;
 
        /* patch stubroutine */
 
@@ -640,20 +640,20 @@ bool patcher_checkcast_instanceof_flags(u1 *sp)
 }
 
 
-/* patcher_checkcast_instanceof_interface **************************************
+/* patcher_checkcast_interface *************************************************
 
    Machine code:
 
    <patched call position>
    45 8b 9a 1c 00 00 00             mov    0x1c(%r10),%r11d
-   49 81 eb 00 00 00 00             sub    $0x0,%r11
-   4d 85 db                         test   %r11,%r11
-   0f 8e 94 04 00 00                jle    0x00002aaaaab018f8
+   41 81 fb 00 00 00 00             cmp    $0x0,%r11d
+   0f 8f 08 00 00 00                jg     0x00002aaaaae511d5
+   48 8b 0c 25 03 00 00 00          mov    0x3,%rcx
    4d 8b 9a 00 00 00 00             mov    0x0(%r10),%r11
 
 *******************************************************************************/
 
-bool patcher_checkcast_instanceof_interface(u1 *sp)
+bool patcher_checkcast_interface(u1 *sp)
 {
        u1                *ra;
        u8                 mcode;
@@ -678,13 +678,13 @@ bool patcher_checkcast_instanceof_interface(u1 *sp)
        /* if we show disassembly, we have to skip the nop's */
 
        if (opt_shownops)
-               ra = ra + 5;
+               ra = ra + PATCHER_CALL_SIZE;
 
        /* patch super class index */
 
        *((s4 *) (ra + 7 + 3)) = (s4) c->index;
 
-       *((s4 *) (ra + 7 + 7 + 3 + 6 + 3)) =
+       *((s4 *) (ra + 7 + 7 + 6 + 8 + 3)) =
                (s4) (OFFSET(vftbl_t, interfacetable[0]) -
                          c->index * sizeof(methodptr*));
 
@@ -741,6 +741,57 @@ bool patcher_checkcast_class(u1 *sp)
 }
 
 
+/* patcher_instanceof_interface ************************************************
+
+   Machine code:
+
+   <patched call position>
+   45 8b 9a 1c 00 00 00             mov    0x1c(%r10),%r11d
+   41 81 fb 00 00 00 00             cmp    $0x0,%r11d
+   0f 8e 94 04 00 00                jle    0x00002aaaaab018f8
+   4d 8b 9a 00 00 00 00             mov    0x0(%r10),%r11
+
+*******************************************************************************/
+
+bool patcher_instanceof_interface(u1 *sp)
+{
+       u1                *ra;
+       u8                 mcode;
+       constant_classref *cr;
+       classinfo         *c;
+
+       /* get stuff from the stack */
+
+       ra    = (u1 *)                *((ptrint *) (sp + 5 * 8));
+       mcode =                       *((u8 *)     (sp + 3 * 8));
+       cr    = (constant_classref *) *((ptrint *) (sp + 2 * 8));
+
+       /* get the fieldinfo */
+
+       if (!(c = resolve_classref_eager(cr)))
+               return false;
+
+       /* patch back original code */
+
+       *((u8 *) ra) = mcode;
+
+       /* if we show disassembly, we have to skip the nop's */
+
+       if (opt_shownops)
+               ra = ra + PATCHER_CALL_SIZE;
+
+       /* patch super class index */
+
+       *((s4 *) (ra + 7 + 3)) = (s4) c->index;
+
+       *((s4 *) (ra + 7 + 7 + 6 + 3)) =
+               (s4) (OFFSET(vftbl_t, interfacetable[0]) -
+                         c->index * sizeof(methodptr*));
+
+       return true;
+}
+
+
 /* patcher_instanceof_class ****************************************************
 
    Machine code:
index 40a4a436b54052411e140a4460f474f0e6a8b475..f9cc702ec2b8d950736ee0c76189ce43ccef4f7d 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: signal.c 7471 2007-03-06 17:01:49Z twisti $
+   $Id: signal.c 7592 2007-03-28 20:12:33Z twisti $
 
 */
 
@@ -128,21 +128,39 @@ void signal_init(void)
                act.sa_sigaction = md_signal_handler_sigsegv;
                act.sa_flags     = SA_NODEFER | SA_SIGINFO;
 
-#if defined(SIGSEGV)
+#  if defined(SIGSEGV)
                sigaction(SIGSEGV, &act, NULL);
-#endif
+#  endif
 
-#if defined(SIGBUS)
+#  if defined(SIGBUS)
                sigaction(SIGBUS, &act, NULL);
-#endif
+#  endif
 
-#if SUPPORT_HARDWARE_DIVIDE_BY_ZERO
+#  if SUPPORT_HARDWARE_DIVIDE_BY_ZERO
                /* SIGFPE handler */
 
                act.sa_sigaction = md_signal_handler_sigfpe;
                act.sa_flags     = SA_NODEFER | SA_SIGINFO;
                sigaction(SIGFPE, &act, NULL);
-#endif
+#  endif
+
+#  if defined(__ARM__)
+               /* XXX use better defines for that (in arch.h) */
+               /* SIGILL handler */
+
+               act.sa_sigaction = md_signal_handler_sigill;
+               act.sa_flags     = SA_NODEFER | SA_SIGINFO;
+               sigaction(SIGILL, &act, NULL);
+#  endif
+
+#  if defined(__POWERPC__)
+               /* XXX use better defines for that (in arch.h) */
+               /* SIGTRAP handler */
+
+               act.sa_sigaction = md_signal_handler_sigtrap;
+               act.sa_flags     = SA_NODEFER | SA_SIGINFO;
+               sigaction(SIGTRAP, &act, NULL);
+#  endif
 # if defined(ENABLE_INTRP)
        }
 # endif
index 9cb02fbee3c19efd0257ac7ba2d42fc2c3c3be18..034ec23057177e26d1d22a57e3bf9ac747134686 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: signallocal.h 7286 2007-02-05 01:07:45Z twisti $
+   $Id: signallocal.h 7592 2007-03-28 20:12:33Z twisti $
 
 */
 
@@ -52,6 +52,16 @@ void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p);
 void md_signal_handler_sigfpe(int sig, siginfo_t *siginfo, void *_p);
 #endif
 
+#if defined(__ARM__)
+/* XXX use better defines for that (in arch.h) */
+void md_signal_handler_sigill(int sig, siginfo_t *siginfo, void *_p);
+#endif
+
+#if defined(__POWERPC__)
+/* XXX use better defines for that (in arch.h) */
+void md_signal_handler_sigtrap(int sig, siginfo_t *siginfo, void *_p);
+#endif
+
 void md_signal_handler_sigusr2(int sig, siginfo_t *siginfo, void *_p);
 
 #endif /* _CACAO_SIGNAL_H */
index e169b9b1e41e0d18209b586b7324482d215d61a0..362e2fd04f38e6c08e7412969f3e383ec0906ad4 100644 (file)
@@ -175,7 +175,6 @@ enum {
 
        OPT_VERBOSE1,
        OPT_NOIEEE,
-       OPT_SOFTNULL,
 
 #if defined(ENABLE_STATISTICS)
        OPT_TIME,
@@ -298,7 +297,6 @@ opt_struct opts[] = {
 #if defined(__ALPHA__)
        { "noieee",            false, OPT_NOIEEE },
 #endif
-       { "softnull",          false, OPT_SOFTNULL },
 #if defined(ENABLE_STATISTICS)
        { "time",              false, OPT_TIME },
        { "stat",              false, OPT_STAT },
@@ -500,7 +498,6 @@ static void XXusage(void)
 #if defined(ENABLE_VERIFIER)
        puts("    -noverify                don't verify classfiles");
 #endif
-       puts("    -softnull                use software nullpointer check");
 #if defined(ENABLE_STATISTICS)
        puts("    -time                    measure the runtime");
        puts("    -stat                    detailed compiler statistics");
@@ -889,7 +886,6 @@ bool vm_create(JavaVMInitArgs *vm_args)
        opt_version       = false;
        opt_exit          = false;
 
-       checknull         = false;
        opt_noieee        = false;
 
        opt_heapmaxsize   = HEAP_MAXSIZE;
@@ -1152,10 +1148,6 @@ bool vm_create(JavaVMInitArgs *vm_args)
                        break;
 #endif
 
-               case OPT_SOFTNULL:
-                       checknull = true;
-                       break;
-
 #if defined(ENABLE_STATISTICS)
                case OPT_TIME:
                        opt_getcompilingtime = true;
index 294429cf8c1bc144c0c912d7c521e237fd43b786..2b7893232620b515af7b17a94e4a35bea4dd2b15 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: descriptor.h 7329 2007-02-11 21:24:14Z twisti $
+   $Id: descriptor.h 7456 2007-03-05 16:13:11Z tbfg $
 
 */
 
@@ -50,6 +50,7 @@ typedef struct methoddesc      methoddesc;
 #include "vmcore/references.h"
 #include "vmcore/utf8.h"
 
+#include "arch.h"              /* needed for HAS_ADDRESS_REGISTER_FILE */
 
 /* data structures ************************************************************/
 
@@ -123,6 +124,9 @@ struct methoddesc {
        s2         paramslots;      /* like above but LONG,DOUBLE count twice     */
        s4         argintreguse;    /* number of used integer argument registers  */
        s4         argfltreguse;    /* number of used float argument registers    */
+#if defined(HAS_ADDRESS_REGISTER_FILE)
+       s4         argadrreguse;    /* number of used address registers */
+#endif
        s4         memuse;          /* number of stack slots used                 */
        paramdesc *params;          /* allocated parameter descriptions [3]       */
        typedesc   returntype;      /* parsed descriptor of the return type       */
index e47f68e444eca7c22c6f3d7a00d91605ffe58cee..fff24eed85c2a645a5ddc637a278a813b62bf938 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: loader.c 7575 2007-03-25 20:30:50Z twisti $
+   $Id: loader.c 7577 2007-03-25 20:55:06Z twisti $
 
 */
 
@@ -1972,6 +1972,7 @@ classinfo *load_class_from_classbuffer(classbuffer *cb)
        /* this class */
 
        i = suck_u2(cb);
+
        if (!(name = (utf *) class_getconstant(c, i, CONSTANT_Class)))
                goto return_exception;
 
@@ -1979,35 +1980,16 @@ classinfo *load_class_from_classbuffer(classbuffer *cb)
                /* we finally have a name for this class */
                c->name = name;
                class_set_packagename(c);
-
-       } else if (name != c->name) {
-               /* TODO: i want to be an exceptions-function! */
-               char *msg;
-               s4    msglen;
-
-               msglen = utf_bytes(c->name) + strlen(" (wrong name: ") +
-                       utf_bytes(name) + strlen(")") + strlen("0");
-
-               msg = MNEW(char, msglen);
-
-               utf_copy_classname(msg, c->name);
-               strcat(msg, " (wrong name: ");
-               utf_cat_classname(msg, name);
-               strcat(msg, ")");
-
-#warning FIX ME!
-/*             *exceptionptr = */
-/*                     new_exception_message("java/lang/NoClassDefFoundError", msg); */
-               exceptions_throw_noclassdeffounderror(c->name);
-
-               MFREE(msg, char, msglen);
-
+       }
+       else if (name != c->name) {
+               exceptions_throw_noclassdeffounderror_wrong_name(c, name);
                goto return_exception;
        }
 
        /* retrieve superclass */
 
        c->super.any = NULL;
+
        if ((i = suck_u2(cb))) {
                if (!(supername = (utf *) class_getconstant(c, i, CONSTANT_Class)))
                        goto return_exception;
index 1bc4a9b9190b6a580ae7fdad614b3831aa9dafac..db1edf6be0b563bb956d3fd7f82a5ce2b0fc38e7 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: options.c 7450 2007-03-04 19:13:29Z edwin $
+   $Id: options.c 7585 2007-03-28 01:24:56Z twisti $
 
 */
 
@@ -95,7 +95,6 @@ bool opt_showexceptionstubs = false;
 bool opt_shownativestub     = false;
 
 bool checkbounds = true;       /* check array bounds                         */
-bool checknull = true;         /* check null pointers                        */
 bool opt_noieee = false;       /* don't implement ieee compliant floats      */
 bool checksync = true;         /* do synchronization                         */
 #if defined(ENABLE_LOOP)
index 37210caed291df49a1c4d4a687a77ac0264a699e..e8d7b5a34a6167b8d8dbc89530f4222f132296d9 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: options.h 7450 2007-03-04 19:13:29Z edwin $
+   $Id: options.h 7585 2007-03-28 01:24:56Z twisti $
 
 */
 
@@ -107,7 +107,6 @@ extern bool opt_showexceptionstubs;
 extern bool opt_shownativestub;
 
 extern bool checkbounds;
-extern bool checknull;
 extern bool opt_noieee;
 extern bool checksync;
 #if defined(ENABLE_LOOP)
index 90768984c56cf50bf3fdbf76d3008a1b67be1387..6e56d06f3a0c746dbc688d66ff7c9fd3ea4a769f 100644 (file)
@@ -26,7 +26,7 @@
 ##
 ## Authors: Christian Thalinger
 ##
-## $Id: Makefile.am 6257 2006-12-28 13:43:06Z twisti $
+## $Id: Makefile.am 7360 2007-02-14 17:50:48Z tbfg $
 
 ## Process this file with automake to produce Makefile.in
 
@@ -40,7 +40,7 @@ else
 JAVAFLAGS = -Xbootclasspath:$(CLASSPATH_CLASSES)
 endif
 
-JAVAH     = $(top_builddir)/src/cacaoh/cacaoh
+JAVAH     = @CACAOH@
 
 SOURCE_FILES = \
        checkjni.java \