From: michi Date: Wed, 28 Mar 2007 23:02:50 +0000 (+0000) Subject: Merged revisions 7501-7598 via svnmerge from X-Git-Url: http://wien.tomnetworks.com/gitweb/?p=cacao.git;a=commitdiff_plain;h=6fd72f4d63f219c79b2132dde9ec0aa5e6c1494b Merged revisions 7501-7598 via svnmerge from svn+ssh://michi@c1.complang.tuwien.ac.at/ahome/cacao/svn/cacao/trunk ........ r7503 | twisti | 2007-03-12 11:11:33 +0100 (Mon, 12 Mar 2007) | 11 lines * src/native/vm/cldc1.1/com_sun_cldc_io_ResourceInputStream.c (vm/vm.h): Added. (open): Call vm_abort. * src/native/vm/cldc1.1/com_sun_cldc_io_j2me_socket_Protocol.c (unistd.h): Added. (readByte): New function. (writeBuf): Likewise. (available0): Likewise. (close0): Likewise. ........ r7504 | twisti | 2007-03-12 14:17:07 +0100 (Mon, 12 Mar 2007) | 2 lines * src/vm/jit/arm/md.c (vm/jit/codegen-common.h): Added. ........ r7505 | twisti | 2007-03-12 14:34:37 +0100 (Mon, 12 Mar 2007) | 8 lines * src/vm/jit/codegen.c (codegen): Change the operand direction of some macros. Started to implement long-compares differently. * src/vm/jit/codegen.h (M_AND, M_ORR, M_EOR, M_AND_IMM, M_MOVEQ) (M_MOVVS_IMM, M_MOVNE_IMM, M_MOVLT_IMM, M_MOVLS_IMM): Changed operand direction. (M_ORR_S, M_CMPEQ, M_CMPLE): New macro. ........ r7510 | michi | 2007-03-13 14:19:07 +0100 (Tue, 13 Mar 2007) | 2 lines * src/vm/jit/arm/linux/Makefile.am: Fixed include path to care about builddir. ........ r7511 | michi | 2007-03-13 17:32:56 +0100 (Tue, 13 Mar 2007) | 6 lines * src/vm/jit/arm/codegen.c (codegen): Long branches are implemented differently now. * src/vm/jit/arm/codegen.h (M_COMPARE): Easier macros without overjumps. (M_MOVEQ_IMM, M_MOVGT_IMM, M_ADDHI_IMM, M_SUBLO_IMM, M_CMPEQ_IMM): New macro. ........ r7513 | twisti | 2007-03-13 21:31:23 +0100 (Tue, 13 Mar 2007) | 2 lines * src/vm/jit/i386/codegen.c (codegen): Fixed compiler warning. ........ r7514 | twisti | 2007-03-13 21:31:51 +0100 (Tue, 13 Mar 2007) | 5 lines * src/vm/jit/i386/emit.c (emit_load): Use switch-case instead of if-else contruct. (emit_store): Likewise. (emit_copy): Likewise. ........ r7516 | michi | 2007-03-14 13:00:07 +0100 (Wed, 14 Mar 2007) | 2 lines * src/mm/nogc.c: Fixed includes and exceptions. ........ r7518 | michi | 2007-03-14 17:44:05 +0100 (Wed, 14 Mar 2007) | 3 lines * src/vm/jit/arm/emit.c (emit_verbosecall_enter): Fixed bug with inmemory arguments, which caused some crashes with verbose-calls. ........ r7519 | michi | 2007-03-14 18:31:05 +0100 (Wed, 14 Mar 2007) | 3 lines * src/vm/jit/arm/codegen.c (codegen): All the long compares have a different implementation now. ........ r7520 | twisti | 2007-03-14 22:16:04 +0100 (Wed, 14 Mar 2007) | 2 lines * src/vm/jit/alpha/md.c (vm/jit/codegen-common.h): Added temporarily. ........ r7521 | twisti | 2007-03-14 22:18:00 +0100 (Wed, 14 Mar 2007) | 5 lines * src/vm/jit/alpha/emit.c (emit_load): Use switch-case instead of if-else contruct. (emit_store): Likewise. (emit_copy): Likewise. ........ r7522 | twisti | 2007-03-14 22:54:49 +0100 (Wed, 14 Mar 2007) | 7 lines * src/vmcore/statistics.c (size_string): Added. (statistics_print_memory_usage): Likewise. * src/vmcore/statistics.h (size_string): Likewise. * src/vm/string.c (vmcore/statistics.h): Added. (literalstring_u2): Added statistics. ........ r7524 | pm | 2007-03-15 08:07:51 +0100 (Thu, 15 Mar 2007) | 7 lines * src/vm/jit/s390/codegen.c, src/vm/jit/s390/codegen.h: Changed a lot. * src/vm/jit/s390/tests, src/vm/jit/s390/tests/tests.java.pp, src/vm/jit/s390/tests/Makefile: Added opcode tests in java. ........ r7525 | pm | 2007-03-15 09:23:19 +0100 (Thu, 15 Mar 2007) | 2 lines * src/vm/jit/s390/tests/tests.java.pp: added INT2CHAR test testing negative values. ........ r7526 | twisti | 2007-03-15 10:28:56 +0100 (Thu, 15 Mar 2007) | 3 lines * src/native/jni.c (_Jv_jni_invokeNative): Release memory in exception case. ........ r7534 | pm | 2007-03-17 00:00:18 +0100 (Sat, 17 Mar 2007) | 11 lines * src/vm/exceptions.c (exceptions_handle_exception): 31 bit address comparison for S390. These address comparison macros need to be moved to some header. * src/vm/jit/s390/emit.c, src/vm/jit/s390/md.c, src/vm/jit/s390/codegen.c, src/vm/jit/s390/codegen.h, src/vm/jit/s390/arch.h, src/vm/jit/s390/patcher.c, src/vm/jit/s390/md-abi.c, src/vm/jit/s390/tests/tests.java.pp, src/vm/jit/s390/tests/Makefile: Changed a lot. ........ r7535 | twisti | 2007-03-17 13:57:32 +0100 (Sat, 17 Mar 2007) | 2 lines * src/vm/builtin.c (builtin_isanysubclass): Cleanup and comments. ........ r7536 | twisti | 2007-03-17 14:10:04 +0100 (Sat, 17 Mar 2007) | 2 lines * src/native/vm/gnu/java_lang_reflect_Method.c (vm/resolve.h): Added. ........ r7537 | twisti | 2007-03-17 14:11:11 +0100 (Sat, 17 Mar 2007) | 3 lines * src/vm/builtin.c (builtin_isanysubclass): Code cleanup. (builtin_isanysubclass_vftbl): Likewise. ........ r7538 | twisti | 2007-03-17 14:12:00 +0100 (Sat, 17 Mar 2007) | 3 lines * src/vm/builtin.h (builtin_isanysubclass_vftbl): Removed, made static. ........ r7543 | ajordan | 2007-03-20 01:25:19 +0100 (Tue, 20 Mar 2007) | 3 lines * src/vm/jit/sparc64/md-abi.c (md_param_alloc_native): using this for native param allocation. No need for my own version of this anymore. * src/vm/jit/sparc64/codegen.c: Likewise. ........ r7547 | twisti | 2007-03-21 14:18:20 +0100 (Wed, 21 Mar 2007) | 4 lines * src/vmcore/linker.c (link_primitivetype_table): Set super class explicitly to NULL. (linker_compute_subclasses): Indent. ........ r7548 | twisti | 2007-03-21 14:19:44 +0100 (Wed, 21 Mar 2007) | 3 lines * src/vmcore/zip.c (zip_get): Don't assign in if-statement, this makes debugging a bit easier. ........ r7549 | twisti | 2007-03-21 14:27:14 +0100 (Wed, 21 Mar 2007) | 22 lines * src/vmcore/statistics.c (size_threadobject, size_lock_hashtable) (size_lock_waiter): Added. (statistics_print_memory_usage): Print new variables. * src/vmcore/statistics.h (size_threadobject, size_lock_hashtable) (size_lock_waiter): Added. * src/threads/native/lock.c (vmcore/options.h): Added. [ENABLE_STATISTICS] (vmcore/statistics.h): Added. (lock_hashtable_init): Added statistics. (lock_hashtable_grow): Likewise. (lock_record_add_waiter): Likewise. (lock_record_remove_waiter): Likewise. * src/threads/native/threads.c [ENABLE_STATISTICS] (vmcore/statistics.h): Added. (threads_preinit): Added statistics. (threads_init): Likewise. (threads_start_javathread): Likewise. (threads_attach_current_thread): Likewise. (threads_detach_thread): Likewise. ........ r7551 | twisti | 2007-03-21 15:26:09 +0100 (Wed, 21 Mar 2007) | 8 lines * src/vmcore/statistics.c (size_lock_record_pool): Added. (statistics_print_memory_usage): Print new variable. * src/vmcore/statistics.h (size_lock_record_pool): Added. * src/threads/native/lock.c (lock_record_alloc_new_pool): Added statistics. ........ r7554 | michi | 2007-03-22 14:55:44 +0100 (Thu, 22 Mar 2007) | 3 lines * src/vm/jit/arm/codegen.c (codegen) [!ENABLE_SOFTFLOAT]: Fixed position of soft null pointer checks in PUTFIELD and GETFIELD. ........ r7559 | twisti | 2007-03-23 12:56:31 +0100 (Fri, 23 Mar 2007) | 5 lines * src/vm/jit/powerpc/emit.c (emit_load): Use switch-case instead of if-else contruct. (emit_store): Likewise. (emit_copy): Likewise. ........ r7560 | twisti | 2007-03-23 19:51:41 +0100 (Fri, 23 Mar 2007) | 4 lines * src/vmcore/classcache.c (classcache_add_constraint) [CLASSCACHE_VERBOSE]: Started to use log-functions. (classcache_debug_dump): Likewise. ........ r7561 | twisti | 2007-03-23 20:10:35 +0100 (Fri, 23 Mar 2007) | 7 lines * src/vm/global.h (ACC_CLASS_PRIMITIVE): Defined. * src/vm/builtin.c (builtin_isanysubclass): Check for primitive classes. * src/vmcore/linker.c (link_primitivetype_table): Set primitive flag. ........ r7562 | twisti | 2007-03-23 21:38:14 +0100 (Fri, 23 Mar 2007) | 4 lines * src/vm/builtin.c (builtin_isanysubclass_vftbl): Removed. (builtin_descriptorscompatible): Use builtin_isanysubclass instead of builtin_isanysubclass_vftbl. ........ r7563 | twisti | 2007-03-23 22:33:53 +0100 (Fri, 23 Mar 2007) | 22 lines * src/vm/builtin.c (builtin_isanysubclass): Removed. (builtin_instanceof): Replaced builtin_isanysubclass with class_isanysubclass. (builtin_descriptorscompatible): Likewise. * src/vm/builtin.h (builtin_isanysubclass): Removed. * src/vm/access.c (access_is_accessible_member): Replaced builtin_isanysubclass with class_isanysubclass. * src/native/vm/java_lang_Class.c (isAssignableFrom): Likewise. * src/vm/jit/asmpart.h (castinfo): Removed. * src/vmcore/class.c (vm/jit/asmpart.h): Added. (class_isanysubclass): New function. * src/vmcore/class.h (castinfo): Added. (class_isanysubclass): Likewise. * src/cacaoh/dummy.c (asm_getclassvalues_atomic): New function. (intrp_asm_getclassvalues_atomic): Likewise. ........ r7573 | twisti | 2007-03-25 20:55:02 +0200 (Sun, 25 Mar 2007) | 21 lines * src/native/native.c (native_get_parametertypes): Removed. (native_get_exceptiontypes): Likewise. * src/native/native.h: Likewise. * src/vmcore/method.c (vm/builtin.h): Added. (vm/resolve.h): Likewise. (method_get_parametertypearray): New function. (method_get_exceptionarray): Likewise. * src/vmcore/method.h (method_get_parametertypearray): Added. (method_get_exceptionarray): Likewise. * src/cacaoh/dummy.c (builtin_anewarray): Added. (resolve_class_from_typedesc): Likewise. * src/native/vm/gnu/java_lang_reflect_Method.c (getParameterTypes): Use method function. (getExceptionTypes): Likewise. * src/native/vm/gnu/java_lang_reflect_Constructor.c (getParameterTypes): Likewise. (getExceptionTypes): Likewise. ........ r7575 | twisti | 2007-03-25 22:30:50 +0200 (Sun, 25 Mar 2007) | 9 lines Reverted patch 7268. * src/vm/jit/code.c: Reverted. * src/vm/jit/code.h: Likewise. * src/vm/jit/jit.c: Likewise. * src/vm/jit/jit.h: Likewise. * src/vmcore/loader.c: Likewise. * src/vmcore/method.h: Likewise. ........ r7581 | pm | 2007-03-26 09:23:16 +0200 (Mon, 26 Mar 2007) | 10 lines * src/vm/jit/s390/emit.c, src/vm/jit/s390/md-abi.h, src/vm/jit/s390/md.c, src/vm/jit/s390/emit.h, src/vm/jit/s390/codegen.c, src/vm/jit/s390/codegen.h, src/vm/jit/s390/tests/tests.java.pp, src/vm/jit/s390/patcher.c, src/vm/jit/s390/md-abi.c: Chaned a lot. ........ r7587 | twisti | 2007-03-28 15:29:09 +0200 (Wed, 28 Mar 2007) | 19 lines * src/vm/exceptions.c (throw_exception_exit_intern): Removed. (throw_exception): Likewise. (throw_exception_exit): Likewise. (throw_main_exception): Likewise. (throw_main_exception_exit): Likewise. (throw_cacao_exception_exit): Likewise. (exceptions_print_stacktrace): New function. * src/vm/exceptions.h: Likewise. * src/vm/vm.c (vm_create): Use vm_abort or exceptions_print_stacktrace instead of throw_main_exception_exit. (vm_run): Likewise. (vm_exit): Likewise. (vm_get_mainclass_from_jar): Likewise. * src/threads/native/threads.c (threads_init): Use return instead of throw_exception_exit. (threads_startup_thread): Use vm_abort. ........ r7593 | twisti | 2007-03-28 22:22:13 +0200 (Wed, 28 Mar 2007) | 3 lines Initialized merge tracking via "svnmerge" with revisions "1-7592" from svn+ssh://c1.complang.tuwien.ac.at/ahome/cacao/svn/cacao/branches/twisti ........ r7594 | twisti | 2007-03-28 22:28:37 +0200 (Wed, 28 Mar 2007) | 3 lines Initialized merge tracking via "svnmerge" with revisions "1-6086" from svn+ssh://c1.complang.tuwien.ac.at/ahome/cacao/svn/cacao/branches/twisti ........ r7595 | twisti | 2007-03-28 22:50:34 +0200 (Wed, 28 Mar 2007) | 3 lines Initialized merge tracking via "svnmerge" with revisions "1-6085" from file:///ahome/cacao/svn/cacao/branches/twisti ........ r7596 | twisti | 2007-03-28 23:05:53 +0200 (Wed, 28 Mar 2007) | 2 lines * Merged in twisti-branch. ........ r7597 | michi | 2007-03-29 00:25:44 +0200 (Thu, 29 Mar 2007) | 2 lines * AUTHORS: Added myself to the list of authors (finally). ........ r7598 | twisti | 2007-03-29 00:32:13 +0200 (Thu, 29 Mar 2007) | 2 lines * svnmerge uninit. ........ --HG-- branch : exact-gc --- diff --git a/AUTHORS b/AUTHORS index 11aa8aa06..a9e6b099f 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,13 +1,15 @@ -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 Mark Probst Stefan Ring +Michael Starzinger Edwin Steiner Christian Thalinger Dieter Thuernbeck diff --git a/configure.ac b/configure.ac index 05284e909..57f25442f 100644 --- a/configure.ac +++ b/configure.ac @@ -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 7441 2007-03-02 23:13:10Z michi $ +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] diff --git a/src/Makefile.am b/src/Makefile.am index 69ec6f6f8..1681eddf5 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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 \ diff --git a/src/cacaoh/dummy.c b/src/cacaoh/dummy.c index 3731f1243..03e9afb88 100644 --- a/src/cacaoh/dummy.c +++ b/src/cacaoh/dummy.c @@ -101,6 +101,16 @@ void intrp_asm_abstractmethoderror(void) abort(); } +void asm_getclassvalues_atomic(vftbl_t *super, vftbl_t *sub, castinfo *out) +{ + abort(); +} + +void intrp_asm_getclassvalues_atomic(vftbl_t *super, vftbl_t *sub, castinfo *out) +{ + abort(); +} + /* builtin ********************************************************************/ @@ -125,6 +135,13 @@ java_objectheader *builtin_new(classinfo *c) return NULL; } +java_objectarray *builtin_anewarray(s4 size, classinfo *componentclass) +{ + abort(); + + return NULL; +} + /* code ***********************************************************************/ @@ -258,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"); @@ -468,6 +496,13 @@ char *properties_get(char *key) /* resolve ********************************************************************/ +bool resolve_class_from_typedesc(typedesc *d, bool checkaccess, bool link, classinfo **result) +{ + abort(); + + return false; +} + /* stupid resolving implementation used by resolve_classref_or_classinfo_eager */ /* This function does eager resolving without any access checks. */ diff --git a/src/mm/boehm-gc/include/private/gc_locks.h b/src/mm/boehm-gc/include/private/gc_locks.h index 89638f6eb..aba1b46b6 100644 --- a/src/mm/boehm-gc/include/private/gc_locks.h +++ b/src/mm/boehm-gc/include/private/gc_locks.h @@ -137,6 +137,8 @@ } # 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. */ @@ -154,6 +156,7 @@ } # define GC_TEST_AND_SET_DEFINED # endif +#endif # if defined(POWERPC) inline static int GC_test_and_set(volatile unsigned int *addr) { int oldval; diff --git a/src/mm/nogc.c b/src/mm/nogc.c index 804fa593d..13ad45953 100644 --- a/src/mm/nogc.c +++ b/src/mm/nogc.c @@ -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 @@ -22,13 +22,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - Contact: cacao@cacaojvm.org - - Authors: Christian Thalinger - - Changes: - - $Id: nogc.c 6034 2006-11-21 21:02:30Z twisti $ + $Id: nogc.c 7596 2007-03-28 21:05:53Z twisti $ */ @@ -44,14 +38,17 @@ #include "mm/gc-common.h" #include "mm/memory.h" + #include "toolbox/logging.h" -#include "vm/options.h" + #include "vm/builtin.h" #include "vm/exceptions.h" #include "vm/global.h" -#include "vm/loader.h" #include "vm/stringlocal.h" +#include "vmcore/loader.h" +#include "vmcore/options.h" + /* global stuff ***************************************************************/ @@ -73,7 +70,11 @@ void *heap_allocate(u4 size, bool references, methodinfo *finalizer) mmapptr = (void *) ((ptrint) mmapptr + size); if (mmapptr > mmaptop) - exceptions_throw_outofmemory_exit(); +<<<<<<< .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) - exceptions_throw_outofmemory_exit(); +<<<<<<< .working + vm_abort("gc_init: out of memory"); +======= + exceptions_throw_outofmemoryerror(); +>>>>>>> .merge-right.r7379 mmapsize = heapmaxsize; mmaptop = (void *) ((ptrint) mmapptr + mmapsize); diff --git a/src/native/include/Makefile.am b/src/native/include/Makefile.am index f4bd5051b..b7a0c1883 100644 --- a/src/native/include/Makefile.am +++ b/src/native/include/Makefile.am @@ -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 7596 2007-03-28 21:05:53Z 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 diff --git a/src/native/jni.c b/src/native/jni.c index 38cf84b9e..25386f917 100644 --- a/src/native/jni.c +++ b/src/native/jni.c @@ -22,7 +22,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - $Id: jni.c 7483 2007-03-08 13:17:40Z michi $ + $Id: jni.c 7601 2007-03-28 23:02:50Z michi $ */ @@ -927,8 +927,10 @@ java_objectheader *_Jv_jni_invokeNative(methodinfo *m, java_objectheader *o, vmargs = MNEW(vm_arg, argcount); - if (!_Jv_jni_vmargs_from_objectarray(o, resm->parseddesc, vmargs, params)) + if (!_Jv_jni_vmargs_from_objectarray(o, resm->parseddesc, vmargs, params)) { + MFREE(vmargs, vm_arg, argcount); return NULL; + } switch (resm->parseddesc->returntype.decltype) { case TYPE_VOID: @@ -4130,7 +4132,7 @@ u2 *javastring_tou2(jstring so) /* GetStringChars ************************************************************** Returns a pointer to the array of Unicode characters of the - string. This pointer is valid until ReleaseStringchars() is called. + string. This pointer is valid until ReleaseStringChars() is called. *******************************************************************************/ @@ -4347,10 +4349,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; } diff --git a/src/native/native.c b/src/native/native.c index 4f70652df..ef8ef2ccb 100644 --- a/src/native/native.c +++ b/src/native/native.c @@ -22,7 +22,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - $Id: native.c 7483 2007-03-08 13:17:40Z michi $ + $Id: native.c 7601 2007-03-28 23:02:50Z michi $ */ @@ -1148,87 +1148,6 @@ java_objectarray *native_class_getdeclaredannotations(classinfo *c) #endif -/* native_get_parametertypes *************************************************** - - Use the descriptor of a method to generate a java/lang/Class array - which contains the classes of the parametertypes of the method. - -*******************************************************************************/ - -java_objectarray *native_get_parametertypes(methodinfo *m) -{ - methoddesc *md; - typedesc *paramtypes; - s4 paramcount; - java_objectarray *oa; - s4 i; - - md = m->parseddesc; - - /* is the descriptor fully parsed? */ - - if (m->parseddesc->params == NULL) - if (!descriptor_params_from_paramtypes(md, m->flags)) - return NULL; - - paramtypes = md->paramtypes; - paramcount = md->paramcount; - - /* skip `this' pointer */ - - if (!(m->flags & ACC_STATIC)) { - paramtypes++; - paramcount--; - } - - /* create class-array */ - - oa = builtin_anewarray(paramcount, class_java_lang_Class); - - if (oa == NULL) - return NULL; - - /* get classes */ - - for (i = 0; i < paramcount; i++) - if (!resolve_class_from_typedesc(¶mtypes[i], true, false, - (classinfo **) &oa->data[i])) - return NULL; - - return oa; -} - - -/* native_get_exceptiontypes *************************************************** - - Get the exceptions which can be thrown by a method. - -*******************************************************************************/ - -java_objectarray *native_get_exceptiontypes(methodinfo *m) -{ - java_objectarray *oa; - classinfo *c; - u2 i; - - /* create class-array */ - - oa = builtin_anewarray(m->thrownexceptionscount, class_java_lang_Class); - - if (oa == NULL) - return NULL; - - for (i = 0; i < m->thrownexceptionscount; i++) { - if ((c = resolve_classref_or_classinfo_eager(m->thrownexceptions[i], true)) == NULL) - return NULL; - - oa->data[i] = (java_objectheader *) c; - } - - return oa; -} - - /* * 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 diff --git a/src/native/native.h b/src/native/native.h index e649d54bf..b12d417e4 100644 --- a/src/native/native.h +++ b/src/native/native.h @@ -22,7 +22,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - $Id: native.h 7393 2007-02-23 20:28:35Z michi $ + $Id: native.h 7601 2007-03-28 23:02:50Z michi $ */ @@ -134,9 +134,6 @@ java_objectheader *native_new_and_init_int(classinfo *c, s4 i); java_objectheader *native_new_and_init_throwable(classinfo *c, java_objectheader *t); -java_objectarray *native_get_parametertypes(methodinfo *m); -java_objectarray *native_get_exceptiontypes(methodinfo *m); - #endif /* _NATIVE_H */ diff --git a/src/native/vm/cldc1.1/com_sun_cldc_io_ResourceInputStream.c b/src/native/vm/cldc1.1/com_sun_cldc_io_ResourceInputStream.c index 566551be8..e0d7a8f10 100644 --- a/src/native/vm/cldc1.1/com_sun_cldc_io_ResourceInputStream.c +++ b/src/native/vm/cldc1.1/com_sun_cldc_io_ResourceInputStream.c @@ -35,6 +35,8 @@ #include "native/include/java_lang_Object.h" #include "native/include/java_lang_String.h" +#include "vm/vm.h" /* REMOVE ME: temporarily */ + /* * Class: com/sun/cldc/io/ResourceInputStream @@ -43,7 +45,7 @@ */ JNIEXPORT java_lang_Object* JNICALL Java_com_sun_cldc_io_ResourceInputStream_open(JNIEnv *env, jclass clazz, java_lang_String *name) { - exceptions_throw_outofmemoryerror(); + vm_abort("Java_com_sun_cldc_io_ResourceInputStream_open: IMPLEMENT ME!"); return NULL; } diff --git a/src/native/vm/cldc1.1/com_sun_cldc_io_j2me_socket_Protocol.c b/src/native/vm/cldc1.1/com_sun_cldc_io_j2me_socket_Protocol.c index b59754194..1274b074f 100644 --- a/src/native/vm/cldc1.1/com_sun_cldc_io_j2me_socket_Protocol.c +++ b/src/native/vm/cldc1.1/com_sun_cldc_io_j2me_socket_Protocol.c @@ -31,6 +31,7 @@ #include #include +#include #include #include @@ -41,6 +42,7 @@ #include "native/jni.h" #include "vm/global.h" +#include "vm/vm.h" /* REMOVE ME: temporarily */ /* @@ -69,14 +71,14 @@ JNIEXPORT s4 JNICALL Java_com_sun_cldc_io_j2me_socket_Protocol_open0(JNIEnv *env /* fill the sockaddr structure */ - serv_addr.sin_family = AF_INET; - serv_addr.sin_port = htons(port); + serv_addr.sin_family = AF_INET; + serv_addr.sin_port = htons(port); - MCOPY(&serv_addr.sin_addr, phostent->h_addr, u1, phostent->h_length); + MCOPY(&serv_addr.sin_addr, phostent->h_addr, u1, phostent->h_length); /* create the socket */ - sockfd = socket(AF_INET, SOCK_STREAM, 0); + sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) return -1; @@ -123,6 +125,63 @@ JNIEXPORT s4 JNICALL Java_com_sun_cldc_io_j2me_socket_Protocol_readBuf(JNIEnv *e } +/* + * Class: com/sun/cldc/io/j2me/socket/Protocol + * Method: readByte + * Signature: (I)I + */ +JNIEXPORT s4 JNICALL Java_com_sun_cldc_io_j2me_socket_Protocol_readByte(JNIEnv *env, jclass clazz, s4 handle) { + + char byte; + ssize_t result; + + /* receive from the socket */ + + result = recv(handle, &byte, 1, 0); + + if (result == 0) { + /* the peer has performed an orderly shutdown */ + + return -1; + } + else if (result < 0) { + /* should throw an IOException */ + + vm_abort("Java_com_sun_cldc_io_j2me_socket_Protocol_readByte: recv failed: %s", strerror(errno)); + } + + return byte; +} + + +/* + * Class: com/sun/cldc/io/j2me/socket/Protocol + * Method: writeBuf + * Signature: (I[BII)I + */ +JNIEXPORT s4 JNICALL Java_com_sun_cldc_io_j2me_socket_Protocol_writeBuf(JNIEnv *env, jclass clazz, s4 handle, java_bytearray* b, s4 off, s4 len) { + + void *buf; + ssize_t result; + + /* get pointer to the buffer */ + + buf = &(b->data[off]); + + /* send the given byte to the socket */ + + result = send(handle, buf, len, 0); + + if (result < 0) + /* should throw an IOException */ + + vm_abort("Java_com_sun_cldc_io_j2me_socket_Protocol_writeBuf: send failed: %s", strerror(errno)); + + return result; + +} + + /* * Class: com/sun/cldc/io/j2me/socket/Protocol * Method: writeByte @@ -146,6 +205,37 @@ JNIEXPORT s4 JNICALL Java_com_sun_cldc_io_j2me_socket_Protocol_writeByte(JNIEnv } +/* + * Class: com/sun/cldc/io/j2me/socket/Protocol + * Method: available0 + * Signature: (I)I + */ +JNIEXPORT s4 JNICALL Java_com_sun_cldc_io_j2me_socket_Protocol_available0(JNIEnv *env, jclass clazz, s4 handle) +{ + /* NOTE: Sun doesn't have an implementation too */ + + return 0; +} + + +/* + * Class: com/sun/cldc/io/j2me/socket/Protocol + * Method: close0 + * Signature: (I)V + */ +JNIEXPORT void JNICALL Java_com_sun_cldc_io_j2me_socket_Protocol_close0(JNIEnv *env, jclass clazz, s4 handle) +{ + int result; + + /* close the file descriptor */ + + result = close(handle); + + if (result < 0) + vm_abort("Java_com_sun_cldc_io_j2me_socket_Protocol_close0: close failed: %s", strerror(errno)); +} + + /* * 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 diff --git a/src/native/vm/gnu/java_lang_reflect_Constructor.c b/src/native/vm/gnu/java_lang_reflect_Constructor.c index d2fa2eaac..9a5a343be 100644 --- a/src/native/vm/gnu/java_lang_reflect_Constructor.c +++ b/src/native/vm/gnu/java_lang_reflect_Constructor.c @@ -22,7 +22,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - $Id: java_lang_reflect_Constructor.c 7441 2007-03-02 23:13:10Z michi $ + $Id: java_lang_reflect_Constructor.c 7573 2007-03-25 18:55:02Z twisti $ */ @@ -82,7 +82,7 @@ JNIEXPORT java_objectarray* JNICALL Java_java_lang_reflect_Constructor_getParame c = (classinfo *) this->clazz; m = &(c->methods[this->slot]); - return native_get_parametertypes(m); + return method_get_parametertypearray(m); } @@ -99,7 +99,7 @@ JNIEXPORT java_objectarray* JNICALL Java_java_lang_reflect_Constructor_getExcept c = (classinfo *) this->clazz; m = &(c->methods[this->slot]); - return native_get_exceptiontypes(m); + return method_get_exceptionarray(m); } diff --git a/src/native/vm/gnu/java_lang_reflect_Method.c b/src/native/vm/gnu/java_lang_reflect_Method.c index 2d5ac85e0..2bb0169ea 100644 --- a/src/native/vm/gnu/java_lang_reflect_Method.c +++ b/src/native/vm/gnu/java_lang_reflect_Method.c @@ -22,7 +22,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - $Id: java_lang_reflect_Method.c 7441 2007-03-02 23:13:10Z michi $ + $Id: java_lang_reflect_Method.c 7573 2007-03-25 18:55:02Z twisti $ */ @@ -45,6 +45,7 @@ #include "vm/builtin.h" #include "vm/exceptions.h" #include "vm/initialize.h" +#include "vm/resolve.h" #include "vm/stringlocal.h" @@ -101,7 +102,7 @@ JNIEXPORT java_objectarray* JNICALL Java_java_lang_reflect_Method_getParameterTy c = (classinfo *) this->declaringClass; m = &(c->methods[this->slot]); - return native_get_parametertypes(m); + return method_get_parametertypearray(m); } @@ -118,7 +119,7 @@ JNIEXPORT java_objectarray* JNICALL Java_java_lang_reflect_Method_getExceptionTy c = (classinfo *) this->declaringClass; m = &(c->methods[this->slot]); - return native_get_exceptiontypes(m); + return method_get_exceptionarray(m); } diff --git a/src/native/vm/java_lang_Class.c b/src/native/vm/java_lang_Class.c index 381269bbf..c0c3c0d02 100644 --- a/src/native/vm/java_lang_Class.c +++ b/src/native/vm/java_lang_Class.c @@ -237,9 +237,7 @@ s4 _Jv_java_lang_Class_isAssignableFrom(java_lang_Class *klass, java_lang_Class if (!link_class(cc)) return 0; - /* XXX this may be wrong for array classes */ - - return builtin_isanysubclass(cc, kc); + return class_isanysubclass(cc, kc); } diff --git a/src/threads/native/lock.c b/src/threads/native/lock.c index 1a65bfaa8..6eeec822f 100644 --- a/src/threads/native/lock.c +++ b/src/threads/native/lock.c @@ -47,6 +47,12 @@ #include "vm/stringlocal.h" #include "vm/vm.h" +#include "vmcore/options.h" + +#if defined(ENABLE_STATISTICS) +# include "vmcore/statistics.h" +#endif + /* arch.h must be here because it defines USE_FAKE_ATOMIC_INSTRUCTIONS */ #include "arch.h" @@ -300,29 +306,35 @@ ptrint lock_pre_compute_thinlock(s4 index) static lock_record_pool_t *lock_record_alloc_new_pool(threadobject *thread, int size) { - int i; lock_record_pool_t *pool; + s4 i; /* get the pool from the memory allocator */ pool = mem_alloc(sizeof(lock_record_pool_header_t) + sizeof(lock_record_t) * size); +#if defined(ENABLE_STATISTICS) + if (opt_stat) + size_lock_record_pool += sizeof(lock_record_pool_header_t) + + sizeof(lock_record_t) * size; +#endif + /* initialize the pool header */ pool->header.size = size; /* initialize the individual lock records */ - for (i=0; ilr[i], thread); - pool->lr[i].nextfree = &pool->lr[i+1]; + pool->lr[i].nextfree = &pool->lr[i + 1]; } /* terminate free list */ - pool->lr[i-1].nextfree = NULL; + pool->lr[i - 1].nextfree = NULL; return pool; } @@ -346,24 +358,24 @@ static lock_record_pool_t *lock_record_alloc_pool(threadobject *t, int size) { pthread_mutex_lock(&lock_global_pool_lock); - if (lock_global_pool) { + if (lock_global_pool != NULL) { int i; lock_record_pool_t *pool; /* pop a pool from the global freelist */ - pool = lock_global_pool; + pool = lock_global_pool; lock_global_pool = pool->header.next; pthread_mutex_unlock(&lock_global_pool_lock); /* re-initialize owner and freelist chaining */ - for (i=0; i < pool->header.size; i++) { - pool->lr[i].owner = NULL; - pool->lr[i].nextfree = &pool->lr[i+1]; + for (i = 0; i < pool->header.size; i++) { + pool->lr[i].owner = NULL; + pool->lr[i].nextfree = &pool->lr[i + 1]; } - pool->lr[i-1].nextfree = NULL; + pool->lr[i - 1].nextfree = NULL; return pool; } @@ -394,7 +406,7 @@ void lock_record_free_pools(lock_record_pool_t *pool) /* algorithm. We must find another way to free */ /* unused lock records. */ - if (!pool) + if (pool == NULL) return; pthread_mutex_lock(&lock_global_pool_lock); @@ -402,6 +414,7 @@ void lock_record_free_pools(lock_record_pool_t *pool) /* find the last pool in the list */ last = &pool->header; + while (last->next) last = &last->next->header; @@ -503,9 +516,15 @@ static void lock_hashtable_init(void) { pthread_mutex_init(&(lock_hashtable.mutex), NULL); - lock_hashtable.size = LOCK_INITIAL_HASHTABLE_SIZE; + lock_hashtable.size = LOCK_INITIAL_HASHTABLE_SIZE; lock_hashtable.entries = 0; - lock_hashtable.ptr = MNEW(lock_record_t *, lock_hashtable.size); + lock_hashtable.ptr = MNEW(lock_record_t *, lock_hashtable.size); + +#if defined(ENABLE_STATISTICS) + if (opt_stat) + size_lock_hashtable += sizeof(lock_record_t *) * lock_hashtable.size; +#endif + MZERO(lock_hashtable.ptr, lock_record_t *, lock_hashtable.size); } @@ -539,11 +558,17 @@ static void lock_hashtable_grow(void) oldtable = lock_hashtable.ptr; newtable = MNEW(lock_record_t *, newsize); + +#if defined(ENABLE_STATISTICS) + if (opt_stat) + size_lock_hashtable += sizeof(lock_record_t *) * newsize; +#endif + MZERO(newtable, lock_record_t *, newsize); /* rehash the entries */ - for (i=0; ihashlink; @@ -560,10 +585,15 @@ static void lock_hashtable_grow(void) /* replace the old table */ - lock_hashtable.ptr = newtable; + lock_hashtable.ptr = newtable; lock_hashtable.size = newsize; MFREE(oldtable, lock_record_t *, oldsize); + +#if defined(ENABLE_STATISTICS) + if (opt_stat) + size_lock_hashtable -= sizeof(lock_record_t *) * oldsize; +#endif } @@ -1064,6 +1094,11 @@ static void lock_record_add_waiter(lock_record_t *lr, threadobject *thread) waiter = NEW(lock_waiter_t); +#if defined(ENABLE_STATISTICS) + if (opt_stat) + size_lock_waiter += sizeof(lock_waiter_t); +#endif + waiter->waiter = thread; waiter->next = lr->waiters; @@ -1099,6 +1134,11 @@ static void lock_record_remove_waiter(lock_record_t *lr, threadobject *thread) FREE(w, lock_waiter_t); +#if defined(ENABLE_STATISTICS) + if (opt_stat) + size_lock_waiter -= sizeof(lock_waiter_t); +#endif + return; } diff --git a/src/threads/native/threads.c b/src/threads/native/threads.c index fbe06fdff..ee50e7687 100644 --- a/src/threads/native/threads.c +++ b/src/threads/native/threads.c @@ -22,7 +22,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - $Id: threads.c 7496 2007-03-12 00:19:05Z michi $ + $Id: threads.c 7601 2007-03-28 23:02:50Z michi $ */ @@ -88,6 +88,10 @@ #include "vmcore/options.h" +#if defined(ENABLE_STATISTICS) +# include "vmcore/statistics.h" +#endif + #if !defined(__DARWIN__) # if defined(__LINUX__) # define GC_LINUX_THREADS @@ -689,6 +693,12 @@ void threads_preinit(void) pthread_mutex_init(&stopworldlock, NULL); mainthreadobj = NEW(threadobject); + +#if defined(ENABLE_STATISTICS) + if (opt_stat) + size_threadobject += sizeof(threadobject); +#endif + mainthreadobj->object = NULL; mainthreadobj->tid = pthread_self(); mainthreadobj->index = 1; @@ -776,6 +786,11 @@ bool threads_init(void) #if defined(ENABLE_GC_CACAO) mainthreadobj = NEW(threadobject); + +# if defined(ENABLE_STATISTICS) + if (opt_stat) + size_threadobject += sizeof(threadobject); +# endif #else mainthreadobj = GCNEW(threadobject); #endif @@ -823,7 +838,7 @@ bool threads_init(void) native_new_and_init(class_java_lang_ThreadGroup); if (threadgroup == NULL) - throw_exception_exit(); + return false; #endif #if defined(WITH_CLASSPATH_GNU) @@ -832,7 +847,7 @@ bool threads_init(void) vmt = (java_lang_VMThread *) builtin_new(class_java_lang_VMThread); if (vmt == NULL) - throw_exception_exit(); + return false; /* set the thread */ @@ -1150,7 +1165,7 @@ static void *threads_startup_thread(void *t) m = class_resolveclassmethod(c, utf_run, utf_void__void, c, true); if (m == NULL) - throw_exception(); + vm_abort("threads_startup_thread: run() method not found in class"); /* set ThreadMXBean variables */ @@ -1227,7 +1242,11 @@ void threads_start_javathread(java_lang_Thread *object) /* create the vm internal threadobject */ thread = NEW(threadobject); - assert(thread); + +#if defined(ENABLE_STATISTICS) + if (opt_stat) + size_threadobject += sizeof(threadobject); +#endif /* link the two objects together */ @@ -1355,6 +1374,11 @@ bool threads_attach_current_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon) thread = NEW(threadobject); +#if defined(ENABLE_STATISTICS) + if (opt_stat) + size_threadobject += sizeof(threadobject); +#endif + if (thread == NULL) return false; @@ -1545,6 +1569,11 @@ bool threads_detach_thread(threadobject *thread) FREE(thread, threadobject); +#if defined(ENABLE_STATISTICS) + if (opt_stat) + size_threadobject -= sizeof(threadobject); +#endif + return true; } diff --git a/src/toolbox/list.c b/src/toolbox/list.c index e277eb572..d6da79efb 100644 --- a/src/toolbox/list.c +++ b/src/toolbox/list.c @@ -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 7596 2007-03-28 21:05:53Z 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); } diff --git a/src/toolbox/list.h b/src/toolbox/list.h index 672751cb0..1feaa1b03 100644 --- a/src/toolbox/list.h +++ b/src/toolbox/list.h @@ -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 @@ -22,13 +22,7 @@ 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 7596 2007-03-28 21:05:53Z 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); diff --git a/src/vm/access.c b/src/vm/access.c index 45e8548bc..502cb1f41 100644 --- a/src/vm/access.c +++ b/src/vm/access.c @@ -22,7 +22,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - $Id: access.c 7441 2007-03-02 23:13:10Z michi $ + $Id: access.c 7563 2007-03-23 21:33:53Z twisti $ */ @@ -148,7 +148,7 @@ bool access_is_accessible_member(classinfo *referer, classinfo *declarer, assert((referer->state & CLASS_LINKED) && (declarer->state & CLASS_LINKED)); - if (builtin_isanysubclass(referer, declarer)) + if (class_isanysubclass(referer, declarer)) return true; return false; diff --git a/src/vm/builtin.c b/src/vm/builtin.c index 75a55f6bc..a2298c90a 100644 --- a/src/vm/builtin.c +++ b/src/vm/builtin.c @@ -28,7 +28,7 @@ calls instead of machine instructions, using the C calling convention. - $Id: builtin.c 7483 2007-03-08 13:17:40Z michi $ + $Id: builtin.c 7596 2007-03-28 21:05:53Z twisti $ */ @@ -370,106 +370,40 @@ bool builtintable_replace_function(void *iptr_) TYPE CHECKS *****************************************************************************/ +/* builtin_instanceof ********************************************************** + Checks if an object is an instance of some given class (or subclass + of that class). If class is an interface, checks if the interface + is implemented. -/*************** internal function: builtin_isanysubclass ********************* - - Checks a subclass relation between two classes. Implemented interfaces - are interpreted as super classes. - Return value: 1 ... sub is subclass of super - 0 ... otherwise - -******************************************************************************/ - -s4 builtin_isanysubclass(classinfo *sub, classinfo *super) -{ - s4 res; - castinfo classvalues; - - if (sub == super) - return 1; - - if (super->flags & ACC_INTERFACE) { - res = (sub->vftbl->interfacetablelength > super->index) && - (sub->vftbl->interfacetable[-super->index] != NULL); - - } else { - /* java.lang.Object is the only super_class_ of any interface */ - if (sub->flags & ACC_INTERFACE) - return (super == class_java_lang_Object); - - ASM_GETCLASSVALUES_ATOMIC(super->vftbl, sub->vftbl, &classvalues); - - res = (u4) (classvalues.sub_baseval - classvalues.super_baseval) <= - (u4) classvalues.super_diffval; - } - - return res; -} - - -s4 builtin_isanysubclass_vftbl(vftbl_t *sub, vftbl_t *super) -{ - s4 res; - s4 base; - castinfo classvalues; - - if (sub == super) - return 1; - - ASM_GETCLASSVALUES_ATOMIC(super, sub, &classvalues); - - if ((base = classvalues.super_baseval) <= 0) { - /* super is an interface */ - res = (sub->interfacetablelength > -base) && - (sub->interfacetable[base] != NULL); - } - else { - /* java.lang.Object is the only super_class_ of any interface */ - if (classvalues.sub_baseval <= 0) - return classvalues.super_baseval == 1; - - res = (u4) (classvalues.sub_baseval - classvalues.super_baseval) - <= (u4) classvalues.super_diffval; - } - - return res; -} - - -/****************** function: builtin_instanceof ***************************** - - Checks if an object is an instance of some given class (or subclass of - that class). If class is an interface, checks if the interface is - implemented. - Return value: 1 ... obj is an instance of class or implements the interface - 0 ... otherwise or if obj == NULL + Return value: 1 ... o is an instance of class or implements the interface + 0 ... otherwise or if o == NULL -*****************************************************************************/ +*******************************************************************************/ -s4 builtin_instanceof(java_objectheader *obj, classinfo *class) +s4 builtin_instanceof(java_objectheader *o, classinfo *class) { - if (!obj) + if (o == NULL) return 0; - return builtin_isanysubclass(obj->vftbl->class, class); + return class_isanysubclass(o->vftbl->class, class); } -/**************** function: builtin_checkcast ******************************* +/* builtin_checkcast *********************************************************** - The same as builtin_instanceof except that 1 is returned when - obj == NULL + The same as builtin_instanceof except that 1 is returned when o == + NULL. -****************************************************************************/ +*******************************************************************************/ -s4 builtin_checkcast(java_objectheader *obj, classinfo *class) +s4 builtin_checkcast(java_objectheader *o, classinfo *class) { - if (obj == NULL) + if (o == NULL) return 1; - if (builtin_isanysubclass(obj->vftbl->class, class)) + if (class_isanysubclass(o->vftbl->class, class)) return 1; return 0; @@ -507,8 +441,8 @@ static s4 builtin_descriptorscompatible(arraydescriptor *desc, (target->elementvftbl->baseval == 1)) return 1; - return builtin_isanysubclass_vftbl(desc->elementvftbl, - target->elementvftbl); + return class_isanysubclass(desc->elementvftbl->class, + target->elementvftbl->class); } if (desc->dimension < target->dimension) @@ -516,8 +450,8 @@ static s4 builtin_descriptorscompatible(arraydescriptor *desc, /* {desc has higher dimension than target} */ - return builtin_isanysubclass_vftbl(pseudo_class_Arraystub->vftbl, - target->elementvftbl); + return class_isanysubclass(pseudo_class_Arraystub, + target->elementvftbl->class); } @@ -538,10 +472,12 @@ s4 builtin_arraycheckcast(java_objectheader *o, classinfo *targetclass) { arraydescriptor *desc; - if (!o) + if (o == NULL) return 1; - if ((desc = o->vftbl->arraydesc) == NULL) + desc = o->vftbl->arraydesc; + + if (desc == NULL) return 0; return builtin_descriptorscompatible(desc, targetclass->vftbl->arraydesc); @@ -550,7 +486,7 @@ s4 builtin_arraycheckcast(java_objectheader *o, classinfo *targetclass) s4 builtin_arrayinstanceof(java_objectheader *o, classinfo *targetclass) { - if (!o) + if (o == NULL) return 0; return builtin_arraycheckcast(o, targetclass); @@ -641,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) *******************************************************************************/ @@ -653,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): @@ -667,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} */ @@ -679,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} */ - /* {o is an array} */ + result = builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc); + } - return builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc); + /* if not possible, throw an exception */ + + if (result == 0) + exceptions_throw_arraystoreexception(); + + /* return result */ + + return result; } @@ -2610,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; } @@ -2628,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; } diff --git a/src/vm/builtin.h b/src/vm/builtin.h index a66fe2d5d..2b9c17ceb 100644 --- a/src/vm/builtin.h +++ b/src/vm/builtin.h @@ -22,7 +22,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - $Id: builtin.h 7483 2007-03-08 13:17:40Z michi $ + $Id: builtin.h 7563 2007-03-23 21:33:53Z twisti $ */ @@ -116,10 +116,6 @@ bool builtintable_replace_function(void *iptr); s4 builtin_instanceof(java_objectheader *obj, classinfo *class); #define BUILTIN_instanceof (functionptr) builtin_instanceof -s4 builtin_isanysubclass (classinfo *sub, classinfo *super); -/* NOT AN OP */ -s4 builtin_isanysubclass_vftbl (vftbl_t *sub, vftbl_t *super); -/* NOT AN OP */ s4 builtin_checkcast(java_objectheader *obj, classinfo *class); /* NOT AN OP */ s4 builtin_arrayinstanceof(java_objectheader *o, classinfo *targetclass); diff --git a/src/vm/exceptions.c b/src/vm/exceptions.c index 722c7df10..6754a62be 100644 --- a/src/vm/exceptions.c +++ b/src/vm/exceptions.c @@ -22,7 +22,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - $Id: exceptions.c 7386 2007-02-21 23:23:25Z 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" @@ -169,137 +172,6 @@ bool exceptions_init(void) } -static void throw_exception_exit_intern(bool doexit) -{ - java_objectheader *xptr; - classinfo *c; - methodinfo *pss; - - xptr = *exceptionptr; - - if (xptr) { - /* clear exception, because we are calling jit code again */ - *exceptionptr = NULL; - - c = xptr->vftbl->class; - - pss = class_resolveclassmethod(c, - utf_printStackTrace, - utf_void__void, - class_java_lang_Object, - false); - - /* print the stacktrace */ - - if (pss) { - (void) vm_call_method(pss, xptr); - - /* This normally means, we are EXTREMLY out of memory or have a */ - /* serious problem while printStackTrace. But may be another */ - /* exception, so print it. */ - - if (*exceptionptr) { - java_lang_Throwable *t; - - t = (java_lang_Throwable *) *exceptionptr; - - fprintf(stderr, "Exception while printStackTrace(): "); - utf_fprint_printable_ascii_classname(stderr, t->header.vftbl->class->name); - - if (t->detailMessage) { - char *buf; - - buf = javastring_tochar((java_objectheader *) t->detailMessage); - fprintf(stderr, ": %s", buf); - MFREE(buf, char, strlen(buf)); - } - - fprintf(stderr, "\n"); - } - - } else { - utf_fprint_printable_ascii_classname(stderr, c->name); - fprintf(stderr, ": printStackTrace()V not found!\n"); - } - - fflush(stderr); - - /* good bye! */ - - if (doexit) - exit(1); - } -} - - -void throw_exception(void) -{ - throw_exception_exit_intern(false); -} - - -void throw_exception_exit(void) -{ - throw_exception_exit_intern(true); -} - - -void throw_main_exception(void) -{ - fprintf(stderr, "Exception in thread \"main\" "); - fflush(stderr); - - throw_exception_exit_intern(false); -} - - -void throw_main_exception_exit(void) -{ - fprintf(stderr, "Exception in thread \"main\" "); - fflush(stderr); - - throw_exception_exit_intern(true); -} - - -void throw_cacao_exception_exit(const char *exception, const char *message, ...) -{ - s4 i; - char *tmp; - s4 len; - va_list ap; - - len = strlen(exception); - tmp = MNEW(char, len + 1); - strncpy(tmp, exception, len); - tmp[len] = '\0'; - - /* convert to classname */ - - for (i = len - 1; i >= 0; i--) - if (tmp[i] == '/') tmp[i] = '.'; - - fprintf(stderr, "Exception in thread \"main\" %s", tmp); - - MFREE(tmp, char, len); - - if (strlen(message) > 0) { - fprintf(stderr, ": "); - - va_start(ap, message); - vfprintf(stderr, message, ap); - va_end(ap); - } - - fprintf(stderr, "\n"); - fflush(stderr); - - /* good bye! */ - - exit(1); -} - - /* exceptions_new_class ******************************************************** Creates an exception object from the given class and initalizes it. @@ -845,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, @@ -1661,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. @@ -1691,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. @@ -1724,6 +1743,15 @@ u1 *exceptions_handle_exception(java_objectheader *xptr, u1 *xpc, u1 *pv, u1 *sp java_objectheader *o; #endif +#ifdef __S390__ + /* Addresses are 31 bit integers */ +# define ADDR_MASK(x) (u1 *)((u4)(x) & 0x7FFFFFFF) +#else +# define ADDR_MASK(x) (x) +#endif + + xpc = ADDR_MASK(xpc); + /* get info from the method header */ code = *((codeinfo **) (pv + CodeinfoPointer)); @@ -1758,7 +1786,7 @@ u1 *exceptions_handle_exception(java_objectheader *xptr, u1 *xpc, u1 *pv, u1 *sp /* is the xpc is the current catch range */ - if ((ex->startpc <= xpc) && (xpc < ex->endpc)) { + if ((ADDR_MASK(ex->startpc) <= xpc) && (xpc < ADDR_MASK(ex->endpc))) { cr = ex->catchtype; /* NULL catches everything */ @@ -1937,6 +1965,80 @@ void exceptions_print_current_exception(void) } +/* exceptions_print_stacktrace ************************************************* + + Prints a pending exception with Throwable.printStackTrace(). If + there happens an exception during printStackTrace(), we print the + thrown exception and the original one. + + NOTE: This function calls Java code. + +*******************************************************************************/ + +void exceptions_print_stacktrace(void) +{ + java_objectheader *oxptr; + java_objectheader *xptr; + classinfo *c; + methodinfo *m; + + /* get original exception */ + + oxptr = *exceptionptr; + + if (oxptr == NULL) + vm_abort("exceptions_print_stacktrace: no exception thrown"); + + /* clear exception, because we are calling jit code again */ + + *exceptionptr = NULL; + + c = oxptr->vftbl->class; + + /* find the printStackTrace() method */ + + m = class_resolveclassmethod(c, + utf_printStackTrace, + utf_void__void, + class_java_lang_Object, + false); + + if (m == NULL) + vm_abort("exceptions_print_stacktrace: printStackTrace()V not found"); + + /* print compatibility message */ + + fprintf(stderr, "Exception in thread \"main\" "); + + /* print the stacktrace */ + + (void) vm_call_method(m, oxptr); + + /* This normally means, we are EXTREMLY out of memory or + have a serious problem while printStackTrace. But may + be another exception, so print it. */ + + xptr = *exceptionptr; + + if (xptr != NULL) { + fprintf(stderr, "Exception while printStackTrace(): "); + + /* now print original exception */ + + exceptions_print_exception(xptr); + stacktrace_print_trace(xptr); + + /* now print original exception */ + + fprintf(stderr, "Original exception was: "); + exceptions_print_exception(oxptr); + stacktrace_print_trace(oxptr); + } + + fflush(stderr); +} + + /* * 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 diff --git a/src/vm/exceptions.h b/src/vm/exceptions.h index c3539cb4c..61544d044 100644 --- a/src/vm/exceptions.h +++ b/src/vm/exceptions.h @@ -22,7 +22,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - $Id: exceptions.h 7261 2007-01-31 10:00:12Z twisti $ + $Id: exceptions.h 7601 2007-03-28 23:02:50Z michi $ */ @@ -43,40 +43,43 @@ /* 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 -/* function prototypes ********************************************************/ -/* load and link exceptions used in the system */ -bool exceptions_init(void); +/* exception pointer **********************************************************/ +#if defined(ENABLE_THREADS) +#define exceptionptr &(THREADOBJECT->_exceptionptr) +#else +#define exceptionptr &_no_threads_exceptionptr +#endif -/* exception throwing functions */ +#if !defined(ENABLE_THREADS) +extern java_objectheader *_no_threads_exceptionptr; +#endif -void throw_exception(void); -void throw_exception_exit(void); -void throw_main_exception(void); -void throw_main_exception_exit(void); - -void throw_cacao_exception_exit(const char *exception, - const char *message, ...); +/* function prototypes ********************************************************/ +/* load and link exceptions used in the system */ +bool exceptions_init(void); /* initialize new exceptions */ @@ -97,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); @@ -132,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); @@ -139,8 +145,11 @@ 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); #endif /* _EXCEPTIONS_H */ diff --git a/src/vm/global.h b/src/vm/global.h index d660b03e1..cf4d92843 100644 --- a/src/vm/global.h +++ b/src/vm/global.h @@ -32,7 +32,7 @@ Joseph Wenninger Christian Thalinger - $Id: global.h 7437 2007-03-02 22:36:09Z michi $ + $Id: global.h 7601 2007-03-28 23:02:50Z michi $ */ @@ -202,10 +202,11 @@ typedef struct java_objectarray java_objectarray; #define ACC_CLASS_REFLECT_MASK 0x0000ffff/* flags reported by reflection */ -#define ACC_CLASS_HAS_POINTERS 0x00010000/* instance contains pointers */ -#define ACC_CLASS_SOFT_REFERENCE 0x00020000 -#define ACC_CLASS_WEAK_REFERENCE 0x00040000 -#define ACC_CLASS_PHANTOM_REFERENCE 0x00080000 +#define ACC_CLASS_PRIMITIVE 0x00010000/* class is a primitive class */ +#define ACC_CLASS_HAS_POINTERS 0x00020000/* instance contains pointers */ +#define ACC_CLASS_SOFT_REFERENCE 0x00040000 +#define ACC_CLASS_WEAK_REFERENCE 0x00080000 +#define ACC_CLASS_PHANTOM_REFERENCE 0x00100000 /* special flags used in methodinfo *******************************************/ diff --git a/src/vm/jit/abi.h b/src/vm/jit/abi.h index 8d80e7b60..74338d881 100644 --- a/src/vm/jit/abi.h +++ b/src/vm/jit/abi.h @@ -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 7596 2007-03-28 21:05:53Z twisti $ */ @@ -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[]; diff --git a/src/vm/jit/alpha/arch.h b/src/vm/jit/alpha/arch.h index 757a3a7a8..c0d4f719a 100644 --- a/src/vm/jit/alpha/arch.h +++ b/src/vm/jit/alpha/arch.h @@ -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 7596 2007-03-28 21:05:53Z twisti $ */ @@ -93,6 +93,13 @@ #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 diff --git a/src/vm/jit/alpha/asmpart.S b/src/vm/jit/alpha/asmpart.S index 63ca7efe5..1d240f9cb 100644 --- a/src/vm/jit/alpha/asmpart.S +++ b/src/vm/jit/alpha/asmpart.S @@ -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 7596 2007-03-28 21:05:53Z twisti $ */ @@ -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 diff --git a/src/vm/jit/alpha/codegen.c b/src/vm/jit/alpha/codegen.c index 24df4ef4a..e8e29f9d8 100644 --- a/src/vm/jit/alpha/codegen.c +++ b/src/vm/jit/alpha/codegen.c @@ -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 7596 2007-03-28 21:05:53Z twisti $ */ @@ -73,13 +73,13 @@ #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; diff --git a/src/vm/jit/alpha/codegen.h b/src/vm/jit/alpha/codegen.h index a567903d1..fb60d38f6 100644 --- a/src/vm/jit/alpha/codegen.h +++ b/src/vm/jit/alpha/codegen.h @@ -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 @@ -22,13 +22,7 @@ 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 7596 2007-03-28 21:05:53Z twisti $ */ @@ -177,6 +171,10 @@ 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) *********/ @@ -226,6 +224,7 @@ } \ } 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 */ diff --git a/src/vm/jit/alpha/emit.c b/src/vm/jit/alpha/emit.c index dd0743e9d..0ee8f57db 100644 --- a/src/vm/jit/alpha/emit.c +++ b/src/vm/jit/alpha/emit.c @@ -43,6 +43,7 @@ #endif #include "vm/builtin.h" +#include "vm/exceptions.h" #include "vm/jit/abi-asm.h" #include "vm/jit/asmpart.h" @@ -63,6 +64,7 @@ s4 emit_load(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg) { codegendata *cd; + s4 disp; s4 reg; /* get required compiler data */ @@ -72,10 +74,21 @@ s4 emit_load(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg) if (IS_INMEMORY(src->flags)) { COUNT_SPILLS; - if (IS_FLT_DBL_TYPE(src->type)) - M_DLD(tempreg, REG_SP, src->vv.regoff * 8); - else - M_LLD(tempreg, REG_SP, src->vv.regoff * 8); + disp = src->vv.regoff * 8; + + switch (src->type) { + case TYPE_INT: + case TYPE_LNG: + case TYPE_ADR: + M_LLD(tempreg, REG_SP, disp); + break; + case TYPE_FLT: + case TYPE_DBL: + M_DLD(tempreg, REG_SP, disp); + break; + default: + vm_abort("emit_load: unknown type %d", src->type); + } reg = tempreg; } @@ -95,6 +108,7 @@ s4 emit_load(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg) void emit_store(jitdata *jd, instruction *iptr, varinfo *dst, s4 d) { codegendata *cd; + s4 disp; /* get required compiler data */ @@ -103,10 +117,21 @@ void emit_store(jitdata *jd, instruction *iptr, varinfo *dst, s4 d) if (IS_INMEMORY(dst->flags)) { COUNT_SPILLS; - if (IS_FLT_DBL_TYPE(dst->type)) - M_DST(d, REG_SP, dst->vv.regoff * 8); - else - M_LST(d, REG_SP, dst->vv.regoff * 8); + disp = dst->vv.regoff * 8; + + switch (dst->type) { + case TYPE_INT: + case TYPE_LNG: + case TYPE_ADR: + M_LST(d, REG_SP, disp); + break; + case TYPE_FLT: + case TYPE_DBL: + M_DST(d, REG_SP, disp); + break; + default: + vm_abort("emit_store: unknown type %d", dst->type); + } } } @@ -143,10 +168,19 @@ void emit_copy(jitdata *jd, instruction *iptr, varinfo *src, varinfo *dst) } if (s1 != d) { - if (IS_FLT_DBL_TYPE(src->type)) - M_FMOV(s1, d); - else + switch (dst->type) { + case TYPE_INT: + case TYPE_LNG: + case TYPE_ADR: M_MOV(s1, d); + break; + case TYPE_FLT: + case TYPE_DBL: + M_FMOV(s1, d); + break; + default: + vm_abort("emit_copy: unknown type %d", dst->type); + } } emit_store(jd, iptr, dst, d); @@ -192,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); } } diff --git a/src/vm/jit/alpha/linux/md-os.c b/src/vm/jit/alpha/linux/md-os.c index 8bc0aec27..ff3e765d5 100644 --- a/src/vm/jit/alpha/linux/md-os.c +++ b/src/vm/jit/alpha/linux/md-os.c @@ -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 7596 2007-03-28 21:05:53Z 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" @@ -52,14 +53,20 @@ 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; } diff --git a/src/vm/jit/alpha/md.c b/src/vm/jit/alpha/md.c index 41c63662a..1aef1bad1 100644 --- a/src/vm/jit/alpha/md.c +++ b/src/vm/jit/alpha/md.c @@ -22,7 +22,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - $Id: md.c 7304 2007-02-09 10:35:26Z twisti $ + $Id: md.c 7596 2007-03-28 21:05:53Z twisti $ */ @@ -89,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 @@ -360,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 diff --git a/src/vm/jit/alpha/patcher.c b/src/vm/jit/alpha/patcher.c index 2c37a8907..17626af79 100644 --- a/src/vm/jit/alpha/patcher.c +++ b/src/vm/jit/alpha/patcher.c @@ -22,7 +22,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - $Id: patcher.c 7483 2007-03-08 13:17:40Z michi $ + $Id: patcher.c 7596 2007-03-28 21:05:53Z 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: + + + 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; diff --git a/src/vm/jit/arm/arch.h b/src/vm/jit/arm/arch.h index 609debb24..2f0fd01c4 100644 --- a/src/vm/jit/arm/arch.h +++ b/src/vm/jit/arm/arch.h @@ -27,7 +27,7 @@ Authors: Michael Starzinger Christian Thalinger - $Id: arch.h 7241 2007-01-27 15:52:01Z twisti $ + $Id: arch.h 7596 2007-03-28 21:05:53Z twisti $ */ @@ -114,6 +114,14 @@ /* 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 diff --git a/src/vm/jit/arm/asmpart.S b/src/vm/jit/arm/asmpart.S index a866859b2..080d7ceb1 100644 --- a/src/vm/jit/arm/asmpart.S +++ b/src/vm/jit/arm/asmpart.S @@ -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 7596 2007-03-28 21:05:53Z twisti $ */ @@ -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 diff --git a/src/vm/jit/arm/codegen.c b/src/vm/jit/arm/codegen.c index 3e803686a..147798f55 100644 --- a/src/vm/jit/arm/codegen.c +++ b/src/vm/jit/arm/codegen.c @@ -22,7 +22,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - $Id: codegen.c 7353 2007-02-13 23:14:35Z twisti $ + $Id: codegen.c 7596 2007-03-28 21:05:53Z twisti $ */ @@ -71,13 +71,13 @@ #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; @@ -793,10 +792,10 @@ bool codegen(jitdata *jd) M_MOV_S(REG_ITMP1, s1); M_RSBMI_IMM(REG_ITMP1, REG_ITMP1, 0); if (IS_IMM(iptr->sx.val.i)) - M_AND_IMM(d, REG_ITMP1, iptr->sx.val.i); + M_AND_IMM(REG_ITMP1, iptr->sx.val.i, d); else { ICONST(REG_ITMP3, iptr->sx.val.i); - M_AND(d, REG_ITMP1, REG_ITMP3); + M_AND(REG_ITMP1, REG_ITMP3, d); } M_RSBMI_IMM(d, d, 0); emit_store_dst(jd, iptr, d); @@ -807,7 +806,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_AND_IMM(REG_ITMP2, s2, 0x1f); + M_AND_IMM(s2, 0x1f, REG_ITMP2); M_MOV(d, REG_LSL_REG(s1, REG_ITMP2)); emit_store_dst(jd, iptr, d); break; @@ -817,7 +816,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_AND_IMM(REG_ITMP2, s2, 0x1f); + M_AND_IMM(s2, 0x1f, REG_ITMP2); M_MOV(d, REG_ASR_REG(s1, REG_ITMP2)); emit_store_dst(jd, iptr, d); break; @@ -827,7 +826,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_AND_IMM(REG_ITMP2, s2, 0x1f); + M_AND_IMM(s2, 0x1f, REG_ITMP2); M_MOV(d, REG_LSR_REG(s1, REG_ITMP2)); emit_store_dst(jd, iptr, d); break; @@ -873,7 +872,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_AND(d, s1, s2); + M_AND(s1, s2, d); emit_store_dst(jd, iptr, d); break; @@ -882,10 +881,10 @@ bool codegen(jitdata *jd) s1 = emit_load_s1_low(jd, iptr, REG_ITMP3); s2 = emit_load_s2_low(jd, iptr, REG_ITMP1); d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED); - M_AND(GET_LOW_REG(d), s1, s2); + M_AND(s1, s2, GET_LOW_REG(d)); s1 = emit_load_s1_high(jd, iptr, REG_ITMP3); s2 = emit_load_s2_high(jd, iptr, REG_ITMP2); - M_AND(GET_HIGH_REG(d), s1, s2); + M_AND(s1, s2, GET_HIGH_REG(d)); emit_store_dst(jd, iptr, d); break; @@ -894,7 +893,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_ORR(d, s1, s2); + M_ORR(s1, s2, d); emit_store_dst(jd, iptr, d); break; @@ -903,10 +902,10 @@ bool codegen(jitdata *jd) s1 = emit_load_s1_low(jd, iptr, REG_ITMP3); s2 = emit_load_s2_low(jd, iptr, REG_ITMP1); d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED); - M_ORR(GET_LOW_REG(d), s1, s2); + M_ORR(s1, s2, GET_LOW_REG(d)); s1 = emit_load_s1_high(jd, iptr, REG_ITMP3); s2 = emit_load_s2_high(jd, iptr, REG_ITMP2); - M_ORR(GET_HIGH_REG(d), s1, s2); + M_ORR(s1, s2, GET_HIGH_REG(d)); emit_store_dst(jd, iptr, d); break; @@ -915,7 +914,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_EOR(d, s1, s2); + M_EOR(s1, s2, d); emit_store_dst(jd, iptr, d); break; @@ -924,10 +923,10 @@ bool codegen(jitdata *jd) s1 = emit_load_s1_low(jd, iptr, REG_ITMP3); s2 = emit_load_s2_low(jd, iptr, REG_ITMP1); d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED); - M_EOR(GET_LOW_REG(d), s1, s2); + M_EOR(s1, s2, GET_LOW_REG(d)); s1 = emit_load_s1_high(jd, iptr, REG_ITMP3); s2 = emit_load_s2_high(jd, iptr, REG_ITMP2); - M_EOR(GET_HIGH_REG(d), s1, s2); + M_EOR(s1, s2, GET_HIGH_REG(d)); emit_store_dst(jd, iptr, d); break; @@ -1071,7 +1070,7 @@ bool codegen(jitdata *jd) M_FIX(d, s1); /* this checks for NaN; to return zero as Java likes it */ M_CMF(s1, 0x8); - M_MOVVS_IMM(d, 0); + M_MOVVS_IMM(0, d); emit_store_dst(jd, iptr, d); break; @@ -1083,7 +1082,7 @@ bool codegen(jitdata *jd) M_FIX(d, s1); /* this checks for NaN; to return zero as Java likes it */ M_CMF(s1, 0x8); - M_MOVVS_IMM(d, 0); + M_MOVVS_IMM(0, d); emit_store_dst(jd, iptr, d); break; @@ -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,32 +1515,37 @@ 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; + + fieldtype = uf->fieldref->parseddesc.fd->type; + } + else { + fieldinfo *fi = iptr->sx.s23.s3.fmiref->p.field; + + fieldtype = fi->type; + disp = fi->offset; + } + #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)) { unresolved_field *uf = iptr->sx.s23.s3.uf; - fieldtype = uf->fieldref->parseddesc.fd->type; - - codegen_addpatchref(cd, PATCHER_get_putfield, - iptr->sx.s23.s3.uf, 0); + codegen_addpatchref(cd, PATCHER_get_putfield, uf, 0); if (opt_showdisassemble) M_NOP; disp = 0; } - else { - fieldinfo *fi = iptr->sx.s23.s3.fmiref->p.field; - - fieldtype = fi->type; - disp = fi->offset; - } switch (fieldtype) { case TYPE_INT: @@ -1611,13 +1582,7 @@ bool codegen(jitdata *jd) case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */ s1 = emit_load_s1(jd, iptr, REG_ITMP3); - gen_nullptr_check(s1); - -#if !defined(ENABLE_SOFTFLOAT) - /* HACK: softnull checks on floats */ - if (!checknull && IS_FLT_DBL_TYPE(fieldtype)) - gen_nullptr_check_intern(s1); -#endif + emit_nullpointer_check(cd, iptr, s1); if (INSTRUCTION_IS_UNRESOLVED(iptr)) { unresolved_field *uf = iptr->sx.s23.s3.uf; @@ -1631,6 +1596,12 @@ bool codegen(jitdata *jd) disp = fi->offset; } +#if !defined(ENABLE_SOFTFLOAT) + /* HACK: softnull checks on floats */ + if (!INSTRUCTION_MUST_CHECK(iptr) && IS_FLT_DBL_TYPE(fieldtype)) + emit_nullpointer_check_force(cd, iptr, s1); +#endif + switch (fieldtype) { case TYPE_INT: #if defined(ENABLE_SOFTFLOAT) @@ -1718,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 ==> ... */ @@ -1752,100 +1713,182 @@ bool codegen(jitdata *jd) case ICMD_IFNE: s1 = emit_load_s1(jd, iptr, REG_ITMP1); - M_COMPARE(s1, iptr->sx.val.i, UNCOND, 0); + M_COMPARE(s1, iptr->sx.val.i); + emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IFEQ, BRANCH_OPT_NONE); + break; - 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); + case ICMD_IF_LEQ: /* ..., value ==> ... */ + + s1 = emit_load_s1_high(jd, iptr, REG_ITMP1); + s2 = emit_load_s1_low(jd, iptr, REG_ITMP2); + if (iptr->sx.val.l == 0) { + M_ORR_S(s1, s2, REG_ITMP3); } - codegen_addreference(cd, iptr->dst.block); + else { + M_COMPARE(s1, (iptr->sx.val.l >> 32)); + /*ICONST(REG_ITMP3, iptr->sx.val.l >> 32); + M_CMP(s1, REG_ITMP3);*/ + ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff); + M_CMPEQ(s2, REG_ITMP3); + } + emit_beq(cd, iptr->dst.block); break; case ICMD_IF_LLT: /* ..., value ==> ... */ - case ICMD_IF_LLE: /* op1 = target JavaVM pc, val.l = constant */ - case ICMD_IF_LGT: - case ICMD_IF_LGE: - case ICMD_IF_LEQ: - case ICMD_IF_LNE: - /* ATTENTION: compare high words signed and low words unsigned */ + s1 = emit_load_s1_high(jd, iptr, REG_ITMP1); + s2 = emit_load_s1_low(jd, iptr, REG_ITMP2); + if (iptr->sx.val.l == 0) { + /* if high word is less than zero, the whole long is too */ + M_CMP_IMM(s1, 0); + emit_blt(cd, iptr->dst.block); + } + else { + /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */ + M_COMPARE(s1, (iptr->sx.val.l >> 32)); + /*ICONST(REG_ITMP3, iptr->sx.val.l >> 32); + M_CMP(s1, REG_ITMP3);*/ + M_EOR(REG_ITMP1, REG_ITMP1, REG_ITMP1); + M_MOVGT_IMM(2, REG_ITMP1); + M_MOVEQ_IMM(1, REG_ITMP1); + + /* low compare: x=x-1(ifLO) */ + M_COMPARE(s2, (iptr->sx.val.l & 0xffffffff)); + /*ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff); + M_CMP(s2, REG_ITMP3);*/ + M_SUBLO_IMM(REG_ITMP1, REG_ITMP1, 1); + + /* branch if (x LT 1) */ + M_CMP_IMM(REG_ITMP1, 1); + emit_blt(cd, iptr->dst.block); + } + break; + + case ICMD_IF_LLE: /* ..., value ==> ... */ s1 = emit_load_s1_high(jd, iptr, REG_ITMP1); - M_COMPARE(s1, (iptr->sx.val.l >> 32), UNCOND, 0); + s2 = emit_load_s1_low(jd, iptr, REG_ITMP2); + if (iptr->sx.val.l == 0) { + /* if high word is less than zero, the whole long is too */ + M_CMP_IMM(s1, 0); + emit_blt(cd, iptr->dst.block); - switch(iptr->opc) { - case ICMD_IF_LLT: - case ICMD_IF_LLE: - M_BLT(0); - codegen_addreference(cd, iptr->dst.block); - break; - case ICMD_IF_LGT: - case ICMD_IF_LGE: - M_BGT(0); - codegen_addreference(cd, iptr->dst.block); - break; - case ICMD_IF_LEQ: /* EQ and NE are the same for unsigned */ - case ICMD_IF_LNE: - break; - default: - assert(0); + /* ... otherwise the low word has to be zero (tricky!) */ + M_CMPEQ_IMM(s2, 0); + emit_beq(cd, iptr->dst.block); } + else { + /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */ + M_COMPARE(s1, (iptr->sx.val.l >> 32)); + /*ICONST(REG_ITMP3, iptr->sx.val.l >> 32); + M_CMP(s1, REG_ITMP3);*/ + M_EOR(REG_ITMP1, REG_ITMP1, REG_ITMP1); + M_MOVGT_IMM(2, REG_ITMP1); + M_MOVEQ_IMM(1, REG_ITMP1); - s1 = emit_load_s1_low(jd, iptr, REG_ITMP1); + /* low compare: x=x+1(ifHI) */ + M_COMPARE(s2, (iptr->sx.val.l & 0xffffffff)); + /*ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff); + M_CMP(s2, REG_ITMP3);*/ + M_ADDHI_IMM(REG_ITMP1, REG_ITMP1, 1); - switch(iptr->opc) { - case ICMD_IF_LLT: - M_COMPARE(s1, (iptr->sx.val.l & 0xffffffff), COND_EQ, 1); - M_BLO(0); - break; - case ICMD_IF_LLE: - M_COMPARE(s1, (iptr->sx.val.l & 0xffffffff), COND_EQ, 1); - M_BLS(0); - break; - case ICMD_IF_LGT: - M_COMPARE(s1, (iptr->sx.val.l & 0xffffffff), COND_EQ, 1); - M_BHI(0); - break; - case ICMD_IF_LGE: - M_COMPARE(s1, (iptr->sx.val.l & 0xffffffff), COND_EQ, 1); - M_BHS(0); - break; - case ICMD_IF_LEQ: - M_COMPARE(s1, (iptr->sx.val.l & 0xffffffff), COND_EQ, 0); - M_BEQ(0); - break; - case ICMD_IF_LNE: - M_COMPARE(s1, (iptr->sx.val.l & 0xffffffff), COND_EQ, 0); + /* branch if (x LE 1) */ + M_CMP_IMM(REG_ITMP1, 1); + emit_ble(cd, iptr->dst.block); + } + break; + + case ICMD_IF_LGE: /* ..., value ==> ... */ + + s1 = emit_load_s1_high(jd, iptr, REG_ITMP1); + s2 = emit_load_s1_low(jd, iptr, REG_ITMP2); + if (iptr->sx.val.l == 0) { + /* if high word is greater or equal zero, the whole long is too */ + M_CMP_IMM(s1, 0); + emit_bge(cd, iptr->dst.block); + } + else { + /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */ + M_COMPARE(s1, (iptr->sx.val.l >> 32)); + /*ICONST(REG_ITMP3, iptr->sx.val.l >> 32); + M_CMP(s1, REG_ITMP3);*/ + M_EOR(REG_ITMP1, REG_ITMP1, REG_ITMP1); + M_MOVGT_IMM(2, REG_ITMP1); + M_MOVEQ_IMM(1, REG_ITMP1); + + /* low compare: x=x-1(ifLO) */ + M_COMPARE(s2, (iptr->sx.val.l & 0xffffffff)); + /*ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff); + M_CMP(s2, REG_ITMP3);*/ + M_SUBLO_IMM(REG_ITMP1, REG_ITMP1, 1); + + /* branch if (x GE 1) */ + M_CMP_IMM(REG_ITMP1, 1); + emit_bge(cd, iptr->dst.block); + } + break; + + case ICMD_IF_LGT: /* ..., value ==> ... */ + + s1 = emit_load_s1_high(jd, iptr, REG_ITMP1); + s2 = emit_load_s1_low(jd, iptr, REG_ITMP2); +#if 0 + if (iptr->sx.val.l == 0) { + /* if high word is greater than zero, the whole long is too */ + M_CMP_IMM(s1, 0); + M_BGT(0); + codegen_add_branch_ref(cd, iptr->dst.block); + + /* ... or high was zero and low is non zero (tricky!) */ + M_EOR(REG_ITMP3, REG_ITMP3, REG_ITMP3); + M_MOVLT_IMM(1, REG_ITMP3); + M_ORR_S(REG_ITMP3, s2, REG_ITMP3); M_BNE(0); - break; - default: - assert(0); + codegen_add_branch_ref(cd, iptr->dst.block); } - codegen_addreference(cd, iptr->dst.block); + else { +#endif + /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */ + M_COMPARE(s1, (iptr->sx.val.l >> 32)); + /*ICONST(REG_ITMP3, iptr->sx.val.l >> 32); + M_CMP(s1, REG_ITMP3);*/ + M_EOR(REG_ITMP1, REG_ITMP1, REG_ITMP1); + M_MOVGT_IMM(2, REG_ITMP1); + M_MOVEQ_IMM(1, REG_ITMP1); + + /* low compare: x=x+1(ifHI) */ + M_COMPARE(s2, (iptr->sx.val.l & 0xffffffff)); + /*ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff); + M_CMP(s2, REG_ITMP3);*/ + M_ADDHI_IMM(REG_ITMP1, REG_ITMP1, 1); + + /* branch if (x GT 1) */ + M_CMP_IMM(REG_ITMP1, 1); + emit_bgt(cd, iptr->dst.block); +#if 0 + } +#endif break; + case ICMD_IF_LNE: /* ..., value ==> ... */ + + s1 = emit_load_s1_high(jd, iptr, REG_ITMP1); + s2 = emit_load_s1_low(jd, iptr, REG_ITMP2); + if (iptr->sx.val.l == 0) { + M_ORR_S(s1, s2, REG_ITMP3); + } + else { + M_COMPARE(s1, (iptr->sx.val.l >> 32)); + /*ICONST(REG_ITMP3, iptr->sx.val.l >> 32); + M_CMP(s1, REG_ITMP3);*/ + ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff); + M_CMPEQ(s2, REG_ITMP3); + } + 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: @@ -1854,99 +1897,132 @@ 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 ==> ... */ - case ICMD_IF_LCMPNE: /* op1 = target JavaVM pc */ - case ICMD_IF_LCMPLT: - case ICMD_IF_LCMPLE: - case ICMD_IF_LCMPGT: - case ICMD_IF_LCMPGE: + /* op1 = target JavaVM pc */ - /* ATTENTION: compare high words signed and low words unsigned */ s1 = emit_load_s1_high(jd, iptr, REG_ITMP1); s2 = emit_load_s2_high(jd, iptr, REG_ITMP2); M_CMP(s1, s2); - switch(iptr->opc) { - case ICMD_IF_LCMPEQ: /* EQ and NE are the same for unsigned */ - case ICMD_IF_LCMPNE: - break; - case ICMD_IF_LCMPLT: - case ICMD_IF_LCMPLE: - M_BLT(0); - codegen_addreference(cd, iptr->dst.block); - break; - case ICMD_IF_LCMPGT: - case ICMD_IF_LCMPGE: - M_BGT(0); - codegen_addreference(cd, iptr->dst.block); - break; - default: - assert(0); - } + s1 = emit_load_s1_low(jd, iptr, REG_ITMP1); + s2 = emit_load_s2_low(jd, iptr, REG_ITMP2); + M_CMPEQ(s1, s2); + + emit_beq(cd, iptr->dst.block); + break; + + case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */ + /* op1 = target JavaVM pc */ + + s1 = emit_load_s1_high(jd, iptr, REG_ITMP1); + s2 = emit_load_s2_high(jd, iptr, REG_ITMP2); + M_CMP(s1, s2); s1 = emit_load_s1_low(jd, iptr, REG_ITMP1); s2 = emit_load_s2_low(jd, iptr, REG_ITMP2); + M_CMPEQ(s1, s2); - switch(iptr->opc) { - case ICMD_IF_LCMPEQ: - M_DAT(COND_EQ,0x0a,0,s1,1,0,s2); - M_BEQ(0); - break; - case ICMD_IF_LCMPNE: - M_DAT(COND_EQ,0x0a,0,s1,1,0,s2); - M_BNE(0); - break; - case ICMD_IF_LCMPLT: - M_BNE(1); - M_CMP(s1, s2); - M_BLO(0); - break; - case ICMD_IF_LCMPLE: - M_BNE(1); - M_CMP(s1, s2); - M_BLS(0); - break; - case ICMD_IF_LCMPGT: - M_BNE(1); - M_CMP(s1, s2); - M_BHI(0); - break; - case ICMD_IF_LCMPGE: - M_BNE(1); - M_CMP(s1, s2); - M_BHS(0); - break; - default: - assert(0); - } - codegen_addreference(cd, iptr->dst.block); + emit_bne(cd, iptr->dst.block); + break; + + case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */ + /* op1 = target JavaVM pc */ + + /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */ + s1 = emit_load_s1_high(jd, iptr, REG_ITMP1); + s2 = emit_load_s2_high(jd, iptr, REG_ITMP2); + M_CMP(s1, s2); + M_EOR(REG_ITMP3, REG_ITMP3, REG_ITMP3); + M_MOVGT_IMM(2, REG_ITMP3); + M_MOVEQ_IMM(1, REG_ITMP3); + + /* low compare: x=x-1(ifLO) */ + s1 = emit_load_s1_low(jd, iptr, REG_ITMP1); + s2 = emit_load_s2_low(jd, iptr, REG_ITMP2); + M_CMP(s1, s2); + M_SUBLO_IMM(REG_ITMP3, REG_ITMP3, 1); + + /* branch if (x LT 1) */ + M_CMP_IMM(REG_ITMP3, 1); + emit_blt(cd, iptr->dst.block); + break; + + case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */ + /* op1 = target JavaVM pc */ + + /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */ + s1 = emit_load_s1_high(jd, iptr, REG_ITMP1); + s2 = emit_load_s2_high(jd, iptr, REG_ITMP2); + M_CMP(s1, s2); + M_EOR(REG_ITMP3, REG_ITMP3, REG_ITMP3); + M_MOVGT_IMM(2, REG_ITMP3); + M_MOVEQ_IMM(1, REG_ITMP3); + + /* low compare: x=x-1(ifLO) */ + s1 = emit_load_s1_low(jd, iptr, REG_ITMP1); + s2 = emit_load_s2_low(jd, iptr, REG_ITMP2); + M_CMP(s1, s2); + M_ADDHI_IMM(REG_ITMP3, REG_ITMP3, 1); + + /* branch if (x LE 1) */ + M_CMP_IMM(REG_ITMP3, 1); + emit_ble(cd, iptr->dst.block); + break; + + case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */ + /* op1 = target JavaVM pc */ + + /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */ + s1 = emit_load_s1_high(jd, iptr, REG_ITMP1); + s2 = emit_load_s2_high(jd, iptr, REG_ITMP2); + M_CMP(s1, s2); + M_EOR(REG_ITMP3, REG_ITMP3, REG_ITMP3); + M_MOVGT_IMM(2, REG_ITMP3); + M_MOVEQ_IMM(1, REG_ITMP3); + + /* low compare: x=x-1(ifLO) */ + s1 = emit_load_s1_low(jd, iptr, REG_ITMP1); + s2 = emit_load_s2_low(jd, iptr, REG_ITMP2); + M_CMP(s1, s2); + M_ADDHI_IMM(REG_ITMP3, REG_ITMP3, 1); + + /* branch if (x GT 1) */ + M_CMP_IMM(REG_ITMP3, 1); + emit_bgt(cd, iptr->dst.block); + break; + + case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */ + /* op1 = target JavaVM pc */ + + /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */ + s1 = emit_load_s1_high(jd, iptr, REG_ITMP1); + s2 = emit_load_s2_high(jd, iptr, REG_ITMP2); + M_CMP(s1, s2); + M_EOR(REG_ITMP3, REG_ITMP3, REG_ITMP3); + M_MOVGT_IMM(2, REG_ITMP3); + M_MOVEQ_IMM(1, REG_ITMP3); + + /* low compare: x=x-1(ifLO) */ + s1 = emit_load_s1_low(jd, iptr, REG_ITMP1); + s2 = emit_load_s2_low(jd, iptr, REG_ITMP2); + M_CMP(s1, s2); + M_SUBLO_IMM(REG_ITMP3, REG_ITMP3, 1); + + /* branch if (x GE 1) */ + M_CMP_IMM(REG_ITMP3, 1); + emit_bge(cd, iptr->dst.block); break; case ICMD_TABLESWITCH: /* ..., index ==> ... */ @@ -1972,9 +2048,8 @@ bool codegen(jitdata *jd) /* range check (index <= high-low) */ i = i - l + 1; - M_COMPARE(REG_ITMP1, i-1, UNCOND, 0); - M_BHI(0); /* unsigned greater than */ - codegen_addreference(cd, table[0].block); + M_COMPARE(REG_ITMP1, i-1); + emit_bugt(cd, table[0].block); /* build jump table top down and use address of lowest entry */ @@ -2006,15 +2081,13 @@ bool codegen(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_ITMP1); while (--i >= 0) { - M_COMPARE(s1, lookup->value, UNCOND, 0); - M_BEQ(0); - codegen_addreference(cd, lookup->target.block); + M_COMPARE(s1, lookup->value); + 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; @@ -2215,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: @@ -2238,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); @@ -2255,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); @@ -2278,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 */ - - 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 */ + /* generate the actual call */ - 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 */ @@ -2357,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; @@ -2379,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, @@ -2393,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 */ @@ -2410,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); - - if (super == NULL) { - M_B(0); - branch3 = cd->mcodeptr; - } - } + emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ITMP3, s1); - 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, @@ -2457,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)); @@ -2475,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); @@ -2520,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); } @@ -2535,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; @@ -2562,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, @@ -2577,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 */ @@ -2600,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)); @@ -2616,23 +2679,20 @@ bool codegen(jitdata *jd) M_LDR_INTERN(REG_ITMP3, REG_ITMP1, s2); M_TST(REG_ITMP3, REG_ITMP3); - M_MOVNE_IMM(d, 1); + 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, @@ -2647,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)); @@ -2667,17 +2726,15 @@ bool codegen(jitdata *jd) /* If d == REG_ITMP2, then it's destroyed */ if (d == REG_ITMP2) M_EOR(d, d, d); - M_MOVLS_IMM(d, 1); - } + 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); } } @@ -2742,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 */ @@ -2756,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: @@ -2774,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; @@ -3078,7 +3128,7 @@ u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd) /* check for exception */ M_TST(REG_ITMP1_XPTR, REG_ITMP1_XPTR); - M_MOVEQ(REG_PC, REG_LR); /* if no exception, return to caller */ + M_MOVEQ(REG_LR, REG_PC); /* if no exception, return to caller */ /* handle exception here */ diff --git a/src/vm/jit/arm/codegen.h b/src/vm/jit/arm/codegen.h index a23496151..bd7ea006c 100644 --- a/src/vm/jit/arm/codegen.h +++ b/src/vm/jit/arm/codegen.h @@ -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 7276 2007-02-02 11:58:18Z michi $ + $Id: codegen.h 7596 2007-03-28 21:05:53Z twisti $ */ @@ -40,74 +40,6 @@ /* 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 ********************************************************************** @@ -453,15 +394,16 @@ void asm_debug_intern(int a1, int a2, int a3, int a4); #define M_ADC(d,a,b) M_DAT(UNCOND,0x05,d,a,0,0,b) /* d = a + b (with Carry) */ #define M_SUB(d,a,b) M_DAT(UNCOND,0x02,d,a,0,0,b) /* d = a - b */ #define M_SBC(d,a,b) M_DAT(UNCOND,0x06,d,a,0,0,b) /* d = a - b (with Carry) */ -#define M_AND(d,a,b) M_DAT(UNCOND,0x00,d,a,0,0,b) /* d = a & b */ -#define M_ORR(d,a,b) M_DAT(UNCOND,0x0c,d,a,0,0,b) /* d = a | b */ -#define M_EOR(d,a,b) M_DAT(UNCOND,0x01,d,a,0,0,b) /* d = a ^ b */ +#define M_AND(a,b,d) M_DAT(UNCOND,0x00,d,a,0,0,b) /* d = a & b */ +#define M_ORR(a,b,d) M_DAT(UNCOND,0x0c,d,a,0,0,b) /* d = a | b */ +#define M_EOR(a,b,d) M_DAT(UNCOND,0x01,d,a,0,0,b) /* d = a ^ b */ #define M_TST(a,b) M_DAT(UNCOND,0x08,0,a,1,0,b) /* TST a & b */ #define M_TEQ(a,b) M_DAT(UNCOND,0x09,0,a,1,0,b) /* TST a ^ b */ #define M_CMP(a,b) M_DAT(UNCOND,0x0a,0,a,1,0,b) /* TST a - b */ #define M_MOV(d,b) M_DAT(UNCOND,0x0d,d,0,0,0,b) /* d = b */ #define M_ADD_S(d,a,b) M_DAT(UNCOND,0x04,d,a,1,0,b) /* d = a + b (update Flags) */ #define M_SUB_S(d,a,b) M_DAT(UNCOND,0x02,d,a,1,0,b) /* d = a - b (update Flags) */ +#define M_ORR_S(a,b,d) M_DAT(UNCOND,0x0c,d,a,1,0,b) /* d = a | b (update flags) */ #define M_MOV_S(d,b) M_DAT(UNCOND,0x0d,d,0,1,0,b) /* d = b (update Flags) */ #define M_ADD_IMM(d,a,i) M_DAT(UNCOND,0x04,d,a,0,1,i) /* d = a + i */ @@ -470,7 +412,7 @@ void asm_debug_intern(int a1, int a2, int a3, int a4); #define M_SBC_IMM(d,a,i) M_DAT(UNCOND,0x06,d,a,0,1,i) /* d = a - i (with Carry) */ #define M_RSB_IMM(d,a,i) M_DAT(UNCOND,0x03,d,a,0,1,i) /* d = -a + i */ #define M_RSC_IMM(d,a,i) M_DAT(UNCOND,0x07,d,a,0,1,i) /* d = -a + i (with Carry) */ -#define M_AND_IMM(d,a,i) M_DAT(UNCOND,0x00,d,a,0,1,i) /* d = a & i */ +#define M_AND_IMM(a,i,d) M_DAT(UNCOND,0x00,d,a,0,1,i) /* d = a & i */ #define M_TST_IMM(a,i) M_DAT(UNCOND,0x08,0,a,1,1,i) /* TST a & i */ #define M_TEQ_IMM(a,i) M_DAT(UNCOND,0x09,0,a,1,1,i) /* TST a ^ i */ #define M_CMP_IMM(a,i) M_DAT(UNCOND,0x0a,0,a,1,1,i) /* TST a - i */ @@ -481,17 +423,29 @@ void asm_debug_intern(int a1, int a2, int a3, int a4); #define M_RSB_IMMS(d,a,i) M_DAT(UNCOND,0x03,d,a,1,1,i) /* d = -a + i (update Flags) */ #define M_ADDSUB_IMM(d,a,i) if((i)>=0) M_ADD_IMM(d,a,i); else M_SUB_IMM(d,a,-(i)) -#define M_MOVEQ(d,b) M_DAT(COND_EQ,0x0d,d,0,0,0,b) -#define M_MOVVS_IMM(d,i) M_DAT(COND_VS,0x0d,d,0,0,1,i) -#define M_MOVNE_IMM(d,i) M_DAT(COND_NE,0x0d,d,0,0,1,i) -#define M_MOVLS_IMM(d,i) M_DAT(COND_LS,0x0d,d,0,0,1,i) +#define M_MOVEQ(a,d) M_DAT(COND_EQ,0x0d,d,0,0,0,a) + +#define M_MOVVS_IMM(i,d) M_DAT(COND_VS,0x0d,d,0,0,1,i) +#define M_MOVEQ_IMM(i,d) M_DAT(COND_EQ,0x0d,d,0,0,1,i) +#define M_MOVNE_IMM(i,d) M_DAT(COND_NE,0x0d,d,0,0,1,i) +#define M_MOVLT_IMM(i,d) M_DAT(COND_LT,0x0d,d,0,0,1,i) +#define M_MOVGT_IMM(i,d) M_DAT(COND_GT,0x0d,d,0,0,1,i) +#define M_MOVLS_IMM(i,d) M_DAT(COND_LS,0x0d,d,0,0,1,i) + +#define M_ADDHI_IMM(d,a,i) M_DAT(COND_HI,0x04,d,a,0,1,i) #define M_ADDLT_IMM(d,a,i) M_DAT(COND_LT,0x04,d,a,0,1,i) #define M_ADDGT_IMM(d,a,i) M_DAT(COND_GT,0x04,d,a,0,1,i) +#define M_SUBLO_IMM(d,a,i) M_DAT(COND_CC,0x02,d,a,0,1,i) #define M_SUBLT_IMM(d,a,i) M_DAT(COND_LT,0x02,d,a,0,1,i) #define M_SUBGT_IMM(d,a,i) M_DAT(COND_GT,0x02,d,a,0,1,i) #define M_RSBMI_IMM(d,a,i) M_DAT(COND_MI,0x03,d,a,0,1,i) #define M_ADCMI_IMM(d,a,i) M_DAT(COND_MI,0x05,d,a,0,1,i) +#define M_CMPEQ(a,b) M_DAT(COND_EQ,0x0a,0,a,1,0,b) /* TST a - b */ +#define M_CMPLE(a,b) M_DAT(COND_LE,0x0a,0,a,1,0,b) /* TST a - b */ + +#define M_CMPEQ_IMM(a,i) M_DAT(COND_EQ,0x0a,0,a,1,1,i) + #define M_MUL(d,a,b) M_MULT(UNCOND,d,a,b,0,0,0x0) /* d = a * b */ @@ -651,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" */ @@ -1070,18 +1030,14 @@ do { \ uses M_CMP or M_CMP_IMM to do the compare ATTENTION: uses REG_ITMP3 as intermediate register */ -/* TODO: improve this and add some comments! */ -#define M_COMPARE(reg, val, cond, overjump) \ +#define M_COMPARE(reg, val) \ if (IS_IMM(val)) { \ - if (overjump) M_BNE(1); \ - /* M_CMP_IMM */ M_DAT(cond,0x0a,0,(reg),1,1,(val)); \ + M_CMP_IMM(reg, (val)); \ } else if(IS_IMM(-(val))) { \ - if (overjump) M_BNE(1); \ - /* M_CMN_IMM */ M_DAT(cond,0x0b,0,(reg),1,1,-(val)); \ + M_CMN_IMM(reg, -(val)); \ } else { \ ICONST(REG_ITMP3, (val)); \ - if (overjump) M_BNE(1); \ - /* M_CMP */ M_DAT(cond,0x0a,0,(reg),1,0,REG_ITMP3); \ + M_CMP(reg, REG_ITMP3); \ } /* M_LONGBRANCH: @@ -1113,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) @@ -1163,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 */ diff --git a/src/vm/jit/arm/emit.c b/src/vm/jit/arm/emit.c index c5ab738d8..7bcb3e754 100644 --- a/src/vm/jit/arm/emit.c +++ b/src/vm/jit/arm/emit.c @@ -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 ********************************************************** @@ -691,12 +836,15 @@ void emit_verbosecall_enter(jitdata *jd) } } else { - s1 = md->params[i].regoff + stackframesize; + s1 = REG_ITMP12_PACKED; + s2 = md->params[i].regoff + stackframesize; if (IS_2_WORD_TYPE(t)) - M_LLD(REG_ITMP12_PACKED, REG_SP, s1 * 4); - else - M_ILD(REG_ITMP1, REG_SP, s1 * 4); + M_LLD(s1, REG_SP, s2 * 4); + else { + M_ILD(GET_LOW_REG(s1), REG_SP, s2 * 4); + M_MOV_IMM(GET_HIGH_REG(s1), 0); + } } /* place argument for tracer */ diff --git a/src/vm/jit/arm/linux/Makefile.am b/src/vm/jit/arm/linux/Makefile.am index a27158890..c4a5d85ae 100644 --- a/src/vm/jit/arm/linux/Makefile.am +++ b/src/vm/jit/arm/linux/Makefile.am @@ -32,7 +32,7 @@ ## Process this file with automake to produce Makefile.in -AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/src/vm/jit/$(ARCH_DIR) +AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/src/vm/jit/$(ARCH_DIR) -I$(top_builddir)/src noinst_LTLIBRARIES = libmd.la diff --git a/src/vm/jit/arm/linux/md-os.c b/src/vm/jit/arm/linux/md-os.c index c47708555..b169ff454 100644 --- a/src/vm/jit/arm/linux/md-os.c +++ b/src/vm/jit/arm/linux/md-os.c @@ -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 @@ -22,11 +22,6 @@ 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 diff --git a/src/vm/jit/arm/md.c b/src/vm/jit/arm/md.c index d11f44643..066ed4113 100644 --- a/src/vm/jit/arm/md.c +++ b/src/vm/jit/arm/md.c @@ -22,7 +22,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - $Id: md.c 7259 2007-01-30 13:58:35Z twisti $ + $Id: md.c 7596 2007-03-28 21:05:53Z twisti $ */ @@ -41,6 +41,8 @@ #include "vm/jit/asmpart.h" #include "vm/jit/md.h" +#include "vm/jit/codegen-common.h" /* REMOVE ME: for codegendata */ + /* md_init ********************************************************************* @@ -76,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); diff --git a/src/vm/jit/asmpart.h b/src/vm/jit/asmpart.h index 2a4a2395f..c527ec0f8 100644 --- a/src/vm/jit/asmpart.h +++ b/src/vm/jit/asmpart.h @@ -22,7 +22,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - $Id: asmpart.h 7338 2007-02-13 00:17:22Z twisti $ + $Id: asmpart.h 7596 2007-03-28 21:05:53Z twisti $ */ @@ -73,15 +73,6 @@ #endif /* defined(ENABLE_JIT) */ -typedef struct castinfo castinfo; - -struct castinfo { - s4 super_baseval; - s4 super_diffval; - s4 sub_baseval; -}; - - /* function prototypes ********************************************************/ /* machine dependent initialization */ @@ -104,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) diff --git a/src/vm/jit/code.c b/src/vm/jit/code.c index baccfd493..82c6ff64a 100644 --- a/src/vm/jit/code.c +++ b/src/vm/jit/code.c @@ -92,10 +92,6 @@ codeinfo *code_codeinfo_new(methodinfo *m) code->m = m; -#if defined(ENABLE_THREADS) - lock_init_object_lock(&code->header); -#endif - #if defined(ENABLE_STATISTICS) if (opt_stat) size_codeinfo += sizeof(codeinfo); diff --git a/src/vm/jit/code.h b/src/vm/jit/code.h index 302428c75..fd46f72c6 100644 --- a/src/vm/jit/code.h +++ b/src/vm/jit/code.h @@ -61,7 +61,6 @@ struct codeinfo { methodinfo *m; /* method this is a realization of */ - java_objectheader header; /* we need this in JIT's monitorenter */ codeinfo *prev; /* previous codeinfo of this method */ u4 codeflags; /* or of CODE_FLAG_ constants */ diff --git a/src/vm/jit/codegen-common.c b/src/vm/jit/codegen-common.c index 47999c1aa..9d81474fc 100644 --- a/src/vm/jit/codegen-common.c +++ b/src/vm/jit/codegen-common.c @@ -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 7489 2007-03-08 17:12:56Z michi $ + $Id: codegen-common.c 7601 2007-03-28 23:02:50Z michi $ */ @@ -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); diff --git a/src/vm/jit/codegen-common.h b/src/vm/jit/codegen-common.h index c23ceef8b..11612d10b 100644 --- a/src/vm/jit/codegen-common.h +++ b/src/vm/jit/codegen-common.h @@ -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 7596 2007-03-28 21:05:53Z 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 */ diff --git a/src/vm/jit/disass-common.c b/src/vm/jit/disass-common.c index 0371ca0a2..725563674 100644 --- a/src/vm/jit/disass-common.c +++ b/src/vm/jit/disass-common.c @@ -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 7596 2007-03-28 21:05:53Z twisti $ */ @@ -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); diff --git a/src/vm/jit/disass.h b/src/vm/jit/disass.h index 5cb3de9b0..cf7c92291 100644 --- a/src/vm/jit/disass.h +++ b/src/vm/jit/disass.h @@ -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 7596 2007-03-28 21:05:53Z twisti $ */ @@ -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 diff --git a/src/vm/jit/dseg.c b/src/vm/jit/dseg.c index 9a2d3b2e6..02400e62c 100644 --- a/src/vm/jit/dseg.c +++ b/src/vm/jit/dseg.c @@ -30,7 +30,7 @@ Joseph Wenninger Edwin Steiner - $Id: dseg.c 7283 2007-02-04 19:41:14Z pm $ + $Id: dseg.c 7596 2007-03-28 21:05:53Z twisti $ */ @@ -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; diff --git a/src/vm/jit/dseg.h b/src/vm/jit/dseg.h index e0f6a9d4f..c313e873d 100644 --- a/src/vm/jit/dseg.h +++ b/src/vm/jit/dseg.h @@ -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 7596 2007-03-28 21:05:53Z twisti $ */ @@ -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 diff --git a/src/vm/jit/emit-common.c b/src/vm/jit/emit-common.c index 2810994f5..243109adc 100644 --- a/src/vm/jit/emit-common.c +++ b/src/vm/jit/emit-common.c @@ -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 diff --git a/src/vm/jit/emit-common.h b/src/vm/jit/emit-common.h index a3f0cac0f..61681eefe 100644 --- a/src/vm/jit/emit-common.h +++ b/src/vm/jit/emit-common.h @@ -33,10 +33,21 @@ #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); diff --git a/src/vm/jit/i386/arch.h b/src/vm/jit/i386/arch.h index 05472fef3..bbda7d6af 100644 --- a/src/vm/jit/i386/arch.h +++ b/src/vm/jit/i386/arch.h @@ -22,11 +22,7 @@ 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 7596 2007-03-28 21:05:53Z twisti $ */ @@ -119,6 +115,14 @@ /* 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 diff --git a/src/vm/jit/i386/asmpart.S b/src/vm/jit/i386/asmpart.S index 92f75974e..b230622ab 100644 --- a/src/vm/jit/i386/asmpart.S +++ b/src/vm/jit/i386/asmpart.S @@ -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 7596 2007-03-28 21:05:53Z twisti $ */ @@ -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 diff --git a/src/vm/jit/i386/codegen.c b/src/vm/jit/i386/codegen.c index 32f9f94b8..a15b6d957 100644 --- a/src/vm/jit/i386/codegen.c +++ b/src/vm/jit/i386/codegen.c @@ -22,7 +22,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - $Id: codegen.c 7483 2007-03-08 13:17:40Z michi $ + $Id: codegen.c 7601 2007-03-28 23:02:50Z michi $ */ @@ -77,7 +77,7 @@ #include "vmcore/utf8.h" -/* codegen ********************************************************************* +/* codegen_emit **************************************************************** Generates machine code. @@ -89,7 +89,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; @@ -104,8 +104,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; @@ -123,11 +125,12 @@ bool codegen(jitdata *jd) /* prevent compiler warnings */ - d = 0; + s1 = 0; + s2 = 0; + d = 0; currentline = 0; - lm = NULL; - bte = NULL; - s2 = 0; + lm = NULL; + bte = NULL; { s4 i, p, t, l; @@ -377,8 +380,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 +629,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 +1919,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 +1929,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 +1941,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 +1953,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 +1965,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 +1977,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 +1996,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 +2007,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 +2018,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 +2030,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 +2046,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 +2057,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 +2068,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 +2079,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 +2097,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 +2107,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 +2118,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 +2139,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 +2149,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 +2159,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 +2169,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 +2179,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 +2193,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 +2203,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 +2245,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 +2287,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 +2330,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 +2394,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 +2435,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 +2473,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 +2494,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 +2537,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 +2547,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 +2582,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 +2602,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 +2647,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 +2661,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 +2669,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 +2682,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 +2695,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 +2708,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 +2741,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 +2863,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 +2901,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 +2985,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 +3000,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 +3021,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 +3045,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 +3137,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 +3156,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 +3203,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 +3230,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 +3252,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 +3260,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 +3307,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 +3362,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 +3401,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 +3442,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 +3467,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 +3513,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 +3827,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); diff --git a/src/vm/jit/i386/codegen.h b/src/vm/jit/i386/codegen.h index 35101a9f6..ccd69f58c 100644 --- a/src/vm/jit/i386/codegen.h +++ b/src/vm/jit/i386/codegen.h @@ -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 @@ -22,12 +22,7 @@ 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 7596 2007-03-28 21:05:53Z twisti $ */ @@ -139,6 +134,9 @@ /* 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; \ @@ -146,6 +144,7 @@ M_NOP; \ M_NOP; \ M_NOP; \ + M_NOP; \ } while (0) @@ -171,6 +170,14 @@ #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); \ diff --git a/src/vm/jit/i386/emit.c b/src/vm/jit/i386/emit.c index 5ff1011f4..5683320d8 100644 --- a/src/vm/jit/i386/emit.c +++ b/src/vm/jit/i386/emit.c @@ -22,7 +22,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - $Id: emit.c 7483 2007-03-08 13:17:40Z michi $ + $Id: emit.c 7596 2007-03-28 21:05:53Z twisti $ */ @@ -44,6 +44,7 @@ #endif #include "vm/builtin.h" +#include "vm/exceptions.h" #include "vm/jit/asmpart.h" #include "vm/jit/dseg.h" @@ -76,17 +77,22 @@ inline s4 emit_load(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg) disp = src->vv.regoff * 4; - 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); + switch (src->type) { + case TYPE_INT: + case TYPE_ADR: + M_ILD(tempreg, REG_SP, disp); + break; + case TYPE_LNG: + M_LLD(tempreg, REG_SP, disp); + break; + case TYPE_FLT: + M_FLD(tempreg, REG_SP, disp); + break; + case TYPE_DBL: + M_DLD(tempreg, REG_SP, disp); + break; + default: + vm_abort("emit_load: unknown type %d", src->type); } reg = tempreg; @@ -176,6 +182,7 @@ inline s4 emit_load_high(jitdata *jd, instruction *iptr,varinfo *src,s4 tempreg) inline void emit_store(jitdata *jd, instruction *iptr, varinfo *dst, s4 d) { codegendata *cd; + s4 disp; /* get required compiler data */ @@ -184,17 +191,24 @@ inline void emit_store(jitdata *jd, instruction *iptr, varinfo *dst, s4 d) if (IS_INMEMORY(dst->flags)) { COUNT_SPILLS; - if (IS_FLT_DBL_TYPE(dst->type)) { - if (IS_2_WORD_TYPE(dst->type)) - M_DST(d, REG_SP, dst->vv.regoff * 4); - else - M_FST(d, REG_SP, dst->vv.regoff * 4); - } - else { - if (IS_2_WORD_TYPE(dst->type)) - M_LST(d, REG_SP, dst->vv.regoff * 4); - else - M_IST(d, REG_SP, dst->vv.regoff * 4); + disp = dst->vv.regoff * 4; + + switch (dst->type) { + case TYPE_INT: + case TYPE_ADR: + M_IST(d, REG_SP, disp); + break; + case TYPE_LNG: + M_LST(d, REG_SP, disp); + break; + case TYPE_FLT: + M_FST(d, REG_SP, disp); + break; + case TYPE_DBL: + M_DST(d, REG_SP, disp); + break; + default: + vm_abort("emit_store: unknown type %d", dst->type); } } } @@ -288,13 +302,20 @@ void emit_copy(jitdata *jd, instruction *iptr, varinfo *src, varinfo *dst) } if (s1 != d) { - if (IS_FLT_DBL_TYPE(src->type)) { + switch (src->type) { + case TYPE_INT: + case TYPE_ADR: + M_MOV(s1, d); + break; + case TYPE_LNG: + M_LNGMOVE(s1, d); + break; + case TYPE_FLT: + case TYPE_DBL: /* M_FMOV(s1, d); */ - } else { - if (IS_2_WORD_TYPE(src->type)) - M_LNGMOVE(s1, d); - else - M_MOV(s1, d); + break; + default: + vm_abort("emit_copy: unknown type %d", src->type); } } @@ -303,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. @@ -313,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); } } @@ -330,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); } } @@ -344,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); + } } @@ -358,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); } } diff --git a/src/vm/jit/i386/linux/md-os.c b/src/vm/jit/i386/linux/md-os.c index 272eb3b1e..e267c11cb 100644 --- a/src/vm/jit/i386/linux/md-os.c +++ b/src/vm/jit/i386/linux/md-os.c @@ -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 @@ -22,13 +22,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - Contact: cacao@cacaojvm.org - - Authors: Christian Thalinger - - Changes: - - $Id: md-os.c 7496 2007-03-12 00:19:05Z michi $ + $Id: md-os.c 7601 2007-03-28 23:02:50Z michi $ */ @@ -48,35 +42,82 @@ #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; } diff --git a/src/vm/jit/i386/md.c b/src/vm/jit/i386/md.c index 91aaf4128..06f036cd3 100644 --- a/src/vm/jit/i386/md.c +++ b/src/vm/jit/i386/md.c @@ -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 @@ -22,12 +22,7 @@ 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 7596 2007-03-28 21:05:53Z 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 diff --git a/src/vm/jit/i386/patcher.c b/src/vm/jit/i386/patcher.c index 297a9902b..db1c9a831 100644 --- a/src/vm/jit/i386/patcher.c +++ b/src/vm/jit/i386/patcher.c @@ -22,7 +22,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - $Id: patcher.c 7483 2007-03-08 13:17:40Z michi $ + $Id: patcher.c 7596 2007-03-28 21:05:53Z 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: + + + 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 */ diff --git a/src/vm/jit/jit.c b/src/vm/jit/jit.c index 647208c91..6c97bc6f3 100644 --- a/src/vm/jit/jit.c +++ b/src/vm/jit/jit.c @@ -22,7 +22,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - $Id: jit.c 7483 2007-03-08 13:17:40Z michi $ + $Id: jit.c 7596 2007-03-28 21:05:53Z twisti $ */ @@ -936,28 +936,25 @@ static u1 *do_nothing_function(void) *******************************************************************************/ -jitdata *jit_jitdata_new(codeinfo *code) +jitdata *jit_jitdata_new(methodinfo *m) { - jitdata *jd; - methodinfo *m; - - /* get required compiler data */ - - m = code->m; + jitdata *jd; /* allocate jitdata structure and fill it */ jd = DNEW(jitdata); - jd->m = code->m; - jd->code = code; - + jd->m = m; jd->cd = DNEW(codegendata); jd->rd = DNEW(registerdata); #if defined(ENABLE_LOOP) jd->ld = DNEW(loopdata); #endif + /* Allocate codeinfo memory from the heap as we need to keep them. */ + + jd->code = code_codeinfo_new(m); + /* initialize variables */ jd->flags = 0; @@ -991,10 +988,9 @@ static u1 *jit_compile_intern(jitdata *jd); u1 *jit_compile(methodinfo *m) { - jitdata *jd; - codeinfo *code; - s4 dumpsize; - u1 *r; + u1 *r; + jitdata *jd; + s4 dumpsize; STATISTICS(count_jit_calls++); @@ -1019,27 +1015,16 @@ u1 *jit_compile(methodinfo *m) return m->code->entrypoint; } - /* We create a codeinfo here and lock on this object, as a object - header in the methodinfo uses to much memory. */ - - code = code_codeinfo_new(m); + /* enter a monitor on the method */ - /* enter a monitor on the codeinfo */ + LOCK_MONITOR_ENTER(m); - LOCK_MONITOR_ENTER(code); - - /* If method has been already compiled return immediately. - ATTENTION: check for m->code!!! */ + /* if method has been already compiled return immediately */ if (m->code != NULL) { - /* leave the lock and free the memory */ - - LOCK_MONITOR_EXIT(code); - - code_codeinfo_free(code); + LOCK_MONITOR_EXIT(m); assert(m->code->entrypoint); - return m->code->entrypoint; } @@ -1058,7 +1043,7 @@ u1 *jit_compile(methodinfo *m) /* create jitdata structure */ - jd = jit_jitdata_new(code); + jd = jit_jitdata_new(m); /* set the flags for the current JIT run */ @@ -1119,6 +1104,10 @@ u1 *jit_compile(methodinfo *m) if (r == NULL) { /* We had an exception! Finish stuff here if necessary. */ + /* release codeinfo */ + + code_codeinfo_free(jd->code); + #if defined(ENABLE_PROFILING) /* Release memory for basic block profiling information. */ @@ -1144,12 +1133,7 @@ u1 *jit_compile(methodinfo *m) /* leave the monitor */ - LOCK_MONITOR_EXIT(code); - - /* If we had an exception, release codeinfo. */ - - if (r == NULL) - code_codeinfo_free(code); + LOCK_MONITOR_EXIT(m); /* return pointer to the methods entry point */ @@ -1166,10 +1150,9 @@ u1 *jit_compile(methodinfo *m) u1 *jit_recompile(methodinfo *m) { u1 *r; - jitdata *jd; - codeinfo *code; - u1 optlevel; - s4 dumpsize; + jitdata *jd; + u1 optlevel; + s4 dumpsize; /* check for max. optimization level */ @@ -1193,17 +1176,13 @@ u1 *jit_recompile(methodinfo *m) compilingtime_start(); #endif - /* create codeinfo */ - - code = code_codeinfo_new(m); - /* mark start of dump memory area */ dumpsize = dump_size(); /* create jitdata structure */ - jd = jit_jitdata_new(code); + jd = jit_jitdata_new(m); /* set the current optimization level to the previous one plus 1 */ @@ -1513,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; diff --git a/src/vm/jit/jit.h b/src/vm/jit/jit.h index 37d9c3bfa..fe5d3949c 100644 --- a/src/vm/jit/jit.h +++ b/src/vm/jit/jit.h @@ -22,7 +22,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - $Id: jit.h 7483 2007-03-08 13:17:40Z michi $ + $Id: jit.h 7596 2007-03-28 21:05:53Z 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 @@ -1270,7 +1261,7 @@ void jit_init(void); void jit_close(void); /* create a new jitdata */ -jitdata *jit_jitdata_new(codeinfo *code); +jitdata *jit_jitdata_new(methodinfo *m); /* compile a method with jit compiler */ u1 *jit_compile(methodinfo *m); diff --git a/src/vm/jit/m68k/Makefile.am b/src/vm/jit/m68k/Makefile.am index ff2bce107..c761839cf 100644 --- a/src/vm/jit/m68k/Makefile.am +++ b/src/vm/jit/m68k/Makefile.am @@ -1,4 +1,4 @@ -DIST_SUBDIRS = uclinux +DIST_SUBDIRS = linux SUBDIRS = $(OS_DIR) diff --git a/src/vm/jit/m68k/arch.h b/src/vm/jit/m68k/arch.h index 161169db7..583c008da 100644 --- a/src/vm/jit/m68k/arch.h +++ b/src/vm/jit/m68k/arch.h @@ -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 */ @@ -88,6 +88,21 @@ #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 */ diff --git a/src/vm/jit/m68k/asmpart.S b/src/vm/jit/m68k/asmpart.S index 957160be9..d9152d0e1 100644 --- a/src/vm/jit/m68k/asmpart.S +++ b/src/vm/jit/m68k/asmpart.S @@ -1,28 +1,296 @@ +/* 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 diff --git a/src/vm/jit/m68k/codegen.c b/src/vm/jit/m68k/codegen.c index 3a93412bf..844ed7825 100644 --- a/src/vm/jit/m68k/codegen.c +++ b/src/vm/jit/m68k/codegen.c @@ -1,3 +1,2170 @@ -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 + +#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; +} diff --git a/src/vm/jit/m68k/codegen.h b/src/vm/jit/m68k/codegen.h index ba209f4f4..736707d57 100644 --- a/src/vm/jit/m68k/codegen.h +++ b/src/vm/jit/m68k/codegen.h @@ -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 + +#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 */ diff --git a/src/vm/jit/m68k/emit.c b/src/vm/jit/m68k/emit.c index e69de29bb..807ba4128 100644 --- a/src/vm/jit/m68k/emit.c +++ b/src/vm/jit/m68k/emit.c @@ -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 + +#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*/ + } +} + diff --git a/src/vm/jit/m68k/machine-instr.h b/src/vm/jit/m68k/machine-instr.h index d920d138d..7d939407e 100644 --- a/src/vm/jit/m68k/machine-instr.h +++ b/src/vm/jit/m68k/machine-instr.h @@ -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 diff --git a/src/vm/jit/m68k/md.c b/src/vm/jit/m68k/md.c index 43bbdb133..4214fad1b 100644 --- a/src/vm/jit/m68k/md.c +++ b/src/vm/jit/m68k/md.c @@ -1,15 +1,218 @@ -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 + +#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 ,%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 : + 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 + e7182: 4e75 rts + e7184: 4480 negl %d0 + e7186: 2f00 movel %d0,%sp@- + e7188: 61ff fff3 82e2 bsrl 1f46c + 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); } diff --git a/src/vm/jit/m68k/patcher.c b/src/vm/jit/m68k/patcher.c index e69de29bb..8e00d734f 100644 --- a/src/vm/jit/m68k/patcher.c +++ b/src/vm/jit/m68k/patcher.c @@ -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 + +#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: + + + +*******************************************************************************/ + +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 index 5207e3d3a..000000000 --- a/src/vm/jit/m68k/uclinux/Makefile.am +++ /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 index e69de29bb..000000000 diff --git a/src/vm/jit/m68k/uclinux/md-abi.h b/src/vm/jit/m68k/uclinux/md-abi.h deleted file mode 100644 index aefc1a8c3..000000000 --- a/src/vm/jit/m68k/uclinux/md-abi.h +++ /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 index e69de29bb..000000000 diff --git a/src/vm/jit/m68k/uclinux/md-os.c b/src/vm/jit/m68k/uclinux/md-os.c deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/vm/jit/mips/arch.h b/src/vm/jit/mips/arch.h index 40c95d529..4e3c01ac9 100644 --- a/src/vm/jit/mips/arch.h +++ b/src/vm/jit/mips/arch.h @@ -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 7596 2007-03-28 21:05:53Z twisti $ */ @@ -162,6 +162,13 @@ #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 diff --git a/src/vm/jit/mips/asmpart.S b/src/vm/jit/mips/asmpart.S index 80d94d8f2..8d76f83d2 100644 --- a/src/vm/jit/mips/asmpart.S +++ b/src/vm/jit/mips/asmpart.S @@ -29,7 +29,7 @@ Changes: Christian Thalinger Edwin Steiner - $Id: asmpart.S 7224 2007-01-18 11:43:03Z twisti $ + $Id: asmpart.S 7596 2007-03-28 21:05:53Z twisti $ */ @@ -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 diff --git a/src/vm/jit/mips/codegen.c b/src/vm/jit/mips/codegen.c index c2817a0b1..203b4b22e 100644 --- a/src/vm/jit/mips/codegen.c +++ b/src/vm/jit/mips/codegen.c @@ -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 7596 2007-03-28 21:05:53Z twisti $ */ @@ -69,13 +69,13 @@ #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; diff --git a/src/vm/jit/mips/codegen.h b/src/vm/jit/mips/codegen.h index d02ee1100..385902563 100644 --- a/src/vm/jit/mips/codegen.h +++ b/src/vm/jit/mips/codegen.h @@ -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 @@ -22,12 +22,7 @@ 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 7596 2007-03-28 21:05:53Z twisti $ */ @@ -105,9 +100,6 @@ do { \ M_NOP; \ M_NOP; \ - M_NOP; \ - M_NOP; \ - M_NOP; \ } while (0) @@ -145,6 +137,11 @@ 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)); \ @@ -414,6 +411,7 @@ #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 */ @@ -422,6 +420,7 @@ #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 */ diff --git a/src/vm/jit/mips/emit.c b/src/vm/jit/mips/emit.c index cc06397e9..6e7f7f61d 100644 --- a/src/vm/jit/mips/emit.c +++ b/src/vm/jit/mips/emit.c @@ -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); } } diff --git a/src/vm/jit/mips/linux/md-os.c b/src/vm/jit/mips/linux/md-os.c index cb8e2639e..9b7e61817 100644 --- a/src/vm/jit/mips/linux/md-os.c +++ b/src/vm/jit/mips/linux/md-os.c @@ -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 7596 2007-03-28 21:05:53Z 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 } diff --git a/src/vm/jit/mips/md.c b/src/vm/jit/mips/md.c index b8b0e9dff..55e48dd47 100644 --- a/src/vm/jit/mips/md.c +++ b/src/vm/jit/mips/md.c @@ -22,7 +22,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - $Id: md.c 7483 2007-03-08 13:17:40Z michi $ + $Id: md.c 7596 2007-03-28 21:05:53Z twisti $ */ @@ -49,63 +49,6 @@ #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 diff --git a/src/vm/jit/mips/patcher.c b/src/vm/jit/mips/patcher.c index 32a21599f..dfe1cc225 100644 --- a/src/vm/jit/mips/patcher.c +++ b/src/vm/jit/mips/patcher.c @@ -22,7 +22,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - $Id: patcher.c 7483 2007-03-08 13:17:40Z michi $ + $Id: patcher.c 7596 2007-03-28 21:05:53Z 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; diff --git a/src/vm/jit/parse.c b/src/vm/jit/parse.c index 7742cb28e..dd383d346 100644 --- a/src/vm/jit/parse.c +++ b/src/vm/jit/parse.c @@ -22,7 +22,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - $Id: parse.c 7483 2007-03-08 13:17:40Z michi $ + $Id: parse.c 7596 2007-03-28 21:05:53Z 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 { diff --git a/src/vm/jit/powerpc/arch.h b/src/vm/jit/powerpc/arch.h index efc5f2a4b..901008ffa 100644 --- a/src/vm/jit/powerpc/arch.h +++ b/src/vm/jit/powerpc/arch.h @@ -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 7596 2007-03-28 21:05:53Z twisti $ */ @@ -103,6 +103,13 @@ #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 diff --git a/src/vm/jit/powerpc/asmpart.S b/src/vm/jit/powerpc/asmpart.S index a81f9220b..47af22d8b 100644 --- a/src/vm/jit/powerpc/asmpart.S +++ b/src/vm/jit/powerpc/asmpart.S @@ -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 7596 2007-03-28 21:05:53Z twisti $ */ @@ -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 ******************************************************* diff --git a/src/vm/jit/powerpc/codegen.c b/src/vm/jit/powerpc/codegen.c index 3b9a60d40..e1a10ca92 100644 --- a/src/vm/jit/powerpc/codegen.c +++ b/src/vm/jit/powerpc/codegen.c @@ -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 7596 2007-03-28 21:05:53Z 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; diff --git a/src/vm/jit/powerpc/codegen.h b/src/vm/jit/powerpc/codegen.h index 1b6a3f822..01c32ba66 100644 --- a/src/vm/jit/powerpc/codegen.h +++ b/src/vm/jit/powerpc/codegen.h @@ -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 @@ -23,14 +23,7 @@ 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 7596 2007-03-28 21:05:53Z twisti $ */ @@ -113,7 +106,13 @@ #define BRANCH_NOPS \ do { \ - M_NOP; \ + if (CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) { \ + M_NOP; \ + M_NOP; \ + } \ + else { \ + M_NOP; \ + } \ } while (0) @@ -135,18 +134,28 @@ 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) */ @@ -242,7 +251,9 @@ #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) diff --git a/src/vm/jit/powerpc/darwin/md-os.c b/src/vm/jit/powerpc/darwin/md-os.c index c90f8d8be..3a23bf810 100644 --- a/src/vm/jit/powerpc/darwin/md-os.c +++ b/src/vm/jit/powerpc/darwin/md-os.c @@ -26,9 +26,7 @@ Authors: Christian Thalinger - Changes: - - $Id: md-os.c 6123 2006-12-05 21:10:54Z twisti $ + $Id: md-os.c 7596 2007-03-28 21:05:53Z 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; } diff --git a/src/vm/jit/powerpc/emit.c b/src/vm/jit/powerpc/emit.c index 62ad7f1ab..1b77a9f0c 100644 --- a/src/vm/jit/powerpc/emit.c +++ b/src/vm/jit/powerpc/emit.c @@ -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" @@ -76,17 +77,22 @@ s4 emit_load(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg) disp = src->vv.regoff * 4; - 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); + switch (src->type) { + case TYPE_INT: + case TYPE_ADR: + M_ILD(tempreg, REG_SP, disp); + break; + case TYPE_LNG: + M_LLD(tempreg, REG_SP, disp); + break; + case TYPE_FLT: + M_FLD(tempreg, REG_SP, disp); + break; + case TYPE_DBL: + M_DLD(tempreg, REG_SP, disp); + break; + default: + vm_abort("emit_load: unknown type %d", src->type); } reg = tempreg; @@ -168,13 +174,14 @@ s4 emit_load_high(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg) /* emit_store ****************************************************************** - XXX + Emit a possible store for the given variable. *******************************************************************************/ void emit_store(jitdata *jd, instruction *iptr, varinfo *dst, s4 d) { codegendata *cd; + s4 disp; /* get required compiler data */ @@ -183,17 +190,24 @@ void emit_store(jitdata *jd, instruction *iptr, varinfo *dst, s4 d) if (IS_INMEMORY(dst->flags)) { COUNT_SPILLS; - if (IS_FLT_DBL_TYPE(dst->type)) { - if (IS_2_WORD_TYPE(dst->type)) - M_DST(d, REG_SP, dst->vv.regoff * 4); - else - M_FST(d, REG_SP, dst->vv.regoff * 4); - } - else { - if (IS_2_WORD_TYPE(dst->type)) - M_LST(d, REG_SP, dst->vv.regoff * 4); - else - M_IST(d, REG_SP, dst->vv.regoff * 4); + disp = dst->vv.regoff * 4; + + switch (dst->type) { + case TYPE_INT: + case TYPE_ADR: + M_IST(d, REG_SP, disp); + break; + case TYPE_LNG: + M_LST(d, REG_SP, disp); + break; + case TYPE_FLT: + M_FST(d, REG_SP, disp); + break; + case TYPE_DBL: + M_DST(d, REG_SP, disp); + break; + default: + vm_abort("emit_store: unknown type %d", dst->type); } } } @@ -239,15 +253,21 @@ void emit_copy(jitdata *jd, instruction *iptr, varinfo *src, varinfo *dst) } if (s1 != d) { - if (IS_FLT_DBL_TYPE(src->type)) + switch (src->type) { + case TYPE_INT: + case TYPE_ADR: + M_MOV(s1, d); + break; + case TYPE_LNG: + M_MOV(GET_LOW_REG(s1), GET_LOW_REG(d)); + M_MOV(GET_HIGH_REG(s1), GET_HIGH_REG(d)); + break; + case TYPE_FLT: + case TYPE_DBL: M_FMOV(s1, d); - else { - if (IS_2_WORD_TYPE(src->type)) { - M_MOV(GET_LOW_REG(s1), GET_LOW_REG(d)); - M_MOV(GET_HIGH_REG(s1), GET_HIGH_REG(d)); - } - else - M_MOV(s1, d); + break; + default: + vm_abort("emit_copy: unknown type %d", dst->type); } } @@ -275,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); } } diff --git a/src/vm/jit/powerpc/linux/md-os.c b/src/vm/jit/powerpc/linux/md-os.c index c3f5ad36a..b0564bc38 100644 --- a/src/vm/jit/powerpc/linux/md-os.c +++ b/src/vm/jit/powerpc/linux/md-os.c @@ -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 @@ -22,11 +22,7 @@ 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 7596 2007-03-28 21:05:53Z 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) @@ -58,49 +55,120 @@ /* 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; } diff --git a/src/vm/jit/powerpc/md.c b/src/vm/jit/powerpc/md.c index 3ec67f021..227a37090 100644 --- a/src/vm/jit/powerpc/md.c +++ b/src/vm/jit/powerpc/md.c @@ -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 7596 2007-03-28 21:05:53Z 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 diff --git a/src/vm/jit/powerpc/patcher.c b/src/vm/jit/powerpc/patcher.c index 77f12f210..275acb322 100644 --- a/src/vm/jit/powerpc/patcher.c +++ b/src/vm/jit/powerpc/patcher.c @@ -22,7 +22,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - $Id: patcher.c 7483 2007-03-08 13:17:40Z michi $ + $Id: patcher.c 7596 2007-03-28 21:05:53Z twisti $ */ @@ -657,20 +657,75 @@ bool patcher_invokeinterface(u1 *sp) } -/* patcher_checkcast_instanceof_interface ************************************** +/* patcher_checkcast_interface ************************************************* Machine code: - 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: + + + 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; diff --git a/src/vm/jit/powerpc64/arch.h b/src/vm/jit/powerpc64/arch.h index 9231f2116..6147447c5 100644 --- a/src/vm/jit/powerpc64/arch.h +++ b/src/vm/jit/powerpc64/arch.h @@ -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 7596 2007-03-28 21:05:53Z twisti $ */ @@ -93,6 +93,13 @@ /* #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 diff --git a/src/vm/jit/powerpc64/asmpart.S b/src/vm/jit/powerpc64/asmpart.S index 6ab2a0be0..49961cd1b 100644 --- a/src/vm/jit/powerpc64/asmpart.S +++ b/src/vm/jit/powerpc64/asmpart.S @@ -29,13 +29,15 @@ Changes: Christian Thalinger Edwin Steiner - $Id: asmpart.S 6265 2007-01-02 20:40:57Z edwin $ + $Id: asmpart.S 7596 2007-03-28 21:05:53Z twisti $ */ #include "config.h" +#define __ASSEMBLY__ + #include "md-abi.h" #include "md-asm.h" @@ -51,20 +53,8 @@ /* 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 ********************************************************** @@ -119,6 +109,12 @@ .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 @@ -135,6 +131,14 @@ #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) diff --git a/src/vm/jit/powerpc64/codegen.c b/src/vm/jit/powerpc64/codegen.c index 7f49dc864..a31cbd8d1 100644 --- a/src/vm/jit/powerpc64/codegen.c +++ b/src/vm/jit/powerpc64/codegen.c @@ -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 7596 2007-03-28 21:05:53Z twisti $ */ @@ -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" @@ -51,32 +50,38 @@ #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); } } diff --git a/src/vm/jit/powerpc64/codegen.h b/src/vm/jit/powerpc64/codegen.h index efe7bb136..ae16d48dc 100644 --- a/src/vm/jit/powerpc64/codegen.h +++ b/src/vm/jit/powerpc64/codegen.h @@ -30,7 +30,7 @@ Christian Thalinger Christian Ullrich - $Id: codegen.h 6078 2006-11-28 22:19:16Z twisti $ + $Id: codegen.h 7596 2007-03-28 21:05:53Z twisti $ */ @@ -49,24 +49,6 @@ /* 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) \ @@ -115,9 +97,12 @@ /* 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) @@ -152,6 +137,11 @@ 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) */ @@ -225,7 +215,7 @@ #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) @@ -307,7 +297,9 @@ #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 { \ diff --git a/src/vm/jit/powerpc64/emit.c b/src/vm/jit/powerpc64/emit.c index f4fc1cd79..43fd7ed74 100644 --- a/src/vm/jit/powerpc64/emit.c +++ b/src/vm/jit/powerpc64/emit.c @@ -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 @@ -22,12 +22,6 @@ 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 $ */ @@ -39,12 +33,23 @@ #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: +*/ diff --git a/src/vm/jit/powerpc64/linux/md-abi.c b/src/vm/jit/powerpc64/linux/md-abi.c index 57da21e51..2014a2c64 100644 --- a/src/vm/jit/powerpc64/linux/md-abi.c +++ b/src/vm/jit/powerpc64/linux/md-abi.c @@ -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 7596 2007-03-28 21:05:53Z 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 diff --git a/src/vm/jit/powerpc64/linux/md-abi.h b/src/vm/jit/powerpc64/linux/md-abi.h index 9d6b365d7..f21759fcc 100644 --- a/src/vm/jit/powerpc64/linux/md-abi.h +++ b/src/vm/jit/powerpc64/linux/md-abi.h @@ -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 @@ -22,13 +22,7 @@ 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 7596 2007-03-28 21:05:53Z 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 */ @@ -56,6 +51,11 @@ #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 */ diff --git a/src/vm/jit/powerpc64/linux/md-os.c b/src/vm/jit/powerpc64/linux/md-os.c index 671301d4e..730435c02 100644 --- a/src/vm/jit/powerpc64/linux/md-os.c +++ b/src/vm/jit/powerpc64/linux/md-os.c @@ -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 7596 2007-03-28 21:05:53Z twisti $ */ @@ -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) @@ -53,50 +54,59 @@ /* 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; } diff --git a/src/vm/jit/powerpc64/md.c b/src/vm/jit/powerpc64/md.c index d3940d833..6da5d7ce1 100644 --- a/src/vm/jit/powerpc64/md.c +++ b/src/vm/jit/powerpc64/md.c @@ -22,10 +22,11 @@ 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 7596 2007-03-28 21:05:53Z twisti $ */ + #include "config.h" #include diff --git a/src/vm/jit/powerpc64/patcher.c b/src/vm/jit/powerpc64/patcher.c index 6f5add6cc..4da8f6793 100644 --- a/src/vm/jit/powerpc64/patcher.c +++ b/src/vm/jit/powerpc64/patcher.c @@ -22,7 +22,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - $Id: patcher.c 7483 2007-03-08 13:17:40Z michi $ + $Id: patcher.c 7596 2007-03-28 21:05:53Z twisti $ */ @@ -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: + + + 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: + + + 806dffc4 lwz r3,-60(r13) + 81adffc0 lwz r13,-64(r13) + 7da903a6 mtctr r13 + 4e800421 bctrl + + + MULTIANEWARRAY: + + + 808dffc0 lwz r4,-64(r13) + 38a10038 addi r5,r1,56 + 81adffbc lwz r13,-68(r13) + 7da903a6 mtctr r13 + 4e800421 bctrl + + + ARRAYCHECKCAST: + + + 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): + + + 81870000 lwz r12,0(r7) + 800c0014 lwz r0,20(r12) + 818dff78 lwz r12,-136(r13) + + + INSTANCEOF (class): + + + 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: + + + 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 ************************************************************** diff --git a/src/vm/jit/reg.c b/src/vm/jit/reg.c index 4673c5ab3..9fcab0228 100644 --- a/src/vm/jit/reg.c +++ b/src/vm/jit/reg.c @@ -32,7 +32,7 @@ Michael Starzinger Edwin Steiner - $Id: reg.c 5435 2006-09-08 18:14:50Z edwin $ + $Id: reg.c 7596 2007-03-28 21:05:53Z twisti $ */ @@ -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; diff --git a/src/vm/jit/s390/arch.h b/src/vm/jit/s390/arch.h index 68d3f968a..62fa6a64c 100644 --- a/src/vm/jit/s390/arch.h +++ b/src/vm/jit/s390/arch.h @@ -22,7 +22,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - $Id: arch.h 7312 2007-02-10 00:49:37Z pm $ + $Id: arch.h 7534 2007-03-16 23:00:18Z pm $ */ @@ -98,6 +98,9 @@ #define CONSECUTIVE_INTEGER_ARGS #define CONSECUTIVE_FLOAT_ARGS +#define HAS_4BYTE_STACKSLOT +#define SUPPORT_COMBINE_INTEGER_REGISTERS + #endif /* _ARCH_H */ diff --git a/src/vm/jit/s390/asmpart.S b/src/vm/jit/s390/asmpart.S index d656e4c59..ae934dccb 100644 --- a/src/vm/jit/s390/asmpart.S +++ b/src/vm/jit/s390/asmpart.S @@ -30,7 +30,7 @@ Changes: Edwin Steiner - $Id: asmpart.S 7483 2007-03-08 13:17:40Z michi $ + $Id: asmpart.S 7596 2007-03-28 21:05:53Z 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 ***************************** * * diff --git a/src/vm/jit/s390/codegen.c b/src/vm/jit/s390/codegen.c index 949c12e90..bc7d5a5cb 100644 --- a/src/vm/jit/s390/codegen.c +++ b/src/vm/jit/s390/codegen.c @@ -29,7 +29,7 @@ Christian Ullrich Edwin Steiner - $Id: codegen.c 7483 2007-03-08 13:17:40Z michi $ + $Id: codegen.c 7581 2007-03-26 07:23:16Z pm $ */ @@ -179,7 +179,7 @@ bool codegen(jitdata *jd) native code e.g. libc or jni (alignment problems with movaps). */ - if (!jd->isleafmethod || opt_verbosecall) + if (!jd->isleafmethod || opt_verbosecall ) /* TODO really 16 bytes ? */ cd->stackframesize = (cd->stackframesize + 3) & ~3; @@ -525,12 +525,10 @@ bool codegen(jitdata *jd) break; case ICMD_LCONST: /* ... ==> ..., constant */ - OOPS(); -#if 0 - d = codegen_reg_of_dst(jd, iptr, REG_ITMP1); + + d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED); LCONST(d, iptr->sx.val.l); emit_store_dst(jd, iptr, d); -#endif break; case ICMD_FCONST: /* ... ==> ..., constant */ @@ -541,13 +539,10 @@ bool codegen(jitdata *jd) break; case ICMD_DCONST: /* ... ==> ..., constant */ - OOPS(); -#if 0 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1); disp = dseg_add_double(cd, iptr->sx.val.d); - emit_movd_membase_reg(cd, RIP, -((cd->mcodeptr + 9) - cd->mcodebase) + disp, d); + M_DLDN(d, REG_PV, disp, REG_ITMP1); emit_store_dst(jd, iptr, d); -#endif break; case ICMD_ACONST: /* ... ==> ..., constant */ @@ -759,7 +754,13 @@ bool codegen(jitdata *jd) d = codegen_reg_of_dst(jd, iptr, REG_ITMP1); M_INTMOVE(s1, d); /* TODO range */ - M_ISUB_IMM(iptr->sx.val.i, d); + if (N_VALID_IMM(iptr->sx.val.i)) { + M_ISUB_IMM(iptr->sx.val.i, d); + } else { + disp = dseg_add_s4(cd, iptr->sx.val.i); + M_ILD(REG_ITMP2, REG_PV, disp); + M_ISUB(REG_ITMP2, d); + } emit_store_dst(jd, iptr, d); break; @@ -874,13 +875,13 @@ bool codegen(jitdata *jd) M_INTMOVE(R0, REG_ITMP3); + s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2); + s1 = emit_load_s1(jd, iptr, R0); M_INTMOVE(s1, R0); N_LHI(REG_ITMP1, 0); N_SRDA(R0, 32, RN); - s2 = emit_load_s2(jd, iptr, REG_ITMP2); - N_DR(R0, s2); if (iptr->opc == ICMD_IREM) { @@ -1196,8 +1197,7 @@ bool codegen(jitdata *jd) break; case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */ - OOPS(); -#if 0 + 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); @@ -1208,9 +1208,41 @@ bool codegen(jitdata *jd) M_IAND(s2, d); } emit_store_dst(jd, iptr, d); -#endif + + break; + + case ICMD_IOR: /* ..., 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); + if (s2 == d) + M_IOR(s1, d); + else { + M_INTMOVE(s1, d); + M_IOR(s2, d); + } + emit_store_dst(jd, iptr, d); + + break; + + case ICMD_IXOR: /* ..., 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); + if (s2 == d) + M_IXOR(s1, d); + else { + M_INTMOVE(s1, d); + M_IXOR(s2, d); + } + emit_store_dst(jd, iptr, d); + break; + + case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */ /* sx.val.i = constant */ OOPS(); @@ -1241,6 +1273,26 @@ bool codegen(jitdata *jd) case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */ /* sx.val.l = constant */ + + s3 = iptr->sx.val.l & 0xffffffff; + s1 = emit_load_s1_low(jd, iptr, REG_ITMP1); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED); + if ((s3 >= 0) && (s3 <= 65535)) + M_AND_IMM(s1, s3, GET_LOW_REG(d)); + else { + ICONST(REG_ITMP3, s3); + M_AND(s1, REG_ITMP3, GET_LOW_REG(d)); + } + s1 = emit_load_s1_high(jd, iptr, REG_ITMP1); + s3 = iptr->sx.val.l >> 32; + if ((s3 >= 0) && (s3 <= 65535)) + M_AND_IMM(s1, s3, GET_HIGH_REG(d)); + else { + ICONST(REG_ITMP3, s3); /* don't use REG_ITMP2 */ + M_AND(s1, REG_ITMP3, GET_HIGH_REG(d)); + } + emit_store_dst(jd, iptr, d); + OOPS(); #if 0 s1 = emit_load_s1(jd, iptr, REG_ITMP1); @@ -1256,22 +1308,6 @@ bool codegen(jitdata *jd) #endif break; - case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */ - OOPS(); -#if 0 - 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 (s2 == d) - M_IOR(s1, d); - else { - M_INTMOVE(s1, d); - M_IOR(s2, d); - } - emit_store_dst(jd, iptr, d); -#endif - break; - case ICMD_IORCONST: /* ..., value ==> ..., value | constant */ /* sx.val.i = constant */ OOPS(); @@ -1317,22 +1353,6 @@ bool codegen(jitdata *jd) #endif break; - case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */ - OOPS(); -#if 0 - 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 (s2 == d) - M_IXOR(s1, d); - else { - M_INTMOVE(s1, d); - M_IXOR(s2, d); - } - emit_store_dst(jd, iptr, d); -#endif - break; - case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */ /* sx.val.i = constant */ OOPS(); @@ -1408,11 +1428,9 @@ bool codegen(jitdata *jd) break; case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */ - OOPS(); -#if 0 s1 = emit_load_s1(jd, iptr, REG_FTMP1); s2 = emit_load_s2(jd, iptr, REG_FTMP2); - d = codegen_reg_of_dst(jd, iptr, REG_FTMP3); + d = codegen_reg_of_dst(jd, iptr, REG_FTMP1); if (s2 == d) M_FADD(s1, d); else { @@ -1420,15 +1438,12 @@ bool codegen(jitdata *jd) M_FADD(s2, d); } emit_store_dst(jd, iptr, d); -#endif break; case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */ - OOPS(); -#if 0 s1 = emit_load_s1(jd, iptr, REG_FTMP1); s2 = emit_load_s2(jd, iptr, REG_FTMP2); - d = codegen_reg_of_dst(jd, iptr, REG_FTMP3); + d = codegen_reg_of_dst(jd, iptr, REG_FTMP1); if (s2 == d) M_DADD(s1, d); else { @@ -1436,45 +1451,32 @@ bool codegen(jitdata *jd) M_DADD(s2, d); } emit_store_dst(jd, iptr, d); -#endif break; case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */ - OOPS(); -#if 0 s1 = emit_load_s1(jd, iptr, REG_FTMP1); - s2 = emit_load_s2(jd, iptr, REG_FTMP2); - d = codegen_reg_of_dst(jd, iptr, REG_FTMP3); - if (s2 == d) { - M_FLTMOVE(s2, REG_FTMP2); - s2 = REG_FTMP2; - } + d = codegen_reg_of_dst(jd, iptr, REG_FTMP1); + s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d); + M_FLTMOVE(s1, d); M_FSUB(s2, d); emit_store_dst(jd, iptr, d); -#endif break; case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */ - OOPS(); -#if 0 s1 = emit_load_s1(jd, iptr, REG_FTMP1); - s2 = emit_load_s2(jd, iptr, REG_FTMP2); - d = codegen_reg_of_dst(jd, iptr, REG_FTMP3); - if (s2 == d) { - M_FLTMOVE(s2, REG_FTMP2); - s2 = REG_FTMP2; - } + d = codegen_reg_of_dst(jd, iptr, REG_FTMP1); + s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d); + M_FLTMOVE(s1, d); M_DSUB(s2, d); emit_store_dst(jd, iptr, d); -#endif break; case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */ s1 = emit_load_s1(jd, iptr, REG_FTMP1); s2 = emit_load_s2(jd, iptr, REG_FTMP2); - d = codegen_reg_of_dst(jd, iptr, REG_FTMP3); + d = codegen_reg_of_dst(jd, iptr, REG_FTMP2); if (s2 == d) M_FMUL(s1, d); else { @@ -1482,15 +1484,12 @@ bool codegen(jitdata *jd) M_FMUL(s2, d); } emit_store_dst(jd, iptr, d); - break; case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */ - OOPS(); -#if 0 s1 = emit_load_s1(jd, iptr, REG_FTMP1); s2 = emit_load_s2(jd, iptr, REG_FTMP2); - d = codegen_reg_of_dst(jd, iptr, REG_FTMP3); + d = codegen_reg_of_dst(jd, iptr, REG_FTMP2); if (s2 == d) M_DMUL(s1, d); else { @@ -1498,39 +1497,26 @@ bool codegen(jitdata *jd) M_DMUL(s2, d); } emit_store_dst(jd, iptr, d); -#endif break; case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */ - OOPS(); -#if 0 s1 = emit_load_s1(jd, iptr, REG_FTMP1); - s2 = emit_load_s2(jd, iptr, REG_FTMP2); - d = codegen_reg_of_dst(jd, iptr, REG_FTMP3); - if (s2 == d) { - M_FLTMOVE(s2, REG_FTMP2); - s2 = REG_FTMP2; - } + d = codegen_reg_of_dst(jd, iptr, REG_FTMP1); + s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d); + M_FLTMOVE(s1, d); M_FDIV(s2, d); emit_store_dst(jd, iptr, d); -#endif break; case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */ - OOPS(); -#if 0 s1 = emit_load_s1(jd, iptr, REG_FTMP1); - s2 = emit_load_s2(jd, iptr, REG_FTMP2); - d = codegen_reg_of_dst(jd, iptr, REG_FTMP3); - if (s2 == d) { - M_FLTMOVE(s2, REG_FTMP2); - s2 = REG_FTMP2; - } + d = codegen_reg_of_dst(jd, iptr, REG_FTMP1); + s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d); + M_FLTMOVE(s1, d); M_DDIV(s2, d); emit_store_dst(jd, iptr, d); -#endif break; case ICMD_I2F: /* ..., value ==> ..., (float) value */ @@ -1633,7 +1619,7 @@ bool codegen(jitdata *jd) case ICMD_F2D: /* ..., value ==> ..., (double) value */ s1 = emit_load_s1(jd, iptr, REG_FTMP1); - d = codegen_reg_of_dst(jd, iptr, REG_FTMP3); + d = codegen_reg_of_dst(jd, iptr, REG_FTMP2); M_CVTFD(s1, d); emit_store_dst(jd, iptr, d); break; @@ -1650,24 +1636,46 @@ bool codegen(jitdata *jd) case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */ /* == => 0, < => 1, > => -1 */ + case ICMD_DCMPL: case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */ /* == => 0, < => 1, > => -1 */ + case ICMD_DCMPG: s1 = emit_load_s1(jd, iptr, REG_FTMP1); s2 = emit_load_s2(jd, iptr, REG_FTMP2); d = codegen_reg_of_dst(jd, iptr, REG_ITMP3); - N_CEBR(s1, s2); + switch (iptr->opc) { + case ICMD_FCMPG: + case ICMD_FCMPL: + N_CEBR(s1, s2); + break; + case ICMD_DCMPG: + case ICMD_DCMPL: + N_CDBR(s1, s2); + break; + } + + N_BRC( /* load 1 */ + DD_H | (iptr->opc == ICMD_FCMPG || iptr->opc == ICMD_DCMPG ? DD_O : 0), + SZ_BRC + SZ_BRC + SZ_BRC + ); + + N_BRC( /* load -1 */ + DD_L | (iptr->opc == ICMD_FCMPL || iptr->opc == ICMD_DCMPL ? DD_O : 0), + SZ_BRC + SZ_BRC + SZ_LHI + SZ_BRC + ); - M_BGT(SZ_BRC + SZ_BRC + SZ_BRC); - M_BLT(SZ_BRC + SZ_BRC + SZ_LHI + SZ_BRC); - M_BEQ(SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI + SZ_BRC); + N_BRC( /* load 0 */ + DD_E, + SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI + SZ_BRC + ); - N_LHI(d, iptr->opc == ICMD_FCMPL ? 1 : -1); /* GT */ + N_LHI(d, 1); /* GT */ M_BR(SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI); - N_LHI(d, iptr->opc == ICMD_FCMPL ? -1 : 1); /* LT */ + N_LHI(d, -1); /* LT */ M_BR(SZ_BRC + SZ_LHI); N_LHI(d, 0); /* EQ */ @@ -1675,42 +1683,6 @@ bool codegen(jitdata *jd) break; - case ICMD_DCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */ - /* == => 0, < => 1, > => -1 */ - OOPS(); -#if 0 - s1 = emit_load_s1(jd, iptr, REG_FTMP1); - s2 = emit_load_s2(jd, iptr, REG_FTMP2); - d = codegen_reg_of_dst(jd, iptr, REG_ITMP3); - M_CLR(d); - 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_CMOVP(REG_ITMP2, d); /* treat unordered as GT */ - emit_store_dst(jd, iptr, d); -#endif - break; - - case ICMD_DCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */ - /* == => 0, < => 1, > => -1 */ - OOPS(); -#if 0 - s1 = emit_load_s1(jd, iptr, REG_FTMP1); - s2 = emit_load_s2(jd, iptr, REG_FTMP2); - d = codegen_reg_of_dst(jd, iptr, REG_ITMP3); - M_CLR(d); - 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_CMOVP(REG_ITMP1, d); /* treat unordered as LT */ - emit_store_dst(jd, iptr, d); -#endif - break; - /* memory operations **************************************************/ @@ -1725,18 +1697,17 @@ bool codegen(jitdata *jd) break; case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */ - OOPS(); -#if 0 - 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); - if (INSTRUCTION_MUST_CHECK(iptr)) { - gen_nullptr_check(s1); - gen_bound_check; - } - emit_movsbq_memindex_reg(cd, OFFSET(java_bytearray, data[0]), s1, s2, 0, d); + s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1); + s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); + + emit_array_checks(cd, iptr, s1, s2); + + N_IC(d, OFFSET(java_bytearray, data[0]), s2, s1); + /* TODO improove this */ + N_SLL(d, 24, RN); + N_SRL(d, 24, RN); emit_store_dst(jd, iptr, d); -#endif break; case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */ @@ -1755,33 +1726,29 @@ bool codegen(jitdata *jd) break; case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */ - OOPS(); -#if 0 - s1 = emit_load_s1(jd, iptr, REG_ITMP1); + s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); - d = codegen_reg_of_dst(jd, iptr, REG_ITMP3); - if (INSTRUCTION_MUST_CHECK(iptr)) { - gen_nullptr_check(s1); - gen_bound_check; - } - emit_movswq_memindex_reg(cd, OFFSET(java_shortarray, data[0]), s1, s2, 1, d); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); + + emit_array_checks(cd, iptr, s1, s2); + + M_INTMOVE(s2, REG_ITMP2); + M_ISLL_IMM(1, REG_ITMP2); + + N_LH(d, OFFSET(java_shortarray, data[0]), REG_ITMP2, s1); emit_store_dst(jd, iptr, d); -#endif break; case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */ - OOPS(); -#if 0 - s1 = emit_load_s1(jd, iptr, REG_ITMP1); + s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); - d = codegen_reg_of_dst(jd, iptr, REG_ITMP3); - if (INSTRUCTION_MUST_CHECK(iptr)) { - gen_nullptr_check(s1); - gen_bound_check; - } - emit_movl_memindex_reg(cd, OFFSET(java_intarray, data[0]), s1, s2, 2, d); + d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); + emit_array_checks(cd, iptr, s1, s2); + + M_INTMOVE(s2, REG_ITMP2); + M_ISLL_IMM(2, REG_ITMP2); /* scale index by 4 */ + N_L(d, OFFSET(java_intarray, data[0]), REG_ITMP2, s1); emit_store_dst(jd, iptr, d); -#endif break; case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */ @@ -1842,17 +1809,12 @@ bool codegen(jitdata *jd) break; case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */ - OOPS(); -#if 0 - 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 = emit_load_s1_notzero(jd, iptr, REG_ITMP1); + s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2); + emit_array_checks(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); -#endif + + N_STC(s3, OFFSET(java_bytearray, data[0]), s2, s1); break; case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */ @@ -1870,73 +1832,65 @@ bool codegen(jitdata *jd) break; case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */ - OOPS(); -#if 0 - s1 = emit_load_s1(jd, iptr, REG_ITMP1); + s1 = emit_load_s1_notzero(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_array_checks(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); -#endif + + M_INTMOVE(s2, REG_ITMP2); + M_ISLL_IMM(1, REG_ITMP2); + + N_STH(s3, OFFSET(java_shortarray, data[0]), REG_ITMP2, s1); break; case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */ - OOPS(); -#if 0 - s1 = emit_load_s1(jd, iptr, REG_ITMP1); + s1 = emit_load_s1_notzero(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_array_checks(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); -#endif - break; + + M_INTMOVE(s2, REG_ITMP2); + M_ISLL_IMM(2, REG_ITMP2); + + N_ST(s3, OFFSET(java_intarray, data[0]), REG_ITMP2, s1); + break; case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */ - OOPS(); -#if 0 - s1 = emit_load_s1(jd, iptr, REG_ITMP1); + s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1); 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, REG_ITMP3); - emit_mov_reg_memindex(cd, s3, OFFSET(java_longarray, data[0]), s1, s2, 3); -#endif + emit_array_checks(cd, iptr, s1, s2); + + M_INTMOVE(s2, REG_ITMP2); + M_ISLL_IMM(3, REG_ITMP2); + + s3 = emit_load_s3_high(jd, iptr, REG_ITMP3); + N_ST(s3, OFFSET(java_intarray, data[0]), REG_ITMP2, s1); + s3 = emit_load_s3_low(jd, iptr, REG_ITMP3); + N_ST(s3, OFFSET(java_intarray, data[0]) + 4, REG_ITMP2, s1); break; case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */ - OOPS(); -#if 0 - s1 = emit_load_s1(jd, iptr, REG_ITMP1); + s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1); 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, REG_FTMP3); - emit_movss_reg_memindex(cd, s3, OFFSET(java_floatarray, data[0]), s1, s2, 2); -#endif + emit_array_checks(cd, iptr, s1, s2); + s3 = emit_load_s3(jd, iptr, REG_FTMP1); + + M_INTMOVE(s2, REG_ITMP2); + M_ISLL_IMM(2, REG_ITMP2); + + N_STE(s3, OFFSET(java_floatarray, data[0]), REG_ITMP2, s1); break; case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */ - OOPS(); -#if 0 - s1 = emit_load_s1(jd, iptr, REG_ITMP1); + s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1); 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, REG_FTMP3); - emit_movsd_reg_memindex(cd, s3, OFFSET(java_doublearray, data[0]), s1, s2, 3); -#endif + emit_array_checks(cd, iptr, s1, s2); + s3 = emit_load_s3(jd, iptr, REG_FTMP1); + + M_INTMOVE(s2, REG_ITMP2); + M_ISLL_IMM(3, REG_ITMP2); + + N_STD(s3, OFFSET(java_doublearray, data[0]), REG_ITMP2, s1); break; case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */ @@ -2237,8 +2191,8 @@ bool codegen(jitdata *jd) 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); + M_ILD(GET_HIGH_REG(d), s1, disp); } break; case TYPE_ADR: @@ -2391,16 +2345,17 @@ bool codegen(jitdata *jd) break; case ICMD_IFNULL: /* ..., value ==> ... */ - 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); + switch (iptr->opc) { + case ICMD_IFNULL: + M_BEQ(0); + break; + case ICMD_IFNONNULL: + M_BNE(0); + break; + } codegen_add_branch_ref(cd, iptr->dst.block); break; @@ -2418,7 +2373,7 @@ bool codegen(jitdata *jd) else { disp = dseg_add_s4(cd, iptr->sx.val.i); N_LHI(REG_ITMP2, disp); - N_CL(s1, 0, REG_ITMP2, REG_PV); + N_C(s1, 0, REG_ITMP2, REG_PV); } switch (iptr->opc) { @@ -2445,242 +2400,239 @@ bool codegen(jitdata *jd) break; - case ICMD_IF_LEQ: /* ..., value ==> ... */ - OOPS(); -#if 0 - 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_BEQ(0); - codegen_add_branch_ref(cd, iptr->dst.block); -#endif - break; - case ICMD_IF_LLT: /* ..., value ==> ... */ - OOPS(); -#if 0 + case ICMD_IF_LLE: /* op1 = target JavaVM pc, val.l = constant */ + case ICMD_IF_LGT: + case ICMD_IF_LGE: + case ICMD_IF_LEQ: + case ICMD_IF_LNE: + { - 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); -#endif - break; + u1 *out_ref = NULL; - case ICMD_IF_LLE: /* ..., value ==> ... */ - OOPS(); -#if 0 + /* ATTENTION: compare high words signed and low words unsigned */ + + s1 = emit_load_s1_high(jd, iptr, REG_ITMP1); - 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); -#endif - break; + if (N_VALID_IMM(iptr->sx.val.l >> 32)) + N_CHI(s1, iptr->sx.val.l >> 32); + else { + disp = dseg_add_s4(cd, iptr->sx.val.l >> 32); + N_LHI(REG_ITMP2, disp); + N_C(s1, 0, REG_ITMP2, REG_PV); + } - case ICMD_IF_LNE: /* ..., value ==> ... */ - OOPS(); -#if 0 + switch(iptr->opc) { + case ICMD_IF_LLT: + case ICMD_IF_LLE: + M_BLT(0); + codegen_addreference(cd, iptr->dst.block); + /* EQ ... fall through */ + out_ref = cd->mcodeptr; + M_BGT(0); + break; + case ICMD_IF_LGT: + case ICMD_IF_LGE: + M_BGT(0); + codegen_addreference(cd, iptr->dst.block); + /* EQ ... fall through */ + out_ref = cd->mcodeptr; + M_BLT(0); + break; + case ICMD_IF_LEQ: + /* EQ ... fall through */ + out_ref = cd->mcodeptr; + M_BNE(0); + break; + case ICMD_IF_LNE: + /* EQ ... fall through */ + M_BNE(0); + codegen_addreference(cd, iptr->dst.block); + break; + default: + assert(0); + } - 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); -#endif - break; + s1 = emit_load_s1_low(jd, iptr, REG_ITMP1); - case ICMD_IF_LGT: /* ..., value ==> ... */ - OOPS(); -#if 0 + disp = dseg_add_s4(cd, (s4)(iptr->sx.val.l & 0xffffffff)); + N_LHI(REG_ITMP2, disp); + N_CL(s1, 0, REG_ITMP2, REG_PV); - 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); -#endif - break; + switch(iptr->opc) { + case ICMD_IF_LLT: + M_BLT(0); + break; + case ICMD_IF_LLE: + M_BLE(0); + break; + case ICMD_IF_LGT: + M_BGT(0); + break; + case ICMD_IF_LGE: + M_BGE(0); + break; + case ICMD_IF_LEQ: + M_BEQ(0); + break; + case ICMD_IF_LNE: + M_BNE(0); + break; + default: + assert(0); + } + codegen_addreference(cd, iptr->dst.block); - case ICMD_IF_LGE: /* ..., value ==> ... */ - OOPS(); -#if 0 + if (out_ref != NULL) { + *(u4 *)out_ref |= (u4)(cd->mcodeptr - out_ref) / 2; + } - 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); -#endif - break; - - case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */ - case ICMD_IF_ACMPEQ: /* 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_BEQ(0); - codegen_add_branch_ref(cd, iptr->dst.block); - break; - - case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */ - - 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 */ - /* TODO do the loads modify the condition code? - * lr, l, la, lhi dont - */ - s1 = emit_load_s1_low(jd, iptr, REG_ITMP1); - s2 = emit_load_s2_low(jd, iptr, REG_ITMP2); - M_BNE(SZ_BRC + SZ_CR + SZ_BRC); - M_CMP(s1, s2); - M_BEQ(0); - codegen_add_branch_ref(cd, iptr->dst.block); break; + case ICMD_IF_ACMPEQ: /* ..., value, value ==> ... */ case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */ - case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */ - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - s2 = emit_load_s2(jd, iptr, REG_ITMP2); - M_ICMP(s1, s2); - M_BNE(0); - codegen_add_branch_ref(cd, iptr->dst.block); + /* Compare addresses as 31 bit unsigned integers */ - break; + s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1); + N_LA(REG_ITMP1, 0, RN, s1); - case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */ - OOPS(); -#if 0 + s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2); + N_LA(REG_ITMP2, 0, RN, s2); - 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); -#endif - break; + M_CMP(REG_ITMP1, REG_ITMP2); - case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */ + switch (iptr->opc) { + case ICMD_IF_ACMPEQ: + M_BEQ(0); + break; + case ICMD_IF_ACMPNE: + M_BNE(0); + break; + } - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - s2 = emit_load_s2(jd, iptr, REG_ITMP2); - M_ICMP(s1, s2); - M_BLT(0); codegen_add_branch_ref(cd, iptr->dst.block); - break; - case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */ - OOPS(); -#if 0 - - 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); -#endif - break; + case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */ + case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */ + case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */ case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */ - - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - s2 = emit_load_s2(jd, iptr, REG_ITMP2); - M_ICMP(s1, s2); - M_BGT(0); - codegen_add_branch_ref(cd, iptr->dst.block); - - break; - - case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */ - - OOPS(); -#if 0 - 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); -#endif - break; - case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */ + case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */ s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); - M_ICMP(s1, s2); - M_BLE(0); + M_CMP(s1, s2); + switch (iptr->opc) { + case ICMD_IF_ICMPEQ: + M_BEQ(0); + break; + case ICMD_IF_ICMPNE: + M_BNE(0); + break; + case ICMD_IF_ICMPLT: + M_BLT(0); + break; + case ICMD_IF_ICMPGT: + M_BGT(0); + break; + case ICMD_IF_ICMPLE: + M_BLE(0); + break; + case ICMD_IF_ICMPGE: + M_BGE(0); + break; + } codegen_add_branch_ref(cd, iptr->dst.block); break; case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */ + case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */ + case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */ + case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */ + case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */ + case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */ + { - 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 */ - /* TODO: the loads should not touch the condition code. */ - s1 = emit_load_s1_low(jd, iptr, REG_ITMP1); - s2 = emit_load_s2_low(jd, iptr, REG_ITMP2); - M_BGT(SZ_BRC + SZ_CR + SZ_BRC); - M_CMP(s1, s2); - M_BLE(0); - codegen_add_branch_ref(cd, iptr->dst.block); - break; + u1 *out_ref = NULL; - case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */ + /* ATTENTION: compare high words signed and low words unsigned */ + + s1 = emit_load_s1_high(jd, iptr, REG_ITMP1); + s2 = emit_load_s2_high(jd, iptr, REG_ITMP2); + + N_CR(s1, s2); + + switch(iptr->opc) { + case ICMD_IF_LCMPLT: + case ICMD_IF_LCMPLE: + M_BLT(0); + codegen_addreference(cd, iptr->dst.block); + /* EQ ... fall through */ + out_ref = cd->mcodeptr; + M_BGT(0); + break; + case ICMD_IF_LCMPGT: + case ICMD_IF_LCMPGE: + M_BGT(0); + codegen_addreference(cd, iptr->dst.block); + /* EQ ... fall through */ + out_ref = cd->mcodeptr; + M_BLT(0); + break; + case ICMD_IF_LCMPEQ: + /* EQ ... fall through */ + out_ref = cd->mcodeptr; + M_BNE(0); + break; + case ICMD_IF_LCMPNE: + /* EQ ... fall through */ + M_BNE(0); + codegen_addreference(cd, iptr->dst.block); + break; + default: + assert(0); + } - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - s2 = emit_load_s2(jd, iptr, REG_ITMP2); - M_ICMP(s1, s2); - M_BGE(0); - codegen_add_branch_ref(cd, iptr->dst.block); + s1 = emit_load_s1_low(jd, iptr, REG_ITMP1); + s2 = emit_load_s2_low(jd, iptr, REG_ITMP2); + + N_CLR(s1, s2); - break; + switch(iptr->opc) { + case ICMD_IF_LCMPLT: + M_BLT(0); + break; + case ICMD_IF_LCMPLE: + M_BLE(0); + break; + case ICMD_IF_LCMPGT: + M_BGT(0); + break; + case ICMD_IF_LCMPGE: + M_BGE(0); + break; + case ICMD_IF_LCMPEQ: + M_BEQ(0); + break; + case ICMD_IF_LCMPNE: + M_BNE(0); + break; + default: + assert(0); + } - case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */ + codegen_addreference(cd, iptr->dst.block); - OOPS(); -#if 0 - 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); -#endif + if (out_ref != NULL) { + *(u4 *)out_ref |= (u4)(cd->mcodeptr - out_ref) / 2; + } + + } break; case ICMD_IRETURN: /* ..., retvalue ==> ... */ @@ -3164,16 +3116,17 @@ gen_method: } 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_TEST(REG_ITMP3); + M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength)); + M_ISUB_IMM(superindex, REG_ITMP3); M_BLE(0); codegen_add_classcastexception_ref(cd, s1); - M_ALD(REG_ITMP3, REG_ITMP2, - (s4) (OFFSET(vftbl_t, interfacetable[0]) - - superindex * sizeof(methodptr*))); - M_TEST(REG_ITMP3); + N_AHI( + REG_ITMP2, + (s4) (OFFSET(vftbl_t, interfacetable[0]) - + superindex * sizeof(methodptr*)) + ); + M_ALD(REG_ITMP2, REG_ITMP2, 0); + M_TEST(REG_ITMP2); M_BEQ(0); codegen_add_classcastexception_ref(cd, s1); @@ -3374,7 +3327,7 @@ gen_method: M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl)); M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength)); - M_ASUB_IMM(superindex, REG_ITMP3); + M_ISUB_IMM(superindex, REG_ITMP3); label1_refs[0] = cd->mcodeptr; M_BLE(0); N_AHI( @@ -3387,7 +3340,7 @@ gen_method: /* d := (REG_ITMP1 != 0) */ N_LTR(d, REG_ITMP1); - M_BEQ(SZ_LHI); + M_BEQ(SZ_BRC + SZ_LHI); N_LHI(d, 1); label1 = cd->mcodeptr; @@ -3431,11 +3384,11 @@ gen_method: #if defined(ENABLE_THREADS) codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase); #endif - M_ISUB(REG_ITMP1, REG_ITMP3); + M_ISUB(REG_ITMP3, REG_ITMP1); /* itmp1 := itmp1 (sub.baseval) - itmp3 (super.baseval) */ N_CLR(REG_ITMP1, REG_ITMP2); /* d := (uint)REG_ITMP1 <= (uint)REG_ITMP2 */ N_LHI(d, 0); - M_BGT(SZ_LHI); + M_BGT(SZ_BRC + SZ_LHI); N_LHI(d, 1); } diff --git a/src/vm/jit/s390/codegen.h b/src/vm/jit/s390/codegen.h index 841a590dd..5228b5828 100644 --- a/src/vm/jit/s390/codegen.h +++ b/src/vm/jit/s390/codegen.h @@ -27,7 +27,7 @@ Authors: Andreas Krall Christian Thalinger - $Id: codegen.h 7483 2007-03-08 13:17:40Z michi $ + $Id: codegen.h 7581 2007-03-26 07:23:16Z pm $ */ @@ -92,14 +92,6 @@ -#define LCONST(r,c) \ - do { \ - if ((c) == 0) \ - M_CLR((d)); \ - else \ - M_MOV_IMM((c), (d)); \ - } while (0) - /* branch defines *************************************************************/ #define BRANCH_NOPS \ @@ -115,8 +107,12 @@ #define PATCHER_NOPS \ do { \ M_NOP; \ + M_NOP; \ + M_NOP; \ } while (0) +#define PATCHER_NOPS_SKIP 12 + /* *** BIG TODO *** * Make all this inline functions !!!!!!!!!! */ @@ -329,6 +325,11 @@ #define N_VALID_DISP(x) ((N_DISP_MIN <= (x)) && ((x) <= N_DISP_MAX)) #define ASSERT_VALID_DISP(x) assert(N_VALID_DISP(x)) +#define N_BRANCH_MIN -32768 +#define N_BRANCH_MAX 32767 +#define N_VALID_BRANCH(x) ((N_BRANCH_MIN <= (x)) && ((x) <= N_BRANCH_MAX)) +#define ASSERT_VALID_BRANCH(x) assert(N_VALID_BRANCH(x)) + /* Condition codes */ #define DD_O 1 @@ -360,7 +361,7 @@ # define SZ_AHI SZ_RI #define N_ALR(r1, r2) N_RR(0x1E, r1, r2) #define N_AL(r1, d2, x2, b2) N_RX(0x5E, r1, d2, x2, b2) -#define N_NR(r1, r2) N_RR(r1, r2) +#define N_NR(r1, r2) N_RR(0x14, r1, r2) #define N_N(r1, d2, x2, b2) N_RX(0x54, r1, d2, x2, b2) #define N_NI(d1, b1, i2) N_SI(0x94, d1, b1, i2) #define N_NC(d1, l, b1, d2, b2) N_NC(0xD4, l, b1, d1, b2, d2) @@ -509,6 +510,12 @@ /* chapter 19. Binary floating point instructions */ +#define N_AEBR(r1, r2) N_RRE(0xB30A, r1, r2) +#define N_ADBR(r1, r2) N_RRE(0xB31A, r1, r2) +#define N_AXBR(r1, r2) N_RRE(0xB34A, r1, r2) +#define N_AEB(r1, d2, x2, b2) N_RXE(0xED0A, r1, d2, x2, b2) +#define N_ADB(r1, d2, x2, b2) N_RXE(0xED1A, r1, d2, x2, b2) + #define N_CEBR(r1, r2) N_RRE(0xB309, r1, r2) #define N_CDBR(r1, r2) N_RRE(0xB319, r1, r2) #define N_CXBR(r1, r2) N_RRE(0xB349, r1, r2) @@ -523,6 +530,12 @@ #define N_CFDBR(r1, m3, r2) N_RRF(0xB399, r1, m3, r2) #define N_CFXBR(r1, m3, r2) N_RRF(0xB39A, r1, m3, r2) +#define N_DEBR(r1, r2) N_RRE(0xB30D, r1, r2) +#define N_DDBR(r1, r2) N_RRE(0xB31D, r1, r2) +#define N_DXBR(r1, r2) N_RRE(0xB34D, r1, r2) +#define N_DEB(r1, d2, x2, b2) N_RXE(0xED0D, r1, d2, x2, b2) +#define N_DDB(r1, d2, x2, b2) N_RXE(0xED1D, r1, d2, x2, b2) + #define N_LDEBR(r1, r2) N_RRE(0xB304, r1, r2) #define N_LXDBR(r1, r2) N_RRE(0xB305, r1, r2) #define N_LXEBR(r1, r2) N_RRE(0xB306, r1, r2) @@ -533,6 +546,12 @@ #define N_MDEBR(r1, r2) N_RRE(0xB30C, r1, r2) #define N_MXDBR(r1, r2) N_RRE(0xB307, r1, r2) +#define N_SEBR(r1, r2) N_RRE(0xB30B, r1, r2) +#define N_SDBR(r1, r2) N_RRE(0xB31B, r1, r2) +#define N_SXBR(r1, r2) N_RRE(0xB34B, r1, r2) +#define N_SEB(r1, d2, x2, b2) N_RXE(0xED0B, r1, d2, x2, b2) +#define N_SDB(r1, d2, x2, b2) N_RXE(0xED1B, r1, d2, x2, b2) + /* Alpha like instructions */ #define M_CALL(r2) N_BASR(R14, r2) @@ -598,6 +617,7 @@ #define M_BGT(off) N_BRC(DD_H, off) #define M_BLT(off) N_BRC(DD_L, off) #define M_BGE(off) N_BRC(DD_HE, off) +#define M_BO(off) N_BRC(DD_O, off) #define M_CMP(r1, r2) N_CR(r1, r2) #define M_CLR(r) N_LHI(r, 0) @@ -615,17 +635,26 @@ #define M_CVTIF(src, dst) N_CEFBR(dst, src) #define M_CVTID(src, dst) N_CDFBR(dst, src) #define M_FMUL(a, dest) N_MEEBR(dest, a) +#define M_FSUB(a, dest) N_SEBR(dest, a) +#define M_FADD(a, dest) N_AEBR(dest, a) +#define M_FDIV(a, dest) N_DEBR(dest, a) +#define M_DMUL(a, dest) N_MDBR(dest, a) +#define M_DSUB(a, dest) N_SDBR(dest, a) +#define M_DADD(a, dest) N_ADBR(dest, a) +#define M_DDIV(a, dest) N_DDBR(dest, a) #define M_CVTFI(src, dst) N_CFEBR(dst, 5, src) #define M_IADD(a, dest) N_AR(dest, a) #define M_ISUB(a, dest) N_SR(dest, a) #define M_IAND(a, dest) N_NR(dest, a) +#define M_IOR(a, dest) N_OR(dest, a) +#define M_IXOR(a, dest) N_XR(dest, a) #define M_CVTFD(src,dst) N_LDEBR(dst, src) #define M_ISLL_IMM(imm,reg) N_SLL(reg, imm, RN) #define M_ISRL_IMM(imm,reg) N_SRL(reg, imm, RN) #define M_IMUL_IMM(val, reg) N_MHI(reg, val) -#define M_IMUL(a, dest) N_MR(dest, a) +#define M_IMUL(a, dest) N_MSR(dest, a) #define ICONST(reg, i) \ do { \ @@ -637,6 +666,12 @@ } \ } while (0) +#define LCONST(reg,c) \ + do { \ + ICONST(GET_HIGH_REG((reg)), (s4) ((s8) (c) >> 32)); \ + ICONST(GET_LOW_REG((reg)), (s4) ((s8) (c))); \ + } while (0) + /* M_INTMOVE: generates an integer-move from register a to b. if a and b are the same int-register, no code will be generated. @@ -732,9 +767,6 @@ #define M_INEG(a) _DEPR( M_INEG(a) ) #define M_LNEG(a) _DEPR( M_LNEG(a) ) -#define M_IOR(a,b) _DEPR( M_IOR(a,b) ) -#define M_IXOR(a,b) _DEPR( M_IXOR(a,b) ) - #define M_IAND_IMM(a,b) _DEPR( M_IAND_IMM(a,b) ) #define M_IOR_IMM(a,b) _DEPR( M_IOR_IMM(a,b) ) #define M_IXOR_IMM(a,b) _DEPR( M_IXOR_IMM(a,b) ) @@ -805,14 +837,6 @@ #define M_FST32(a,b,disp) _DEPR( M_FST32(a,b,disp) ) #define M_DST32(a,b,disp) _DEPR( M_DST32(a,b,disp) ) -#define M_FADD(a,b) _DEPR( M_FADD(a,b) ) -#define M_DADD(a,b) _DEPR( M_DADD(a,b) ) -#define M_FSUB(a,b) _DEPR( M_FSUB(a,b) ) -#define M_DSUB(a,b) _DEPR( M_DSUB(a,b) ) -#define M_DMUL(a,b) _DEPR( M_DMUL(a,b) ) -#define M_FDIV(a,b) _DEPR( M_FDIV(a,b) ) -#define M_DDIV(a,b) _DEPR( M_DDIV(a,b) ) - #define M_CVTLF(a,b) _DEPR( M_CVTLF(a,b) ) #define M_CVTLD(a,b) _DEPR( M_CVTLD(a,b) ) #define M_CVTDI(a,b) _DEPR( M_CVTDI(a,b) ) diff --git a/src/vm/jit/s390/emit.c b/src/vm/jit/s390/emit.c index 1fd742a8f..50b29fcb0 100644 --- a/src/vm/jit/s390/emit.c +++ b/src/vm/jit/s390/emit.c @@ -26,7 +26,7 @@ Authors: Christian Thalinger - $Id: emit.c 7483 2007-03-08 13:17:40Z michi $ + $Id: emit.c 7581 2007-03-26 07:23:16Z pm $ */ @@ -212,15 +212,15 @@ void emit_cmovxx(codegendata *cd, instruction *iptr, s4 s, s4 d) *******************************************************************************/ -void emit_exception_stubs(jitdata *jd) +__PORTED__ void emit_exception_stubs(jitdata *jd) { -#if 0 codegendata *cd; registerdata *rd; exceptionref *er; s4 branchmpc; s4 targetmpc; s4 targetdisp; + s4 disp; /* get required compiler data */ @@ -241,6 +241,8 @@ void emit_exception_stubs(jitdata *jd) MCODECHECK(512); + /* move index register into REG_ITMP1 */ + /* Check if the exception is an ArrayIndexOutOfBoundsException. If so, move index register into a4. */ @@ -250,38 +252,57 @@ void emit_exception_stubs(jitdata *jd) /* calcuate exception address */ - M_MOV_IMM(0, rd->argintregs[3]); - dseg_adddata(cd); - M_AADD_IMM32(er->branchpos - 6, rd->argintregs[3]); + if (N_VALID_DISP(er->branchpos - 4)) { + M_LDA(rd->argintregs[3], REG_PV, er->branchpos - 4); + } else { + M_INTMOVE(REG_PV, rd->argintregs[3]); + M_AADD_IMM(er->branchpos - 4, REG_PV); + } - /* move function to call into REG_ITMP3 */ + /* move function to call into REG_ITMP! */ - M_MOV_IMM(er->function, REG_ITMP3); + disp = dseg_add_functionptr(cd, er->function); + M_ALD(REG_ITMP1, REG_PV, disp); if (targetdisp == 0) { - targetdisp = cd->mcodeptr - cd->mcodebase; + targetdisp = (cd->mcodeptr) - (cd->mcodebase); - emit_lea_membase_reg(cd, RIP, -((cd->mcodeptr + 7) - cd->mcodebase), rd->argintregs[0]); + M_MOV(REG_PV, 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_ALD(rd->argintregs[2], + REG_SP, cd->stackframesize * 4 - SIZEOF_VOID_P); + + M_ASUB_IMM((2 * 4) + 96, REG_SP); + + M_AST(rd->argintregs[3], REG_SP, (0 * 4) + 96); /* store XPC */ + + M_MOV(REG_ITMP1, REG_PV); + M_JSR(REG_RA, REG_PV); + + /* Recalculate PV */ + + N_BASR(REG_ITMP1, RN); + disp = (s4) (cd->mcodeptr - cd->mcodebase); + M_LDA(REG_PV, REG_ITMP1, -disp); - M_CALL(REG_ITMP3); + M_MOV(REG_RESULT, REG_ITMP1_XPTR); - M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8); - M_AADD_IMM(2 * 8, REG_SP); + M_ALD(REG_ITMP2_XPC, REG_SP, (0 * 4) + 96); + M_AADD_IMM((2 * 4) + 96, REG_SP); - M_MOV_IMM(asm_handle_exception, REG_ITMP3); - M_JMP(REG_ITMP3); + disp = dseg_add_functionptr(cd, asm_handle_exception); + M_ALD(REG_ITMP3, REG_PV, disp); + M_JMP(RN, REG_ITMP3); } else { - M_JMP_IMM((cd->mcodebase + targetdisp) - - (cd->mcodeptr + PATCHER_CALL_SIZE)); + disp = ((cd->mcodebase) + targetdisp) - + (( cd->mcodeptr) ); + + M_BR(disp); } + } -#endif } @@ -2338,7 +2359,7 @@ void emit_rdtsc(codegendata *cd) *******************************************************************************/ -s4 emit_load_high(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg) +__PORTED__ s4 emit_load_high(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg) { codegendata *cd; s4 disp; @@ -2355,7 +2376,7 @@ s4 emit_load_high(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg) disp = src->vv.regoff * 4; - M_ILD(tempreg, REG_SP, disp); + M_ILD(tempreg, REG_SP, disp + 4); reg = tempreg; } @@ -2371,7 +2392,7 @@ s4 emit_load_high(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg) *******************************************************************************/ -s4 emit_load_low(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg) +__PORTED__ s4 emit_load_low(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg) { codegendata *cd; s4 disp; @@ -2388,7 +2409,7 @@ s4 emit_load_low(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg) disp = src->vv.regoff * 4; - M_ILD(tempreg, REG_SP, disp + 4); + M_ILD(tempreg, REG_SP, disp); reg = tempreg; } @@ -2450,6 +2471,28 @@ s4 emit_load_s2_notzero(jitdata *jd, instruction *iptr, s4 tempreg) { } } +s4 emit_load_s1_but(jitdata *jd, instruction *iptr, s4 tempreg, s4 notreg) { + codegendata *cd = jd->cd; + s4 reg = emit_load_s1(jd, iptr, tempreg); + if (reg == notreg) { + M_MOV(reg, tempreg); + return tempreg; + } else { + return reg; + } +} + +s4 emit_load_s2_but(jitdata *jd, instruction *iptr, s4 tempreg, s4 notreg) { + codegendata *cd = jd->cd; + s4 reg = emit_load_s2(jd, iptr, tempreg); + if (reg == notreg) { + M_MOV(reg, tempreg); + return tempreg; + } else { + return reg; + } +} + /* * 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 diff --git a/src/vm/jit/s390/emit.h b/src/vm/jit/s390/emit.h index 478fbfbab..13bfedba3 100644 --- a/src/vm/jit/s390/emit.h +++ b/src/vm/jit/s390/emit.h @@ -28,7 +28,7 @@ Changes: - $Id: emit.h 7483 2007-03-08 13:17:40Z michi $ + $Id: emit.h 7581 2007-03-26 07:23:16Z pm $ */ @@ -360,6 +360,9 @@ void emit_rdtsc(codegendata *cd); s4 emit_load_s1_notzero(jitdata *jd, instruction *iptr, s4 tempreg); s4 emit_load_s2_notzero(jitdata *jd, instruction *iptr, s4 tempreg); +s4 emit_load_s1_but(jitdata *jd, instruction *iptr, s4 tempreg, s4 notreg); +s4 emit_load_s2_but(jitdata *jd, instruction *iptr, s4 tempreg, s4 notreg); + #endif /* _MD_EMIT_H */ diff --git a/src/vm/jit/s390/md-abi.c b/src/vm/jit/s390/md-abi.c index a644ef7e8..4cc4992c6 100644 --- a/src/vm/jit/s390/md-abi.c +++ b/src/vm/jit/s390/md-abi.c @@ -28,7 +28,7 @@ Changes: - $Id: md-abi.c 7407 2007-02-26 19:12:03Z michi $ + $Id: md-abi.c 7581 2007-03-26 07:23:16Z pm $ */ @@ -40,6 +40,7 @@ #include "vmcore/descriptor.h" #include "vm/global.h" +#include "vm/jit/jit.h" /* register descripton array **************************************************/ @@ -80,7 +81,7 @@ const s4 abi_registers_integer_temporary[] = { }; s4 nregdescfloat[] = { - REG_ARG, REG_TMP, REG_ARG, REG_TMP, REG_SAV, REG_TMP, REG_SAV, REG_TMP, + REG_ARG, REG_TMP, REG_ARG, REG_TMP, REG_RES, REG_TMP, REG_RES, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_END }; @@ -91,8 +92,8 @@ const s4 abi_registers_float_argument[] = { }; const s4 abi_registers_float_saved[] = { - 4, /* f4/fs0 */ - 6 /* f6/fs0 */ + /* nothing */ + -1 }; const s4 abi_registers_float_temporary[] = { @@ -138,51 +139,91 @@ void md_param_alloc(methoddesc *md) switch (md->paramtypes[i].type) { case TYPE_INT: case TYPE_ADR: - case TYPE_LNG: if (iarg < INT_ARG_CNT) { - pd->inmemory = false; - pd->regoff = iarg; + pd->inmemory = false; +/* pd->regoff = abi_registers_integer_argument[iarg]; */ + pd->regoff = iarg; + iarg++; } else { - pd->inmemory = true; - pd->regoff = stacksize; - } - if (iarg < INT_ARG_CNT) - iarg++; - else + pd->inmemory = true; + pd->regoff = stacksize; stacksize++; + } + break; + + case TYPE_LNG: + if (iarg < INT_ARG_CNT - 1) { + /* _ALIGN(iarg); */ + pd->inmemory = false; +/* pd->regoff = */ +/* PACK_REGS(abi_registers_integer_argument[iarg + 1], */ +/* abi_registers_integer_argument[iarg]); */ + pd->regoff = PACK_REGS(iarg + 1, iarg); + iarg += 2; + } + else { + /* _ALIGN(stacksize); */ + pd->inmemory = true; + pd->regoff = stacksize; + iarg = INT_ARG_CNT; + stacksize += 2; + } break; case TYPE_FLT: - case TYPE_DBL: if (farg < FLT_ARG_CNT) { - pd->inmemory = false; - pd->regoff = farg; + pd->inmemory = false; +/* pd->regoff = abi_registers_float_argument[farg]; */ + pd->regoff = farg; + farg++; } else { - pd->inmemory = true; - pd->regoff = stacksize; + pd->inmemory = true; + pd->regoff = stacksize; + stacksize++; } - if (farg < FLT_ARG_CNT) + break; + + case TYPE_DBL: + if (farg < FLT_ARG_CNT) { + pd->inmemory = false; +/* pd->regoff = abi_registers_integer_argument[farg]; */ + pd->regoff = farg; farg++; - else - stacksize++; + } + else { + /* _ALIGN(stacksize); */ + pd->inmemory = true; + pd->regoff = stacksize; + stacksize += 2; + } break; + + default: + assert(0); } } - /* Since XMM0 (==A0) is used for passing return values, this - argument register usage has to be regarded, too. */ + /* Since R3/R4, F1 (==A0/A1, A0) are used for passing return + values, this argument register usage has to be regarded, + too. */ - if (IS_FLT_DBL_TYPE(md->returntype.type)) - if (farg < 1) - farg = 1; + if (IS_INT_LNG_TYPE(md->returntype.type)) { + if (iarg < (IS_2_WORD_TYPE(md->returntype.type) ? 2 : 1)) + iarg = IS_2_WORD_TYPE(md->returntype.type) ? 2 : 1; + } + else { + if (IS_FLT_DBL_TYPE(md->returntype.type)) + if (farg < 1) + farg = 1; + } /* fill register and stack usage */ md->argintreguse = iarg; md->argfltreguse = farg; - md->memuse = stacksize; + md->memuse = stacksize; } void md_param_alloc_native(methoddesc *md) @@ -228,25 +269,32 @@ void md_return_alloc(jitdata *jd, stackptr stackslot) md = m->parseddesc; - /* precoloring only straightforward possible with flt/dbl types - For Address/Integer/Long REG_RESULT == rax == REG_ITMP1 and so - could be destroyed if the return value Stack Slot "lives too - long" */ + /* In Leafmethods Local Vars holding parameters are precolored to + their argument register -> so leafmethods with paramcount > 0 + could already use R3 == a00! */ - if (IS_FLT_DBL_TYPE(md->returntype.type)) { - /* In Leafmethods Local Vars holding parameters are precolored - to their argument register -> so leafmethods with - paramcount > 0 could already use a00! */ + if (!jd->isleafmethod || (md->paramcount == 0)) { + /* Only precolor the stackslot, if it is not a SAVEDVAR <-> + has not to survive method invokations. */ - if (!jd->isleafmethod || (md->paramcount == 0)) { - /* Only precolor the stackslot, if it is not a SAVEDVAR - <-> has not to survive method invokations */ + if (!(stackslot->flags & SAVEDVAR)) { + VAR(stackslot->varnum)->flags = PREALLOC; - if (!(stackslot->flags & SAVEDVAR)) { + if (IS_INT_LNG_TYPE(md->returntype.type)) { + if (!IS_2_WORD_TYPE(md->returntype.type)) { + if (rd->argintreguse < 1) + rd->argintreguse = 1; - VAR(stackslot->varnum)->flags = PREALLOC; + VAR(stackslot->varnum)->vv.regoff = REG_RESULT; + } + else { + if (rd->argintreguse < 2) + rd->argintreguse = 2; - /* float/double */ + VAR(stackslot->varnum)->vv.regoff = REG_RESULT_PACKED; + } + } + else { /* float/double */ if (rd->argfltreguse < 1) rd->argfltreguse = 1; diff --git a/src/vm/jit/s390/md-abi.h b/src/vm/jit/s390/md-abi.h index 9d1fdfc02..7f74b788a 100644 --- a/src/vm/jit/s390/md-abi.h +++ b/src/vm/jit/s390/md-abi.h @@ -28,7 +28,7 @@ Changes: - $Id: md-abi.h 7483 2007-03-08 13:17:40Z michi $ + $Id: md-abi.h 7581 2007-03-26 07:23:16Z pm $ */ @@ -155,9 +155,10 @@ #define REG_FRESULT F0 /* to deliver floating point method results */ -#define REG_FTMP1 F1 /* temporary floating point register */ -#define REG_FTMP2 F3 /* temporary floating point register */ -#define REG_FTMP3 F5 /* temporary floating point register */ +#define REG_FTMP1 F4 /* temporary floating point register */ +#define REG_FTMP2 F6 /* temporary floating point register */ +/* No ftmp3 */ +/* #define REG_FTMP3 F5 */ /* temporary floating point register */ #define __REG_IFTMP 10 /* temporary integer and floating point register */ @@ -169,10 +170,10 @@ #define INT_RES_CNT 5 /* number of integer reserved registers */ #define FLT_REG_CNT 16 /* number of float registers */ -#define FLT_SAV_CNT 2 /* number of float callee saved registers */ +#define FLT_SAV_CNT 0 /* number of float callee saved registers */ #define FLT_ARG_CNT 2 /* number of float argument registers */ #define FLT_TMP_CNT 12 /* number of float temporary registers */ -#define FLT_RES_CNT 0 /* number of float reserved registers */ +#define FLT_RES_CNT 2 /* number of float reserved registers */ #define TRACE_ARGS_NUM 8 diff --git a/src/vm/jit/s390/md.c b/src/vm/jit/s390/md.c index 42d16449b..e3d250353 100644 --- a/src/vm/jit/s390/md.c +++ b/src/vm/jit/s390/md.c @@ -28,7 +28,7 @@ Changes: Edwin Steiner - $Id: md.c 7367 2007-02-16 07:17:01Z pm $ + $Id: md.c 7581 2007-03-26 07:23:16Z pm $ */ @@ -36,15 +36,12 @@ #define REG_RIP 0 #define REG_RAX 0 #define REG_R10 0 -#define REG_ITMP2 0 #define REG_RIP 0 #define REG_RSP 0 #define REG_RIP 0 #define REG_RAX 0 #define REG_R10 0 -#define REG_ITMP2 0 #define REG_RIP 0 -#define REG_METHODPTR 0 #define _GNU_SOURCE @@ -71,6 +68,9 @@ #include "vm/jit/disass.h" /* XXX debug */ #endif +#include "vm/jit/codegen-common.h" +#include "vm/jit/s390/codegen.h" + #include #define OOPS() assert(0); @@ -225,7 +225,7 @@ void md_codegen_patch_branch(codegendata *cd, s4 branchmpc, s4 targetmpc) disp += 4; /* size of branch */ disp /= 2; /* specified in halfwords */ - /* TODO check for overflow */ + ASSERT_VALID_BRANCH(disp); /* patch the branch instruction before the mcodeptr */ diff --git a/src/vm/jit/s390/patcher.c b/src/vm/jit/s390/patcher.c index ba568c2c2..74a382118 100644 --- a/src/vm/jit/s390/patcher.c +++ b/src/vm/jit/s390/patcher.c @@ -28,7 +28,7 @@ Changes: - $Id: patcher.c 7483 2007-03-08 13:17:40Z michi $ + $Id: patcher.c 7581 2007-03-26 07:23:16Z pm $ */ @@ -37,6 +37,7 @@ #include "vm/types.h" #include "vm/jit/s390/codegen.h" +#include "vm/jit/s390/md-abi.h" #include "mm/memory.h" #include "native/native.h" @@ -86,7 +87,6 @@ java_objectheader *patcher_wrapper(u1 *sp, u1 *pv, u1 *ra) o = (java_objectheader *) *((ptrint *) (sp + 4 * 4)); f = (functionptr) *((ptrint *) (sp + 0 * 4)); - /* TODO here was PATCHER_CALL_SIZE previously ! */ xpc = xpc - 4; /* the patch position is 4 bytes before the RA */ *((ptrint *) (sp + 5 * 4)) = (ptrint) xpc; @@ -246,63 +246,48 @@ bool patcher_get_putstatic(u1 *sp) Machine code: - - 45 8b 8f 00 00 00 00 mov 0x0(%r15),%r9d - *******************************************************************************/ bool patcher_get_putfield(u1 *sp) { - OOPS(); u1 *ra; - u8 mcode; + u4 mcode; unresolved_field *uf; fieldinfo *fi; u1 byte; /* get stuff from the stack */ - ra = (u1 *) *((ptrint *) (sp + 5 * 8)); - mcode = *((u8 *) (sp + 3 * 8)); - uf = (unresolved_field *) *((ptrint *) (sp + 2 * 8)); + ra = (u1 *) *((ptrint *) (sp + 5 * 4)); + mcode = *((u4 *) (sp + 3 * 4)); + uf = (unresolved_field *) *((ptrint *) (sp + 2 * 4)); /* get the fieldinfo */ if (!(fi = resolve_field_eager(uf))) return false; - /* patch back original code (instruction code is smaller than 8 bytes) */ + /* patch back original code */ - *((u4 *) (ra + 0)) = (u4) mcode; - *((u1 *) (ra + 4)) = (u1) (mcode >> 32); + *((u4 *) ra) = mcode; - /* if we show disassembly, we have to skip the nop's */ + /* If NOPs are generated, skip them */ if (opt_shownops) - ra = ra + 5; - - /* patch the field's offset: we check for the field type, because the */ - /* instructions have different lengths */ - - if (IS_INT_LNG_TYPE(fi->type)) { - /* check for special case: %rsp or %r12 as base register */ - - byte = *(ra + 3); - - if (byte == 0x24) - *((u4 *) (ra + 4)) = (u4) (fi->offset); - else - *((u4 *) (ra + 3)) = (u4) (fi->offset); - } - else { - /* check for special case: %rsp or %r12 as base register */ - - byte = *(ra + 5); - - if (byte == 0x24) - *((u4 *) (ra + 6)) = (u4) (fi->offset); - else - *((u4 *) (ra + 5)) = (u4) (fi->offset); + ra += PATCHER_NOPS_SKIP; + + /* patch correct offset */ + + if (fi->type == TYPE_LNG) { + assert(N_VALID_DISP(fi->offset + 4)); + /* 2 RX operations, for 2 words; each already contains a 0 or 4 offset. */ + *((u4 *) ra ) |= (fi->offset + (*((u4 *) ra) & 0xF)); + ra += 4; + *((u4 *) ra ) |= (fi->offset + (*((u4 *) ra) & 0xF)); + } else { + assert(N_VALID_DISP(fi->offset)); + /* 1 RX operation */ + *((u4 *) ra) |= fi->offset; } return true; @@ -583,6 +568,11 @@ bool patcher_invokevirtual(u1 *sp) *((u4 *) ra) = mcode; + /* If NOPs are generated, skip them */ + + if (opt_shownops) + ra += PATCHER_NOPS_SKIP; + /* patch vftbl index */ @@ -591,7 +581,7 @@ bool patcher_invokevirtual(u1 *sp) assert(N_VALID_DISP(off)); - *((s4 *)(ra + 4 + 4)) |= off; + *((s4 *)(ra + 4)) |= off; return true; } @@ -626,6 +616,11 @@ bool patcher_invokeinterface(u1 *sp) *((u4 *) ra) = mcode; + /* If NOPs are generated, skip them */ + + if (opt_shownops) + ra += PATCHER_NOPS_SKIP; + /* get interfacetable index */ idx = (s4) (OFFSET(vftbl_t, interfacetable[0]) - @@ -642,8 +637,8 @@ bool patcher_invokeinterface(u1 *sp) /* patch them */ - *((s4 *)(ra + 4 + 4)) |= idx; - *((s4 *)(ra + 4 + 4 + 4)) |= off; + *((s4 *)(ra + 4)) |= idx; + *((s4 *)(ra + 4 + 4)) |= off; return true; } @@ -775,28 +770,20 @@ bool patcher_resolve_classref_to_vftbl(u1 *sp) Machine code: - - 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 - 4d 8b 9a 00 00 00 00 mov 0x0(%r10),%r11 - *******************************************************************************/ bool patcher_checkcast_instanceof_interface(u1 *sp) { - OOPS(); u1 *ra; - u8 mcode; + u4 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)); + ra = (u1 *) *((ptrint *) (sp + 5 * 4)); + mcode = *((u4 *) (sp + 3 * 4)); + cr = (constant_classref *) *((ptrint *) (sp + 2 * 4)); /* get the fieldinfo */ @@ -805,20 +792,36 @@ bool patcher_checkcast_instanceof_interface(u1 *sp) /* patch back original code */ - *((u8 *) ra) = mcode; + *((u4 *) ra) = mcode; - /* if we show disassembly, we have to skip the nop's */ + /* If NOPs are generated, skip them */ if (opt_shownops) - ra = ra + 5; + ra += PATCHER_NOPS_SKIP; /* patch super class index */ - *((s4 *) (ra + 7 + 3)) = (s4) c->index; + /* From here, split your editor and open codegen.c */ + + switch (*(ra + 1) >> 4) { + case REG_ITMP1: + /* First M_ALD is into ITMP1 */ + /* INSTANCEOF code */ + case REG_ITMP2: + /* First M_ALD is into ITMP1 */ + /* CHECKCAST code */ - *((s4 *) (ra + 7 + 7 + 3 + 6 + 3)) = - (s4) (OFFSET(vftbl_t, interfacetable[0]) - - c->index * sizeof(methodptr*)); + *(u4 *)(ra + SZ_L + SZ_L) |= (u2)(s2)(- c->index); + *(u4 *)(ra + SZ_L + SZ_L + SZ_AHI + SZ_BRC) |= + (u2)(s2)(OFFSET(vftbl_t, interfacetable[0]) - + c->index * sizeof(methodptr*)); + + break; + + default: + assert(0); + break; + } return true; } diff --git a/src/vm/jit/sparc64/arch.h b/src/vm/jit/sparc64/arch.h index 0708fc2d0..459ad892a 100644 --- a/src/vm/jit/sparc64/arch.h +++ b/src/vm/jit/sparc64/arch.h @@ -90,6 +90,14 @@ #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 diff --git a/src/vm/jit/sparc64/asmpart.S b/src/vm/jit/sparc64/asmpart.S index 6567e1da3..cfaf31e2a 100644 --- a/src/vm/jit/sparc64/asmpart.S +++ b/src/vm/jit/sparc64/asmpart.S @@ -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 diff --git a/src/vm/jit/sparc64/codegen.c b/src/vm/jit/sparc64/codegen.c index 792082849..e26d96df7 100644 --- a/src/vm/jit/sparc64/codegen.c +++ b/src/vm/jit/sparc64/codegen.c @@ -29,9 +29,8 @@ #include "config.h" -#include #include - +#include #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" @@ -68,18 +68,38 @@ 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. @@ -2989,9 +2936,6 @@ u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd) cd = jd->cd; rd = jd->rd; - /* redo param allocation */ - md_native_param_alloc(nmd); - /* initialize variables */ md = m->parseddesc; diff --git a/src/vm/jit/sparc64/codegen.h b/src/vm/jit/sparc64/codegen.h index 447718d76..6edfa3b1b 100644 --- a/src/vm/jit/sparc64/codegen.h +++ b/src/vm/jit/sparc64/codegen.h @@ -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.c b/src/vm/jit/sparc64/emit.c index b015d17be..2595d79e8 100644 --- a/src/vm/jit/sparc64/emit.c +++ b/src/vm/jit/sparc64/emit.c @@ -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, @@ -28,13 +28,18 @@ #include "config.h" + +#include + #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. diff --git a/src/vm/jit/sparc64/linux/md-os.c b/src/vm/jit/sparc64/linux/md-os.c index a2eed3eb7..5f50a10b2 100644 --- a/src/vm/jit/sparc64/linux/md-os.c +++ b/src/vm/jit/sparc64/linux/md-os.c @@ -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, @@ -22,23 +22,19 @@ 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 -#include +#include #include "vm/types.h" +#include "vm/jit/sparc64/codegen.h" #include "vm/jit/sparc64/md-abi.h" #include "vm/exceptions.h" @@ -48,6 +44,40 @@ #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 @@ -55,46 +85,70 @@ *******************************************************************************/ -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: */ diff --git a/src/vm/jit/sparc64/md-abi.c b/src/vm/jit/sparc64/md-abi.c index 68a5fe11c..a0e6d8f07 100644 --- a/src/vm/jit/sparc64/md-abi.c +++ b/src/vm/jit/sparc64/md-abi.c @@ -160,13 +160,14 @@ void md_param_alloc(methoddesc *md) md->memuse = stacksize; } -/* md_native_param_alloc ************************************************************** - XXX - -*******************************************************************************/ +/* md_param_alloc_native ******************************************************* + * + * Pre-allocate arguments according to the native ABI. + * + * *******************************************************************************/ -void md_native_param_alloc(methoddesc *md) +void md_param_alloc_native(methoddesc *md) { paramdesc *pd; s4 i; @@ -229,61 +230,6 @@ void md_native_param_alloc(methoddesc *md) md->memuse = stacksize; } -/* md_param_alloc_native ******************************************************* - * - * Pre-allocate arguments according to the native ABI. - * - * *******************************************************************************/ - -void md_param_alloc_native(methoddesc *md) -{ - /* XXX need to merge this with my hacked solution to the same problem */ - md_param_alloc(md); -} - -/* reg_setup ******************************************************************* - - TODO - -*******************************************************************************/ -#if 0 -void md_native_reg_setup(jitdata *jd) -{ - methodinfo *m; - registerdata *rd; - s4 i; - - /* get required compiler data */ - - m = jd->m; - rd = jd->rd; - - /* setup the integer register table */ - - - rd->argintregs = DMNEW(s4, INT_NATARG_CNT); - rd->argintreguse = 0; - - for (rd->argintreguse = 0, i = 8; rd->argintreguse < INT_NATARG_CNT; i++) { - rd->argintregs[rd->argintreguse++] = i; - } - - assert(rd->argintreguse == INT_NATARG_CNT); - - /* setup the float register table */ - - rd->argfltregs = DMNEW(s4, FLT_NATARG_CNT); - - rd->argfltreguse = 0; - - - for (rd->argfltreguse = 0, i = 0; rd->argfltreguse < FLT_NATARG_CNT; i++) { - rd->argfltregs[rd->argfltreguse++] = i; - } - assert(rd->argfltreguse == FLT_NATARG_CNT); - -} -#endif /* md_return_alloc ************************************************************* XXX diff --git a/src/vm/jit/sparc64/md.c b/src/vm/jit/sparc64/md.c index ee1bdfe29..9a55c3695 100644 --- a/src/vm/jit/sparc64/md.c +++ b/src/vm/jit/sparc64/md.c @@ -46,8 +46,17 @@ #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; } diff --git a/src/vm/jit/sparc64/patcher.c b/src/vm/jit/sparc64/patcher.c index 9f76e1ffe..e9467d192 100644 --- a/src/vm/jit/sparc64/patcher.c +++ b/src/vm/jit/sparc64/patcher.c @@ -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)); diff --git a/src/vm/jit/stacktrace.c b/src/vm/jit/stacktrace.c index 0e3e4df10..c540b0347 100644 --- a/src/vm/jit/stacktrace.c +++ b/src/vm/jit/stacktrace.c @@ -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 7596 2007-03-28 21:05:53Z twisti $ */ @@ -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 */ diff --git a/src/vm/jit/verify/typecheck-invoke.inc b/src/vm/jit/verify/typecheck-invoke.inc index bad9f4af6..1e4ee26dd 100644 --- a/src/vm/jit/verify/typecheck-invoke.inc +++ b/src/vm/jit/verify/typecheck-invoke.inc @@ -26,8 +26,6 @@ Authors: Edwin Steiner - Changes: - $Id$ */ @@ -312,7 +310,8 @@ 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 { diff --git a/src/vm/jit/x86_64/arch.h b/src/vm/jit/x86_64/arch.h index 25f8a0747..4db3d27a9 100644 --- a/src/vm/jit/x86_64/arch.h +++ b/src/vm/jit/x86_64/arch.h @@ -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 7596 2007-03-28 21:05:53Z twisti $ */ @@ -99,6 +99,14 @@ #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 diff --git a/src/vm/jit/x86_64/asmpart.S b/src/vm/jit/x86_64/asmpart.S index 79d21ea83..fc54876a2 100644 --- a/src/vm/jit/x86_64/asmpart.S +++ b/src/vm/jit/x86_64/asmpart.S @@ -22,7 +22,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - $Id: asmpart.S 7483 2007-03-08 13:17:40Z michi $ + $Id: asmpart.S 7596 2007-03-28 21:05:53Z 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 ***************************** * * diff --git a/src/vm/jit/x86_64/codegen.c b/src/vm/jit/x86_64/codegen.c index d6915b2a0..0ddd91b45 100644 --- a/src/vm/jit/x86_64/codegen.c +++ b/src/vm/jit/x86_64/codegen.c @@ -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 7596 2007-03-28 21:05:53Z twisti $ */ @@ -75,13 +75,13 @@ #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; diff --git a/src/vm/jit/x86_64/codegen.h b/src/vm/jit/x86_64/codegen.h index 8b9e96a31..2e8140380 100644 --- a/src/vm/jit/x86_64/codegen.h +++ b/src/vm/jit/x86_64/codegen.h @@ -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 7596 2007-03-28 21:05:53Z twisti $ */ @@ -43,17 +43,6 @@ /* 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) \ @@ -64,9 +53,10 @@ #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: @@ -118,6 +108,9 @@ /* 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; \ @@ -125,6 +118,7 @@ M_NOP; \ M_NOP; \ M_NOP; \ + M_NOP; \ } while (0) @@ -192,6 +186,14 @@ #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) @@ -199,10 +201,13 @@ #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) @@ -250,6 +255,7 @@ #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)) @@ -259,8 +265,14 @@ #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)) @@ -269,15 +281,8 @@ #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)) diff --git a/src/vm/jit/x86_64/emit.c b/src/vm/jit/x86_64/emit.c index 6c6be8218..70e52f9a7 100644 --- a/src/vm/jit/x86_64/emit.c +++ b/src/vm/jit/x86_64/emit.c @@ -22,7 +22,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - $Id: emit.c 7483 2007-03-08 13:17:40Z michi $ + $Id: emit.c 7596 2007-03-28 21:05:53Z 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)); diff --git a/src/vm/jit/x86_64/emit.h b/src/vm/jit/x86_64/emit.h index ce88f97b7..5296dd259 100644 --- a/src/vm/jit/x86_64/emit.h +++ b/src/vm/jit/x86_64/emit.h @@ -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 @@ -22,13 +22,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - Contact: cacao@cacaojvm.org - - Authors: Christian Thalinger - - Changes: - - $Id: emit.h 6087 2006-11-29 20:15:47Z twisti $ + $Id: emit.h 7596 2007-03-28 21:05:53Z 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); diff --git a/src/vm/jit/x86_64/linux/md-os.c b/src/vm/jit/x86_64/linux/md-os.c index 298c85866..c8ec58b42 100644 --- a/src/vm/jit/x86_64/linux/md-os.c +++ b/src/vm/jit/x86_64/linux/md-os.c @@ -35,10 +35,15 @@ #include #include +#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" @@ -47,18 +52,25 @@ /* 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; } diff --git a/src/vm/jit/x86_64/md.c b/src/vm/jit/x86_64/md.c index e59e81f58..7514f1edb 100644 --- a/src/vm/jit/x86_64/md.c +++ b/src/vm/jit/x86_64/md.c @@ -22,7 +22,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - $Id: md.c 7483 2007-03-08 13:17:40Z michi $ + $Id: md.c 7596 2007-03-28 21:05:53Z 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 diff --git a/src/vm/jit/x86_64/patcher.c b/src/vm/jit/x86_64/patcher.c index c0623969b..ef1551844 100644 --- a/src/vm/jit/x86_64/patcher.c +++ b/src/vm/jit/x86_64/patcher.c @@ -22,7 +22,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - $Id: patcher.c 7483 2007-03-08 13:17:40Z michi $ + $Id: patcher.c 7596 2007-03-28 21:05:53Z 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: 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: + + + 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: diff --git a/src/vm/signal.c b/src/vm/signal.c index 4425ae871..096bb0c93 100644 --- a/src/vm/signal.c +++ b/src/vm/signal.c @@ -22,7 +22,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - $Id: signal.c 7483 2007-03-08 13:17:40Z michi $ + $Id: signal.c 7601 2007-03-28 23:02:50Z michi $ */ @@ -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 diff --git a/src/vm/signallocal.h b/src/vm/signallocal.h index 0ded4eafb..eaef44b32 100644 --- a/src/vm/signallocal.h +++ b/src/vm/signallocal.h @@ -22,7 +22,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - $Id: signallocal.h 7480 2007-03-08 12:46:19Z michi $ + $Id: signallocal.h 7601 2007-03-28 23:02:50Z michi $ */ @@ -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_sigusr1(int sig, siginfo_t *siginfo, void *_p); void md_signal_handler_sigusr2(int sig, siginfo_t *siginfo, void *_p); diff --git a/src/vm/string.c b/src/vm/string.c index 20749900e..a9b1d1a33 100644 --- a/src/vm/string.c +++ b/src/vm/string.c @@ -22,7 +22,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - $Id: string.c 7257 2007-01-29 23:07:40Z twisti $ + $Id: string.c 7522 2007-03-14 21:54:49Z twisti $ */ @@ -52,6 +52,7 @@ #include "vm/stringlocal.h" #include "vmcore/options.h" +#include "vmcore/statistics.h" #include "vmcore/utf8.h" @@ -575,6 +576,11 @@ java_objectheader *literalstring_u2(java_chararray *a, u4 length, u4 offset, js = NEW(java_lang_String); +#if defined(ENABLE_STATISTICS) + if (opt_stat) + size_string += sizeof(java_lang_String); +#endif + #if defined(ENABLE_THREADS) lock_init_object_lock(&js->header); #endif @@ -587,6 +593,12 @@ java_objectheader *literalstring_u2(java_chararray *a, u4 length, u4 offset, /* create new literalstring */ s = NEW(literalstring); + +#if defined(ENABLE_STATISTICS) + if (opt_stat) + size_string += sizeof(literalstring); +#endif + s->hashlink = hashtable_string.ptr[slot]; s->string = (java_objectheader *) js; hashtable_string.ptr[slot] = s; diff --git a/src/vm/vm.c b/src/vm/vm.c index 541fbb8dd..5d1cc1e49 100644 --- a/src/vm/vm.c +++ b/src/vm/vm.c @@ -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; @@ -1474,17 +1466,17 @@ bool vm_create(JavaVMInitArgs *vm_args) /* AFTER: threads_preinit */ if (!string_init()) - throw_main_exception_exit(); + vm_abort("vm_create: string_init failed"); /* AFTER: threads_preinit */ if (!utf8_init()) - throw_main_exception_exit(); + vm_abort("vm_create: utf8_init failed"); /* AFTER: thread_preinit */ if (!suck_init()) - throw_main_exception_exit(); + vm_abort("vm_create: suck_init failed"); suck_add_from_property("java.endorsed.dirs"); @@ -1508,25 +1500,25 @@ bool vm_create(JavaVMInitArgs *vm_args) _Jv_bootclasspath pointer. */ if (!properties_postinit()) - vm_abort("properties_postinit failed"); + vm_abort("vm_create: properties_postinit failed"); /* initialize the classcache hashtable stuff: lock, hashtable (must be done _after_ threads_preinit) */ if (!classcache_init()) - throw_main_exception_exit(); + vm_abort("vm_create: classcache_init failed"); /* initialize the memory subsystem (must be done _after_ threads_preinit) */ if (!memory_init()) - throw_main_exception_exit(); + vm_abort("vm_create: memory_init failed"); /* initialize the finalizer stuff (must be done _after_ threads_preinit) */ if (!finalizer_init()) - throw_main_exception_exit(); + vm_abort("vm_create: finalizer_init failed"); /* install architecture dependent signal handlers */ @@ -1557,19 +1549,19 @@ bool vm_create(JavaVMInitArgs *vm_args) classcache_init) */ if (!loader_init()) - vm_abort("loader_init failed"); + vm_abort("vm_create: loader_init failed"); if (!linker_init()) - vm_abort("linker_init failed"); + vm_abort("vm_create: linker_init failed"); if (!native_init()) - throw_main_exception_exit(); + vm_abort("vm_create: native_init failed"); if (!exceptions_init()) - throw_main_exception_exit(); + vm_abort("vm_create: exceptions_init failed"); if (!builtin_init()) - throw_main_exception_exit(); + vm_abort("vm_create: builtin_init failed"); #if defined(ENABLE_JNI) /* Initialize the JNI subsystem (must be done _before_ @@ -1577,57 +1569,57 @@ bool vm_create(JavaVMInitArgs *vm_args) (e.g. NewGlobalRef). */ if (!jni_init()) - throw_main_exception_exit(); + vm_abort("vm_create: jni_init failed"); #endif #if defined(ENABLE_THREADS) if (!threads_init()) - throw_main_exception_exit(); + vm_abort("vm_create: threads_init failed"); #endif #if defined(ENABLE_PROFILING) /* initialize profiling */ if (!profile_init()) - throw_main_exception_exit(); + vm_abort("vm_create: profile_init failed"); #endif #if defined(ENABLE_THREADS) /* initialize recompilation */ if (!recompile_init()) - throw_main_exception_exit(); + vm_abort("vm_create: recompile_init failed"); /* start the signal handler thread */ if (!signal_start_thread()) - throw_main_exception_exit(); + vm_abort("vm_create: signal_start_thread failed"); /* finally, start the finalizer thread */ if (!finalizer_start_thread()) - throw_main_exception_exit(); + vm_abort("vm_create: finalizer_start_thread failed"); # if !defined(NDEBUG) /* start the memory profiling thread */ if (opt_verbosememory) if (!memory_start_thread()) - throw_main_exception_exit(); + vm_abort("vm_create: memory_start_thread failed"); # endif /* start the recompilation thread (must be done before the profiling thread) */ if (!recompile_start_thread()) - throw_main_exception_exit(); + vm_abort("vm_create: recompile_start_thread failed"); # if defined(ENABLE_PROFILING) /* start the profile sampling thread */ /* if (opt_prof) */ /* if (!profile_start_thread()) */ -/* throw_main_exception_exit(); */ +/* exceptions_print_stacktrace(); */ # endif #endif @@ -1695,10 +1687,15 @@ void vm_run(JavaVM *vm, JavaVMInitArgs *vm_args) status = 0; - if (opt_jar == true) + if (opt_jar == true) { /* open jar file with java.util.jar.JarFile */ + mainstring = vm_get_mainclass_from_jar(mainstring); + if (mainstring == NULL) + vm_exit(1); + } + /* load the main class */ mainutf = utf_new_char(mainstring); @@ -1711,11 +1708,15 @@ void vm_run(JavaVM *vm, JavaVMInitArgs *vm_args) /* error loading class */ - if ((exceptions_get_exception() != NULL) || (mainclass == NULL)) - throw_main_exception_exit(); + if ((exceptions_get_exception() != NULL) || (mainclass == NULL)) { + exceptions_print_stacktrace(); + vm_exit(1); + } - if (!link_class(mainclass)) - throw_main_exception_exit(); + if (!link_class(mainclass)) { + exceptions_print_stacktrace(); + vm_exit(1); + } /* find the `main' method of the main class */ @@ -1725,8 +1726,9 @@ void vm_run(JavaVM *vm, JavaVMInitArgs *vm_args) class_java_lang_Object, false); - if (*exceptionptr) { - throw_main_exception_exit(); + if (exceptions_get_exception()) { + exceptions_print_stacktrace(); + vm_exit(1); } /* there is no main method or it isn't static */ @@ -1737,7 +1739,8 @@ void vm_run(JavaVM *vm, JavaVMInitArgs *vm_args) utf_new_char("main"), utf_new_char("([Ljava/lang/String;)V")); - throw_main_exception_exit(); + exceptions_print_stacktrace(); + vm_exit(1); } /* build argument array */ @@ -1779,14 +1782,14 @@ void vm_run(JavaVM *vm, JavaVMInitArgs *vm_args) /* exception occurred? */ - if (*exceptionptr) { - throw_main_exception(); + if (exceptions_get_exception()) { + exceptions_print_stacktrace(); status = 1; } /* unload the JavaVM */ - vm_destroy(vm); + (void) vm_destroy(vm); /* and exit */ @@ -1836,8 +1839,10 @@ void vm_exit(s4 status) } #endif - if (!link_class(class_java_lang_System)) - throw_main_exception_exit(); + if (!link_class(class_java_lang_System)) { + exceptions_print_stacktrace(); + exit(1); + } /* call java.lang.System.exit(I)V */ @@ -1847,8 +1852,10 @@ void vm_exit(s4 status) class_java_lang_Object, true); - if (m == NULL) - throw_main_exception_exit(); + if (m == NULL) { + exceptions_print_stacktrace(); + exit(1); + } /* call the exit function with passed exit status */ @@ -1997,16 +2004,19 @@ static char *vm_get_mainclass_from_jar(char *mainstring) c = load_class_from_sysloader(utf_new_char("java/util/jar/JarFile")); - if (c == NULL) - throw_main_exception_exit(); - + if (c == NULL) { + exceptions_print_stacktrace(); + return NULL; + } + /* create JarFile object */ o = builtin_new(c); - if (o == NULL) - throw_main_exception_exit(); - + if (o == NULL) { + exceptions_print_stacktrace(); + return NULL; + } m = class_resolveclassmethod(c, utf_init, @@ -2014,15 +2024,19 @@ static char *vm_get_mainclass_from_jar(char *mainstring) class_java_lang_Object, true); - if (m == NULL) - throw_main_exception_exit(); + if (m == NULL) { + exceptions_print_stacktrace(); + return NULL; + } s = javastring_new_from_ascii(mainstring); (void) vm_call_method(m, o, s); - if (*exceptionptr) - throw_main_exception_exit(); + if (exceptions_get_exception()) { + exceptions_print_stacktrace(); + return NULL; + } /* get manifest object */ @@ -2032,14 +2046,16 @@ static char *vm_get_mainclass_from_jar(char *mainstring) class_java_lang_Object, true); - if (m == NULL) - throw_main_exception_exit(); + if (m == NULL) { + exceptions_print_stacktrace(); + return NULL; + } o = vm_call_method(m, o); if (o == NULL) { fprintf(stderr, "Could not get manifest from %s (invalid or corrupt jarfile?)\n", mainstring); - vm_exit(1); + return NULL; } @@ -2051,14 +2067,16 @@ static char *vm_get_mainclass_from_jar(char *mainstring) class_java_lang_Object, true); - if (m == NULL) - throw_main_exception_exit(); + if (m == NULL) { + exceptions_print_stacktrace(); + return NULL; + } o = vm_call_method(m, o); if (o == NULL) { fprintf(stderr, "Could not get main attributes from %s (invalid or corrupt jarfile?)\n", mainstring); - vm_exit(1); + return NULL; } @@ -2070,15 +2088,19 @@ static char *vm_get_mainclass_from_jar(char *mainstring) class_java_lang_Object, true); - if (m == NULL) - throw_main_exception_exit(); + if (m == NULL) { + exceptions_print_stacktrace(); + return NULL; + } s = javastring_new_from_ascii("Main-Class"); o = vm_call_method(m, o, s); - if (o == NULL) - throw_main_exception_exit(); + if (o == NULL) { + exceptions_print_stacktrace(); + return NULL; + } return javastring_tochar(o); } @@ -2175,11 +2197,13 @@ static void vm_compile_method(void) /* create, load and link the main class */ - if (!(mainclass = load_class_bootstrap(utf_new_char(mainstring)))) - throw_main_exception_exit(); + mainclass = load_class_bootstrap(utf_new_char(mainstring)); + + if (mainclass == NULL) + exceptions_print_stacktrace(); if (!link_class(mainclass)) - throw_main_exception_exit(); + exceptions_print_stacktrace(); if (opt_signature != NULL) { m = class_resolveclassmethod(mainclass, diff --git a/src/vmcore/class.c b/src/vmcore/class.c index c90c8d31a..b7c014f75 100644 --- a/src/vmcore/class.c +++ b/src/vmcore/class.c @@ -22,7 +22,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - $Id: class.c 7483 2007-03-08 13:17:40Z michi $ + $Id: class.c 7601 2007-03-28 23:02:50Z michi $ */ @@ -49,6 +49,8 @@ #include "vm/exceptions.h" #include "vm/global.h" +#include "vm/jit/asmpart.h" + #include "vmcore/class.h" #include "vmcore/classcache.h" #include "vmcore/loader.h" @@ -1382,6 +1384,56 @@ bool class_issubclass(classinfo *sub, classinfo *super) } +/* class_isanysubclass ********************************************************* + + Checks a subclass relation between two classes. Implemented + interfaces are interpreted as super classes. + + Return value: 1 ... sub is subclass of super + 0 ... otherwise + +*******************************************************************************/ + +bool class_isanysubclass(classinfo *sub, classinfo *super) +{ + castinfo classvalues; + u4 diffval; + bool result; + + /* This is the trivial case. */ + + if (sub == super) + return true; + + /* Primitive classes are only subclasses of themselves. */ + + if ((sub->flags & ACC_CLASS_PRIMITIVE) || + (super->flags & ACC_CLASS_PRIMITIVE)) + return false; + + /* Check for interfaces. */ + + if (super->flags & ACC_INTERFACE) { + result = (sub->vftbl->interfacetablelength > super->index) && + (sub->vftbl->interfacetable[-super->index] != NULL); + } + else { + /* java.lang.Object is the only super class of any + interface. */ + + if (sub->flags & ACC_INTERFACE) + return (super == class_java_lang_Object); + + ASM_GETCLASSVALUES_ATOMIC(super->vftbl, sub->vftbl, &classvalues); + + diffval = classvalues.sub_baseval - classvalues.super_baseval; + result = diffval <= (u4) classvalues.super_diffval; + } + + return result; +} + + /* class_printflags ************************************************************ Prints flags of a class. diff --git a/src/vmcore/class.h b/src/vmcore/class.h index e28d03b9f..68bf1d8e7 100644 --- a/src/vmcore/class.h +++ b/src/vmcore/class.h @@ -22,7 +22,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - $Id: class.h 7399 2007-02-23 23:29:13Z michi $ + $Id: class.h 7601 2007-03-28 23:02:50Z michi $ */ @@ -35,6 +35,7 @@ typedef struct classinfo classinfo; typedef struct innerclassinfo innerclassinfo; typedef struct extra_classref extra_classref; +typedef struct castinfo castinfo; #include "config.h" @@ -165,6 +166,15 @@ struct extra_classref { }; +/* castinfo *******************************************************************/ + +struct castinfo { + s4 super_baseval; + s4 super_diffval; + s4 sub_baseval; +}; + + /* global variables ***********************************************************/ extern list unlinkedclasses; /* this is only used for eager class loading */ @@ -328,6 +338,7 @@ methodinfo *class_resolveclassmethod(classinfo *c, utf *name, utf *dest, classin methodinfo *class_resolveinterfacemethod(classinfo *c, utf *name, utf *dest, classinfo *referer, bool throwexception); bool class_issubclass(classinfo *sub, classinfo *super); +bool class_isanysubclass(classinfo *sub, classinfo *super); /* some debugging functions */ diff --git a/src/vmcore/classcache.c b/src/vmcore/classcache.c index 11a666907..0b26cc5c1 100644 --- a/src/vmcore/classcache.c +++ b/src/vmcore/classcache.c @@ -22,7 +22,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - $Id: classcache.c 7441 2007-03-02 23:13:10Z michi $ + $Id: classcache.c 7560 2007-03-23 18:51:41Z twisti $ */ @@ -1177,9 +1177,11 @@ bool classcache_add_constraint(classloader * a, assert(classname); #ifdef CLASSCACHE_VERBOSE - fprintf(stdout, "classcache_add_constraint(%p,%p,", (void *) a, (void *) b); + log_start(); + log_print("classcache_add_constraint(%p,%p,", (void *) a, (void *) b); utf_fprint_printable_ascii_classname(stdout, classname); - fprintf(stdout, ")\n"); + log_print(")\n"); + log_finish(); #endif /* a constraint with a == b is trivially satisfied */ @@ -1521,10 +1523,10 @@ void classcache_debug_dump(FILE * file,utf *only) CLASSCACHE_LOCK(); - fprintf(file, "\n=== [loaded class cache] =====================================\n\n"); - fprintf(file, "hash size : %d\n", (int) hashtable_classcache.size); - fprintf(file, "hash entries: %d\n", (int) hashtable_classcache.entries); - fprintf(file, "\n"); + log_println("=== [loaded class cache] ====================================="); + log_println("hash size : %d", (int) hashtable_classcache.size); + log_println("hash entries: %d", (int) hashtable_classcache.entries); + log_println(""); if (only) { c = classcache_lookup_name(only); @@ -1543,20 +1545,25 @@ dump_it: /* iterate over all class entries */ for (clsen = c->classes; clsen; clsen = clsen->next) { if (clsen->classobj) { - fprintf(file, " loaded %p\n", (void *) clsen->classobj); + log_println(" loaded %p", (void *) clsen->classobj); } else { - fprintf(file, " unresolved\n"); + log_println(" unresolved"); } - fprintf(file, " loaders:"); + + log_start(); + log_print(" loaders: "); for (lden = clsen->loaders; lden; lden = lden->next) { - fprintf(file, "<%p> %p", (void *) lden, (void *) lden->loader); + log_print("<%p> %p ", (void *) lden, (void *) lden->loader); } - fprintf(file, "\n constraints:"); + log_finish(); + + log_start(); + log_print(" constraints: "); for (lden = clsen->constraints; lden; lden = lden->next) { - fprintf(file, "<%p> %p", (void *) lden, (void *) lden->loader); + log_print("<%p> %p ", (void *) lden, (void *) lden->loader); } - fprintf(file, "\n"); + log_finish(); } } diff --git a/src/vmcore/descriptor.h b/src/vmcore/descriptor.h index 294429cf8..f6dec16a7 100644 --- a/src/vmcore/descriptor.h +++ b/src/vmcore/descriptor.h @@ -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 7596 2007-03-28 21:05:53Z twisti $ */ @@ -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 */ diff --git a/src/vmcore/linker.c b/src/vmcore/linker.c index e9c3c249d..4bd8aacf8 100644 --- a/src/vmcore/linker.c +++ b/src/vmcore/linker.c @@ -22,7 +22,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - $Id: linker.c 7483 2007-03-08 13:17:40Z michi $ + $Id: linker.c 7561 2007-03-23 19:10:35Z twisti $ */ @@ -90,7 +90,7 @@ static s4 classvalue; *******************************************************************************/ -primitivetypeinfo primitivetype_table[PRIMITIVETYPE_COUNT] = { +primitivetypeinfo primitivetype_table[PRIMITIVETYPE_COUNT] = { { NULL, NULL, "java/lang/Integer", 'I', "int" , "[I", NULL, NULL }, { NULL, NULL, "java/lang/Long", 'J', "long" , "[J", NULL, NULL }, { NULL, NULL, "java/lang/Float", 'F', "float" , "[F", NULL, NULL }, @@ -336,7 +336,13 @@ static bool link_primitivetype_table(void) c = class_create_classinfo(utf_new_char(primitivetype_table[i].name)); - c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT; + /* primitive classes don't have a super class */ + + c->super.any = NULL; + + /* set flags and mark it as primitive class */ + + c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT | ACC_CLASS_PRIMITIVE; /* prevent loader from loading primitive class */ @@ -352,8 +358,9 @@ static bool link_primitivetype_table(void) /* create class for wrapping the primitive type */ u = utf_new_char(primitivetype_table[i].wrapname); + c = load_class_bootstrap(u); - if (!(c = load_class_bootstrap(u))) + if (c == NULL) return false; primitivetype_table[i].class_wrap = c; @@ -364,6 +371,7 @@ static bool link_primitivetype_table(void) u = utf_new_char(primitivetype_table[i].arrayname); c = class_create_classinfo(u); c = load_newly_created_array(c, NULL); + if (c == NULL) return false; @@ -1202,12 +1210,12 @@ static void linker_compute_subclasses(classinfo *c) #endif if (!(c->flags & ACC_INTERFACE)) { - c->nextsub = 0; - c->sub = 0; + c->nextsub = NULL; + c->sub = NULL; } if (!(c->flags & ACC_INTERFACE) && (c->super.any != NULL)) { - c->nextsub = c->super.cls->sub; + c->nextsub = c->super.cls->sub; c->super.cls->sub = c; } diff --git a/src/vmcore/loader.c b/src/vmcore/loader.c index 4239fbd22..bbd577bc0 100644 --- a/src/vmcore/loader.c +++ b/src/vmcore/loader.c @@ -22,7 +22,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - $Id: loader.c 7483 2007-03-08 13:17:40Z michi $ + $Id: loader.c 7601 2007-03-28 23:02:50Z michi $ */ @@ -1214,6 +1214,10 @@ static bool loader_load_method(classbuffer *cb, methodinfo *m, c = cb->class; +#if defined(ENABLE_THREADS) + lock_init_object_lock(&m->header); +#endif + #if defined(ENABLE_STATISTICS) if (opt_stat) count_all_methods++; @@ -2090,6 +2094,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; @@ -2097,35 +2102,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; @@ -2679,6 +2665,10 @@ classinfo *load_newly_created_array(classinfo *c, classloader *loader) clone = c->methods; MSET(clone, 0, methodinfo, 1); +#if defined(ENABLE_THREADS) + lock_init_object_lock(&clone->header); +#endif + /* ATTENTION: if you delete the ACC_NATIVE below, set clone->maxlocals=1 (interpreter related) */ diff --git a/src/vmcore/method.c b/src/vmcore/method.c index 274008a37..f9dc0924e 100644 --- a/src/vmcore/method.c +++ b/src/vmcore/method.c @@ -22,7 +22,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - $Id: method.c 7483 2007-03-08 13:17:40Z michi $ + $Id: method.c 7573 2007-03-25 18:55:02Z twisti $ */ @@ -36,7 +36,9 @@ #include "mm/memory.h" +#include "vm/builtin.h" #include "vm/global.h" +#include "vm/resolve.h" #include "vm/jit/methodheader.h" @@ -146,6 +148,96 @@ methodinfo *method_vftbl_lookup(vftbl_t *vftbl, methodinfo* m) } +/* method_get_parametertypearray *********************************************** + + Use the descriptor of a method to generate a java.lang.Class array + which contains the classes of the parametertypes of the method. + + This function is called by java.lang.reflect.{Constructor,Method}. + +*******************************************************************************/ + +java_objectarray *method_get_parametertypearray(methodinfo *m) +{ + methoddesc *md; + typedesc *paramtypes; + s4 paramcount; + java_objectarray *oa; + s4 i; + classinfo *c; + + md = m->parseddesc; + + /* is the descriptor fully parsed? */ + + if (m->parseddesc->params == NULL) + if (!descriptor_params_from_paramtypes(md, m->flags)) + return NULL; + + paramtypes = md->paramtypes; + paramcount = md->paramcount; + + /* skip `this' pointer */ + + if (!(m->flags & ACC_STATIC)) { + paramtypes++; + paramcount--; + } + + /* create class-array */ + + oa = builtin_anewarray(paramcount, class_java_lang_Class); + + if (oa == NULL) + return NULL; + + /* get classes */ + + for (i = 0; i < paramcount; i++) { + if (!resolve_class_from_typedesc(¶mtypes[i], true, false, &c)) + return NULL; + + oa->data[i] = (java_objectheader *) c; + } + + return oa; +} + + +/* method_get_exceptionarray *************************************************** + + Get the exceptions which can be thrown by a method. + +*******************************************************************************/ + +java_objectarray *method_get_exceptionarray(methodinfo *m) +{ + java_objectarray *oa; + classinfo *c; + s4 i; + + /* create class-array */ + + oa = builtin_anewarray(m->thrownexceptionscount, class_java_lang_Class); + + if (oa == NULL) + return NULL; + + /* iterate over all exceptions and store the class in the array */ + + for (i = 0; i < m->thrownexceptionscount; i++) { + c = resolve_classref_or_classinfo_eager(m->thrownexceptions[i], true); + + if (c == NULL) + return NULL; + + oa->data[i] = (java_objectheader *) c; + } + + return oa; +} + + /* method_count_implementations ************************************************ Count the implementations of a method in a class cone (a class and all its diff --git a/src/vmcore/method.h b/src/vmcore/method.h index 208f8a57a..ea02e1a39 100644 --- a/src/vmcore/method.h +++ b/src/vmcore/method.h @@ -22,7 +22,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - $Id: method.h 7483 2007-03-08 13:17:40Z michi $ + $Id: method.h 7575 2007-03-25 20:30:50Z twisti $ */ @@ -63,6 +63,7 @@ typedef struct codeinfo codeinfo; /* methodinfo *****************************************************************/ struct methodinfo { /* method structure */ + java_objectheader header; /* we need this in jit's monitorenter */ s4 flags; /* ACC flags */ utf *name; /* name of method */ utf *descriptor; /* JavaVM descriptor string of method */ @@ -157,6 +158,9 @@ bool method_canoverwrite(methodinfo *m, methodinfo *old); methodinfo *method_vftbl_lookup(vftbl_t *vftbl, methodinfo* m); +java_objectarray *method_get_parametertypearray(methodinfo *m); +java_objectarray *method_get_exceptionarray(methodinfo *m); + void method_add_assumption_monomorphic(methodinfo *m, methodinfo *caller); void method_break_assumption_monomorphic(methodinfo *m, method_worklist **wl); diff --git a/src/vmcore/options.c b/src/vmcore/options.c index 51f9c8b32..13f56a7e7 100644 --- a/src/vmcore/options.c +++ b/src/vmcore/options.c @@ -22,7 +22,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - $Id: options.c 7483 2007-03-08 13:17:40Z michi $ + $Id: options.c 7596 2007-03-28 21:05:53Z 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) diff --git a/src/vmcore/options.h b/src/vmcore/options.h index ee06449b4..2409cabc4 100644 --- a/src/vmcore/options.h +++ b/src/vmcore/options.h @@ -22,7 +22,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - $Id: options.h 7483 2007-03-08 13:17:40Z michi $ + $Id: options.h 7596 2007-03-28 21:05:53Z 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) diff --git a/src/vmcore/statistics.c b/src/vmcore/statistics.c index 8cf56b9f8..9d6a67b32 100644 --- a/src/vmcore/statistics.c +++ b/src/vmcore/statistics.c @@ -22,7 +22,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - $Id: statistics.c 7483 2007-03-08 13:17:40Z michi $ + $Id: statistics.c 7551 2007-03-21 14:26:09Z twisti $ */ @@ -76,13 +76,20 @@ s4 globaluseddumpsize = 0; /* variables for measurements *************************************************/ -s4 size_classinfo = 0; -s4 size_fieldinfo = 0; -s4 size_methodinfo = 0; -s4 size_lineinfo = 0; -s4 size_codeinfo = 0; +s4 size_classinfo = 0; +s4 size_fieldinfo = 0; +s4 size_methodinfo = 0; +s4 size_lineinfo = 0; +s4 size_codeinfo = 0; -s4 size_stack_map = 0; +s4 size_stack_map = 0; +s4 size_string = 0; + +s4 size_threadobject = 0; + +s4 size_lock_record_pool = 0; +s4 size_lock_hashtable = 0; +s4 size_lock_waiter = 0; int count_const_pool_len = 0; int count_classref_len = 0; @@ -630,7 +637,12 @@ void statistics_print_memory_usage(void) printf("utf: %10d\n", count_utf_len); printf("vmcode: %10d\n", count_vmcode_len); printf("exception tables: %10d\n", count_extable_len); - printf("stack map: %10d\n", size_stack_map); + printf("stack map: %10d\n", size_stack_map); + printf("string: %10d\n", size_string); + printf("threadobject: %10d\n", size_threadobject); + printf("lock record pool: %10d\n", size_lock_record_pool); + printf("lock hashtable: %10d\n", size_lock_hashtable); + printf("lock waiter: %10d\n", size_lock_waiter); printf(" ----------\n"); sum = @@ -643,7 +655,12 @@ void statistics_print_memory_usage(void) count_utf_len + count_vmcode_len + count_extable_len + - size_stack_map; + size_stack_map + + size_string + + size_threadobject + + size_lock_record_pool + + size_lock_hashtable + + size_lock_waiter; printf(" %10d\n", sum); printf("\n"); diff --git a/src/vmcore/statistics.h b/src/vmcore/statistics.h index 597d3be9a..f02548010 100644 --- a/src/vmcore/statistics.h +++ b/src/vmcore/statistics.h @@ -22,7 +22,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - $Id: statistics.h 7369 2007-02-16 17:56:40Z twisti $ + $Id: statistics.h 7551 2007-03-21 14:26:09Z twisti $ */ @@ -96,6 +96,13 @@ extern s4 size_lineinfo; extern s4 size_codeinfo; extern s4 size_stack_map; +extern s4 size_string; + +extern s4 size_threadobject; + +extern s4 size_lock_record_pool; +extern s4 size_lock_hashtable; +extern s4 size_lock_waiter; extern int count_const_pool_len; extern int count_classref_len; diff --git a/src/vmcore/zip.c b/src/vmcore/zip.c index 2ee7f2b60..84511522d 100644 --- a/src/vmcore/zip.c +++ b/src/vmcore/zip.c @@ -22,7 +22,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - $Id: zip.c 7407 2007-02-26 19:12:03Z michi $ + $Id: zip.c 7548 2007-03-21 13:19:44Z twisti $ */ @@ -408,7 +408,9 @@ classbuffer *zip_get(list_classpath_entry *lce, classinfo *c) /* try to find the class in the current archive */ - if ((htzfe = zip_find(lce, c->name)) == NULL) + htzfe = zip_find(lce, c->name); + + if (htzfe == NULL) return NULL; /* read stuff from local file header */ diff --git a/tests/regression/native/Makefile.am b/tests/regression/native/Makefile.am index 90768984c..ece0e5ba8 100644 --- a/tests/regression/native/Makefile.am +++ b/tests/regression/native/Makefile.am @@ -26,7 +26,7 @@ ## ## Authors: Christian Thalinger ## -## $Id: Makefile.am 6257 2006-12-28 13:43:06Z twisti $ +## $Id: Makefile.am 7596 2007-03-28 21:05:53Z twisti $ ## 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 \