Merged revisions 7501-7598 via svnmerge from
authormichi <none@none>
Wed, 28 Mar 2007 23:02:50 +0000 (23:02 +0000)
committermichi <none@none>
Wed, 28 Mar 2007 23:02:50 +0000 (23:02 +0000)
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

154 files changed:
AUTHORS
configure.ac
src/Makefile.am
src/cacaoh/dummy.c
src/mm/boehm-gc/include/private/gc_locks.h
src/mm/nogc.c
src/native/include/Makefile.am
src/native/jni.c
src/native/native.c
src/native/native.h
src/native/vm/cldc1.1/com_sun_cldc_io_ResourceInputStream.c
src/native/vm/cldc1.1/com_sun_cldc_io_j2me_socket_Protocol.c
src/native/vm/gnu/java_lang_reflect_Constructor.c
src/native/vm/gnu/java_lang_reflect_Method.c
src/native/vm/java_lang_Class.c
src/threads/native/lock.c
src/threads/native/threads.c
src/toolbox/list.c
src/toolbox/list.h
src/vm/access.c
src/vm/builtin.c
src/vm/builtin.h
src/vm/exceptions.c
src/vm/exceptions.h
src/vm/global.h
src/vm/jit/abi.h
src/vm/jit/alpha/arch.h
src/vm/jit/alpha/asmpart.S
src/vm/jit/alpha/codegen.c
src/vm/jit/alpha/codegen.h
src/vm/jit/alpha/emit.c
src/vm/jit/alpha/linux/md-os.c
src/vm/jit/alpha/md.c
src/vm/jit/alpha/patcher.c
src/vm/jit/arm/arch.h
src/vm/jit/arm/asmpart.S
src/vm/jit/arm/codegen.c
src/vm/jit/arm/codegen.h
src/vm/jit/arm/emit.c
src/vm/jit/arm/linux/Makefile.am
src/vm/jit/arm/linux/md-os.c
src/vm/jit/arm/md.c
src/vm/jit/asmpart.h
src/vm/jit/code.c
src/vm/jit/code.h
src/vm/jit/codegen-common.c
src/vm/jit/codegen-common.h
src/vm/jit/disass-common.c
src/vm/jit/disass.h
src/vm/jit/dseg.c
src/vm/jit/dseg.h
src/vm/jit/emit-common.c
src/vm/jit/emit-common.h
src/vm/jit/i386/arch.h
src/vm/jit/i386/asmpart.S
src/vm/jit/i386/codegen.c
src/vm/jit/i386/codegen.h
src/vm/jit/i386/emit.c
src/vm/jit/i386/linux/md-os.c
src/vm/jit/i386/md.c
src/vm/jit/i386/patcher.c
src/vm/jit/jit.c
src/vm/jit/jit.h
src/vm/jit/m68k/Makefile.am
src/vm/jit/m68k/arch.h
src/vm/jit/m68k/asmpart.S
src/vm/jit/m68k/codegen.c
src/vm/jit/m68k/codegen.h
src/vm/jit/m68k/emit.c
src/vm/jit/m68k/machine-instr.h
src/vm/jit/m68k/md.c
src/vm/jit/m68k/patcher.c
src/vm/jit/m68k/uclinux/Makefile.am [deleted file]
src/vm/jit/m68k/uclinux/md-abi.c [deleted file]
src/vm/jit/m68k/uclinux/md-abi.h [deleted file]
src/vm/jit/m68k/uclinux/md-asm.h [deleted file]
src/vm/jit/m68k/uclinux/md-os.c [deleted file]
src/vm/jit/mips/arch.h
src/vm/jit/mips/asmpart.S
src/vm/jit/mips/codegen.c
src/vm/jit/mips/codegen.h
src/vm/jit/mips/emit.c
src/vm/jit/mips/linux/md-os.c
src/vm/jit/mips/md.c
src/vm/jit/mips/patcher.c
src/vm/jit/parse.c
src/vm/jit/powerpc/arch.h
src/vm/jit/powerpc/asmpart.S
src/vm/jit/powerpc/codegen.c
src/vm/jit/powerpc/codegen.h
src/vm/jit/powerpc/darwin/md-os.c
src/vm/jit/powerpc/emit.c
src/vm/jit/powerpc/linux/md-os.c
src/vm/jit/powerpc/md.c
src/vm/jit/powerpc/patcher.c
src/vm/jit/powerpc64/arch.h
src/vm/jit/powerpc64/asmpart.S
src/vm/jit/powerpc64/codegen.c
src/vm/jit/powerpc64/codegen.h
src/vm/jit/powerpc64/emit.c
src/vm/jit/powerpc64/linux/md-abi.c
src/vm/jit/powerpc64/linux/md-abi.h
src/vm/jit/powerpc64/linux/md-os.c
src/vm/jit/powerpc64/md.c
src/vm/jit/powerpc64/patcher.c
src/vm/jit/reg.c
src/vm/jit/s390/arch.h
src/vm/jit/s390/asmpart.S
src/vm/jit/s390/codegen.c
src/vm/jit/s390/codegen.h
src/vm/jit/s390/emit.c
src/vm/jit/s390/emit.h
src/vm/jit/s390/md-abi.c
src/vm/jit/s390/md-abi.h
src/vm/jit/s390/md.c
src/vm/jit/s390/patcher.c
src/vm/jit/sparc64/arch.h
src/vm/jit/sparc64/asmpart.S
src/vm/jit/sparc64/codegen.c
src/vm/jit/sparc64/codegen.h
src/vm/jit/sparc64/emit.c
src/vm/jit/sparc64/linux/md-os.c
src/vm/jit/sparc64/md-abi.c
src/vm/jit/sparc64/md.c
src/vm/jit/sparc64/patcher.c
src/vm/jit/stacktrace.c
src/vm/jit/verify/typecheck-invoke.inc
src/vm/jit/x86_64/arch.h
src/vm/jit/x86_64/asmpart.S
src/vm/jit/x86_64/codegen.c
src/vm/jit/x86_64/codegen.h
src/vm/jit/x86_64/emit.c
src/vm/jit/x86_64/emit.h
src/vm/jit/x86_64/linux/md-os.c
src/vm/jit/x86_64/md.c
src/vm/jit/x86_64/patcher.c
src/vm/signal.c
src/vm/signallocal.h
src/vm/string.c
src/vm/vm.c
src/vmcore/class.c
src/vmcore/class.h
src/vmcore/classcache.c
src/vmcore/descriptor.h
src/vmcore/linker.c
src/vmcore/loader.c
src/vmcore/method.c
src/vmcore/method.h
src/vmcore/options.c
src/vmcore/options.h
src/vmcore/statistics.c
src/vmcore/statistics.h
src/vmcore/zip.c
tests/regression/native/Makefile.am

diff --git a/AUTHORS b/AUTHORS
index 11aa8aa060a449483d61d26b8f0c214e2d926284..a9e6b099f79f3b35681a09a69f3338663d8f4735 100644 (file)
--- 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
index 05284e9099bc4a68726a95941f2c8a17c058d101..57f25442f5fbdd4793b7529b5efca23c475ebf0b 100644 (file)
@@ -22,7 +22,7 @@ dnl along with this program; if not, write to the Free Software
 dnl Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 dnl 02110-1301, USA.
 dnl 
-dnl $Id: configure.ac 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]
index 69ec6f6f808e3cc03cd29910eb53c938d82d5e7b..1681eddf5b875405bdb6538e11391e928c126c52 100644 (file)
@@ -22,7 +22,7 @@
 ## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 ## 02110-1301, USA.
 ##
-## $Id: Makefile.am 7365 2007-02-15 19:42:13Z twisti $
+## $Id: Makefile.am 7596 2007-03-28 21:05:53Z twisti $
 
 ## Process this file with automake to produce Makefile.in
 
@@ -49,13 +49,17 @@ THREADS_DIR = \
        threads
 endif
 
+if ENABLE_CACAOH
+CACAOH_DIR = \
+       cacaoh 
+endif
+
 # DON'T CHANGE THIS ORDER!!!
 
 SUBDIRS = \
        toolbox \
        vmcore \
-       cacaoh \
-       \
+       $(CACAOH_DIR) \
        $(VM_DIR) \
        native \
        fdlibm \
index 3731f1243ca1bd0e6316400b6e515dd1481186bc..03e9afb885245b357f9ce5ce61bb9408eae1921c 100644 (file)
@@ -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.               */
 
index 89638f6eb63e1da7f7fdc150940954f22b9a9427..aba1b46b6910ece97cb2d13d93b2af932e970c79 100644 (file)
        }
 #      define GC_TEST_AND_SET_DEFINED
 #    endif
+/* tbfg */
+#if 0          
 #    ifdef M68K
        /* Contributed by Tony Mantler.  I'm not sure how well it was   */
        /* tested.                                                      */
        }
 #      define GC_TEST_AND_SET_DEFINED
 #    endif
+#endif
 #    if defined(POWERPC)
         inline static int GC_test_and_set(volatile unsigned int *addr) {
           int oldval;
index 804fa593d7e6333fb3cf7c74d4ea11cadba00a60..13ad45953135410080684bc0b538cc89d0138839 100644 (file)
@@ -1,6 +1,6 @@
 /* src/mm/nogc.c - allocates memory through malloc (no GC)
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
    J. Wenninger, Institut f. Computersprachen - TU Wien
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Christian Thalinger
-
-   Changes:
-
-   $Id: nogc.c 6034 2006-11-21 21:02:30Z twisti $
+   $Id: nogc.c 7596 2007-03-28 21:05:53Z twisti $
 
 */
 
 
 #include "mm/gc-common.h"
 #include "mm/memory.h"
+
 #include "toolbox/logging.h"
-#include "vm/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);
index f4bd5051bac9751ffcd2c054b7532f45724e8f25..b7a0c18835f18b6a898607259992d528cdedb92a 100644 (file)
@@ -22,7 +22,7 @@
 ## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 ## 02110-1301, USA.
 ##
-## $Id: Makefile.am 7374 2007-02-19 23:47:58Z twisti $
+## $Id: Makefile.am 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
index 38cf84b9e72b72d8a514f5529211d89e270e4497..25386f917baaed006f6ac5d9d2cac16fa01ab8e4 100644 (file)
@@ -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;
 }
index 4f70652df0d22cc2138cfcccdb90efc70900ce23..ef8ef2ccb00caeae2e58cb7404d9a061708e0452 100644 (file)
@@ -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(&paramtypes[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
index e649d54bf6a70efe217af3b00ba2b67df5ba81be..b12d417e44997e706366df30d5486da61633620f 100644 (file)
@@ -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 */
 
 
index 566551be897afe6d6641c5da4d53effc7012a86b..e0d7a8f1066d1403929da8d4d052ed4907de6bf5 100644 (file)
@@ -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;
 }
index b59754194ff83d7dc65fe1a5ba2367ecd2ffc32f..1274b074fe459be05a11d61633b7ac5e3153c42e 100644 (file)
@@ -31,6 +31,7 @@
 
 #include <errno.h>
 #include <netdb.h>
+#include <unistd.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 
@@ -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
index d2fa2eaac92e5c04b13b446267782d8cc8cff0a0..9a5a343be2438e0a4eddffa570114e390f901abf 100644 (file)
@@ -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);
 }
 
 
index 2d5ac85e07a31d786f13a57c8dc5c820b23633b1..2bb0169eabe27a124df48e800f350b74b1a398f5 100644 (file)
@@ -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);
 }
 
 
index 381269bbfcfeae7d85256419f665c4afdb6560a0..c0c3c0d026b844170d225cd57ee9ff3a418b4fe9 100644 (file)
@@ -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);
 }
 
 
index 1a65bfaa81477660cbcc043ac556588ef1132461..6eeec822fb1f4ab88d694f33e7b59541cbac7c11 100644 (file)
 #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; i<size; i++) {
+       for (i = 0; i < size; i++) {
                lock_record_init(&pool->lr[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; i<oldsize; ++i) {
+       for (i = 0; i < oldsize; i++) {
                lr = oldtable[i];
                while (lr) {
                        next = lr->hashlink;
@@ -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;
                }
 
index fbe06fdff8705b4ac75a6cd22b8870b2b931c56b..ee50e7687bcadc35060f96c9f4f5f2e142826ba8 100644 (file)
@@ -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 $
 
 */
 
 
 #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;
 }
 
index e277eb572a6c21b43f4270fec8458a173e2a2644..d6da79efb2fc982e3e01d12091d220e4ef843ccb 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: list.c 7246 2007-01-29 18:49:05Z twisti $
+   $Id: list.c 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);
 }
 
  
index 672751cb08afc7d74f642c661d1ec940dc9638a2..1feaa1b03dd56b91909474041d6f740e25155aca 100644 (file)
@@ -1,6 +1,6 @@
 /* src/toolbox/list.h - synchronized linked list
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
    J. Wenninger, Institut f. Computersprachen - TU Wien
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Reinhard Grafl
-
-   Changes: Christian Thalinger
-
-   $Id: list.h 5894 2006-11-02 12:54:15Z twisti $
+   $Id: list.h 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);
index 45e8548bcd3d03721ea65e3c8c0a6f421f0a9439..502cb1f41e74f93548f662060d2805b04e497521 100644 (file)
@@ -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;
index 75a55f6bce360f3c288bb63fd83c6be655a64d25..a2298c90ace40d418f14fde369015cbfb1c59084 100644 (file)
@@ -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;
                        }
index a66fe2d5dc2fb1056420df43b67194ab59e833ef..2b9c17ceb9fc69730f73d7edec4481ccc8305950 100644 (file)
@@ -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);
index 722c7df10670fbe0f53b3560ea2eaa33de48dfc8..6754a62beaa76b2034589bb217a5e32f632b066a 100644 (file)
@@ -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
index c3539cb4c7115461d202320f440013dac8446dc3..61544d0449d15f87ca6904ff5dce7f42e4c9c4c4 100644 (file)
@@ -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 $
 
 */
 
 
 /* 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 */
 
index d660b03e1820b4f37f4afb45df5afda81019ec4f..cf4d928433cebcae7d50efabb36bb14d7ac69694 100644 (file)
@@ -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 *******************************************/
index 8d80e7b60c09f3c42e6a63fb1155e8ca6f1bdd92..74338d881312f53d76818adc35f86233f2f86fee 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: abi.h 7329 2007-02-11 21:24:14Z twisti $
+   $Id: abi.h 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[];
index 757a3a7a80819e65f0c041570095f6928e76f80c..c0d4f719ae91f8aedc45604156d705a84dcd7e7c 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: arch.h 7241 2007-01-27 15:52:01Z twisti $
+   $Id: arch.h 7596 2007-03-28 21:05:53Z twisti $
 
 */
 
 #endif
 
 
+/* branches *******************************************************************/
+
+#define SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER       0
+#define SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER     1
+#define SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS    0
+
+
 /* exceptions *****************************************************************/
 
 #define SUPPORT_HARDWARE_DIVIDE_BY_ZERO  0
index 63ca7efe59aaaa92b295459e080d2fc09d872551..1d240f9cb2fc2b4f353188d8abec140936c74df5 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: asmpart.S 7253 2007-01-29 21:37:00Z twisti $
+   $Id: asmpart.S 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
index 24df4ef4a38f894c6ab65af9eeba979e3e61fc6a..e8e29f9d8e45d271ad447ac110e97a60adff2c24 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: codegen.c 7251 2007-01-29 20:24:53Z twisti $
+   $Id: codegen.c 7596 2007-03-28 21:05:53Z twisti $
 
 */
 
 #include "vmcore/options.h"
 
 
-/* codegen *********************************************************************
+/* codegen_emit ****************************************************************
 
    Generates machine code.
 
 *******************************************************************************/
 
-bool codegen(jitdata *jd)
+bool codegen_emit(jitdata *jd)
 {
        methodinfo         *m;
        codeinfo           *code;
@@ -280,8 +280,8 @@ bool codegen(jitdata *jd)
                        M_ALD(REG_A0, REG_PV, disp);
                }
                else {
-                       M_BEQZ(REG_A0, 0);
-                       codegen_add_nullpointerexception_ref(cd);
+                       M_BNEZ(REG_A0, 1);
+                       M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_NULLPOINTER);
                }
 
                M_AST(REG_A0, REG_SP, s1 * 8);
@@ -716,14 +716,13 @@ bool codegen(jitdata *jd)
                case ICMD_IDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
                case ICMD_IREM:       /* ..., val1, val2  ==> ..., val1 % val2        */
 
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+                       s1 = emit_load_s1(jd, iptr, REG_A0);
+                       s2 = emit_load_s2(jd, iptr, REG_A1);
                        d = codegen_reg_of_dst(jd, iptr, REG_RESULT);
-                       M_BEQZ(s2, 0);
-                       codegen_add_arithmeticexception_ref(cd);
+                       emit_arithmetic_check(cd, iptr, s2);
 
-                       M_MOV(s1, REG_A0);
-                       M_MOV(s2, REG_A1);
+                       M_INTMOVE(s1, REG_A0);
+                       M_INTMOVE(s2, REG_A1);
                        bte = iptr->sx.s23.s3.bte;
                        disp = dseg_add_functionptr(cd, bte->fp);
                        M_ALD(REG_PV, REG_PV, disp);
@@ -738,16 +737,14 @@ bool codegen(jitdata *jd)
                case ICMD_LDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
                case ICMD_LREM:       /* ..., val1, val2  ==> ..., val1 % val2        */
 
-                       bte = iptr->sx.s23.s3.bte;
-
                        s1 = emit_load_s1(jd, iptr, REG_A0);
                        s2 = emit_load_s2(jd, iptr, REG_A1);
                        d = codegen_reg_of_dst(jd, iptr, REG_RESULT);
-                       M_BEQZ(s2, 0);
-                       codegen_add_arithmeticexception_ref(cd);
+                       emit_arithmetic_check(cd, iptr, s2);
 
                        M_INTMOVE(s1, REG_A0);
                        M_INTMOVE(s2, REG_A1);
+                       bte = iptr->sx.s23.s3.bte;
                        disp = dseg_add_functionptr(cd, bte->fp);
                        M_ALD(REG_PV, REG_PV, disp);
                        M_JSR(REG_RA, REG_PV);
@@ -1431,7 +1428,7 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                       emit_nullpointer_check(cd, iptr, s1);
+                       /* implicit null-pointer check */
                        M_ILD(d, s1, OFFSET(java_arrayheader, size));
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1441,7 +1438,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        if (has_ext_instr_set) {
                                M_LADD(s2, s1, REG_ITMP1);
                                M_BLDU(d, REG_ITMP1, OFFSET (java_bytearray, data[0]));
@@ -1462,7 +1460,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        if (has_ext_instr_set) {
                                M_LADD(s2, s1, REG_ITMP1);
                                M_LADD(s2, REG_ITMP1, REG_ITMP1);
@@ -1483,7 +1482,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        if (has_ext_instr_set) {
                                M_LADD(s2, s1, REG_ITMP1);
                                M_LADD(s2, REG_ITMP1, REG_ITMP1);
@@ -1505,7 +1505,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_S4ADDQ(s2, s1, REG_ITMP1);
                        M_ILD(d, REG_ITMP1, OFFSET(java_intarray, data[0]));
                        emit_store_dst(jd, iptr, d);
@@ -1516,7 +1517,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_S8ADDQ(s2, s1, REG_ITMP1);
                        M_LLD(d, REG_ITMP1, OFFSET(java_longarray, data[0]));
                        emit_store_dst(jd, iptr, d);
@@ -1527,7 +1529,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_S4ADDQ(s2, s1, REG_ITMP1);
                        M_FLD(d, REG_ITMP1, OFFSET(java_floatarray, data[0]));
                        emit_store_dst(jd, iptr, d);
@@ -1538,7 +1541,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_S8ADDQ(s2, s1, REG_ITMP1);
                        M_DLD(d, REG_ITMP1, OFFSET(java_doublearray, data[0]));
                        emit_store_dst(jd, iptr, d);
@@ -1549,7 +1553,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_SAADDQ(s2, s1, REG_ITMP1);
                        M_ALD(d, REG_ITMP1, OFFSET(java_objectarray, data[0]));
                        emit_store_dst(jd, iptr, d);
@@ -1560,7 +1565,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
                        if (has_ext_instr_set) {
                                M_LADD(s2, s1, REG_ITMP1);
@@ -1581,7 +1587,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
                        if (has_ext_instr_set) {
                                M_LADD(s2, s1, REG_ITMP1);
@@ -1604,7 +1611,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
                        if (has_ext_instr_set) {
                                M_LADD(s2, s1, REG_ITMP1);
@@ -1627,7 +1635,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
                        M_S4ADDQ(s2, s1, REG_ITMP1);
                        M_IST(s3, REG_ITMP1, OFFSET(java_intarray, data[0]));
@@ -1637,7 +1646,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
                        M_S8ADDQ(s2, s1, REG_ITMP1);
                        M_LST(s3, REG_ITMP1, OFFSET(java_longarray, data[0]));
@@ -1647,7 +1657,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_FTMP3);
                        M_S4ADDQ(s2, s1, REG_ITMP1);
                        M_FST(s3, REG_ITMP1, OFFSET(java_floatarray, data[0]));
@@ -1657,7 +1668,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_FTMP3);
                        M_S8ADDQ(s2, s1, REG_ITMP1);
                        M_DST(s3, REG_ITMP1, OFFSET(java_doublearray, data[0]));
@@ -1667,7 +1679,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_A0);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_A1);
 
                        M_INTMOVE(s1, REG_A0);
@@ -1678,9 +1691,7 @@ bool codegen(jitdata *jd)
                        M_JSR(REG_RA, REG_PV);
                        disp = (s4) (cd->mcodeptr - cd->mcodebase);
                        M_LDA(REG_PV, REG_RA, -disp);
-
-                       M_BEQZ(REG_RESULT, 0);
-                       codegen_add_arraystoreexception_ref(cd);
+                       emit_exception_check(cd, iptr);
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
@@ -1694,7 +1705,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        if (has_ext_instr_set) {
                                M_LADD(s2, s1, REG_ITMP1);
                                M_BST(REG_ZERO, REG_ITMP1, OFFSET(java_bytearray, data[0]));
@@ -1714,7 +1726,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        if (has_ext_instr_set) {
                                M_LADD(s2, s1, REG_ITMP1);
                                M_LADD(s2, REG_ITMP1, REG_ITMP1);
@@ -1736,7 +1749,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        if (has_ext_instr_set) {
                                M_LADD(s2, s1, REG_ITMP1);
                                M_LADD(s2, REG_ITMP1, REG_ITMP1);
@@ -1758,7 +1772,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_S4ADDQ(s2, s1, REG_ITMP1);
                        M_IST(REG_ZERO, REG_ITMP1, OFFSET(java_intarray, data[0]));
                        break;
@@ -1767,7 +1782,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_S8ADDQ(s2, s1, REG_ITMP1);
                        M_LST(REG_ZERO, REG_ITMP1, OFFSET(java_longarray, data[0]));
                        break;
@@ -1776,7 +1792,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_SAADDQ(s2, s1, REG_ITMP1);
                        M_AST(REG_ZERO, REG_ITMP1, OFFSET(java_objectarray, data[0]));
                        break;
@@ -1916,7 +1933,6 @@ bool codegen(jitdata *jd)
                case ICMD_GETFIELD:   /* ...  ==> ..., value                          */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       emit_nullpointer_check(cd, iptr, s1);
 
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
                                uf        = iptr->sx.s23.s3.uf;
@@ -1931,6 +1947,7 @@ bool codegen(jitdata *jd)
                                disp      = fi->offset;
                        }
 
+                       /* implicit null-pointer check */
                        switch (fieldtype) {
                        case TYPE_INT:
                                d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
@@ -1959,7 +1976,6 @@ bool codegen(jitdata *jd)
                case ICMD_PUTFIELD:   /* ..., objectref, value  ==> ...               */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       emit_nullpointer_check(cd, iptr, s1);
 
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
                                uf        = iptr->sx.s23.s3.uf;
@@ -1981,6 +1997,7 @@ bool codegen(jitdata *jd)
                        if (INSTRUCTION_IS_UNRESOLVED(iptr))
                                codegen_add_patch_ref(cd, PATCHER_get_putfield, uf, 0);
 
+                       /* implicit null-pointer check */
                        switch (fieldtype) {
                        case TYPE_INT:
                                M_IST(s2, s1, disp);
@@ -2005,7 +2022,6 @@ bool codegen(jitdata *jd)
                                          /* following NOP)                           */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       emit_nullpointer_check(cd, iptr, s1);
 
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
                                uf        = iptr->sx.s23.s3.uf;
@@ -2020,6 +2036,7 @@ bool codegen(jitdata *jd)
                                disp      = fi->offset;
                        }
 
+                       /* implicit null-pointer check */
                        switch (fieldtype) {
                        case TYPE_INT:
                                M_IST(REG_ZERO, s1, disp);
@@ -2066,258 +2083,213 @@ bool codegen(jitdata *jd)
                case ICMD_GOTO:         /* ... ==> ...                                */
                case ICMD_RET:          /* ... ==> ...                                */
 
-                       M_BR(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                       emit_br(cd, iptr->dst.block);
                        ALIGNCODENOP;
                        break;
 
                case ICMD_JSR:          /* ... ==> ...                                */
 
-                       M_BR(0);
-                       codegen_add_branch_ref(cd, iptr->sx.s23.s3.jsrtarget.block);
+                       emit_br(cd, iptr->sx.s23.s3.jsrtarget.block);
                        ALIGNCODENOP;
                        break;
                        
                case ICMD_IFNULL:       /* ..., value ==> ...                         */
+               case ICMD_IFNONNULL:
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       M_BEQZ(s1, 0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IFNONNULL:    /* ..., value ==> ...                         */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       M_BNEZ(s1, 0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                       emit_bccz(cd, iptr->dst.block, iptr->opc - ICMD_IFNULL, s1, BRANCH_OPT_NONE);
                        break;
 
                case ICMD_IFEQ:         /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.i == 0) {
-                               M_BEQZ(s1, 0);
-                               }
+                       if (iptr->sx.val.i == 0)
+                               emit_beqz(cd, iptr->dst.block, s1);
                        else {
-                               if ((iptr->sx.val.i > 0) && (iptr->sx.val.i <= 255)) {
+                               if ((iptr->sx.val.i > 0) && (iptr->sx.val.i <= 255))
                                        M_CMPEQ_IMM(s1, iptr->sx.val.i, REG_ITMP1);
-                                       }
                                else {
                                        ICONST(REG_ITMP2, iptr->sx.val.i);
                                        M_CMPEQ(s1, REG_ITMP2, REG_ITMP1);
-                                       }
-                               M_BNEZ(REG_ITMP1, 0);
                                }
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                               emit_bnez(cd, iptr->dst.block, REG_ITMP1);
+                       }
                        break;
 
                case ICMD_IFLT:         /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.i == 0) {
-                               M_BLTZ(s1, 0);
-                               }
+                       if (iptr->sx.val.i == 0)
+                               emit_bltz(cd, iptr->dst.block, s1);
                        else {
-                               if ((iptr->sx.val.i > 0) && (iptr->sx.val.i <= 255)) {
+                               if ((iptr->sx.val.i > 0) && (iptr->sx.val.i <= 255))
                                        M_CMPLT_IMM(s1, iptr->sx.val.i, REG_ITMP1);
-                                       }
                                else {
                                        ICONST(REG_ITMP2, iptr->sx.val.i);
                                        M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
-                                       }
-                               M_BNEZ(REG_ITMP1, 0);
                                }
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                               emit_bnez(cd, iptr->dst.block, REG_ITMP1);
+                       }
                        break;
 
                case ICMD_IFLE:         /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.i == 0) {
-                               M_BLEZ(s1, 0);
-                               }
+                       if (iptr->sx.val.i == 0)
+                               emit_blez(cd, iptr->dst.block, s1);
                        else {
-                               if ((iptr->sx.val.i > 0) && (iptr->sx.val.i <= 255)) {
+                               if ((iptr->sx.val.i > 0) && (iptr->sx.val.i <= 255))
                                        M_CMPLE_IMM(s1, iptr->sx.val.i, REG_ITMP1);
-                                       }
                                else {
                                        ICONST(REG_ITMP2, iptr->sx.val.i);
                                        M_CMPLE(s1, REG_ITMP2, REG_ITMP1);
-                                       }
-                               M_BNEZ(REG_ITMP1, 0);
                                }
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                               emit_bnez(cd, iptr->dst.block, REG_ITMP1);
+                       }
                        break;
 
                case ICMD_IFNE:         /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.i == 0) {
-                               M_BNEZ(s1, 0);
-                               }
+                       if (iptr->sx.val.i == 0)
+                               emit_bnez(cd, iptr->dst.block, s1);
                        else {
-                               if ((iptr->sx.val.i > 0) && (iptr->sx.val.i <= 255)) {
+                               if ((iptr->sx.val.i > 0) && (iptr->sx.val.i <= 255))
                                        M_CMPEQ_IMM(s1, iptr->sx.val.i, REG_ITMP1);
-                                       }
                                else {
                                        ICONST(REG_ITMP2, iptr->sx.val.i);
                                        M_CMPEQ(s1, REG_ITMP2, REG_ITMP1);
-                                       }
-                               M_BEQZ(REG_ITMP1, 0);
                                }
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                               emit_beqz(cd, iptr->dst.block, REG_ITMP1);
+                       }
                        break;
 
                case ICMD_IFGT:         /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.i == 0) {
-                               M_BGTZ(s1, 0);
-                               }
+                       if (iptr->sx.val.i == 0)
+                               emit_bgtz(cd, iptr->dst.block, s1);
                        else {
-                               if ((iptr->sx.val.i > 0) && (iptr->sx.val.i <= 255)) {
+                               if ((iptr->sx.val.i > 0) && (iptr->sx.val.i <= 255))
                                        M_CMPLE_IMM(s1, iptr->sx.val.i, REG_ITMP1);
-                                       }
                                else {
                                        ICONST(REG_ITMP2, iptr->sx.val.i);
                                        M_CMPLE(s1, REG_ITMP2, REG_ITMP1);
-                                       }
-                               M_BEQZ(REG_ITMP1, 0);
                                }
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                               emit_beqz(cd, iptr->dst.block, REG_ITMP1);
+                       }
                        break;
 
                case ICMD_IFGE:         /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.i == 0) {
-                               M_BGEZ(s1, 0);
-                               }
+                       if (iptr->sx.val.i == 0)
+                               emit_bgez(cd, iptr->dst.block, s1);
                        else {
-                               if ((iptr->sx.val.i > 0) && (iptr->sx.val.i <= 255)) {
+                               if ((iptr->sx.val.i > 0) && (iptr->sx.val.i <= 255))
                                        M_CMPLT_IMM(s1, iptr->sx.val.i, REG_ITMP1);
-                                       }
                                else {
                                        ICONST(REG_ITMP2, iptr->sx.val.i);
                                        M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
-                                       }
-                               M_BEQZ(REG_ITMP1, 0);
                                }
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                               emit_beqz(cd, iptr->dst.block, REG_ITMP1);
+                       }
                        break;
 
                case ICMD_IF_LEQ:       /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.l == 0) {
-                               M_BEQZ(s1, 0);
-                               }
+                       if (iptr->sx.val.l == 0)
+                               emit_beqz(cd, iptr->dst.block, s1);
                        else {
-                               if ((iptr->sx.val.l > 0) && (iptr->sx.val.l <= 255)) {
+                               if ((iptr->sx.val.l > 0) && (iptr->sx.val.l <= 255))
                                        M_CMPEQ_IMM(s1, iptr->sx.val.l, REG_ITMP1);
-                                       }
                                else {
                                        LCONST(REG_ITMP2, iptr->sx.val.l);
                                        M_CMPEQ(s1, REG_ITMP2, REG_ITMP1);
-                                       }
-                               M_BNEZ(REG_ITMP1, 0);
                                }
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                               emit_bnez(cd, iptr->dst.block, REG_ITMP1);
+                       }
                        break;
 
                case ICMD_IF_LLT:       /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.l == 0) {
-                               M_BLTZ(s1, 0);
-                               }
+                       if (iptr->sx.val.l == 0)
+                               emit_bltz(cd, iptr->dst.block, s1);
                        else {
-                               if ((iptr->sx.val.l > 0) && (iptr->sx.val.l <= 255)) {
+                               if ((iptr->sx.val.l > 0) && (iptr->sx.val.l <= 255))
                                        M_CMPLT_IMM(s1, iptr->sx.val.l, REG_ITMP1);
-                                       }
                                else {
                                        LCONST(REG_ITMP2, iptr->sx.val.l);
                                        M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
-                                       }
-                               M_BNEZ(REG_ITMP1, 0);
                                }
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                               emit_bnez(cd, iptr->dst.block, REG_ITMP1);
+                       }
                        break;
 
                case ICMD_IF_LLE:       /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.l == 0) {
-                               M_BLEZ(s1, 0);
-                               }
+                       if (iptr->sx.val.l == 0)
+                               emit_blez(cd, iptr->dst.block, s1);
                        else {
-                               if ((iptr->sx.val.l > 0) && (iptr->sx.val.l <= 255)) {
+                               if ((iptr->sx.val.l > 0) && (iptr->sx.val.l <= 255))
                                        M_CMPLE_IMM(s1, iptr->sx.val.l, REG_ITMP1);
-                                       }
                                else {
                                        LCONST(REG_ITMP2, iptr->sx.val.l);
                                        M_CMPLE(s1, REG_ITMP2, REG_ITMP1);
-                                       }
-                               M_BNEZ(REG_ITMP1, 0);
                                }
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                               emit_bnez(cd, iptr->dst.block, REG_ITMP1);
+                       }
                        break;
 
                case ICMD_IF_LNE:       /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.l == 0) {
-                               M_BNEZ(s1, 0);
-                               }
+                       if (iptr->sx.val.l == 0)
+                               emit_bnez(cd, iptr->dst.block, s1);
                        else {
-                               if ((iptr->sx.val.l > 0) && (iptr->sx.val.l <= 255)) {
+                               if ((iptr->sx.val.l > 0) && (iptr->sx.val.l <= 255))
                                        M_CMPEQ_IMM(s1, iptr->sx.val.l, REG_ITMP1);
-                                       }
                                else {
                                        LCONST(REG_ITMP2, iptr->sx.val.l);
                                        M_CMPEQ(s1, REG_ITMP2, REG_ITMP1);
-                                       }
-                               M_BEQZ(REG_ITMP1, 0);
                                }
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                               emit_beqz(cd, iptr->dst.block, REG_ITMP1);
+                       }
                        break;
 
                case ICMD_IF_LGT:       /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.l == 0) {
-                               M_BGTZ(s1, 0);
-                               }
+                       if (iptr->sx.val.l == 0)
+                               emit_bgtz(cd, iptr->dst.block, s1);
                        else {
-                               if ((iptr->sx.val.l > 0) && (iptr->sx.val.l <= 255)) {
+                               if ((iptr->sx.val.l > 0) && (iptr->sx.val.l <= 255))
                                        M_CMPLE_IMM(s1, iptr->sx.val.l, REG_ITMP1);
-                                       }
                                else {
                                        LCONST(REG_ITMP2, iptr->sx.val.l);
                                        M_CMPLE(s1, REG_ITMP2, REG_ITMP1);
-                                       }
-                               M_BEQZ(REG_ITMP1, 0);
                                }
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                               emit_beqz(cd, iptr->dst.block, REG_ITMP1);
+                       }
                        break;
 
                case ICMD_IF_LGE:       /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.l == 0) {
-                               M_BGEZ(s1, 0);
-                               }
+                       if (iptr->sx.val.l == 0)
+                               emit_bgez(cd, iptr->dst.block, s1);
                        else {
-                               if ((iptr->sx.val.l > 0) && (iptr->sx.val.l <= 255)) {
+                               if ((iptr->sx.val.l > 0) && (iptr->sx.val.l <= 255))
                                        M_CMPLT_IMM(s1, iptr->sx.val.l, REG_ITMP1);
-                                       }
                                else {
                                        LCONST(REG_ITMP2, iptr->sx.val.l);
                                        M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
-                                       }
-                               M_BEQZ(REG_ITMP1, 0);
                                }
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                               emit_beqz(cd, iptr->dst.block, REG_ITMP1);
+                       }
                        break;
 
                case ICMD_IF_ICMPEQ:    /* ..., value, value ==> ...                  */
@@ -2327,8 +2299,7 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_CMPEQ(s1, s2, REG_ITMP1);
-                       M_BNEZ(REG_ITMP1, 0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                       emit_bnez(cd, iptr->dst.block, REG_ITMP1);
                        break;
 
                case ICMD_IF_ICMPNE:    /* ..., value, value ==> ...                  */
@@ -2338,8 +2309,7 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_CMPEQ(s1, s2, REG_ITMP1);
-                       M_BEQZ(REG_ITMP1, 0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                       emit_beqz(cd, iptr->dst.block, REG_ITMP1);
                        break;
 
                case ICMD_IF_ICMPLT:    /* ..., value, value ==> ...                  */
@@ -2348,8 +2318,7 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_CMPLT(s1, s2, REG_ITMP1);
-                       M_BNEZ(REG_ITMP1, 0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                       emit_bnez(cd, iptr->dst.block, REG_ITMP1);
                        break;
 
                case ICMD_IF_ICMPGT:    /* ..., value, value ==> ...                  */
@@ -2358,8 +2327,7 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_CMPLE(s1, s2, REG_ITMP1);
-                       M_BEQZ(REG_ITMP1, 0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                       emit_beqz(cd, iptr->dst.block, REG_ITMP1);
                        break;
 
                case ICMD_IF_ICMPLE:    /* ..., value, value ==> ...                  */
@@ -2368,8 +2336,7 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_CMPLE(s1, s2, REG_ITMP1);
-                       M_BNEZ(REG_ITMP1, 0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                       emit_bnez(cd, iptr->dst.block, REG_ITMP1);
                        break;
 
                case ICMD_IF_ICMPGE:    /* ..., value, value ==> ...                  */
@@ -2378,8 +2345,7 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_CMPLT(s1, s2, REG_ITMP1);
-                       M_BEQZ(REG_ITMP1, 0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                       emit_beqz(cd, iptr->dst.block, REG_ITMP1);
                        break;
 
 
@@ -2524,8 +2490,7 @@ nowperformreturn:
                                M_LDA(REG_ITMP2, REG_ZERO, i - 1);
                                M_CMPULE(REG_ITMP1, REG_ITMP2, REG_ITMP2);
                        }
-                       M_BEQZ(REG_ITMP2, 0);
-                       codegen_add_branch_ref(cd, table[0].block);
+                       emit_beqz(cd, table[0].block, REG_ITMP2);
 
                        /* build jump table top down and use address of lowest entry */
 
@@ -2571,15 +2536,11 @@ nowperformreturn:
                                        }
                                        M_CMPEQ(s1, REG_ITMP2, REG_ITMP2);
                                }
-                               M_BNEZ(REG_ITMP2, 0);
-                               codegen_add_branch_ref(cd, lookup->target.block);
+                               emit_bnez(cd, lookup->target.block, REG_ITMP2);
                                lookup++;
                        }
 
-                       M_BR(0);
-                       
-                       codegen_add_branch_ref(cd, iptr->sx.s23.s3.lookupdefault.block);
-
+                       emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
                        ALIGNCODENOP;
                        break;
                        }
@@ -2653,12 +2614,20 @@ gen_method:
                                disp = dseg_add_functionptr(cd, bte->fp);
 
                                M_ALD(REG_PV, REG_PV, disp);  /* Pointer to built-in-function */
+
+                               /* generate the actual call */
+
+                               M_JSR(REG_RA, REG_PV);
+                               REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
+                               disp = (s4) (cd->mcodeptr - cd->mcodebase);
+                               M_LDA(REG_PV, REG_RA, -disp);
+
+                               emit_exception_check(cd, iptr);
                                break;
 
                        case ICMD_INVOKESPECIAL:
-                               M_BEQZ(REG_A0, 0);
-                               codegen_add_nullpointerexception_ref(cd);
-                               /* fall through */
+                               emit_nullpointer_check(cd, iptr, REG_A0);
+                               /* fall-through */
 
                        case ICMD_INVOKESTATIC:
                                if (lm == NULL) {
@@ -2671,11 +2640,16 @@ gen_method:
                                        disp = dseg_add_address(cd, lm->stubroutine);
 
                                M_ALD(REG_PV, REG_PV, disp);         /* method pointer in r27 */
+
+                               /* generate the actual call */
+
+                               M_JSR(REG_RA, REG_PV);
+                               REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
+                               disp = (s4) (cd->mcodeptr - cd->mcodebase);
+                               M_LDA(REG_PV, REG_RA, -disp);
                                break;
 
                        case ICMD_INVOKEVIRTUAL:
-                               emit_nullpointer_check(cd, iptr, REG_A0);
-
                                if (lm == NULL) {
                                        codegen_add_patch_ref(cd, PATCHER_invokevirtual, um, 0);
 
@@ -2685,14 +2659,19 @@ gen_method:
                                        s1 = OFFSET(vftbl_t, table[0]) +
                                                sizeof(methodptr) * lm->vftblindex;
 
-                               M_ALD(REG_METHODPTR, REG_A0,
-                                         OFFSET(java_objectheader, vftbl));
+                               /* implicit null-pointer check */
+                               M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_objectheader, vftbl));
                                M_ALD(REG_PV, REG_METHODPTR, s1);
+
+                               /* generate the actual call */
+
+                               M_JSR(REG_RA, REG_PV);
+                               REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
+                               disp = (s4) (cd->mcodeptr - cd->mcodebase);
+                               M_LDA(REG_PV, REG_RA, -disp);
                                break;
 
                        case ICMD_INVOKEINTERFACE:
-                               emit_nullpointer_check(cd, iptr, REG_A0);
-
                                if (lm == NULL) {
                                        codegen_add_patch_ref(cd, PATCHER_invokeinterface, um, 0);
 
@@ -2706,25 +2685,18 @@ gen_method:
                                        s2 = sizeof(methodptr) * (lm - lm->class->methods);
                                }
                                        
-                               M_ALD(REG_METHODPTR, REG_A0,
-                                         OFFSET(java_objectheader, vftbl));    
+                               /* implicit null-pointer check */
+                               M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_objectheader, vftbl));
                                M_ALD(REG_METHODPTR, REG_METHODPTR, s1);
                                M_ALD(REG_PV, REG_METHODPTR, s2);
-                               break;
-                       }
-
-                       /* generate the actual call */
-
-                       M_JSR(REG_RA, REG_PV);
-                       REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
-                       disp = (s4) (cd->mcodeptr - cd->mcodebase);
-                       M_LDA(REG_PV, REG_RA, -disp);
 
-                       /* actually only used for ICMD_BUILTIN */
+                               /* generate the actual call */
 
-                       if (INSTRUCTION_MUST_CHECK(iptr)) {
-                               M_BEQZ(REG_RESULT, 0);
-                               codegen_add_fillinstacktrace_ref(cd);
+                               M_JSR(REG_RA, REG_PV);
+                               REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
+                               disp = (s4) (cd->mcodeptr - cd->mcodebase);
+                               M_LDA(REG_PV, REG_RA, -disp);
+                               break;
                        }
 
                        /* store the return value */
@@ -2785,22 +2757,10 @@ gen_method:
 #endif
                                s1 = emit_load_s1(jd, iptr, REG_ITMP1);
 
-                               /* calculate interface checkcast code size */
-
-                               s2 = 6;
-                               if (super == NULL)
-                                       s2 += opt_shownops ? 1 : 0;
-
-                               /* calculate class checkcast code size */
-
-                               s3 = 9 /* 8 + (s1 == REG_ITMP1) */;
-                               if (super == NULL)
-                                       s3 += opt_shownops ? 1 : 0;
-
                                /* if class is not resolved, check which code to call */
 
                                if (super == NULL) {
-                                       M_BEQZ(s1, 4 + (opt_shownops ? 1 : 0) + s2 + 1 + s3);
+                                       emit_label_beqz(cd, BRANCH_LABEL_1, s1);
 
                                        disp = dseg_add_unique_s4(cd, 0);         /* super->flags */
 
@@ -2812,7 +2772,7 @@ gen_method:
                                        disp = dseg_add_s4(cd, ACC_INTERFACE);
                                        M_ILD(REG_ITMP3, REG_PV, disp);
                                        M_AND(REG_ITMP2, REG_ITMP3, REG_ITMP2);
-                                       M_BEQZ(REG_ITMP2, s2 + 1);
+                                       emit_label_beqz(cd, BRANCH_LABEL_2, REG_ITMP2);
                                }
 
                                /* interface checkcast code */
@@ -2820,33 +2780,36 @@ gen_method:
                                if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
                                        if (super == NULL) {
                                                codegen_add_patch_ref(cd,
-                                                                                         PATCHER_checkcast_instanceof_interface,
+                                                                                         PATCHER_checkcast_interface,
                                                                                          iptr->sx.s23.s3.c.ref,
                                                                                          0);
                                        }
                                        else
-                                               M_BEQZ(s1, s2);
+                                               emit_label_beqz(cd, BRANCH_LABEL_3, s1);
 
                                        M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
                                        M_ILD(REG_ITMP3, REG_ITMP2,
                                                  OFFSET(vftbl_t, interfacetablelength));
                                        M_LDA(REG_ITMP3, REG_ITMP3, -superindex);
-                                       M_BLEZ(REG_ITMP3, 0);
-                                       codegen_add_classcastexception_ref(cd, s1);
+                                       emit_classcast_check(cd, iptr, BRANCH_LE, REG_ITMP3, s1);
+
                                        M_ALD(REG_ITMP3, REG_ITMP2,
                                                  (s4) (OFFSET(vftbl_t, interfacetable[0]) -
                                                                superindex * sizeof(methodptr*)));
-                                       M_BEQZ(REG_ITMP3, 0);
-                                       codegen_add_classcastexception_ref(cd, s1);
+                                       emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ITMP3, s1);
 
                                        if (super == NULL)
-                                               M_BR(s3);
+                                               emit_label_br(cd, BRANCH_LABEL_4);
+                                       else
+                                               emit_label(cd, BRANCH_LABEL_3);
                                }
 
                                /* class checkcast code */
 
                                if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
                                        if (super == NULL) {
+                                               emit_label(cd, BRANCH_LABEL_2);
+
                                                disp = dseg_add_unique_address(cd, NULL);
 
                                                codegen_add_patch_ref(cd,
@@ -2857,7 +2820,7 @@ gen_method:
                                        else {
                                                disp = dseg_add_address(cd, supervftbl);
 
-                                               M_BEQZ(s1, s3);
+                                               emit_label_beqz(cd, BRANCH_LABEL_5, s1);
                                        }
 
                                        M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
@@ -2884,8 +2847,15 @@ gen_method:
 #endif
                                        /*                              } */
                                        M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3);
-                                       M_BEQZ(REG_ITMP3, 0);
-                                       codegen_add_classcastexception_ref(cd, s1);
+                                       emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ITMP3, s1);
+
+                                       if (super != NULL)
+                                               emit_label(cd, BRANCH_LABEL_5);
+                               }
+
+                               if (super == NULL) {
+                                       emit_label(cd, BRANCH_LABEL_1);
+                                       emit_label(cd, BRANCH_LABEL_4);
                                }
 
                                d = codegen_reg_of_dst(jd, iptr, s1);
@@ -2915,8 +2885,7 @@ gen_method:
                                M_LDA(REG_PV, REG_RA, -disp);
 
                                s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                               M_BEQZ(REG_RESULT, 0);
-                               codegen_add_classcastexception_ref(cd, s1);
+                               emit_classcast_check(cd, iptr, BRANCH_EQ, REG_RESULT, s1);
 
                                d = codegen_reg_of_dst(jd, iptr, s1);
                        }
@@ -2963,28 +2932,17 @@ gen_method:
 #endif
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+
                        if (s1 == d) {
                                M_MOV(s1, REG_ITMP1);
                                s1 = REG_ITMP1;
                        }
 
-                       /* calculate interface instanceof code size */
-
-                       s2 = 6;
-                       if (super == NULL)
-                               s2 += (d == REG_ITMP2 ? 1 : 0) + (opt_shownops ? 1 : 0);
-
-                       /* calculate class instanceof code size */
-
-                       s3 = 7;
-                       if (super == NULL)
-                               s3 += (opt_shownops ? 1 : 0);
-
                        /* if class is not resolved, check which code to call */
 
                        if (super == NULL) {
                                M_CLR(d);
-                               M_BEQZ(s1, 4 + (opt_shownops ? 1 : 0) + s2 + 1 + s3);
+                               emit_label_beqz(cd, BRANCH_LABEL_1, s1);
 
                                disp = dseg_add_unique_s4(cd, 0);             /* super->flags */
 
@@ -2996,7 +2954,7 @@ gen_method:
                                disp = dseg_add_s4(cd, ACC_INTERFACE);
                                M_ILD(REG_ITMP2, REG_PV, disp);
                                M_AND(REG_ITMP3, REG_ITMP2, REG_ITMP3);
-                               M_BEQZ(REG_ITMP3, s2 + 1);
+                               emit_label_beqz(cd, BRANCH_LABEL_2, REG_ITMP3);
                        }
 
                        /* interface instanceof code */
@@ -3009,12 +2967,12 @@ gen_method:
                                                M_CLR(d);
 
                                        codegen_add_patch_ref(cd,
-                                                                                 PATCHER_checkcast_instanceof_interface,
+                                                                                 PATCHER_instanceof_interface,
                                                                                  iptr->sx.s23.s3.c.ref, 0);
                                }
                                else {
                                        M_CLR(d);
-                                       M_BEQZ(s1, s2);
+                                       emit_label_beqz(cd, BRANCH_LABEL_3, s1);
                                }
 
                                M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
@@ -3027,13 +2985,17 @@ gen_method:
                                M_CMPULT(REG_ZERO, REG_ITMP1, d);      /* REG_ITMP1 != 0  */
 
                                if (super == NULL)
-                                       M_BR(s3);
+                                       emit_label_br(cd, BRANCH_LABEL_4);
+                               else
+                                       emit_label(cd, BRANCH_LABEL_3);
                        }
 
                        /* class instanceof code */
 
                        if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
                                if (super == NULL) {
+                                       emit_label(cd, BRANCH_LABEL_2);
+
                                        disp = dseg_add_unique_address(cd, NULL);
 
                                        codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_vftbl,
@@ -3044,7 +3006,7 @@ gen_method:
                                        disp = dseg_add_address(cd, supervftbl);
 
                                        M_CLR(d);
-                                       M_BEQZ(s1, s3);
+                                       emit_label_beqz(cd, BRANCH_LABEL_5, s1);
                                }
 
                                M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
@@ -3060,7 +3022,16 @@ gen_method:
 #endif
                                M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
                                M_CMPULE(REG_ITMP1, REG_ITMP2, d);
+
+                               if (super != NULL)
+                                       emit_label(cd, BRANCH_LABEL_5);
+                       }
+
+                       if (super == NULL) {
+                               emit_label(cd, BRANCH_LABEL_1);
+                               emit_label(cd, BRANCH_LABEL_4);
                        }
+
                        emit_store_dst(jd, iptr, d);
                        }
                        break;
@@ -3117,8 +3088,7 @@ gen_method:
 
                        /* check for exception before result assignment */
 
-                       M_BEQZ(REG_RESULT, 0);
-                       codegen_add_fillinstacktrace_ref(cd);
+                       emit_exception_check(cd, iptr);
 
                        d = codegen_reg_of_dst(jd, iptr, REG_RESULT);
                        M_INTMOVE(REG_RESULT, d);
@@ -3140,12 +3110,9 @@ gen_method:
 
        /* generate stubs */
 
-       emit_exception_stubs(jd);
        emit_patcher_stubs(jd);
        REPLACEMENT_EMIT_STUBS(jd);
 
-       codegen_finish(jd);
-
        /* everything's ok */
 
        return true;
index a567903d1c97f8a10c05178ad2750fc0b956ef9f..fb60d38f617914493e68f5c382ee6c5d4440579f 100644 (file)
@@ -1,6 +1,6 @@
 /* vm/jit/alpha/codegen.h - code generation macros and definitions for Alpha
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
    J. Wenninger, Institut f. Computersprachen - TU Wien
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Andreas Krall
-            Reinhard Grafl
-            Christian Thalinger
-
-   $Id: codegen.h 6078 2006-11-28 22:19:16Z twisti $
+   $Id: codegen.h 7596 2007-03-28 21:05:53Z twisti $
 
 */
 
         cd->mcodeptr += 4; \
     } while (0)
 
+#define M_MEM_GET_A(x)                  (((x) >> 21) & 0x1f  )
+#define M_MEM_GET_B(x)                  (((x) >> 16) & 0x1f  )
+#define M_MEM_GET_DISP(x)               ( (x)        & 0xffff)
+
 
 /* macros for all used commands (see an Alpha-manual for description) *********/
 
         } \
     } while (0)
 
+#define M_ALD_INTERN(a,b,disp)  M_LLD_INTERN(a,b,disp)
 #define M_ALD(a,b,disp)         M_LLD(a,b,disp)                 /* addr load  */
 
 #define M_BST(a,b,disp)         M_MEM(0x0e,a,b,disp)            /*  8 store   */
index dd0743e9dee072f8213f0b27150bb3e003c9c316..0ee8f57dbd62f45d6d0999b59ae162fd4665c15f 100644 (file)
@@ -43,6 +43,7 @@
 #endif
 
 #include "vm/builtin.h"
+#include "vm/exceptions.h"
 
 #include "vm/jit/abi-asm.h"
 #include "vm/jit/asmpart.h"
@@ -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);
        }
 }
 
index 8bc0aec27f2dc5e739a67ca4b0d2a4d04736f5f6..ff3e765d5ca6decd26d11d968a4f7a4e8eade16a 100644 (file)
@@ -1,4 +1,4 @@
-/* src/vm/jit/alpha/linux/md.c - machine dependent Alpha Linux functions
+/* src/vm/jit/alpha/linux/md-os.c - machine dependent Alpha Linux functions
 
    Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: md-os.c 7251 2007-01-29 20:24:53Z twisti $
+   $Id: md-os.c 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"
 
 void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
 {
-       ucontext_t  *_uc;
-       mcontext_t  *_mc;
-       u4           instr;
-       ptrint       addr;
-       u1          *pv;
-       u1          *sp;
-       u1          *ra;
-       u1          *xpc;
+       ucontext_t        *_uc;
+       mcontext_t        *_mc;
+       u1                *pv;
+       u1                *sp;
+       u1                *ra;
+       u1                *xpc;
+       u4                 mcode;
+       s4                 d;
+       s4                 s1;
+       s4                 disp;
+       ptrint             val;
+       ptrint             addr;
+       s4                 type;
+       java_objectheader *e;
 
        _uc = (ucontext_t *) _p;
        _mc = &_uc->uc_mcontext;
@@ -69,23 +76,40 @@ void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
        ra  = (u1 *) _mc->sc_regs[REG_RA];           /* this is correct for leafs */
        xpc = (u1 *) _mc->sc_pc;
 
-       instr = *((s4 *) (_mc->sc_pc));
-       addr = _mc->sc_regs[(instr >> 16) & 0x1f];
+       /* get exception-throwing instruction */
 
-       if (addr == 0) {
-               _mc->sc_regs[REG_ITMP1_XPTR] =
-                       (ptrint) stacktrace_hardware_nullpointerexception(pv, sp, ra, xpc);
+       mcode = *((u4 *) xpc);
 
-               _mc->sc_regs[REG_ITMP2_XPC] = (ptrint) xpc;
-               _mc->sc_pc = (ptrint) asm_handle_exception;
+       d    = M_MEM_GET_A(mcode);
+       s1   = M_MEM_GET_B(mcode);
+       disp = M_MEM_GET_DISP(mcode);
+
+       val   = _mc->sc_regs[d];
+
+       /* check for special-load */
+
+       if (s1 == REG_ZERO) {
+               /* we use the exception type as load displacement */
+
+               type = disp;
        }
        else {
-               codegen_get_pv_from_pc(xpc);
-
-               /* this should not happen */
+               /* This is a normal NPE: addr must be NULL and the NPE-type
+                  define is 0. */
 
-               assert(0);
+               addr = _mc->sc_regs[s1];
+               type = (s4) addr;
        }
+
+       /* generate appropriate exception */
+
+       e = exceptions_new_hardware_exception(pv, sp, ra, xpc, type, val);
+
+       /* set registers */
+
+       _mc->sc_regs[REG_ITMP1_XPTR] = (ptrint) e;
+       _mc->sc_regs[REG_ITMP2_XPC]  = (ptrint) xpc;
+       _mc->sc_pc                   = (ptrint) asm_handle_exception;
 }
 
 
index 41c63662af286dc32c159e11ee69cd4534084a0d..1aef1bad18a3691f664747805fd5a63ce3906d91 100644 (file)
@@ -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
index 2c37a890760009bb18ef11f30b369845462acdc8..17626af7916060fbd34f8a679eac03b8f2bf2e59 100644 (file)
@@ -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:
+
+   <patched call position>
+   a78e0000    ldq     at,0(s5)
+   a3bc001c    ldl     gp,28(at)
+   23bdfffd    lda     gp,-3(gp)
+   efa0002e    ble     gp,0x00000200002bf6b0
+   a7bcffe8    ldq     gp,-24(at)
+
+*******************************************************************************/
+
+bool patcher_instanceof_interface(u1 *sp)
 {
        u1                *ra;
        constant_classref *cr;
index 609debb245a0d3ac63de61868668cab6c547369c..2f0fd01c4c189178fa29fbf3b87d4ecb721f97be 100644 (file)
@@ -27,7 +27,7 @@
    Authors: Michael Starzinger
             Christian Thalinger
 
-   $Id: arch.h 7241 2007-01-27 15:52:01Z twisti $
+   $Id: arch.h 7596 2007-03-28 21:05:53Z twisti $
 
 */
 
 /* define SUPPORT_COMBINE_INTEGER_REGISTERS                                   */
 
 
+/* branches *******************************************************************/
+
+#define SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER       1
+#define SUPPORT_BRANCH_CONDITIONAL_UNSIGNED_CONDITIONS      1
+#define SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER     0
+#define SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS    0
+
+
 /* exceptions *****************************************************************/
 
 #define SUPPORT_HARDWARE_DIVIDE_BY_ZERO  0
index a866859b2b2dd485e45deb04b2b78c220ce4ac48..080d7ceb192e00411ec1ec11bc5c7609b8735181 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: asmpart.S 7325 2007-02-11 20:10:35Z twisti $
+   $Id: asmpart.S 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
 
 
index 3e803686aa7e281a954af1bc251f726231c3a37b..147798f55d79eda9aca29e7c83dc59dbfc07e75a 100644 (file)
@@ -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 $
 
 */
 
 #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 */
 
index a23496151574a93362e180c3284558a4d4ee07b0..bd7ea006c6b5bbb304255657a42778fbe599bbe8 100644 (file)
@@ -1,6 +1,6 @@
 /* src/vm/jit/arm/codegen.h - code generation macros and definitions for ARM
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
    J. Wenninger, Institut f. Computersprachen - TU Wien
@@ -27,7 +27,7 @@
    Authors: Michael Starzinger
             Christian Thalinger
 
-   $Id: codegen.h 7276 2007-02-02 11:58:18Z michi $
+   $Id: codegen.h 7596 2007-03-28 21:05:53Z twisti $
 
 */
 
 
 /* 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 */
 
 
index c5ab738d8c1429d95b25f54ce507d1abf626d7c0..7bcb3e7543d5b3e27a54b24c9d998bf80501a230 100644 (file)
@@ -44,6 +44,7 @@
 #endif
 
 #include "vm/builtin.h"
+#include "vm/exceptions.h"
 #include "vm/global.h"
 
 #include "vm/jit/asmpart.h"
@@ -338,6 +339,101 @@ void emit_iconst(codegendata *cd, s4 d, s4 value)
 }
 
 
+/* emit_branch *****************************************************************
+
+   Emits the code for conditional and unconditional branchs.
+
+*******************************************************************************/
+
+void emit_branch(codegendata *cd, s4 disp, s4 condition, s4 reg, u4 opt)
+{
+       s4 checkdisp;
+       s4 branchdisp;
+
+       /* calculate the different displacements */
+
+       checkdisp  = (disp - 8);
+       branchdisp = (disp - 8) >> 2;
+
+       /* check which branch to generate */
+
+       if (condition == BRANCH_UNCONDITIONAL) {
+               /* check displacement for overflow */
+
+               if ((checkdisp < (s4) 0xff000000) || (checkdisp > (s4) 0x00ffffff)) {
+                       /* if the long-branches flag isn't set yet, do it */
+
+                       if (!CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
+                               cd->flags |= (CODEGENDATA_FLAG_ERROR |
+                                                         CODEGENDATA_FLAG_LONGBRANCHES);
+                       }
+
+                       vm_abort("emit_branch: emit unconditional long-branch code");
+               }
+               else {
+                       M_B(branchdisp);
+               }
+       }
+       else {
+               /* and displacement for overflow */
+
+               if ((checkdisp < (s4) 0xff000000) || (checkdisp > (s4) 0x00ffffff)) {
+                       /* if the long-branches flag isn't set yet, do it */
+
+                       if (!CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
+                               cd->flags |= (CODEGENDATA_FLAG_ERROR |
+                                                         CODEGENDATA_FLAG_LONGBRANCHES);
+                       }
+
+                       vm_abort("emit_branch: emit conditional long-branch code");
+               }
+               else {
+                       switch (condition) {
+                       case BRANCH_EQ:
+                               M_BEQ(branchdisp);
+                               break;
+                       case BRANCH_NE:
+                               M_BNE(branchdisp);
+                               break;
+                       case BRANCH_LT:
+                               M_BLT(branchdisp);
+                               break;
+                       case BRANCH_GE:
+                               M_BGE(branchdisp);
+                               break;
+                       case BRANCH_GT:
+                               M_BGT(branchdisp);
+                               break;
+                       case BRANCH_LE:
+                               M_BLE(branchdisp);
+                               break;
+                       case BRANCH_UGT:
+                               M_BHI(branchdisp);
+                               break;
+                       default:
+                               vm_abort("emit_branch: unknown condition %d", condition);
+                       }
+               }
+       }
+}
+
+
+/* emit_arithmetic_check *******************************************************
+
+   Emit an ArithmeticException check.
+
+*******************************************************************************/
+
+void emit_arithmetic_check(codegendata *cd, instruction *iptr, s4 reg)
+{
+       if (INSTRUCTION_MUST_CHECK(iptr)) {
+               CHECK_INT_REG(reg);
+               M_TEQ_IMM(reg, 0);
+               M_TRAPEQ(0, EXCEPTION_HARDWARE_ARITHMETIC);
+       }
+}
+
+
 /* emit_nullpointer_check ******************************************************
 
    Emit a NullPointerException check.
@@ -348,11 +444,16 @@ void emit_nullpointer_check(codegendata *cd, instruction *iptr, s4 reg)
 {
        if (INSTRUCTION_MUST_CHECK(iptr)) {
                M_TST(reg, reg);
-               M_BEQ(0);
-               codegen_add_nullpointerexception_ref(cd);
+               M_TRAPEQ(0, EXCEPTION_HARDWARE_NULLPOINTER);
        }
 }
 
+void emit_nullpointer_check_force(codegendata *cd, instruction *iptr, s4 reg)
+{
+       M_TST(reg, reg);
+       M_TRAPEQ(0, EXCEPTION_HARDWARE_NULLPOINTER);
+}
+
 
 /* emit_arrayindexoutofbounds_check ********************************************
 
@@ -365,8 +466,50 @@ void emit_arrayindexoutofbounds_check(codegendata *cd, instruction *iptr, s4 s1,
        if (INSTRUCTION_MUST_CHECK(iptr)) {
                M_ILD_INTERN(REG_ITMP3, s1, OFFSET(java_arrayheader, size));
                M_CMP(s2, REG_ITMP3);
-               M_BHS(0);
-               codegen_add_arrayindexoutofboundsexception_ref(cd, s2);
+               M_TRAPHS(s2, EXCEPTION_HARDWARE_ARRAYINDEXOUTOFBOUNDS);
+       }
+}
+
+
+/* emit_classcast_check ********************************************************
+
+   Emit a ClassCastException check.
+
+*******************************************************************************/
+
+void emit_classcast_check(codegendata *cd, instruction *iptr, s4 condition, s4 reg, s4 s1)
+{
+       if (INSTRUCTION_MUST_CHECK(iptr)) {
+               switch (condition) {
+               case BRANCH_EQ:
+                       M_TRAPEQ(s1, EXCEPTION_HARDWARE_CLASSCAST);
+                       break;
+
+               case BRANCH_LE:
+                       M_TRAPLE(s1, EXCEPTION_HARDWARE_CLASSCAST);
+                       break;
+
+               case BRANCH_UGT:
+                       M_TRAPHI(s1, EXCEPTION_HARDWARE_CLASSCAST);
+                       break;
+
+               default:
+                       vm_abort("emit_classcast_check: unknown condition %d", condition);
+               }
+       }
+}
+
+/* emit_exception_check ********************************************************
+
+   Emit an Exception check.
+
+*******************************************************************************/
+
+void emit_exception_check(codegendata *cd, instruction *iptr)
+{
+       if (INSTRUCTION_MUST_CHECK(iptr)) {
+               M_TST(REG_RESULT, REG_RESULT);
+               M_TRAPEQ(0, EXCEPTION_HARDWARE_EXCEPTION);
        }
 }
 
@@ -377,6 +520,7 @@ void emit_arrayindexoutofbounds_check(codegendata *cd, instruction *iptr, s4 s1,
 
 *******************************************************************************/
 
+#if 0
 void emit_exception_stubs(jitdata *jd)
 {
        codegendata  *cd;
@@ -399,7 +543,7 @@ void emit_exception_stubs(jitdata *jd)
        for (er = cd->exceptionrefs; er != NULL; er = er->next) {
                /* back-patch the branch to this exception code */
 
-               branchmpc = er->branchpos;
+               branchmpc = er->branchmpc;
                targetmpc = cd->mcodeptr - cd->mcodebase;
 
                md_codegen_patch_branch(cd, branchmpc, targetmpc);
@@ -415,8 +559,8 @@ void emit_exception_stubs(jitdata *jd)
 
                /* calcuate exception address */
 
-               assert((er->branchpos - 4) % 4 == 0);
-               M_ADD_IMM_EXT_MUL4(REG_ITMP2_XPC, REG_PV, (er->branchpos - 4) / 4);
+               assert((er->branchmpc - 4) % 4 == 0);
+               M_ADD_IMM_EXT_MUL4(REG_ITMP2_XPC, REG_PV, (er->branchmpc - 4) / 4);
 
                /* move function to call into REG_ITMP3 */
 
@@ -473,6 +617,7 @@ void emit_exception_stubs(jitdata *jd)
                }
        }
 }
+#endif
 
 
 /* emit_patcher_stubs **********************************************************
@@ -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 */
index a27158890652769e9e7cfd9c059781b184e80c9b..c4a5d85aefe50232d24fae0ca8f925b150615afb 100644 (file)
@@ -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
 
index c47708555272c5ed50b355d4db94984efaf89a57..b169ff45436b5062379cf58d97dd5aa6aa6288ca 100644 (file)
@@ -1,6 +1,6 @@
-/* src/vm/jit/arm/linux/md.c - machine dependent arm linux functions
+/* src/vm/jit/arm/linux/md-os.c - machine dependent arm linux functions
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
    J. Wenninger, Institut f. Computersprachen - TU Wien
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Michael Starzinger
-            Christian Thalinger
-
    $Id: md.c 166 2006-01-22 23:38:44Z twisti $
 
 */
@@ -66,8 +61,7 @@ typedef struct ucontext {
 
 /* md_signal_handler_sigsegv ***************************************************
 
-   NullPointerException signal handler for hardware null pointer
-   check.
+   Signal handler for hardware exceptions.
 
 *******************************************************************************/
 
@@ -116,6 +110,60 @@ void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
 }
 
 
+/* md_signal_handler_sigill ****************************************************
+
+   Illegal Instruction signal handler for hardware exception checks.
+
+*******************************************************************************/
+
+void md_signal_handler_sigill(int sig, siginfo_t *siginfo, void *_p)
+{
+       ucontext_t        *_uc;
+       scontext_t        *_sc;
+       u1                *pv;
+       u1                *sp;
+       u1                *ra;
+       u1                *xpc;
+       u4                 mcode;
+       s4                 type;
+       ptrint             val;
+       java_objectheader *o;
+
+       _uc = (ucontext_t*) _p;
+       _sc = &_uc->uc_mcontext;
+
+       /* ATTENTION: glibc included messed up kernel headers we needed a
+          workaround for the ucontext structure. */
+
+       pv  = (u1*) _sc->arm_ip;
+       sp  = (u1*) _sc->arm_sp;
+       ra  = (u1*) _sc->arm_lr;                     /* this is correct for leafs */
+       xpc = (u1*) _sc->arm_pc;
+
+       /* get exception-throwing instruction */
+
+       mcode = *((u4 *) xpc);
+
+       /* check for undefined instruction we use */
+
+       if ((mcode & 0x0ff000f0) != 0x07f000f0)
+               vm_abort("md_signal_handler_sigill: unknown illegal instruction");
+
+       type = (mcode >> 8) & 0x0fff;
+       val  = *((s4 *) _sc + OFFSET(scontext_t, arm_r0)/4 + (mcode & 0x0f));
+
+       /* generate appropriate exception */
+
+       o = exceptions_new_hardware_exception(pv, sp, ra, xpc, type, val);
+
+       /* set registers */
+
+       _sc->arm_r10 = (ptrint) o;
+       _sc->arm_fp  = (ptrint) xpc;
+       _sc->arm_pc  = (ptrint) asm_handle_exception;
+}
+
+
 /* thread_restartcriticalsection ***********************************************
 
    TODO: document me
index d11f44643efe7a6a7b0a99f3164a72dc4f38380e..066ed41138721f77526c79d484eb5ee23f00807a 100644 (file)
@@ -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);
index 2a4a2395fd8e94258155ecaf4068e31ffcfad4ec..c527ec0f85dbefc80e0dba1adc5ea96175f10445 100644 (file)
@@ -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 $
 
 */
 
 #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)
index baccfd4935275049360cd33fc36874617f3cd693..82c6ff64a6a9b35e896ff76896ce63b7c4529ae3 100644 (file)
@@ -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);
index 302428c75060e197e33e21ec17e7509796a91901..fd46f72c6748c03298567e3ae43d3cbb26b1ba91 100644 (file)
@@ -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         */
index 47999c1aa33f584b3678ea477e89072e117bdbc5..9d81474fce8b304a3ffaa7f333d64206c7b7f34b 100644 (file)
@@ -39,7 +39,7 @@
    memory. All functions writing values into the data area return the offset
    relative the begin of the code area (start of procedure).   
 
-   $Id: codegen-common.c 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);
index c23ceef8b2fc7889d4dea9ab2173707ffa9bf43a..11612d10b242aee4682cc5d965612f189c38bc07 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: codegen-common.h 7283 2007-02-04 19:41:14Z pm $
+   $Id: codegen-common.h 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 */
 
index 0371ca0a2278d4ec3500ace89192ca0f590ba5ee..725563674f78cb68cb3185a7629c249e8b73488d 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: disass-common.c 7382 2007-02-21 20:24:01Z twisti $
+   $Id: disass-common.c 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);
index 5cb3de9b04a0d2dbfb5fc7bb4cac0d658f5440da..cf7c92291c69baa2ecb87381aec62a9aa90fb180 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: disass.h 7331 2007-02-11 21:41:19Z twisti $
+   $Id: disass.h 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
index 9a2d3b2e6a5a9ae5ee8f4eca5e25760412ef768b..02400e62c636194ee1b5d370b6d5a809a34f73d8 100644 (file)
@@ -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;
index e0f6a9d4f08c79676b6d2d8838fce71a99eff94e..c313e873d77728e3c6a42c500a0c5c82244ceb9e 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: dseg.h 7246 2007-01-29 18:49:05Z twisti $
+   $Id: dseg.h 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
index 2810994f58a5973d3e900710a3f99c6defff4091..243109adc6b2754a6c65a1b6fc428d252d8094de 100644 (file)
@@ -33,6 +33,7 @@
 
 #include "vm/types.h"
 
+#include "arch.h"
 #include "codegen.h"
 
 #include "vm/jit/emit-common.h"
@@ -246,13 +247,14 @@ void emit_store_dst(jitdata *jd, instruction *iptr, s4 d)
 }
 
 
-/* emit_bxx ********************************************************************
+/* emit_bccz *******************************************************************
 
-   Wrappers for conditional branch instructions.
+   Emit conditional and unconditional branch instructions on integer
+   regiseters.
 
 *******************************************************************************/
 
-void emit_bc(codegendata *cd, basicblock *target, s4 condition)
+void emit_bccz(codegendata *cd, basicblock *target, s4 condition, s4 reg, u4 options)
 {
        s4 branchmpc;
        s4 disp;
@@ -268,90 +270,379 @@ void emit_bc(codegendata *cd, basicblock *target, s4 condition)
                branchmpc = cd->mcodeptr - cd->mcodebase;
                disp      = target->mpc - branchmpc;
 
-#if 0
-               emit_branch(cd, disp, condition);
-#endif
+               emit_branch(cd, disp, condition, reg, options);
        }
        else {
                /* current mcodeptr is the correct position,
                   afterwards emit the NOPs */
 
-#if 0
-               codegen_add_branch_ref(cd, target, condition);
-#endif
+               codegen_add_branch_ref(cd, target, condition, reg, options);
 
                /* generate NOPs as placeholder for branch code */
-               /* XXX if recompile-with-long-branches */
 
                BRANCH_NOPS;
        }
 }
 
 
+/* emit_bcc ********************************************************************
+
+   Emit conditional and unconditional branch instructions on condition
+   codes.
+
+*******************************************************************************/
+
+void emit_bcc(codegendata *cd, basicblock *target, s4 condition, u4 options)
+{
+       emit_bccz(cd, target, condition, -1, options);
+}
+
+
+/* emit_br *********************************************************************
+
+   Wrapper for unconditional branches.
+
+*******************************************************************************/
+
 void emit_br(codegendata *cd, basicblock *target)
 {
-       emit_bc(cd, target, BRANCH_UNCONDITIONAL);
+       emit_bcc(cd, target, BRANCH_UNCONDITIONAL, BRANCH_OPT_NONE);
 }
 
 
-void emit_beq(codegendata *cd, basicblock *target)
+/* emit_bxxz *******************************************************************
+
+   Wrappers for branches on one integer register.
+
+*******************************************************************************/
+
+#if SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER
+
+void emit_beqz(codegendata *cd, basicblock *target, s4 reg)
+{
+       emit_bccz(cd, target, BRANCH_EQ, reg, BRANCH_OPT_NONE);
+}
+
+void emit_bnez(codegendata *cd, basicblock *target, s4 reg)
 {
-       emit_bc(cd, target, BRANCH_EQ);
+       emit_bccz(cd, target, BRANCH_NE, reg, BRANCH_OPT_NONE);
 }
 
+void emit_bltz(codegendata *cd, basicblock *target, s4 reg)
+{
+       emit_bccz(cd, target, BRANCH_LT, reg, BRANCH_OPT_NONE);
+}
 
-void emit_bne(codegendata *cd, basicblock *target)
+void emit_bgez(codegendata *cd, basicblock *target, s4 reg)
 {
-       emit_bc(cd, target, BRANCH_NE);
+       emit_bccz(cd, target, BRANCH_GE, reg, BRANCH_OPT_NONE);
 }
 
+void emit_bgtz(codegendata *cd, basicblock *target, s4 reg)
+{
+       emit_bccz(cd, target, BRANCH_GT, reg, BRANCH_OPT_NONE);
+}
 
-void emit_blt(codegendata *cd, basicblock *target)
+void emit_blez(codegendata *cd, basicblock *target, s4 reg)
 {
-       emit_bc(cd, target, BRANCH_LT);
+       emit_bccz(cd, target, BRANCH_LE, reg, BRANCH_OPT_NONE);
 }
 
+#endif /* SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER */
 
-void emit_bge(codegendata *cd, basicblock *target)
+
+/* emit_bxx ********************************************************************
+
+   Wrappers for branches on two integer registers.
+
+   We use PACK_REGS here, so we don't have to change the branchref
+   data structure and the emit_bccz function.
+
+*******************************************************************************/
+
+#if SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS
+
+void emit_beq(codegendata *cd, basicblock *target, s4 s1, s4 s2)
 {
-       emit_bc(cd, target, BRANCH_GE);
+       emit_bccz(cd, target, BRANCH_EQ, PACK_REGS(s1, s2), BRANCH_OPT_NONE);
 }
 
+void emit_bne(codegendata *cd, basicblock *target, s4 s1, s4 s2)
+{
+       emit_bccz(cd, target, BRANCH_NE, PACK_REGS(s1, s2), BRANCH_OPT_NONE);
+}
 
-void emit_bgt(codegendata *cd, basicblock *target)
+#endif /* SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS */
+
+
+/* emit_bxx ********************************************************************
+
+   Wrappers for branches on condition codes.
+
+*******************************************************************************/
+
+#if SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER
+
+void emit_beq(codegendata *cd, basicblock *target)
+{
+       emit_bcc(cd, target, BRANCH_EQ, BRANCH_OPT_NONE);
+}
+
+void emit_bne(codegendata *cd, basicblock *target)
 {
-       emit_bc(cd, target, BRANCH_GT);
+       emit_bcc(cd, target, BRANCH_NE, BRANCH_OPT_NONE);
 }
 
+void emit_blt(codegendata *cd, basicblock *target)
+{
+       emit_bcc(cd, target, BRANCH_LT, BRANCH_OPT_NONE);
+}
+
+void emit_bge(codegendata *cd, basicblock *target)
+{
+       emit_bcc(cd, target, BRANCH_GE, BRANCH_OPT_NONE);
+}
+
+void emit_bgt(codegendata *cd, basicblock *target)
+{
+       emit_bcc(cd, target, BRANCH_GT, BRANCH_OPT_NONE);
+}
 
 void emit_ble(codegendata *cd, basicblock *target)
 {
-       emit_bc(cd, target, BRANCH_LE);
+       emit_bcc(cd, target, BRANCH_LE, BRANCH_OPT_NONE);
 }
 
+#if SUPPORT_BRANCH_CONDITIONAL_UNSIGNED_CONDITIONS
+void emit_bult(codegendata *cd, basicblock *target)
+{
+       emit_bcc(cd, target, BRANCH_ULT, BRANCH_OPT_NONE);
+}
 
+void emit_bule(codegendata *cd, basicblock *target)
+{
+       emit_bcc(cd, target, BRANCH_ULE, BRANCH_OPT_NONE);
+}
+
+void emit_buge(codegendata *cd, basicblock *target)
+{
+       emit_bcc(cd, target, BRANCH_UGE, BRANCH_OPT_NONE);
+}
+
+void emit_bugt(codegendata *cd, basicblock *target)
+{
+       emit_bcc(cd, target, BRANCH_UGT, BRANCH_OPT_NONE);
+}
+#endif
+
+#if defined(__POWERPC__) || defined(__POWERPC64__)
 void emit_bnan(codegendata *cd, basicblock *target)
 {
-       emit_bc(cd, target, BRANCH_NAN);
+       emit_bcc(cd, target, BRANCH_NAN, BRANCH_OPT_NONE);
+}
+#endif
+
+#endif /* SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER */
+
+
+/* emit_label_bccz *************************************************************
+
+   Emit a branch to a label.  Possibly emit the branch, if it is a
+   backward branch.
+
+*******************************************************************************/
+
+void emit_label_bccz(codegendata *cd, s4 label, s4 condition, s4 reg, u4 options)
+{
+       list               *list;
+       branch_label_ref_t *br;
+       s4                  mpc;
+       s4                  disp;
+
+       /* get the label list */
+
+       list = cd->brancheslabel;
+
+       /* search if the label is already in the list */
+
+       for (br = list_first_unsynced(list); br != NULL;
+                br = list_next_unsynced(list, br)) {
+               /* is this entry the correct label? */
+
+               if (br->label == label)
+                       break;
+       }
+
+       /* a branch reference was found */
+
+       if (br != NULL) {
+               /* calculate the mpc of the branch instruction */
+
+               mpc  = cd->mcodeptr - cd->mcodebase;
+               disp = br->mpc - mpc;
+
+               emit_branch(cd, disp, condition, reg, options);
+
+               /* now remove the branch reference */
+
+               list_remove_unsynced(list, br);
+       }
+       else {
+               /* current mcodeptr is the correct position,
+                  afterwards emit the NOPs */
+
+               codegen_branch_label_add(cd, label, condition, reg, options);
+
+               /* generate NOPs as placeholder for branch code */
+
+               BRANCH_NOPS;
+       }
 }
 
 
-/* emit_array_checks ***********************************************************
+/* emit_label ******************************************************************
 
-   Emit exception checks for array accesses, if they need to be
-   emitted.
+   Emit a label for a branch.  Possibly emit the branch, if it is a
+   forward branch.
 
 *******************************************************************************/
 
-void emit_array_checks(codegendata *cd, instruction *iptr, s4 s1, s4 s2)
+void emit_label(codegendata *cd, s4 label)
 {
-       if (INSTRUCTION_MUST_CHECK(iptr)) {
-               emit_nullpointer_check(cd, iptr, s1);
-               emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
+       list               *list;
+       branch_label_ref_t *br;
+       s4                  mpc;
+       s4                  disp;
+       u1                 *mcodeptr;
+
+       /* get the label list */
+
+       list = cd->brancheslabel;
+
+       /* search if the label is already in the list */
+
+       for (br = list_first_unsynced(list); br != NULL;
+                br = list_next_unsynced(list, br)) {
+               /* is this entry the correct label? */
+
+               if (br->label == label)
+                       break;
+       }
+
+       /* a branch reference was found */
+
+       if (br != NULL) {
+               /* calculate the mpc of the branch instruction */
+
+               mpc  = cd->mcodeptr - cd->mcodebase;
+               disp = mpc - br->mpc;
+
+               /* temporary set the mcodeptr */
+
+               mcodeptr     = cd->mcodeptr;
+               cd->mcodeptr = cd->mcodebase + br->mpc;
+
+               emit_branch(cd, disp, br->condition, br->reg, br->options);
+
+               /* restore mcodeptr */
+
+               cd->mcodeptr = mcodeptr;
+
+               /* now remove the branch reference */
+
+               list_remove_unsynced(list, br);
+       }
+       else {
+               /* add the label to the list (use invalid values for condition
+                  and register) */
+
+               codegen_branch_label_add(cd, label, -1, -1, BRANCH_OPT_NONE );
        }
 }
 
 
+/* emit_label_bcc **************************************************************
+
+   Emit conditional and unconditional label-branch instructions on
+   condition codes.
+
+*******************************************************************************/
+
+void emit_label_bcc(codegendata *cd, s4 label, s4 condition, u4 options)
+{
+       emit_label_bccz(cd, label, condition, -1, options);
+}
+
+
+/* emit_label_br ***************************************************************
+
+   Wrapper for unconditional label-branches.
+
+*******************************************************************************/
+
+void emit_label_br(codegendata *cd, s4 label)
+{
+       emit_label_bcc(cd, label, BRANCH_UNCONDITIONAL, BRANCH_OPT_NONE);
+}
+
+
+/* emit_label_bxxz *************************************************************
+
+   Wrappers for label-branches on one integer register.
+
+*******************************************************************************/
+
+#if SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER
+
+void emit_label_beqz(codegendata *cd, s4 label, s4 reg)
+{
+       emit_label_bccz(cd, label, BRANCH_EQ, reg, BRANCH_OPT_NONE);
+}
+
+#endif /* SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER */
+
+
+/* emit_label_bxx **************************************************************
+
+   Wrappers for label-branches on condition codes.
+
+*******************************************************************************/
+
+#if SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER
+
+void emit_label_beq(codegendata *cd, s4 label)
+{
+       emit_label_bcc(cd, label, BRANCH_EQ, BRANCH_OPT_NONE);
+}
+
+void emit_label_bne(codegendata *cd, s4 label)
+{
+       emit_label_bcc(cd, label, BRANCH_NE, BRANCH_OPT_NONE);
+}
+
+void emit_label_blt(codegendata *cd, s4 label)
+{
+       emit_label_bcc(cd, label, BRANCH_LT, BRANCH_OPT_NONE);
+}
+
+void emit_label_bge(codegendata *cd, s4 label)
+{
+       emit_label_bcc(cd, label, BRANCH_GE, BRANCH_OPT_NONE);
+}
+
+void emit_label_bgt(codegendata *cd, s4 label)
+{
+       emit_label_bcc(cd, label, BRANCH_GT, BRANCH_OPT_NONE);
+}
+
+void emit_label_ble(codegendata *cd, s4 label)
+{
+       emit_label_bcc(cd, label, BRANCH_LE, BRANCH_OPT_NONE);
+}
+
+#endif /* SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER */
+
+
 /*
  * These are local overrides for various environment variables in Emacs.
  * Please do not remove this and leave it at the end of the file, where
index a3f0cac0f41a8c4b4f72d65d5c723696bc09a9be..61681eefec65b498de4fd0c47660aa0c9d1f2ebf 100644 (file)
 #include "config.h"
 #include "vm/types.h"
 
+#include "arch.h"
+
 #include "vm/jit/codegen-common.h"
 #include "vm/jit/jit.h"
 
 
+/* branch labels **************************************************************/
+
+#define BRANCH_LABEL_1    1
+#define BRANCH_LABEL_2    2
+#define BRANCH_LABEL_3    3
+#define BRANCH_LABEL_4    4
+#define BRANCH_LABEL_5    5
+
+
 /* constant range macros ******************************************************/
 
 #if SIZEOF_VOID_P == 8
@@ -90,30 +101,82 @@ void emit_copy(jitdata *jd, instruction *iptr, varinfo *src, varinfo *dst);
 void emit_iconst(codegendata *cd, s4 d, s4 value);
 void emit_lconst(codegendata *cd, s4 d, s8 value);
 
+/* branch-emitting functions */
+void emit_bccz(codegendata *cd, basicblock *target, s4 condition, s4 reg, u4 options);
+void emit_bcc(codegendata *cd, basicblock *target, s4 condition, u4 options);
+
+/* wrapper for unconditional branches */
 void emit_br(codegendata *cd, basicblock *target);
-void emit_bc(codegendata *cd, basicblock *target, s4 condition);
 
+/* wrappers for branches on one integer register */
+
+#if SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER
+void emit_beqz(codegendata *cd, basicblock *target, s4 reg);
+void emit_bnez(codegendata *cd, basicblock *target, s4 reg);
+void emit_bltz(codegendata *cd, basicblock *target, s4 reg);
+void emit_bgez(codegendata *cd, basicblock *target, s4 reg);
+void emit_bgtz(codegendata *cd, basicblock *target, s4 reg);
+void emit_blez(codegendata *cd, basicblock *target, s4 reg);
+#endif
+
+/* wrappers for branches on two integer registers */
+
+#if SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS
+void emit_beq(codegendata *cd, basicblock *target, s4 s1, s4 s2);
+void emit_bne(codegendata *cd, basicblock *target, s4 s1, s4 s2);
+#endif
+
+/* wrappers for branches on condition codes */
+
+#if SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER
 void emit_beq(codegendata *cd, basicblock *target);
 void emit_bne(codegendata *cd, basicblock *target);
 void emit_blt(codegendata *cd, basicblock *target);
 void emit_bge(codegendata *cd, basicblock *target);
 void emit_bgt(codegendata *cd, basicblock *target);
 void emit_ble(codegendata *cd, basicblock *target);
+#endif
+
+#if SUPPORT_BRANCH_CONDITIONAL_UNSIGNED_CONDITIONS
+void emit_bult(codegendata *cd, basicblock *target);
+void emit_bule(codegendata *cd, basicblock *target);
+void emit_buge(codegendata *cd, basicblock *target);
+void emit_bugt(codegendata *cd, basicblock *target);
+#endif
 
+#if defined(__POWERPC__)
 void emit_bnan(codegendata *cd, basicblock *target);
+#endif
+
+/* label-branches */
+void emit_label_bccz(codegendata *cd, s4 label, s4 condition, s4 reg, u4 options);
+void emit_label(codegendata *cd, s4 label);
+void emit_label_bcc(codegendata *cd, s4 label, s4 condition, u4 options);
 
-void emit_branch(codegendata *cd, s4 disp, s4 condition);
+void emit_label_br(codegendata *cd, s4 label);
+
+#if SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER
+void emit_label_beqz(codegendata *cd, s4 label, s4 reg);
+#endif
+
+#if SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER
+void emit_label_beq(codegendata *cd, s4 label);
+void emit_label_bne(codegendata *cd, s4 label);
+void emit_label_blt(codegendata *cd, s4 label);
+void emit_label_bge(codegendata *cd, s4 label);
+void emit_label_bgt(codegendata *cd, s4 label);
+void emit_label_ble(codegendata *cd, s4 label);
+#endif
+
+/* machine dependent branch-emitting function */
+void emit_branch(codegendata *cd, s4 disp, s4 condition, s4 reg, u4 options);
 
 void emit_arithmetic_check(codegendata *cd, instruction *iptr, s4 reg);
 void emit_arrayindexoutofbounds_check(codegendata *cd, instruction *iptr, s4 s1, s4 s2);
-void emit_arraystore_check(codegendata *cd, instruction *iptr, s4 reg);
 void emit_classcast_check(codegendata *cd, instruction *iptr, s4 condition, s4 reg, s4 s1);
 void emit_nullpointer_check(codegendata *cd, instruction *iptr, s4 reg);
 void emit_exception_check(codegendata *cd, instruction *iptr);
 
-void emit_array_checks(codegendata *cd, instruction *iptr, s4 s1, s4 s2);
-
-void emit_exception_stubs(jitdata *jd);
 void emit_patcher_stubs(jitdata *jd);
 #if defined(ENABLE_REPLACEMENT)
 void emit_replacement_stubs(jitdata *jd);
index 05472fef387baa0a4a8c132da4f019923d3ff6db..bbda7d6af646e505202047ac13711aa1f8c3e26a 100644 (file)
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Christian Thalinger
-
-   $Id: arch.h 7241 2007-01-27 15:52:01Z twisti $
+   $Id: arch.h 7596 2007-03-28 21:05:53Z twisti $
 
 */
 
 /* define SUPPORT_COMBINE_INTEGER_REGISTERS */
 
 
+/* branches *******************************************************************/
+
+#define SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER       1
+#define SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER     0
+#define SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS    0
+#define SUPPORT_BRANCH_CONDITIONAL_UNSIGNED_CONDITIONS      1
+
+
 /* exceptions *****************************************************************/
 
 #define SUPPORT_HARDWARE_DIVIDE_BY_ZERO  1
index 92f75974ef7cdd67ef3d2a6a6d9870ac88bb2068..b230622ab73161ee5fa55406c74bd13da3f302a2 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: asmpart.S 7310 2007-02-09 13:00:04Z twisti $
+   $Id: asmpart.S 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
 
 
index 32f9f94b8ae7d4dbecff97c7b458c57bb8906abf..a15b6d9575918dc8717b6ce18629546b80c9252c 100644 (file)
@@ -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);
index 35101a9f6f20803d31f87d0660e0399f4dc39abc..ccd69f58c5590d16b2a20059e634d45b4cdff6af 100644 (file)
@@ -1,6 +1,6 @@
 /* src/vm/jit/i386/codegen.h - code generation macros and definitions for i386
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
    J. Wenninger, Institut f. Computersprachen - TU Wien
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Andreas Krall
-            Christian Thalinger
-
-   $Id: codegen.h 6211 2006-12-16 22:53:24Z edwin $
+   $Id: codegen.h 7596 2007-03-28 21:05:53Z twisti $
 
 */
 
 
 /* branch defines *************************************************************/
 
+#define BRANCH_UNCONDITIONAL_SIZE    5  /* size in bytes of a branch          */
+#define BRANCH_CONDITIONAL_SIZE      6  /* size in bytes of a branch          */
+
 #define BRANCH_NOPS \
     do { \
         M_NOP; \
         M_NOP; \
         M_NOP; \
         M_NOP; \
+        M_NOP; \
     } while (0)
 
 
 #define M_ALD(a,b,disp)         M_ILD(a,b,disp)
 #define M_ALD32(a,b,disp)       M_ILD32(a,b,disp)
 
+#define M_ALD_MEM(a,disp)       emit_mov_mem_reg(cd, (disp), (a))
+
+#define M_ALD_MEM_GET_OPC(p)    (*(p))
+#define M_ALD_MEM_GET_MOD(p)    (((*(p + 1)) >> 6) & 0x03)
+#define M_ALD_MEM_GET_REG(p)    (((*(p + 1)) >> 3) & 0x07)
+#define M_ALD_MEM_GET_RM(p)     (((*(p + 1))     ) & 0x07)
+#define M_ALD_MEM_GET_DISP(p)   (*((u4 *) (p + 2)))
+
 #define M_LLD(a,b,disp) \
     do { \
         M_ILD(GET_LOW_REG(a),b,disp); \
index 5ff1011f43ee2efa5a95aaef3cb38eb77c54574e..5683320d82fd7166949aa67c85cc63695a08fbee 100644 (file)
@@ -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);
        }
 }
 
index 272eb3b1edc5b205e26b331482966d6d8cf18c39..e267c11cb515ae85aa7798156785d8e37ad41cf1 100644 (file)
@@ -1,6 +1,6 @@
 /* src/vm/jit/i386/linux/md-os.c - machine dependent i386 Linux functions
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
    J. Wenninger, Institut f. Computersprachen - TU Wien
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Christian Thalinger
-
-   Changes:
-
-   $Id: md-os.c 7496 2007-03-12 00:19:05Z michi $
+   $Id: md-os.c 7601 2007-03-28 23:02:50Z michi $
 
 */
 
 #include "vm/exceptions.h"
 #include "vm/signallocal.h"
 #include "vm/stringlocal.h"
+
 #include "vm/jit/asmpart.h"
 #include "vm/jit/stacktrace.h"
 
+#include "vm/jit/i386/codegen.h"
+
 
 /* md_signal_handler_sigsegv ***************************************************
 
-   NullPointerException signal handler for hardware null pointer
-   check.
+   Signal handler for hardware exceptions.
 
 *******************************************************************************/
 
 void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
 {
-       ucontext_t *_uc;
-       mcontext_t *_mc;
-       u1         *sp;
-       u1         *ra;
-       u1         *xpc;
+       ucontext_t        *_uc;
+       mcontext_t        *_mc;
+       u1                *pv;
+       u1                *sp;
+       u1                *ra;
+       u1                *xpc;
+       u1                 opc;
+       u1                 mod;
+       u1                 rm;
+       s4                 d;
+       s4                 disp;
+       ptrint             val;
+       s4                 type;
+       java_objectheader *e;
 
        _uc = (ucontext_t *) _p;
        _mc = &_uc->uc_mcontext;
 
+       pv  = NULL;                 /* is resolved during stackframeinfo creation */
        sp  = (u1 *) _mc->gregs[REG_ESP];
        xpc = (u1 *) _mc->gregs[REG_EIP];
-       ra  = xpc;                          /* return address is equal to xpc     */
+       ra  = xpc;                              /* return address is equal to XPC */
 
-       _mc->gregs[REG_EAX] =
-               (ptrint) stacktrace_hardware_nullpointerexception(NULL, sp, ra, xpc);
+       /* get exception-throwing instruction */
+
+       opc = M_ALD_MEM_GET_OPC(xpc);
+       mod = M_ALD_MEM_GET_MOD(xpc);
+       rm  = M_ALD_MEM_GET_RM(xpc);
+
+       /* for values see emit_mov_mem_reg and emit_mem */
+
+       if ((opc == 0x8b) && (mod == 0) && (rm == 5)) {
+               /* this was a hardware-exception */
+
+               d    = M_ALD_MEM_GET_REG(xpc);
+               disp = M_ALD_MEM_GET_DISP(xpc);
+
+               /* we use the exception type as load displacement */
+
+               type = disp;
+
+               /* ATTENTION: The _mc->gregs layout is completely crazy!  The
+                  registers are reversed starting with number 4 for REG_EDI
+                  (see /usr/include/sys/ucontext.h).  We have to convert that
+                  here. */
+
+               val = _mc->gregs[REG_EAX - d];
+       }
+       else {
+               /* this was a normal NPE */
+
+               type = EXCEPTION_HARDWARE_NULLPOINTER;
+       }
+
+       /* generate appropriate exception */
+
+       e = exceptions_new_hardware_exception(pv, sp, ra, xpc, type, val);
+
+       /* set registers */
 
+       _mc->gregs[REG_EAX] = (ptrint) e;
        _mc->gregs[REG_ECX] = (ptrint) xpc;                      /* REG_ITMP2_XPC */
        _mc->gregs[REG_EIP] = (ptrint) asm_handle_exception;
 }
index 91aaf41286916d5334208f1e1d68afba6151e475..06f036cd33043e63b952a6191778db3d8a9c5c3c 100644 (file)
@@ -1,6 +1,6 @@
 /* src/vm/jit/i386/md.c - machine dependent i386 functions
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
    J. Wenninger, Institut f. Computersprachen - TU Wien
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Christian Thalinger
-            Edwin Steiner
-
-   $Id: md.c 7255 2007-01-29 21:39:38Z twisti $
+   $Id: md.c 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
index 297a9902b847d94398b603d63e27bf696e542a08..db1c9a8315d91de91c82111d13c24ba480dabfc6 100644 (file)
@@ -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:
+
+   <patched call position>
+   8b 91 00 00 00 00          mov    0x00000000(%ecx),%edx
+   81 ea 00 00 00 00          sub    $0x00000000,%edx
+   85 d2                      test   %edx,%edx
+   0f 8e 13 00 00 00          jle    0x00000000
+   8b 91 00 00 00 00          mov    0x00000000(%ecx),%edx
+
+*******************************************************************************/
+
+bool patcher_instanceof_interface(u1 *sp)
+{
+       u1                *ra;
+       u8                 mcode;
+       constant_classref *cr;
+       classinfo         *c;
+
+       /* get stuff from the stack */
+
+       ra    = (u1 *)                *((ptrint *) (sp + 6 * 4));
+       mcode =                       *((u8 *)     (sp + 2 * 4));
+       cr    = (constant_classref *) *((ptrint *) (sp + 1 * 4));
+
+       /* get the fieldinfo */
+
+       if (!(c = resolve_classref_eager(cr)))
+               return false;
+
+       /* patch back original code */
+
+       *((u4 *) (ra + 0)) = (u4) mcode;
+       *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
+
+       /* if we show disassembly, we have to skip the nop's */
+
+       if (opt_shownops)
                ra = ra + 5;
 
        /* patch super class index */
@@ -778,7 +832,7 @@ bool patcher_checkcast_class(u1 *sp)
 
        /* if we show disassembly, we have to skip the nop's */
 
-       if (opt_showdisassemble)
+       if (opt_shownops)
                ra = ra + 5;
 
        /* patch super class' vftbl */
@@ -827,7 +881,7 @@ bool patcher_instanceof_class(u1 *sp)
 
        /* if we show disassembly, we have to skip the nop's */
 
-       if (opt_showdisassemble)
+       if (opt_shownops)
                ra = ra + 5;
 
        /* patch super class' vftbl */
@@ -948,7 +1002,7 @@ bool patcher_resolve_native(u1 *sp)
 
        /* if we show disassembly, we have to skip the nop's */
 
-       if (opt_showdisassemble)
+       if (opt_shownops)
                ra = ra + 5;
 
        /* patch native function pointer */
index 647208c91611fd32417a1842350a44820ae3747e..6c97bc6f36a3f0caa26c97a720a5466bee6bcc1a 100644 (file)
@@ -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;
index 37d9c3bfa6943d824edaa39ff608108cdd42558a..fe5d3949c51a2d7922bc564c37f6e5bb57b3cb25 100644 (file)
@@ -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);
index ff2bce107b9ba3de2ae27b8c001fc4d810c32130..c761839cfe0bcef4464c19844b2ebd5cf7f4fb73 100644 (file)
@@ -1,4 +1,4 @@
-DIST_SUBDIRS = uclinux
+DIST_SUBDIRS = linux
 
 SUBDIRS = $(OS_DIR)
 
index 161169db740c6ebde22f6c295ed3d02115e7306f..583c008dacf5c0e2ae5d9759c06969aa252096d8 100644 (file)
@@ -59,7 +59,7 @@
 #define SUPPORT_LONG_FCVT                0
 
 #define SUPPORT_CONST_LOGICAL            0  /* AND, OR, XOR with immediates   */
-#define SUPPORT_CONST_MUL                0  /* mutiply with immediate         */
+#define SUPPORT_CONST_MUL                1  /* mutiply with immediate         */
 
 #define SUPPORT_CONST_STORE              0  /* do we support const stores     */
 #define SUPPORT_CONST_STORE_ZERO_ONLY    0  /* on some risc machines we can   */
 #endif
 
 
+#define HAS_ADDRESS_REGISTER_FILE        1
+
+#define HAS_4BYTE_STACKSLOT            1
+
+/* coldfire has tst instruction */
+#define SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER       1
+#define SUPPORT_BRANCH_CONDITIONAL_UNSIGNED_CONDITIONS     1
+#define SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER     0
+#define SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS    0
+
+#define TRACE_ARGS_NUM                 8
+
+#warning There is no REG_ZERO
+#define REG_ZERO 666
+
 #define SPECIALMEMUSE
 /* #define HAS_4BYTE_STACKSLOT */
 /* #define SUPPORT_COMBINE_INTEGER_REGISTERS */
index 957160be9d7186bfbb8bf50056b6dfc3a4ea863d..d9152d0e13944c04a8031b3a349c87e0b0e323b1 100644 (file)
+/*     src/vm/jit/m68k/asmpart.S
+ *     for cacao 
+ *     Roland Lezuo
+ */
+
+#include "config.h"
+
+#include "vm/jit/m68k/offsets.h"
+
+.data
+call_jit_dummy:
+       .long 0xdeadbeef
+
+.text
+
 .globl asm_vm_call_method
 .globl asm_vm_call_method_int
 .globl asm_vm_call_method_long
 .globl asm_vm_call_method_float
 .globl asm_vm_call_method_double
+.globl asm_vm_call_method_end
 .globl asm_vm_call_method_exception_handler
 
 .globl asm_call_jit_compiler
+
+.globl asm_patcher_wrapper
+
 .globl asm_getclassvalues_atomic
 .globl asm_abstractmethoderror
 .globl asm_criticalsections
 
+.globl asm_handle_exception
+
+/*
+ *     This functions implement the C prototyped funtion
+ *     java_objectheader *asm_vm_call_method(methodinfo *m, s4 vmargscount,vm_arg *vmargs);
+ *     the _int, _long, _float, _double are used for different return types
+ *
+ *     The function may still be uncompiled, so the jit compiler gets invoked.
+ *
+ *
+ */
 
+       /* this is the method header see src/vm/jit/methodheader.h */
+       .align  4
+       .long   0                           /* catch type all                     */
+       .long   0                           /* handler pc                         */
+       .long   0                           /* end pc                             */
+       .long   0                           /* start pc                           */
+       .long   1                           /* extable size                       */
+       .long   0                           /* line number table start            */
+       .long   0                           /* line number table size             */
+       .long   0                           /* fltsave                            */
+       .long   0                           /* intsave                            */
+       .long   0                           /* isleaf                             */
+       .long   0                           /* IsSync                             */
+       .long   0                           /* frame size                         */
+       .long   0                           /* codeinfo pointer                   */
 asm_vm_call_method:
 asm_vm_call_method_int:
 asm_vm_call_method_long:
 asm_vm_call_method_float:
 asm_vm_call_method_double:
+       addal   #(-11*4),%sp                                            /* create stackframe to save registers */
+       moveml  %d2/%d3/%d4/%d5/%d6/%d7/%a2/%a3/%a4/%a5/%fp,%sp@        /* save registers */
+
+       /* fetch arguments from vmargs data structure */
+       movel   %sp@(11*4+1*4),%a2                              /* methodinfo argument in atmp1 */
+       movel   %sp@(11*4+3*4),%a3                              /* args block */
+       movel   %sp@(11*4+2*4),%d2                              /* arg count */
+
+       moveal  %sp, %a5                                        /* memorize stack */
+       tst     %d2                                             /* do we have arguments ? */
+       beq     L_asm_vm_call_method_copy_done
+       subql   #1,%d2                                          /* simplifies offset calulation */
+
+       movel   #(sizevmarg), %d0
+       mulsl   %d2, %d0                                        
+       moveal  %a3, %a0
+       addal   %d0, %a0                                        /* %a0 points to last vmarg block */
 
+       addql   #1, %d2
+L_asm_vm_call_copy_arg:
+       subql   #1, %d2                                         /* why wasn't that here */
+
+       movel   %a0@(offvmargdata+4), %d0
+       movel   %d0,%sp@-                                       /* push argument onto stack */
+
+       movel   %a0@(offvmargtype), %d0                         /* %d0 contains type of arg */  
+       btstl   #0, %d0                                         /* test if 2 word type */
+       beq     L_asm_vm_call_copy_1_word_type
+       movel   %a0@(offvmargdata), %d0                         /* push second word onto stack */
+       movel   %d0,%sp@-
+L_asm_vm_call_copy_1_word_type:
+
+       subl    #(sizevmarg),%a0
+       tst     %d2                                             /* arguments left ? */
+       bne     L_asm_vm_call_copy_arg
+
+L_asm_vm_call_method_copy_done:
+
+       leal    asm_call_jit_compiler,%a4                       /* we need to fake a invocation as it would happen from jit code */
+       movel   %a4, call_jit_dummy                             /* we need a writeable memory location */
+       moveal  call_jit_dummy, %a4                             /* XXX do we have a race condition here ? */
+       jsr     %a4@
+
+L_asm_vm_call_method_return:
+       movel   %a5, %sp                                                /* pop arguments off stack */
+       moveml  %sp@, %d2/%d3/%d4/%d5/%d6/%d7/%a2/%a3/%a4/%a5/%fp       /* restore registers */
+       addal   #(11*4),%sp                                             /* restore stack */
+       rts                                                             /* return to c code */
+       jsr 0   /* never come back ? */
+
+/* asm_vm_call_method_exception_handler        
+ *
+ * calls void *builtin_throw_exception(java_objectheader *xptr) when no other handler is appropiate
+ * this functions gets called indirectly from asm_handle_exception, which back then moved xptr to %a3
+ * clear software design is in the eye of the beholder.
+ */
 asm_vm_call_method_exception_handler:
+       movel   %a3, %sp@-                      /* push xptr argument */
+       jsr     builtin_throw_exception
+       lea     %sp@(4), %sp                    /* pop arg off stack */
+       bra     L_asm_vm_call_method_return
+
 
+asm_vm_call_method_end:                                                /* symbol needed to insert method into avl tree */
+       rts
+/*
+ *     Invokes compiler for untranslated java methods.
+ *     C prototype: void asm_call_jit_compiler(void);
+ *     BUT: this does not match reality, arguments _ARE_ passed via createcompilerstub and asm_vm_call_method...
+ *     arguments passed via %a2(methodinfo) == REG_ATMP1
+ *                           %a3(mptr)       == REG_ATMP2
+ */
 asm_call_jit_compiler:
+       addal   #(-4*4),%sp                                             /* create stackframe to save registers */
+       moveml  %a0/%a1/%d0/%d1,%sp@                                    /* save volatile registers */
+
+       movel   %sp@(4*4),%sp@-                                         /* push arguments onto stack (ra)*/
+       pea     %sp@(4*4+4)                                             /* the old stack pointer */
+       movel   %a3,%sp@-                                               /* mptr */
+       movel   %a2,%sp@-                                               /* methodinfo */
+
+       /* C prototype: u1 *jit_asm_compile(methodinfo *m, u1 *mptr, u1 *sp, u1 *ra); */
+       jsr     jit_asm_compile                                         /* invoke compiler */
+       lea     %sp@(4*4),%sp                                           /* pop arguments off stack */
+       moveal  %d0, %a2                                                /* to tmp register */
 
+       moveml %sp@,%a0/%a1/%d0/%d1                                     /* restore volatile registers */
+       addal   #(4*4),%sp                                              /* remove stackframe */
+
+       tstl    %a2                                                     /* check for exception */
+       beq     L_asm_call_jit_compiler_exception
+
+       jmp     %a2@                                                    /* invoke java method */
+       jsr     0                                                       /* we should not ever return here */
+
+L_asm_call_jit_compiler_exception:
+       jsr     0                                                       /* TODO */
+
+       moveml  %fp@(-4*4), %a0/%a1/%d0/%d1                             /* restore registers */
+       unlk    %fp                                                     /* FIXME: this is wrong */
+       rts
+
+/* asm_patcher_wrapper ********************************************************
+       
+  prepares arguments on stack
+  calls patcher_wrapper signature: java_objectheader *patcher_wrapper(u1 *sp, u1 *pv, u1 *ra);
+
+  Stack layout:
+     24   return address
+     20   REG_ITMP3
+     16   pointer to virtual java_objectheader
+     12   last byte of machine code (xmcode)
+      8   machine code (which is patched back later)
+      4   unresolved field reference
+      0   patcher function pointer to call
+*******************************************************************************/
+asm_patcher_wrapper:
+
+  movel %sp, %d0
+  /* save scratch registers */
+  movel %a0, %sp@-
+  movel %a1, %sp@-
+  movel %d0, %sp@-
+  movel %d1, %sp@-
+#if !defined(ENABLE_SOFTFLOAT)
+  movel %f0, %sp@-
+  movel %f1, %sp@-
+#endif
+
+  clrl %sp@-                           /* pass ra */
+  clrl %sp@-                           /* pass pv, if null use findmethod */
+  movel %d0, %sp@-                     /* pass sp of patcher stub */
+  jsr  patcher_wrapper                 /* return value in %d0 */
+
+  lea  %sp@(3*4), %sp                  /* pop arguments off stack */
+
+  tst  %d0                             /* test if exception occured */
+  bne  L_asm_patcher_wrapper_exception
+
+#if !defined(ENABLE_SOFTFLOAT)
+  movel %sp@+, %f0
+  movel %sp@+, %f1
+#endif
+  movel %sp@+, %d1
+  movel %sp@+, %d0
+  movel %sp@+, %a1
+  movel %sp@+, %a0
+
+  lea   %sp@(6*4), %sp                 /* restore stack and remove patcher stub*/
+  rts                                  /* back to jit code */
+
+L_asm_patcher_wrapper_exception:
+  /* WARNING: the stack is still disturbed, look at asm_patcher_wrapper for details */
+  jsr 0                                        /* TODO */
+
+/********************************************************************************
+       Reads a few values atomically. 
+       C signature:
+       void asm_getclassvalues_atomic(vftbl_t *super, vftbl_t *sub, castinfo *out);
+
+       super ... sp@(4)
+       sub   ... sp@(8)
+       out   ... sp@(12)
+********************************************************************************/
 asm_getclassvalues_atomic:
+_crit_restart:
+_crit_begin:
+       moveal  %sp@(4), %a0
+       movel   %a0@(offbaseval), %d0
+       movel   %a0@(offdiffval), %d1
+       
+       moveal  %sp@(8), %a0
+       moveal  %a0@(offbaseval), %a0
+_crit_end:
+       moveal  %sp@(12), %a1
+       movel   %d0, %a1@(offcast_super_baseval)
+       movel   %d1, %a1@(offcast_super_diffval)
+       movel   %a0, %a1@(offcast_sub_baseval)
+
+       rts
+.data
+asm_criticalsections:
+#if defined(ENABLE_THREADS)
+       .long _crit_begin
+       .long _crit_end
+       .long _crit_restart
+#endif
+       .long 0
+.text
 
 asm_abstractmethoderror:
 
-asm_criticalsections:
+/* asm_handle_exception ********************************************************
+*                                                                              *
+*   This function handles an exception. It does not use the usual calling      *
+*   conventions. The exception pointer is passed in REG_ATMP1 and the          *
+*   pc from the exception raising position is passed in REG_ATMP2. It searches *
+*   the local exception table for a handler. If no one is found, it unwinds    *
+*   stacks and continues searching the callers.                                *
+*                                                                              *
+*   void asm_handle_exception (void);
+*   exception object pointer...%a2   exception raising address...%a3           *
+*                                                                              *
+*******************************************************************************/
+asm_handle_exception:
+asm_handle_nat_exception:
+L_asm_handle_exception_stack_loop:
+       
+       /* we need the dseg, figure it out */
+       movel   %a3, %sp@-                              /* push ra argument */
+       jsr     md_codegen_get_pv_from_pc               /* pv in %d0 now */
+       movel   %d0, %d2                                /* move to safe register */
+       lea     %sp@(4), %sp                            /* pop args off stack */
+
+       /* now call the following c function */
+       /* u1 *exceptions_handle_exception(java_objectheader *xptr, u1 *xpc, u1 *pv, u1 *sp) */
+       movel   %sp,%sp@-
+       movel   %d2,%sp@-
+       movel   %a3,%sp@-
+       movel   %a2,%sp@-
+       jsr     exceptions_handle_exception             /* %d0 is address of handler or 0 when not catched */
+       lea     %sp@(4*4), %sp                          /* pop args off stack */
+       tstl    %d0
+       beq     L_asm_handle_exception_not_catched
+
+       /* %d0 contains address of exception handler */
+       moveal  %d0, %a0
+       jsr     %a0@
+
+L_asm_handle_exception_not_catched:
+       jsr 0
+illegal
+.long 0x23234242
index 3a93412bf2426ce2c1358c006168bd55dec20aa1..844ed7825bd377764bc1bcabd2061bd30a9325cc 100644 (file)
-void codegen(void) {}
-void createnativestub(void) {}
-void createcompilerstub(void) {}
+/* src/vm/jit/m68k/codegen.c
+
+   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
+   C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
+   E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
+   J. Wenninger, Institut f. Computersprachen - TU Wien
+
+   This file is part of CACAO.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
+
+   $Id: codegen.c 7564 2007-03-23 23:36:17Z twisti $
+*/
+
+
+#include "config.h"
+
+#include <assert.h>
+
+#include "md-abi.h"
+
+#include "vm/types.h"
+#include "vm/jit/m68k/codegen.h"
+#include "vm/jit/m68k/emit.h"
+
+#include "mm/memory.h"
+#include "native/jni.h"
+#include "native/native.h"
+
+#if defined(ENABLE_THREADS)
+# include "threads/native/lock.h"
+#endif
+
+#include "vm/builtin.h"
+#include "vm/exceptions.h"
+#include "vm/global.h"
+#include "vm/stringlocal.h"
+#include "vm/vm.h"
+
+#include "vm/jit/asmpart.h"
+#include "vm/jit/codegen-common.h"
+#include "vm/jit/dseg.h"
+#include "vm/jit/emit-common.h"
+#include "vm/jit/jit.h"
+#include "vm/jit/parse.h"
+#include "vm/jit/patcher.h"
+#include "vm/jit/reg.h"
+#include "vm/jit/replace.h"
+#include "vm/jit/stacktrace.h"
+#include "vm/jit/md.h"
+
+#include "vmcore/loader.h"
+#include "vmcore/options.h"
+#include "vmcore/utf8.h"
+
+
+bool codegen_emit(jitdata *jd) 
+{      
+       methodinfo         *m;
+       codeinfo           *code;
+       codegendata        *cd;
+       registerdata       *rd;
+       s4                  len, s1, s2, s3, d, disp;
+       ptrint              a;
+       varinfo            *var;
+       basicblock         *bptr;
+       instruction        *iptr;
+       exception_entry    *ex;
+       u2                  currentline;
+       methodinfo         *lm;             /* local methodinfo for ICMD_INVOKE*  */
+       unresolved_method  *um;
+       builtintable_entry *bte;
+       methoddesc         *md;
+       s4                  fieldtype;
+       s4                  varindex;
+       unresolved_field   *uf;
+       fieldinfo          *fi;
+
+       /* get required compiler data */
+
+       m    = jd->m;
+       code = jd->code;
+       cd   = jd->cd;
+       rd   = jd->rd;
+
+       /* prevent compiler warnings */
+
+       d = 0;
+       lm = NULL;
+       bte = NULL;
+
+       {
+               s4 i, p, t, l;
+               /* save calle saved registers */
+               s4 savedregs_num = 0;
+
+               savedregs_num += (INT_SAV_CNT - rd->savintreguse);
+               savedregs_num += (ADR_SAV_CNT - rd->savadrreguse);
+               savedregs_num += (FLT_SAV_CNT - rd->savfltreguse) * 2;
+
+               cd->stackframesize = rd->memuse + savedregs_num;
+#if defined(ENABLE_THREADS)
+               assert(0);
+#endif
+       
+               /* create method header */
+               (void) dseg_add_unique_address(cd, code);              /* CodeinfoPointer */
+               (void) dseg_add_unique_s4(cd, cd->stackframesize * 4); /* FrameSize       */
+#if defined(ENABLE_THREADS)
+               if (checksync && (m->flags & ACC_SYNCHRONIZED))
+                       (void) dseg_add_unique_s4(cd, (rd->memuse + 1) * 4);/* IsSync         */
+               else
+#endif
+                       (void) dseg_add_unique_s4(cd, 0);                  /* IsSync          */
+               (void) dseg_add_unique_s4(cd, jd->isleafmethod);       /* IsLeaf          */
+               (void) dseg_add_unique_s4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
+               (void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
+
+               dseg_addlinenumbertablesize(cd);
+
+               (void) dseg_add_unique_s4(cd, jd->exceptiontablelength); /* ExTableSize   */
+
+               /* create exception table */
+               for (ex = jd->exceptiontable; ex != NULL; ex = ex->down) {
+                       dseg_add_target(cd, ex->start);
+                       dseg_add_target(cd, ex->end);
+                       dseg_add_target(cd, ex->handler);
+                       (void) dseg_add_unique_address(cd, ex->catchtype.any);
+               }
+
+#if defined(ENABLE_PROFILING)
+               assert(0);
+#endif
+
+#if !defined(NDEBUG)
+               emit_verbosecall_enter(jd);
+#endif
+               /* create stack frame */
+               M_AADD_IMM(-(cd->stackframesize*4), REG_SP);
+
+               /* save used callee saved registers */
+               p = cd->stackframesize;
+               for (i=INT_SAV_CNT-1; i>=rd->savintreguse; --i) {
+                       p--; M_IST(rd->savintregs[i], REG_SP, p*4);
+               }
+               for (i=ADR_SAV_CNT-1; i>=rd->savadrreguse; --i) {
+                       p--; M_AST(rd->savadrregs[i], REG_SP, p*4);
+               }
+#if !defined(ENABLE_SOFTFLOAT)
+               for (i=FLT_SAV_CNT-1; i>=rd->savfltreguse; --i) {
+                       p-=2; M_FST(rd->savfltregs[i], REG_SP, p*4);    /* FIXME */
+               }       
+#else
+               assert(FLT_SAV_CNT == 0);
+               assert(rd->savfltreguse == 0);
+#endif
+               /* take arguments out of stack frame */
+               md = m->parseddesc;
+               for (p = 0, l = 0; p < md->paramcount; p++) {
+                       t = md->paramtypes[p].type;
+                       varindex = jd->local_map[l * 5 + t];
+       
+                       l++;
+                       if (IS_2_WORD_TYPE(t))    /* increment local counter for 2 word types */
+                               l++;
+
+                       if (varindex == UNUSED)
+                               continue;
+
+                       var = VAR(varindex);
+       
+                       s1 = md->params[p].regoff;
+                       assert(md->params[p].inmemory);                 /* all args are on stack */
+
+                       switch (t)      {
+#if defined(ENABLE_SOFTFLOAT)
+                       case TYPE_FLT:
+                       case TYPE_DBL:
+#endif
+                       case TYPE_LNG:
+                       case TYPE_INT:
+                               if (!IS_INMEMORY(var->flags)) {      /* stack arg -> register */
+                                       if (IS_2_WORD_TYPE(t))  {
+                                               M_LLD(var->vv.regoff, REG_SP, (cd->stackframesize + s1 + 1) * 4);
+                                       } else {
+                                               M_ILD(var->vv.regoff, REG_SP, (cd->stackframesize + s1 + 1) * 4);
+                                       }
+                               } else {                             /* stack arg -> spilled  */
+#if 1
+                                       M_ILD(REG_ITMP1, REG_SP, (cd->stackframesize + s1 + 1) * 4);
+                                       M_IST(REG_ITMP1, REG_SP, var->vv.regoff * 4);
+                                       if (IS_2_WORD_TYPE(t)) {
+                                               M_ILD(REG_ITMP1, REG_SP, (cd->stackframesize + s1 + 1) * 4 + 4);
+                                               M_IST(REG_ITMP1, REG_SP, var->vv.regoff * 4 + 4);
+                                       }
+#else
+                                       /* Reuse Memory Position on Caller Stack */
+                                       var->vv.regoff = cd->stackframesize + s1;
+#endif
+                               } 
+                               break;
+#if !defined(ENABLE_SOFTFLOAT)
+                       case TYPE_FLT:
+                       case TYPE_DBL:
+                               if (!IS_INMEMORY(var->flags)) {      /* stack-arg -> register */
+                                       if (IS_2_WORD_TYPE(t))  {
+                                               M_DLD(var->vv.regoff, REG_SP, (cd->stackframesize + s1 + 1) * 4);
+                                       } else {
+                                               M_FLD(var->vv.regoff, REG_SP, (cd->stackframesize + s1 + 1) * 4);
+                                       }
+                               } else {                             /* stack-arg -> spilled  */
+#if 1
+                                       if (IS_2_WORD_TYPE(t)) {
+                                               M_DLD(REG_FTMP1, REG_SP, (cd->stackframesize + s1 + 1) * 4);
+                                               M_DST(REG_FTMP1, REG_SP, var->vv.regoff * 4);
+                                       } else {
+                                               M_FLD(REG_FTMP1, REG_SP, (cd->stackframesize + s1 + 1) * 4);
+                                               M_FST(REG_FTMP1, REG_SP, var->vv.regoff * 4);
+                                       }
+#else
+                                       /* Reuse Memory Position on Caller Stack */
+                                       var->vv.regoff = cd->stackframesize + s1;
+#endif
+                               }
+                               break;
+#endif /* SOFTFLOAT */
+                       case TYPE_ADR:
+                               if (!IS_INMEMORY(var->flags)) {      /* stack-arg -> register */
+                                       M_ALD(var->vv.regoff, REG_SP, (cd->stackframesize + s1 + 1) * 4);
+                               } else {                             /* stack-arg -> spilled  */
+#if 1
+                                       M_ALD(REG_ATMP1, REG_SP, (cd->stackframesize + s1 + 1) * 4);
+                                       M_AST(REG_ATMP1, REG_SP, var->vv.regoff * 4);
+#else
+                               /* Reuse Memory Position on Caller Stack */
+                               var->vv.regoff = cd->stackframesize + s1;
+#endif
+                               }
+                               break;
+                       default: assert(0);
+                       }
+               } /* end for argument out of stack*/
+       }
+
+
+
+       /* create replacement points */
+       REPLACEMENT_POINTS_INIT(cd, jd);
+
+       /* foreach basic block */
+       for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
+       
+       bptr->mpc = (s4) (cd->mcodeptr - cd->mcodebase);
+
+       if (bptr->flags >= BBREACHED)   {
+       
+       /* branch resolving */
+       codegen_resolve_branchrefs(cd, bptr);
+
+       /* FIXME there are still some constrcuts to copy in here */
+
+       /* walk through all instructions */
+       len = bptr->icount;
+       currentline = 0;
+
+       for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
+               if (iptr->line != currentline) {
+                       dseg_addlinenumber(cd, iptr->line);
+                       currentline = iptr->line;
+               }
+
+               MCODECHECK(1024);                         /* 1kB should be enough */
+
+               switch (iptr->opc) {
+               case ICMD_NOP:        /* ...  ==> ...                                 */
+               case ICMD_POP:        /* ..., value  ==> ...                          */
+               case ICMD_POP2:       /* ..., value, value  ==> ...                   */
+                       break;
+
+               case ICMD_INLINE_START:
+
+                       REPLACEMENT_POINT_INLINE_START(cd, iptr);
+                       break;
+
+               case ICMD_INLINE_BODY:
+
+                       REPLACEMENT_POINT_INLINE_BODY(cd, iptr);
+                       dseg_addlinenumber_inline_start(cd, iptr);
+                       dseg_addlinenumber(cd, iptr->line);
+                       break;
+
+               case ICMD_INLINE_END:
+
+                       dseg_addlinenumber_inline_end(cd, iptr);
+                       dseg_addlinenumber(cd, iptr->line);
+                       break;
+
+               case ICMD_CHECKNULL:  /* ..., objectref  ==> ..., objectref           */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       assert(VAROP(iptr->s1)->type == TYPE_ADR);
+                       emit_nullpointer_check(cd, iptr, s1);
+                       break;
+
+
+               /* CONST **************************************************************/
+               case ICMD_ICONST:     /* ...  ==> ..., constant                       */
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+                       M_IMOV_IMM(iptr->sx.val.i, d);
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+               case ICMD_LCONST:     /* ...  ==> ..., constant                       */
+
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
+                       LCONST(iptr->sx.val.l, d);
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+               case ICMD_FCONST:     /* ...  ==> ..., constant                       */
+
+#if defined(ENABLE_SOFTFLOAT)
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+                       M_IMOV_IMM(iptr->sx.val.i, d);
+                       emit_store_dst(jd, iptr, d);
+#else
+                       d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
+                       FCONST(iptr->sx.val.f, d);
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       break;
+
+               case ICMD_DCONST:     /* ...  ==> ..., constant                       */
+
+#if defined(ENABLE_SOFTFLOAT)
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
+                       LCONST(iptr->sx.val.l, d);
+                       emit_store_dst(jd, iptr, d);
+#else
+                       d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
+                       DCONST(iptr->sx.val.d, d);
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       break;
+
+
+
+               /* integer operations ************************************************/
+               case ICMD_INEG:       /* ..., value  ==> ..., - value                 */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1); 
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+                       M_INTMOVE(s1, REG_ITMP1);
+                       M_INEG(REG_ITMP1);
+                       M_INTMOVE(REG_ITMP1, d);
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+#if 0
+               case ICMD_LNEG:       /* ..., value  ==> ..., - value                 */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
+                       M_SUBFIC(GET_LOW_REG(s1), 0, GET_LOW_REG(d));
+                       M_SUBFZE(GET_HIGH_REG(s1), GET_HIGH_REG(d));
+                       emit_store_dst(jd, iptr, d);
+                       break;
+#endif
+               case ICMD_I2L:        /* ..., value  ==> ..., value                   */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP2);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
+                       M_INTMOVE(s1, GET_LOW_REG(d));                          /* sets negativ bit */
+                       M_BPL(4);
+                       M_ISET(GET_HIGH_REG(d));
+                       M_TPFW;
+                       M_ICLR(GET_HIGH_REG(d));
+
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+               case ICMD_L2I:        /* ..., value  ==> ..., value                   */
+
+                       s1 = emit_load_s1_low(jd, iptr, REG_ITMP2);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+                       M_INTMOVE(s1, d);
+                       emit_store_dst(jd, iptr, d);
+                       break;
+               case ICMD_INT2BYTE:   /* ..., value  ==> ..., value                   */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+                       M_BSEXT(s1, d);
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+               case ICMD_INT2CHAR:   /* ..., value  ==> ..., value                   */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+                       M_CZEXT(s1, d);
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+               case ICMD_INT2SHORT:  /* ..., value  ==> ..., value                   */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+                       M_SSEXT(s1, d);
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+
+
+               case ICMD_IADD:       /* ..., val1, val2  ==> ..., val1 + val2        */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+                       M_INTMOVE(s2, REG_ITMP2);
+                       M_IADD(s1, REG_ITMP2);
+                       M_INTMOVE(REG_ITMP2, d);
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+                                     /* s1.localindex = variable, sx.val.i = constant*/
+
+               case ICMD_IINC:
+               case ICMD_IADDCONST:
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+                       M_INTMOVE(s1, REG_ITMP1);
+                       M_IADD_IMM(iptr->sx.val.i, REG_ITMP1);
+                       M_INTMOVE(REG_ITMP1, d);
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+               case ICMD_ISUB:       /* ..., val1, val2  ==> ..., val1 - val2        */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+                       M_INTMOVE(s1, REG_ITMP1);
+                       M_ISUB(s2, REG_ITMP1);
+                       M_INTMOVE(REG_ITMP1, d);
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+               case ICMD_ISUBCONST:  /* ..., value  ==> ..., value + constant        */
+                                     /* sx.val.i = constant                          */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+                       M_INTMOVE(s1, REG_ITMP1);
+                       M_IADD_IMM(-iptr->sx.val.i, REG_ITMP1);
+                       M_INTMOVE(REG_ITMP1, d);
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+               case ICMD_IDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+                       emit_arithmetic_check(cd, iptr, s2);
+
+                       M_INTMOVE(s1, REG_ITMP1);
+                       M_IDIV(s2, REG_ITMP1);
+                       M_INTMOVE(REG_ITMP1, d);
+
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+               case ICMD_IREM:       /* ..., val1, val2  ==> ..., val1 % val2        */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
+                       emit_arithmetic_check(cd, iptr, s2);
+
+                       M_IREM(s2, s1, REG_ITMP3);
+                       M_INTMOVE(REG_ITMP3, d);
+
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+               case ICMD_LDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
+               case ICMD_LREM:       /* ..., val1, val2  ==> ..., val1 % val2        */
+
+                       bte = iptr->sx.s23.s3.bte;
+                       md  = bte->md;
+
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP12_PACKED);
+                       M_INTMOVE(GET_LOW_REG(s2), REG_ITMP3);
+                       M_IOR(GET_HIGH_REG(s2), REG_ITMP3);
+                       /* XXX could be optimized */
+                       emit_arithmetic_check(cd, iptr, REG_ITMP3);
+
+                       M_LST(s2, REG_SP, 2 * 4);
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED);
+                       M_LST(s1, REG_SP, 0 * 4);
+
+                       M_JSR_IMM(bte->fp);
+
+                       d = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
+                       M_LNGMOVE(REG_RESULT_PACKED, d);
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+               case ICMD_IMUL:       /* ..., val1, val2  ==> ..., val1 * val2        */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+                       M_INTMOVE(s2, REG_ITMP2);
+                       M_IMUL(s1, REG_ITMP2);
+                       M_INTMOVE(REG_ITMP2, d);
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+               case ICMD_IMULCONST:  /* ..., value  ==> ..., value * constant        */
+                                     /* sx.val.i = constant                          */
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+                       M_IMOV_IMM(iptr->sx.val.i, REG_ITMP2);
+                       M_IMUL(s1, REG_ITMP2);
+                       M_INTMOVE(REG_ITMP2, d);
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+               case ICMD_ISHL:       /* ..., val1, val2  ==> ..., val1 << val2       */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+                       M_INTMOVE(s1, REG_ITMP1);
+                       M_INTMOVE(s2, REG_ITMP2);
+                       M_IAND_IMM(0x1f, REG_ITMP2);
+                       M_ISSL(REG_ITMP2, REG_ITMP1);
+                       M_INTMOVE(REG_ITMP1, d);
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+               case ICMD_ISHLCONST:  /* ..., value  ==> ..., value << constant       */
+                                     /* sx.val.i = constant                          */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+                       M_INTMOVE(s1, REG_ITMP1)
+                       M_ISSL_IMM(iptr->sx.val.i & 0x1f, REG_ITMP1);
+                       M_INTMOVE(REG_ITMP1, d);
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+               case ICMD_ISHR:       /* ..., val1, val2  ==> ..., val1 >> val2       */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+                       M_INTMOVE(s1, REG_ITMP1);
+                       M_INTMOVE(s2, REG_ITMP2);
+                       M_IAND_IMM(0x1f, REG_ITMP2);
+                       M_ISSR(REG_ITMP2, REG_ITMP1);
+                       M_INTMOVE(REG_ITMP1, d);
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+               case ICMD_ISHRCONST:  /* ..., value  ==> ..., value >> constant       */
+                                     /* sx.val.i = constant                          */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+                       M_INTMOVE(s1, REG_ITMP1)
+                       M_ISSR_IMM(iptr->sx.val.i & 0x1f, REG_ITMP1);
+                       M_INTMOVE(REG_ITMP1, d);
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+               case ICMD_IUSHR:      /* ..., val1, val2  ==> ..., val1 >>> val2      */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+                       M_INTMOVE(s1, REG_ITMP1);
+                       M_INTMOVE(s2, REG_ITMP2);
+                       M_IAND_IMM(0x1f, REG_ITMP2);
+                       M_IUSR(REG_ITMP2, REG_ITMP1);
+                       M_INTMOVE(REG_ITMP1, d);
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+               case ICMD_IUSHRCONST: /* ..., value  ==> ..., value >>> constant      */
+                                     /* sx.val.i = constant                          */
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+                       M_INTMOVE(s1, REG_ITMP1)
+                       M_IUSR_IMM(iptr->sx.val.i & 0x1f, REG_ITMP1);
+                       M_INTMOVE(REG_ITMP1, d);
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+               case ICMD_IAND:       /* ..., val1, val2  ==> ..., val1 & val2        */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+                       M_INTMOVE(s2, REG_ITMP2);
+                       M_IAND(s1, REG_ITMP2);
+                       M_INTMOVE(REG_ITMP2, d);
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+               case ICMD_IANDCONST:  /* ..., value  ==> ..., value & constant        */
+                                     /* sx.val.i = constant                          */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+                       M_INTMOVE(s1, REG_ITMP1);
+                       M_IAND_IMM(iptr->sx.val.i, REG_ITMP1);
+                       M_INTMOVE(REG_ITMP1, d);
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+
+
+
+               /* load/store/copy/move operations ************************************/
+
+               case ICMD_ILOAD:      /* ...  ==> ..., content of local variable      */
+               case ICMD_ALOAD:      /* s1 = local variable                          */
+               case ICMD_LLOAD:
+               case ICMD_FLOAD:  
+               case ICMD_DLOAD:  
+               case ICMD_ISTORE:     /* ..., value  ==> ...                          */
+               case ICMD_LSTORE:
+               case ICMD_FSTORE:
+               case ICMD_DSTORE: 
+               case ICMD_COPY:
+               case ICMD_MOVE:
+                       emit_copy(jd, iptr, VAROP(iptr->s1), VAROP(iptr->dst));
+                       break;
+
+               case ICMD_ASTORE:
+                       if (!(iptr->flags.bits & INS_FLAG_RETADDR))
+                               emit_copy(jd, iptr, VAROP(iptr->s1), VAROP(iptr->dst));
+                       break;
+
+
+               case ICMD_ACONST:     /* ...  ==> ..., constant                       */
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                               constant_classref *cr = iptr->sx.val.c.ref;;
+                               codegen_addpatchref(cd, PATCHER_resolve_classref_to_classinfo, cr, 0);
+                               M_AMOV_IMM(0, d);
+                       } else {
+                               M_AMOV_IMM(iptr->sx.val.anyptr, d);
+                       }
+                       emit_store_dst(jd, iptr, d);
+                       break;
+               /* BRANCH *************************************************************/
+
+               case ICMD_ATHROW:       /* ..., objectref ==> ... (, objectref)       */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ATMP1);
+                       M_ADRMOVE(s1, REG_ATMP1_XPTR);
+
+#ifdef ENABLE_VERIFIER
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                               unresolved_class *uc = iptr->sx.s23.s2.uc;
+
+                               codegen_addpatchref(cd, PATCHER_resolve_class, uc, 0);
+                       }
+#endif /* ENABLE_VERIFIER */
+                       M_JSR_PCREL(2);                         /* get current PC */
+                       M_APOP(REG_ATMP2);              
+
+                       M_AMOV_IMM(asm_handle_exception, REG_ATMP3);
+                       M_JMP(REG_ATMP3);
+                       ALIGNCODENOP;
+                       break;
+
+               case ICMD_GOTO:         /* ... ==> ...                                */
+               case ICMD_RET:          /* ... ==> ...                                */
+
+                       emit_br(cd, iptr->dst.block);
+                       ALIGNCODENOP;
+                       break;
+
+               case ICMD_JSR:          /* ... ==> ...                                */
+
+                       emit_br(cd, iptr->sx.s23.s3.jsrtarget.block);
+                       ALIGNCODENOP;
+                       break;
+
+
+
+               case ICMD_IFNULL:       /* ..., value ==> ...                         */
+               case ICMD_IFNONNULL:
+                       assert(IS_ADR_TYPE(VAROP(iptr->s1)->type));
+                       s1 = emit_load_s1(jd, iptr, REG_ATMP1);
+                       M_ATST(s1);
+                       emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IFNULL, BRANCH_OPT_NONE);
+                       break;
+
+               case ICMD_IFLT:
+               case ICMD_IFLE:
+               case ICMD_IFNE:
+               case ICMD_IFGT:
+               case ICMD_IFGE:
+               case ICMD_IFEQ:         /* ..., value ==> ...                         */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       assert (VAROP(iptr->s1)->type == TYPE_INT);
+                       M_ICMP_IMM(iptr->sx.val.i, s1); 
+                       emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IFEQ, BRANCH_OPT_NONE);
+                       break;
+
+               case ICMD_IF_ICMPEQ:    /* ..., value, value ==> ...                  */
+               case ICMD_IF_ICMPNE:
+               case ICMD_IF_ICMPLT:
+               case ICMD_IF_ICMPGT:
+               case ICMD_IF_ICMPLE:
+               case ICMD_IF_ICMPGE:
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+                       M_ICMP(s2, s1);
+                       emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IF_ICMPEQ, BRANCH_OPT_NONE);
+                       break;
+
+               case ICMD_IF_ACMPEQ:    /* op1 = target JavaVM pc                     */
+               case ICMD_IF_ACMPNE:
+
+                       s1 = emit_load_s1(jd, iptr, REG_ATMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ATMP2);
+                       M_ACMP(s1, s2);
+                       emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IF_ACMPEQ, BRANCH_OPT_NONE);
+                       break;
+
+
+               /* MEMORY *************************************************************/
+               case ICMD_GETSTATIC:
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr))    {
+                               assert(0);
+                       } else  {
+                               fieldinfo *fi = iptr->sx.s23.s3.fmiref->p.field;
+
+                               fieldtype = fi->type;
+                               if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
+                                       codegen_addpatchref(cd, PATCHER_initialize_class, fi->class, disp);
+                               }
+
+                               disp = (ptrint) &(fi->value);
+                       }
+                       M_AMOV_IMM(disp, REG_ATMP1);
+                       switch (fieldtype) {
+#if defined(ENABLE_SOFTFLOAT)
+                       case TYPE_FLT:
+#endif
+                       case TYPE_INT:
+                               d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+                               M_ILD(d, REG_ATMP1, 0);
+                               break;
+                       case TYPE_ADR:
+                               d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+                               M_ALD(d, REG_ATMP1, 0);
+                               break;
+#if defined(ENABLE_SOFTFLOAT)
+                       case TYPE_DBL:
+#endif
+                       case TYPE_LNG:
+                               d = codegen_reg_of_dst(jd, iptr, REG_ITMP23_PACKED);
+                               M_LLD(d, REG_ATMP1, 0);
+                               break;
+#if !defined(ENABLE_SOFTFLOAT)
+                       case TYPE_FLT:
+                               d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
+                               M_FLD(d, REG_ATMP1, 0);
+                               break;
+                       case TYPE_DBL:                          
+                               d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
+                               M_DLD(d, REG_ATMP1, 0);
+                               break;
+#endif
+                       }
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+               case ICMD_PUTSTATIC:  /* ..., value  ==> ...                          */
+
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                               uf        = iptr->sx.s23.s3.uf;
+                               fieldtype = uf->fieldref->parseddesc.fd->type;
+
+                               codegen_addpatchref(cd, PATCHER_get_putstatic, uf, 0);
+                       } else {
+                               fi        = iptr->sx.s23.s3.fmiref->p.field;
+                               fieldtype = fi->type;
+                               disp      = &(fi->value);
+
+                               if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
+                                       codegen_addpatchref(cd, PATCHER_initialize_class, fi->class, 0);
+                       }
+               
+                       M_AMOV_IMM(disp, REG_ATMP1);
+                       switch (fieldtype) {
+#if defined(ENABLE_SOFTFLOAT)
+                       case TYPE_FLT:
+#endif
+                       case TYPE_INT:
+                               s1 = emit_load_s1(jd, iptr, REG_ITMP2);
+                               M_IST(s1, REG_ATMP1, 0);
+                               break;
+#if defined(ENABLE_SOFTFLOAT)
+                       case TYPE_DBL:
+#endif
+                       case TYPE_LNG:
+                               s1 = emit_load_s1(jd, iptr, REG_ITMP23_PACKED);
+                               M_LST(s1, REG_ATMP1, 0);
+                               break;
+                       case TYPE_ADR:
+                               s1 = emit_load_s1(jd, iptr, REG_ITMP2);
+                               M_AST(s1, REG_ATMP1, 0);
+                               break;
+#if !defined(ENABLE_SOFTFLOAT)
+                       case TYPE_FLT:
+                               s1 = emit_load_s1(jd, iptr, REG_FTMP2);
+                               M_FST(s1, REG_ATMP1, 0);
+                               break;
+                       case TYPE_DBL:
+                               s1 = emit_load_s1(jd, iptr, REG_FTMP2);
+                               M_DST(s1, REG_ATMP1, 0);
+                               break;
+#endif
+                       default: assert(0);
+                       }
+                       break;
+
+               case ICMD_GETFIELD:   /* ...  ==> ..., value                          */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                               uf        = iptr->sx.s23.s3.uf;
+                               fieldtype = uf->fieldref->parseddesc.fd->type;
+                               disp      = 0;
+
+                               codegen_addpatchref(cd, PATCHER_get_putfield, uf, 0);
+                       }
+                       else {
+                               fi        = iptr->sx.s23.s3.fmiref->p.field;
+                               fieldtype = fi->type;
+                               disp      = fi->offset;
+                       }
+
+                       /* implicit null-pointer check */
+                       switch (fieldtype) {
+#if defined(ENABLE_SOFTFLOAT)
+                       case TYPE_FLT:
+#endif
+                       case TYPE_INT:
+                               d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+                               M_ILD(d, s1, disp);
+                               break;
+#if defined(ENABLE_SOFTFLOAT)
+                       case TYPE_DBL:
+#endif
+                       case TYPE_LNG:
+                               d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
+                               if (GET_HIGH_REG(d) == s1) {
+                                       M_ILD(GET_LOW_REG(d), s1, disp + 4);
+                                       M_ILD(GET_HIGH_REG(d), s1, disp);
+                               } else {
+                                       M_ILD(GET_HIGH_REG(d), s1, disp);
+                                       M_ILD(GET_LOW_REG(d), s1, disp + 4);
+                               }
+                               break;
+                       case TYPE_ADR:
+                               d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+                               M_ALD(d, s1, disp);
+                               break;
+#if !defined(ENABLE_SOFTFLOAT)
+                       case TYPE_FLT:
+                               d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
+                               M_FLD(d, s1, disp);
+                               break;
+                       case TYPE_DBL:                          
+                               d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
+                               M_DLD(d, s1, disp);
+                               break;
+#endif
+                       }
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+               case ICMD_PUTFIELD:   /* ..., value  ==> ...                          */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ATMP1);
+
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                               uf        = iptr->sx.s23.s3.uf;
+                               fieldtype = uf->fieldref->parseddesc.fd->type;
+                               disp      = 0;
+                       }
+                       else {
+                               fi        = iptr->sx.s23.s3.fmiref->p.field;
+                               fieldtype = fi->type;
+                               disp      = fi->offset;
+                       }
+
+                       if (IS_INT_LNG_TYPE(fieldtype)) {
+                               if (IS_2_WORD_TYPE(fieldtype)) {
+                                       s2 = emit_load_s2(jd, iptr, REG_ITMP23_PACKED);
+                               } else {
+                                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+                               }
+                       } else {
+                               s2 = emit_load_s2(jd, iptr, REG_FTMP2);
+                       }
+
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr))
+                               codegen_addpatchref(cd, PATCHER_get_putfield, uf, 0);
+
+                       /* implicit null-pointer check */
+                       switch (fieldtype) {
+#if defined(ENABLE_SOFTFLOAT)
+                       case TYPE_FLT:
+#endif
+                       case TYPE_INT:
+                               M_IST(s2, s1, disp);
+                               break;
+
+#if defined(ENABLE_SOFTFLOAT)
+                       case TYPE_DBL:
+#endif
+                       case TYPE_LNG:
+                               M_IST(GET_LOW_REG(s2), s1, disp + 4);      /* keep this order */
+                               M_IST(GET_HIGH_REG(s2), s1, disp);         /* keep this order */
+                               break;
+                       case TYPE_ADR:
+                               M_AST(s2, s1, disp);
+                               break;
+#if !defined(ENABLE_SOFTFLOAT)
+                       case TYPE_FLT:
+                               M_FST(s2, s1, disp);
+                               break;
+                       case TYPE_DBL:
+                               M_DST(s2, s1, disp);
+                               break;
+#endif
+                       }
+                       break;
+
+               case ICMD_ARRAYLENGTH: /* ..., arrayref  ==> ..., length              */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ATMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+                       /* implicit null-pointer check */
+                       M_ILD(d, s1, OFFSET(java_arrayheader, size));
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+               case ICMD_BALOAD:     /* ..., arrayref, index  ==> ..., value         */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ATMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
+                       M_INTMOVE(s2, REG_ITMP2);
+                       M_IADD_IMM(OFFSET(java_bytearray, data[0]), REG_ITMP2);
+                       M_ADRMOVE(s1, REG_ATMP1);
+                       M_AADDINT(REG_ITMP2, REG_ATMP1);
+                       /* implicit null-pointer check */
+                       M_LBZX(REG_ATMP1, d);
+                       M_BSEXT(d, d);
+                       emit_store_dst(jd, iptr, d);
+                       break;                  
+
+               case ICMD_CALOAD:     /* ..., arrayref, index  ==> ..., value         */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ATMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
+                       M_INTMOVE(s2, REG_ITMP2);
+                       M_ISSL_IMM(1, REG_ITMP2);
+                       M_IADD_IMM(OFFSET(java_chararray, data[0]), REG_ITMP2);
+                       M_ADRMOVE(s1, REG_ATMP1);
+                       M_AADDINT(REG_ITMP2, REG_ATMP1);
+                       /* implicit null-pointer check */
+                       M_LHZX(REG_ATMP1, d);
+                       /*M_CZEXT(d, d);*/
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+               case ICMD_SALOAD:     /* ..., arrayref, index  ==> ..., value         */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ATMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
+                       M_INTMOVE(s2, REG_ITMP2);
+                       M_ISSL_IMM(1, REG_ITMP2);
+                       M_IADD_IMM(OFFSET(java_shortarray, data[0]), REG_ITMP2);
+                       M_ADRMOVE(s1, REG_ATMP1);
+                       M_AADDINT(REG_ITMP2, REG_ATMP1);
+               
+                       /* implicit null-pointer check */
+                       M_LHZX(REG_ATMP1, d);
+                       M_HSEXT(d, d);
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+               case ICMD_IALOAD:     /* ..., arrayref, index  ==> ..., value         */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ATMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
+                       M_INTMOVE(s2, REG_ITMP2);
+                       M_ISSL_IMM(2, REG_ITMP2);
+                       M_IADD_IMM(OFFSET(java_intarray, data[0]), REG_ITMP2);
+                       M_ADRMOVE(s1, REG_ATMP1);
+                       M_AADDINT(REG_ITMP2, REG_ATMP1);
+       
+                       /* implicit null-pointer check */
+                       M_LWZX(REG_ATMP1, d);
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+#if 0
+               case ICMD_LALOAD:     /* ..., arrayref, index  ==> ..., value         */
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
+                       M_SLL_IMM(s2, 3, REG_ITMP2);
+                       M_IADD(s1, REG_ITMP2, REG_ITMP2);
+                       M_LLD_INTERN(d, REG_ITMP2, OFFSET(java_longarray, data[0]));
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+               case ICMD_FALOAD:     /* ..., arrayref, index  ==> ..., value         */
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+                       d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
+                       M_SLL_IMM(s2, 2, REG_ITMP2);
+                       M_IADD_IMM(REG_ITMP2, OFFSET(java_floatarray, data[0]), REG_ITMP2);
+                       /* implicit null-pointer check */
+                       M_LFSX(d, s1, REG_ITMP2);
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+               case ICMD_DALOAD:     /* ..., arrayref, index  ==> ..., value         */
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+                       d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
+                       M_SLL_IMM(s2, 3, REG_ITMP2);
+                       M_IADD_IMM(REG_ITMP2, OFFSET(java_doublearray, data[0]), REG_ITMP2);
+                       /* implicit null-pointer check */
+                       M_LFDX(d, s1, REG_ITMP2);
+                       emit_store_dst(jd, iptr, d);
+                       break;
+               #endif
+
+               case ICMD_AALOAD:     /* ..., arrayref, index  ==> ..., value         */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ATMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
+                       M_INTMOVE(s2, REG_ITMP2);
+                       M_ISSL_IMM(2, REG_ITMP2);
+                       M_IADD_IMM(OFFSET(java_objectarray, data[0]), REG_ITMP2);
+                       M_ADRMOVE(s1, REG_ATMP1);
+                       M_AADDINT(REG_ITMP2, REG_ATMP1);
+       
+                       /* implicit null-pointer check */
+                       M_LAX(REG_ATMP1, d);
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+
+               case ICMD_BASTORE:    /* ..., arrayref, index, value  ==> ...         */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
+                       s3 = emit_load_s3(jd, iptr, REG_ITMP3);
+                       M_INTMOVE(s2, REG_ITMP2);
+                       M_IADD_IMM(OFFSET(java_bytearray, data[0]), REG_ITMP2);
+                       M_ADRMOVE(s1, REG_ATMP1);
+                       M_AADDINT(REG_ITMP2, REG_ATMP1);
+       
+                       /* implicit null-pointer check */
+                       M_STBX(REG_ATMP1, s3);
+                       break;
+
+               case ICMD_CASTORE:    /* ..., arrayref, index, value  ==> ...         */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
+                       s3 = emit_load_s3(jd, iptr, REG_ITMP3);
+                       M_INTMOVE(s2, REG_ITMP2);
+                       M_ISSL_IMM(1, REG_ITMP2);
+                       M_IADD_IMM(OFFSET(java_chararray, data[0]), REG_ITMP2); 
+                       M_ADRMOVE(s1, REG_ATMP1);
+                       M_AADDINT(REG_ITMP2, REG_ATMP1);
+                       /* implicit null-pointer check */
+                       M_STHX(REG_ATMP1, s3);
+                       break;
+
+               case ICMD_SASTORE:    /* ..., arrayref, index, value  ==> ...         */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
+                       s3 = emit_load_s3(jd, iptr, REG_ITMP3);
+                       M_INTMOVE(s2, REG_ITMP2);
+                       M_ISSL_IMM(1, REG_ITMP2);
+                       M_IADD_IMM(OFFSET(java_shortarray, data[0]), REG_ITMP2);
+                       M_ADRMOVE(s1, REG_ATMP1);
+                       M_AADDINT(REG_ITMP2, REG_ATMP1);
+                       /* implicit null-pointer check */
+                       M_STHX(REG_ATMP1, s3);
+                       break;
+
+               case ICMD_IASTORE:    /* ..., arrayref, index, value  ==> ...         */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
+                       s3 = emit_load_s3(jd, iptr, REG_ITMP3);
+                       M_INTMOVE(s2, REG_ITMP2);
+                       M_ISSL_IMM(1, REG_ITMP2);
+                       M_IADD_IMM(OFFSET(java_intarray, data[0]), REG_ITMP2);
+                       M_ADRMOVE(s1, REG_ATMP1);
+                       M_AADDINT(REG_ITMP2, REG_ATMP1);
+                       /* implicit null-pointer check */
+                       M_STWX(REG_ATMP1, s3);
+                       break;
+
+#if 0
+               case ICMD_LASTORE:    /* ..., arrayref, index, value  ==> ...         */
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
+                       s3 = emit_load_s3_high(jd, iptr, REG_ITMP3);
+                       M_INTMOVE(s2, REG_ITMP2);
+                       M_IADD_IMM(OFFSET(java_bytearray, data[0]), REG_ITMP2);
+                       M_ISSL_IMM(1, REG_ITMP2);
+                       M_ADRMOVE(s1, REG_ATMP1);
+                       M_AADDINT(REG_ITMP2, REG_ATMP1);
+                       /* implicit null-pointer check */
+                       M_STWX(s3, s1, REG_ITMP2);
+                       M_IADD_IMM(REG_ITMP2, 4, REG_ITMP2);
+                       s3 = emit_load_s3_low(jd, iptr, REG_ITMP3);
+                       M_STWX(s3, s1, REG_ITMP2);
+                       break;
+
+               case ICMD_FASTORE:    /* ..., arrayref, index, value  ==> ...         */
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
+                       s3 = emit_load_s3(jd, iptr, REG_FTMP3);
+                       M_SLL_IMM(s2, 2, REG_ITMP2);
+                       M_IADD_IMM(REG_ITMP2, OFFSET(java_floatarray, data[0]), REG_ITMP2);
+                       /* implicit null-pointer check */
+                       M_STFSX(s3, s1, REG_ITMP2);
+                       break;
+
+               case ICMD_DASTORE:    /* ..., arrayref, index, value  ==> ...         */
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
+                       s3 = emit_load_s3(jd, iptr, REG_FTMP3);
+                       M_SLL_IMM(s2, 3, REG_ITMP2);
+                       M_IADD_IMM(REG_ITMP2, OFFSET(java_doublearray, data[0]), REG_ITMP2);
+                       /* implicit null-pointer check */
+                       M_STFDX(s3, s1, REG_ITMP2);
+                       break;
+
+       #endif
+               case ICMD_AASTORE:    /* ..., arrayref, index, value  ==> ...         */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ATMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP1);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
+                       s3 = emit_load_s3(jd, iptr, REG_ATMP2);
+
+                       /* XXX what if array is NULL */
+                       disp = dseg_add_functionptr(cd, BUILTIN_canstore);
+
+                       M_AST(s1, REG_SP, 0*4);
+                       M_AST(s3, REG_SP, 1*4);
+                       M_JSR_IMM(BUILTIN_canstore);    
+                       emit_exception_check_ireg(cd, iptr);
+
+                       s1 = emit_load_s1(jd, iptr, REG_ATMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP1);
+                       s3 = emit_load_s3(jd, iptr, REG_ATMP2);
+                       M_INTMOVE(s2, REG_ITMP1);
+                       M_ISSL_IMM(2, REG_ITMP1);
+                       M_IADD_IMM(OFFSET(java_objectarray, data[0]), REG_ITMP1);
+                       M_INTMOVE(s1, REG_ATMP1);
+                       M_AADDINT(REG_ITMP1, REG_ATMP1);
+                       /* implicit null-pointer check */
+                       M_STAX(REG_ATMP1, s3);
+                       break;
+
+
+
+               /* METHOD INVOCATION *********************************************************/
+               case ICMD_BUILTIN:      /* ..., [arg1, [arg2 ...]] ==> ...            */
+                       bte = iptr->sx.s23.s3.bte;
+                       md  = bte->md;
+                       goto gen_method;
+
+               case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ...            */
+               case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
+               case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer    */
+               case ICMD_INVOKEINTERFACE:
+                       REPLACEMENT_POINT_INVOKE(cd, iptr);
+
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                               lm = NULL;
+                               um = iptr->sx.s23.s3.um;
+                               md = um->methodref->parseddesc.md;
+                       }
+                       else {
+                               lm = iptr->sx.s23.s3.fmiref->p.method;
+                               um = NULL;
+                               md = lm->parseddesc;
+                       }
+       gen_method:
+                       s3 = md->paramcount;
+       
+                       MCODECHECK((s3 << 1) + 64);
+
+                       /* copy arguments to stack */
+                       for (s3 = s3 - 1; s3 >= 0; s3--)        {
+                               var = VAR(iptr->sx.s23.s2.args[s3]);
+                               /* already preallocated */
+                               if (var->flags & PREALLOC) continue;
+               
+                               if (!md->params[s3].inmemory) assert(0);
+
+                               switch (var->type)      {
+#if defined(ENABLE_SOFTFLOAT)
+                                       case TYPE_DBL:
+#endif
+                                       case TYPE_LNG:
+                                               d = emit_load(jd, iptr, var, REG_ITMP12_PACKED);
+                                               M_LST(d, REG_SP, md->params[s3].regoff*4);
+                                               break;
+#if defined(ENABLE_SOFTFLOAT)
+                                       case TYPE_FLT:
+#endif
+                                       case TYPE_INT:
+                                               d = emit_load(jd, iptr, var, REG_ITMP1);
+                                               M_IST(d, REG_SP, md->params[s3].regoff*4);
+                                               break;
+                                       case TYPE_ADR:
+                                               d = emit_load(jd, iptr, var, REG_ATMP1);
+                                               M_AST(d, REG_SP, md->params[s3].regoff*4);
+                                               break;
+#if !defined(ENABLE_SOFTFLOAT)
+                                       case TYPE_FLT:
+                                       case TYPE_DBL:
+#endif
+                                       default:
+                                               assert(0);
+                               }
+                       }
+
+                       /* arguments in place now */
+                       switch(iptr->opc)       {
+                               case ICMD_BUILTIN: 
+                                       disp = (ptrint) bte->fp;
+                                       d = md->returntype.type;
+                                       M_JSR_IMM(disp);
+
+                                       REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
+                                       /*emit_exception_check(cd, iptr); TODO */
+                                       break;
+
+                               case ICMD_INVOKESPECIAL: 
+                                       /* adress register for sure */
+                                       M_ALD(REG_ATMP1, REG_SP, 0);
+                                       emit_nullpointer_check(cd, iptr, REG_ATMP1);
+                                       /* fall through */
+                               case ICMD_INVOKESTATIC: 
+                                       if (lm == NULL) {
+                                               codegen_addpatchref(cd, PATCHER_invokestatic_special, um, 0);
+                                               disp = 0;
+                                               M_AMOV_IMM(disp, REG_ATMP1);
+                                       } else  {
+                                               disp = lm->stubroutine;
+                                               M_AMOV_IMM(disp, REG_ATMP1);
+                                       }
+
+                                       /* generate the actual call */
+                                       M_JSR(REG_ATMP1);
+                                       REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
+                                       break;
+
+
+                               case ICMD_INVOKEVIRTUAL:
+                                       if (lm == NULL) {
+                                               codegen_addpatchref(cd, PATCHER_invokevirtual, um, 0);
+                                               s1 = 0;
+                                       } else {
+                                               s1 = OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * lm->vftblindex;
+                                       }
+                                       /* load object pointer (==argument 0) */
+                                       M_ALD(REG_ATMP1, REG_SP, 0);
+                                       /* implicit null-pointer check */
+                                       M_ALD(REG_METHODPTR, REG_ATMP1, OFFSET(java_objectheader, vftbl));
+                                       M_ALD(REG_ATMP1, REG_METHODPTR, s1);
+                                       /* generate the actual call */
+                                       M_JSR(REG_ATMP1);
+                                       break;
+                               case ICMD_INVOKEINTERFACE: 
+                                       if (lm == NULL) {
+                                               codegen_addpatchref(cd, PATCHER_invokeinterface, um, 0);
+
+                                               s1 = 0;
+                                               s2 = 0;
+                                       } else {
+                                               s1 = OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr*) * lm->class->index;
+                                               s2 = sizeof(methodptr) * (lm - lm->class->methods);
+                                       }
+                                       /* load object pointer (==argument 0) */
+                                       M_ALD(REG_ATMP1, REG_SP, 0);
+
+                                       /* implicit null-pointer check */
+                                       M_ALD(REG_METHODPTR, REG_ATMP1, OFFSET(java_objectheader, vftbl));
+                                       M_ALD(REG_METHODPTR, REG_METHODPTR, s1);
+                                       M_ALD(REG_ATMP1, REG_METHODPTR, s2);
+
+                                       /* generate the actual call */
+                                       M_JSR(REG_ATMP1);
+                                       REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
+                                       break;
+
+                               default: assert(0);
+                               }       /* switch (iptr->opc) */
+
+                               REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
+                               
+                               /* store return value */
+                               d = md->returntype.type;
+
+                               switch (d)      {
+                                       case TYPE_VOID: break;
+#if defined(ENABLE_SOFTFLOAT)
+                                       case TYPE_FLT:
+#endif
+                                       case TYPE_INT:
+                                               s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
+                                               M_INTMOVE(REG_RESULT, s1);
+                                               break;
+#if defined(ENABLE_SOFTFLOAT)
+                                       case TYPE_DBL:
+#endif
+                                       case TYPE_LNG:
+                                               s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
+                                               M_LNGMOVE(REG_RESULT_PACKED, s1);
+                                               break;
+                                       case TYPE_ADR:
+                                               s1 = codegen_reg_of_dst(jd, iptr, REG_ATMP1);
+                                               /* all stuff is returned in %d0 */
+                                               M_INT2ADRMOVE(REG_RESULT, s1);
+                                               break;
+#if !defined(ENABLE_SOFTFLOAT)
+                                       case TYPE_FLT:
+                                       case TYPE_DBL:
+#endif
+                                       default:
+                                               assert(0);
+                               }
+                               if (d != TYPE_VOID) emit_store_dst(jd, iptr, s1);
+                       break; /* ICMD_INVOKE* */
+
+#if defined(ENABLE_SOFTFLOAT)
+               case ICMD_FRETURN:
+#endif
+               case ICMD_IRETURN:      /* ..., retvalue ==> ...                      */
+
+                       REPLACEMENT_POINT_RETURN(cd, iptr);
+                       s1 = emit_load_s1(jd, iptr, REG_RESULT);
+                       M_INTMOVE(s1, REG_RESULT);
+                       goto nowperformreturn;
+
+               case ICMD_ARETURN:      /* ..., retvalue ==> ...                      */
+
+                       REPLACEMENT_POINT_RETURN(cd, iptr);
+                       s1 = emit_load_s1(jd, iptr, REG_RESULT);
+                       assert(VAROP(iptr->s1)->type == TYPE_ADR);
+                       M_ADR2INTMOVE(s1, REG_RESULT);
+
+#ifdef ENABLE_VERIFIER
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                               unresolved_class *uc = iptr->sx.s23.s2.uc;
+
+                               codegen_addpatchref(cd, PATCHER_resolve_class, uc, 0);
+                       }
+#endif /* ENABLE_VERIFIER */
+                       goto nowperformreturn;
+
+#if defined(ENABLE_SOFTFLOAT)
+               case ICMD_DRETURN:
+#endif
+               case ICMD_LRETURN:      /* ..., retvalue ==> ...                      */
+
+                       REPLACEMENT_POINT_RETURN(cd, iptr);
+                       s1 = emit_load_s1(jd, iptr, REG_RESULT_PACKED);
+                       M_LNGMOVE(s1, REG_RESULT_PACKED);
+                       goto nowperformreturn;
+
+#if !defined(ENABLE_SOFTFLOAT)
+               case ICMD_FRETURN:      /* ..., retvalue ==> ...                      */
+               case ICMD_DRETURN:
+
+                       REPLACEMENT_POINT_RETURN(cd, iptr);
+                       s1 = emit_load_s1(jd, iptr, REG_FRESULT);
+                       M_FLTMOVE(s1, REG_FRESULT);
+                       goto nowperformreturn;
+#endif
+
+               case ICMD_RETURN:      /* ...  ==> ...                                */
+
+                       REPLACEMENT_POINT_RETURN(cd, iptr);
+
+nowperformreturn:
+                       {
+                       s4 i, p;
+                       
+                       p = cd->stackframesize;
+
+                       /* call trace function */
+#if !defined(NDEBUG)
+                       emit_verbosecall_exit(jd);
+#endif
+
+#if defined(ENABLE_THREADS)
+                       if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
+                               disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
+                               M_ALD(REG_ITMP3, REG_PV, disp);
+                               M_MTCTR(REG_ITMP3);
+
+                               /* we need to save the proper return value */
+
+                               switch (iptr->opc) {
+                               case ICMD_LRETURN:
+                                       M_IST(REG_RESULT2, REG_SP, rd->memuse * 4 + 8);
+                                       /* fall through */
+                               case ICMD_IRETURN:
+                               case ICMD_ARETURN:
+                                       M_IST(REG_RESULT , REG_SP, rd->memuse * 4 + 4);
+                                       break;
+                               case ICMD_FRETURN:
+                                       M_FST(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
+                                       break;
+                               case ICMD_DRETURN:
+                                       M_DST(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
+                                       break;
+                               }
+
+                               M_ALD(REG_A0, REG_SP, rd->memuse * 4);
+                               M_JSR;
+
+                               /* and now restore the proper return value */
+
+                               switch (iptr->opc) {
+                               case ICMD_LRETURN:
+                                       M_ILD(REG_RESULT2, REG_SP, rd->memuse * 4 + 8);
+                                       /* fall through */
+                               case ICMD_IRETURN:
+                               case ICMD_ARETURN:
+                                       M_ILD(REG_RESULT , REG_SP, rd->memuse * 4 + 4);
+                                       break;
+                               case ICMD_FRETURN:
+                                       M_FLD(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
+                                       break;
+                               case ICMD_DRETURN:
+                                       M_DLD(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
+                                       break;
+                               }
+                       }
+#endif
+
+
+                       /* restore return address                                         */
+#if 0
+                       if (!jd->isleafmethod) {
+                               /* ATTENTION: Don't use REG_ZERO (r0) here, as M_ALD
+                                  may have a displacement overflow. */
+
+                               M_ALD(REG_ITMP1, REG_SP, p * 4 + LA_LR_OFFSET);
+                               M_MTLR(REG_ITMP1);
+                       }
+#endif
+                       /* restore saved registers                                        */
+
+                       for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
+                               p--; M_ILD(rd->savintregs[i], REG_SP, p * 4);
+                       }
+                       for (i=ADR_SAV_CNT-1; i>=rd->savadrreguse; --i) {
+                               p--; M_ALD(rd->savadrregs[i], REG_SP, p*4);
+                       }
+#if !defined(ENABLE_SOFTFLOAT)
+                       for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
+                               p -= 2; M_DLD(rd->savfltregs[i], REG_SP, p * 4);
+                       }
+#endif
+                       /* deallocate stack                                               */
+                       M_AADD_IMM(cd->stackframesize*4, REG_SP);
+                       M_RET;
+                       }
+                       break;
+
+               /* the evil ones */
+               case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult            */
+                                     /* val.a: (classinfo*) superclass               */
+
+                       /*  superclass is an interface:
+                        *
+                        *  return (sub != NULL) &&
+                        *         (sub->vftbl->interfacetablelength > super->index) &&
+                        *         (sub->vftbl->interfacetable[-super->index] != NULL);
+                        *
+                        *  superclass is a class:
+                        *
+                        *  return ((sub != NULL) && (0
+                        *          <= (sub->vftbl->baseval - super->vftbl->baseval) <=
+                        *          super->vftbl->diffvall));
+                        */
+
+                       {
+                       classinfo *super;
+                       s4         superindex;
+
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                               super      = NULL;
+                               superindex = 0;
+                       }
+                       else {
+                               super      = iptr->sx.s23.s3.c.cls;
+                               superindex = super->index;
+                       }
+                       
+#if defined(ENABLE_THREADS)
+                       codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
+#endif
+                       s1 = emit_load_s1(jd, iptr, REG_ATMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+
+                       assert(VAROP(iptr->s1 )->type == TYPE_ADR);
+                       assert(VAROP(iptr->dst)->type == TYPE_INT);
+
+                       M_ICLR(d);
+
+                       /* if class is not resolved, check which code to call */
+
+                       if (super == NULL) {
+                               M_ATST(s1);
+                               emit_label_beq(cd, BRANCH_LABEL_1);
+
+                               codegen_addpatchref(cd, PATCHER_resolve_classref_to_flags, iptr->sx.s23.s3.c.ref, 0);
+
+                               M_IMOV_IMM32(0, REG_ITMP3);
+                               M_IAND_IMM(ACC_INTERFACE, REG_ITMP3);
+                               emit_label_beq(cd, BRANCH_LABEL_2);
+                       }
+
+                       /* interface instanceof code */
+
+                       if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
+                               if (super == NULL) {
+                                       codegen_addpatchref(cd, PATCHER_instanceof_interface, iptr->sx.s23.s3.c.ref, 0);
+                               } else {
+                                       M_ATST(s1);
+                                       emit_label_beq(cd, BRANCH_LABEL_3);
+                               }
+
+                               M_ALD(REG_ATMP1, s1, OFFSET(java_objectheader, vftbl));
+                               M_ILD(REG_ITMP3, REG_ATMP1, OFFSET(vftbl_t, interfacetablelength));
+                               M_IADD_IMM(-superindex, REG_ITMP3);     /* -superindex may be patched patched */
+                               M_ITST(REG_ITMP3);
+                               M_BLE(10);
+                               M_ALD(REG_ATMP1, REG_ATMP1, OFFSET(vftbl_t, interfacetable[0]) - superindex * sizeof(methodptr*));      /* patch here too! */
+                               M_ATST(REG_ATMP1);
+                               M_BEQ(2);
+                               M_IMOV_IMM(1, d);
+
+                               if (super == NULL)
+                                       emit_label_br(cd, BRANCH_LABEL_4);
+                               else
+                                       emit_label(cd, BRANCH_LABEL_3);
+                       }
+
+                       /* class instanceof code */
+
+                       if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
+                               if (super == NULL) {
+                                       emit_label(cd, BRANCH_LABEL_2);
+
+                                       codegen_addpatchref(cd, PATCHER_resolve_classref_to_vftbl, iptr->sx.s23.s3.c.ref, 0);
+                                       M_AMOV_IMM(0, REG_ATMP2);
+                               } else {
+                                       M_AMOV_IMM(super->vftbl, REG_ATMP2);
+                                       M_ATST(s1);
+                                       emit_label_beq(cd, BRANCH_LABEL_5);
+                               }
+
+                               M_ALD(REG_ATMP1, s1, OFFSET(java_objectheader, vftbl));
+#if defined(ENABLE_THREADS)
+                               codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
+#endif
+                               M_ILD(REG_ITMP1, REG_ATMP1, OFFSET(vftbl_t, baseval));
+                               M_ILD(REG_ITMP3, REG_ATMP2, OFFSET(vftbl_t, baseval));
+                               M_ILD(REG_ITMP2, REG_ATMP2, OFFSET(vftbl_t, diffval));
+#if defined(ENABLE_THREADS)
+                               codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
+#endif
+                               M_ISUB(REG_ITMP3, REG_ITMP1);
+                               M_ICMP(REG_ITMP1, REG_ITMP2);
+                               M_BGT(4);
+                               M_IMOV_IMM(1, d);
+                               M_TPFW;                 /* overlaps next instruction */
+                               M_ICLR(d);
+
+                               if (super != NULL)
+                                       emit_label(cd, BRANCH_LABEL_5);
+                       }
+
+                       if (super == NULL) {
+                               emit_label(cd, BRANCH_LABEL_1);
+                               emit_label(cd, BRANCH_LABEL_4);
+                       }
+
+                       emit_store_dst(jd, iptr, d);
+                       }
+                       break;
+
+               case ICMD_CHECKCAST:  /* ..., objectref ==> ..., objectref            */
+                                     /* val.a: (classinfo*) superclass               */
+
+                       /*  superclass is an interface:
+                        *
+                        *  OK if ((sub == NULL) ||
+                        *         (sub->vftbl->interfacetablelength > super->index) &&
+                        *         (sub->vftbl->interfacetable[-super->index] != NULL));
+                        *
+                        *  superclass is a class:
+                        *
+                        *  OK if ((sub == NULL) || (0
+                        *         <= (sub->vftbl->baseval - super->vftbl->baseval) <=
+                        *         super->vftbl->diffvall));
+                        */
+
+                       if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
+                               /* object type cast-check */
+
+                               classinfo *super;
+                               s4         superindex;
+
+                               if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                                       super      = NULL;
+                                       superindex = 0;
+                               }
+                               else {
+                                       super      = iptr->sx.s23.s3.c.cls;
+                                       superindex = super->index;
+                               }
+
+#if defined(ENABLE_THREADS)
+                               codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
+#endif
+
+                               s1 = emit_load_s1(jd, iptr, REG_ATMP1);
+                               assert(VAROP(iptr->s1)->type == TYPE_ADR);
+
+                               /* if class is not resolved, check which code to call */
+
+                               if (super == NULL) {
+                                       M_ATST(s1);
+                                       emit_label_beq(cd, BRANCH_LABEL_1);
+
+                                       codegen_addpatchref(cd, PATCHER_resolve_classref_to_flags, iptr->sx.s23.s3.c.ref, 0);
+                       
+                                       M_IMOV_IMM32(0, REG_ITMP2);
+                                       M_IAND_IMM(ACC_INTERFACE, REG_ITMP2);
+                                       emit_label_beq(cd, BRANCH_LABEL_2);
+                               }
+
+                               /* interface checkcast code */
+
+                               if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
+                                       if (super == NULL) {
+                                               codegen_addpatchref(cd, PATCHER_checkcast_interface, iptr->sx.s23.s3.c.ref, 0);
+                                       } else {
+                                               M_ATST(s1);
+                                               emit_label_beq(cd, BRANCH_LABEL_3);
+                                       }
+
+                                       M_ALD(REG_ATMP2, s1, OFFSET(java_objectheader, vftbl));
+                                       M_ILD(REG_ITMP3, REG_ATMP2, OFFSET(vftbl_t, interfacetablelength));
+       
+                                       M_IADD_IMM(-superindex, REG_ITMP3);     /* superindex patched */
+                                       M_ITST(REG_ITMP3);
+                                       emit_classcast_check(cd, iptr, BRANCH_LE, REG_ITMP3, s1);
+
+                                       M_ALD(REG_ATMP3, REG_ATMP2, OFFSET(vftbl_t, interfacetable[0]) - superindex * sizeof(methodptr*));      /* patched*/
+                                       M_ATST(REG_ATMP3);
+                                       emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ATMP3, s1);
+
+                                       if (super == NULL)
+                                               emit_label_br(cd, BRANCH_LABEL_4);
+                                       else
+                                               emit_label(cd, BRANCH_LABEL_3);
+                               }
+
+                               /* class checkcast code */
+
+                               if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
+                                       if (super == NULL) {
+                                               emit_label(cd, BRANCH_LABEL_2);
+
+                                               codegen_addpatchref(cd, PATCHER_resolve_classref_to_vftbl, iptr->sx.s23.s3.c.ref, 0);
+                                               M_AMOV_IMM(0, REG_ATMP3);
+                                       } else {
+                                               M_AMOV_IMM(super->vftbl, REG_ATMP3);
+                                               M_ATST(s1);
+                                               emit_label_beq(cd, BRANCH_LABEL_5);
+                                       }
+
+                                       M_ALD(REG_ATMP2, s1, OFFSET(java_objectheader, vftbl));
+#if defined(ENABLE_THREADS)
+                                       codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
+#endif
+                                       M_ILD(REG_ITMP3, REG_ATMP2, OFFSET(vftbl_t, baseval));  /* REG_ITMP3 == sub->vftbl->baseval */
+#if 0
+                                       if (s1 != REG_ATMP1) {
+#endif
+                                               M_ILD(REG_ITMP1, REG_ATMP3, OFFSET(vftbl_t, baseval));
+                                               M_ILD(REG_ITMP2, REG_ATMP3, OFFSET(vftbl_t, diffval));
+#if defined(ENABLE_THREADS)
+                                               codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
+#endif
+                                               M_ISUB(REG_ITMP1, REG_ITMP3);
+                                               M_ICMP(REG_ITMP2, REG_ITMP1);   /* XXX was CMPU */
+#if 0                                  
+                                       } else {
+                                               assert(0);
+                                               M_ILD(REG_ITMP2, REG_ATMP3, OFFSET(vftbl_t, baseval));
+                                               M_ISUB(REG_ITMP3, REG_ITMP2);
+                                               M_ILD(REG_ITMP3, REG_ATMP3, OFFSET(vftbl_t, diffval));
+                                               M_ICMP(REG_ITMP2, REG_ITMP3);   /* XXX was CMPU */
+#if defined(ENABLE_THREADS)
+                                               codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
+#endif
+                                       }
+#endif
+                                       emit_classcast_check(cd, iptr, BRANCH_UGT, REG_ITMP3, s1); /* XXX was BRANCH_GT */
+
+                                       if (super != NULL)
+                                               emit_label(cd, BRANCH_LABEL_5);
+                               }
+
+                               if (super == NULL) {
+                                       emit_label(cd, BRANCH_LABEL_1);
+                                       emit_label(cd, BRANCH_LABEL_4);
+                               }
+
+                               d = codegen_reg_of_dst(jd, iptr, s1);
+                       } else {
+                               /* array type cast-check */
+
+                               s1 = emit_load_s1(jd, iptr, REG_ATMP2);
+
+                               if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                                       codegen_addpatchref(cd, PATCHER_resolve_classref_to_classinfo, iptr->sx.s23.s3.c.ref, 0);
+                                       M_AMOV_IMM(0, REG_ATMP1);
+                               } else {
+                                       M_AMOV_IMM(iptr->sx.s23.s3.c.cls, REG_ATMP1);
+                               }
+       
+                               M_APUSH(s1);
+                               M_APUSH(REG_ATMP1);
+                               M_JSR_IMM(BUILTIN_arraycheckcast);
+                               M_AADD_IMM(2*4, REG_SP);                /* pop arguments off stack */
+                               M_ITST(REG_RESULT);
+                               emit_classcast_check(cd, iptr, BRANCH_EQ, REG_RESULT, s1);
+
+                               s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                               d = codegen_reg_of_dst(jd, iptr, s1);
+                       }
+                       assert(VAROP(iptr->dst)->type == TYPE_ADR);
+                       M_ADRMOVE(s1, d);
+                       emit_store_dst(jd, iptr, d);
+                       break;
+
+               case ICMD_TABLESWITCH:  /* ..., index ==> ...                         */
+                       {
+                       s4 i, l;
+                       branch_target_t *table;
+
+                       table = iptr->dst.table;
+
+                       l = iptr->sx.s23.s2.tablelow;
+                       i = iptr->sx.s23.s3.tablehigh;
+                       
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       M_INTMOVE(s1, REG_ITMP1);
+                       if (l != 0) M_ISUB_IMM(l, REG_ITMP1);
+
+                       i = i - l + 1;
+
+                       /* range check */
+                       M_ICMP_IMM(i - 1, REG_ITMP1);
+                       emit_bugt(cd, table[0].block);
+
+                       /* build jump table top down and use address of lowest entry */
+                       table += i;
+
+                       while (--i >= 0) {
+                               dseg_add_target(cd, table->block); 
+                               --table;
+                       }
+
+                       /* length of dataseg after last dseg_add_target is used by load */
+                       M_AMOV_IMM(0, REG_ATMP2);
+                       dseg_adddata(cd);
+
+                       M_ISSL_IMM(2, REG_ITMP1);                       /* index * 4 == offset in table */
+                       M_AADDINT(REG_ITMP1, REG_ATMP2);                /* offset in table */
+                       M_AADD_IMM(-(cd->dseglen), REG_ATMP2);          /* start of table in dseg */
+                       M_ALD(REG_ATMP1, REG_ATMP2, 0);
+
+                       M_JMP(REG_ATMP1);
+                       ALIGNCODENOP;
+                       }
+                       break;
+
+               case ICMD_LOOKUPSWITCH: /* ..., key ==> ...                           */
+                       {
+                       s4 i;
+                       lookup_target_t *lookup;
+
+                       lookup = iptr->dst.lookup;
+
+                       i = iptr->sx.s23.s2.lookupcount;
+                       
+                       MCODECHECK((i<<2)+8);
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+
+                       while (--i >= 0) {
+                               M_ICMP_IMM(lookup->value, s1);
+                               emit_beq(cd, lookup->target.block);
+                               lookup++;
+                       }
+
+                       emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
+                       ALIGNCODENOP;
+                       break;
+                       }
+
+
+               default:
+                       printf("UNKNOWN OPCODE %d\n", iptr->opc);
+                       exceptions_throw_internalerror("Unknown ICMD %d during code generation", iptr->opc);
+                       return false;
+       } /* switch */
+       M_TPF;
+       } /* for each instruction */
+       } /* if (btpre->flags >= BBREACHED) */
+       } /* for each basic block */
+
+       dseg_createlinenumbertable(cd);
+
+       /* generate stubs */
+       emit_patcher_stubs(jd);
+       REPLACEMENT_EMIT_STUBS(jd);
+
+       return true;
+}
+
+/* createnativestub ************************************************************
+
+   Creates a stub routine which calls a native method.
+
+*******************************************************************************/
+u1* createnativestub(functionptr f, jitdata *jd, methoddesc *nmd) 
+{
+       methodinfo   *m;
+       codeinfo     *code;
+       codegendata  *cd;
+       registerdata *rd;
+       methoddesc   *md;
+       s4 nativeparams, i, j, t, s1, s2;
+       
+       /* get required compiler data */
+
+       m    = jd->m;
+       code = jd->code;
+       cd   = jd->cd;
+       rd   = jd->rd;
+
+       md = m->parseddesc;
+       nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
+
+       /* calc stackframe size */
+       cd->stackframesize =    sizeof(stackframeinfo) / SIZEOF_VOID_P +
+                               sizeof(localref_table) / SIZEOF_VOID_P +
+                               nmd->memuse +
+                               4 +                                             /* %d0,%d1,%a0,%a1*/
+                               2 * 2 +                                         /* %f0,%f1 */
+                               1 +                                             /* functionptr */
+                               4;                                              /* args for codegen_start_native_call */
+
+       /* create method header */
+       (void) dseg_add_unique_address(cd, code);                      /* CodeinfoPointer */
+       (void) dseg_add_unique_s4(cd, cd->stackframesize * 4);         /* FrameSize       */
+       (void) dseg_add_unique_s4(cd, 0);                              /* IsSync          */
+       (void) dseg_add_unique_s4(cd, 0);                              /* IsLeaf          */
+       (void) dseg_add_unique_s4(cd, 0);                              /* IntSave         */
+       (void) dseg_add_unique_s4(cd, 0);                              /* FltSave         */
+       (void) dseg_addlinenumbertablesize(cd);
+       (void) dseg_add_unique_s4(cd, 0);                              /* ExTableSize     */
+
+       /* print call trace */
+#if !defined(NDEBUG)
+       if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) {
+               emit_verbosecall_enter(jd);
+       }
+#endif
+
+       /* generate code */
+       M_AADD_IMM(-(cd->stackframesize*4), REG_SP);
+
+       /* get function address (this must happen before the stackframeinfo) */
+#if !defined(WITH_STATIC_CLASSPATH)
+       if (f == NULL)  {
+               codegen_addpatchref(cd, PATCHER_resolve_native_function, m, 0);
+               /*M_AMOV_IMM(0, REG_ATMP2);*/
+       }
+#endif
+       M_AMOV_IMM(f, REG_ATMP2); /* do not move this line, the patcher is needed */
+
+       M_AST(REG_ATMP2, REG_SP, 4 * 4);
+
+       /* save integer and float temp registers */
+       /*
+       M_IST(REG_D0, REG_SP, 4*4 + 2*8 + 3*4);
+       M_IST(REG_D1, REG_SP, 4*4 + 2*8 + 2*4);
+       M_AST(REG_A0, REG_SP, 4*4 + 2*8 + 1*4);
+       M_AST(REG_A1, REG_SP, 4*4 + 2*8 + 0*4);
+       */
+
+       /* TODO */
+       /* store %f0, %f1 */
+
+       /* put arguments for codegen_start_native_call onto stack */
+       /* void codegen_start_native_call(u1 *datasp, u1 *pv, u1 *sp, u1 *ra) */
+       
+       M_AMOV(REG_SP, REG_ATMP1);
+       M_AADD_IMM(cd->stackframesize * 4, REG_ATMP1);
+
+       M_ALD(REG_ATMP3, REG_ATMP1, 0 * 4);
+       M_AST(REG_ATMP3, REG_SP, 3 * 4);                /* ra */
+
+       M_AST(REG_ATMP1, REG_SP, 0 * 4);                /* datasp */
+
+       M_AADD_IMM(1 * 4 , REG_ATMP1);                  
+       M_AST(REG_ATMP1, REG_SP, 2 * 4);                /* sp */
+
+       M_AMOV_IMM(0, REG_ATMP2);                       /* 0 needs to patched */
+       dseg_adddata(cd);                               /* this patches it */
+
+       M_AST(REG_ATMP2, REG_SP, 1 * 4);                /* pv */
+
+       M_JSR_IMM(codegen_start_native_call);
+
+       /* load function pointer */
+       M_ALD(REG_ATMP2, REG_SP, 4 * 4);
+
+       /* copy arguments into stackframe */
+       for (i = md->paramcount -1, j = i + nativeparams; i >= 0; --i, --j)     {
+               t = md->paramtypes[i].type;
+               /* all arguments via stack */
+               assert(md->params[i].inmemory);                                         
+
+               s1 = (md->params[i].regoff + cd->stackframesize + 1) * 4;
+               s2 = nmd->params[j].regoff * 4;
+
+               /* simply copy argument stack */
+               M_ILD(REG_ITMP1, REG_SP, s1);
+               M_IST(REG_ITMP1, REG_SP, s2);
+               if (IS_2_WORD_TYPE(t))  {
+                       M_ILD(REG_ITMP1, REG_SP, s1 + 4);
+                       M_IST(REG_ITMP1, REG_SP, s2 + 4);
+               }
+       }
+
+       /* for static function class as second arg */
+       if (m->flags & ACC_STATIC)      {
+               M_AMOV_IMM(m->class, REG_ATMP1);
+               M_AST(REG_ATMP1, REG_SP, 1 * 4);
+       }
+       /* env ist first argument */
+       M_AMOV_IMM(_Jv_env, REG_ATMP1);
+       M_AST(REG_ATMP1, REG_SP, 0 * 4);
+
+       /* call the native function */
+       M_JSR(REG_ATMP2);
+
+       /* save return value */
+       switch (md->returntype.type)    {
+               case TYPE_VOID: break;
+
+#if defined(ENABLE_SOFTFLOAT)
+               case TYPE_DBL:
+#endif
+               case TYPE_LNG:
+                       M_IST(REG_D1, REG_SP, 2 * 4);
+                       /* fall through */
+
+#if defined(ENABLE_SOFTFLOAT)
+               case TYPE_FLT:
+#endif
+               case TYPE_INT:
+               case TYPE_ADR:
+                       M_IST(REG_D0, REG_SP, 1 * 4);
+                       break;
+
+#if !defined(ENABLE_SOFTFLOAT)
+               case TYPE_FLT:
+               case TYPE_DBL:  /* FIXME */
+#endif
+               default: assert(0);
+       }
+       
+       /* print call trace */
+#if ! defined(NDEBUG)
+       if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) {
+               emit_verbosecall_exit(jd);
+       }
+#endif
+       /* remove native stackframe info */
+       /* therefore we call: java_objectheader *codegen_finish_native_call(u1 *datasp) */
+
+       M_AMOV(REG_SP, REG_ATMP3);
+       M_AADD_IMM(cd->stackframesize * 4, REG_ATMP3);
+       M_AST(REG_ATMP3, REG_SP, 0 * 4);                        /* datasp */
+       M_JSR_IMM(codegen_finish_native_call);
+       
+       M_INT2ADRMOVE(REG_RESULT, REG_ATMP3);
+       /* restore return value */
+       switch (md->returntype.type)    {
+               case TYPE_VOID: break;
+
+#if defined(ENABLE_SOFTFLOAT)
+               case TYPE_DBL:
+#endif
+               case TYPE_LNG:
+                       M_ILD(REG_D1, REG_SP, 2 * 4);
+                       /* fall through */
+#if defined(ENABLE_SOFTFLOAT)
+               case TYPE_FLT:
+#endif
+               case TYPE_INT:
+               case TYPE_ADR:
+                       M_ILD(REG_D0, REG_SP, 1 * 4);
+                       break;
+
+#if !defined(ENABLE_SOFTFLOAT)
+               case TYPE_FLT:
+               case TYPE_DBL:  /* FIXME */
+#endif
+               default: assert(0);
+       }
+       /* restore saved registers */
+
+       M_AADD_IMM(cd->stackframesize*4, REG_SP);
+       /* check for exception */
+       M_ATST(REG_ATMP3);
+       M_BNE(2);
+       M_RET;
+
+       /* handle exception */
+       M_JSR_IMM(0);   /* FIXME */
+
+
+       /* generate patcher stub call code */
+       emit_patcher_stubs(jd);
+       codegen_finish(jd);
+
+       return code->entrypoint;
+}
+
+/* createcompilerstub **********************************************************
+
+   Creates a stub routine which calls the compiler.
+       
+*******************************************************************************/
+
+#define COMPILERSTUB_DATASIZE (3 * SIZEOF_VOID_P)
+#define COMPILERSTUB_CODESIZE (6+6+6+2)
+#define COMPILERSTUB_SIZE (COMPILERSTUB_DATASIZE +  COMPILERSTUB_CODESIZE)
+u1* createcompilerstub(methodinfo *m) 
+{ 
+       u1          *s;
+       ptrint      *d;
+       codegendata *cd;
+       s4          dumpsize;
+
+       s = CNEW(u1, COMPILERSTUB_SIZE);
+       
+       /* set data and code pointer */
+       d = (ptrint *)s;
+       s = s + COMPILERSTUB_DATASIZE;
+
+       /* mark start of dump memory area */
+       dumpsize = dump_size();
+       cd = DNEW(codegendata);
+       cd->mcodeptr = s;
+
+       /* Store codeinfo pointer in the same place as in the
+        * methodheader for compiled methods */
+       d[0] = (ptrint) asm_call_jit_compiler;
+       d[1] = (ptrint) m;
+       d[2] = (ptrint) &d[1];          /* fake code->m */
+
+       M_AMOV_IMM(m, REG_ATMP1);
+       M_AMOV_IMM(asm_call_jit_compiler, REG_ATMP3);
+       M_JMP_IMM(asm_call_jit_compiler);
+       M_RET;
+       
+       md_cacheflush((u1 *) d, COMPILERSTUB_SIZE);
+#if defined(ENABLE_STATISTICS)
+       if (opt_stat)
+               count_cstub_len += COMPILERSTUB_SIZE;
+#endif
+
+       /* release dump area */
+       dump_release(dumpsize);
+
+       return s;
+}
index ba209f4f4847a7ea143a4bf8d28314ad7259c504..736707d573cbaf73058851bcef0cffa7c47fed33 100644 (file)
@@ -1,7 +1,379 @@
+/* src/vm/jit/m68k/codegen.h
+
+   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
+   C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
+   E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
+   J. Wenninger, Institut f. Computersprachen - TU Wien
+
+   This file is part of CACAO.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
+
+   $Id: arch.h 5330 2006-09-05 18:43:12Z edwin $
+
+*/
+
+
 #ifndef _CODEGEN_H
 #define _CODEGEN_H
 
-#define PATCHER_CALL_SIZE      1
-#define BRANCH_NOPS            0
+#include "config.h"
+
+#include <stdint.h>
+
+#include "md-abi.h"
+#include "vm/jit/m68k/emit.h"
+
+
+#define MCODECHECK(icnt) \
+    do { \
+        if ((cd->mcodeptr + (icnt) * 4) > cd->mcodeend) \
+            codegen_increase(cd); \
+    } while (0)
+
+
+#define PATCHER_NOPS \
+       do { M_TPFL; M_TPF; M_TPF } while (0);
+
+#define BRANCH_NOPS \
+    do { \
+        if (CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) { \
+           M_NOP; \
+            M_NOP; \
+            M_NOP; \
+        } else { \
+           M_NOP; \
+            M_NOP; \
+        } \
+    } while (0)
+
+
+/* coldfire instruction format:
+ * -----------------------------
+ * | Op Word                    |
+ * |____________________________|
+ * | extension word 1(optional) |
+ * |____________________________|
+ * | extension word 2(optional) |
+ * |____________________________|
+ *
+ *
+ * Opword:
+ *
+ *                     | effective addr
+ *                     |  mode |  reg.
+ * x x x x x x x x x x | M M M | R R R
+ *
+ * MMM = 000 ---> data register   direct: RRR = register
+ * MMM = 001 ---> addr register   direct: RRR = register
+ * MMM = 010 ---> addr register indirect: RRR = register
+ * MMM = 011 ---> addr reg ind postincr : RRR = register
+ * MMM = 100 ---> addr reg ind predecr  : RRR = register
+ * MMM = 101 ---> addr reg ind + displac: RRR = register + ext.wrd.1
+ * MMM = 110 ---> addr reg ind + scaled index and 8 bit displacement
+ * MMM = 111, RRR = 010 ---> PC ind. with displacement + ext.wrd.1
+ * MMM = 111, RRR = 011 ---> PC ind. with scaled inex + 8but displacement
+ * MMM = 111, RRR = 000 + ext.wrd.1 ---> absolute short
+ * MMM = 111, RRR = 001 + ext.wrd.1+2 -> absolute long
+ * MMM = 111, RRR = 100 + ext.wrd1/2 --> immediate data
+ */
+
+/* one word opcodes */
+#define OPWORD(op, mode, reg) \
+       do { \
+               *((u2*)cd->mcodeptr) = (u2) (((op) << 6) | ((mode)<<3) | (reg)); \
+               cd->mcodeptr += 2; \
+       } while(0);
+/* opword + one extension word */
+/* usage of int16_t instead of s2 as is clashes with variable name */
+#define OPWORD_IMM16(op, mode, reg, imm) \
+       do { \
+               *((u2*)cd->mcodeptr) = (u2) (((op) << 6) | ((mode)<<3) | (reg)); \
+               cd->mcodeptr += 2; \
+               *((int16_t*)(cd->mcodeptr)) = imm; \
+               cd->mcodeptr += 2; \
+       } while(0);
+
+/* opword + two extension words */
+/* usage of int32_t instead of s4 as is clashes with variable name */
+#define OPWORD_IMM32(op, mode, reg, imm) \
+       do { \
+               *((u2*)cd->mcodeptr) = (u2) (((op) << 6) | ((mode)<<3) | (reg)); \
+               cd->mcodeptr += 2; \
+               *((int32_t*)(cd->mcodeptr)) = imm; \
+               cd->mcodeptr += 4; \
+       } while(0);
+
+/* create NOPS to align basicblock boundaries 
+ * using real nops here as they are not executed, so no performance penalty
+ **/
+#define ALIGNCODENOP \
+    do { \
+        for (s1 = 0; s1 < (s4) (((ptrint) cd->mcodeptr) & 7); s1++) \
+            M_NOP; \
+    } while (0)
+
+
+
+#define PATCHER_CALL_SIZE      6
+
+#define M_NOP          OPWORD(0x139,6,1)                               /* 0x4371 do not use as it syncs pipeline */
+#define M_ILLEGAL      OPWORD(0x12b,7,4)                               /* 0x4afc */
+#define M_TPF          OPWORD(0x147,7,4)                               /* tfp with no  ext. word use instead of NOP*/
+#define M_TPFW         OPWORD(0x147,7,2)                               /* tfp with one ext. word */
+#define M_TPFL         OPWORD(0x147,7,3)                               /* tfp with two ext. word */
+
+/*M_XMOVX....M_XMOVX(source, destination) */
+#define M_IMOV(a,b)    OPWORD( ( (2<<6) | ((b) << 3) | 0), 0, (a))     /* move.l */
+#define M_AMOV(a,b)    OPWORD( ( (2<<6) | ((b) << 3) | 1), 1, (a))     /* movea.l */
+#define M_IMOV_IMM(a,b)        emit_mov_imm_reg(cd, (a), (b))
+#define M_AMOV_IMM(a,b)        OPWORD_IMM32( ( (2<<6) | ((b) << 3) | 1), 7, 4, (a))
+
+/* for sure generates a 32 bit immedeate form, needed when there are patchers involved */
+#define M_IMOV_IMM32(a,b)      OPWORD_IMM32(((2<<6) | ((b) << 3) | 0), 7, 4, (a))
+
+#define        M_ICLR(a)       OPWORD(0x10a, 0, (a))                           /* clr.l */
+#define M_ISET(a)      OPWORD( ( (0xa <<6) | (0 << 3) | 5), 0, (a))    /* mov3q #-1 */
+
+#define M_JMP(a)       OPWORD(0x13b,2,(a))                             /* jmp %aX@ */
+#define M_JMP_IMM(a)   OPWORD_IMM32(0x13b,7,1,(a))                     /* jmp.l */
+#define M_JSR(a)       OPWORD(0x13a,2,(a))                             /* jsr %aX@ */
+#define M_JSR_IMM(a)   OPWORD_IMM32(0x13a,7,1,(a))                     /* jsr.l */
+#define M_BSR_IMM(a)   OPWORD_IMM32(0x187,7,7,(a))                     /* bsr.l */
+#define M_JSR_PCREL(a) OPWORD_IMM16(0x13a,7,2,(a))                     /* jsr.l (d16,PC) */
+
+#define M_RET          OPWORD(0x139,6,5)                               /* 0x4375 */
+#define M_LINK(a,b)    OPWORD_IMM16(0x139,2,(a), (b))                  /* link */
+#define M_UNLK(a)      OPWORD(0x139, 3, (a))                           /* unlk */
+
+/* push and pop are implemented using move.l */
+/* we need 3 variants, data, address and float registers */
+/* also a POPALL and PUSHALL for verbose:call code, use them only there! */
+#define M_IPUSH(a)             OPWORD(0xbc,0,(a))
+#define M_APUSH(a)             OPWORD(0xbc,1,(a))
+
+#define M_IPOP(a)              OPWORD( ( (2<<6) | ((a) << 3) | 0 ), 3, REG_SP)
+#define M_APOP(a)              OPWORD( ( (2<<6) | ((a) << 3) | 1 ), 3, REG_SP)         /* movea.l acutally */
+
+
+#define M_IPUSH_IMM(a)         OPWORD_IMM32(0x121,7,1, (a))                            /* pea.l */
+
+#define        M_PUSHALL               OPWORD_IMM16(0x123,2,REG_SP,0xFFFF)                     /* A0-A7, D0-D7 pushed onto stack */
+#define M_POPALL               OPWORD_IMM16(0x133,2,REG_SP,0xFFFF)                     /* A0-A7, D0-D7 poped off stack */
+
+/* M_XLD(a,b,c)....M_XLD(destinationreg, addressbase, offset)  */
+#define M_ILD(a,b,c)           OPWORD_IMM16( ( (2<<6) | ((a) << 3) | 0), 5, (b), (c))
+#define M_ALD(a,b,c)           OPWORD_IMM16( ( (2<<6) | ((a) << 3) | 1), 5, (b), (c))
+#define M_LLD(a,b,c)           do {\
+                                       M_ILD(GET_HIGH_REG(a), (b), (c));\
+                                       M_ILD(GET_LOW_REG (a), (b), (c)+4);\
+                               } while(0);
+
+#if !defined(ENABLE_SOFTFLOAT)
+       #define M_FLD(a,b,c)            M_ILLEGAL
+       #define M_DLD(a,b,c)            M_ILLEGAL
+#endif
+
+/* M_XST(a,b,c)....M_XST(sourceregister, addressbase, offset)   */
+#define M_IST(a,b,c)           OPWORD_IMM16( ( (2<<6) | ((b) << 3) | 5), 0, (a), (c))
+#define M_AST(a,b,c)           OPWORD_IMM16( ( (2<<6) | ((b) << 3) | 5), 1, (a), (c))
+#define M_LST(a,b,c)           do      {\
+                                       M_IST(GET_HIGH_REG(a), (b), (c));\
+                                       M_IST(GET_LOW_REG (a), (b), (c)+4);\
+                               } while(0);
 
+#if !defined(ENABLE_SOFTFLOAT)
+       #define M_FST(a,b,c)            M_ILLEGAL
+       #define M_DST(a,b,c)            M_ILLEGAL
 #endif
+
+/*M_XADD_IMM(a,b)...M_XADD_IMM(offset, reg) */
+#define M_AADD_IMM(a,b)                OPWORD_IMM32( ( (0xd<<6) | ((b)<<3) | 7), 7, 4, (a))
+#define M_IADD_IMM(a,b)                OPWORD_IMM32( ( (0xd<<6) | ((b)<<3) | 2), 7, 4, (a))
+#define M_ISUB_IMM(a,b)                M_IADD_IMM(-(a), (b))
+
+/* M_OP(source, dest) ...  dest (OP) source -> dest*/
+#define M_ISUB(a,b)            OPWORD ( ( (9<<6)   | ((b)<<3) | 2), 0, (a))                    /* sub.l */
+#define M_IADD(a,b)            OPWORD ( ( (0xd<<6) | ((b)<<3) | 2), 0, (a))                    /* add.l */
+
+#define M_IMUL(a,b)            OPWORD_IMM16 ( 0x130, 0, (a), ( ((b) << 12) | (1 << 11)))       /* muls.l */
+#define M_IDIV(a,b)            OPWORD_IMM16 ( 0x131, 0, (a), ( ((b) << 12) | (1 << 11) | (b))) /* divs.l */
+
+#define M_ISSL(a,b)            OPWORD ( ( (0xe<<6) | ((a) << 3) | 6), 4, (b))                  /* asl.l */
+#define M_ISSR(a,b)            OPWORD ( ( (0xe<<6) | ((a) << 3) | 2), 4, (b))                  /* asr.l */
+#define M_IUSR(a,b)            OPWORD ( ( (0xe<<6) | ((a) << 3) | 2), 5, (b))                  /* lsr.l */
+
+#define M_IAND(a,b)            OPWORD ( ( (0xc<<6) | ((b) << 3) | 2), 0, (a))                  /* and.l */
+
+#define M_IOR(a,b)             OPWORD ( ( (0x8<<6) | ((b) << 3) | 2), 0, (a))                  /* or.l */
+
+
+/* ultra sepcial 3 register form, b%a = c, (a!=c) */
+#define M_IREM(a,b,c)          OPWORD_IMM16 ( 0x131, 0, (a), ( ((b) << 12) | (1 << 11) | (c))) /* rems.l */
+
+/* M_OP(dest) */
+#define M_INEG(a)              OPWORD(0x112, 0, (a))                                           /* neg.l */
+
+/* only generate opcode when condition true */
+#define OPWORD_COND(c, u,v,w)  \
+       do { \
+               if ( (c) ) { OPWORD( (u),(v),(w) ) }  \
+       } while(0);
+/* assert on the opcode */
+#define OPWORD_ASSERT(a, u,v,w)        \
+       do { \
+               assert((a)); \
+               OPWORD( (u),(v),(w) )  \
+       } while(0);
+
+/* M_XMOVE....M_XMOVE(sourcereg, destreg) */
+#define M_INTMOVE(a,b)         OPWORD_COND(((a) != (b)), ( ( 2<<6) | ((b) << 3) | 0), 0, (a));
+#define M_ADRMOVE(a,b)         OPWORD_COND(((a) != (b)), ( ( 2<<6) | ((b) << 3) | 1), 1, (a));
+#define M_INT2ADRMOVE(a,b)     OPWORD( ( (2<<6) | ((b) << 3) | 1), 0, (a));
+#define M_ADR2INTMOVE(a,b)     OPWORD( ( (2<<6) | ((b) << 3) | 0), 1, (a));
+#define M_LNGMOVE(a,b)         do      {\
+                                       M_INTMOVE(GET_LOW_REG (a), GET_LOW_REG (b));\
+                                       M_INTMOVE(GET_HIGH_REG(a), GET_HIGH_REG(b));\
+                               } while(0);
+
+#if !defined(ENABLE_SOFTLFOAT)
+       #define M_FLTMOVE(a,b)          M_ILLEGAL
+       #define M_DBLMOVE(a,b)          M_ILLEGAL
+#endif
+/* M_XTST....M_XTST(register) */
+#define M_ITST(a)              OPWORD(0x12a, 0, (a))                   /* tst.l */
+#define M_ATST(a)              OPWORD(0x12a, 1, (a))                   /* tst.l */
+
+/* M_XCMPI....M_XMCPI(immideate, register) */
+#define M_ICMP_IMM(a,b)                OPWORD_IMM32( 0x32, 0, (b), (a))
+#if 0
+#define M_ACMPI(a,b)           OPWORD_IMM32( ( (0xb << 6) | ((b) << 3) | 7), 7, 4, (a))        /* cmpa.l # */
+#endif
+/* M_XCMP....M_XCMP(reg1, reg2) */
+#define M_ICMP(b,a)            OPWORD( ( (0xb << 6) | ((a) << 3) | 2), 0, (b))                 /* cmp.l */
+#define M_ACMP(b,a)            OPWORD( ( (0xb << 6) | ((a) << 3) | 7), 1, (b))                 /* cmpa.l */
+
+/* M_AND_IMM(imm, register)    */
+#define M_IAND_IMM(a,b)                OPWORD_IMM32( 0xa, 0, (b), (a))                                 /* andi.l # */
+
+/* All kind of branches one could ever possibly need, each with 16 and 32 bit displacement */
+/* BRANCH16 and BRANCH32 are helpers */
+#define BRANCH8(cond,imm) \
+       do { \
+               *((u2*)cd->mcodeptr) = (u2) (((0x6) << 12) | ((cond)<<8) | (int8_t)imm); \
+               cd->mcodeptr += 2; \
+       } while(0);
+
+#define BRANCH16(cond,imm) \
+       do { \
+               *((u2*)cd->mcodeptr) = (u2) (((0x6) << 12) | ((cond)<<8) | 0x00); \
+               cd->mcodeptr += 2; \
+               *((int16_t*)(cd->mcodeptr)) = imm; \
+               cd->mcodeptr += 2; \
+       } while(0);
+#define BRANCH32(cond,imm) \
+       do { \
+               *((u2*)cd->mcodeptr) = (u2) (((0x6) << 12) | ((cond)<<8) | 0xff); \
+               cd->mcodeptr += 2; \
+               *((int32_t*)(cd->mcodeptr)) = imm; \
+               cd->mcodeptr += 4; \
+       } while(0);
+
+#define M_BR_16(a)                     BRANCH16(0x0, (a))      /* branch always */
+#define M_BR_32(a)                     BRANCH32(0x0, (a))
+
+#define M_BEQ(a)                       BRANCH8 (0x7, (a))
+#define M_BEQ_16(a)                    BRANCH16(0x7, (a))
+#define M_BEQ_32(a)                    BRANCH32(0x7, (a))
+
+#define M_BNE(a)                       BRANCH8 (0x6, (a))
+#define M_BNE_16(a)                    BRANCH16(0x6, (a))
+#define M_BNE_32(a)                    BRANCH32(0x6, (a))
+
+#define M_BLT(a)                       BRANCH8 (0xd, (a))
+#define M_BLT_16(a)                    BRANCH16(0xd, (a))
+#define M_BLT_32(a)                    BRANCH32(0xd, (a))
+
+#define M_BGE(a)                       BRANCH8 (0xc, (a))
+#define M_BGE_16(a)                    BRANCH16(0xc, (a))
+#define M_BGE_32(a)                    BRANCH32(0xc, (a))
+
+#define M_BGT(a)                       BRANCH8 (0xe, (a))
+#define M_BGT_16(a)                    BRANCH16(0xe, (a))
+#define M_BGT_32(a)                    BRANCH32(0xe, (a))
+
+#define M_BLE(a)                       BRANCH8 (0xf, (a))
+#define M_BLE_16(a)                    BRANCH16(0xf, (a))
+#define M_BLE_32(a)                    BRANCH32(0xf, (a))
+
+#define M_BHI(a)                       BRANCH8 (0x2, (a))
+#define M_BHI_16(a)                    BRANCH16(0x2, (a))
+#define M_BHI_32(a)                    BRANCH32(0x2, (a))
+
+#define        M_BMI(a)                        BRANCH8(0xb, (a))
+#define M_BPL(a)                       BRANCH8(0xa, (a))
+
+#define M_BNAN_16(a)                   M_ILLEGAL               /* TODO */
+#define M_BNAN_32(a)                   M_ILLEGAL
+
+/* array store/load stuff */
+/* M_LXXX(baseaddressregister, targetregister) */
+/* M_SXXX(baseaddressregsiter, sourceregister)  */
+#define M_LBZX(a,c)                    OPWORD( ( (1<<6) | ((c) << 3) | 0), 2, (a))     /* move.l */
+#define M_LHZX(a,c)                    OPWORD( ( (3<<6) | ((c) << 3) | 0), 2, (a))
+#define        M_LWZX(a,c)                     OPWORD( ( (2<<6) | ((c) << 3) | 0), 2, (a))
+#define M_LAX(a,c)                     OPWORD( ( (2<<6) | ((c) << 3) | 1), 2, (a))     /* movea.l */
+
+#define M_STBX(a,c)                    OPWORD( ( (1<<6) | ((a) << 3) | 2), 0, (c))     /* move.l */
+#define M_STHX(a,c)                    OPWORD( ( (3<<6) | ((a) << 3) | 2), 0, (c))
+#define M_STWX(a,c)                    OPWORD( ( (2<<6) | ((a) << 3) | 2), 0, (c))
+#define M_STAX(a,c)                    OPWORD( ( (2<<6) | ((a) << 3) | 2), 1, (c))     /* movea.l */
+
+#define M_BSEXT(a,b)                   OPWORD( ( (7<<6) | ((b) << 3) | 4), 0, (a))     /* mvs.b */
+#define M_CZEXT(a,b)                   OPWORD( ( (7<<6) | ((b) << 3) | 7), 0, (a))     /* mvz.w */
+#define M_SSEXT(a,b)                   OPWORD( ( (7<<6) | ((b) << 3) | 5), 0, (a))     /* mvs.w */
+#define M_HSEXT(a,b)                   M_ILLEGAL
+
+/* adds content of integer reg a to address register b, result is b */
+#define M_AADDINT(a,b)                 OPWORD( ( (0xd<<6) | ((b) << 3) | 7), 0, (a))   /* adda.l */
+#define M_ASUBINT(a,b)                 OPWORD( ( (0x9<<6) | ((b) << 3) | 7), 0, (a))   /* suba.l */
+
+/* immideate a shift left int register b, immideate has 3 bits */
+#define M_ISSL_IMM(a,b)                        OPWORD_ASSERT( ((a)<=7), ( (0xe<<6) | ((a) << 3) | 6), 1, (b))  /* lsl */
+#define M_ISSR_IMM(a,b)                        OPWORD_ASSERT( ((a)<=7), ( (0xe<<6) | ((a) << 3) | 2), 0, (b))  /* lsl */
+#define M_IUSR_IMM(a,b)                        OPWORD_ASSERT( ((a)<=7), ( (0xe<<6) | ((a) << 3) | 2), 1, (b))  /* lsl */
+
+
+/* constant handling */
+/* XCONST(constant value, register) */
+#define LCONST(a,b)                    do {\
+                                               M_IMOV_IMM(((uint32_t)(a)), GET_LOW_REG((b)));\
+                                               M_IMOV_IMM(((uint32_t)(a>>32)), GET_HIGH_REG((b)));\
+                                       } while(0);
+
+#if !defined(ENABLE_SOFTFLOAT)
+       #define FCONST(a,b)             M_ILLEGAL
+       #define DCONST(a,b)             M_ILLEGAL
+#endif
+
+#define M_TRAP_SETREGISTER(a)          OPWORD( 0x128, 0, (a))          /* tst.b */
+#define M_TRAP(a) \
+       do { \
+               *((u2*)cd->mcodeptr) = (u2) ( 0x4e40 | (a) ); \
+               cd->mcodeptr += 2; \
+       } while(0);
+
+#endif /* _CODEGEN_H */
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..807ba412813a2fe3c883987925f40bb267950008 100644 (file)
@@ -0,0 +1,686 @@
+/* src/vm/jit/m68k/emit.c
+
+   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
+   C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
+   E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
+   J. Wenninger, Institut f. Computersprachen - TU Wien
+
+   This file is part of CACAO.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
+
+   $Id: arch.h 5330 2006-09-05 18:43:12Z edwin $
+
+*/
+#include "config.h"
+
+#include <assert.h>
+
+#include "emit.h"
+#include "vm/jit/emit-common.h"
+#include "vm/exceptions.h"
+#include "vm/jit/asmpart.h"
+
+#include "vm/builtin.h"
+#include "mm/memory.h"
+
+#include "codegen.h"
+
+/*
+ *     Loads an immededat operand into data register
+ */
+void emit_mov_imm_reg (codegendata *cd, s4 imm, s4 dreg)
+{
+       if ((imm & 0x000000FF) == imm)  {
+               /* use byte form */
+               *((s2*)cd->mcodeptr) = 0x7000 | (dreg << 9) | imm;      /* MOVEQ.L */
+               cd->mcodeptr += 2;
+       } else if ((imm  & 0xFFFF0000) != 0)    {
+               /* use long form */
+               OPWORD( ((2<<6) | (dreg << 3) | 0), 7, 4);
+               *((s4*)cd->mcodeptr) = (s4)imm;
+               cd->mcodeptr += 4;
+       } else {
+               /* use word form */
+               OPWORD( ((3<<6) | (dreg << 3) | 0), 7, 4);
+               *((s2*)cd->mcodeptr) = (s2)imm;
+               cd->mcodeptr += 2;
+       }
+}
+
+/* emit_copy *******************************************************************
+
+   Generates a register/memory to register/memory copy.
+
+*******************************************************************************/
+void emit_copy(jitdata *jd, instruction *iptr, varinfo *src, varinfo *dst)
+{
+       codegendata  *cd;
+       s4            s1, d;
+
+       /* get required compiler data */
+
+       cd = jd->cd;
+
+       if ((src->vv.regoff != dst->vv.regoff) ||
+               (IS_INMEMORY(src->flags ^ dst->flags))) {
+
+               /* If one of the variables resides in memory, we can eliminate
+                  the register move from/to the temporary register with the
+                  order of getting the destination register and the load. */
+
+               if (IS_INMEMORY(src->flags)) {
+                       if (IS_LNG_TYPE(src->type))
+                               d = codegen_reg_of_var(iptr->opc, dst, REG_ITMP12_PACKED);
+                       else
+                               d = codegen_reg_of_var(iptr->opc, dst, REG_IFTMP);
+
+                       s1 = emit_load(jd, iptr, src, d);
+               } else {
+                       if (IS_LNG_TYPE(src->type))
+                               s1 = emit_load(jd, iptr, src, REG_ITMP12_PACKED);
+                       else
+                               s1 = emit_load(jd, iptr, src, REG_IFTMP);
+
+                       d = codegen_reg_of_var(iptr->opc, dst, s1);
+               }
+
+               if (s1 != d) {
+                       switch(src->type)       {
+                               case TYPE_INT: M_INTMOVE(s1, d); break;
+                               case TYPE_ADR: M_ADRMOVE(s1, d); break;
+                               case TYPE_LNG: M_LNGMOVE(s1, d); break;
+#if !defined(ENABLE_SOFTFLOAT)
+                               case TYPE_FLT: M_FLTMOVE(s1, d); break;
+                               case TYPE_DBL: M_DBLMOVE(s1, d); break;
+#else
+                               case TYPE_FLT: M_INTMOVE(s1, d); break;
+                               case TYPE_DBL: M_LNGMOVE(s1, d); break;
+#endif
+                               default: assert(0);
+                       }
+               }
+               emit_store(jd, iptr, dst, d);
+       }
+}
+/* emit_store ******************************************************************
+
+   Emits a possible store of the destination operand.
+
+*******************************************************************************/
+
+inline void emit_store(jitdata *jd, instruction *iptr, varinfo *dst, s4 d)
+{
+       codegendata  *cd;
+
+       /* get required compiler data */
+
+       cd = jd->cd;
+
+       if (IS_INMEMORY(dst->flags)) {
+               COUNT_SPILLS;
+       
+               switch(dst->type)       {
+#if defined(ENABLE_SOFTFLOAT)
+                       case TYPE_DBL:
+#endif
+                       case TYPE_LNG:
+                               M_LST(d, REG_SP, dst->vv.regoff * 4);
+                               break;
+#if defined(ENABLE_SOFTFLOAT)
+                       case TYPE_FLT:
+#endif
+                       case TYPE_INT:
+                               M_IST(d, REG_SP, dst->vv.regoff * 4);
+                               break;
+                       case TYPE_ADR:
+                               M_AST(d, REG_SP, dst->vv.regoff * 4);
+                               break;
+#if !defined(ENABLE_SOFTFLOAT)
+                       case TYPE_DBL:
+                               M_DST(d, REG_SP, dst->vv.regoff * 4);
+                               break;
+                       case TYPE_FLT:
+                               M_FST(d, REG_SP, dst->vv.regoff * 4);
+                               break;
+#endif
+                       default:
+                               assert(0);
+               }
+       }
+}
+/* emit_load *******************************************************************
+
+   Emits a possible load of an operand.
+
+*******************************************************************************/
+s4 emit_load(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
+{
+       codegendata *cd;
+       s4           disp;
+       s4           reg;
+
+       /* get required compiler data */
+
+       cd = jd->cd;
+
+       if (IS_INMEMORY(src->flags)) {
+               COUNT_SPILLS;
+
+               disp = src->vv.regoff * 4;
+       
+               switch (src->type)      {
+#if defined(ENABLE_SOFTFLOAT)
+                       case TYPE_FLT:
+#endif
+                       case TYPE_INT: 
+                               M_ILD(tempreg, REG_SP, disp);
+                               break;
+#if defined(ENABLE_SOFTFLOAT)
+                       case TYPE_DBL:
+#endif
+                       case TYPE_LNG:
+                               M_LLD(tempreg, REG_SP, disp);
+                               break;
+                       case TYPE_ADR:
+                               M_ALD(tempreg, REG_SP, disp);
+                               break;
+#if !defined(ENABLE_SOFTFLOAT)
+                       case TYPE_FLT:
+                               M_FLD(tempreg, REG_SP, disp);
+                               break;
+                       case TYPE_DBL:
+                               M_DLD(tempreg, REG_SP, disp);
+                               break;
+#endif
+                       default: assert(0);
+               }
+               #if 0
+               if (IS_FLT_DBL_TYPE(src->type)) {
+                       if (IS_2_WORD_TYPE(src->type)) {
+                               M_DLD(tempreg, REG_SP, disp);
+                        } else {
+                               M_FLD(tempreg, REG_SP, disp);
+                       }
+               } else {
+                       if (IS_2_WORD_TYPE(src->type)) {
+                               M_LLD(tempreg, REG_SP, disp);
+                       } else {
+                               M_ILD(tempreg, REG_SP, disp);
+                       }
+               }
+               #endif
+
+               reg = tempreg;
+       }
+       else
+               reg = src->vv.regoff;
+
+       return reg;
+}
+
+
+/* emit_patcher_stubs **********************************************************
+
+   Generates the code for the patcher stubs.
+
+*******************************************************************************/
+void emit_patcher_stubs(jitdata *jd)
+{
+       codegendata *cd;
+       patchref    *pref;
+       u8           mcode;
+       u1          *savedmcodeptr;
+       u1          *tmpmcodeptr;
+       s4           targetdisp;
+       s4           disp;
+
+       /* get required compiler data */
+
+       cd = jd->cd;
+
+       /* generate code patching stub call code */
+
+       targetdisp = 0;
+
+       for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
+               /* check code segment size */
+
+               MCODECHECK(512);
+
+               /* Get machine code which is patched back in later. A
+                  `bsr.l' is 6 bytes long. */
+
+               savedmcodeptr = cd->mcodebase + pref->branchpos;
+               mcode = *((u8 *) savedmcodeptr);
+
+               /* patch in `bsr.l' to call the following code */
+
+               tmpmcodeptr  = cd->mcodeptr;    /* save current mcodeptr              */
+               cd->mcodeptr = savedmcodeptr;   /* set mcodeptr to patch position     */
+
+               M_BSR_IMM(tmpmcodeptr - (savedmcodeptr + PATCHER_CALL_SIZE) + 4);
+
+               cd->mcodeptr = tmpmcodeptr;     /* restore the current mcodeptr       */
+
+               /* save REG_ITMP3 */
+               M_IPUSH(REG_ITMP3);     /* FIXME why, and restore where ? */
+
+               /* move pointer to java_objectheader onto stack */
+
+#if defined(ENABLE_THREADS)
+               (void) dseg_add_unique_address(cd, NULL);                  /* flcword */
+               (void) dseg_add_unique_address(cd, lock_get_initial_lock_word());
+               disp = dseg_add_unique_address(cd, NULL);                  /* vftbl   */
+
+               assert(0); /* The next lines are wrong */
+               M_MOV_IMM(0, REG_ITMP3);
+               dseg_adddata(cd);
+               M_AADD_IMM(REG_ITMP3, disp);
+               M_IPUSH(REG_ITMP3);
+#else
+               M_IPUSH_IMM(0);
+#endif
+
+               /* push move machine code bytes and classinfo pointer */
+
+               M_IPUSH_IMM(mcode >> 32);
+               M_IPUSH_IMM(mcode);
+               M_IPUSH_IMM(pref->ref);
+               M_IPUSH_IMM(pref->patcher);
+
+               M_JMP_IMM(asm_patcher_wrapper);
+       }
+}
+s4 emit_load_low(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg) 
+{
+       codegendata  *cd;
+       s4            disp;
+       s4            reg;
+
+       assert(src->type == TYPE_LNG);
+
+       /* get required compiler data */
+       cd = jd->cd;
+
+       if (IS_INMEMORY(src->flags)) {
+               COUNT_SPILLS;
+
+               disp = src->vv.regoff * 4;
+               M_ILD(tempreg, REG_SP, disp + 4);
+               reg = tempreg;
+       } else {
+               reg = GET_LOW_REG(src->vv.regoff);
+       }
+       return reg;
+}
+s4 emit_load_high(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
+{
+       codegendata  *cd;
+       s4            disp;
+       s4            reg;
+
+       assert(src->type == TYPE_LNG);
+
+       /* get required compiler data */
+       cd = jd->cd;
+
+       if (IS_INMEMORY(src->flags)) {
+               COUNT_SPILLS;
+               disp = src->vv.regoff * 4;
+               M_ILD(tempreg, REG_SP, disp);
+               reg = tempreg;
+       } else {
+               reg = GET_HIGH_REG(src->vv.regoff);
+       }
+       return reg;
+}
+/* emit_branch *****************************************************************
+
+   Emits the code for conditional and unconditional branchs.
+
+*******************************************************************************/
+void emit_branch(codegendata *cd, s4 disp, s4 condition, s4 reg, u4 opt) 
+{ 
+       /* calculate the different displacements */
+       /* PC is a at branch instruction + 2 */
+       /* coditional and uncondition branching work the same way */
+       /* short branches have signed 16 bit offset */
+       /* long branches are signed 32 bit */
+       /* the 8 bit offset branching instructions are not used */
+
+       disp  =  disp - 2;
+
+       /* check displacement for overflow */
+       if ((disp & 0x0000FFFF) != disp)        {
+               if (!CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
+                       cd->flags |= (CODEGENDATA_FLAG_ERROR | CODEGENDATA_FLAG_LONGBRANCHES);
+               }
+       }
+
+       /* check which branch to generate */
+
+       if (condition == BRANCH_UNCONDITIONAL) {
+               if (CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd))      {
+                       M_BR_32(disp);
+               } else  {
+                       M_BR_16(disp);
+               }
+       } else {
+               if (CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
+                       switch (condition) {
+                       case BRANCH_EQ:
+                               M_BEQ_32(disp);
+                               break;
+                       case BRANCH_NE:
+                               M_BNE_32(disp);
+                               break;
+                       case BRANCH_LT:
+                               M_BLT_32(disp);
+                               break;
+                       case BRANCH_GE:
+                               M_BGE_32(disp);
+                               break;
+                       case BRANCH_GT:
+                               M_BGT_32(disp);
+                               break;
+                       case BRANCH_LE:
+                               M_BLE_32(disp);
+                               break;
+                       case BRANCH_NAN:
+                               M_BNAN_32(disp);
+                               break;
+                       case BRANCH_UGT:
+                               M_BHI_32(disp);
+                               break;
+
+                       default:
+                               vm_abort("emit_branch: unknown condition %d", condition);
+                       }
+               } else {
+                       switch (condition) {
+                       case BRANCH_EQ:
+                               M_BEQ_16(disp);
+                               break;
+                       case BRANCH_NE:
+                               M_BNE_16(disp);
+                               break;
+                       case BRANCH_LT:
+                               M_BLT_16(disp);
+                               break;
+                       case BRANCH_GE:
+                               M_BGE_16(disp);
+                               break;
+                       case BRANCH_GT:
+                               M_BGT_16(disp);
+                               break;
+                       case BRANCH_LE:
+                               M_BLE_16(disp);
+                               break;
+                       case BRANCH_NAN:
+                               M_BNAN_16(disp);
+                               break;
+                       case BRANCH_UGT:
+                               M_BHI_16(disp);
+                               break;
+                       default:
+                               vm_abort("emit_branch: unknown condition %d", condition);
+                       }
+               }
+       }
+}
+
+
+#if !defined(NDEBUG)
+/*
+ *     Trace functions. Implement -verbose:call flag
+ *     code marked by real NOP, but performance is no matter when using -verbose:call :)
+ */
+void emit_verbosecall_enter(jitdata* jd) 
+{ 
+       methodinfo   *m;
+       codegendata  *cd;
+       registerdata *rd;
+       methoddesc   *md;
+       s4      disp,i,t;
+
+
+       if (!JITDATA_HAS_FLAG_VERBOSECALL(jd))
+               return;
+       
+       /* get required compiler data */
+       m  = jd->m;
+       cd = jd->cd;
+       rd = jd->rd;
+       md = m->parseddesc;
+
+       /* mark trace code */
+       M_NOP;
+
+       M_LINK(REG_FP, -16*4);  
+       M_PUSHALL;
+
+       /* builtin_verbosecall_enter takes all args as s8 type */
+       /* TRACE_ARGS_NUM is the number of args the builtin_verbosecall_enter expects */
+       M_IPUSH_IMM(m);
+       
+       disp = 16*4 + 4 + 4;    /* points to old argument stack initially */
+
+       /* travel up stack to the first argument of the function which needs to be copied */
+       for (i=0; (i < md->paramcount) && (i < TRACE_ARGS_NUM); i++)    {
+               disp += 4;
+               if (IS_2_WORD_TYPE(md->paramtypes[i].type)) {   
+                       disp += 4;
+               }
+       }
+
+       /* disp now points to the first arg which gets copied to the trace stack, relative to REG_SP! */
+       for (i=TRACE_ARGS_NUM-1; i>=0; --i) {
+               if (i < md->paramcount) {
+                       /* traced function has such an argument */
+                       t = md->paramtypes[i].type;
+                       
+                       if (IS_2_WORD_TYPE(t))  {
+                               /* copy from original argument stack */
+                               M_ILD(REG_ITMP1, REG_SP, disp);
+                               M_IPUSH(REG_ITMP1);
+                               M_ILD(REG_ITMP1, REG_SP, disp);
+                               M_IPUSH(REG_ITMP1);
+                       } else  {
+                               /* displacment is increased as 4 byte on original stack but 8 byte on trace stack */
+                               M_ILD(REG_ITMP1, REG_SP, disp);
+                               M_IPUSH(REG_ITMP1);
+                               M_IPUSH_IMM(0);
+                               disp += 4;
+                       }
+               } else  {
+                       /* function has no arg here, push nothing and adapt displacement */
+                       M_IPUSH_IMM(0);
+                       M_IPUSH_IMM(0);
+                       disp += 8;
+               }
+       }
+       M_JSR_IMM(builtin_verbosecall_enter);
+       /* pop arguments off stack */
+       M_AADD_IMM(TRACE_ARGS_NUM*8+4, REG_SP);
+
+       M_POPALL;
+       M_UNLK(REG_FP);
+       M_NOP;
+}
+void emit_verbosecall_exit(jitdata* jd) 
+{ 
+       methodinfo   *m;
+       codegendata  *cd;
+       registerdata *rd;
+       methoddesc   *md;
+
+       if (!JITDATA_HAS_FLAG_VERBOSECALL(jd))
+               return;
+
+       /* get required compiler data */
+       m  = jd->m;
+       cd = jd->cd;
+       rd = jd->rd;
+       md = m->parseddesc;
+
+       /* void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m); */
+
+
+       /* mark trace code */
+       M_NOP;
+       M_LINK(REG_FP, 0);
+
+       M_IPUSH_IMM(m);                                 /* push methodinfo */
+
+       M_IPUSH_IMM(0);                                 /* TODO push float result */
+
+       M_IPUSH_IMM(0);                                 /* TODO push double result */
+       M_IPUSH_IMM(0);                                 /* TODO push double result */
+
+       M_IPUSH(GET_HIGH_REG(REG_RESULT_PACKED))
+       M_IPUSH(GET_LOW_REG(REG_RESULT_PACKED))         /* push long result */
+
+
+       M_JSR_IMM(builtin_verbosecall_exit);
+
+       /* poping result registers from stack */
+       M_IPOP(GET_LOW_REG(REG_RESULT_PACKED))
+       M_IPOP(GET_HIGH_REG(REG_RESULT_PACKED))
+
+#if 0
+       /* that is wrong of course, overwrites registers and stuff */
+       M_IPOP(0);      /* TODO: pop double result */
+       M_IPOP(0);      /* TODO: pop double result */
+
+       M_IPOP(0);      /* TODO: pop float result */
+#else
+       M_AADD_IMM(3*4, REG_SP);
+#endif
+       M_AADD_IMM(4, REG_SP);                          /* remove rest of stack */
+       M_UNLK(REG_FP);
+       M_NOP;
+}
+#endif
+
+/* emit_classcast_check ********************************************************
+
+   Emit a ClassCastException check.
+
+*******************************************************************************/
+
+void emit_classcast_check(codegendata *cd, instruction *iptr, s4 condition, s4 reg, s4 s1)
+{
+       if (INSTRUCTION_MUST_CHECK(iptr)) {
+               switch (condition) {
+               case BRANCH_LE:
+                       M_BGT(4);
+                       break;
+               case BRANCH_EQ:
+                       M_BNE(4);
+                       break;
+               case BRANCH_GT:
+                       M_BLE(4);
+                       break;
+               case BRANCH_UGT:
+                       M_BHI(4);
+                       break;
+               default:
+                       vm_abort("emit_classcast_check: unknown condition %d", condition);
+               }
+               M_TRAP_SETREGISTER(s1);
+               M_TRAP(EXCEPTION_HARDWARE_CLASSCAST);
+       }
+}
+
+/* emit_arrayindexoutofbounds_check ********************************************
+
+   Emit a ArrayIndexOutOfBoundsException check.
+
+*******************************************************************************/
+void emit_arrayindexoutofbounds_check(codegendata *cd, instruction *iptr, s4 s1, s4 s2)
+{
+       if (INSTRUCTION_MUST_CHECK(iptr)) {
+               M_ILD(REG_ITMP3, s1, OFFSET(java_arrayheader, size));
+               M_ICMP(REG_ITMP3, s2);
+               M_BLT(2);
+               /*M_ALD_INTERN(s2, REG_ZERO, EXCEPTION_LOAD_DISP_ARRAYINDEXOUTOFBOUNDS);*/
+               M_ILLEGAL; /*FIXME */
+       }
+}
+
+/* emit_nullpointer_check ******************************************************
+
+   Emit a NullPointerException check.
+
+*******************************************************************************/
+void emit_nullpointer_check(codegendata *cd, instruction *iptr, s4 reg)
+{
+       if (INSTRUCTION_MUST_CHECK(iptr)) {
+               /* did like to assert on TYPE_ADR, but not possible in here */
+               /* so assert before each emit_nullpointer_check */
+               M_ATST(reg);
+               M_BNE(2);
+               /*M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_LOAD_DISP_NULLPOINTER);*/
+               M_ILLEGAL;
+       }
+}
+
+/* emit_arithmetic_check *******************************************************
+
+   Emit an ArithmeticException check.
+
+*******************************************************************************/
+
+void emit_arithmetic_check(codegendata *cd, instruction *iptr, s4 reg)
+{
+       if (INSTRUCTION_MUST_CHECK(iptr)) {
+               M_ITST(reg);
+               M_BNE(2);
+               /*M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_ARITHMETIC);*/
+               M_ILLEGAL; /* FIXME */
+       }
+}
+
+/* emit_exception_check_areg **************************************************
+ *
+   Emit an Exception check, tested register is address REG_RESULT
+
+*******************************************************************************/
+void emit_exception_check_areg(codegendata *cd, instruction *iptr)
+{
+       if (INSTRUCTION_MUST_CHECK(iptr)) {
+               M_ATST(REG_RESULT);
+               M_BNE(2);
+               /*M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_EXCEPTION);*/
+               M_ILLEGAL; /*FIXME*/
+       }
+}
+/* emit_exception_check_ireg **************************************************
+
+   Emit an Exception check. Teste register is integer REG_RESULT
+
+*******************************************************************************/
+void emit_exception_check_ireg(codegendata *cd, instruction *iptr)
+{
+       if (INSTRUCTION_MUST_CHECK(iptr)) {
+               M_ITST(REG_RESULT);
+               M_BNE(2);
+               /*M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_EXCEPTION);*/
+               M_ILLEGAL; /*FIXME*/
+       }
+}
+
index d920d138d30306b702d48a2cfd78a4ba0cb6bf30..7d939407eeab88afeb08fd7f8858af4bf38e7c74 100644 (file)
@@ -1,15 +1,50 @@
+/* src/vm/jit/m68k/machine-instr.h  
+
+   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
+   C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
+   E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
+   J. Wenninger, Institut f. Computersprachen - TU Wien
+
+   This file is part of CACAO.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
+
+   $Id: arch.h 5330 2006-09-05 18:43:12Z edwin $
+
+*/
+
+
 #ifndef _MACHINE_INSTR_H
 #define _MACHINE_INSTR_H
 
 static inline long compare_and_swap(long *p, long oldval, long newval)
 {
-       assert(0);
-       return 0;
+       /* XXX, coldifre has no atomic compare and swap instrcution */
+       #warning "compare_and_swap is not atmically"
+       if (*p == oldval)       {
+               *p = newval;
+               return oldval;
+       } 
+       return *p;
 }
 
-#define STORE_ORDER_BARRIER()                          assert(0);
-#define MEMORY_BARRIER_BEFORE_ATOMIC()                 assert(0); 
-#define MEMORY_BARRIER_AFTER_ATOMIC()                  assert(0);
-#define MEMORY_BARRIER()                               assert(0);
+
+#define STORE_ORDER_BARRIER() __asm__ __volatile__ ("" : : : "memory");
+#define MEMORY_BARRIER_BEFORE_ATOMIC() __asm__ __volatile__ ("" : : : "memory");
+#define MEMORY_BARRIER_AFTER_ATOMIC() __asm__ __volatile__ ("" : : : "memory");
+#define MEMORY_BARRIER() __asm__ __volatile__ ( "" : : : "memory" );
 
 #endif
index 43bbdb1337f0215d8c7972e828daf7843bdb98e5..4214fad1b1668b5f78a1350a0ad268ec49c6dab0 100644 (file)
-void md_init(void) {}
+/*     src/vm/jit/m68k/md.c
 
-void md_get_method_patch_address(void) {}
-void md_icacheflush(void) {}
-void md_stacktrace_get_returnaddress(void) {}
-void md_codegen_get_pv_from_pc(void) {}
-void md_signal_handler_sigsegv(void) {}
-void md_codegen_patch_branch(void) {}
-void md_cacheflush(void) {}
-void md_param_alloc(void) {}
-void md_return_alloc(void) {}
+   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
+   C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
+   E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
+   J. Wenninger, Institut f. Computersprachen - TU Wien
 
+   This file is part of CACAO.
 
-int nregdescint;
-int nregdescfloat;
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
+
+   $Id: arch.h 5330 2006-09-05 18:43:12Z edwin $
+
+*/
+#include "config.h"
+
+#include <assert.h>
+
+#include "md-os.h"
+
+#include "vm/types.h"
+#include "vm/jit/codegen-common.h"
+#include "vm/jit/md.h"
+
+#include "offsets.h"
+#include "vm/vm.h"
+#include "vmcore/class.h"
+#include "vmcore/linker.h"
+#include "vmcore/method.h"
+#include "mm/memory.h"
+#include "vm/jit/asmpart.h"
+/*
+ *     As a sanity measuremnt we assert the offset.h values in here as m68k gets
+ *     crosscompiled for sure and noone thinks of offset.h wen changing compile flags
+ *     and subtile bugs will result...
+ *
+ *     m68k uses the trap instruction for hardware exceptions, need to register
+ *     according signal handler
+ */
+void md_init(void) 
+{
+       assert(sizeof(vm_arg) == sizevmarg);
+       assert(OFFSET(java_objectheader, vftbl) == offobjvftbl);
+       assert(OFFSET(vftbl_t, baseval) == offbaseval);
+       assert(OFFSET(vftbl_t, diffval) == offdiffval);
+       assert(OFFSET(vm_arg, type) == offvmargtype);
+       assert(OFFSET(vm_arg, data) == offvmargdata);
+       assert(OFFSET(castinfo, super_baseval) == offcast_super_baseval);
+       assert(OFFSET(castinfo, super_diffval) == offcast_super_diffval);
+       assert(OFFSET(castinfo, sub_baseval) == offcast_sub_baseval);
+
+#if defined(ENABLE_REPLACEMENT)
+       assert(sizeof(executionstate_t) = sizeexecutionstate);
+       assert(OFFSET(executionstate_t, pc) == offes_pc);
+       assert(OFFSET(executionstate_t, sp) == offes_sp);
+       assert(OFFSET(executionstate_t, pv) == offes_pv);
+       assert(OFFSET(executionstate_t, intregs) == offes_intregs);
+       assert(OFFSET(executionstate_t, fltregs) == offes_fltregs);
+#endif
+
+#ifdef __LINUX__
+       md_init_linux();
+#endif
+}
+
+/* md_codegen_get_pv_from_pc ***************************************************
+
+   On this architecture just a wrapper function to
+   codegen_get_pv_from_pc.
+
+*******************************************************************************/
+u1* md_codegen_get_pv_from_pc(u1 *ra) 
+{ 
+       u1 *pv;
+       pv = codegen_get_pv_from_pc(ra);
+
+       return pv;
+}
+
+/* md_get_method_patch_address *************************************************
+   Gets the patch address of the currently compiled method. Has to be 
+   extracted from the load instructions which lead to the jump.
+
+from asmpart.S (asm_vm_call_method):
+84:   2879 0000 0000  moveal 0 <asm_vm_call_method-0x34>,%a4
+8a:   4e94            jsr %a4@
+
+
+from invokestatic / invokespecial
+0x40290882:   247c 4029 03b4    moveal #1076429748,%a2
+0x40290888:   4e92              jsr %a2@
+
+from invokevirtual
+0x40297eca:   266a 0000         moveal %a2@(0),%a3
+0x40297ece:   246b 002c         moveal %a3@(44),%a2
+0x40297ed2:   4e92              jsr %a2@
+
+
+
+*******************************************************************************/
+
+u1* md_get_method_patch_address(u1 *ra, stackframeinfo *sfi, u1 *mptr) 
+{
+       u1 * pa;
+       s2   offset;
+
+       if (*((u2*)(ra - 2)) == 0x4e94) {               /* jsr %a4@ */
+               /* we had a moveal XXX, %a3 which is a 3 word opcode */
+               /* 2679 0000 0000 */
+               assert(*(u2*)(ra - 8) == 0x2879);               /* moveal */
+               pa = *((u4*)(ra - 6));                          /* another indirection ! */
+       } else if (*((u2*)(ra - 2)) == 0x4e92)  {               /* jsr %a2@ */
+               if (*(u2*)(ra - 8) == 0x247c)   {
+                       /* found a invokestatic/invokespecial */
+                       pa = ((u4*)(ra - 6));                   /* no indirection ! */
+               } else if (*((u2*)(ra - 6)) == 0x246b)  {
+                       /* found an invokevirtual */
+                       /* get offset of load instruction 246b XXXX */
+                       offset = *((s2*)(ra - 4));
+                       pa = mptr + offset;                     /* mptr contains the magic we want */
+               } else  {
+                       assert(0);
+               }
+       } else {
+               assert(0);
+       }
+
+       return pa;
+}
+
+/* XXX i can't find a definition of cacheflush in any installed header files but i can find the symbol in libc */
+/* lets extract the signature from the assembler code*/
+/*
+    000e7158 <cacheflush>:
+    e7158:       707b            moveq #123,%d0
+    e715a:       2f04            movel %d4,%sp@-
+    e715c:       282f 0014       movel %sp@(20),%d4                    arg 
+    e7160:       2243            moveal %d3,%a1
+    e7162:       262f 0010       movel %sp@(16),%d3                    arg 
+    e7166:       2042            moveal %d2,%a0
+    e7168:       242f 000c       movel %sp@(12),%d2                    arg 
+    e716c:       222f 0008       movel %sp@(8),%d1                     arg 
+    e7170:       4e40            trap #0                               traps into system i guess
+    e7172:       2408            movel %a0,%d2
+    e7174:       2609            movel %a1,%d3
+    e7176:       281f            movel %sp@+,%d4
+    e7178:       223c ffff f001  movel #-4095,%d1
+    e717e:       b081            cmpl %d1,%d0
+    e7180:       6402            bccs e7184 <cacheflush+0x2c>
+    e7182:       4e75            rts
+    e7184:       4480            negl %d0
+    e7186:       2f00            movel %d0,%sp@-
+    e7188:       61ff fff3 82e2  bsrl 1f46c <D_MAX_EXP+0x1ec6d>
+    e718e:       209f            movel %sp@+,%a0@
+    e7190:       70ff            moveq #-1,%d0
+    e7192:       2040            moveal %d0,%a0
+    e7194:       4e75            rts
+    e7196:       4e75            rts
+                                                                       */
+
+/* seems to have 4 arguments */
+/* best guess: it is this syscall */
+/* asmlinkage int sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len) */
+/* kernel 2.6.10 with freescale patches (the one I develop against) needs a patch of */
+/* arch/m68k/kernel/sys_m68k.c(sys_cacheflush) */
+/* evil hack: */
+/*
+void DcacheFlushInvalidateCacheBlock(void *start, unsigned long size);
+void IcacheInvalidateCacheBlock(void *start, unsigned long size);
+
+asmlinkage int
+sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
+{
+       lock_kernel();
+       DcacheFlushInvalidateCacheBlock(addr, len);
+       IcacheInvalidateCacheBlock(addr, len);
+       unlock_kernel();
+       return 0;
+}
+*/
+extern int cacheflush(unsigned long addr, int scope, int cache, unsigned long len);
+
+#include "asm/cachectl.h"      /* found more traces of the cacheflush function */
+#include "errno.h"
+
+void md_cacheflush(u1 *addr, s4 nbytes)  { cacheflush(addr, FLUSH_SCOPE_PAGE, FLUSH_CACHE_BOTH, nbytes); }
+void md_dcacheflush(u1 *addr, s4 nbytes) { cacheflush(addr, FLUSH_SCOPE_PAGE, FLUSH_CACHE_DATA, nbytes); }
+void md_icacheflush(u1* addr, s4 nbytes) { cacheflush(addr, FLUSH_SCOPE_LINE, FLUSH_CACHE_INSN, nbytes); }
+
+/* md_stacktrace_get_returnaddress *********************************************
+
+   Returns the return address of the current stackframe, specified by
+   the passed stack pointer and the stack frame size.
+
+*******************************************************************************/
+u1* md_stacktrace_get_returnaddress(u1* sp, u4 framesize) 
+{ 
+       /* return address is above stackpointer */
+       u1 *ra = *((u1**)(sp + framesize));
+       return ra;
+}
+
+
+void md_codegen_patch_branch(void) { assert(0); }
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..8e00d734fc9a1441d973aa162711769cc3f26238 100644 (file)
@@ -0,0 +1,694 @@
+/* src/vm/jit/m68k/patcher.c - m68k patcher functions
+
+   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
+   C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
+   E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
+   J. Wenninger, Institut f. Computersprachen - TU Wien
+
+   This file is part of CACAO.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
+
+   $Id: arch.h 5330 2006-09-05 18:43:12Z edwin $
+
+*/
+
+#include "config.h"
+
+#include <assert.h>
+
+#include "vm/types.h"
+
+#include "mm/memory.h"
+#include "native/native.h"
+
+#include "vm/builtin.h"
+#include "vm/exceptions.h"
+#include "vm/initialize.h"
+#include "vm/resolve.h"
+
+#include "vm/jit/asmpart.h"
+#include "vm/jit/patcher.h"
+#include "vm/jit/md.h"
+#include "vm/jit/methodheader.h"
+#include "vm/jit/stacktrace.h"
+
+#include "vmcore/class.h"
+#include "vmcore/field.h"
+#include "vmcore/options.h"
+#include "vmcore/references.h"
+
+#include "codegen.h"
+
+/* patcher_wrapper *************************************************************
+
+   Wrapper for all patchers.  It also creates the stackframe info
+   structure.
+
+   If the return value of the patcher function is false, it gets the
+   exception object, clears the exception pointer and returns the
+   exception.
+
+*******************************************************************************/
+
+java_objectheader *patcher_wrapper(u1 *sp, u1 *pv, u1 *ra)
+{
+       stackframeinfo     sfi;
+       u1                *xpc;
+       java_objectheader *o;
+       functionptr        f;
+       bool               result;
+       java_objectheader *e;
+       u4                 mcode, xmcode;
+
+       /* define the patcher function */
+
+       bool (*patcher_function)(u1 *);
+
+       /* get stuff from the stack */
+
+       xpc = (u1 *)                *((ptrint *) (sp + 6 * 4));
+       /* REG_ITMP3                              sp + 5 * 4 */
+       o   = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
+       mcode =                     *((u4*)      (sp + 3 * 4));
+       xmcode =                    *((u4*)      (sp + 2 * 4));
+       /* unresolved file                        sp + 1 * 4 */
+       f   = (functionptr)         *((ptrint *) (sp + 0 * 4));
+
+
+       /* calculate and set the new return address */
+
+       xpc = xpc - PATCHER_CALL_SIZE;
+       *((ptrint *) (sp + 6 * 4)) = (ptrint) xpc;
+
+       /* patch back original code */
+
+       *((u4*)(xpc))   = mcode;
+       *((u4*)(xpc+4)) = xmcode;
+       md_icacheflush(xpc, 8);
+
+       /* cast the passed function to a patcher function */
+
+       patcher_function = (bool (*)(u1 *)) (ptrint) f;
+
+       /* enter a monitor on the patching position */
+
+       PATCHER_MONITORENTER;
+
+       /* create the stackframeinfo */
+
+       /* RA is passed as NULL, but the XPC is correct and can be used in
+          stacktrace_create_extern_stackframeinfo for
+          md_codegen_get_pv_from_pc. */
+
+       stacktrace_create_extern_stackframeinfo(&sfi, pv, sp + 7 * 4, xpc, xpc);
+
+       /* call the proper patcher function */
+
+       result = (patcher_function)(sp);
+
+       /* remove the stackframeinfo */
+
+       stacktrace_remove_stackframeinfo(&sfi);
+
+       /* check for return value and exit accordingly */
+
+       if (result == false) {
+               e = exceptions_get_and_clear_exception();
+
+               PATCHER_MONITOREXIT;
+
+               return e;
+       }
+       PATCHER_MARK_PATCHED_MONITOREXIT;
+
+       return NULL;
+}
+
+/* patcher_initialize_class ****************************************************
+
+   Initalizes a given classinfo pointer.  This function does not patch
+   any data.
+
+*******************************************************************************/
+
+bool patcher_initialize_class(u1 *sp)
+{
+       classinfo *c;
+
+       /* get stuff from the stack */
+
+       c = (classinfo *) *((ptrint *) (sp + 1 * 4));
+
+       /* check if the class is initialized */
+
+       if (!(c->state & CLASS_INITIALIZED))
+               if (!initialize_class(c))
+                       return false;
+
+       return true;
+}
+
+/* patcher_invokevirtual *******************************************************
+
+   Machine code:
+0x4029bc46:   61ff 0000 00ba    bsrl 0x4029bd02
+0x4029bc4c:   246f 0000         moveal %sp@(0),%a2
+0x4029bc50:   266a 0000         moveal %a2@(0),%a3
+0x4029bc54:   246b 0000         moveal %a3@(0),%a2     <-- patch this (0) offset
+0x4029bc58:   4e92              jsr %a2@
+
+*******************************************************************************/
+
+bool patcher_invokevirtual(u1 *sp)
+{
+       u1                *ra;
+       unresolved_method *um;
+       methodinfo        *m;
+       s2                 disp;
+
+       /* get stuff from the stack */
+       ra = (u1 *)                *((ptrint *) (sp + 6 * 4));
+       um = (unresolved_method *) *((ptrint *) (sp + 1 * 4));
+
+       /* get the fieldinfo */
+       if (!(m = resolve_method_eager(um)))
+               return false;
+
+       /* if we show NOPs, we have to skip them */
+       if (opt_shownops) ra += PATCHER_CALL_SIZE;
+
+       assert( *((u2*)(ra+8)) == 0x246b);
+
+       /* patch vftbl index */
+       disp = (OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex);
+       *((s2 *) (ra + 10)) = disp;
+
+       /* synchronize instruction cache */
+       md_icacheflush(ra + 10, 2);
+
+       return true;
+}
+
+/* patcher_invokestatic_special ************************************************
+
+   Machine code:
+
+   INVOKESPECIAL
+0x402902bc:   61ff 0000 0076    bsrl 0x40290334
+0x402902c2:   247c 0000 0000    moveal #0,%a2          <-- this #0
+0x402902c8:   4e92              jsr %a2@
+
+******************************************************************************/
+
+bool patcher_invokestatic_special(u1 *sp)
+{
+       unresolved_method *um;
+       s4                 disp;
+       methodinfo        *m;
+
+       /* get stuff from the stack */
+
+       disp =                       *((s4 *)     (sp + 6 * 4));
+       um   = (unresolved_method *) *((ptrint *) (sp + 1 * 4));
+
+       /* get the fieldinfo */
+
+       if (!(m = resolve_method_eager(um)))
+               return false;
+
+       /* patch stubroutine */
+
+       if (opt_shownops) disp += PATCHER_CALL_SIZE;
+
+       *((ptrint *) (disp+2)) = (ptrint) m->stubroutine;
+
+       /* synchronize inst cache */
+
+       md_icacheflush(disp+2, SIZEOF_VOID_P);
+
+       return true;
+}
+
+
+/* patcher_resolve_class *******************************************************
+
+   Resolves a given unresolved_class pointer.  This function does not
+   patch any data.
+
+*******************************************************************************/
+
+#ifdef ENABLE_VERIFIER
+bool patcher_resolve_class(u1 *sp)
+{
+       unresolved_class *uc;
+       classinfo        *c;
+
+       /* get stuff from the stack */
+
+       uc = (unresolved_class *) *((ptrint *) (sp + 2 * 4));
+
+       /* resolve the class */
+       assert(0);
+
+       if (!resolve_class(uc, resolveEager, false, &c))
+               return false;
+
+       return true;
+}
+#endif /* ENABLE_VERIFIER */
+
+/* patcher_resolve_classref_to_classinfo ***************************************
+  ACONST:
+       0x4028f2ca:   2479 0000 0000    moveal 0x00000000,%a2
+*******************************************************************************/
+bool patcher_resolve_classref_to_classinfo(u1 *sp)
+{
+       constant_classref *cr;
+       s4                 disp;
+       u1                *pv;
+       classinfo         *c;
+
+       /* get stuff from the stack */
+
+       cr   = (constant_classref *) *((ptrint *) (sp + 1 * 4));
+       disp =                       *((s4 *)     (sp + 6 * 4));
+
+       /* get the classinfo */
+
+       if (!(c = resolve_classref_eager(cr)))
+               return false;
+
+       /* patch the classinfo pointer */
+
+       if (opt_shownops) disp += PATCHER_CALL_SIZE;
+
+       *((ptrint *) (disp+2)) = (ptrint) c;
+
+       /* synchronize inst cache */
+
+       md_icacheflush(disp+2, SIZEOF_VOID_P);
+
+       return true;
+}
+
+/* patcher_get_putstatic *******************************************************
+
+   Machine code:
+
+*******************************************************************************/
+
+bool patcher_get_putstatic(u1 *sp)
+{
+       u1               *ra;
+       u4                mcode;
+       unresolved_field *uf;
+       s4                disp;
+       u1               *pv;
+       fieldinfo        *fi;
+
+       /* get stuff from the stack */
+
+       ra    = (u1 *)                *((ptrint *) (sp + 5 * 4));
+       mcode =                       *((u4 *)     (sp + 3 * 4));
+       uf    = (unresolved_field *)  *((ptrint *) (sp + 2 * 4));
+       disp  =                       *((s4 *)     (sp + 1 * 4));
+       pv    = (u1 *)                *((ptrint *) (sp + 0 * 4));
+
+       /* get the fieldinfo */
+
+       assert(0);
+
+       if (!(fi = resolve_field_eager(uf)))
+               return false;
+
+       /* check if the field's class is initialized */
+
+       if (!(fi->class->state & CLASS_INITIALIZED))
+               if (!initialize_class(fi->class))
+                       return false;
+
+       /* patch the field value's address */
+
+       *((ptrint *) (pv + disp)) = (ptrint) &(fi->value);
+
+       /* synchronize data cache */
+
+       md_dcacheflush(pv + disp, SIZEOF_VOID_P);
+
+       return true;
+}
+
+/* patcher_get_putfield ********************************************************
+
+   Machine code:
+
+   <patched call position>
+
+*******************************************************************************/
+
+bool patcher_get_putfield(u1 *sp)
+{
+       u1               *ra;
+       unresolved_field *uf;
+       fieldinfo        *fi;
+       s2                disp;
+
+       ra = (u1 *)               *((ptrint *) (sp + 6 * 4));
+       uf = (unresolved_field *) *((ptrint *) (sp + 1 * 4));
+
+       /* get the fieldinfo */
+
+       assert(0);
+
+       if (!(fi = resolve_field_eager(uf)))
+               return false;
+
+       /* if we show NOPs, we have to skip them */
+
+       if (opt_shownops) {
+               /* patch the field's offset */
+
+               if (IS_LNG_TYPE(fi->type)) {
+                       /* If the field has type long, we have to patch two
+                          instructions.  But we have to check which instruction
+                          is first.  We do that with the offset of the first
+                          instruction. */
+
+                       disp = *((u4 *) (ra + 1 * 4));
+
+                       if (disp == 4) {
+                               *((u4 *) (ra + 1 * 4)) |= (s2) ((fi->offset + 4) & 0x0000ffff);
+                               *((u4 *) (ra + 2 * 4)) |= (s2) ((fi->offset + 0) & 0x0000ffff);
+                       }
+                       else {
+                               *((u4 *) (ra + 1 * 4)) |= (s2) ((fi->offset + 0) & 0x0000ffff);
+                               *((u4 *) (ra + 2 * 4)) |= (s2) ((fi->offset + 4) & 0x0000ffff);
+                       }
+               }
+               else
+                       *((u4 *) (ra + 1 * 4)) |= (s2) (fi->offset & 0x0000ffff);
+       }
+       else {
+               if (IS_LNG_TYPE(fi->type)) {
+
+                       disp = *((u4 *) (sp + 3 * 4));
+
+                       /* We patch the first instruction in the patcher stub
+                          stack and the second in the code.  The first
+                          instruction is patched back later in
+                          patcher_wrapper. */
+
+                       if (disp == 4) {
+                               *((u4 *) (sp + 3 * 4)) |= (s2) ((fi->offset + 4) & 0x0000ffff);
+                               *((u4 *) (ra + 1 * 4)) |= (s2) ((fi->offset + 0) & 0x0000ffff);
+                       }
+                       else {
+                               *((u4 *) (sp + 3 * 4)) |= (s2) ((fi->offset + 0) & 0x0000ffff);
+                               *((u4 *) (ra + 1 * 4)) |= (s2) ((fi->offset + 4) & 0x0000ffff);
+                       }
+               }
+               else
+                       *((u4 *) (sp + 3 * 4)) |= (s2) (fi->offset & 0x0000ffff);
+       }
+
+       /* synchronize instruction cache */
+
+       md_icacheflush(ra + 1 * 4, 2 * 4);
+
+       return true;
+}
+/* patcher_resolve_classref_to_flags *******************************************
+
+   CHECKCAST/INSTANCEOF:
+
+
+CHECKCAST:
+0x4029b056:   61ff 0000 013e    bsrl 0x4029b196
+0x4029b05c:   263c 0000 0000    movel #0,%d3           <-- patch this #0
+0x4029b062:   0283 0000 0200    andil #512,%d3
+
+INSTANCEOF:
+0x402a4aa8:   61ff 0000 05c4    bsrl 0x402a506e
+0x402a4aae:   283c 0000 0000    movel #0,%d4           <-- same here
+0x402a4ab4:   0284 0000 0200    andil #512,%d4
+
+
+*******************************************************************************/
+
+bool patcher_resolve_classref_to_flags(u1 *sp)
+{
+       constant_classref *cr;
+       s4                 disp;
+       classinfo         *c;
+
+       /* get stuff from the stack */
+       cr   = (constant_classref *) *((ptrint *) (sp + 1 * 4));
+       disp =                       *((s4 *)     (sp + 6 * 4));
+
+       /* get the fieldinfo */
+       if (!(c = resolve_classref_eager(cr)))
+               return false;
+
+       /* patch class flags */
+       if (opt_shownops) disp += PATCHER_CALL_SIZE;
+       assert( (*((u2*)(disp)) == 0x263c) || (*((u2*)(disp)) == 0x283c) );
+       *((s4 *) (disp + 2)) = (s4) c->flags;
+
+       /* synchronize insn cache */
+       md_icacheflush(disp + 2, SIZEOF_VOID_P);
+
+       return true;
+}
+
+/* patcher_resolve_classref_to_vftbl *******************************************
+
+   CHECKCAST (class):
+0x4029b094:   61ff 0000 00b4    bsrl 0x4029b14a
+0x4029b09a:   287c 0000 0000    moveal #0,%a4          <-- patch this #0
+0x4029b0a0:   2668 0000         moveal %a0@(0),%a3
+
+   INSTANCEOF (class):
+0x402a9300:   61ff 0000 0574    bsrl 0x402a9876
+0x402a9306:   267c 0000 0000    moveal #0,%a3
+0x402a930c:   246a 0000         moveal %a2@(0),%a2
+
+
+*******************************************************************************/
+
+bool patcher_resolve_classref_to_vftbl(u1 *sp)
+{
+       constant_classref *cr;
+       s4                 disp;
+       classinfo         *c;
+
+       /* get stuff from the stack */
+       cr   = (constant_classref *) *((ptrint *) (sp + 1 * 4));
+       disp =                       *((s4 *)     (sp + 6 * 4));
+
+       /* get the fieldinfo */
+       if (!(c = resolve_classref_eager(cr)))
+               return false;
+
+       /* patch super class' vftbl */
+       if (opt_shownops) disp += PATCHER_CALL_SIZE;
+       assert( (*((u2*)disp) == 0x287c) || (*((u2*)disp)== 0x267c) );
+
+       *((s4 *) (disp+2)) = (s4) c->vftbl;
+
+       /* synchronize insin cache */
+       md_icacheflush(disp+2, SIZEOF_VOID_P);
+
+       return true;
+}
+
+/* patcher_instanceof_interface ************************************************
+
+   Machine code:
+
+0x402a92da:   61ff 0000 05c0    bsrl 0x402a989c
+0x402a92e0:   246a 0000         moveal %a2@(0),%a2
+0x402a92e4:   282a 0010         movel %a2@(16),%d4
+0x402a92e8:   d8bc 0000 0000    addl #0,%d4            <-- this const
+0x402a92ee:   4a84              tstl %d4
+0x402a92f0:   6e0a              bles 0x402a92fc
+0x402a92f2:   246a 0000         moveal %a2@(0),%a2     <-- this offset
+
+*******************************************************************************/
+
+bool patcher_instanceof_interface(u1 *sp)
+{
+       u1                *ra;
+       constant_classref *cr;
+       classinfo         *c;
+       s4                 disp;
+
+       /* get stuff from the stack */
+
+       ra = (u1 *)                *((ptrint *) (sp + 6 * 4));
+       cr = (constant_classref *) *((ptrint *) (sp + 1 * 4));
+
+       /* get the fieldinfo */
+       if (!(c = resolve_classref_eager(cr)))
+               return false;
+
+       /* if we show NOPs, we have to skip them */
+       if (opt_shownops) ra += PATCHER_CALL_SIZE;
+               
+       /* patch super class index */
+       disp = -(c->index);
+       assert( *((u2*)(ra + 8)) == 0xd8bc );
+       *((s4 *) (ra + 10 )) = disp;
+
+       disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
+
+       assert( (s2)disp  == disp);
+       assert ( *((s2*)(ra+18)) == 0x246a );
+
+       *((s2 *) (ra + 20)) = disp;
+
+       /* synchronize instruction cache */
+       md_icacheflush(ra + 10, 12);
+
+       return true;
+}
+
+/* patcher_checkcast_interface *************************************************
+
+0x402a9400:   61ff 0000 03b6    bsrl 0x402a97b8
+0x402a9406:   266a 0000         moveal %a2@(0),%a3
+0x402a940a:   282b 0010         movel %a3@(16),%d4
+0x402a940e:   d8bc 0000 0000    addl #0,%d4            <-- this 0
+0x402a9414:   4a84              tstl %d4
+0x402a9416:   6e02              bgts 0x402a941a
+             1234              tstb %d0
+0x402a9418:   4afc              illegal
+0x402a941a:   286b 0000         moveal %a3@(0),%a4     <-- and this 0 offset
+
+*******************************************************************************/
+
+bool patcher_checkcast_interface(u1 *sp)
+{
+       u1                *ra;
+       constant_classref *cr;
+       classinfo         *c;
+       s4                 disp;
+
+       /* get stuff from the stack */
+       ra = (u1 *)                *((ptrint *) (sp + 6 * 4));
+       cr = (constant_classref *) *((ptrint *) (sp + 1 * 4));
+
+       /* get the fieldinfo */
+       if (!(c = resolve_classref_eager(cr)))
+               return false;
+
+       /* if we show NOPs, we have to skip them */
+       if (opt_shownops) ra += PATCHER_CALL_SIZE;
+
+       /* patch super class index */
+       disp = -(c->index);
+       assert ( *((u2 *)(ra + 8)) == 0xd8bc );
+       *((s4 *) (ra + 10)) = disp;
+
+       disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
+       assert( *((u2 *)(ra + 22)) == 0x286b );
+       assert( (s2)disp == disp);
+       *((s2 *) (ra + 24)) = disp;
+       
+       /* synchronize instruction cache */
+       md_icacheflush(ra + 10, 16);
+
+       return true;
+}
+
+/* patcher_resolve_native_function *********************************************
+
+   XXX
+
+*******************************************************************************/
+
+#if !defined(WITH_STATIC_CLASSPATH)
+bool patcher_resolve_native_function(u1 *sp)
+{
+       methodinfo  *m;
+       s4           disp;
+       functionptr  f;
+
+       /* get stuff from the stack */
+       m    = (methodinfo *) *((ptrint *) (sp + 1 * 4));
+       disp =                *((s4 *)     (sp + 6 * 4));
+
+       /* resolve native function */
+       if (!(f = native_resolve_function(m)))
+               return false;
+
+       /* patch native function pointer */
+       if (opt_shownops) disp += PATCHER_CALL_SIZE;
+       *((ptrint *) (disp + 2)) = (ptrint) f;
+
+       /* synchronize data cache */
+       md_icacheflush(disp + 2, SIZEOF_VOID_P);
+
+       return true;
+}
+#endif /* !defined(WITH_STATIC_CLASSPATH) */
+
+
+/* patcher_invokeinterface *****************************************************
+
+   Machine code:
+
+
+*******************************************************************************/
+
+bool patcher_invokeinterface(u1 *sp)
+{
+       u1                *ra;
+       unresolved_method *um;
+       methodinfo        *m;
+       s4                 disp;
+
+       /* get stuff from the stack */
+       ra = (u1 *)                *((ptrint *) (sp + 6 * 4));
+       um = (unresolved_method *) *((ptrint *) (sp + 1 * 4));
+
+       assert(0);
+
+       /* get the fieldinfo */
+       if (!(m = resolve_method_eager(um)))
+               return false;
+
+       /* if we show NOPs, we have to skip them */
+       if (opt_shownops) ra = ra + PATCHER_CALL_SIZE;
+
+       /* patch interfacetable index (first #0) */
+       disp = OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr*) * m->class->index;
+
+       /* XXX TWISTI: check displacement */
+       *((s4 *) (ra + 1 * 4)) |= (disp & 0x0000ffff);
+
+       /* patch method offset (second #0) */
+       disp = sizeof(methodptr) * (m - m->class->methods);
+
+       /* XXX TWISTI: check displacement */
+       *((s4 *) (ra + 2 * 4)) |= (disp & 0x0000ffff);
+
+       /* synchronize instruction cache */
+       md_icacheflush(ra + 1 * 4, 2 * 4);
+
+       return true;
+}
+
diff --git a/src/vm/jit/m68k/uclinux/Makefile.am b/src/vm/jit/m68k/uclinux/Makefile.am
deleted file mode 100644 (file)
index 5207e3d..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-## src/vm/jit/powerpc64/linux/Makefile.am
-##
-## Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
-## C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
-## E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
-## J. Wenninger, Institut f. Computersprachen - TU Wien
-##
-## This file is part of CACAO.
-##
-## This program is free software; you can redistribute it and/or
-## modify it under the terms of the GNU General Public License as
-## published by the Free Software Foundation; either version 2, or (at
-## your option) any later version.
-##
-## This program is distributed in the hope that it will be useful, but
-## WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-## General Public License for more details.
-##
-## You should have received a copy of the GNU General Public License
-## along with this program; if not, write to the Free Software
-## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-## 02110-1301, USA.
-##
-## Contact: cacao@cacaojvm.org
-##
-## Authors: Christian Thalinger
-##
-## Changes:
-##
-## $Id: Makefile.am 5081 2006-07-06 13:59:01Z tbfg $
-
-## Process this file with automake to produce Makefile.in
-
-AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/src/vm/jit/$(ARCH_DIR)
-
-LIBS =
-
-noinst_HEADERS = \
-       md-asm.h
-
-noinst_LTLIBRARIES = libmd.la
-
-libmd_la_SOURCES = \
-       md-abi.c \
-       md-abi.h \
-       md-os.c
-
-
-## Local variables:
-## mode: Makefile
-## indent-tabs-mode: t
-## c-basic-offset: 4
-## tab-width: 8
-## compile-command: "automake --add-missing"
-## End:
diff --git a/src/vm/jit/m68k/uclinux/md-abi.c b/src/vm/jit/m68k/uclinux/md-abi.c
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/src/vm/jit/m68k/uclinux/md-abi.h b/src/vm/jit/m68k/uclinux/md-abi.h
deleted file mode 100644 (file)
index aefc1a8..0000000
+++ /dev/null
@@ -1,109 +0,0 @@
-/* src/vm/jit/m68k/linux/md-abi.h - defines for PowerPC64 Linux ABI
-
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
-   C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
-   E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
-   J. Wenninger, Institut f. Computersprachen - TU Wien
-
-   This file is part of CACAO.
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2, or (at
-   your option) any later version.
-
-   This program is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-   02110-1301, USA.
-
-   Contact: cacao@cacaojvm.org
-
-   Authors: Roland Lezuo
-
-   Changes:
-
-   $Id: md-abi.h 5940 2006-11-09 09:59:28Z tbfg $
-
-*/
-
-
-#ifndef _MD_ABI_H
-#define _MD_ABI_H
-
-/* preallocated registers *****************************************************/
-
-/* integer registers */
-
-#define REG_TOC                 2   /* TOC (see function descriptors ELF ABI)        */
-#define REG_RESULT       3   /* to deliver method results                     */
-
-#define REG_PV          14   /* procedure vector, must be provided by caller  */
-#define REG_METHODPTR   12   /* pointer to the place from where the procedure */
-                             /* vector has been fetched                       */
-#define REG_ITMP1       11   /* temporary register                            */
-#define REG_ITMP2       12   /* temporary register and method pointer         */
-#define REG_ITMP3       16   /* temporary register                            */
-
-#define REG_ITMP1_XPTR  11   /* exception pointer = temporary register 1      */
-#define REG_ITMP2_XPC   12   /* exception pc = temporary register 2           */
-
-#define REG_SP           1   /* stack pointer                                 */
-#define REG_ZERO         0   /* almost always zero: only in address calc.     */
-
-/* floating point registers */
-
-#define REG_FRESULT      1   /* to deliver floating point method results      */
-#define REG_FTMP1       16   /* temporary floating point register             */
-#define REG_FTMP2       17   /* temporary floating point register             */
-#define REG_FTMP3        0   /* temporary floating point register             */
-
-#define REG_IFTMP       16   /* temporary integer and floating point register */
-
-
-#define INT_REG_CNT     32   /* number of integer registers                   */
-#define INT_SAV_CNT      9   /* number of int callee saved registers          */
-#define INT_ARG_CNT      8   /* number of int argument registers              */
-#define INT_TMP_CNT      7   /* number of integer temporary registers         */
-#define INT_RES_CNT      8   /* number of integer reserved registers          */
-
-#define FLT_REG_CNT     32   /* number of float registers                     */
-#define FLT_SAV_CNT     16   /* number of float callee saved registers        */
-#define FLT_ARG_CNT     13   /* number of float argument registers            */
-#define FLT_TMP_CNT      0   /* number of float temporary registers           */
-#define FLT_RES_CNT      3   /* number of float reserved registers            */
-
-#define TRACE_ARGS_NUM   8
-
-
-/* ABI defines ****************************************************************/
-
-#define LA_SIZE         48   /* linkage area size                             */
-#define LA_SIZE_ALIGNED 16   /* linkage area size aligned to 16-byte          */
-#define LA_SIZE_IN_POINTERS    (LA_SIZE / SIZEOF_VOID_P)
-#define LA_LR_OFFSET    16   /* link register offset in linkage area          */
-#define PA_SIZE                (PA_SIZE_IN_POINTERS*8) 
-#define PA_SIZE_IN_POINTERS    8 /* linux/ppc64 has a minimun parameter save area size, XXX:darwin? */
-
-/* #define ALIGN_FRAME_SIZE(sp)       (sp) */
-
-#endif /* _MD_ABI_H */
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- */
diff --git a/src/vm/jit/m68k/uclinux/md-asm.h b/src/vm/jit/m68k/uclinux/md-asm.h
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/src/vm/jit/m68k/uclinux/md-os.c b/src/vm/jit/m68k/uclinux/md-os.c
deleted file mode 100644 (file)
index e69de29..0000000
index 40c95d529bdf7aa24d2ba1702cbf2b5fa8a1ec56..4e3c01ac991b50a0f83a28764b4399f4d82d4cd1 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: arch.h 7241 2007-01-27 15:52:01Z twisti $
+   $Id: arch.h 7596 2007-03-28 21:05:53Z twisti $
 
 */
 
 #endif /* SIZEOF_VOID_P == 8 */
 
 
+/* branches *******************************************************************/
+
+#define SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER       0
+#define SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER     1
+#define SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS    1
+
+
 /* exceptions *****************************************************************/
 
 #define SUPPORT_HARDWARE_DIVIDE_BY_ZERO  0
index 80d94d8f28195c3a6e8338b2b284b319d14719cf..8d76f83d2ff8943375202e335e38fccbf599fa48 100644 (file)
@@ -29,7 +29,7 @@
    Changes: Christian Thalinger
             Edwin Steiner
 
-   $Id: asmpart.S 7224 2007-01-18 11:43:03Z twisti $
+   $Id: asmpart.S 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
index c2817a0b1ea0b26d8383e116461a330ca75d406d..203b4b22e90083b8f964d797e39117c75b1c69d6 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: codegen.c 7252 2007-01-29 21:09:01Z twisti $
+   $Id: codegen.c 7596 2007-03-28 21:05:53Z twisti $
 
 */
 
 #include "vmcore/options.h"
 
 
-/* codegen *********************************************************************
+/* codegen_emit ****************************************************************
 
    Generates machine code.
 
 *******************************************************************************/
 
-bool codegen(jitdata *jd)
+bool codegen_emit(jitdata *jd)
 {
        methodinfo         *m;
        codeinfo           *code;
@@ -353,24 +353,19 @@ bool codegen(jitdata *jd)
                if (m->flags & ACC_STATIC) {
                        disp = dseg_add_address(cd, &m->class->object.header);
                        M_ALD(REG_A0, REG_PV, disp);
+                       disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
+                       M_ALD(REG_ITMP3, REG_PV, disp);
                }
                else {
 /*                     emit_nullpointer_check(cd, iptr, REG_A0); */
-                       M_BNEZ(REG_A0, 6);
-                       M_NOP;
-
-                       M_LUI(REG_ITMP3, 0);
-                       M_OR_IMM(REG_ITMP3, 0, REG_ITMP3);
-                       codegen_add_nullpointerexception_ref(cd);
-                       M_AADD(REG_PV, REG_ITMP3, REG_ITMP3);
-                       M_JMP(REG_ITMP3);
-                       M_NOP;
+                       M_BNEZ(REG_A0, 2);
+                       disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
+                       M_ALD(REG_ITMP3, REG_PV, disp);                   /* branch delay */
+                       M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_NULLPOINTER);
                }
 
-               disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
-               M_ALD(REG_ITMP3, REG_PV, disp);
                M_JSR(REG_RA, REG_ITMP3);
-               M_AST(REG_A0, REG_SP, s1 * 8);         /* branch delay */
+               M_AST(REG_A0, REG_SP, s1 * 8);                        /* branch delay */
 
 # if !defined(NDEBUG)
                if (opt_verbosecall) {
@@ -1760,7 +1755,7 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                       emit_nullpointer_check(cd, iptr, s1);
+                       /* implicit null-pointer check */
                        M_ILD(d, s1, OFFSET(java_arrayheader, size));
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1770,8 +1765,9 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_AADD(s2, s1, REG_ITMP3);
+                       /* implicit null-pointer check */
                        M_BLDS(d, REG_ITMP3, OFFSET(java_bytearray, data[0]));
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1781,9 +1777,10 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_AADD(s2, s1, REG_ITMP3);
                        M_AADD(s2, REG_ITMP3, REG_ITMP3);
+                       /* implicit null-pointer check */
                        M_SLDU(d, REG_ITMP3, OFFSET(java_chararray, data[0]));
                        emit_store_dst(jd, iptr, d);
                        break;                  
@@ -1793,9 +1790,10 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_AADD(s2, s1, REG_ITMP3);
                        M_AADD(s2, REG_ITMP3, REG_ITMP3);
+                       /* implicit null-pointer check */
                        M_SLDS(d, REG_ITMP3, OFFSET(java_shortarray, data[0]));
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1805,10 +1803,11 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ASLL_IMM(s2, 2, REG_ITMP3);
                        M_AADD(REG_ITMP3, s1, REG_ITMP3);
-                       M_ILD(d, REG_ITMP3, OFFSET(java_intarray, data[0]));
+                       /* implicit null-pointer check */
+                       M_ILD_INTERN(d, REG_ITMP3, OFFSET(java_intarray, data[0]));
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -1821,10 +1820,11 @@ bool codegen(jitdata *jd)
 #else
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
 #endif
-                       emit_array_checks(cd, iptr, s1, s2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ASLL_IMM(s2, 3, REG_ITMP3);
                        M_AADD(REG_ITMP3, s1, REG_ITMP3);
-                       M_LLD(d, REG_ITMP3, OFFSET(java_longarray, data[0]));
+                       /* implicit null-pointer check */
+                       M_LLD_INTERN(d, REG_ITMP3, OFFSET(java_longarray, data[0]));
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -1833,10 +1833,11 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ASLL_IMM(s2, 2, REG_ITMP3);
                        M_AADD(REG_ITMP3, s1, REG_ITMP3);
-                       M_FLD(d, REG_ITMP3, OFFSET(java_floatarray, data[0]));
+                       /* implicit null-pointer check */
+                       M_FLD_INTERN(d, REG_ITMP3, OFFSET(java_floatarray, data[0]));
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -1845,10 +1846,11 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ASLL_IMM(s2, 3, REG_ITMP3);
                        M_AADD(REG_ITMP3, s1, REG_ITMP3);
-                       M_DLD(d, REG_ITMP3, OFFSET(java_doublearray, data[0]));
+                       /* implicit null-pointer check */
+                       M_DLD_INTERN(d, REG_ITMP3, OFFSET(java_doublearray, data[0]));
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -1857,10 +1859,11 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP3);
                        M_AADD(REG_ITMP3, s1, REG_ITMP3);
-                       M_ALD(d, REG_ITMP3, OFFSET(java_objectarray, data[0]));
+                       /* implicit null-pointer check */
+                       M_ALD_INTERN(d, REG_ITMP3, OFFSET(java_objectarray, data[0]));
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -1869,9 +1872,10 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_AADD(s2, s1, REG_ITMP1);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
+                       /* implicit null-pointer check */
                        M_BST(s3, REG_ITMP1, OFFSET(java_bytearray, data[0]));
                        break;
 
@@ -1880,10 +1884,11 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_AADD(s2, s1, REG_ITMP1);
                        M_AADD(s2, REG_ITMP1, REG_ITMP1);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
+                       /* implicit null-pointer check */
                        M_SST(s3, REG_ITMP1, OFFSET(java_chararray, data[0]));
                        break;
 
@@ -1891,10 +1896,11 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ASLL_IMM(s2, 2, REG_ITMP2);
                        M_AADD(REG_ITMP2, s1, REG_ITMP1);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
+                       /* implicit null-pointer check */
                        M_IST_INTERN(s3, REG_ITMP1, OFFSET(java_intarray, data[0]));
                        break;
 
@@ -1902,7 +1908,7 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ASLL_IMM(s2, 3, REG_ITMP2);
                        M_AADD(REG_ITMP2, s1, REG_ITMP1);
 #if SIZEOF_VOID_P == 8
@@ -1910,6 +1916,7 @@ bool codegen(jitdata *jd)
 #else
                        s3 = emit_load_s3(jd, iptr, REG_ITMP23_PACKED);
 #endif
+                       /* implicit null-pointer check */
                        M_LST_INTERN(s3, REG_ITMP1, OFFSET(java_longarray, data[0]));
                        break;
 
@@ -1917,10 +1924,11 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ASLL_IMM(s2, 2, REG_ITMP2);
                        M_AADD(REG_ITMP2, s1, REG_ITMP1);
                        s3 = emit_load_s3(jd, iptr, REG_FTMP1);
+                       /* implicit null-pointer check */
                        M_FST_INTERN(s3, REG_ITMP1, OFFSET(java_floatarray, data[0]));
                        break;
 
@@ -1928,10 +1936,11 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ASLL_IMM(s2, 3, REG_ITMP2);
                        M_AADD(REG_ITMP2, s1, REG_ITMP1);
                        s3 = emit_load_s3(jd, iptr, REG_FTMP1);
+                       /* implicit null-pointer check */
                        M_DST_INTERN(s3, REG_ITMP1, OFFSET(java_doublearray, data[0]));
                        break;
 
@@ -1940,26 +1949,23 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
 
-                       M_MOV(s1, REG_A0);
-                       M_MOV(s3, REG_A1);
+                       M_INTMOVE(s1, REG_A0);
+                       M_INTMOVE(s3, REG_A1);
                        disp = dseg_add_functionptr(cd, BUILTIN_canstore);
                        M_ALD(REG_ITMP3, REG_PV, disp);
                        M_JSR(REG_RA, REG_ITMP3);
                        M_NOP;
-
-/*                     M_BEQZ(REG_RESULT, 0); */
-/*                     codegen_add_arraystoreexception_ref(cd); */
-/*                     M_NOP; */
-                       emit_arraystore_check(cd, iptr, REG_RESULT);
+                       emit_exception_check(cd, iptr);
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
                        M_AADD(REG_ITMP2, s1, REG_ITMP1);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
+                       /* implicit null-pointer check */
                        M_AST_INTERN(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
                        break;
 
@@ -1968,8 +1974,9 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_AADD(s2, s1, REG_ITMP1);
+                       /* implicit null-pointer check */
                        M_BST(REG_ZERO, REG_ITMP1, OFFSET(java_bytearray, data[0]));
                        break;
 
@@ -1978,9 +1985,10 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_AADD(s2, s1, REG_ITMP1);
                        M_AADD(s2, REG_ITMP1, REG_ITMP1);
+                       /* implicit null-pointer check */
                        M_SST(REG_ZERO, REG_ITMP1, OFFSET(java_chararray, data[0]));
                        break;
 
@@ -1988,9 +1996,10 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ASLL_IMM(s2, 2, REG_ITMP2);
                        M_AADD(REG_ITMP2, s1, REG_ITMP1);
+                       /* implicit null-pointer check */
                        M_IST_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_intarray, data[0]));
                        break;
 
@@ -1998,9 +2007,10 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ASLL_IMM(s2, 3, REG_ITMP2);
                        M_AADD(REG_ITMP2, s1, REG_ITMP1);
+                       /* implicit null-pointer check */
 #if SIZEOF_VOID_P == 8
                        M_LST_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_longarray, data[0]));
 #else
@@ -2012,9 +2022,10 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
                        M_AADD(REG_ITMP2, s1, REG_ITMP1);
+                       /* implicit null-pointer check */
                        M_AST_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_objectarray, data[0]));
                        break;
 
@@ -2326,143 +2337,120 @@ bool codegen(jitdata *jd)
                case ICMD_GOTO:         /* ... ==> ...                                */
                case ICMD_RET:          /* ... ==> ...                                */
 
-                       M_BR(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_br(cd, iptr->dst.block);
                        ALIGNCODENOP;
                        break;
 
                case ICMD_JSR:          /* ... ==> ...                                */
 
-                       M_BR(0);
-                       codegen_add_branch_ref(cd, iptr->sx.s23.s3.jsrtarget.block);
-                       M_NOP;
+                       emit_br(cd, iptr->sx.s23.s3.jsrtarget.block);
                        ALIGNCODENOP;
                        break;
                        
                case ICMD_IFNULL:       /* ..., value ==> ...                         */
+               case ICMD_IFNONNULL:
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       M_BEQZ(s1, 0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
-                       break;
-
-               case ICMD_IFNONNULL:    /* ..., value ==> ...                         */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       M_BNEZ(s1, 0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_bccz(cd, iptr->dst.block, iptr->opc - ICMD_IFNULL, s1, BRANCH_OPT_NONE);
                        break;
 
                case ICMD_IFEQ:         /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.i == 0) {
-                               M_BEQZ(s1, 0);
-                       else {
+                       if (iptr->sx.val.i == 0)
+                               emit_beqz(cd, iptr->dst.block, s1);
+                       else {
                                ICONST(REG_ITMP2, iptr->sx.val.i);
-                               M_BEQ(s1, REG_ITMP2, 0);
+                               emit_beq(cd, iptr->dst.block, s1, REG_ITMP2);
                        }
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
                        break;
 
                case ICMD_IFLT:         /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.i == 0) {
-                               M_BLTZ(s1, 0);
-                       else {
-                               if ((iptr->sx.val.i >= -32768) && (iptr->sx.val.i <= 32767)) {
+                       if (iptr->sx.val.i == 0)
+                               emit_bltz(cd, iptr->dst.block, s1);
+                       else {
+                               if ((iptr->sx.val.i >= -32768) && (iptr->sx.val.i <= 32767))
                                        M_CMPLT_IMM(s1, iptr->sx.val.i, REG_ITMP1);
-                               else {
+                               else {
                                        ICONST(REG_ITMP2, iptr->sx.val.i);
                                        M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
                                }
-                               M_BNEZ(REG_ITMP1, 0);
+                               emit_bnez(cd, iptr->dst.block, REG_ITMP1);
                        }
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
                        break;
 
                case ICMD_IFLE:         /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.i == 0) {
-                               M_BLEZ(s1, 0);
-                       else {
+                       if (iptr->sx.val.i == 0)
+                               emit_blez(cd, iptr->dst.block, s1);
+                       else {
                                if ((iptr->sx.val.i >= -32769) && (iptr->sx.val.i <= 32766)) {
                                        M_CMPLT_IMM(s1, iptr->sx.val.i + 1, REG_ITMP1);
-                                       M_BNEZ(REG_ITMP1, 0);
-                               } else {
+                                       emit_bnez(cd, iptr->dst.block, REG_ITMP1);
+                               }
+                               else {
                                        ICONST(REG_ITMP2, iptr->sx.val.i);
                                        M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
-                                       M_BEQZ(REG_ITMP1, 0);
+                                       emit_beqz(cd, iptr->dst.block, REG_ITMP1);
                                }
                        }
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
                        break;
 
                case ICMD_IFNE:         /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.i == 0) {
-                               M_BNEZ(s1, 0);
-                       else {
+                       if (iptr->sx.val.i == 0)
+                               emit_bnez(cd, iptr->dst.block, s1);
+                       else {
                                ICONST(REG_ITMP2, iptr->sx.val.i);
-                               M_BNE(s1, REG_ITMP2, 0);
+                               emit_bne(cd, iptr->dst.block, s1, REG_ITMP2);
                        }
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
                        break;
 
                case ICMD_IFGT:         /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.i == 0) {
-                               M_BGTZ(s1, 0);
-                       else {
+                       if (iptr->sx.val.i == 0)
+                               emit_bgtz(cd, iptr->dst.block, s1);
+                       else {
                                if ((iptr->sx.val.i >= -32769) && (iptr->sx.val.i <= 32766)) {
                                        M_CMPLT_IMM(s1, iptr->sx.val.i + 1, REG_ITMP1);
-                                       M_BEQZ(REG_ITMP1, 0);
-                               } else {
+                                       emit_beqz(cd, iptr->dst.block, REG_ITMP1);
+                               }
+                               else {
                                        ICONST(REG_ITMP2, iptr->sx.val.i);
                                        M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
-                                       M_BNEZ(REG_ITMP1, 0);
+                                       emit_bnez(cd, iptr->dst.block, REG_ITMP1);
                                }
                        }
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
                        break;
 
                case ICMD_IFGE:         /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.i == 0) {
-                               M_BGEZ(s1, 0);
-                       else {
-                               if ((iptr->sx.val.i >= -32768) && (iptr->sx.val.i <= 32767)) {
+                       if (iptr->sx.val.i == 0)
+                               emit_bgez(cd, iptr->dst.block, s1);
+                       else {
+                               if ((iptr->sx.val.i >= -32768) && (iptr->sx.val.i <= 32767))
                                        M_CMPLT_IMM(s1, iptr->sx.val.i, REG_ITMP1);
-                               else {
+                               else {
                                        ICONST(REG_ITMP2, iptr->sx.val.i);
                                        M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
                                }
-                               M_BEQZ(REG_ITMP1, 0);
+                               emit_beqz(cd, iptr->dst.block, REG_ITMP1);
                        }
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
                        break;
 
                case ICMD_IF_LEQ:       /* ..., value ==> ...                         */
 
 #if SIZEOF_VOID_P == 8
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.l == 0) {
+                       if (iptr->sx.val.l == 0)
                                M_BEQZ(s1, 0);
-                       else {
+                       else {
                                LCONST(REG_ITMP2, iptr->sx.val.l);
                                M_BEQ(s1, REG_ITMP2, 0);
                        }
@@ -2470,7 +2458,7 @@ bool codegen(jitdata *jd)
                        if (iptr->sx.val.l == 0) {
                                s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED);
                                M_OR(GET_LOW_REG(s1), GET_HIGH_REG(s1), REG_ITMP3);
-                               M_BEQZ(REG_ITMP3, 0);
+                               emit_beqz(cd, iptr->dst.block, REG_ITMP3);
                        }
                        else {
                                s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
@@ -2480,11 +2468,9 @@ bool codegen(jitdata *jd)
                                ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
                                M_XOR(s1, REG_ITMP3, REG_ITMP3);
                                M_OR(REG_ITMP2, REG_ITMP3, REG_ITMP3);
-                               M_BEQZ(REG_ITMP3, 0);
+                               emit_beqz(cd, iptr->dst.block, REG_ITMP3);
                        }
 #endif
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
                        break;
 
                case ICMD_IF_LLT:       /* ..., value ==> ...                         */
@@ -2506,25 +2492,21 @@ bool codegen(jitdata *jd)
                        if (iptr->sx.val.l == 0) {
                                /* if high word is less than zero, the whole long is too */
                                s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
-                               M_BLTZ(s1, 0);
+                               emit_bltz(cd, iptr->dst.block, s1);
                        }
                        else {
                                s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
                                ICONST(REG_ITMP2, iptr->sx.val.l >> 32);
                                M_CMPLT(s1, REG_ITMP2, REG_ITMP3);
-                               M_BNEZ(REG_ITMP3, 0);
-                               codegen_add_branch_ref(cd, iptr->dst.block);
-                               M_NOP;
+                               emit_bnez(cd, iptr->dst.block, REG_ITMP3);
                                s2 = emit_load_s1_low(jd, iptr, REG_ITMP3);
-                               M_BNE(s1, REG_ITMP2, 5);
+                               M_BNE(s1, REG_ITMP2, 5); /* XXX */
                                M_NOP;
                                ICONST(REG_ITMP2, iptr->sx.val.l & 0xffffffff);
                                M_CMPULT(s2, REG_ITMP2, REG_ITMP3);
-                               M_BNEZ(REG_ITMP3, 0);
+                               emit_bnez(cd, iptr->dst.block, REG_ITMP3);
                        }
 #endif
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
                        break;
 
                case ICMD_IF_LLE:       /* ..., value ==> ...                         */
@@ -2546,30 +2528,24 @@ bool codegen(jitdata *jd)
 #else
                        if (iptr->sx.val.l == 0) {
                                s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED);
-                               M_BGTZ(GET_HIGH_REG(s1), 5);
+                               M_BGTZ(GET_HIGH_REG(s1), 5); /* XXX */
                                M_NOP;
-                               M_BLTZ(GET_HIGH_REG(s1), 0);
-                               codegen_add_branch_ref(cd, iptr->dst.block);
-                               M_NOP;
-                               M_BEQZ(GET_LOW_REG(s1), 0);
+                               emit_bltz(cd, iptr->dst.block, GET_HIGH_REG(s1));
+                               emit_beqz(cd, iptr->dst.block, GET_LOW_REG(s1));
                        }
                        else {
                                s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
                                ICONST(REG_ITMP2, iptr->sx.val.l >> 32);
                                M_CMPLT(s1, REG_ITMP2, REG_ITMP3);
-                               M_BNEZ(REG_ITMP3, 0);
-                               codegen_add_branch_ref(cd, iptr->dst.block);
-                               M_NOP;
+                               emit_bnez(cd, iptr->dst.block, REG_ITMP3);
                                s2 = emit_load_s1_low(jd, iptr, REG_ITMP3);
-                               M_BNE(s1, REG_ITMP2, 5);
+                               M_BNE(s1, REG_ITMP2, 5); /* XXX */
                                M_NOP;
                                ICONST(REG_ITMP2, iptr->sx.val.l & 0xffffffff);
                                M_CMPUGT(s2, REG_ITMP2, REG_ITMP3);
-                               M_BEQZ(REG_ITMP3, 0);
+                               emit_beqz(cd, iptr->dst.block, REG_ITMP3);
                        }
 #endif
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
                        break;
 
                case ICMD_IF_LNE:       /* ..., value ==> ...                         */
@@ -2586,7 +2562,7 @@ bool codegen(jitdata *jd)
                        if (iptr->sx.val.l == 0) {
                                s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED);
                                M_OR(GET_LOW_REG(s1), GET_HIGH_REG(s1), REG_ITMP3);
-                               M_BNEZ(REG_ITMP3, 0);
+                               emit_bnez(cd, iptr->dst.block, REG_ITMP3);
                        }
                        else {
                                s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
@@ -2596,11 +2572,9 @@ bool codegen(jitdata *jd)
                                ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
                                M_XOR(s1, REG_ITMP3, REG_ITMP3);
                                M_OR(REG_ITMP2, REG_ITMP3, REG_ITMP3);
-                               M_BNEZ(REG_ITMP3, 0);
+                               emit_bnez(cd, iptr->dst.block, REG_ITMP3);
                        }
 #endif
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
                        break;
 
                case ICMD_IF_LGT:       /* ..., value ==> ...                         */
@@ -2622,30 +2596,24 @@ bool codegen(jitdata *jd)
 #else
                        if (iptr->sx.val.l == 0) {
                                s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED);
-                               M_BGTZ(GET_HIGH_REG(s1), 0);
-                               codegen_add_branch_ref(cd, iptr->dst.block);
-                               M_NOP;
-                               M_BLTZ(GET_HIGH_REG(s1), 3);
+                               emit_bgtz(cd, iptr->dst.block, GET_HIGH_REG(s1));
+                               M_BLTZ(GET_HIGH_REG(s1), 3); /* XXX */
                                M_NOP;
-                               M_BNEZ(GET_LOW_REG(s1), 0);
+                               emit_bnez(cd, iptr->dst.block, GET_LOW_REG(s1));
                        }
                        else {
                                s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
                                ICONST(REG_ITMP2, iptr->sx.val.l >> 32);
                                M_CMPGT(s1, REG_ITMP2, REG_ITMP3);
-                               M_BNEZ(REG_ITMP3, 0);
-                               codegen_add_branch_ref(cd, iptr->dst.block);
-                               M_NOP;
+                               emit_bnez(cd, iptr->dst.block, REG_ITMP3);
                                s2 = emit_load_s1_low(jd, iptr, REG_ITMP3);
-                               M_BNE(s1, REG_ITMP2, 5);
+                               M_BNE(s1, REG_ITMP2, 5); /* XXX */
                                M_NOP;
                                ICONST(REG_ITMP2, iptr->sx.val.l & 0xffffffff);
                                M_CMPUGT(s2, REG_ITMP2, REG_ITMP3);
-                               M_BNEZ(REG_ITMP3, 0);
+                               emit_bnez(cd, iptr->dst.block, REG_ITMP3);
                        }
 #endif
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
                        break;
 
                case ICMD_IF_LGE:       /* ..., value ==> ...                         */
@@ -2667,25 +2635,21 @@ bool codegen(jitdata *jd)
                        if (iptr->sx.val.l == 0) {
                                /* if high word is greater equal zero, the whole long is too */
                                s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
-                               M_BGEZ(s1, 0);
+                               emit_bgez(cd, iptr->dst.block, s1);
                        }
                        else {
                                s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
                                ICONST(REG_ITMP2, iptr->sx.val.l >> 32);
                                M_CMPGT(s1, REG_ITMP2, REG_ITMP3);
-                               M_BNEZ(REG_ITMP3, 0);
-                               codegen_add_branch_ref(cd, iptr->dst.block);
-                               M_NOP;
+                               emit_bnez(cd, iptr->dst.block, REG_ITMP3);
                                s2 = emit_load_s1_low(jd, iptr, REG_ITMP3);
-                               M_BNE(s1, REG_ITMP2, 5);
+                               M_BNE(s1, REG_ITMP2, 5); /* XXX */
                                M_NOP;
                                ICONST(REG_ITMP2, iptr->sx.val.l & 0xffffffff);
                                M_CMPULT(s2, REG_ITMP2, REG_ITMP3);
-                               M_BEQZ(REG_ITMP3, 0);
+                               emit_beqz(cd, iptr->dst.block, REG_ITMP3);
                        }
 #endif
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
                        break;
 
                case ICMD_IF_ICMPEQ:    /* ..., value, value ==> ...                  */
@@ -2696,9 +2660,7 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       M_BEQ(s1, s2, 0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_beq(cd, iptr->dst.block, s1, s2);
                        break;
 
 #if SIZEOF_VOID_P == 4
@@ -2707,13 +2669,11 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
-                       M_BNE(s1, s2, 3);
+                       M_BNE(s1, s2, 3); /* XXX TWISTI: uff, that is a problem */
                        M_NOP;
                        s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
-                       M_BEQ(s1, s2, 0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_beq(cd, iptr->dst.block, s1, s2);
                        break;
 #endif
 
@@ -2725,24 +2685,19 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       M_BNE(s1, s2, 0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_bne(cd, iptr->dst.block, s1, s2);
                        break;
 
 #if SIZEOF_VOID_P == 4
                case ICMD_IF_LCMPNE:    /* ..., value, value ==> ...                  */
 
+                       /* TODO: could be optimized (XOR or SUB) */
                        s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
-                       M_BNE(s1, s2, 0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_bne(cd, iptr->dst.block, s1, s2);
                        s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
-                       M_BNE(s1, s2, 0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_bne(cd, iptr->dst.block, s1, s2);
                        break;
 #endif
 
@@ -2754,9 +2709,7 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_CMPLT(s1, s2, REG_ITMP3);
-                       M_BNEZ(REG_ITMP3, 0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_bnez(cd, iptr->dst.block, REG_ITMP3);
                        break;
 
 #if SIZEOF_VOID_P == 4
@@ -2765,19 +2718,15 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
                        M_CMPLT(s1, s2, REG_ITMP3);
-                       M_BNEZ(REG_ITMP3, 0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_bnez(cd, iptr->dst.block, REG_ITMP3);
                        M_CMPGT(s1, s2, REG_ITMP3);
                        /* load low-bits before the branch, so we know the distance */
                        s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
-                       M_BNEZ(REG_ITMP3, 4);
+                       M_BNEZ(REG_ITMP3, 4); /* XXX */
                        M_NOP;
                        M_CMPULT(s1, s2, REG_ITMP3);
-                       M_BNEZ(REG_ITMP3, 0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_bnez(cd, iptr->dst.block, REG_ITMP3);
                        break;
 #endif
 
@@ -2789,9 +2738,7 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_CMPGT(s1, s2, REG_ITMP3);
-                       M_BNEZ(REG_ITMP3, 0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_bnez(cd, iptr->dst.block, REG_ITMP3);
                        break;
 
 #if SIZEOF_VOID_P == 4
@@ -2800,19 +2747,15 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
                        M_CMPGT(s1, s2, REG_ITMP3);
-                       M_BNEZ(REG_ITMP3, 0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_bnez(cd, iptr->dst.block, REG_ITMP3);
                        M_CMPLT(s1, s2, REG_ITMP3);
                        /* load low-bits before the branch, so we know the distance */
                        s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
-                       M_BNEZ(REG_ITMP3, 4);
+                       M_BNEZ(REG_ITMP3, 4); /* XXX */
                        M_NOP;
                        M_CMPUGT(s1, s2, REG_ITMP3);
-                       M_BNEZ(REG_ITMP3, 0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_bnez(cd, iptr->dst.block, REG_ITMP3);
                        break;
 #endif
 
@@ -2824,9 +2767,7 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_CMPGT(s1, s2, REG_ITMP3);
-                       M_BEQZ(REG_ITMP3, 0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_beqz(cd, iptr->dst.block, REG_ITMP3);
                        break;
 
 #if SIZEOF_VOID_P == 4
@@ -2835,19 +2776,15 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
                        M_CMPLT(s1, s2, REG_ITMP3);
-                       M_BNEZ(REG_ITMP3, 0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_bnez(cd, iptr->dst.block, REG_ITMP3);
                        M_CMPGT(s1, s2, REG_ITMP3);
                        /* load low-bits before the branch, so we know the distance */
                        s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
-                       M_BNEZ(REG_ITMP3, 4);
+                       M_BNEZ(REG_ITMP3, 4); /* XXX */
                        M_NOP;
                        M_CMPUGT(s1, s2, REG_ITMP3);
-                       M_BEQZ(REG_ITMP3, 0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_beqz(cd, iptr->dst.block, REG_ITMP3);
                        break;
 #endif
 
@@ -2859,9 +2796,7 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_CMPLT(s1, s2, REG_ITMP3);
-                       M_BEQZ(REG_ITMP3, 0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_beqz(cd, iptr->dst.block, REG_ITMP3);
                        break;
 
 #if SIZEOF_VOID_P == 4
@@ -2870,19 +2805,15 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
                        M_CMPGT(s1, s2, REG_ITMP3);
-                       M_BNEZ(REG_ITMP3, 0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_bnez(cd, iptr->dst.block, REG_ITMP3);
                        M_CMPLT(s1, s2, REG_ITMP3);
                        /* load low-bits before the branch, so we know the distance */
                        s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
-                       M_BNEZ(REG_ITMP3, 4);
+                       M_BNEZ(REG_ITMP3, 4); /* XXX */
                        M_NOP;
                        M_CMPULT(s1, s2, REG_ITMP3);
-                       M_BEQZ(REG_ITMP3, 0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_beqz(cd, iptr->dst.block, REG_ITMP3);
                        break;
 #endif
 
@@ -3078,9 +3009,7 @@ nowperformreturn:
                        /* range check */
 
                        M_CMPULT_IMM(REG_ITMP1, i, REG_ITMP2);
-                       M_BEQZ(REG_ITMP2, 0);
-                       codegen_add_branch_ref(cd, table[0].block); /* default target */
-                       M_ASLL_IMM(REG_ITMP1, POINTERSHIFT, REG_ITMP1);     /* delay slot */
+                       emit_beqz(cd, table[0].block, REG_ITMP2);
 
                        /* build jump table top down and use address of lowest entry */
 
@@ -3094,6 +3023,7 @@ nowperformreturn:
 
                        /* length of dataseg after last dseg_add_target is used by load */
 
+                       M_ASLL_IMM(REG_ITMP1, POINTERSHIFT, REG_ITMP1);
                        M_AADD(REG_ITMP1, REG_PV, REG_ITMP2);
                        M_ALD(REG_ITMP2, REG_ITMP2, -(cd->dseglen));
                        M_JMP(REG_ITMP2);
@@ -3116,15 +3046,11 @@ nowperformreturn:
 
                        while (--i >= 0) {
                                ICONST(REG_ITMP2, lookup->value);
-                               M_BEQ(s1, REG_ITMP2, 0);
-                               codegen_add_branch_ref(cd, lookup->target.block); 
-                               M_NOP;
+                               emit_beq(cd, lookup->target.block, s1, REG_ITMP2);
                                ++lookup;
                        }
 
-                       M_BR(0);
-                       codegen_add_branch_ref(cd, iptr->sx.s23.s3.lookupdefault.block);
-                       M_NOP;
+                       emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
                        ALIGNCODENOP;
                        break;
                        }
@@ -3260,23 +3186,22 @@ gen_method:
 
                                M_ALD(REG_ITMP3, REG_PV, disp);  /* built-in-function pointer */
 
+                               /* generate the actual call */
+
                                /* TWISTI: i actually don't know the reason for using
                                   REG_ITMP3 here instead of REG_PV. */
-                               s1 = REG_ITMP3;
-                               break;
 
-                       case ICMD_INVOKESPECIAL:
-/*                             emit_nullpointer_check(cd, REG_A0); */
-                               M_BNEZ(REG_A0, 6);
+                               M_JSR(REG_RA, REG_ITMP3);
                                M_NOP;
+                               REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
+                               disp = (s4) (cd->mcodeptr - cd->mcodebase);
+                               M_LDA(REG_PV, REG_RA, -disp);
 
-                               M_LUI(REG_ITMP3, 0);
-                               M_OR_IMM(REG_ITMP3, 0, REG_ITMP3);
-                               codegen_add_nullpointerexception_ref(cd);
-                               M_AADD(REG_PV, REG_ITMP3, REG_ITMP3);
-                               M_JMP(REG_ITMP3);
-                               M_NOP;
+                               emit_exception_check(cd, iptr);
+                               break;
 
+                       case ICMD_INVOKESPECIAL:
+                               emit_nullpointer_check(cd, iptr, REG_A0);
                                /* fall through */
 
                        case ICMD_INVOKESTATIC:
@@ -3290,7 +3215,14 @@ gen_method:
                                        disp = dseg_add_address(cd, lm->stubroutine);
 
                                M_ALD(REG_PV, REG_PV, disp);          /* method pointer in pv */
-                               s1 = REG_PV;
+
+                               /* generate the actual call */
+
+                               M_JSR(REG_RA, REG_PV);
+                               M_NOP;
+                               REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
+                               disp = (s4) (cd->mcodeptr - cd->mcodebase);
+                               M_LDA(REG_PV, REG_RA, -disp);
                                break;
 
                        case ICMD_INVOKEVIRTUAL:
@@ -3305,9 +3237,17 @@ gen_method:
                                        s1 = OFFSET(vftbl_t, table[0]) +
                                                sizeof(methodptr) * lm->vftblindex;
 
+                               /* implicit null-pointer check */
                                M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_objectheader, vftbl));
                                M_ALD(REG_PV, REG_METHODPTR, s1);
-                               s1 = REG_PV;
+
+                               /* generate the actual call */
+
+                               M_JSR(REG_RA, REG_PV);
+                               M_NOP;
+                               REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
+                               disp = (s4) (cd->mcodeptr - cd->mcodebase);
+                               M_LDA(REG_PV, REG_RA, -disp);
                                break;
 
                        case ICMD_INVOKEINTERFACE:
@@ -3326,24 +3266,20 @@ gen_method:
                                        s2 = sizeof(methodptr) * (lm - lm->class->methods);
                                }
 
+                               /* implicit null-pointer check */
                                M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_objectheader, vftbl));
                                M_ALD(REG_METHODPTR, REG_METHODPTR, s1);
                                M_ALD(REG_PV, REG_METHODPTR, s2);
-                               s1 = REG_PV;
-                               break;
-                       }
 
-                       /* generate the actual call */
-
-                       M_JSR(REG_RA, s1);
-                       M_NOP;
-                       REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
-                       disp = (s4) (cd->mcodeptr - cd->mcodebase);
-                       M_LDA(REG_PV, REG_RA, -disp);
+                               /* generate the actual call */
 
-                       /* actually only used for ICMD_BUILTIN */
-
-                       emit_exception_check(cd, iptr);
+                               M_JSR(REG_RA, REG_PV);
+                               M_NOP;
+                               REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
+                               disp = (s4) (cd->mcodeptr - cd->mcodebase);
+                               M_LDA(REG_PV, REG_RA, -disp);
+                               break;
+                       }
 
                        /* store return value */
 
@@ -3412,25 +3348,10 @@ gen_method:
 
                                s1 = emit_load_s1(jd, iptr, REG_ITMP1);
 
-                               /* calculate interface checkcast code size */
-
-/*                             s2 = 3 + 2 + 1 + 2; */
-                               s2 = 3 + 7 + 1 + 7;
-                               if (super == NULL)
-                                       s2 += (opt_shownops ? PATCHER_CALL_INSTRUCTIONS : 0);
-
-                               /* calculate class checkcast code size */
-
-/*                             s3 = 2 + 1 + 4 + 1 + 2 /\* 10 + (s1 == REG_ITMP1) *\/; */
-                               s3 = 2 + 1 + 4 + 1 + 7;
-                               if (super == NULL)
-                                       s3 += (opt_shownops ? PATCHER_CALL_INSTRUCTIONS : 0);
-
                                /* if class is not resolved, check which code to call */
 
                                if (super == NULL) {
-                                       M_BEQZ(s1, 5 + (opt_shownops ? PATCHER_CALL_INSTRUCTIONS : 0) + s2 + 2 + s3);
-                                       M_NOP;
+                                       emit_label_beqz(cd, BRANCH_LABEL_1, s1);
 
                                        cr   = iptr->sx.s23.s3.c.ref;
                                        disp = dseg_add_unique_s4(cd, 0);         /* super->flags */
@@ -3438,11 +3359,9 @@ gen_method:
                                        codegen_add_patch_ref(cd, PATCHER_checkcast_instanceof_flags,
                                                                                  cr, disp);
 
-                                       /* XXX TWISTI M_ILD can be 2 instructions long (jump offset) */
                                        M_ILD(REG_ITMP2, REG_PV, disp);
                                        M_AND_IMM(REG_ITMP2, ACC_INTERFACE, REG_ITMP2);
-                                       M_BEQZ(REG_ITMP2, 1 + s2 + 2);
-                                       M_NOP;
+                                       emit_label_beqz(cd, BRANCH_LABEL_2, REG_ITMP2);
                                }
 
                                /* interface checkcast code */
@@ -3455,8 +3374,7 @@ gen_method:
                                                                                          cr, 0);
                                        }
                                        else {
-                                               M_BEQZ(s1, 1 + s2);
-                                               M_NOP;
+                                               emit_label_beqz(cd, BRANCH_LABEL_3, s1);
                                        }
 
                                        M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
@@ -3470,16 +3388,18 @@ gen_method:
                                                  superindex * sizeof(methodptr*));
                                        emit_classcast_check(cd, iptr, ICMD_IFEQ, REG_ITMP3, s1);
 
-                                       if (super == NULL) {
-                                               M_BR(1 + s3);
-                                               M_NOP;
-                                       }
+                                       if (super == NULL)
+                                               emit_label_br(cd, BRANCH_LABEL_4);
+                                       else
+                                               emit_label(cd, BRANCH_LABEL_3);
                                }
 
                                /* class checkcast code */
 
                                if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
                                        if (super == NULL) {
+                                               emit_label(cd, BRANCH_LABEL_2);
+
                                                cr   = iptr->sx.s23.s3.c.ref;
                                                disp = dseg_add_unique_address(cd, NULL);
 
@@ -3490,8 +3410,7 @@ gen_method:
                                        else {
                                                disp = dseg_add_address(cd, super->vftbl);
 
-                                               M_BEQZ(s1, 1 + s3);
-                                               M_NOP;
+                                               emit_label_beqz(cd, BRANCH_LABEL_5, s1);
                                        }
 
                                        M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
@@ -3518,6 +3437,14 @@ gen_method:
                                        /*                              } */
                                        M_CMPULT(REG_ITMP3, REG_ITMP2, REG_ITMP3);
                                        emit_classcast_check(cd, iptr, ICMD_IFNE, REG_ITMP3, s1);
+
+                                       if (super != NULL)
+                                               emit_label(cd, BRANCH_LABEL_5);
+                               }
+
+                               if (super == NULL) {
+                                       emit_label(cd, BRANCH_LABEL_1);
+                                       emit_label(cd, BRANCH_LABEL_4);
                                }
 
                                d = codegen_reg_of_dst(jd, iptr, s1);
@@ -3589,30 +3516,18 @@ gen_method:
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+
                        if (s1 == d) {
                                M_MOV(s1, REG_ITMP1);
                                s1 = REG_ITMP1;
                        }
 
-                       /* calculate interface instanceof code size */
-
-                       s2 = 7;
-                       if (super == NULL)
-                               s2 += (opt_shownops ? PATCHER_CALL_INSTRUCTIONS : 0);
-
-                       /* calculate class instanceof code size */
-
-                       s3 = 8;
-                       if (super == NULL)
-                               s3 += (opt_shownops ? PATCHER_CALL_INSTRUCTIONS : 0);
-
                        M_CLR(d);
 
                        /* if class is not resolved, check which code to call */
 
                        if (super == NULL) {
-                               M_BEQZ(s1, 5 + (opt_shownops ? PATCHER_CALL_INSTRUCTIONS : 0) + s2 + 2 + s3);
-                               M_NOP;
+                               emit_label_beqz(cd, BRANCH_LABEL_1, s1);
 
                                cr   = iptr->sx.s23.s3.c.ref;
                                disp = dseg_add_unique_s4(cd, 0);             /* super->flags */
@@ -3620,11 +3535,9 @@ gen_method:
                                codegen_add_patch_ref(cd, PATCHER_checkcast_instanceof_flags,
                                                                          cr, disp);
 
-                               /* XXX TWISTI M_ILD can be 2 instructions long (jump offset) */
                                M_ILD(REG_ITMP3, REG_PV, disp);
                                M_AND_IMM(REG_ITMP3, ACC_INTERFACE, REG_ITMP3);
-                               M_BEQZ(REG_ITMP3, 1 + s2 + 2);
-                               M_NOP;
+                               emit_label_beqz(cd, BRANCH_LABEL_2, REG_ITMP3);
                        }
 
                        /* interface instanceof code */
@@ -3637,8 +3550,7 @@ gen_method:
                                                                                  cr, 0);
                                }
                                else {
-                                       M_BEQZ(s1, 1 + s2);
-                                       M_NOP;
+                                       emit_label_beqz(cd, BRANCH_LABEL_3, s1);
                                }
 
                                M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
@@ -3652,16 +3564,18 @@ gen_method:
                                          superindex * sizeof(methodptr*));
                                M_CMPULT(REG_ZERO, REG_ITMP1, d);      /* REG_ITMP1 != 0  */
 
-                               if (super == NULL) {
-                                       M_BR(1 + s3);
-                                       M_NOP;
-                               }
+                               if (super == NULL)
+                                       emit_label_br(cd, BRANCH_LABEL_4);
+                               else
+                                       emit_label(cd, BRANCH_LABEL_3);
                        }
 
                        /* class instanceof code */
 
                        if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
                                if (super == NULL) {
+                                       emit_label(cd, BRANCH_LABEL_2);
+
                                        cr   = iptr->sx.s23.s3.c.ref;
                                        disp = dseg_add_unique_address(cd, NULL);
 
@@ -3671,8 +3585,7 @@ gen_method:
                                else {
                                        disp = dseg_add_address(cd, super->vftbl);
 
-                                       M_BEQZ(s1, 1 + s3);
-                                       M_NOP;
+                                       emit_label_beqz(cd, BRANCH_LABEL_5, s1);
                                }
 
                                M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
@@ -3689,7 +3602,16 @@ gen_method:
                                M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1); 
                                M_CMPULT(REG_ITMP2, REG_ITMP1, d);
                                M_XOR_IMM(d, 1, d);
+
+                               if (super != NULL)
+                                       emit_label(cd, BRANCH_LABEL_5);
                        }
+
+                       if (super == NULL) {
+                               emit_label(cd, BRANCH_LABEL_1);
+                               emit_label(cd, BRANCH_LABEL_4);
+                       }
+
                        emit_store_dst(jd, iptr, d);
                        }
                        break;
@@ -3783,14 +3705,11 @@ gen_method:
 
        dseg_createlinenumbertable(cd);
 
-       /* generate exception and patcher stubs */
+       /* generate stubs */
 
-       emit_exception_stubs(jd);
        emit_patcher_stubs(jd);
        REPLACEMENT_EMIT_STUBS(jd);
 
-       codegen_finish(jd);
-
        /* everything's ok */
 
        return true;
index d02ee11000cb93d7924cbaec96f7d858a975f25c..385902563fbbe69f3d0033a311e6f0e1ec3f141c 100644 (file)
@@ -1,6 +1,6 @@
 /* src/vm/jit/mips/codegen.h - code generation macros and definitions for MIPS
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
    J. Wenninger, Institut f. Computersprachen - TU Wien
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Andreas Krall
-            Christian Thalinger
-
-   $Id: codegen.h 7206 2007-01-11 22:39:52Z twisti $
+   $Id: codegen.h 7596 2007-03-28 21:05:53Z twisti $
 
 */
 
     do { \
         M_NOP; \
         M_NOP; \
-        M_NOP; \
-        M_NOP; \
-        M_NOP; \
     } while (0)
 
 
         cd->mcodeptr += 4; \
     } while (0)
 
+#define M_ITYPE_GET_RS(x)               (((x) >> 21) & 0x1f  )
+#define M_ITYPE_GET_RT(x)               (((x) >> 16) & 0x1f  )
+#define M_ITYPE_GET_IMM(x)              ( (x)        & 0xffff)
+
+
 #define M_JTYPE(op,imm) \
     do { \
         *((u4 *) cd->mcodeptr) = (((op) << 26) | ((off) & 0x3ffffff)); \
 #define M_BGEZ(a,disp)          M_ITYPE(0x01,a,1,disp)          /* br a >= 0  */
 #define M_BGTZ(a,disp)          M_ITYPE(0x07,a,0,disp)          /* br a >  0  */
 
+#if 0
 #define M_BEQL(a,b,disp)        M_ITYPE(0x14,a,b,disp)          /* br a == b  */
 #define M_BNEL(a,b,disp)        M_ITYPE(0x15,a,b,disp)          /* br a != b  */
 #define M_BEQZL(a,disp)         M_ITYPE(0x14,a,0,disp)          /* br a == 0  */
 #define M_BNEZL(a,disp)         M_ITYPE(0x15,a,0,disp)          /* br a != 0  */
 #define M_BGEZL(a,disp)         M_ITYPE(0x01,a,3,disp)          /* br a >= 0  */
 #define M_BGTZL(a,disp)         M_ITYPE(0x17,a,0,disp)          /* br a >  0  */
+#endif
 
 #define M_BR(disp)              M_ITYPE(0x04,0,0,disp)          /* branch     */
 #define M_BRS(disp)             M_ITYPE(0x01,0,17,disp)         /* branch sbr */
index cc06397e9a9901ac8214a059fd19a1c4e7fa83f3..6e7f7f61d5af6f8dfdd648f5c842406bc2f65cfc 100644 (file)
@@ -334,89 +334,118 @@ void emit_lconst(codegendata *cd, s4 d, s8 value)
 }
 
 
-/* emit_arithmetic_check *******************************************************
+/* emit_branch *****************************************************************
 
-   Emit an ArithmeticException check.
+   Emits the code for conditional and unconditional branchs.
+
+   NOTE: The reg argument may contain two packed registers.
 
 *******************************************************************************/
 
-void emit_arithmetic_check(codegendata *cd, instruction *iptr, s4 reg)
+void emit_branch(codegendata *cd, s4 disp, s4 condition, s4 reg, u4 opt)
 {
-       if (INSTRUCTION_MUST_CHECK(iptr)) {
-#if 0
-               M_BEQZ(reg, 0);
-               codegen_add_arithmeticexception_ref(cd);
-               M_NOP;
-#else
-               M_BNEZ(reg, 6);
-               M_NOP;
+       s4 checkdisp;
+       s4 branchdisp;
 
-               M_LUI(REG_ITMP3, 0);
-               M_OR_IMM(REG_ITMP3, 0, REG_ITMP3);
-               codegen_add_arithmeticexception_ref(cd);
-               M_AADD(REG_PV, REG_ITMP3, REG_ITMP3);
-               M_JMP(REG_ITMP3);
-               M_NOP;
-#endif
+       /* calculate the different displacements */
+
+       checkdisp  = (disp - 4);
+       branchdisp = (disp - 4) >> 2;
+
+       /* check which branch to generate */
+
+       if (condition == BRANCH_UNCONDITIONAL) {
+               /* check displacement for overflow */
+
+               if ((checkdisp < (s4) 0xffff8000) || (checkdisp > (s4) 0x00007fff)) {
+                       /* if the long-branches flag isn't set yet, do it */
+
+                       if (!CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
+                               cd->flags |= (CODEGENDATA_FLAG_ERROR |
+                                                         CODEGENDATA_FLAG_LONGBRANCHES);
+                       }
+
+                       vm_abort("emit_branch: emit unconditional long-branch code");
+               }
+               else {
+                       M_BR(branchdisp);
+                       M_NOP;
+               }
+       }
+       else {
+               /* and displacement for overflow */
+
+               if ((checkdisp < (s4) 0xffff8000) || (checkdisp > (s4) 0x00007fff)) {
+                       /* if the long-branches flag isn't set yet, do it */
+
+                       if (!CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
+                               cd->flags |= (CODEGENDATA_FLAG_ERROR |
+                                                         CODEGENDATA_FLAG_LONGBRANCHES);
+                       }
+
+                       vm_abort("emit_branch: emit conditional long-branch code");
+               }
+               else {
+                       switch (condition) {
+                       case BRANCH_EQ:
+                               M_BEQ(GET_HIGH_REG(reg), GET_LOW_REG(reg), branchdisp);
+                               break;
+                       case BRANCH_NE:
+                               M_BNE(GET_HIGH_REG(reg), GET_LOW_REG(reg), branchdisp);
+                               break;
+                       case BRANCH_LT:
+                               M_BLTZ(reg, branchdisp);
+                               break;
+                       case BRANCH_GE:
+                               M_BGEZ(reg, branchdisp);
+                               break;
+                       case BRANCH_GT:
+                               M_BGTZ(reg, branchdisp);
+                               break;
+                       case BRANCH_LE:
+                               M_BLEZ(reg, branchdisp);
+                               break;
+                       default:
+                               vm_abort("emit_branch: unknown condition %d", condition);
+                       }
+
+                       /* branch delay */
+                       M_NOP;
+               }
        }
 }
 
 
-/* emit_arrayindexoutofbounds_check ********************************************
+/* emit_arithmetic_check *******************************************************
 
-   Emit an ArrayIndexOutOfBoundsException check.
+   Emit an ArithmeticException check.
 
 *******************************************************************************/
 
-void emit_arrayindexoutofbounds_check(codegendata *cd, instruction *iptr, s4 s1, s4 s2)
+void emit_arithmetic_check(codegendata *cd, instruction *iptr, s4 reg)
 {
        if (INSTRUCTION_MUST_CHECK(iptr)) {
-               M_ILD(REG_ITMP3, s1, OFFSET(java_arrayheader, size));
-               M_CMPULT(s2, REG_ITMP3, REG_ITMP3);
-
-#if 0
-               M_BEQZ(REG_ITMP3, 0);
-               codegen_add_arrayindexoutofboundsexception_ref(cd, s2);
-               M_NOP;
-#else
-               M_BNEZ(REG_ITMP3, 6);
-               M_NOP;
-
-               M_LUI(REG_ITMP3, 0);
-               M_OR_IMM(REG_ITMP3, 0, REG_ITMP3);
-               codegen_add_arrayindexoutofboundsexception_ref(cd, s2);
-               M_AADD(REG_PV, REG_ITMP3, REG_ITMP3);
-               M_JMP(REG_ITMP3);
+               M_BNEZ(reg, 2);
                M_NOP;
-#endif
+               M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_ARITHMETIC);
        }
 }
 
 
-/* emit_arraystore_check *******************************************************
+/* emit_arrayindexoutofbounds_check ********************************************
 
-   Emit an ArrayStoreException check.
+   Emit an ArrayIndexOutOfBoundsException check.
 
 *******************************************************************************/
 
-void emit_arraystore_check(codegendata *cd, instruction *iptr, s4 reg)
+void emit_arrayindexoutofbounds_check(codegendata *cd, instruction *iptr, s4 s1, s4 s2)
 {
        if (INSTRUCTION_MUST_CHECK(iptr)) {
-#if 0
-               M_BEQZ(reg, 0);
-               codegen_add_arraystoreexception_ref(cd);
-               M_NOP;
-#else
-               M_BNEZ(reg, 6);
-               M_NOP;
-
-               M_LUI(REG_ITMP3, 0);
-               M_OR_IMM(REG_ITMP3, 0, REG_ITMP3);
-               codegen_add_arraystoreexception_ref(cd);
-               M_AADD(REG_PV, REG_ITMP3, REG_ITMP3);
-               M_JMP(REG_ITMP3);
+               M_ILD_INTERN(REG_ITMP3, s1, OFFSET(java_arrayheader, size));
+               M_CMPULT(s2, REG_ITMP3, REG_ITMP3);
+               M_BNEZ(REG_ITMP3, 2);
                M_NOP;
-#endif
+               M_ALD_INTERN(s2, REG_ZERO, EXCEPTION_HARDWARE_ARRAYINDEXOUTOFBOUNDS);
        }
 }
 
@@ -430,37 +459,25 @@ void emit_arraystore_check(codegendata *cd, instruction *iptr, s4 reg)
 void emit_classcast_check(codegendata *cd, instruction *iptr, s4 condition, s4 reg, s4 s1)
 {
        if (INSTRUCTION_MUST_CHECK(iptr)) {
-#if 0
-               M_BNEZ(reg, 0);
-               codegen_add_classcastexception_ref(cd, s1);
-               M_NOP;
-#else
                switch (condition) {
                case ICMD_IFEQ:
-                       M_BNEZ(reg, 6);
+                       M_BNEZ(reg, 2);
                        break;
 
                case ICMD_IFNE:
-                       M_BEQZ(reg, 6);
+                       M_BEQZ(reg, 2);
                        break;
 
                case ICMD_IFLE:
-                       M_BGTZ(reg, 6);
+                       M_BGTZ(reg, 2);
                        break;
 
                default:
-                       vm_abort("emit_classcast_check: condition %d not found", condition);
+                       vm_abort("emit_classcast_check: unknown condition %d", condition);
                }
 
                M_NOP;
-
-               M_LUI(REG_ITMP3, 0);
-               M_OR_IMM(REG_ITMP3, 0, REG_ITMP3);
-               codegen_add_classcastexception_ref(cd, s1);
-               M_AADD(REG_PV, REG_ITMP3, REG_ITMP3);
-               M_JMP(REG_ITMP3);
-               M_NOP;
-#endif
+               M_ALD_INTERN(s1, REG_ZERO, EXCEPTION_HARDWARE_CLASSCAST);
        }
 }
 
@@ -474,21 +491,9 @@ void emit_classcast_check(codegendata *cd, instruction *iptr, s4 condition, s4 r
 void emit_nullpointer_check(codegendata *cd, instruction *iptr, s4 reg)
 {
        if (INSTRUCTION_MUST_CHECK(iptr)) {
-#if 0
-               M_BEQZ(reg, 0);
-               codegen_add_nullpointerexception_ref(cd);
-               M_NOP;
-#else
-               M_BNEZ(reg, 6);
+               M_BNEZ(reg, 2);
                M_NOP;
-
-               M_LUI(REG_ITMP3, 0);
-               M_OR_IMM(REG_ITMP3, 0, REG_ITMP3);
-               codegen_add_nullpointerexception_ref(cd);
-               M_AADD(REG_PV, REG_ITMP3, REG_ITMP3);
-               M_JMP(REG_ITMP3);
-               M_NOP;
-#endif
+               M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_NULLPOINTER);
        }
 }
 
@@ -502,138 +507,9 @@ void emit_nullpointer_check(codegendata *cd, instruction *iptr, s4 reg)
 void emit_exception_check(codegendata *cd, instruction *iptr)
 {
        if (INSTRUCTION_MUST_CHECK(iptr)) {
-#if 0
-               M_BEQZ(REG_RESULT, 0);
-               codegen_add_fillinstacktrace_ref(cd);
-               M_NOP;
-#else
-               M_BNEZ(REG_RESULT, 6);
+               M_BNEZ(REG_RESULT, 2);
                M_NOP;
-
-               M_LUI(REG_ITMP3, 0);
-               M_OR_IMM(REG_ITMP3, 0, REG_ITMP3);
-               codegen_add_fillinstacktrace_ref(cd);
-               M_AADD(REG_PV, REG_ITMP3, REG_ITMP3);
-               M_JMP(REG_ITMP3);
-               M_NOP;
-#endif
-       }
-}
-
-
-/* emit_exception_stubs ********************************************************
-
-   Generates the code for the exception stubs.
-
-*******************************************************************************/
-
-void emit_exception_stubs(jitdata *jd)
-{
-       codegendata  *cd;
-       registerdata *rd;
-       exceptionref *er;
-       s4            branchmpc;
-       s4            targetmpc;
-       s4            targetdisp;
-       s4            disp;
-
-       /* get required compiler data */
-
-       cd = jd->cd;
-       rd = jd->rd;
-
-       /* generate exception stubs */
-
-       targetdisp = 0;
-
-       for (er = cd->exceptionrefs; er != NULL; er = er->next) {
-               /* back-patch the branch to this exception code */
-
-               branchmpc = er->branchpos;
-               targetmpc = cd->mcodeptr - cd->mcodebase;
-
-               md_codegen_patch_branch(cd, branchmpc, targetmpc);
-
-               MCODECHECK(100);
-
-               /* Check if the exception is an
-                  ArrayIndexOutOfBoundsException.  If so, move index register
-                  into REG_ITMP1. */
-
-               if (er->reg != -1)
-                       M_MOV(er->reg, REG_ITMP1);
-
-               /* calcuate exception address */
-
-               M_LDA(REG_ITMP2_XPC, REG_PV, er->branchpos - 4);
-
-               /* move function to call into REG_ITMP3 */
-
-               disp = dseg_add_functionptr(cd, er->function);
-               M_ALD(REG_ITMP3, REG_PV, disp);
-
-               if (targetdisp == 0) {
-                       targetdisp = ((u4 *) cd->mcodeptr) - ((u4 *) cd->mcodebase);
-
-                       M_MOV(REG_PV, REG_A0);
-                       M_MOV(REG_SP, REG_A1);
-
-                       if (jd->isleafmethod)
-                               M_MOV(REG_RA, REG_A2);
-                       else
-                               M_ALD(REG_A2, REG_SP, (cd->stackframesize - 1) * 8);
-
-                       M_MOV(REG_ITMP2_XPC, REG_A3);
-
-#if SIZEOF_VOID_P == 8
-                       /* XXX */
-                       M_MOV(REG_ITMP1, REG_A4);
-
-                       M_ASUB_IMM(REG_SP, 2 * 8, REG_SP);
-                       M_AST(REG_ITMP2_XPC, REG_SP, 0 * 8);
-
-                       if (jd->isleafmethod)
-                               M_AST(REG_RA, REG_SP, 1 * 8);
-#else
-                       M_ASUB_IMM(REG_SP, 5*4 + 2 * 8, REG_SP);
-                       M_AST(REG_ITMP2_XPC, REG_SP, 5*4 + 0 * 8);
-
-                       if (jd->isleafmethod)
-                               M_AST(REG_RA, REG_SP, 5*4 + 1 * 8);
-
-                       M_AST(REG_ITMP1, REG_SP, 4 * 4);
-#endif
-
-                       M_JSR(REG_RA, REG_ITMP3);
-                       M_NOP;
-                       M_MOV(REG_RESULT, REG_ITMP1_XPTR);
-
-#if SIZEOF_VOID_P == 8
-                       if (jd->isleafmethod)
-                               M_ALD(REG_RA, REG_SP, 1 * 8);
-
-                       M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
-                       M_AADD_IMM(REG_SP, 2 * 8, REG_SP);
-#else
-                       if (jd->isleafmethod)
-                               M_ALD(REG_RA, REG_SP, 5*4 + 1 * 8);
-
-                       M_ALD(REG_ITMP2_XPC, REG_SP, 5*4 + 0 * 8);
-                       M_AADD_IMM(REG_SP, 5*4 + 2 * 8, REG_SP);
-#endif
-
-                       disp = dseg_add_functionptr(cd, asm_handle_exception);
-                       M_ALD(REG_ITMP3, REG_PV, disp);
-                       M_JMP(REG_ITMP3);
-                       M_NOP;
-               }
-               else {
-                       disp = (((u4 *) cd->mcodebase) + targetdisp) -
-                               (((u4 *) cd->mcodeptr) + 1);
-
-                       M_BR(disp);
-                       M_NOP;
-               }
+               M_ALD_INTERN(REG_RESULT, REG_ZERO, EXCEPTION_HARDWARE_EXCEPTION);
        }
 }
 
index cb8e2639e0aa3dc7d3184e4ac0fd3691c969b918..9b7e618170f9045d8ff6e13ce05a9c295adff174 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: md-os.c 7252 2007-01-29 21:09:01Z twisti $
+   $Id: md-os.c 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
 }
 
 
index b8b0e9dff3de3a323113fb19aeec95ac51fa3933..55e48dd4799a4a37cc0d70847eb2ea857137a42e 100644 (file)
@@ -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 $
 
 */
 
 #endif
 
 
-/* md_codegen_patch_branch *****************************************************
-
-   Back-patches a branch instruction.
-
-*******************************************************************************/
-
-void md_codegen_patch_branch(codegendata *cd, s4 branchmpc, s4 targetmpc)
-{
-       s4 *mcodeptr;
-       s4  mcode;
-       s4  disp;                           /* branch displacement                */
-       s4  lo;
-       s4  hi;
-
-       /* calculate the patch position */
-
-       mcodeptr = (s4 *) (cd->mcodebase + branchmpc);
-
-       /* get the instruction before the exception point */
-
-       mcode = mcodeptr[-1];
-
-       /* check for: ori t9,t9,0 */
-
-       if ((mcode >> 16) == 0x3739) {
-               /* Calculate the branch displacement.  For jumps we need a
-                  displacement relative to PV. */
-
-               disp = targetmpc;
-
-        lo = (short) disp;
-        hi = (short) ((disp - lo) >> 16);
-
-               /* patch the two instructions before the mcodeptr */
-
-               mcodeptr[-2] |= (hi & 0x0000ffff);
-               mcodeptr[-1] |= (lo & 0x0000ffff);
-       }
-       else {
-               /* Calculate the branch displacement.  For branches we need a
-                  displacement relative and shifted to the branch PC. */
-
-               disp = (targetmpc - branchmpc) >> 2;
-
-               /* On the MIPS we can only branch signed 16-bit instruction words
-                  (signed 18-bit = 32KB = +/- 16KB). Check this! */
-
-               if ((disp < (s4) 0xffff8000) || (disp > (s4) 0x00007fff))
-                       vm_abort("jump displacement is out of range: %d > +/-%d", disp, 0x00007fff);
-
-               /* patch the branch instruction before the mcodeptr */
-
-               mcodeptr[-1] |= (disp & 0x0000ffff);
-       }
-}
-
-
 /* md_stacktrace_get_returnaddress *********************************************
 
    Returns the return address of the current stackframe, specified by
index 32a21599f8effb56ac219a012cb8b3b18a45ae06..dfe1cc22544917a6c0a043a8a39d2c74dbe83cce 100644 (file)
@@ -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;
index 7742cb28e52680f20564d34eefdff21555644479..dd383d346addb9bf3a149057a9eadbf1d39dee5d 100644 (file)
@@ -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 {
index efc5f2a4b1b41391b41c09a66f494fdbb124913f..901008ffa95cfd6920bc238298693ccf6d76f1df 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: arch.h 7241 2007-01-27 15:52:01Z twisti $
+   $Id: arch.h 7596 2007-03-28 21:05:53Z twisti $
 
 */
 
 #define SUPPORT_COMBINE_INTEGER_REGISTERS
 
 
+/* branches *******************************************************************/
+
+#define SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER       1
+#define SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER     0
+#define SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS    0
+
+
 /* exceptions *****************************************************************/
 
 #define SUPPORT_HARDWARE_DIVIDE_BY_ZERO  0
index a81f9220bee3c9f0ad1a6f66da0e86f518e1f485..47af22d8b5166726d051ef384a2d00f4c9f1b2b3 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: asmpart.S 7225 2007-01-18 12:55:53Z twisti $
+   $Id: asmpart.S 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 *******************************************************
 
index 3b9a60d40b0fe68174a6892832520fe8290eeb50..e1a10ca9216eeddeed3b0302a10261c17035c7c5 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: codegen.c 7293 2007-02-06 08:58:32Z twisti $
+   $Id: codegen.c 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;
index 1b6a3f82257c689f78428265624d2f95077bf1a5..01c32ba66eb4b1c0990ef7aa2e29af6b715b8b23 100644 (file)
@@ -1,7 +1,7 @@
 /* src/vm/jit/powerpc/codegen.h - code generation macros and definitions for
                                   32-bit PowerPC
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
    J. Wenninger, Institut f. Computersprachen - TU Wien
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Andreas Krall
-            Stefan Ring
-            Christian Thalinger
-            Christian Ullrich
-
-   $Id: codegen.h 6078 2006-11-28 22:19:16Z twisti $
+   $Id: codegen.h 7596 2007-03-28 21:05:53Z twisti $
 
 */
 
 
 #define BRANCH_NOPS \
     do { \
-        M_NOP; \
+        if (CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) { \
+            M_NOP; \
+            M_NOP; \
+        } \
+        else { \
+            M_NOP; \
+        } \
     } while (0)
 
 
         cd->mcodeptr += 4; \
     } while (0)
 
+#define M_OP3_GET_A(x)                (((x) >> 16) & 0x1f  )
+#define M_OP3_GET_B(x)                (((x) >> 11) & 0x1f  )
+
+
 #define M_OP4(x,y,rc,d,a,b,c) \
     do { \
         *((u4 *) cd->mcodeptr) = (((x) << 26) | ((d) << 21) | ((a) << 16) | ((b) << 11) | ((c) << 6) | ((y) << 1) | (rc)); \
         cd->mcodeptr += 4; \
     } while (0)
 
+
 #define M_OP2_IMM(x,d,a,i) \
     do { \
         *((u4 *) cd->mcodeptr) = (((x) << 26) | ((d) << 21) | ((a) << 16) | ((i) & 0xffff)); \
         cd->mcodeptr += 4; \
     } while (0)
 
+#define M_INSTR_OP2_IMM_D(x)            (((x) >> 21) & 0x1f  )
+#define M_INSTR_OP2_IMM_A(x)            (((x) >> 16) & 0x1f  )
+#define M_INSTR_OP2_IMM_I(x)            ( (x)        & 0xffff)
+
+
 #define M_BMASK     0x03fffffc                      /* (((1 << 26) - 1) & ~3) */
 #define M_BCMASK    0x0000fffc                      /* (((1 << 16) - 1) & ~3) */
 
 #define M_STWUX(a,b,c)                  M_OP3(31,183,0,0,a,b,c)
 
 #define M_LDAH(a,b,c)                   M_ADDIS(b, c, a)
+
 #define M_TRAP                          M_OP3(31, 4, 0, 0, 31, 0, 0)
+#define M_TRAPGEU(a,b)                  M_OP3(31, 4, 0, 0, 5, a, b)
 
 #define M_NOP                           M_OR_IMM(0, 0, 0)
 #define M_MOV(a,b)                      M_OR(a, a, b)
index c90f8d8bea1c947be76cf63d39f6929fecb51b9d..3a23bf810d325b6a6cd68d5fceb61dfa207cb59e 100644 (file)
@@ -26,9 +26,7 @@
 
    Authors: Christian Thalinger
 
-   Changes:
-
-   $Id: md-os.c 6123 2006-12-05 21:10:54Z twisti $
+   $Id: md-os.c 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;
 }
index 62ad7f1abe899cf3a81a3827e5896862cba91129..1b77a9f0c67591444869a5e9546ba3529b8e3652 100644 (file)
@@ -47,6 +47,7 @@
 #include "vm/exceptions.h"
 
 #include "vm/jit/asmpart.h"
+#include "vm/jit/codegen-common.h"
 #include "vm/jit/dseg.h"
 #include "vm/jit/emit-common.h"
 #include "vm/jit/jit.h"
@@ -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);
        }
 }
 
index c3f5ad36a9a6453c954804e48af2c0b6db5072a4..b0564bc38dafb2a7429039730c50b8171a90ced2 100644 (file)
@@ -1,6 +1,6 @@
 /* src/vm/jit/powerpc/linux/md-os.c - machine dependent PowerPC Linux functions
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
    J. Wenninger, Institut f. Computersprachen - TU Wien
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Christian Thalinger
-
-   $Id: md-os.c 5939 2006-11-09 09:54:00Z twisti $
+   $Id: md-os.c 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)
 
 /* md_signal_handler_sigsegv ***************************************************
 
-   NullPointerException signal handler for hardware null pointer
-   check.
+   Signal handler for hardware-exceptions.
 
 *******************************************************************************/
 
 void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
 {
-       ucontext_t  *_uc;
-       mcontext_t  *_mc;
-       u4           instr;
-       s4           reg;
-       ptrint       addr;
-       u1          *pv;
-       u1          *sp;
-       u1          *ra;
-       u1          *xpc;
+       ucontext_t        *_uc;
+       mcontext_t        *_mc;
+       u1                *pv;
+       u1                *sp;
+       u1                *ra;
+       u1                *xpc;
+       u4                 mcode;
+       s4                 s1;
+       s4                 disp;
+       s4                 d;
+       ptrint             addr;
+       ptrint             val;
+       s4                 type;
+       java_objectheader *o;
 
        _uc = (ucontext_t *) _p;
        _mc = _uc->uc_mcontext.uc_regs;
 
-       instr = *((u4 *) _mc->gregs[PT_NIP]);
-       reg = (instr >> 16) & 0x1f;
-       addr = _mc->gregs[reg];
-
        pv  = (u1 *) _mc->gregs[REG_PV];
        sp  = (u1 *) _mc->gregs[REG_SP];
        ra  = (u1 *) _mc->gregs[PT_LNK];         /* this is correct for leafs */
        xpc = (u1 *) _mc->gregs[PT_NIP];
 
-       if (addr == 0) {
-               _mc->gregs[REG_ITMP1_XPTR] =
-                       (ptrint) stacktrace_hardware_nullpointerexception(pv, sp, ra, xpc);
+       /* get exception-throwing instruction */
+
+       mcode = *((u4 *) xpc);
+
+       s1   = M_INSTR_OP2_IMM_A(mcode);
+       disp = M_INSTR_OP2_IMM_I(mcode);
+       d    = M_INSTR_OP2_IMM_D(mcode);
 
-               _mc->gregs[REG_ITMP2_XPC] = (ptrint) xpc;
-               _mc->gregs[PT_NIP] = (ptrint) asm_handle_exception;
+       val  = _mc->gregs[d];
+
+       /* check for special-load */
+
+       if (s1 == REG_ZERO) {
+               /* we use the exception type as load displacement */
+
+               type = disp;
        }
        else {
-               codegen_get_pv_from_pc(xpc);
+               /* This is a normal NPE: addr must be NULL and the NPE-type
+                  define is 0. */
+
+               addr = _mc->gregs[s1];
+               type = (s4) addr;
+       }
+
+       /* generate appropriate exception */
+
+       o = exceptions_new_hardware_exception(pv, sp, ra, xpc, type, val);
+
+       /* set registers */
+
+       _mc->gregs[REG_ITMP1_XPTR] = (ptrint) o;
+       _mc->gregs[REG_ITMP2_XPC]  = (ptrint) xpc;
+       _mc->gregs[PT_NIP]         = (ptrint) asm_handle_exception;
+}
+
+
+/* md_signal_handler_sigtrap ***************************************************
+
+   Signal handler for hardware-traps.
+
+*******************************************************************************/
+
+void md_signal_handler_sigtrap(int sig, siginfo_t *siginfo, void *_p)
+{
+       ucontext_t        *_uc;
+       mcontext_t        *_mc;
+       u1                *pv;
+       u1                *sp;
+       u1                *ra;
+       u1                *xpc;
+       u4                 mcode;
+       s4                 s1;
+       ptrint             val;
+       s4                 type;
+       java_objectheader *o;
+
+       _uc = (ucontext_t *) _p;
+       _mc = _uc->uc_mcontext.uc_regs;
+
+       pv  = (u1 *) _mc->gregs[REG_PV];
+       sp  = (u1 *) _mc->gregs[REG_SP];
+       ra  = (u1 *) _mc->gregs[PT_LNK];         /* this is correct for leafs */
+       xpc = (u1 *) _mc->gregs[PT_NIP];
+
+       /* get exception-throwing instruction */
+
+       mcode = *((u4 *) xpc);
+
+       s1 = M_OP3_GET_A(mcode);
+
+       /* for now we only handle ArrayIndexOutOfBoundsException */
+
+       type = EXCEPTION_HARDWARE_ARRAYINDEXOUTOFBOUNDS;
+       val  = _mc->gregs[s1];
+
+       /* generate appropriate exception */
+
+       o = exceptions_new_hardware_exception(pv, sp, ra, xpc, type, val);
 
-               /* this should not happen */
+       /* set registers */
 
-               assert(0);
-       }               
+       _mc->gregs[REG_ITMP1_XPTR] = (ptrint) o;
+       _mc->gregs[REG_ITMP2_XPC]  = (ptrint) xpc;
+       _mc->gregs[PT_NIP]         = (ptrint) asm_handle_exception;
 }
 
 
index 3ec67f0211e7bf1e3ea4eabfb86424480ede2ae7..227a37090b843796258f84103354997354bd1c43 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: md.c 7246 2007-01-29 18:49:05Z twisti $
+   $Id: md.c 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
index 77f12f21032d291580cc4b619587b21326952af9..275acb322a28a0a7688da7782fc2d5c8202c3507 100644 (file)
@@ -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:
 
    <patched call position>
-   81870000    lwz   r12,0(r7)
-   800c0010    lwz   r0,16(r12)
-   34000000    addic.        r0,r0,0
-   408101fc    ble-  0x3002e518
-   800c0000    lwz   r0,0(r12)
+   81870000    lwz     r12,0(r7)
+   800c0010    lwz     r0,16(r12)
+   34000000    addic.  r0,r0,0
+   41810008    bgt-    0x014135d8
+   83c00003    lwz     r30,3(0)
+   800c0000    lwz     r0,0(r12)
+
+*******************************************************************************/
+
+bool patcher_checkcast_interface(u1 *sp)
+{
+       u1                *ra;
+       constant_classref *cr;
+       classinfo         *c;
+       s4                 disp;
+
+       /* get stuff from the stack */
+
+       ra = (u1 *)                *((ptrint *) (sp + 5 * 4));
+       cr = (constant_classref *) *((ptrint *) (sp + 2 * 4));
+
+       /* get the fieldinfo */
+
+       if (!(c = resolve_classref_eager(cr)))
+               return false;
+
+       /* if we show NOPs, we have to skip them */
+
+       if (opt_shownops)
+               ra = ra + 1 * 4;
+
+       /* patch super class index */
+
+       disp = -(c->index);
+
+       *((s4 *) (ra + 2 * 4)) |= (disp & 0x0000ffff);
+
+       disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
+
+       *((s4 *) (ra + 5 * 4)) |= (disp & 0x0000ffff);
+
+       /* synchronize instruction cache */
+
+       md_icacheflush(ra + 2 * 4, 4 * 4);
+
+       return true;
+}
+
+
+/* patcher_instanceof_interface ************************************************
+
+   Machine code:
+
+   <patched call position>
+   81870000    lwz     r12,0(r7)
+   800c0010    lwz     r0,16(r12)
+   34000000    addic.  r0,r0,0
+   41810008    bgt-    0x014135d8
+   83c00003    lwz     r30,3(0)
+   800c0000    lwz     r0,0(r12)
 
 *******************************************************************************/
 
-bool patcher_checkcast_instanceof_interface(u1 *sp)
+bool patcher_instanceof_interface(u1 *sp)
 {
        u1                *ra;
        constant_classref *cr;
index 9231f2116194fab65a84851c9714724242427aca..6147447c515646f2c3864e346b2bd0804bd5753b 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: arch.h 7241 2007-01-27 15:52:01Z twisti $
+   $Id: arch.h 7596 2007-03-28 21:05:53Z twisti $
 
 */
 
 /* #define SUPPORT_COMBINE_INTEGER_REGISTERS */
 
 
+/* branches *******************************************************************/
+
+#define SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER       1
+#define SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER     0
+#define SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS    0
+
+
 /* exceptions *****************************************************************/
 
 #define SUPPORT_HARDWARE_DIVIDE_BY_ZERO  0
index 6ab2a0be04a6a916cee98f76c185aa20760ed8a9..49961cd1b47a7a273025fd9ba331d2bda83677b2 100644 (file)
    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"
 
 
 /* export functions ***********************************************************/
 
-#ifdef ENABLE_LIBJVM
-       .globl asm_vm_call_method
-       .globl asm_vm_call_method_int
-       .globl asm_vm_call_method_long
-       .globl asm_vm_call_method_float
-       .globl asm_vm_call_method_double
-#else
-       .globl .asm_vm_call_method
-       .globl .asm_vm_call_method_int
-       .globl .asm_vm_call_method_long
-       .globl .asm_vm_call_method_float
-       .globl .asm_vm_call_method_double
-#endif
        .globl asm_vm_call_method_exception_handler
+       .globl asm_vm_call_method_end
 
        .globl asm_call_jit_compiler
 
@@ -80,9 +70,9 @@
        .globl .asm_replacement_in
 #endif
 
-       .globl .asm_cacheflush          /* no function descriptor needed, only called direct */
+       .globl asm_cacheflush
        .globl asm_criticalsections
-       .globl .asm_getclassvalues_atomic
+       .globl asm_getclassvalues_atomic
 
 
 /* asm_vm_call_method **********************************************************
        .quad   0                           /* codeinfo pointer                   */
 
 #ifdef ENABLE_LIBJVM
+       
+       .globl asm_vm_call_method
+       .globl asm_vm_call_method_int
+       .globl asm_vm_call_method_long
+       .globl asm_vm_call_method_float
+       .globl asm_vm_call_method_double
        .section ".opd","aw"
        .align 3
 
 #else
        asm_vm_call_method:
        .globl asm_vm_call_method
+       asm_vm_call_method_int:
+       .globl asm_vm_call_method_int
+       asm_vm_call_method_long:
+       .globl asm_vm_call_method_long
+       asm_vm_call_method_float:
+       .globl asm_vm_call_method_float
+       asm_vm_call_method_double:
+       .globl asm_vm_call_method_double
 #endif
 
 .asm_vm_call_method:
@@ -632,6 +636,8 @@ L_handle_fda12:
        lfd     fa12,offvmargdata(itmp1)
        b       L_register_copy
 
+asm_vm_call_method_end:
+       nop
 
 /* asm_call_jit_compiler *******************************************************
 
@@ -1293,7 +1299,17 @@ asm_replacement_out:
 /* asm_cacheflush **************************************************************
        copied from linux/arch/ppc64/kernel/vdso64/cacheflush.S
        assumes 128 byte cache line size.
+       All registers used may be trashed for fun and profit.
 *******************************************************************************/
+
+       .section ".opd","aw"
+       .align 3
+asm_cacheflush:
+               .quad   .asm_cacheflush,.TOC.@tocbase,0
+               .previous
+               .size asm_cacheflush, 24
+               .type .asm_cacheflush,@function
+               .globl .asm_cacheflush 
 .asm_cacheflush:
        /* construct the AND mask */
        li      r6,   0xffffffffffff8000
@@ -1323,7 +1339,19 @@ asm_replacement_out:
        isync
        blr
 
+/*
+               asm_getclassvalues_atomic 
+*/
+       .section ".opd","aw"
+       .align 3
+asm_getclassvalues_atomic:
+               .quad   .asm_getclassvalues_atomic,.TOC.@tocbase,0
+               .previous
+               .size asm_getclassvalues_atomic, 24
+               .type .asm_getclassvalues_atomic,@function
+               .globl .asm_getclassvalues_atomic
 .asm_getclassvalues_atomic:
+
 _crit_restart:
 _crit_begin:
        lwz     r6,offbaseval(r3)
index 7f49dc864a8e0c7bb6d2a8dfcbbd11162e6bb257..a31cbd8d113a1c8483cf988615e9a24b950bb526 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: codegen.c 7311 2007-02-09 13:20:27Z twisti $
+   $Id: codegen.c 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"
 #include "vm/stringlocal.h"
 #include "vm/vm.h"
 
+#include "vm/jit/abi-asm.h"
+#include "vm/jit/md.h"
 #include "vm/jit/asmpart.h"
 #include "vm/jit/codegen-common.h"
 #include "vm/jit/dseg.h"
 #include "vm/jit/emit-common.h"
 #include "vm/jit/jit.h"
-#include "vm/jit/md.h"
 #include "vm/jit/parse.h"
 #include "vm/jit/patcher.h"
 #include "vm/jit/reg.h"
 #include "vm/jit/replace.h"
+#include "vm/jit/stacktrace.h"
+
+#include "vmcore/loader.h"
+#include "vmcore/options.h"
 
 #if defined(ENABLE_LSRA)
 # include "vm/jit/allocator/lsra.h"
 #endif
 
-#include "vmcore/loader.h"
-#include "vmcore/options.h"
+#if defined(ENABLE_THREADS)
+# include "threads/native/lock.h"
+#endif
 
 
-/* codegen *********************************************************************
+/* codegen_emit ****************************************************************
 
    Generates machine code.
 
 *******************************************************************************/
 
-bool codegen(jitdata *jd)
+bool codegen_emit(jitdata *jd)
 {
        methodinfo         *m;
        codeinfo           *code;
@@ -90,6 +95,7 @@ bool codegen(jitdata *jd)
        exception_entry    *ex;
        u2                  currentline;
        methodinfo         *lm;             /* local methodinfo for ICMD_INVOKE*  */
+       unresolved_method  *um;
        builtintable_entry *bte;
        methoddesc         *md;
        s4                  fieldtype;
@@ -236,11 +242,7 @@ bool codegen(jitdata *jd)
                                if (!IS_INMEMORY(var->flags)) {      /* reg arg -> register   */
                                        M_FLTMOVE(s2, var->vv.regoff);
                                } else {                                         /* reg arg -> spilled    */
-                                       if (IS_2_WORD_TYPE(t)) {
-                                               M_DST(s2, REG_SP, var->vv.regoff * 8);
-                                       } else {
-                                               M_DST(s2, REG_SP, var->vv.regoff * 8);  /*  F XXX */
-                                       }
+                                       M_DST(s2, REG_SP, var->vv.regoff * 8);
                                }
 
                        } else {                                 /* stack arguments       */
@@ -292,8 +294,8 @@ bool codegen(jitdata *jd)
                }
                else {
                        M_TST(rd->argintregs[0]);
-                       M_BEQ(0);
-                       codegen_add_nullpointerexception_ref(cd);
+                       M_BNE(1);
+                       M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_NULLPOINTER);
                }
 
                M_AST(rd->argintregs[0], REG_SP, s1 * 8);       /* rd->memuse * 8 */
@@ -335,13 +337,7 @@ bool codegen(jitdata *jd)
                if (bptr->flags >= BBREACHED) {
 
                /* branch resolving */
-
-               {
-               branchref *brefs;
-               for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
-                       md_codegen_patch_branch(cd, brefs->branchpos, bptr->mpc);
-                       }
-               }
+               codegen_resolve_branchrefs(cd, bptr);
 
                /* handle replacement points */
 
@@ -428,7 +424,7 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        M_TST(s1);
                        M_BEQ(0);
-                       codegen_add_nullpointerexception_ref(cd);
+                       emit_nullpointer_check(cd, iptr, s1);
                        break;
 
                /* constant operations ************************************************/
@@ -466,17 +462,15 @@ bool codegen(jitdata *jd)
                case ICMD_ACONST:     /* ...  ==> ..., constant                       */
 
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
-                       disp = dseg_add_address(cd, iptr->sx.val.anyptr);
 
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                               disp = dseg_add_unique_address(cd, iptr->sx.val.c.ref);
                                codegen_addpatchref(cd, PATCHER_aconst,
                                                                        iptr->sx.val.c.ref,
                                                                    disp);
-
-                               if (opt_showdisassemble)
-                                       M_NOP;
+                       } else  {
+                               disp = dseg_add_address(cd, iptr->sx.val.anyptr);
                        }
-
                        M_ALD(d, REG_PV, disp);
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -663,9 +657,7 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
-                       M_TST(s2);
-                       M_BEQ(0);
-                       codegen_add_arithmeticexception_ref(cd);
+                       emit_arithmetic_check(cd, iptr, s2);
 
                        M_DIV(s1, s2, d);
                        /* we need to test if divident was 0x8000000000000, bit OV is set in XER in this case */
@@ -685,9 +677,7 @@ bool codegen(jitdata *jd)
                case ICMD_LREM:       /* ..., val1, val2  ==> ..., val1 % val2        */
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       M_TST(s2);
-                       M_BEQ(0);
-                       codegen_add_arithmeticexception_ref(cd);
+                       emit_arithmetic_check(cd, iptr, s2);
 
                        M_DIV(s1, s2,  REG_ITMP3);      
                        /* we need to test if divident was 0x8000000000000, bit OV is set in XER in this case */
@@ -974,6 +964,7 @@ bool codegen(jitdata *jd)
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
                        /* XXX implement me!!! */
+                       vm_abort("codegen: implement ICMD_LCMP!");
                        emit_store_dst(jd, iptr, d);
                        break;
                        break;
@@ -1143,8 +1134,7 @@ bool codegen(jitdata *jd)
                        s2 = emit_load_s2(jd, iptr, REG_FTMP2);
                        M_FCMPU(s1, s2);
                        M_BNAN(1);
-                       M_BEQ(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_beq(cd, iptr->dst.block);
                        break;
 
                case ICMD_IF_FCMPNE:    /* ..., value, value ==> ...                  */
@@ -1153,10 +1143,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_FTMP1);
                        s2 = emit_load_s2(jd, iptr, REG_FTMP2);
                        M_FCMPU(s1, s2);
-                       M_BNAN(0);
-                       codegen_addreference(cd, iptr->dst.block);
-                       M_BNE(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_bnan(cd, iptr->dst.block);
+                       emit_bne(cd, iptr->dst.block);
                        break;
 
 
@@ -1166,10 +1154,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_FTMP1);
                        s2 = emit_load_s2(jd, iptr, REG_FTMP2);
                        M_FCMPU(s1, s2);
-                       M_BNAN(0);
-                       codegen_addreference(cd, iptr->dst.block);
-                       M_BLT(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_bnan(cd, iptr->dst.block);
+                       emit_blt(cd, iptr->dst.block);
                        break;
 
                case ICMD_IF_FCMPL_GT:  /* ..., value, value ==> ...                  */
@@ -1179,8 +1165,7 @@ bool codegen(jitdata *jd)
                        s2 = emit_load_s2(jd, iptr, REG_FTMP2);
                        M_FCMPU(s1, s2);
                        M_BNAN(1);
-                       M_BGT(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_bgt(cd, iptr->dst.block);
                        break;
 
                case ICMD_IF_FCMPL_LE:  /* ..., value, value ==> ...                  */
@@ -1189,10 +1174,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_FTMP1);
                        s2 = emit_load_s2(jd, iptr, REG_FTMP2);
                        M_FCMPU(s1, s2);
-                       M_BNAN(0);
-                       codegen_addreference(cd, iptr->dst.block);
-                       M_BLE(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_bnan(cd, iptr->dst.block);
+                       emit_ble(cd, iptr->dst.block);
                        break;
 
                case ICMD_IF_FCMPL_GE:  /* ..., value, value ==> ...                  */
@@ -1202,8 +1185,7 @@ bool codegen(jitdata *jd)
                        s2 = emit_load_s2(jd, iptr, REG_FTMP2);
                        M_FCMPU(s1, s2);
                        M_BNAN(1);
-                       M_BGE(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_bge(cd, iptr->dst.block);
                        break;
 
                case ICMD_IF_FCMPG_LT:  /* ..., value, value ==> ...                  */
@@ -1213,8 +1195,7 @@ bool codegen(jitdata *jd)
                        s2 = emit_load_s2(jd, iptr, REG_FTMP2);
                        M_FCMPU(s1, s2);
                        M_BNAN(1);
-                       M_BLT(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_blt(cd, iptr->dst.block);
                        break;
 
                case ICMD_IF_FCMPG_GT:  /* ..., value, value ==> ...                  */
@@ -1223,10 +1204,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_FTMP1);
                        s2 = emit_load_s2(jd, iptr, REG_FTMP2);
                        M_FCMPU(s1, s2);
-                       M_BNAN(0);
-                       codegen_addreference(cd, iptr->dst.block);
-                       M_BGT(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_bnan(cd, iptr->dst.block);
+                       emit_bgt(cd, iptr->dst.block);
                        break;
 
                case ICMD_IF_FCMPG_LE:  /* ..., value, value ==> ...                  */
@@ -1236,8 +1215,7 @@ bool codegen(jitdata *jd)
                        s2 = emit_load_s2(jd, iptr, REG_FTMP2);
                        M_FCMPU(s1, s2);
                        M_BNAN(1);
-                       M_BLE(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_ble(cd, iptr->dst.block);
                        break;
 
                case ICMD_IF_FCMPG_GE:  /* ..., value, value ==> ...                  */
@@ -1246,10 +1224,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_FTMP1);
                        s2 = emit_load_s2(jd, iptr, REG_FTMP2);
                        M_FCMPU(s1, s2);
-                       M_BNAN(0);
-                       codegen_addreference(cd, iptr->dst.block);
-                       M_BGE(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_bnan(cd, iptr->dst.block);
+                       emit_bge(cd, iptr->dst.block);
                        break;
 
 
@@ -1259,7 +1235,7 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                       gen_nullptr_check(s1);
+                       emit_nullpointer_check(cd, iptr, s1);
                        M_ILD(d, s1, OFFSET(java_arrayheader, size));
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1269,11 +1245,9 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                       if (INSTRUCTION_MUST_CHECK(iptr)) {
-                               gen_nullptr_check(s1);
-                               gen_bound_check;
-                       }
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_IADD_IMM(s2, OFFSET(java_bytearray, data[0]), REG_ITMP2);
+                       /* implicit null-pointer check */
                        M_LBZX(d, s1, REG_ITMP2);
                        M_BSEXT(d, d);
                        emit_store_dst(jd, iptr, d);
@@ -1284,13 +1258,11 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                       if (INSTRUCTION_MUST_CHECK(iptr)) {
-                               gen_nullptr_check(s1);
-                               gen_bound_check;
-                       }
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_SLL_IMM(s2, 1, REG_ITMP2);
                        M_IADD_IMM(REG_ITMP2, OFFSET(java_chararray, data[0]), REG_ITMP2);
-                       M_LHAX(d, s1, REG_ITMP2);
+                       /* implicit null-pointer check */
+                       M_LHZX(d, s1, REG_ITMP2);
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -1299,12 +1271,10 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                       if (INSTRUCTION_MUST_CHECK(iptr)) {
-                               gen_nullptr_check(s1);
-                               gen_bound_check;
-                       }
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_SLL_IMM(s2, 1, REG_ITMP2);
                        M_IADD_IMM(REG_ITMP2, OFFSET(java_shortarray, data[0]), REG_ITMP2);
+                       /* implicit null-pointer check */
                        M_LHAX(d, s1, REG_ITMP2);
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1314,13 +1284,11 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                       if (INSTRUCTION_MUST_CHECK(iptr)) {
-                               gen_nullptr_check(s1);
-                               gen_bound_check;
-                       }
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_SLL_IMM(s2, 2, REG_ITMP2);
                        M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray, data[0]), REG_ITMP2);
-                       M_LWZX(d, s1, REG_ITMP2);
+                       /* implicit null-pointer check */
+                       M_LWAX(d, s1, REG_ITMP2);
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -1329,12 +1297,10 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, PACK_REGS(REG_ITMP2, REG_ITMP1));
-                       if (INSTRUCTION_MUST_CHECK(iptr)) {
-                               gen_nullptr_check(s1);
-                               gen_bound_check;
-                       }
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_SLL_IMM(s2, 3, REG_ITMP2);
                        M_IADD(s1, REG_ITMP2, REG_ITMP2);
+                       /* implicit null-pointer check */
                        M_LLD_INTERN(d, REG_ITMP2, OFFSET(java_longarray, data[0]));
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1344,12 +1310,10 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
-                       if (INSTRUCTION_MUST_CHECK(iptr)) {
-                               gen_nullptr_check(s1);
-                               gen_bound_check;
-                       }
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_SLL_IMM(s2, 2, REG_ITMP2);
                        M_IADD_IMM(REG_ITMP2, OFFSET(java_floatarray, data[0]), REG_ITMP2);
+                       /* implicit null-pointer check */
                        M_LFSX(d, s1, REG_ITMP2);
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1359,12 +1323,10 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
-                       if (INSTRUCTION_MUST_CHECK(iptr)) {
-                               gen_nullptr_check(s1);
-                               gen_bound_check;
-                       }
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_SLL_IMM(s2, 3, REG_ITMP2);
                        M_IADD_IMM(REG_ITMP2, OFFSET(java_doublearray, data[0]), REG_ITMP2);
+                       /* implicit null-pointer check */
                        M_LFDX(d, s1, REG_ITMP2);
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1374,12 +1336,10 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                       if (INSTRUCTION_MUST_CHECK(iptr)) {
-                               gen_nullptr_check(s1);
-                               gen_bound_check;
-                       }
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_SLL_IMM(s2, 3, REG_ITMP2);
                        M_IADD_IMM(REG_ITMP2, OFFSET(java_objectarray, data[0]), REG_ITMP2);
+                       /* implicit null-pointer check */
                        M_ALDX(d, s1, REG_ITMP2);
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1389,12 +1349,10 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       if (INSTRUCTION_MUST_CHECK(iptr)) {
-                               gen_nullptr_check(s1);
-                               gen_bound_check;
-                       }
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
                        M_IADD_IMM(s2, OFFSET(java_bytearray, data[0]), REG_ITMP2);
+                       /* implicit null-pointer check */
                        M_STBX(s3, s1, REG_ITMP2);
                        break;
 
@@ -1402,13 +1360,11 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       if (INSTRUCTION_MUST_CHECK(iptr)) {
-                               gen_nullptr_check(s1);
-                               gen_bound_check;
-                       }
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
                        M_SLL_IMM(s2, 1, REG_ITMP2);
                        M_IADD_IMM(REG_ITMP2, OFFSET(java_chararray, data[0]), REG_ITMP2);
+                       /* implicit null-pointer check */
                        M_STHX(s3, s1, REG_ITMP2);
                        break;
 
@@ -1416,10 +1372,7 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       if (INSTRUCTION_MUST_CHECK(iptr)) {
-                               gen_nullptr_check(s1);
-                               gen_bound_check;
-                       }
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
                        M_SLL_IMM(s2, 1, REG_ITMP2);
                        M_IADD_IMM(REG_ITMP2, OFFSET(java_shortarray, data[0]), REG_ITMP2);
@@ -1430,13 +1383,11 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       if (INSTRUCTION_MUST_CHECK(iptr)) {
-                               gen_nullptr_check(s1);
-                               gen_bound_check;
-                       }
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
                        M_SLL_IMM(s2, 2, REG_ITMP2);
                        M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray, data[0]), REG_ITMP2);
+                       /* implicit null-pointer check */
                        M_STWX(s3, s1, REG_ITMP2);
                        break;
 
@@ -1444,13 +1395,11 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       if (INSTRUCTION_MUST_CHECK(iptr)) {
-                               gen_nullptr_check(s1);
-                               gen_bound_check;
-                       }
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
                        M_SLL_IMM(s2, 3, REG_ITMP2);
                        M_IADD_IMM(REG_ITMP2, OFFSET(java_longarray, data[0]), REG_ITMP2);
+                       /* implicit null-pointer check */
                        M_LSTX(s3, s1, REG_ITMP2);
                        break;
 
@@ -1458,13 +1407,11 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       if (INSTRUCTION_MUST_CHECK(iptr)) {
-                               gen_nullptr_check(s1);
-                               gen_bound_check;
-                       }
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_FTMP3);
                        M_SLL_IMM(s2, 2, REG_ITMP2);
                        M_IADD_IMM(REG_ITMP2, OFFSET(java_floatarray, data[0]), REG_ITMP2);
+                       /* implicit null-pointer check */
                        M_STFSX(s3, s1, REG_ITMP2);
                        break;
 
@@ -1472,44 +1419,38 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       if (INSTRUCTION_MUST_CHECK(iptr)) {
-                               gen_nullptr_check(s1);
-                               gen_bound_check;
-                       }
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_FTMP3);
                        M_SLL_IMM(s2, 3, REG_ITMP2);
                        M_IADD_IMM(REG_ITMP2, OFFSET(java_doublearray, data[0]), REG_ITMP2);
+                       /* implicit null-pointer check */
                        M_STFDX(s3, s1, REG_ITMP2);
                        break;
 
                case ICMD_AASTORE:    /* ..., arrayref, index, value  ==> ...         */
 
-                       s1 = emit_load_s1(jd, iptr, rd->argintregs[0]);
+                       s1 = emit_load_s1(jd, iptr, REG_A0);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       if (INSTRUCTION_MUST_CHECK(iptr)) {
-                               gen_nullptr_check(s1);
-                               gen_bound_check;
-                       }
-                       s3 = emit_load_s3(jd, iptr, rd->argintregs[1]);
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
+                       s3 = emit_load_s3(jd, iptr, REG_A1);
 
                        disp = dseg_add_functionptr(cd, BUILTIN_canstore);
                        M_ALD(REG_ITMP3, REG_PV, disp);
                        M_ALD(REG_ITMP3, REG_ITMP3, 0); /* TOC */
                        M_MTCTR(REG_ITMP3);
 
-                       M_INTMOVE(s1, rd->argintregs[0]);
-                       M_INTMOVE(s3, rd->argintregs[1]);
+                       M_INTMOVE(s1, REG_A0);
+                       M_INTMOVE(s3, REG_A1);
 
                        M_JSR;
-                       M_TST(REG_RESULT);
-                       M_BEQ(0);
-                       codegen_add_arraystoreexception_ref(cd);
+                       emit_exception_check(cd, iptr);
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
                        M_SLL_IMM(s2, 3, REG_ITMP2);
                        M_IADD_IMM(REG_ITMP2, OFFSET(java_objectarray, data[0]), REG_ITMP2);
+                       /* implicit null-pointer check */
                        M_ASTX(s3, s1, REG_ITMP2);
                        break;
 
@@ -1613,7 +1554,6 @@ bool codegen(jitdata *jd)
                case ICMD_GETFIELD:   /* ...  ==> ..., value                          */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       gen_nullptr_check(s1);
 
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
                                uf = iptr->sx.s23.s3.uf;
@@ -1621,16 +1561,13 @@ bool codegen(jitdata *jd)
                                disp = 0;
 
                                codegen_addpatchref(cd, PATCHER_get_putfield, uf, 0);
-
-                               if (opt_showdisassemble)
-                                       M_NOP;
-
                        } else {
                                fi = iptr->sx.s23.s3.fmiref->p.field;
                                fieldtype = fi->type;
                                disp = fi->offset;
                        }
 
+                       /* implicit null-pointer check */
                        switch (fieldtype) {
                        case TYPE_INT:
                                d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
@@ -1659,7 +1596,6 @@ bool codegen(jitdata *jd)
                case ICMD_PUTFIELD:   /* ..., value  ==> ...                          */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       gen_nullptr_check(s1);
 
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
                                uf        = iptr->sx.s23.s3.uf;
@@ -1680,12 +1616,10 @@ bool codegen(jitdata *jd)
 
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
                                codegen_addpatchref(cd, PATCHER_get_putfield, uf, 0);
-
-                               if (opt_showdisassemble)
-                                       M_NOP;
                        }
 
 
+                       /* implicit null-pointer check */
                        switch (fieldtype) {
                        case TYPE_INT:
                                M_IST(s2, s1, disp);
@@ -1717,9 +1651,6 @@ bool codegen(jitdata *jd)
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
                                codegen_addpatchref(cd, PATCHER_athrow_areturn,
                                                                        iptr->sx.s23.s2.uc, 0);
-
-                               if (opt_showdisassemble)
-                                       M_NOP;
                        }
 #endif /* ENABLE_VERIFIER */
 
@@ -1739,15 +1670,13 @@ bool codegen(jitdata *jd)
                case ICMD_GOTO:         /* ... ==> ...                                */
                case ICMD_RET:          /* ... ==> ...                                */
 
-                       M_BR(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_br(cd, iptr->dst.block);
                        ALIGNCODENOP;
                        break;
 
                case ICMD_JSR:          /* ... ==> ...                                */
 
-                       M_BR(0);
-                       codegen_addreference(cd, iptr->sx.s23.s3.jsrtarget.block);
+                       emit_br(cd, iptr->sx.s23.s3.jsrtarget.block);
                        ALIGNCODENOP;
                        break;
 
@@ -1755,16 +1684,14 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        M_TST(s1);
-                       M_BEQ(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_beq(cd, iptr->dst.block);
                        break;
 
                case ICMD_IFNONNULL:    /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        M_TST(s1);
-                       M_BNE(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_bne(cd, iptr->dst.block);
                        break;
 
                case ICMD_IFLT:
@@ -1781,71 +1708,45 @@ bool codegen(jitdata *jd)
                                ICONST(REG_ITMP2, iptr->sx.val.i);
                                M_CMP(s1, REG_ITMP2);
                        }
-                       switch (iptr->opc) {
-                       case ICMD_IFLT:
-                               M_BLT(0);
-                               break;
-                       case ICMD_IFLE:
-                               M_BLE(0);
-                               break;
-                       case ICMD_IFNE:
-                               M_BNE(0);
-                               break;
-                       case ICMD_IFGT:
-                               M_BGT(0);
-                               break;
-                       case ICMD_IFGE:
-                               M_BGE(0);
-                               break;
-                       case ICMD_IFEQ:
-                               M_BEQ(0);
-                               break;
-                       }
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IFEQ, BRANCH_OPT_NONE);
                        break;
                        
                case ICMD_IF_LEQ:       /* ..., value ==> ...                         */
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        LCONST(REG_ITMP2, iptr->sx.val.l);
                        M_CMP(s1, REG_ITMP2);
-                       M_BEQ(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_beq(cd, iptr->dst.block);
                        break;
                case ICMD_IF_LLT:       /* ..., value ==> ...                         */
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        LCONST(REG_ITMP2, iptr->sx.val.l);
                        M_CMP(s1, REG_ITMP2);
-                       M_BLT(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_blt(cd, iptr->dst.block);
                        break;
                case ICMD_IF_LLE:       /* ..., value ==> ...                         */
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        LCONST(REG_ITMP2, iptr->sx.val.l);
                        M_CMP(s1, REG_ITMP2);
-                       M_BLE(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_ble(cd, iptr->dst.block);
                        break;
 
                case ICMD_IF_LNE:       /* ..., value ==> ... */
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        LCONST(REG_ITMP2, iptr->sx.val.l);
                        M_CMP(s1, REG_ITMP2);
-                       M_BNE(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_bne(cd, iptr->dst.block);
                        break;
                case ICMD_IF_LGE:       /* ..., value ==> ... */
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        LCONST(REG_ITMP2, iptr->sx.val.l);
                        M_CMP(s1, REG_ITMP2);
-                       M_BGE(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_bge(cd, iptr->dst.block);
                        break;
                case ICMD_IF_LGT:       /* ..., value ==> ...                         */
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        LCONST(REG_ITMP2, iptr->sx.val.l);
                        M_CMP(s1, REG_ITMP2);
-                       M_BGT(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_bgt(cd, iptr->dst.block);
                        break;
                case ICMD_IF_ICMPEQ:    /* ..., value, value ==> ...                  */
                case ICMD_IF_ACMPEQ:    /* op1 = target JavaVM pc                     */
@@ -1854,8 +1755,7 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_CMP(s1, s2);
-                       M_BEQ(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_beq(cd, iptr->dst.block);
                        break;
 
                case ICMD_IF_ICMPNE:    /* ..., value, value ==> ...                  */
@@ -1865,8 +1765,7 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_CMP(s1, s2);
-                       M_BNE(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_bne(cd, iptr->dst.block);
                        break;
 
 
@@ -1876,8 +1775,7 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_CMP(s1, s2);
-                       M_BLT(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_blt(cd, iptr->dst.block);
                        break;
 
                case ICMD_IF_ICMPGT:    /* ..., value, value ==> ...                  */
@@ -1886,8 +1784,7 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_CMP(s1, s2);
-                       M_BGT(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_bgt(cd, iptr->dst.block);
                        break;
 
                case ICMD_IF_ICMPLE:    /* ..., value, value ==> ...                  */
@@ -1896,8 +1793,7 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_CMP(s1, s2);
-                       M_BLE(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_ble(cd, iptr->dst.block);
                        break;
 
                case ICMD_IF_ICMPGE:    /* ..., value, value ==> ...                  */
@@ -1906,8 +1802,7 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_CMP(s1, s2);
-                       M_BGE(0);
-                       codegen_addreference(cd, iptr->dst.block);
+                       emit_bge(cd, iptr->dst.block);
                        break;
 
 
@@ -1929,9 +1824,6 @@ bool codegen(jitdata *jd)
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
                                codegen_addpatchref(cd, PATCHER_athrow_areturn,
                                                                        iptr->sx.s23.s2.uc, 0);
-
-                               if (opt_showdisassemble)
-                                       M_NOP;
                        }
 #endif /* ENABLE_VERIFIER */
 
@@ -2065,8 +1957,7 @@ nowperformreturn:
                        /* range check */
 
                        M_CMPUI(REG_ITMP1, i - 1);
-                       M_BGT(0);
-                       codegen_addreference(cd, table[0].block);
+                       emit_bgt(cd, table[0].block);
 
                        /* build jump table top down and use address of lowest entry */
 
@@ -2075,7 +1966,6 @@ nowperformreturn:
                        while (--i >= 0) {
                                dseg_add_target(cd, table->block); 
                                --table;
-                               }
                        }
 
                        /* length of dataseg after last dseg_add_unique_target is used by load */
@@ -2086,6 +1976,7 @@ nowperformreturn:
                        M_MTCTR(REG_ITMP2);
                        M_RTS;
                        ALIGNCODENOP;
+                       }
                        break;
 
 
@@ -2104,18 +1995,17 @@ nowperformreturn:
                                val = lookup->value;
                                if ((val >= -32768) && (val <= 32767)) {
                                        M_CMPI(s1, val);
+                       
                                } else {
                                        a = dseg_add_s4(cd, val);
                                        M_ILD(REG_ITMP2, REG_PV, a);
                                        M_CMP(s1, REG_ITMP2);
                                }
-                               M_BEQ(0);
-                               codegen_addreference(cd, lookup->target.block);
+                               emit_beq(cd, lookup->target.block);
                                ++lookup;
                        }
 
-                       M_BR(0);
-                       codegen_addreference(cd, iptr->sx.s23.s3.lookupdefault.block);
+                       emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
 
                        ALIGNCODENOP;
                        break;
@@ -2136,11 +2026,13 @@ nowperformreturn:
                        REPLACEMENT_POINT_INVOKE(cd, iptr);
 
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
-                               md = iptr->sx.s23.s3.um->methodref->parseddesc.md;
                                lm = NULL;
+                               um = iptr->sx.s23.s3.um;
+                               md = um->methodref->parseddesc.md;
                        }
                        else {
                                lm = iptr->sx.s23.s3.fmiref->p.method;
+                               um = NULL;
                                md = lm->parseddesc;
                        }
 
@@ -2173,10 +2065,7 @@ gen_method:
                                                M_FLTMOVE(d, s1);
                                        } else {
                                                d = emit_load(jd, iptr, var, REG_FTMP1);
-                                               if (IS_2_WORD_TYPE(var->type))
-                                                       M_DST(d, REG_SP, md->params[s3].regoff * 8);
-                                               else
-                                                       M_DST(d, REG_SP, md->params[s3].regoff * 8);    /* F XXX */
+                                               M_DST(d, REG_SP, md->params[s3].regoff * 8);
                                        }
                                }
                        } /* end of for */
@@ -2184,81 +2073,62 @@ gen_method:
                        switch (iptr->opc) {
                        case ICMD_BUILTIN:
                                disp = dseg_add_functionptr(cd, bte->fp);
-                               d = md->returntype.type;
+                               M_ALD(REG_PV, REG_PV, disp);
+                               M_ALD(REG_PV, REG_PV, 0);       /* TOC */
 
-                               M_ALD(REG_PV, REG_PV, disp);    /* pointer to built-in-function descriptor */
-                               M_ALD(REG_ITMP1, REG_PV, 0);    /* function entry point address, what about TOC */
-                               M_MTCTR(REG_ITMP1);
+                               /* generate the actual call */
+                               REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
+                               M_MTCTR(REG_PV);
                                M_JSR;
                                REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
                                disp = (s4) (cd->mcodeptr - cd->mcodebase);
                                M_MFLR(REG_ITMP1);
                                M_LDA(REG_PV, REG_ITMP1, -disp);
 
-                               if (INSTRUCTION_MUST_CHECK(iptr)) {
-                                       M_CMPI(REG_RESULT, 0);
-                                       M_BEQ(0);
-                                       codegen_add_fillinstacktrace_ref(cd);
-                               }
+                               emit_exception_check(cd, iptr);
                                break;
 
+
                        case ICMD_INVOKESPECIAL:
-                               gen_nullptr_check(rd->argintregs[0]);
-                               M_ILD(REG_ITMP1, rd->argintregs[0], 0); /* hardware nullptr   */
+                               emit_nullpointer_check(cd, iptr, REG_A0);
                                /* fall through */
 
                        case ICMD_INVOKESTATIC:
                                if (lm == NULL) {
-                                       unresolved_method *um = iptr->sx.s23.s3.um;
-
-                                       disp = dseg_add_unique_address(cd, NULL);
+                                       disp = dseg_add_unique_address(cd, um);
 
                                        codegen_addpatchref(cd, PATCHER_invokestatic_special,
                                                                                um, disp);
-
-                                       if (opt_showdisassemble)
-                                               M_NOP;
-
-                                       d = md->returntype.type;
-
                                } else {
                                        disp = dseg_add_address(cd, lm->stubroutine);
-                                       d = md->returntype.type;
                                }
-
-                               M_NOP;
                                M_ALD(REG_PV, REG_PV, disp);
+
+                               /* generate the actual call */
+
                                M_MTCTR(REG_PV);
                                M_JSR;
                                REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
                                disp = (s4) (cd->mcodeptr - cd->mcodebase);
                                M_MFLR(REG_ITMP1);
                                M_LDA(REG_PV, REG_ITMP1, -disp);
-                               break;
 
+                               break;
                        case ICMD_INVOKEVIRTUAL:
-                               gen_nullptr_check(rd->argintregs[0]);
-
                                if (lm == NULL) {
-                                       unresolved_method *um = iptr->sx.s23.s3.um;
-
                                        codegen_addpatchref(cd, PATCHER_invokevirtual, um, 0);
-
-                                       if (opt_showdisassemble)
-                                               M_NOP;
-
                                        s1 = 0;
-                                       d = md->returntype.type;
-
                                } else {
                                        s1 = OFFSET(vftbl_t, table[0]) +
                                                sizeof(methodptr) * lm->vftblindex;
-                                       d = md->returntype.type;
                                }
 
-                               M_ALD(REG_METHODPTR, rd->argintregs[0],
-                                         OFFSET(java_objectheader, vftbl));
+                               /* implicit null-pointer check */
+                               M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_objectheader, vftbl));
                                M_ALD(REG_PV, REG_METHODPTR, s1);
+
+                               /* generate the actual call */
+
                                M_MTCTR(REG_PV);
                                M_JSR;
                                REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
@@ -2268,43 +2138,38 @@ gen_method:
                                break;
 
                        case ICMD_INVOKEINTERFACE:
-                               gen_nullptr_check(rd->argintregs[0]);
-
                                if (lm == NULL) {
-                                       unresolved_method *um = iptr->sx.s23.s3.um;
-
                                        codegen_addpatchref(cd, PATCHER_invokeinterface, um, 0);
 
-                                       if (opt_showdisassemble)
-                                               M_NOP;
-
                                        s1 = 0;
                                        s2 = 0;
-                                       d = md->returntype.type;
 
                                } else {
                                        s1 = OFFSET(vftbl_t, interfacetable[0]) -
                                                sizeof(methodptr*) * lm->class->index;
 
                                        s2 = sizeof(methodptr) * (lm - lm->class->methods);
-
-                                       d = md->returntype.type;
                                }
 
-                               M_ALD(REG_METHODPTR, rd->argintregs[0],
-                                         OFFSET(java_objectheader, vftbl));    
+                               /* implicit null-pointer check */
+                               M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_objectheader, vftbl));    
                                M_ALD(REG_METHODPTR, REG_METHODPTR, s1);
                                M_ALD(REG_PV, REG_METHODPTR, s2);
+
+                               /* generate the actual call */
+
                                M_MTCTR(REG_PV);
                                M_JSR;
                                REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
                                disp = (s4) (cd->mcodeptr - cd->mcodebase);
                                M_MFLR(REG_ITMP1);
                                M_LDA(REG_PV, REG_ITMP1, -disp);
+
                                break;
                        }
+                       /* store return value */
 
-                       /* d contains return type */
+                       d = md->returntype.type;
 
                        if (d != TYPE_VOID) {
                                if (IS_INT_LNG_TYPE(d)) {
@@ -2319,7 +2184,6 @@ gen_method:
                        }
                        break;
 
-
                case ICMD_CHECKCAST:  /* ..., objectref ==> ..., objectref            */
                                      /* val.a: (classinfo*) superclass               */
 
@@ -2357,32 +2221,35 @@ gen_method:
 
                                /* calculate interface checkcast code size */
 
-                               s2 = 7;
+                               s2 = 9;
+#if defined(SOFTEX)
+                               s2 += CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd) ? 2 : 0;
+#endif
                                if (super == NULL)
-                                       s2 += (opt_showdisassemble ? 1 : 0);
+                                       s2 += (opt_shownops ? 1 : 0);
 
                                /* calculate class checkcast code size */
 
-                               s3 = 9 + (s1 == REG_ITMP1);
+                               s3 = 10 + (s1 == REG_ITMP1);
+#if defined(SOFTEX)
+                               s3 += CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd) ? 1 : 0;
+#endif
                                if (super == NULL)
-                                       s3 += (opt_showdisassemble ? 1 : 0);
+                                       s3 += (opt_shownops ? 1 : 0);
 
                                /* if class is not resolved, check which code to call */
 
                                if (super == NULL) {
                                        M_TST(s1);
-                                       M_BEQ(3 + (opt_showdisassemble ? 1 : 0) + s2 + 1 + s3);
+                                       M_BEQ(3 + (opt_shownops ? 1 : 0) + s2 + 1 + s3);
 
-                                       disp = dseg_add_s4(cd, 0);                     /* super->flags */
+                                       disp = dseg_add_unique_s4(cd, 0);                     /* super->flags */
 
                                        codegen_addpatchref(cd,
                                                                                PATCHER_checkcast_instanceof_flags,
                                                                                iptr->sx.s23.s3.c.ref,
                                                                                disp);
 
-                                       if (opt_showdisassemble)
-                                               M_NOP;
-
                                        M_ILD(REG_ITMP2, REG_PV, disp);
                                        M_AND_IMM(REG_ITMP2, ACC_INTERFACE, REG_ITMP2);
                                        M_BEQ(s2 + 1);
@@ -2393,12 +2260,9 @@ gen_method:
                                if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
                                        if (super == NULL) {
                                                codegen_addpatchref(cd,
-                                                                                       PATCHER_checkcast_instanceof_interface,
+                                                                                       PATCHER_checkcast_interface,
                                                                                        iptr->sx.s23.s3.c.ref,
                                                                                        0);
-                                               if (opt_showdisassemble)
-                                                       M_NOP;
-
                                        } else {
                                                M_TST(s1);
                                                M_BEQ(s2);
@@ -2407,14 +2271,12 @@ gen_method:
                                        M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
                                        M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
                                        M_LDATST(REG_ITMP3, REG_ITMP3, -superindex);
-                                       M_BLE(0);
-                                       codegen_add_classcastexception_ref(cd, s1);     /*XXX s1?? */
+                                       emit_classcast_check(cd, iptr, BRANCH_LE, REG_ITMP3, s1);
                                        M_ALD(REG_ITMP3, REG_ITMP2,
                                                  OFFSET(vftbl_t, interfacetable[0]) -
                                                  superindex * sizeof(methodptr*));
                                        M_TST(REG_ITMP3);
-                                       M_BEQ(0);
-                                       codegen_add_classcastexception_ref(cd, s1);     /*XXX s1??*/
+                                       emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ITMP3, s1);
 
                                        if (!super)
                                                M_BR(s3);
@@ -2424,12 +2286,10 @@ gen_method:
 
                                if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
                                        if (super == NULL) {
-                                               disp = dseg_add_address(cd, NULL);
+                                               disp = dseg_add_unique_address(cd, NULL);
                                                codegen_addpatchref(cd, PATCHER_checkcast_class,
                                                                                        iptr->sx.s23.s3.c.ref,
                                                                                        disp);
-                                               if (opt_showdisassemble)
-                                                       M_NOP;
                                        } else {
                                                disp = dseg_add_address(cd, super->vftbl);
                                                M_TST(s1);
@@ -2461,8 +2321,7 @@ gen_method:
 #endif
                                        }
                                        M_CMPU(REG_ITMP3, REG_ITMP2);
-                                       M_BGT(0);
-                                       codegen_add_classcastexception_ref(cd, s1); /* XXX s1? */
+                                       emit_classcast_check(cd, iptr, BRANCH_GT, REG_ITMP3, s1);
                                }
                                d = codegen_reg_of_dst(jd, iptr, s1);
 
@@ -2474,13 +2333,10 @@ gen_method:
 
 
                                if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
-                                       disp = dseg_add_address(cd, NULL);
+                                       disp = dseg_add_unique_address(cd, NULL);
                                        codegen_addpatchref(cd, PATCHER_builtin_arraycheckcast,
                                                                                iptr->sx.s23.s3.c.ref,
                                                                                disp);
-
-                                       if (opt_showdisassemble)
-                                               M_NOP;
                                } else {
                                        disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
                                }
@@ -2492,8 +2348,7 @@ gen_method:
                                M_MTCTR(REG_ITMP2);
                                M_JSR;
                                M_TST(REG_RESULT);
-                               M_BEQ(0);
-                               codegen_add_classcastexception_ref(cd, s1); /* XXX s1? */
+                               emit_classcast_check(cd, iptr, BRANCH_EQ, REG_RESULT, s1);
 
                                s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                                d = codegen_reg_of_dst(jd, iptr, s1);
@@ -2502,6 +2357,7 @@ gen_method:
                        emit_store_dst(jd, iptr, d);
                        break;
 
+
                case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult            */
                                      /* val.a: (classinfo*) superclass               */
 
@@ -2548,30 +2404,27 @@ gen_method:
 
                        s2 = 8;
                        if (!super)
-                               s2 += (opt_showdisassemble ? 1 : 0);
+                               s2 += (opt_shownops ? 1 : 0);
 
                        /* calculate class instanceof code size */
 
-                       s3 = 10;
-                       if (!super)
-                               s3 += (opt_showdisassemble ? 1 : 0);
+                       s3 = 11;
+                       if (super == NULL)
+                               s3 += (opt_shownops ? 1 : 0);
 
                        M_CLR(d);
 
                        /* if class is not resolved, check which code to call */
 
-                       if (!super) {
+                       if (super == NULL) {
                                M_TST(s1);
-                               M_BEQ(3 + (opt_showdisassemble ? 1 : 0) + s2 + 1 + s3);
+                               M_BEQ(3 + (opt_shownops ? 1 : 0) + s2 + 1 + s3);
 
                                disp = dseg_add_unique_s4(cd, 0);                     /* super->flags */
 
                                codegen_addpatchref(cd, PATCHER_checkcast_instanceof_flags,
                                                                        iptr->sx.s23.s3.c.ref, disp);
 
-                               if (opt_showdisassemble)
-                                       M_NOP;
-
                                M_ILD(REG_ITMP3, REG_PV, disp);
                                M_AND_IMM(REG_ITMP3, ACC_INTERFACE, REG_ITMP3);
                                M_BEQ(s2 + 1);
@@ -2586,11 +2439,8 @@ gen_method:
 
                                } else {
                                        codegen_addpatchref(cd,
-                                                                               PATCHER_checkcast_instanceof_interface,
+                                                                               PATCHER_instanceof_interface,
                                                                                iptr->sx.s23.s3.c.ref, 0);
-
-                                       if (opt_showdisassemble)
-                                               M_NOP;
                                }
 
                                M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
@@ -2604,27 +2454,24 @@ gen_method:
                                M_BEQ(1);
                                M_IADD_IMM(REG_ZERO, 1, d);
 
-                               if (!super)
+                               if (super == NULL)
                                        M_BR(s3);
                        }
 
                        /* class instanceof code */
 
-                       if (!super || !(super->flags & ACC_INTERFACE)) {
-                               disp = dseg_add_address(cd, supervftbl);
+                       if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
 
                                if (super) {
+                                       disp = dseg_add_address(cd, supervftbl);
                                        M_TST(s1);
                                        M_BEQ(s3);
 
                                } else {
+                                       disp = dseg_add_unique_address(cd, NULL);
                                        codegen_addpatchref(cd, PATCHER_instanceof_class,
                                                                                iptr->sx.s23.s3.c.ref,
                                                                                disp);
-
-                                       if (opt_showdisassemble) {
-                                               M_NOP;
-                                       }
                                }
 
                                M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
@@ -2639,6 +2486,7 @@ gen_method:
                                codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
 #endif
                                M_SUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
+                               M_EXTSW(REG_ITMP1, REG_ITMP1);
                                M_CMPU(REG_ITMP1, REG_ITMP2);
                                M_CLR(d);
                                M_BGT(1);
@@ -2677,14 +2525,10 @@ gen_method:
                        /* is patcher function set? */
 
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
-                               disp = dseg_add_address(cd, NULL);
+                               disp = dseg_add_unique_address(cd, NULL);
 
                                codegen_addpatchref(cd, PATCHER_builtin_multianewarray,
                                                                        iptr->sx.s23.s3.c.ref, disp);
-
-                               if (opt_showdisassemble)
-                                       M_NOP;
-
                        } else {
                                disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
                        }
@@ -2708,10 +2552,7 @@ gen_method:
                        M_JSR;
 
                        /* check for exception before result assignment */
-
-                       M_CMPI(REG_RESULT, 0);
-                       M_BEQ(0);
-                       codegen_add_fillinstacktrace_ref(cd);
+                       emit_exception_check(cd, iptr);
 
                        d = codegen_reg_of_dst(jd, iptr, REG_RESULT);
                        M_INTMOVE(REG_RESULT, d);
@@ -2731,220 +2572,10 @@ gen_method:
 
        dseg_createlinenumbertable(cd);
 
+       /* generate stubs */
 
-       /* generate exception and patcher stubs */
-
-       {
-               exceptionref *eref;
-               patchref     *pref;
-               u4            mcode;
-               u1           *savedmcodeptr;
-               u1           *tmpmcodeptr;
-
-               savedmcodeptr = NULL;
-
-               /* generate exception stubs */
-
-               for (eref = cd->exceptionrefs; eref != NULL; eref = eref->next) {
-                       md_codegen_patch_branch(cd, eref->branchpos, cd->mcodeptr - cd->mcodebase);
-
-                       MCODECHECK(100);
-
-                       /* Check if the exception is an
-                          ArrayIndexOutOfBoundsException.  If so, move index register
-                          into REG_ITMP1. */
-
-                       if (eref->reg != -1)
-                               M_MOV(eref->reg, REG_ITMP1);
-
-                       /* calcuate exception address */
-
-                       M_LDA(REG_ITMP2_XPC, REG_PV, eref->branchpos - 4);
-
-                       /* move function to call into REG_ITMP3 */
-
-                       disp = dseg_add_functionptr(cd, eref->function);
-                       M_ALD(REG_ITMP3, REG_PV, disp);
-                       M_ALD(REG_ITMP3, REG_ITMP3, 0); /* TOC */
-
-                       if (savedmcodeptr != NULL) {
-                               disp = ((u4 *) savedmcodeptr) - (((u4 *) cd->mcodeptr) + 1);
-                               M_BR(disp);
-
-                       } else {
-                               savedmcodeptr = cd->mcodeptr;
-
-                               if (jd->isleafmethod) {
-                                       M_MFLR(REG_ZERO);
-                                       M_AST(REG_ZERO, REG_SP, cd->stackframesize * 8 + LA_LR_OFFSET);
-                               }
-
-                               M_MOV(REG_PV, rd->argintregs[0]);
-                               M_MOV(REG_SP, rd->argintregs[1]);
-
-                               if (jd->isleafmethod)
-                                       M_MOV(REG_ZERO, rd->argintregs[2]);
-                               else
-                                       M_ALD(rd->argintregs[2],
-                                                 REG_SP, cd->stackframesize * 8 + LA_LR_OFFSET);
-
-                               M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
-                               M_MOV(REG_ITMP1, rd->argintregs[4]);
-
-                               M_STDU(REG_SP, REG_SP, -(LA_SIZE + 6 * 8));
-                               M_AST(REG_ITMP2_XPC, REG_SP, LA_SIZE + 5 * 8);
-
-                               M_MTCTR(REG_ITMP3);
-                               M_JSR;
-                               M_MOV(REG_RESULT, REG_ITMP1_XPTR);
-
-                               M_ALD(REG_ITMP2_XPC, REG_SP, LA_SIZE + 5 * 8);
-                               M_LADD_IMM(REG_SP, LA_SIZE + 6 * 8, REG_SP);
-
-                               if (jd->isleafmethod) {
-                                       /* XXX FIXME: REG_ZERO can cause problems here! */
-                                       assert(cd->stackframesize * 8 <= 32767);
-
-                                       M_ALD(REG_ZERO, REG_SP, cd->stackframesize * 8 + LA_LR_OFFSET);
-                                       M_MTLR(REG_ZERO);
-                               }
-
-                               disp = dseg_add_functionptr(cd, asm_handle_exception);
-                               M_ALD(REG_ITMP3, REG_PV, disp);
-                               M_MTCTR(REG_ITMP3);
-                               M_RTS;
-                       }
-               }
-
-
-               /* generate code patching stub call code */
-
-               for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
-                       /* check code segment size */
-
-                       MCODECHECK(16);
-
-                       /* Get machine code which is patched back in later. The
-                          call is 1 instruction word long. */
-
-                       tmpmcodeptr = (u1 *) (cd->mcodebase + pref->branchpos);
-
-                       mcode = *((u4 *) tmpmcodeptr);
-
-                       /* Patch in the call to call the following code (done at
-                          compile time). */
-
-                       savedmcodeptr = cd->mcodeptr;   /* save current mcodeptr          */
-                       cd->mcodeptr  = tmpmcodeptr;    /* set mcodeptr to patch position */
-
-                       disp = ((u4 *) savedmcodeptr) - (((u4 *) tmpmcodeptr) + 1);
-                       M_BR(disp);
-
-                       cd->mcodeptr = savedmcodeptr;   /* restore the current mcodeptr   */
-
-                       /* create stack frame - keep stack 16-byte aligned */
-
-                       M_AADD_IMM(REG_SP, -8 * 8, REG_SP);
-
-                       /* calculate return address and move it onto the stack */
-
-                       M_LDA(REG_ITMP3, REG_PV, pref->branchpos);
-                       M_AST_INTERN(REG_ITMP3, REG_SP, 5 * 8);
-
-                       /* move pointer to java_objectheader onto stack */
-
-#if defined(ENABLE_THREADS)
-                       /* order reversed because of data segment layout */
-
-                       (void) dseg_add_unique_address(cd, NULL);                         /* flcword    */
-                       (void) dseg_add_unique_address(cd, lock_get_initial_lock_word()); /* monitorPtr */
-                       disp = dseg_add_unique_address(cd, NULL);                         /* vftbl      */
-
-                       M_LDA(REG_ITMP3, REG_PV, disp);
-                       M_AST_INTERN(REG_ITMP3, REG_SP, 4 * 8);
-#else
-                       /* do nothing */
-#endif
-
-                       /* move machine code onto stack */
-
-                       disp = dseg_add_unique_s4(cd, mcode);
-                       M_ILD(REG_ITMP3, REG_PV, disp);
-                       M_IST_INTERN(REG_ITMP3, REG_SP, 3 * 8);
-
-                       /* move class/method/field reference onto stack */
-
-                       disp = dseg_add_unique_address(cd, pref->ref);
-                       M_ALD(REG_ITMP3, REG_PV, disp);
-                       M_AST_INTERN(REG_ITMP3, REG_SP, 2 * 8);
-
-                       /* move data segment displacement onto stack */
-
-                       disp = dseg_add_functionptr(cd, pref->disp);
-                       M_LLD(REG_ITMP3, REG_PV, disp);
-                       M_IST_INTERN(REG_ITMP3, REG_SP, 1 * 8);
-
-                       /* move patcher function pointer onto stack */
-
-                       disp = dseg_add_functionptr(cd, pref->patcher);
-                       M_ALD(REG_ITMP3, REG_PV, disp);
-                       M_AST_INTERN(REG_ITMP3, REG_SP, 0 * 8);
-
-                       disp = dseg_add_functionptr(cd, asm_patcher_wrapper);
-                       M_ALD(REG_ITMP3, REG_PV, disp);
-                       M_MTCTR(REG_ITMP3);
-                       M_RTS;
-               }
-
-               /* generate replacement-out stubs */
-
-#if 0
-               {
-                       int i;
-
-                       replacementpoint = jd->code->rplpoints;
-
-                       for (i = 0; i < jd->code->rplpointcount; ++i, ++replacementpoint) {
-                               /* check code segment size */
-
-                               MCODECHECK(100);
-
-                               /* note start of stub code */
-
-                               replacementpoint->outcode = (u1 *) (cd->mcodeptr - cd->mcodebase);
-
-                               /* make machine code for patching */
-
-                               tmpmcodeptr  = cd->mcodeptr;
-                               cd->mcodeptr = (u1 *) &(replacementpoint->mcode) + 1 /* big-endian */;
-
-                               disp = (ptrint)((s4*)replacementpoint->outcode - (s4*)replacementpoint->pc) - 1;
-                               M_BR(disp);
-
-                               cd->mcodeptr = tmpmcodeptr;
-
-                               /* create stack frame - keep 16-byte aligned */
-
-                               M_AADD_IMM(REG_SP, -4 * 4, REG_SP);
-
-                               /* push address of `rplpoint` struct */
-
-                               disp = dseg_add_unique_address(cd, replacementpoint);
-                               M_ALD(REG_ITMP3, REG_PV, disp);
-                               M_AST_INTERN(REG_ITMP3, REG_SP, 0 * 4);
-
-                               /* jump to replacement function */
-
-                               disp = dseg_add_unique_address(cd, asm_replacement_out);
-                               M_ALD(REG_ITMP3, REG_PV, disp);
-                               M_MTCTR(REG_ITMP3);
-                               M_RTS;
-                       }
-               }
-#endif
-       }
-
-       codegen_finish(jd);
+       emit_patcher_stubs(jd);
+       REPLACEMENT_EMIT_STUBS(jd);
 
        /* everything's ok */
 
@@ -3083,9 +2714,6 @@ u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd)
 #if !defined(WITH_STATIC_CLASSPATH)
        if (f == NULL) {
                codegen_addpatchref(cd, PATCHER_resolve_native, m, funcdisp);
-
-               if (opt_showdisassemble)
-                       M_NOP;
        }
 #endif
 
@@ -3228,11 +2856,7 @@ u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd)
                        M_LST(REG_RESULT, REG_SP, LA_SIZE + PA_SIZE + 1 * 8);
                }
                else {
-/*                     if (IS_2_WORD_TYPE(md->returntype.type)) */
-                               M_DST(REG_FRESULT, REG_SP, LA_SIZE + PA_SIZE + 1 * 8);
-/*                     else
-                               M_FST(REG_FRESULT, REG_SP, LA_SIZE + PA_SIZE + 1 * 8);  */ /* FIXME, needed F XXX?*/
-                       
+                       M_DST(REG_FRESULT, REG_SP, LA_SIZE + PA_SIZE + 1 * 8);
                }
        }
 
index efe7bb1367db95e9f21555605b8c47c4bc40d357..ae16d48dc63a6d3d80c6fe72c34f1977f49cb530 100644 (file)
@@ -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 $
 
 */
 
 
 /* additional functions and macros to generate code ***************************/
 
-/* gen_nullptr_check(objreg) */
-
-#define gen_nullptr_check(objreg) \
-    if (checknull) { \
-        M_TST((objreg)); \
-        M_BEQ(0); \
-        codegen_add_nullpointerexception_ref(cd); \
-    }
-
-#define gen_bound_check \
-    if (checkbounds) { \
-        M_ILD(REG_ITMP3, s1, OFFSET(java_arrayheader, size));\
-        M_CMPU(s2, REG_ITMP3);\
-        M_BGE(0);\
-        codegen_add_arrayindexoutofboundsexception_ref(cd, s2); \
-    }
-
-
 /* MCODECHECK(icnt) */
 
 #define MCODECHECK(icnt) \
 
 
 /* branch defines *************************************************************/
-
+/* and additional branch is needed when generating long branches */
 #define BRANCH_NOPS \
     do { \
+       if (CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {\
+               M_NOP; \
+       } \
         M_NOP; \
     } while (0)
 
         cd->mcodeptr += 4; \
     } while (0)
 
+/* for instruction decodeing */
+#define M_INSTR_OP2_IMM_D(x)            (((x) >> 21) & 0x1f  )
+#define M_INSTR_OP2_IMM_A(x)            (((x) >> 16) & 0x1f  )
+#define M_INSTR_OP2_IMM_I(x)            ( (x)        & 0xffff)
+
 #define M_BCMASK     0x0000fffc                     /* (((1 << 16) - 1) & ~3) */
 #define M_BMASK    0x03fffffc                     /* (((1 << 26) - 1) & ~3) */
 
 #define M_ADDIS(a,b,c)                  M_OP2_IMM(15, c, a, b)
 #define M_STFIWX(a,b,c)                 M_OP3(31, 983, 0, 0, a, b, c)
 
-#define M_LWZX(a,b,c)                   M_OP3(31, 23, 0, 0, a, b, c)
+#define M_LWAX(a,b,c)                   M_OP3(31, 341, 0, 0, a, b, c)
 #define M_LHZX(a,b,c)                   M_OP3(31, 279, 0, 0, a, b, c)
 #define M_LHAX(a,b,c)                   M_OP3(31, 343, 0, 0, a, b, c)
 #define M_LHAX(a,b,c)                   M_OP3(31, 343, 0, 0, a, b, c)
 #define M_ILD_INTERN(a,b,disp)          M_OP2_IMM(32,a,b,disp) /* LWZ */
 #endif
 
-#define M_ILD_INTERN(a,b,disp)         M_OP2_IMM(58, a, b, (((disp) & 0xfffe) | 0x0002))
+#define M_LWZ(a,b,disp)                        M_OP2_IMM(32,a,b,disp)  /* needed for hardware exceptions */
+
+#define M_ILD_INTERN(a,b,disp)         M_OP2_IMM(58, a, b, (((disp) & 0xfffe) | 0x0002))       /* this is LWA actually */
 
 #define M_ILD(a,b,disp) \
     do { \
index f4fc1cd7968215d195afff13f0cac0ad4d030d48..43fd7ed74c0a8daacc877a58a85c23eb9690c5a3 100644 (file)
@@ -1,6 +1,6 @@
-/* src/vm/jit/powerpc64/emit.c - PowerPC code emitter functions
+/* src/vm/jit/powerpc64/emit.c - PowerPC64 code emitter functions
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
    J. Wenninger, Institut f. Computersprachen - TU Wien
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Christian Thalinger
-
-   Changes:
-
    $Id: emitfuncs.c 4398 2006-01-31 23:43:08Z twisti $
 
 */
 
 #include "vm/types.h"
 
+#include "mm/memory.h"
+
 #include "md-abi.h"
 #include "vm/jit/powerpc64/codegen.h"
 
+#include "vmcore/options.h"
+
 #include "vm/builtin.h"
 #include "vm/jit/emit-common.h"
 #include "vm/jit/jit.h"
+#include "vm/vm.h"
+#include "vm/jit/asmpart.h"
+#include "vm/exceptions.h"
+
+#if defined(ENABLE_THREADS)
+# include "threads/native/lock.h"
+#endif
 
 
 /* emit_load *******************************************************************
@@ -69,10 +74,7 @@ s4 emit_load(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
                disp = src->vv.regoff * 8;
 
                if (IS_FLT_DBL_TYPE(src->type)) {
-                       if (IS_2_WORD_TYPE(src->type))
-                               M_DLD(tempreg, REG_SP, disp);
-                       else
-                               M_FLD(tempreg, REG_SP, disp);
+                       M_DLD(tempreg, REG_SP, disp);
                }
                else {
                        M_LLD(tempreg, REG_SP, disp);
@@ -105,10 +107,7 @@ void emit_store(jitdata *jd, instruction *iptr, varinfo *dst, s4 d)
                COUNT_SPILLS;
 
                if (IS_FLT_DBL_TYPE(dst->type)) {
-/*                     if (IS_2_WORD_TYPE(dst->type))*/
-                               M_DST(d, REG_SP, dst->vv.regoff * 8);
-/*                     else
-                               M_DST(d, REG_SP, dst->vv.regoff * 8); F XXX */
+                       M_DST(d, REG_SP, dst->vv.regoff * 8);
                }
                else {
                        M_LST(d, REG_SP, dst->vv.regoff * 8);
@@ -193,10 +192,10 @@ void emit_lconst(codegendata *cd, s4 d, s8 value)
 
 
 /* emit_verbosecall_enter ******************************************************
- *
*    Generates the code for the call trace.
- *
- ********************************************************************************/
+
+   Generates the code for the call trace.
+
+*******************************************************************************/
 
 void emit_verbosecall_enter (jitdata *jd)
 {
@@ -299,7 +298,7 @@ void emit_verbosecall_enter (jitdata *jd)
 #endif
        /* call via function descriptor */
        /* XXX: what about TOC? */
-       p = dseg_add_functionptr(cd, builtin_trace_args);
+       p = dseg_add_functionptr(cd, builtin_verbosecall_enter);
        M_ALD(REG_ITMP2, REG_PV, p);
        M_ALD(REG_ITMP1, REG_ITMP2, 0);
        M_MTCTR(REG_ITMP1);
@@ -338,17 +337,26 @@ void emit_verbosecall_enter (jitdata *jd)
 
 
 /* emit_verbosecall_exit ******************************************************
- *
- *    Generates the code for the call trace.
- *
- ********************************************************************************/
+
+   Generates the code for the call trace.
+
+   void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m);
+
+*******************************************************************************/
 
 void emit_verbosecall_exit(jitdata *jd)
 {
-       codegendata *cd = jd->cd;
-       s4 disp;
+       methodinfo   *m;
+       codegendata  *cd;
+       s4            disp;
+
+       /* get required compiler data */
+
+       m  = jd->m;
+       cd = jd->cd;
 
        /* mark trace code */
+
        M_NOP;
 
        M_MFLR(REG_ZERO);
@@ -357,18 +365,15 @@ void emit_verbosecall_exit(jitdata *jd)
        M_LST(REG_RESULT, REG_SP, LA_SIZE+PA_SIZE+1*8);
        M_AST(REG_ZERO, REG_SP, LA_SIZE+PA_SIZE+2*8);
 
-#if defined(__DARWIN__)
-       M_MOV(REG_RESULT, jd->rd->argintregs[1]);
-#else
-       M_MOV(REG_RESULT, jd->rd->argintregs[1]);
-#endif
+       M_MOV(REG_RESULT, REG_A0);
+
+       M_FLTMOVE(REG_FRESULT, REG_FA0);
+       M_FLTMOVE(REG_FRESULT, REG_FA1);
 
-       disp = dseg_add_address(cd, jd->m);
-       M_ALD(jd->rd->argintregs[0], REG_PV, disp);
+       disp = dseg_add_address(cd, m);
+       M_ALD(REG_A3, REG_PV, disp);
 
-       M_FLTMOVE(REG_FRESULT, jd->rd->argfltregs[0]);
-       M_FLTMOVE(REG_FRESULT, jd->rd->argfltregs[1]);
-       disp = dseg_add_functionptr(cd, builtin_displaymethodstop);
+       disp = dseg_add_functionptr(cd, builtin_verbosecall_exit);
        /* call via function descriptor, XXX: what about TOC ? */
        M_ALD(REG_ITMP2, REG_PV, disp);
        M_ALD(REG_ITMP2, REG_ITMP2, 0);
@@ -382,21 +387,482 @@ void emit_verbosecall_exit(jitdata *jd)
        M_MTLR(REG_ZERO);
 
        /* mark trace code */
+
        M_NOP;
 }
 
+/* emit_branch *****************************************************************
+
+   Emits the code for conditional and unconditional branchs.
+
+*******************************************************************************/
+
+void emit_branch(codegendata *cd, s4 disp, s4 condition, s4 reg, u4 opt)
+{
+       s4 checkdisp;
+       s4 branchdisp;
+
+       /* calculate the different displacements */
+
+       checkdisp  =  disp + 4;
+       branchdisp = (disp - 4) >> 2;
+
+       /* check which branch to generate */
+
+       if (condition == BRANCH_UNCONDITIONAL) {
+               /* check displacement for overflow */
+
+               if ((checkdisp < (s4) 0xfe000000) || (checkdisp > (s4) 0x01fffffc)) {
+                       /* if the long-branches flag isn't set yet, do it */
+
+                       if (!CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
+                               log_println("setting error");
+                               cd->flags |= (CODEGENDATA_FLAG_ERROR |
+                                                         CODEGENDATA_FLAG_LONGBRANCHES);
+                       }
+
+                       vm_abort("emit_branch: emit unconditional long-branch code");
+               }
+               else {
+                       M_BR(branchdisp);
+               }
+       }
+       else {
+               /* and displacement for overflow */
+
+               if ((checkdisp < (s4) 0xffff8000) || (checkdisp > (s4) 0x00007fff)) {
+                       /* if the long-branches flag isn't set yet, do it */
+
+                       if (!CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
+                               log_println("setting error");
+                               cd->flags |= (CODEGENDATA_FLAG_ERROR |
+                                                         CODEGENDATA_FLAG_LONGBRANCHES);
+                       }
+                       log_println("generating long-branch");
+
+                       branchdisp --;          /* we jump from the second instruction */
+                       switch (condition) {
+                       case BRANCH_EQ:
+                               M_BNE(1);
+                               M_BR(branchdisp);
+                               break;
+                       case BRANCH_NE:
+                               M_BEQ(1);
+                               M_BR(branchdisp);
+                               break;
+                       case BRANCH_LT:
+                               M_BGE(1);
+                               M_BR(branchdisp);
+                               break;
+                       case BRANCH_GE:
+                               M_BLT(1);
+                               M_BR(branchdisp);
+                               break;
+                       case BRANCH_GT:
+                               M_BLE(1);
+                               M_BR(branchdisp);
+                               break;
+                       case BRANCH_LE:
+                               M_BGT(1);
+                               M_BR(branchdisp);
+                               break;
+                       case BRANCH_NAN:
+                               vm_abort("emit_branch: long BRANCH_NAN");
+                               break;
+                       default:
+                               vm_abort("emit_branch: unknown condition %d", condition);
+                       }
+
+               }
+               else {
+                       switch (condition) {
+                       case BRANCH_EQ:
+                               M_BEQ(branchdisp);
+                               break;
+                       case BRANCH_NE:
+                               M_BNE(branchdisp);
+                               break;
+                       case BRANCH_LT:
+                               M_BLT(branchdisp);
+                               break;
+                       case BRANCH_GE:
+                               M_BGE(branchdisp);
+                               break;
+                       case BRANCH_GT:
+                               M_BGT(branchdisp);
+                               break;
+                       case BRANCH_LE:
+                               M_BLE(branchdisp);
+                               break;
+                       case BRANCH_NAN:
+                               M_BNAN(branchdisp);
+                               break;
+                       default:
+                               vm_abort("emit_branch: unknown condition %d", condition);
+                       }
+               }
+       }
+}
+
+/* emit_arrayindexoutofbounds_check ********************************************
+
+   Emit a ArrayIndexOutOfBoundsException check.
+
+*******************************************************************************/
+
+void emit_arrayindexoutofbounds_check(codegendata *cd, instruction *iptr, s4 s1, s4 s2)
+{
+       if (checkbounds) {
+#define SOFTEX 0
+#if SOFTEX
+               M_ILD(REG_ITMP3, s1, OFFSET(java_arrayheader, size));
+               M_CMPU(s2, REG_ITMP3);
+               codegen_add_arrayindexoutofboundsexception_ref(cd, s2);
+               BRANCH_NOPS;
+#else
+               M_ILD(REG_ITMP3, s1, OFFSET(java_arrayheader, size));
+               M_CMPU(s2, REG_ITMP3);
+               M_BLT(1);
+               /* ALD is 4 byte aligned, ILD 2, onyl LWZ is byte aligned */
+               M_LWZ(s2, REG_ZERO, EXCEPTION_HARDWARE_ARRAYINDEXOUTOFBOUNDS);
+#endif
+       }
+}
+
+
+/* emit_arithmetic_check *******************************************************
+
+   Emit an ArithmeticException check.
+
+*******************************************************************************/
+
+void emit_arithmetic_check(codegendata *cd, instruction *iptr, s4 reg)
+{
+       if (INSTRUCTION_MUST_CHECK(iptr))       {
+       #if SOFTEX
+               M_TST(reg);
+               codegen_add_arithmeticexception_ref(cd);
+               BRANCH_NOPS;
+       #else
+               M_TST(reg);
+               M_BNE(1);
+               /* ALD is 4 byte aligned, ILD 2, onyl LWZ is byte aligned */
+               M_LWZ(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_ARITHMETIC);
+       #endif
+       }
+}
+
+#if 0
+/* emit_arraystore_check *******************************************************
+
+   Emit an ArrayStoreException check.
+
+*******************************************************************************/
+
+void emit_arraystore_check(codegendata *cd, instruction *iptr, s4 reg)
+{
+       if (INSTRUCTION_MUST_CHECK(iptr))       {
+               M_TST(REG_RESULT);
+               codegen_add_arraystoreexception_ref(cd);
+               BRANCH_NOPS;
+       }
+}
+#endif
+
+/* emit_classcast_check ********************************************************
+
+   Emit a ClassCastException check.
+
+*******************************************************************************/
+
+void emit_classcast_check(codegendata *cd, instruction *iptr, s4 condition, s4 reg, s4 s1)
+{
+       if (INSTRUCTION_MUST_CHECK(iptr))       {
+       #if SOFTEX
+               codegen_add_classcastexception_ref(cd, condition, s1);
+               BRANCH_NOPS;
+               M_NOP;
+       #else
+               switch(condition)       {
+                       case BRANCH_LE:
+                               M_BGT(1);
+                               break;
+                       case BRANCH_EQ:
+                               M_BNE(1);
+                               break;
+                       case BRANCH_GT:
+                               M_BLE(1);
+                               break;
+                       default:
+                               vm_abort("emit_classcast_check: unknown condition %d", condition);
+               }
+               /* ALD is 4 byte aligned, ILD 2, onyl LWZ is byte aligned */
+               M_LWZ(s1, REG_ZERO, EXCEPTION_HARDWARE_CLASSCAST);
+       #endif
+       }
+}
+
+
+/* emit_nullpointer_check ******************************************************
+
+   Emit a NullPointerException check.
+
+*******************************************************************************/
+
+void emit_nullpointer_check(codegendata *cd, instruction *iptr, s4 reg)
+{
+       if (INSTRUCTION_MUST_CHECK(iptr))       {
+               M_TST(reg);
+               M_BNE(1);
+               /* ALD is 4 byte aligned, ILD 2, onyl LWZ is byte aligned */
+               M_LWZ(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_NULLPOINTER);
+       }
+}
+
+/* emit_exception_check ********************************************************
+
+   Emit an Exception check.
+
+*******************************************************************************/
+
+void emit_exception_check(codegendata *cd, instruction *iptr)
+{
+       if (INSTRUCTION_MUST_CHECK(iptr))       {
+       #if SOFTEX
+               M_CMPI(REG_RESULT, 0);
+               codegen_add_fillinstacktrace_ref(cd);
+               BRANCH_NOPS;
+       #else
+               M_TST(REG_RESULT);
+               M_BNE(1);
+               /* ALD is 4 byte aligned, ILD 2, onyl LWZ is byte aligned */
+               M_LWZ(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_EXCEPTION);
+       #endif
+       }
+}
+
+
+/* emit_patcher_stubs **********************************************************
+
+   Generates the code for the patcher stubs.
+
+*******************************************************************************/
+void emit_patcher_stubs(jitdata *jd)
+{
+       codegendata *cd;
+       patchref    *pref;
+       u4           mcode;
+       u1          *savedmcodeptr;
+       u1          *tmpmcodeptr;
+       s4           targetdisp;
+       s4           disp;
+
+       cd = jd->cd;
+
+       /* generate code patching stub call code */
+
+       targetdisp = 0;
+
+       for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
+               /* check code segment size */
+
+               MCODECHECK(16);
 
+               /* Get machine code which is patched back in later. The
+                  call is 1 instruction word long. */
+
+               tmpmcodeptr = (u1 *) (cd->mcodebase + pref->branchpos);
+
+               mcode = *((u4 *) tmpmcodeptr);
+
+               /* Patch in the call to call the following code (done at
+                  compile time). */
+
+               savedmcodeptr = cd->mcodeptr;   /* save current mcodeptr          */
+               cd->mcodeptr  = tmpmcodeptr;    /* set mcodeptr to patch position */
+
+               disp = ((u4 *) savedmcodeptr) - (((u4 *) tmpmcodeptr) + 1);
+               M_BR(disp);
+
+               cd->mcodeptr = savedmcodeptr;   /* restore the current mcodeptr   */
+
+               /* create stack frame - keep stack 16-byte aligned */
+
+               M_AADD_IMM(REG_SP, -8 * 8, REG_SP);
+
+               /* calculate return address and move it onto the stack */
+
+               M_LDA(REG_ITMP3, REG_PV, pref->branchpos);
+               M_AST_INTERN(REG_ITMP3, REG_SP, 5 * 8);
+
+               /* move pointer to java_objectheader onto stack */
+
+#if defined(ENABLE_THREADS)
+               /* order reversed because of data segment layout */
+
+               (void) dseg_add_unique_address(cd, NULL);                         /* flcword    */
+               (void) dseg_add_unique_address(cd, lock_get_initial_lock_word()); /* monitorPtr */
+               disp = dseg_add_unique_address(cd, NULL);                         /* vftbl      */
+
+               M_LDA(REG_ITMP3, REG_PV, disp);
+               M_AST_INTERN(REG_ITMP3, REG_SP, 4 * 8);
+#else
+               /* do nothing */
+#endif
+
+               /* move machine code onto stack */
+
+               disp = dseg_add_s4(cd, mcode);
+               M_ILD(REG_ITMP3, REG_PV, disp);
+               M_IST_INTERN(REG_ITMP3, REG_SP, 3 * 8);
+
+               /* move class/method/field reference onto stack */
+
+               disp = dseg_add_address(cd, pref->ref);
+               M_ALD(REG_ITMP3, REG_PV, disp);
+               M_AST_INTERN(REG_ITMP3, REG_SP, 2 * 8);
+
+               /* move data segment displacement onto stack */
+
+               disp = dseg_add_s4(cd, pref->disp);
+               M_ILD(REG_ITMP3, REG_PV, disp);
+               M_IST_INTERN(REG_ITMP3, REG_SP, 1 * 8);
+               M_NOP;
+
+               /* move patcher function pointer onto stack */
+
+               disp = dseg_add_functionptr(cd, pref->patcher);
+               M_ALD(REG_ITMP3, REG_PV, disp);
+               M_AST_INTERN(REG_ITMP3, REG_SP, 0 * 8);
+
+#if 0
+               disp = dseg_add_functionptr(cd, asm_patcher_wrapper);
+               M_ALD(REG_ITMP3, REG_PV, disp);
+               M_MTCTR(REG_ITMP3);
+               M_RTS;
+#else
+               if (targetdisp == 0) {
+                       targetdisp = ((u4 *) cd->mcodeptr) - ((u4 *) cd->mcodebase);
+
+                       disp = dseg_add_functionptr(cd, asm_patcher_wrapper);
+                       M_ALD(REG_ITMP3, REG_PV, disp);
+                       M_MTCTR(REG_ITMP3);
+                       M_RTS;
+               }
+               else {
+                       disp = (((u4 *) cd->mcodebase) + targetdisp) -
+                               (((u4 *) cd->mcodeptr) + 1);
+                       M_BR(disp);
+               }
+#endif
+       }
+}
+
+
+/* emit_replacement_stubs ******************************************************
+
+   Generates the code for the replacement stubs.
+
+*******************************************************************************/
+
+#if defined(ENABLE_REPLACEMENT)
+void emit_replacement_stubs(jitdata *jd)
+{
+       codegendata *cd;
+       codeinfo    *code;
+       rplpoint    *replacementpoint;
+       s4           disp;
+       s4           i;
+#if !defined(NDEBUG)
+       u1          *savedmcodeptr;
+#endif
+
+       /* get required compiler data */
+
+       cd   = jd->cd;
+       code = jd->code;
+
+       replacementpoint = jd->code->rplpoints;
+
+       for (i = 0; i < code->rplpointcount; ++i, ++replacementpoint) {
+               /* do not generate stubs for non-trappable points */
+
+               if (replacementpoint->flags & RPLPOINT_FLAG_NOTRAP)
+                       continue;
+
+
+               /* check code segment size */
+
+               MCODECHECK(100);
+
+#if !defined(NDEBUG)
+               savedmcodeptr = cd->mcodeptr;
+#endif
+               /* create stack frame - keep 16-byte aligned */
+
+               M_AADD_IMM(REG_SP, -4 * 8, REG_SP);
+
+               /* push address of `rplpoint` struct */
+
+               disp = dseg_add_address(cd, replacementpoint);
+               M_ALD(REG_ITMP3, REG_PV, disp);
+               M_AST_INTERN(REG_ITMP3, REG_SP, 0 * 8);
+
+               /* jump to replacement function */
+
+               disp = dseg_add_functionptr(cd, asm_replacement_out);
+               M_ALD(REG_ITMP3, REG_PV, disp);
+               M_MTCTR(REG_ITMP3);
+               M_RTS;
+
+               assert((cd->mcodeptr - savedmcodeptr) == 4*REPLACEMENT_STUB_SIZE);
+
+#if 0
+               /* note start of stub code */
+
+               replacementpoint->outcode = (u1 *) (cd->mcodeptr - cd->mcodebase);
+
+               /* make machine code for patching */
+
+               savedmcodeptr  = cd->mcodeptr;
+               cd->mcodeptr = (u1 *) &(replacementpoint->mcode) + 1 /* big-endian */;
+
+               disp = (ptrint)((s4*)replacementpoint->outcode - (s4*)replacementpoint->pc) - 1;
+               M_BR(disp);
+
+               cd->mcodeptr = savedmcodeptr;
+
+               /* create stack frame - keep 16-byte aligned */
+
+               M_AADD_IMM(REG_SP, -4 * 4, REG_SP);
+
+               /* push address of `rplpoint` struct */
+
+               disp = dseg_add_unique_address(cd, replacementpoint);
+               M_ALD(REG_ITMP3, REG_PV, disp);
+               M_AST_INTERN(REG_ITMP3, REG_SP, 0 * 4);
+
+               /* jump to replacement function */
+
+               disp = dseg_add_functionptr(cd, asm_replacement_out);
+               M_ALD(REG_ITMP3, REG_PV, disp);
+               M_MTCTR(REG_ITMP3);
+               M_RTS;
+#endif
+       }
+}
+#endif /* define(ENABLE_REPLACEMENT) */
 
 /*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
+* These are local overrides for various environment variables in Emacs.
+* Please do not remove this and leave it at the end of the file, where
+* Emacs will automagically detect them.
+* ---------------------------------------------------------------------
+* Local variables:
+* mode: c
+* indent-tabs-mode: t
+* c-basic-offset: 4
+* tab-width: 4
+* End:
+* vim:noexpandtab:sw=4:ts=4:
+*/
index 57da21e518ceb64300f452f2a4273a3d870e1b11..2014a2c64c25f791f967a9f1bc8d233cee7d5180 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: md-abi.c 7311 2007-02-09 13:20:27Z twisti $
+   $Id: md-abi.c 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
index 9d6b365d79fbc900b0a69f7d2af1ba5402d8ad8e..f21759fccade4bf5a877ee58168c2188c4ce35ea 100644 (file)
@@ -1,6 +1,6 @@
 /* src/vm/jit/powerpc64/linux/md-abi.h - defines for PowerPC64 Linux ABI
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
    J. Wenninger, Institut f. Computersprachen - TU Wien
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Christian Thalinger
-
-   Changes:
-
-   $Id: md-abi.h 5940 2006-11-09 09:59:28Z tbfg $
+   $Id: md-abi.h 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                     */
 
 #define REG_SP           1   /* stack pointer                                 */
 #define REG_ZERO         0   /* almost always zero: only in address calc.     */
 
+#define REG_A0           3   /* define some argument registers                */
+#define REG_A1           4
+#define REG_A2           5
+#define REG_A3           6
+
 /* floating point registers */
 
 #define REG_FRESULT      1   /* to deliver floating point method results      */
@@ -65,6 +65,9 @@
 
 #define REG_IFTMP       16   /* temporary integer and floating point register */
 
+#define REG_FA0          1   /* define some argument registers                */
+#define REG_FA1          2
+
 
 #define INT_REG_CNT     32   /* number of integer registers                   */
 #define INT_SAV_CNT      9   /* number of int callee saved registers          */
index 671301d4ef93c94f7da812d315fd4a3058c32a8c..730435c0294af9d7d26a306573c6dbfe6da7d32e 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: md-os.c 7311 2007-02-09 13:20:27Z twisti $
+   $Id: md-os.c 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)
 
 
 /* md_signal_handler_sigsegv ***************************************************
-
-   NullPointerException signal handler for hardware null pointer
-   check.
+       Signal handler for hardware-exceptions.
 
 *******************************************************************************/
 
 void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
 {
-       ucontext_t  *_uc;
-       mcontext_t  *_mc;
-       u4           instr;
-       s4           reg;
-       ptrint       addr;
-       u1          *pv;
-       u1          *sp;
-       u1          *ra;
-       u1          *xpc;
+       ucontext_t      *_uc;
+       mcontext_t      *_mc;
+       u1              *pv;
+       u1              *sp;
+       u1              *ra;
+       u1              *xpc;
+       u4              mcode;
+       s4              s1;
+       s4              disp;
+       s4              d;
+       s4              type;
+       ptrint          addr;
+       ptrint          val;
+       java_objectheader *e;
 
        _uc = (ucontext_t *) _p;
        _mc = &(_uc->uc_mcontext);
-       
-       pv  = (u1 *) _mc->gp_regs[REG_PV];
-       sp  = (u1 *) _mc->gp_regs[REG_SP];
-       ra  = (u1 *) _mc->gp_regs[PT_LNK];           /* this is correct for leafs */
-       xpc = (u1 *) _mc->gp_regs[PT_NIP];
-
-       instr = *((u4 *) xpc);
-       reg   = (instr >> 16) & 0x1f;
-       addr  = _mc->gp_regs[reg];
-
-       if (addr == 0) {
-               _mc->gp_regs[REG_ITMP1_XPTR] =
-                       (ptrint) stacktrace_hardware_nullpointerexception(pv, sp, ra, xpc);
-
-               _mc->gp_regs[REG_ITMP2_XPC] = (ptrint) xpc;
-               _mc->gp_regs[PT_NIP] = (ptrint) asm_handle_exception;
-       }
-       else {
-               codegen_get_pv_from_pc(xpc);
 
-               /* this should not happen */
+       /* get register values */
+       pv = (u1*) _mc->gp_regs[REG_PV];
+       sp = (u1*) _mc->gp_regs[REG_SP];
+       ra = (u1*) _mc->gp_regs[PT_LNK];                     /* correct for leafs */
+       xpc =(u1*) _mc->gp_regs[PT_NIP];
+
+       /* get the throwing instruction */
+       mcode = *((u4*)xpc);
+
+       s1   = M_INSTR_OP2_IMM_A(mcode);
+       disp = M_INSTR_OP2_IMM_I(mcode);
+       d    = M_INSTR_OP2_IMM_D(mcode);
+
+       val  = _mc->gp_regs[d];
+
+       if (s1 == REG_ZERO)     {
+               /* we use the exception type as load displacement */
+               type = disp;
+       } else  {
+               /* normal NPE */
+               addr = _mc->gp_regs[s1];
+               type = (s4) addr;
+       }
+       e = exceptions_new_hardware_exception(pv, sp, ra, xpc, type, val);
 
-               assert(0);
-       }               
+       _mc->gp_regs[REG_ITMP1]     = (ptrint) e;
+       _mc->gp_regs[REG_ITMP2_XPC] = (ptrint) xpc;
+       _mc->gp_regs[PT_NIP]        = (ptrint) asm_handle_exception;
 }
 
 
index d3940d833a5aa12e569d7e4a3bcbae9e374c19d0..6da5d7ce18373fa8f2e6ea106bf981d4255b811a 100644 (file)
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: md.c 7311 2007-02-09 13:20:27Z twisti $
+   $Id: md.c 7596 2007-03-28 21:05:53Z twisti $
 
 */
 
+
 #include "config.h"
 
 #include <assert.h>
index 6f5add6cc7bfa6ce5ba53c918284aeddc6f15fad..4da8f67931f0cc32566162eb0f47f7c7c7f2f767 100644 (file)
@@ -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:
+
+   <patched call position>
+   81870000    lwz   r12,0(r7)
+   800c0010    lwz   r0,16(r12)
+   34000000    addic.        r0,r0,0
+   408101fc    bgt-  0x3002e518                FIXME
+   83c00003    lwz   r30,3(0)          FIXME
+   800c0000    lwz   r0,0(r12)
+
+*******************************************************************************/
+bool patcher_checkcast_interface(u1 *sp)
+{
+       u1 *ra;
+       constant_classref *cr;
+       classinfo *c;
+       s4 disp;
+       u4 mcode;
+
+       /* get stuff from stack */
+       ra = (u1*)                      *((ptrint *)(sp + 5*8));
+       mcode =                         *((u4*) (sp + 3*8));
+       cr = (constant_classref*)       *((ptrint*)(sp+2*8));
+
+       /* get the fieldinfo */
+       if (!(c = resolve_classref_eager(cr)))  {
+               return false;
+       }
+
+       /* patch back original code */
+       *((u4 *) ra) = mcode;
+
+       /* if we show NOPs, we have to skip them */
+       if (opt_shownops)       {
+               ra = ra +4;
+       }
+
+       /* patch super class index */
+       disp = -(c->index);
+
+       *((s4*)(ra + 2*4)) |= (disp & 0x0000ffff);
+
+       disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
+
+       *((s4 *)(ra + 5*4)) |= (disp & 0x0000ffff);
+
+       /* sync instruction cache */
+       md_icacheflush(ra, 5*4);
+
+       return true;
+}
 
 
-/* patcher_checkcast_instanceof_interface **************************************
+/* patcher_instanceof_interface **************************************
 
    Machine code:
 
@@ -631,7 +685,7 @@ bool patcher_checkcast_instanceof_flags(u1 *sp)
 
 *******************************************************************************/
 
-bool patcher_checkcast_instanceof_interface(u1 *sp)
+bool patcher_instanceof_interface(u1 *sp)
 {
        u1                *ra;
        u4                 mcode;
@@ -656,7 +710,7 @@ bool patcher_checkcast_instanceof_interface(u1 *sp)
 
        /* if we show disassembly, we have to skip the nop */
 
-       if (opt_showdisassemble)
+       if (opt_shownops)
                ra = ra + 4;
 
        /* patch super class index */
@@ -729,6 +783,67 @@ bool patcher_checkcast_class(u1 *sp)
        return true;
 }
 
+/* patcher_resolve_classref_to_classinfo ***************************************
+
+   ACONST:
+
+   <patched call postition>
+   806dffc4    lwz   r3,-60(r13)
+   81adffc0    lwz   r13,-64(r13)
+   7da903a6    mtctr r13
+   4e800421    bctrl
+
+
+   MULTIANEWARRAY:
+
+   <patched call position>
+   808dffc0    lwz   r4,-64(r13)
+   38a10038    addi  r5,r1,56
+   81adffbc    lwz   r13,-68(r13)
+   7da903a6    mtctr r13
+   4e800421    bctrl
+
+
+   ARRAYCHECKCAST:
+
+   <patched call position>
+   808dffd8    lwz   r4,-40(r13)
+   81adffd4    lwz   r13,-44(r13)
+   7da903a6    mtctr r13
+   4e800421    bctrl
+
+*******************************************************************************/
+
+bool patcher_resolve_classref_to_classinfo(u1 *sp)
+{
+       constant_classref *cr;
+       s4                 disp;
+       u1                *pv;
+       classinfo         *c;
+
+       /* get stuff from the stack */
+
+       cr   = (constant_classref *) *((ptrint *) (sp + 2 * 8));
+       disp =                       *((s4 *)     (sp + 1 * 8));
+       pv   = (u1 *)                *((ptrint *) (sp + 0 * 8));
+
+       /* get the classinfo */
+
+       if (!(c = resolve_classref_eager(cr)))
+               return false;
+
+       /* patch the classinfo pointer */
+
+       *((ptrint *) (pv + disp)) = (ptrint) c;
+
+       /* synchronize data cache */
+
+       md_dcacheflush(pv + disp, SIZEOF_VOID_P);
+
+       return true;
+}
+
+
 
 /* patcher_instanceof_class ****************************************************
 
@@ -781,6 +896,90 @@ bool patcher_instanceof_class(u1 *sp)
        return true;
 }
 
+/* patcher_resolve_classref_to_vftbl *******************************************
+
+   CHECKCAST (class):
+
+   <patched call position>
+   81870000    lwz   r12,0(r7)
+   800c0014    lwz   r0,20(r12)
+   818dff78    lwz   r12,-136(r13)
+
+
+   INSTANCEOF (class):
+
+   <patched call position>
+   817d0000    lwz   r11,0(r29)
+   818dff8c    lwz   r12,-116(r13)
+
+*******************************************************************************/
+
+bool patcher_resolve_classref_to_vftbl(u1 *sp)
+{
+       constant_classref *cr;
+       s4                 disp;
+       u1                *pv;
+       classinfo         *c;
+
+       /* get stuff from the stack */
+
+       cr   = (constant_classref *) *((ptrint *) (sp + 2 * 8));
+       disp =                       *((s4 *)     (sp + 1 * 8));
+       pv   = (u1 *)                *((ptrint *) (sp + 0 * 8));
+
+       /* get the fieldinfo */
+
+       if (!(c = resolve_classref_eager(cr)))
+               return false;
+
+       /* patch super class' vftbl */
+
+       *((ptrint *) (pv + disp)) = (ptrint) c->vftbl;
+
+       /* synchronize data cache */
+
+       md_dcacheflush(pv + disp, SIZEOF_VOID_P);
+
+       return true;
+}
+
+/* patcher_resolve_classref_to_flags *******************************************
+
+   CHECKCAST/INSTANCEOF:
+
+   <patched call position>
+   818dff7c    lwz   r12,-132(r13)
+
+*******************************************************************************/
+
+bool patcher_resolve_classref_to_flags(u1 *sp)
+{
+       constant_classref *cr;
+       s4                 disp;
+       u1                *pv;
+       classinfo         *c;
+
+       /* get stuff from the stack */
+
+       cr   = (constant_classref *) *((ptrint *) (sp + 2 * 8));
+       disp =                       *((s4 *)     (sp + 1 * 8));
+       pv   = (u1 *)                *((ptrint *) (sp + 0 * 8));
+
+       /* get the fieldinfo */
+
+       if (!(c = resolve_classref_eager(cr)))
+               return false;
+
+       /* patch class flags */
+
+       *((s4 *) (pv + disp)) = (s4) c->flags;
+
+       /* synchronize data cache */
+
+       md_dcacheflush(pv + disp, SIZEOF_VOID_P);
+
+       return true;
+}
 
 /* patcher_clinit **************************************************************
 
index 4673c5ab373958692f1ee22f22f2bdb8e211bd5b..9fcab0228e374957efa9ac34b7a47b610ab56fee 100644 (file)
@@ -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;
index 68d3f968a729914c6304557c06be0de28c4dec06..62fa6a64c829303c80dfa85300fdb9966f155db7 100644 (file)
@@ -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 */
 
 
index d656e4c595c0e8d3527c7d6dc34c15c515a26fb7..ae934dccb1b766b1be83b09f22781090efd0f2f1 100644 (file)
@@ -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 *****************************
 *                                                                              *
index 949c12e90c2a203357187111bf5c65e45762dbf4..bc7d5a5cb1da4c68265b8293181755793ee5ef68 100644 (file)
@@ -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);
                        }
 
index 841a590ddb7bc7843a1aead8f16b69a38ccd03b8..5228b5828273539494e70b57de6c377dafe84d7a 100644 (file)
@@ -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 $
 
 */
 
 
 
 
-#define LCONST(r,c) \
-    do { \
-        if ((c) == 0) \
-            M_CLR((d)); \
-        else \
-            M_MOV_IMM((c), (d)); \
-    } while (0)
-
 /* branch defines *************************************************************/
 
 #define BRANCH_NOPS \
 #define PATCHER_NOPS \
     do { \
         M_NOP; \
+               M_NOP; \ 
+               M_NOP; \
     } while (0)
 
+#define PATCHER_NOPS_SKIP   12 
+
 /* *** BIG TODO ***
  * Make all this inline functions !!!!!!!!!!
  */
 #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
 #      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)
 
 /* 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)
 #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)
 #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)
 #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)
 #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 { \
                } \
        } 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.
 #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) )
 #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) )
index 1fd742a8f878105e7ff4a6c835754cd9b1e6cdd8..50b29fcb07aca4740a40f52028d674abc8ce33c0 100644 (file)
@@ -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
index 478fbfbabc54361a80b66ad309fc1777b5c41af3..13bfedba3822ccb2aebedbe8e65b2f00dfb8b5d3 100644 (file)
@@ -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 */
 
 
index a644ef7e81a6d461f3ae4d96bfe845f4003c40ad..4cc4992c6fb6344395203d96ebc2fc8b17bc61ea 100644 (file)
@@ -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;
 
index 9d1fdfc0259e33d75a5cbbe046b937156fe5ec11..7f74b788aeac871426f846db78a82fae29b36be6 100644 (file)
@@ -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 $
 
 */
 
 
 #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 */
 
 #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
 
index 42d16449bebbe51bab192e820ed6d22fe3a17cfa..e3d250353b175726564b2aa8bd535bea699f3e68 100644 (file)
@@ -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 $
 
 */
 
 #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 <assert.h>
 #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 */
 
index ba568c2c2cc462116bc89fb3885500b01615ffcb..74a38211837300af907f4b979ab55ce1a45775c2 100644 (file)
@@ -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:
 
-   <patched call position>
-   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:
 
-   <patched call position>
-   45 8b 9a 1c 00 00 00             mov    0x1c(%r10),%r11d
-   49 81 eb 00 00 00 00             sub    $0x0,%r11
-   4d 85 db                         test   %r11,%r11
-   0f 8e 94 04 00 00                jle    0x00002aaaaab018f8
-   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;
 }
index 0708fc2d0256fa9cdbbc83efa6916d6a3e4953e9..459ad892a8be55b2ef9dbb47c4fb658c7032f8f7 100644 (file)
 #endif
 
 
+/* branches *******************************************************************/
+
+#define SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER       1
+#define SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER     1
+#define SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS    0
+#define SUPPORT_BRANCH_CONDITIONAL_UNSIGNED_CONDITIONS      1
+
+
 /* exceptions *****************************************************************/
 
 #define SUPPORT_HARDWARE_DIVIDE_BY_ZERO  0
index 6567e1da392e0a839b698eb49b84c4cf0369a7f9..cfaf31e2ab3b5742a7e43ff4ce3c093559864248 100644 (file)
@@ -53,6 +53,7 @@
        .global asm_vm_call_method_float  
        .global asm_vm_call_method_double 
        .global asm_vm_call_method_exception_handler
+       .global asm_vm_call_method_end
 
        .global asm_call_jit_compiler
 
@@ -181,6 +182,7 @@ asm_vm_call_method_exception_handler:
        call    builtin_throw_exception
        nop
        return  %i7 + 8                          /* implicit window restore */
+asm_vm_call_method_end:
        nop
        
 
index 7920828491ec03910cf6cfa29199addcd8e2e1d7..e26d96df76259646ba4348ce680be105fc1b3254 100644 (file)
@@ -29,9 +29,8 @@
 
 #include "config.h"
 
-#include <stdio.h>
 #include <assert.h>
-
+#include <stdio.h>
 
 #include "vm/types.h"
 
@@ -52,6 +51,7 @@
 #include "vm/jit/codegen-common.h"
 #include "vm/jit/dseg.h"
 #include "vm/jit/emit-common.h"
+#include "vm/jit/sparc64/emit.h"
 #include "vm/jit/jit.h"
 #include "vm/jit/parse.h"
 #include "vm/jit/patcher.h"
 
 bool fits_13(s4 disp)
 {
-       /*  printf("fits disp %d?\n", disp); */
+       /*
+       if ((disp < -4096) || (disp > 4095))
+               printf("disp %d\n", disp);
+       */
 
        return (disp >= -4096) && (disp <= 4095);
 }
 
-/* codegen *********************************************************************
+s4 get_lopart_disp(disp)
+{
+       s4 lodisp;
+       
+       if (disp > 0)
+               lodisp = setlo_part(disp);
+       else {
+               if (setlo_part(disp) == 0)
+                       lodisp = 0;
+               else
+                       lodisp = setlo_part(disp) | 0x1c00;
+       }
+               
+       return lodisp;
+}
+       
+
+/* codegen_emit ****************************************************************
 
    Generates machine code.
 
 *******************************************************************************/
 
-bool codegen(jitdata *jd)
+bool codegen_emit(jitdata *jd)
 {
        methodinfo         *m;
        codeinfo           *code;
@@ -254,7 +274,7 @@ bool codegen(jitdata *jd)
 
                                } else {                             /* stack arg -> spilled  */
                                        /* add the callers window save registers */
-                                       var->vv.regoff = cd->stackframesize + JITSTACK_CNT + s1;
+                                       var->vv.regoff = cd->stackframesize + s1;
                                }
                        }
                
@@ -273,7 +293,7 @@ bool codegen(jitdata *jd)
                                        M_DLD(var->vv.regoff, REG_FP, JITSTACK + (s1 * 8));
 
                                } else {                             /* stack-arg -> spilled  */
-                                       var->vv.regoff = cd->stackframesize + JITSTACK_CNT + s1;
+                                       var->vv.regoff = cd->stackframesize + s1;
                                }
                        }
                }
@@ -674,9 +694,9 @@ bool codegen(jitdata *jd)
                        emit_arithmetic_check(cd, iptr, s2);
                        M_ISEXT(s1, s1);
                        /* XXX trim s2 like s1 ? */
-                       M_DIVX(s1, s2, d);
-                       M_MULX(s2, d, d);
-                       M_SUB(s1, d, d);
+                       M_DIVX(s1, s2, REG_ITMP3);
+                       M_MULX(s2, REG_ITMP3, REG_ITMP3);
+                       M_SUB(s1, REG_ITMP3, d);
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -686,9 +706,9 @@ bool codegen(jitdata *jd)
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
                        emit_arithmetic_check(cd, iptr, s2);
-                       M_DIVX(s1, s2, d);
-                       M_MULX(s2, d, d);
-                       M_SUB(s1, d, d);
+                       M_DIVX(s1, s2, REG_ITMP3);
+                       M_MULX(s2, REG_ITMP3, REG_ITMP3);
+                       M_SUB(s1, REG_ITMP3, d);
                        emit_store_dst(jd, iptr, d);
                        break;
 
@@ -705,7 +725,15 @@ bool codegen(jitdata *jd)
                        break;
 
                case ICMD_ISHL:       /* ..., val1, val2  ==> ..., val1 << val2       */
-               case ICMD_LSHL:
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+                       M_SLL(s1, s2, d);
+                       emit_store_dst(jd, iptr, d);
+                       break;
+                       
+               case ICMD_LSHL:       /* ..., val1, val2  ==> ..., val1 << val2       */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
@@ -715,7 +743,16 @@ bool codegen(jitdata *jd)
                        break;
 
                case ICMD_ISHLCONST:  /* ..., value  ==> ..., value << constant       */
-               case ICMD_LSHLCONST:  /* val.i = constant                             */
+                                     /* val.i = constant                             */
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+                       M_SLL_IMM(s1, iptr->sx.val.i, d);
+                       emit_store_dst(jd, iptr, d);
+                       break;
+                       
+               case ICMD_LSHLCONST:  /* ..., value  ==> ..., value << constant       */
+                                     /* val.i = constant                             */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
@@ -1211,7 +1248,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_AADD(s2, s1, REG_ITMP3);
                        M_BLDS(d, REG_ITMP3, OFFSET(java_bytearray, data[0]));
                        emit_store_dst(jd, iptr, d);
@@ -1222,7 +1260,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_AADD(s2, s1, REG_ITMP3);
                        M_AADD(s2, REG_ITMP3, REG_ITMP3);
                        M_SLDU(d, REG_ITMP3, OFFSET(java_chararray, data[0]));
@@ -1234,7 +1273,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_AADD(s2, s1, REG_ITMP3);
                        M_AADD(s2, REG_ITMP3, REG_ITMP3);
                        M_SLDS(d, REG_ITMP3, OFFSET(java_shortarray, data[0]));
@@ -1246,7 +1286,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ASLL_IMM(s2, 2, REG_ITMP3);
                        M_AADD(REG_ITMP3, s1, REG_ITMP3);
                        M_ILD(d, REG_ITMP3, OFFSET(java_intarray, data[0]));
@@ -1258,7 +1299,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ASLL_IMM(s2, 3, REG_ITMP3);
                        M_AADD(REG_ITMP3, s1, REG_ITMP3);
                        M_LDX(d, REG_ITMP3, OFFSET(java_longarray, data[0]));
@@ -1270,7 +1312,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ASLL_IMM(s2, 2, REG_ITMP3);
                        M_AADD(REG_ITMP3, s1, REG_ITMP3);
                        M_FLD(d, REG_ITMP3, OFFSET(java_floatarray, data[0]));
@@ -1282,7 +1325,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ASLL_IMM(s2, 3, REG_ITMP3);
                        M_AADD(REG_ITMP3, s1, REG_ITMP3);
                        M_DLD(d, REG_ITMP3, OFFSET(java_doublearray, data[0]));
@@ -1294,7 +1338,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP3);
                        M_AADD(REG_ITMP3, s1, REG_ITMP3);
                        M_ALD(d, REG_ITMP3, OFFSET(java_objectarray, data[0]));
@@ -1306,7 +1351,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_AADD(s2, s1, REG_ITMP1);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
                        M_BST(s3, REG_ITMP1, OFFSET(java_bytearray, data[0]));
@@ -1317,7 +1363,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_AADD(s2, s1, REG_ITMP1);
                        M_AADD(s2, REG_ITMP1, REG_ITMP1);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
@@ -1328,7 +1375,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ASLL_IMM(s2, 2, REG_ITMP2);
                        M_AADD(REG_ITMP2, s1, REG_ITMP1);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
@@ -1339,7 +1387,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ASLL_IMM(s2, 3, REG_ITMP2);
                        M_AADD(REG_ITMP2, s1, REG_ITMP1);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
@@ -1350,7 +1399,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ASLL_IMM(s2, 2, REG_ITMP2);
                        M_AADD(REG_ITMP2, s1, REG_ITMP1);
                        s3 = emit_load_s3(jd, iptr, REG_FTMP1);
@@ -1361,7 +1411,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ASLL_IMM(s2, 3, REG_ITMP2);
                        M_AADD(REG_ITMP2, s1, REG_ITMP1);
                        s3 = emit_load_s3(jd, iptr, REG_FTMP1);
@@ -1373,7 +1424,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
 
                        M_MOV(s1, rd->argintregs[0]);
@@ -1382,16 +1434,14 @@ bool codegen(jitdata *jd)
                        M_ALD(REG_ITMP3, REG_PV, disp);
                        M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
                        M_NOP;
-
-                       M_BEQZ(REG_RESULT_CALLER, 0);
-                       codegen_add_arraystoreexception_ref(cd);
-                       M_NOP;
+                       emit_exception_check(cd, iptr);
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
                        M_AADD(REG_ITMP2, s1, REG_ITMP1);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
+                       /* implicit null-pointer check */
                        M_AST_INTERN(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
                        break;
 
@@ -1400,7 +1450,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_AADD(s2, s1, REG_ITMP1);
                        M_BST(REG_ZERO, REG_ITMP1, OFFSET(java_bytearray, data[0]));
                        break;
@@ -1410,7 +1461,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_AADD(s2, s1, REG_ITMP1);
                        M_AADD(s2, REG_ITMP1, REG_ITMP1);
                        M_SST(REG_ZERO, REG_ITMP1, OFFSET(java_chararray, data[0]));
@@ -1420,7 +1472,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ASLL_IMM(s2, 2, REG_ITMP2);
                        M_AADD(REG_ITMP2, s1, REG_ITMP1);
                        M_IST_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_intarray, data[0]));
@@ -1430,7 +1483,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ASLL_IMM(s2, 3, REG_ITMP2);
                        M_AADD(REG_ITMP2, s1, REG_ITMP1);
                        M_STX_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_longarray, data[0]));
@@ -1440,7 +1494,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
                        M_AADD(REG_ITMP2, s1, REG_ITMP1);
                        M_AST_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_objectarray, data[0]));
@@ -1750,158 +1805,115 @@ bool codegen(jitdata *jd)
                case ICMD_GOTO:         /* ... ==> ...                                */
                case ICMD_RET:          /* ... ==> ...                                */
 
-                       M_BR(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_br(cd, iptr->dst.block);
                        ALIGNCODENOP;
                        break;
 
                case ICMD_JSR:          /* ... ==> ...                                */
 
-                       M_BR(0);
-                       codegen_add_branch_ref(cd, iptr->sx.s23.s3.jsrtarget.block);
-                       M_NOP;
+                       emit_br(cd, iptr->sx.s23.s3.jsrtarget.block);
                        ALIGNCODENOP;
                        break;
 
                case ICMD_IFNULL:       /* ..., value ==> ...                         */
+               case ICMD_IFNONNULL:
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       M_BEQZ(s1, 0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
-                       break;
-
-               case ICMD_IFNONNULL:    /* ..., value ==> ...                         */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       M_BNEZ(s1, 0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_bccz(cd, iptr->dst.block, iptr->opc - ICMD_IFNULL, s1, BRANCH_OPT_NONE);
                        break;
+                       
+               /* Note: int compares must not branch on the register directly.       */
+               /* Reason is, that register content is not 32-bit clean.              */
 
                case ICMD_IFEQ:         /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.i == 0) {
-                               M_BEQZ(s1, 0);
-                       } else {
-                               if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
-                                       M_CMP_IMM(s1, iptr->sx.val.i);
-                                       }
-                               else {
-                                       ICONST(REG_ITMP2, iptr->sx.val.i);
-                                       M_CMP(s1, REG_ITMP2);
-                                       }
-                               M_BEQ(0);
-                               }
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       
+                       if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
+                               M_CMP_IMM(s1, iptr->sx.val.i);
+                       }
+                       else {
+                               ICONST(REG_ITMP2, iptr->sx.val.i);
+                               M_CMP(s1, REG_ITMP2);
+                       }
+                       emit_beq(cd, iptr->dst.block);
                        break;
 
                case ICMD_IFLT:         /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.i == 0) {
-                               M_BLTZ(s1, 0);
-                       } else {
-                               if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
-                                       M_CMP_IMM(s1, iptr->sx.val.i);
-                               } else {
-                                       ICONST(REG_ITMP2, iptr->sx.val.i);
-                                       M_CMP(s1, REG_ITMP2);
-                               }
-                               M_BLT(0);
+                       
+                       if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
+                               M_CMP_IMM(s1, iptr->sx.val.i);
+                       } 
+                       else {
+                               ICONST(REG_ITMP2, iptr->sx.val.i);
+                               M_CMP(s1, REG_ITMP2);
                        }
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_blt(cd, iptr->dst.block);
                        break;
 
                case ICMD_IFLE:         /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.i == 0) {
-                               M_BLEZ(s1, 0);
-                               }
+
+                       if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
+                               M_CMP_IMM(s1, iptr->sx.val.i);
+                       }
                        else {
-                               if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
-                                       M_CMP_IMM(s1, iptr->sx.val.i);
-                                       }
-                               else {
-                                       ICONST(REG_ITMP2, iptr->sx.val.i);
-                                       M_CMP(s1, REG_ITMP2);
-                               }
-                               M_BLE(0);
+                               ICONST(REG_ITMP2, iptr->sx.val.i);
+                               M_CMP(s1, REG_ITMP2);
                        }
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_ble(cd, iptr->dst.block);
                        break;
 
                case ICMD_IFNE:         /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.i == 0) {
-                               M_BNEZ(s1, 0);
-                               }
+               
+                       if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
+                               M_CMP_IMM(s1, iptr->sx.val.i);
+                       }
                        else {
-                               if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
-                                       M_CMP_IMM(s1, iptr->sx.val.i);
-                               }
-                               else {
-                                       ICONST(REG_ITMP2, iptr->sx.val.i);
-                                       M_CMP(s1, REG_ITMP2);
-                               }
-                               M_BNE(0);
+                               ICONST(REG_ITMP2, iptr->sx.val.i);
+                               M_CMP(s1, REG_ITMP2);
                        }
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_bne(cd, iptr->dst.block);
                        break;
                                                
                case ICMD_IFGT:         /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.i == 0) {
-                               M_BGTZ(s1, 0);
+               
+                       if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
+                               M_CMP_IMM(s1, iptr->sx.val.i);
                        } 
                        else {
-                               if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
-                                       M_CMP_IMM(s1, iptr->sx.val.i);
-                               } else {
-                                       ICONST(REG_ITMP2, iptr->sx.val.i);
-                                       M_CMP(s1, REG_ITMP2);
-                               }
-                               M_BGT(0);
+                               ICONST(REG_ITMP2, iptr->sx.val.i);
+                               M_CMP(s1, REG_ITMP2);
                        }
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_bgt(cd, iptr->dst.block);          
                        break;
 
                case ICMD_IFGE:         /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.i == 0) {
-                               M_BGEZ(s1, 0);
-                               }
+
+                       if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
+                               M_CMP_IMM(s1, iptr->sx.val.i);
+                       }
                        else {
-                               if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
-                                       M_CMP_IMM(s1, iptr->sx.val.i);
-                                       }
-                               else {
-                                       ICONST(REG_ITMP2, iptr->sx.val.i);
-                                       M_CMP(s1, REG_ITMP2);
-                               }
-                               M_BGE(0);
+                               ICONST(REG_ITMP2, iptr->sx.val.i);
+                               M_CMP(s1, REG_ITMP2);
                        }
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_bge(cd, iptr->dst.block);
                        break;
                        
                case ICMD_IF_LEQ:       /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.l == 0) {
-                               M_BEQZ(s1, 0);
-                       }
+                       if (iptr->sx.val.l == 0)
+                               emit_beqz(cd, iptr->dst.block, s1);
                        else {
                                if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
                                        M_CMP_IMM(s1, iptr->sx.val.l);
@@ -1910,18 +1922,15 @@ bool codegen(jitdata *jd)
                                        LCONST(REG_ITMP2, iptr->sx.val.l);
                                        M_CMP(s1, REG_ITMP2);
                                }
-                               M_XBEQ(0);
+                               emit_beq_xcc(cd, iptr->dst.block);
                        }
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
                        break;
                        
                case ICMD_IF_LLT:       /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.l == 0) {
-                               M_BLTZ(s1, 0);
-                       } 
+                       if (iptr->sx.val.l == 0)
+                               emit_bltz(cd, iptr->dst.block, s1);
                        else {
                                if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
                                        M_CMP_IMM(s1, iptr->sx.val.l);
@@ -1930,76 +1939,66 @@ bool codegen(jitdata *jd)
                                        ICONST(REG_ITMP2, iptr->sx.val.l);
                                        M_CMP(s1, REG_ITMP2);
                                }
-                               M_XBLT(0);
+                               emit_blt_xcc(cd, iptr->dst.block);
                        }
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
                        break;
 
                case ICMD_IF_LLE:       /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.l == 0) {
-                               M_BLEZ(s1, 0);
-                               }
+                       if (iptr->sx.val.l == 0)
+                               emit_blez(cd, iptr->dst.block, s1);
                        else {
                                if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
                                        M_CMP_IMM(s1, iptr->sx.val.l);
-                                       }
+                               }
                                else {
                                        ICONST(REG_ITMP2, iptr->sx.val.l);
                                        M_CMP(s1, REG_ITMP2);
                                }
-                               M_XBLE(0);
+                               emit_ble_xcc(cd, iptr->dst.block);
                        }
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
                        break;
                        
                case ICMD_IF_LNE:       /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.l == 0) {
-                               M_BNEZ(s1, 0);
-                               }
+                       if (iptr->sx.val.l == 0)
+                               emit_bnez(cd, iptr->dst.block, s1);
                        else {
                                if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
-                                       M_CMP_IMM(s1, iptr->sx.val.i);
+                                       M_CMP_IMM(s1, iptr->sx.val.l);
                                }
                                else {
                                        ICONST(REG_ITMP2, iptr->sx.val.l);
                                        M_CMP(s1, REG_ITMP2);
                                }
-                               M_XBNE(0);
+                               emit_bne_xcc(cd, iptr->dst.block);
                        }
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
                        break;
                                                
                case ICMD_IF_LGT:       /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.l == 0) {
-                               M_BGTZ(s1, 0);
-                       else {
+                       if (iptr->sx.val.l == 0)
+                               emit_bgtz(cd, iptr->dst.block, s1);
+                       else {
                                if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
                                        M_CMP_IMM(s1, iptr->sx.val.l);
-                               } else {
+                               } 
+                               else {
                                        ICONST(REG_ITMP2, iptr->sx.val.l);
                                        M_CMP(s1, REG_ITMP2);
                                }
-                               M_XBGT(0);
+                               emit_bgt_xcc(cd, iptr->dst.block);
                        }
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
                        break;
 
                case ICMD_IF_LGE:       /* ..., value ==> ...                         */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (iptr->sx.val.l == 0) {
-                               M_BGEZ(s1, 0);
-                       }
+                       if (iptr->sx.val.l == 0)
+                               emit_bgez(cd, iptr->dst.block, s1);
                        else {
                                if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
                                        M_CMP_IMM(s1, iptr->sx.val.l);
@@ -2008,10 +2007,8 @@ bool codegen(jitdata *jd)
                                        ICONST(REG_ITMP2, iptr->sx.val.l);
                                        M_CMP(s1, REG_ITMP2);
                                }
-                               M_XBGE(0);
+                               emit_bge_xcc(cd, iptr->dst.block);
                        }
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
                        break;                  
                        
 
@@ -2021,9 +2018,7 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_CMP(s1, s2);
-                       M_XBEQ(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_beq_xcc(cd, iptr->dst.block);
                        break;
 
                case ICMD_IF_ICMPEQ:    /* 32-bit compare                             */
@@ -2031,9 +2026,7 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_CMP(s1, s2);
-                       M_BEQ(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_beq(cd, iptr->dst.block);
                        break;
 
                case ICMD_IF_ACMPNE:    /* ..., value, value ==> ...                  */
@@ -2042,9 +2035,7 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_CMP(s1, s2);
-                       M_XBNE(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_bne_xcc(cd, iptr->dst.block);
                        break;
                        
                case ICMD_IF_ICMPNE:    /* 32-bit compare                             */
@@ -2052,9 +2043,7 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_CMP(s1, s2);
-                       M_BNE(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_bne(cd, iptr->dst.block);
                        break;
 
                case ICMD_IF_LCMPLT:    /* ..., value, value ==> ...                  */
@@ -2062,9 +2051,7 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_CMP(s1, s2);
-                       M_XBLT(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_blt_xcc(cd, iptr->dst.block);
                        break;
                        
                case ICMD_IF_ICMPLT:    /* 32-bit compare                             */
@@ -2072,9 +2059,7 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_CMP(s1, s2);
-                       M_BLT(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_blt(cd, iptr->dst.block);
                        break;
 
                case ICMD_IF_LCMPGT:    /* ..., value, value ==> ...                  */
@@ -2082,9 +2067,7 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_CMP(s1, s2);
-                       M_XBGT(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_bgt_xcc(cd, iptr->dst.block);
                        break;
                        
                case ICMD_IF_ICMPGT:    /* 32-bit compare                             */
@@ -2092,9 +2075,7 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_CMP(s1, s2);
-                       M_BGT(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_bgt(cd, iptr->dst.block);
                        break;
 
                case ICMD_IF_LCMPLE:    /* ..., value, value ==> ...                  */
@@ -2102,9 +2083,7 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_CMP(s1, s2);
-                       M_BLE(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_ble_xcc(cd, iptr->dst.block);
                        break;
                        
                case ICMD_IF_ICMPLE:    /* 32-bit compare                             */
@@ -2112,9 +2091,7 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_CMP(s1, s2);
-                       M_BLE(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_ble(cd, iptr->dst.block);
                        break;                  
        
 
@@ -2123,9 +2100,7 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_CMP(s1, s2);
-                       M_BGE(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_bge_xcc(cd, iptr->dst.block);
                        break;
                        
                case ICMD_IF_ICMPGE:    /* 32-bit compare                             */
@@ -2133,9 +2108,7 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_CMP(s1, s2);
-                       M_BGE(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       M_NOP;
+                       emit_bge(cd, iptr->dst.block);
                        break;
 
 
@@ -2247,9 +2220,7 @@ nowperformreturn:
                                ICONST(REG_ITMP2, i - 1);
                                M_CMP(REG_ITMP1, REG_ITMP2);
                        }               
-                       M_XBUGT(0);
-                       codegen_add_branch_ref(cd, table[0].block); /* default target */
-                       M_ASLL_IMM(REG_ITMP1, POINTERSHIFT, REG_ITMP1);      /* delay slot*/
+                       emit_bugt(cd, table[0].block); /* default target */
 
                        /* build jump table top down and use address of lowest entry */
 
@@ -2263,6 +2234,7 @@ nowperformreturn:
 
                        /* length of dataseg after last dseg_addtarget is used by load */
 
+                       M_ASLL_IMM(REG_ITMP1, POINTERSHIFT, REG_ITMP1);
                        M_AADD(REG_ITMP1, REG_PV, REG_ITMP2);
                        M_ALD(REG_ITMP2, REG_ITMP2, -(cd->dseglen));
                        M_JMP(REG_ZERO, REG_ITMP2, REG_ZERO);
@@ -2289,15 +2261,11 @@ nowperformreturn:
                                        ICONST(REG_ITMP2, lookup->value);
                                        M_CMP(s1, REG_ITMP2);
                                }
-                               M_BEQ(0);
-                               codegen_add_branch_ref(cd, lookup->target.block); 
-                               M_NOP;
+                               emit_beq(cd, lookup->target.block);
                                ++lookup;
                        }
 
-                       M_BR(0);
-                       codegen_add_branch_ref(cd, iptr->sx.s23.s3.lookupdefault.block);
-                       M_NOP;
+                       emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
                        ALIGNCODENOP;
                        break;
                        }
@@ -2378,17 +2346,22 @@ gen_method:
                                disp = dseg_add_functionptr(cd, bte->fp);
 
                                M_ALD(REG_PV_CALLER, REG_PV, disp);  /* built-in-function pointer */
-                               s1 = REG_PV_CALLER;
 
                                /* XXX jit-c-call */
-
+                               /* generate the actual call */
+    
+                           M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
+                           M_NOP;
+                           disp = (s4) (cd->mcodeptr - cd->mcodebase);
+                           /* REG_RA holds the value of the jmp instruction, therefore +8 */
+                           M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8); 
+
+                               emit_exception_check(cd, iptr);
                                break;
 
                        case ICMD_INVOKESPECIAL:
-                               M_BEQZ(REG_OUT0, 0);
-                               codegen_add_nullpointerexception_ref(cd);
-                               M_NOP;
-                               /* fall through */
+                               emit_nullpointer_check(cd, iptr, REG_OUT0);
+                               /* fall-through */
 
                        case ICMD_INVOKESTATIC:
                                if (lm == NULL) {
@@ -2401,7 +2374,14 @@ gen_method:
                                        disp = dseg_add_address(cd, lm->stubroutine);
 
                                M_ALD(REG_PV_CALLER, REG_PV, disp);          /* method pointer in pv */
-                               s1 = REG_PV_CALLER;
+                               
+                               /* generate the actual call */
+    
+                           M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
+                           M_NOP;
+                           disp = (s4) (cd->mcodeptr - cd->mcodebase);
+                           /* REG_RA holds the value of the jmp instruction, therefore +8 */
+                           M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8); 
                                break;
 
                        case ICMD_INVOKEVIRTUAL:
@@ -2416,10 +2396,17 @@ gen_method:
                                        s1 = OFFSET(vftbl_t, table[0]) +
                                                sizeof(methodptr) * lm->vftblindex;
 
-                               M_ALD(REG_METHODPTR, REG_OUT0,
-                                         OFFSET(java_objectheader, vftbl));
+                               /* implicit null-pointer check */
+                               M_ALD(REG_METHODPTR, REG_OUT0,OFFSET(java_objectheader, vftbl));
                                M_ALD(REG_PV_CALLER, REG_METHODPTR, s1);
-                               s1 = REG_PV_CALLER;
+                               
+                               /* generate the actual call */
+    
+                           M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
+                           M_NOP;
+                           disp = (s4) (cd->mcodeptr - cd->mcodebase);
+                           /* REG_RA holds the value of the jmp instruction, therefore +8 */
+                           M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8); 
                                break;
 
                        case ICMD_INVOKEINTERFACE:
@@ -2438,29 +2425,19 @@ gen_method:
                                        s2 = sizeof(methodptr) * (lm - lm->class->methods);
                                }
 
-                               M_ALD(REG_METHODPTR, REG_OUT0,
-                                         OFFSET(java_objectheader, vftbl));
+                               /* implicit null-pointer check */
+                               M_ALD(REG_METHODPTR, REG_OUT0, OFFSET(java_objectheader, vftbl));
                                M_ALD(REG_METHODPTR, REG_METHODPTR, s1);
                                M_ALD(REG_PV_CALLER, REG_METHODPTR, s2);
-                               s1 = REG_PV_CALLER;
-                               break;
-                       }
 
-                       /* generate the actual call */
-
-                       M_JMP(REG_RA_CALLER, s1, REG_ZERO);
-                       M_NOP;
-                       disp = (s4) (cd->mcodeptr - cd->mcodebase);
-                       /* REG_RA holds the value of the jmp instruction, therefore +8 */
-                       M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8); 
-
-
-                       /* actually only used for ICMD_BUILTIN */
-
-                       if (INSTRUCTION_MUST_CHECK(iptr)) {
-                               M_BEQZ(REG_RESULT_CALLER, 0);
-                               codegen_add_fillinstacktrace_ref(cd);
-                               M_NOP;
+                           /* generate the actual call */
+    
+                           M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
+                           M_NOP;
+                           disp = (s4) (cd->mcodeptr - cd->mcodebase);
+                           /* REG_RA holds the value of the jmp instruction, therefore +8 */
+                           M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8);
+                               break;
                        }
 
                        /* store return value */
@@ -2520,23 +2497,10 @@ gen_method:
 
                                s1 = emit_load_s1(jd, iptr, REG_ITMP1);
 
-                               /* calculate interface checkcast code size */
-
-                               s2 = 8;
-                               if (super == NULL)
-                                       s2 += (opt_shownops ? PATCHER_CALL_INSTRUCTIONS : 0);
-
-                               /* calculate class checkcast code size */
-
-                               s3 = 10;
-                               if (super == NULL)
-                                       s3 += (opt_shownops ? PATCHER_CALL_INSTRUCTIONS : 0);
-
                                /* if class is not resolved, check which code to call */
 
                                if (super == NULL) {
-                                       M_BEQZ(s1, 5 + (opt_shownops ? PATCHER_CALL_INSTRUCTIONS : 0) + s2 + 2 + s3 + 1);
-                                       M_NOP;
+                                       emit_label_beqz(cd, BRANCH_LABEL_1, s1);
 
                                        cr   = iptr->sx.s23.s3.c.ref;
                                        disp = dseg_add_unique_s4(cd, 0);         /* super->flags */
@@ -2546,8 +2510,7 @@ gen_method:
 
                                        M_ILD(REG_ITMP2, REG_PV, disp);
                                        M_AND_IMM(REG_ITMP2, ACC_INTERFACE, REG_ITMP2);
-                                       M_BEQZ(REG_ITMP2, s2 + 2 + 2);
-                                       M_NOP;
+                                       emit_label_beqz(cd, BRANCH_LABEL_2, REG_ITMP2);
                                }
 
                                /* interface checkcast code */
@@ -2560,37 +2523,32 @@ gen_method:
                                                                                          cr, 0);
                                        }
                                        else {
-                                               M_BEQZ(s1, s2 + 2);
-                                               M_NOP;
+                                               emit_label_beqz(cd, BRANCH_LABEL_3, s1);
                                        }
 
                                        M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
                                        M_ILD(REG_ITMP3, REG_ITMP2,
                                                        OFFSET(vftbl_t, interfacetablelength));
                                        M_ADD_IMM(REG_ITMP3, -superindex, REG_ITMP3);
-                                       M_BLEZ(REG_ITMP3, 0);
-                                       codegen_add_classcastexception_ref(cd, s1);
-                                       M_NOP;
+                                       emit_classcast_check(cd, iptr, ICMD_IFLE, REG_ITMP3, s1);
+
                                        M_ALD(REG_ITMP3, REG_ITMP2,
                                                  OFFSET(vftbl_t, interfacetable[0]) -
                                                  superindex * sizeof(methodptr*));
-                                       M_BEQZ(REG_ITMP3, 0);
-                                       codegen_add_classcastexception_ref(cd, s1);
-                                       M_NOP;
+                                       emit_classcast_check(cd, iptr, ICMD_IFEQ, REG_ITMP3, s1);
 
-                                       if (super == NULL) {
-                                   /* on sparc we always add 2 to the size of the code we want  */
-                                   /* branch over. (1 for branch delay nop, 1 since the base is */
-                                   /* the address of the branch instruction */
-                                               M_BR(s3 + 2);
-                                               M_NOP;
-                                       }
+                                       if (super == NULL)
+                                               emit_label_br(cd, BRANCH_LABEL_4);
+                                       else
+                                               emit_label(cd, BRANCH_LABEL_3);
                                }
 
                                /* class checkcast code */
 
                                if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
                                        if (super == NULL) {
+                                               emit_label(cd, BRANCH_LABEL_2);
+
                                                cr   = iptr->sx.s23.s3.c.ref;
                                                disp = dseg_add_unique_address(cd, NULL);
 
@@ -2601,8 +2559,7 @@ gen_method:
                                        else {
                                                disp = dseg_add_address(cd, super->vftbl);
 
-                                               M_BEQZ(s1, s3 + 2);
-                                               M_NOP;
+                                               emit_label_beqz(cd, BRANCH_LABEL_5, s1);
                                        }
 
                                        M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
@@ -2620,9 +2577,15 @@ gen_method:
 #endif
                                        /*                              } */
                                        M_CMP(REG_ITMP3, REG_ITMP2);
-                                       M_BULT(0);                         /* branch if ITMP3 < ITMP2 */ 
-                                       codegen_add_classcastexception_ref(cd, s1);
-                                       M_NOP;
+                                       emit_classcast_check(cd, iptr, BRANCH_ULT, REG_ITMP3, s1);
+
+                                       if (super != NULL)
+                                               emit_label(cd, BRANCH_LABEL_5);
+                               }
+
+                               if (super == NULL) {
+                                       emit_label(cd, BRANCH_LABEL_1);
+                                       emit_label(cd, BRANCH_LABEL_4);
                                }
 
                                d = codegen_reg_of_dst(jd, iptr, s1);
@@ -2653,9 +2616,7 @@ gen_method:
                                M_NOP;
 
                                s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                               M_BEQZ(REG_RESULT_CALLER, 0);
-                               codegen_add_classcastexception_ref(cd, s1);
-                               M_NOP;
+                               emit_classcast_check(cd, iptr, ICMD_IFEQ, REG_RESULT_CALLER, s1);
 
                                d = codegen_reg_of_dst(jd, iptr, s1);
                        }
@@ -2665,6 +2626,7 @@ gen_method:
                        break;
 
                case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult            */
+                                     /* val.a: (classinfo*) superclass               */
 
                        /*  superclass is an interface:
                         *      
@@ -2705,25 +2667,12 @@ gen_method:
                                s1 = REG_ITMP1;
                        }
 
-                       /* calculate interface instanceof code size */
-
-                       s2 = 7;
-                       if (super == NULL)
-                               s2 += (opt_shownops ? PATCHER_CALL_INSTRUCTIONS : 0);
-
-                       /* calculate class instanceof code size */
-
-                       s3 = 8;
-                       if (super == NULL)
-                               s3 += (opt_shownops ? PATCHER_CALL_INSTRUCTIONS : 0);
-
                        M_CLR(d);
 
                        /* if class is not resolved, check which code to call */
 
                        if (super == NULL) {
-                               M_BEQZ(s1, 5 + (opt_shownops ? PATCHER_CALL_INSTRUCTIONS : 0) + s2 + 2 + s3);
-                               M_NOP;
+                               emit_label_beqz(cd, BRANCH_LABEL_1, s1);
 
                                cr   = iptr->sx.s23.s3.c.ref;
                                disp = dseg_add_unique_s4(cd, 0);             /* super->flags */
@@ -2733,8 +2682,7 @@ gen_method:
 
                                M_ILD(REG_ITMP3, REG_PV, disp);
                                M_AND_IMM(REG_ITMP3, ACC_INTERFACE, REG_ITMP3);
-                               M_BEQZ(REG_ITMP3, s2 + 2 + 2);
-                               M_NOP;
+                               emit_label_beqz(cd, BRANCH_LABEL_2, REG_ITMP3);
                        }
 
                        /* interface instanceof code */
@@ -2747,8 +2695,7 @@ gen_method:
                                                                                  cr, 0);
                                }
                                else {
-                                       M_BEQZ(s1, s2 + 2);
-                                       M_NOP;
+                                       emit_label_beqz(cd, BRANCH_LABEL_3, s1);
                                }
 
                                M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
@@ -2761,16 +2708,18 @@ gen_method:
                                                        superindex * sizeof(methodptr*)));
                                M_CMOVRNE_IMM(REG_ITMP1, 1, d);      /* REG_ITMP1 != 0  */
 
-                               if (super == NULL) {
-                                       M_BR(s3 + 2);
-                                       M_NOP;
-                               }
+                               if (super == NULL)
+                                       emit_label_br(cd, BRANCH_LABEL_4);
+                               else
+                                       emit_label(cd, BRANCH_LABEL_3);
                        }
 
                        /* class instanceof code */
 
                        if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
                                if (super == NULL) {
+                                       emit_label(cd, BRANCH_LABEL_2);
+
                                        cr   = iptr->sx.s23.s3.c.ref;
                                        disp = dseg_add_unique_address(cd, NULL);
 
@@ -2780,8 +2729,7 @@ gen_method:
                                else {
                                        disp = dseg_add_address(cd, supervftbl);
 
-                                       M_BEQZ(s1, s3 + 2);
-                                       M_NOP;
+                                       emit_label_beqz(cd, BRANCH_LABEL_5, s1);
                                }
 
                                M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
@@ -2798,7 +2746,16 @@ gen_method:
                                M_SUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
                                M_CMP(REG_ITMP1, REG_ITMP2);
                                M_XCMOVULE_IMM(1, d);
+
+                               if (super != NULL)
+                                       emit_label(cd, BRANCH_LABEL_5);
                        }
+
+                       if (super == NULL) {
+                               emit_label(cd, BRANCH_LABEL_1);
+                               emit_label(cd, BRANCH_LABEL_4);
+                       }
+
                        emit_store_dst(jd, iptr, d);
                        }
                        break;
@@ -2855,9 +2812,7 @@ gen_method:
 
                        /* check for exception before result assignment */
 
-                       M_BEQZ(REG_RESULT_CALLER, 0);
-                       codegen_add_fillinstacktrace_ref(cd);
-                       M_NOP;
+                       emit_exception_check(cd, iptr);
 
                        d = codegen_reg_of_dst(jd, iptr, REG_RESULT_CALLER);
                        M_INTMOVE(REG_RESULT_CALLER, d);
@@ -2880,15 +2835,10 @@ gen_method:
        
        dseg_createlinenumbertable(cd);
 
-       /* generate exception and patcher stubs */
+       /* generate stubs */
 
-       emit_exception_stubs(jd);
        emit_patcher_stubs(jd);
-#if defined(ENABLE_REPLACEMENT)
-       emit_replacement_stubs(jd);
-#endif /* defined(ENABLE_REPLACEMENT) */
-
-       codegen_finish(jd);
+       REPLACEMENT_EMIT_STUBS(jd);
        
        /* everything's ok */
 
@@ -2896,9 +2846,6 @@ gen_method:
 }
 
 
-
-
-
 /* createcompilerstub **********************************************************
 
    Creates a stub routine which calls the compiler.
@@ -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;
index 447718d76b08f88579a83a959e7e77424b2a04fe..6edfa3b1bfffb625e44affa31b2689fe2d1d4337 100644 (file)
@@ -63,6 +63,9 @@ s4 nat_argintregs[INT_NATARG_CNT];
 #define PATCHER_CALL_INSTRUCTIONS    2     /* number of instructions          */
 #define PATCHER_CALL_SIZE            2 * 4 /* size in bytes of a patcher call */
 
+#define EXCEPTION_CHECK_INSTRUCTIONS 3     /* number of instructions          */
+#define EXCEPTION_CHECK_SIZE         3 * 4 /* byte size of an exception check */
+
 #define PATCHER_NOPS \
     do { \
         M_NOP; \
@@ -142,6 +145,10 @@ s4 nat_argintregs[INT_NATARG_CNT];
        } while (0)
 
 
+#define M_OP3_GET_RD(x)               (((x) >> 25) & 0x1f)
+#define M_OP3_GET_RS(x)               (((x) >> 14) & 0x1f)
+#define M_OP3_GET_IMM(x)              ( (x)        & 0x1fff)
+
 /* 3-address-operations: M_OP3C
  *       rcond ... condition opcode
  *       rs2 ..... register number or 10bit signed immediate
@@ -166,8 +173,8 @@ s4 nat_argintregs[INT_NATARG_CNT];
  */
 #define M_SHFT(op,op3,rs1,rs2,rd,imm,x) \
        do { \
-               *((u4 *) cd->mcodeptr) =  ( (((s4)(op)) << 30) | ((op3) << 19) | ((rd) << 25) | ((rs1) << 14) | ((rs2) << 0) | \
-                     ((imm) << 13) | ((x) << 12) ); \
+               *((u4 *) cd->mcodeptr) =  ( (((s4)(op)) << 30) | ((op3) << 19) | ((rd) << 25) | ((rs1) << 14) | ((imm) << 13) | \
+                       ((x) << 12) | (((imm) && (x))?((rs2) & 0x3f):((rs2) & 0x1f)) ); \
                cd->mcodeptr += 4; \
        } while (0)
 
@@ -306,13 +313,15 @@ s4 nat_argintregs[INT_NATARG_CNT];
 
 #define M_SLLX(rs1,rs2,rd)             M_SHFT(0x02,0x25,rs1,rs2,rd,REG,1)      /* 64b rd = rs << rs2 */
 #define M_SLLX_IMM(rs1,rs2,rd) M_SHFT(0x02,0x25,rs1,rs2,rd,IMM,1)
+#define M_SLL(rs1,rs2,rd)              M_SHFT(0x02,0x25,rs1,rs2,rd,REG,0)      /* 32b rd = rs << rs2 */
+#define M_SLL_IMM(rs1,rs2,rd)  M_SHFT(0x02,0x25,rs1,rs2,rd,IMM,0)
 #define M_SRLX(rs1,rs2,rd)             M_SHFT(0x02,0x26,rs1,rs2,rd,REG,1)      /* 64b rd = rs >>>rs2 */
 #define M_SRLX_IMM(rs1,rs2,rd) M_SHFT(0x02,0x26,rs1,rs2,rd,IMM,1)
 #define M_SRL(rs1,rs2,rd)              M_SHFT(0x02,0x26,rs1,rs2,rd,REG,0)      /* 32b rd = rs >>>rs2 */
 #define M_SRL_IMM(rs1,rs2,rd)  M_SHFT(0x02,0x26,rs1,rs2,rd,IMM,0)
 #define M_SRAX(rs1,rs2,rd)             M_SHFT(0x02,0x27,rs1,rs2,rd,REG,1)      /* 64b rd = rs >> rs2 */
 #define M_SRAX_IMM(rs1,rs2,rd) M_SHFT(0x02,0x27,rs1,rs2,rd,IMM,1)
-#define M_SRA(rs1,rs2,rd)     M_SHFT(0x02,0x27,rs1,rs2,rd,REG,0)  /* 32b rd = rs >> rs2 */
+#define M_SRA(rs1,rs2,rd)       M_SHFT(0x02,0x27,rs1,rs2,rd,REG,0)  /* 32b rd = rs >> rs2 */
 #define M_SRA_IMM(rs1,rs2,rd)  M_SHFT(0x02,0x27,rs1,rs2,rd,IMM,0)
 
 #define M_ISEXT(rs,rd)                         M_SRA(rs,REG_ZERO,rd)                 /* sign extend 32 bits*/
@@ -386,7 +395,10 @@ s4 nat_argintregs[INT_NATARG_CNT];
 
 /* #define FITS_13BIT_IMM(x)       ((x >= -4096) && (x <= 4095)) */
 
-bool fits13(s4 disp);
+bool fits_13(s4 disp);
+s4   get_lopart_disp(s4 disp);
+
+#define abs(x) ((x) < 0 ? (-(x)) : (x))
 
 #define sethi_part(x) ((x)>>10)
 #define setlo_part(x) ((x) & 0x3ff)
@@ -407,14 +419,18 @@ bool fits13(s4 disp);
        
 #define DO_SETHI_PART(c,rs,rd) \
        do { \
-               M_SETHI(sethi_part(c), rd); \
                if (c > 0) { \
+                       M_SETHI(sethi_part(c), rd); \
                        M_ADD(rs,rd,rd); \
                } \
                else { \
+                       M_SETHI(sethi_part(-c), rd); \
                        M_SUB(rs,rd,rd); \
+                       assert(sethi_part(c) != 0xf); \
                } \
        } while (0)
+       
+
                
 
 #define M_LDA(rd,rs,disp) \
@@ -442,10 +458,8 @@ bool fits13(s4 disp);
             M_LDX_INTERN(rd,rs,disp); \
         } \
         else { \
-                       printf("ldx imm = %d\n", disp); \
-            DO_SETHI_PART(disp,rs,rd); \
-            M_LDX_INTERN(rd,rd,setlo_part(disp)); \
-                       assert(0); \
+               DO_SETHI_PART(disp,rs,rd); \
+               M_LDX_INTERN(rd,rd,get_lopart_disp(disp)); \
         } \
     } while (0)
 
@@ -457,8 +471,7 @@ bool fits13(s4 disp);
        } \
         else { \
             DO_SETHI_PART(disp,rs,rd); \
-            M_ILD_INTERN(rd,rd,setlo_part(disp)); \
-                       assert(0); \
+            M_ILD_INTERN(rd,rd,get_lopart_disp(disp)); \
         } \
     } while (0)
 
index b015d17be61370f78832673b12e95cd03dd41d54..2595d79e8ad52c581e819d17d2ebb992e449a020 100644 (file)
@@ -1,4 +1,4 @@
-/* src/vm/jit/sparc64/emit.c - Sparc code emitter functions
+/* src/vm/jit/sparc64/emit.c - SPARC code emitter functions
 
    Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
 
 
 #include "config.h"
+
+#include <assert.h>
+
 #include "vm/types.h"
 
 #include "vm/jit/sparc64/codegen.h"
 #include "vm/jit/sparc64/md-abi.h"
+#include "vm/jit/sparc64/emit.h"
 
 #include "mm/memory.h"
 
+#include "vm/exceptions.h"
 #include "vm/stringlocal.h" /* XXX for gen_resolvebranch */
 #include "vm/jit/abi-asm.h"
 #include "vm/jit/asmpart.h"
@@ -228,6 +233,212 @@ void emit_lconst(codegendata *cd, s4 d, s8 value)
        }
 }
 
+/* emit_branch *****************************************************************
+
+   Emits the code for conditional and unconditional branchs.
+
+*******************************************************************************/
+
+void emit_branch(codegendata *cd, s4 disp, s4 condition, s4 reg, u4 opt)
+{
+       s4 branchdisp;
+
+       /* calculate the different displacements */
+
+       branchdisp = disp >> 2;
+
+       /* check which branch to generate */
+
+       if (condition == BRANCH_UNCONDITIONAL) {
+               /* check displacement for overflow (19-bit)*/
+
+               if ((branchdisp < (s4) 0xfffc0000) || (branchdisp > (s4) 0x003ffff)) {
+                       /* if the long-branches flag isn't set yet, do it */
+
+                       if (!CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
+                               cd->flags |= (CODEGENDATA_FLAG_ERROR |
+                                                         CODEGENDATA_FLAG_LONGBRANCHES);
+                       }
+
+                       vm_abort("emit_branch: emit unconditional long-branch code");
+               }
+               else {
+                       M_BR(branchdisp);
+                       M_NOP;
+               }
+       }
+       else if (reg == -1) {
+               /* branch on condition codes */
+
+               /* check displacement for overflow (19-bit)*/
+
+               if ((branchdisp < (s4) 0xfffc0000) || (branchdisp > (s4) 0x003ffff)) {
+                       /* if the long-branches flag isn't set yet, do it */
+
+                       if (!CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
+                               log_println("setting error");
+                               cd->flags |= (CODEGENDATA_FLAG_ERROR |
+                                                         CODEGENDATA_FLAG_LONGBRANCHES);
+                       }
+
+                       vm_abort("emit_branch: emit long-branch on cc code");
+               }
+               else {
+                       /* check whether to branch on 64-bit condition code */
+                       if (BRANCH_CHECKS_XCC(opt)) {
+                               switch (condition) {
+                               case BRANCH_EQ:
+                                       M_XBEQ(branchdisp);
+                                       break;
+                               case BRANCH_NE:
+                                       M_XBNE(branchdisp);
+                                       break;
+                               case BRANCH_LT:
+                                       M_XBLT(branchdisp);
+                                       break;
+                               case BRANCH_GE:
+                                       M_XBGE(branchdisp);
+                                       break;
+                               case BRANCH_GT:
+                                       M_XBGT(branchdisp);
+                                       break;
+                               case BRANCH_LE:
+                                       M_XBLE(branchdisp);
+                                       break;
+                               case BRANCH_UGT:
+                                       M_XBUGT(branchdisp);
+                                       break;
+                               case BRANCH_ULT:
+                                       M_XBULT(branchdisp);
+                                       break;
+                               default:
+                                       vm_abort("emit_branch: unknown condition %d", condition);
+                               }
+                               
+                               /* branch delay */
+                               M_NOP;
+                       }
+                       else {
+                               switch (condition) {
+                               case BRANCH_EQ:
+                                       M_BEQ(branchdisp);
+                                       break;
+                               case BRANCH_NE:
+                                       M_BNE(branchdisp);
+                                       break;
+                               case BRANCH_LT:
+                                       M_BLT(branchdisp);
+                                       break;
+                               case BRANCH_GE:
+                                       M_BGE(branchdisp);
+                                       break;
+                               case BRANCH_GT:
+                                       M_BGT(branchdisp);
+                                       break;
+                               case BRANCH_LE:
+                                       M_BLE(branchdisp);
+                                       break;
+                               case BRANCH_UGT:
+                                       M_BUGT(branchdisp);
+                                       break;
+                               case BRANCH_ULT:
+                                       M_BULT(branchdisp);
+                                       break;
+                               default:
+                                       vm_abort("emit_branch: unknown condition %d", condition);
+                               }
+
+                               /* branch delay */
+                               M_NOP;
+                       }
+               }
+       }
+       else {
+               /* branch on register */
+
+               /* check displacement for overflow (16-bit) */
+
+               if ((branchdisp < (s4) 0xffff8000) || (branchdisp > (s4) 0x0007fff)) {
+                       /* if the long-branches flag isn't set yet, do it */
+
+                       if (!CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
+                               log_println("setting error");
+                               cd->flags |= (CODEGENDATA_FLAG_ERROR |
+                                                         CODEGENDATA_FLAG_LONGBRANCHES);
+                       }
+
+                       vm_abort("emit_branch: emit long-branch on reg code");
+               }
+               else {
+                       switch (condition) {
+                       case BRANCH_EQ:
+                               M_BEQZ(reg, branchdisp);
+                               break;
+                       case BRANCH_NE:
+                               M_BNEZ(reg, branchdisp);
+                               break;
+                       case BRANCH_LT:
+                               M_BLTZ(reg, branchdisp);
+                               break;
+                       case BRANCH_GE:
+                               M_BGEZ(reg, branchdisp);
+                               break;
+                       case BRANCH_GT:
+                               M_BGTZ(reg, branchdisp);
+                               break;
+                       case BRANCH_LE:
+                               M_BLEZ(reg, branchdisp);
+                               break;
+                       default:
+                               vm_abort("emit_branch: unknown condition %d", condition);
+                       }
+
+                       /* branch delay */
+                       M_NOP;
+               }
+       }
+}
+
+
+/* emit_bxx_xcc*****************************************************************
+
+   Wrappers for branches on 64-bit condition codes (SPARC specific).
+
+*******************************************************************************/
+
+void emit_beq_xcc(codegendata *cd, basicblock *target)
+{
+       emit_bcc(cd, target, BRANCH_EQ, BRANCH_OPT_XCC);
+}
+
+void emit_bne_xcc(codegendata *cd, basicblock *target)
+{
+       emit_bcc(cd, target, BRANCH_NE, BRANCH_OPT_XCC);
+}
+
+void emit_blt_xcc(codegendata *cd, basicblock *target)
+{
+       emit_bcc(cd, target, BRANCH_LT, BRANCH_OPT_XCC);
+}
+
+void emit_bge_xcc(codegendata *cd, basicblock *target)
+{
+       emit_bcc(cd, target, BRANCH_GE, BRANCH_OPT_XCC);
+}
+
+void emit_bgt_xcc(codegendata *cd, basicblock *target)
+{
+       emit_bcc(cd, target, BRANCH_GT, BRANCH_OPT_XCC);
+}
+
+void emit_ble_xcc(codegendata *cd, basicblock *target)
+{
+       emit_bcc(cd, target, BRANCH_LE, BRANCH_OPT_XCC);
+}
+
+
+
+
 
 /* emit_arithmetic_check *******************************************************
 
@@ -238,9 +449,9 @@ void emit_lconst(codegendata *cd, s4 d, s8 value)
 void emit_arithmetic_check(codegendata *cd, instruction *iptr, s4 reg)
 {
        if (INSTRUCTION_MUST_CHECK(iptr)) {
-               M_BEQZ(reg, 0);
-               codegen_add_arithmeticexception_ref(cd);
+               M_BNEZ(reg, 3);
                M_NOP;
+               M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_ARITHMETIC);
        }
 }
 
@@ -256,12 +467,47 @@ void emit_arrayindexoutofbounds_check(codegendata *cd, instruction *iptr, s4 s1,
        if (INSTRUCTION_MUST_CHECK(iptr)) {
                M_ILD(REG_ITMP3, s1, OFFSET(java_arrayheader, size));
                M_CMP(s2, REG_ITMP3);
-               M_XBUGE(0);
-               codegen_add_arrayindexoutofboundsexception_ref(cd, s2);
+               M_XBULT(3);
                M_NOP;
+               M_ALD_INTERN(s2, REG_ZERO, EXCEPTION_HARDWARE_ARRAYINDEXOUTOFBOUNDS);
        }
 }
 
+
+/* emit_classcast_check ********************************************************
+
+   Emit a ClassCastException check.
+
+*******************************************************************************/
+
+void emit_classcast_check(codegendata *cd, instruction *iptr, s4 condition, s4 reg, s4 s1)
+{
+/* XXX: use 64-bit or 32-bit compares??? */
+
+       if (INSTRUCTION_MUST_CHECK(iptr)) {
+               switch (condition) {
+               case ICMD_IFEQ:
+                       M_BNEZ(reg, 3);
+                       break;
+
+               case ICMD_IFLE:
+                       M_BGTZ(reg, 3);
+                       break;
+
+               case BRANCH_ULT:
+                       M_XBUGE(3);
+                       break;
+
+               default:
+                       vm_abort("emit_classcast_check: unknown condition %d", condition);
+               }
+
+               M_NOP;
+               M_ALD_INTERN(s1, REG_ZERO, EXCEPTION_HARDWARE_CLASSCAST);
+       }
+}
+
+
 /* emit_nullpointer_check ******************************************************
 
    Emit a NullPointerException check.
@@ -271,22 +517,29 @@ void emit_arrayindexoutofbounds_check(codegendata *cd, instruction *iptr, s4 s1,
 void emit_nullpointer_check(codegendata *cd, instruction *iptr, s4 reg)
 {
        if (INSTRUCTION_MUST_CHECK(iptr)) {
-               M_BEQZ(reg, 0);
-               codegen_add_nullpointerexception_ref(cd);
+               M_BNEZ(reg, 3);
                M_NOP;
+               M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_NULLPOINTER);
        }
 }
 
-/* emit_exception_stubs ********************************************************
 
-   Generates the code for the exception stubs.
+/* emit_exception_check ********************************************************
+
+   Emit an Exception check.
 
 *******************************************************************************/
 
-void emit_exception_stubs(jitdata *jd)
+void emit_exception_check(codegendata *cd, instruction *iptr)
 {
+       if (INSTRUCTION_MUST_CHECK(iptr)) {
+               M_BNEZ(REG_RESULT_CALLER, 3);
+               M_NOP;
+               M_ALD_INTERN(REG_RESULT_CALLER, REG_ZERO, EXCEPTION_HARDWARE_EXCEPTION);
+       }
 }
 
+
 /* emit_patcher_stubs **********************************************************
 
    Generates the code for the patcher stubs.
index a2eed3eb726d11596db814508b31de200bef1b05..5f50a10b2df345512a31c81eea9d6732833ba824 100644 (file)
@@ -1,4 +1,4 @@
-/* src/vm/jit/alpha/linux/md.c - machine dependent Alpha Linux functions
+/* src/vm/jit/sparc64/linux/md-os.c - machine dependent SPARC Linux functions
 
    Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Christian Thalinger
-
-   Changes:
-
-   $Id: md-os.c 4357 2006-01-22 23:33:38Z twisti $
+   $Id: md-os.c 7363 2007-02-15 14:57:04Z twisti $
 
 */
 
+
 #include "config.h"
 
 #include <assert.h>
-#include <ucontext.h>
+#include <signal.h>
 
 #include "vm/types.h"
 
+#include "vm/jit/sparc64/codegen.h"
 #include "vm/jit/sparc64/md-abi.h"
 
 #include "vm/exceptions.h"
 #include "vm/jit/stacktrace.h"
 
 
+typedef struct sigcontext sigcontext;
+
+ptrint md_get_reg_from_context(sigcontext *ctx, u4 rindex)
+{
+       ptrint val;     
+       s8     *window;
+       
+       
+       /* return 0 for REG_ZERO */
+       
+       if (rindex == 0)
+               return 0;
+               
+       
+       if (rindex <= 15) {
+               
+               /* register is in global or out range, available in context */
+               
+               val = ctx->sigc_regs.u_regs[rindex];
+       }
+       else {
+               assert(rindex <= 31);
+               
+               /* register is local or in, need to fetch from regsave area on stack */
+               
+               window = ctx->sigc_regs.u_regs[REG_SP] + BIAS;
+               val = window[rindex - 16];
+       }
+       
+       return val;
+}
+       
+       
+
 /* md_signal_handler_sigsegv ***************************************************
 
    NullPointerException signal handler for hardware null pointer
 
 *******************************************************************************/
 
-void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
+void md_signal_handler_sigsegv(int sig, siginfo_t *info , void *_p)
 {
+       /*
        ucontext_t  *_uc;
        mcontext_t  *_mc;
-       u4           instr;
-       ptrint       addr;
+       */
+       sigcontext *ctx;
        u1          *pv;
        u1          *sp;
        u1          *ra;
        u1          *xpc;
+       u4          mcode;
+       s4                 d;
+       s4                 s1;
+       s4                 disp;
+       ptrint             val;
+       ptrint             addr;
+       s4                 type;
+       java_objectheader *e;
 
-       _uc = (ucontext_t *) _p;
-       _mc = &_uc->uc_mcontext;
+       ctx = (sigcontext *) info;
+
+
+       pv  = (u1 *) md_get_reg_from_context(ctx, REG_PV_CALLEE);
+       sp  = (u1 *) md_get_reg_from_context(ctx, REG_SP);
+       ra  = (u1 *) md_get_reg_from_context(ctx, REG_RA_CALLEE);  /* this is correct for leafs */
+       xpc = (u1 *) ctx->sigc_regs.tpc;
+
+       /* get exception-throwing instruction */        
 
-       instr = *((s4 *) (_mc->mc_gregs[MC_PC]));
-       /*addr = _mc->sc_regs[(instr >> 16) & 0x1f];*/
-       addr = 0;
+       mcode = *((u4 *) xpc);
 
-       if (addr == 0) {
-               pv  = (u1 *) _mc->mc_gregs[MC_G2];
-               sp  = (u1 *) _mc->mc_fp;
-               ra  = (u1 *) _mc->mc_i7;       /* this is correct for leafs */
-               xpc = (u1 *) _mc->mc_gregs[MC_PC];
+       d    = M_OP3_GET_RD(mcode);
+       s1   = M_OP3_GET_RS(mcode);
+       disp = M_OP3_GET_IMM(mcode);
 
-               _mc->mc_gregs[MC_G4] =
-                       (ptrint) stacktrace_hardware_nullpointerexception(pv, sp, ra, xpc);
+       /* flush register windows? */
+       
+       val   = md_get_reg_from_context(ctx, d);
+
+       /* check for special-load */
 
-               _mc->mc_gregs[MC_G5] = (ptrint) xpc;
-               _mc->mc_gregs[MC_PC] = (ptrint) asm_handle_exception;
+       if (s1 == REG_ZERO) {
+               /* we use the exception type as load displacement */
 
-       } else {
-               addr += (long) ((instr << 16) >> 16);
+               type = disp;
+       }
+       else {
+               /* This is a normal NPE: addr must be NULL and the NPE-type
+                  define is 0. */
 
-               /*
-               throw_cacao_exception_exit(string_java_lang_InternalError,
-                                                                  "Segmentation fault: 0x%016lx at 0x%016lx\n",
-                                                                  addr, _mc->mc_gregs[MC_PC]);
-                                                                  */
-               assert(0);
+               addr  = md_get_reg_from_context(ctx, s1);
+               type = (s4) addr;
        }
+
+
+       e = exceptions_new_hardware_exception(pv, sp, ra, xpc, type, val);
+
+       /* set registers */
+
+       ctx->sigc_regs.u_regs[REG_ITMP2_XPTR] = (ptrint) e;
+       ctx->sigc_regs.u_regs[REG_ITMP3_XPC]  = (ptrint) xpc;
+       ctx->sigc_regs.tpc                    = (ptrint) asm_handle_exception;
+       ctx->sigc_regs.tnpc                   = (ptrint) asm_handle_exception + 4;
 }
 
 
@@ -153,4 +207,5 @@ void md_icacheflush(u1 *addr, s4 nbytes)
  * c-basic-offset: 4
  * tab-width: 4
  * End:
+ * vim:noexpandtab:sw=4:ts=4:
  */
index 68a5fe11ccb7da06fe572060d615900c9703d44f..a0e6d8f07971180a5d6a679bfd7504f3f194208b 100644 (file)
@@ -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
index ee1bdfe29ab8164ce5231fec7dba95a423282399..9a55c36954fe44cb8973025baba23e975b4091ae 100644 (file)
 #define SHIFT_AND_MASK(instr) \
        ((instr >> 13) & 0x60fc1)
 
+/* NOP is defined as a SETHI instruction with rd and imm. set to zero */
+/* therefore we check if the 22-bit immediate is zero */
 #define IS_SETHI(instr) \
-       ((instr & 0xc1c00000)  == 0x00800000)
+       (((instr & 0xc1c00000)  == 0x01000000) \
+       && ((instr & 0x3fffff) != 0x0))
+       
+#define IS_LDX_IMM(instr) \
+       (((instr >> 13) & 0x60fc1) == 0x602c1)
+       
+#define IS_SUB(instr) \
+       (((instr >> 13) & 0x60fc0) == 0x40100)
 
 inline s2 decode_13bit_imm(u4 instr) {
        s2 imm;
@@ -74,64 +83,6 @@ void md_init(void)
 }
 
 
-/* md_codegen_patch_branch *****************************************************
-
-   Back-patches a branch instruction.
-
-*******************************************************************************/
-
-void md_codegen_patch_branch(codegendata *cd, s4 branchmpc, s4 targetmpc)
-{
-       s4 *mcodeptr;
-       s4  mcode;
-       s4  disp;                           /* branch displacement                */
-
-       /* calculate the patch position */
-
-       mcodeptr = (s4 *) (cd->mcodebase + branchmpc);
-
-       /* get the instruction before the exception point */
-
-       mcode = mcodeptr[-1];
-       
-       /* Calculate the branch displacement.  SPARC displacements regard current
-          PC as base => (branchmpc - 4 */
-       
-       disp = (targetmpc - (branchmpc - 4)) >> 2;
-       
-
-       /* check for BPcc or FBPfcc instruction */
-       if (((mcode >> 16) & 0xc1c0) == 0x0040) {
-       
-               /* check branch displacement (19-bit)*/
-       
-               if ((disp < (s4) 0xfffc0000) || (disp > (s4) 0x003ffff))
-                       vm_abort("branch displacement is out of range: %d > +/-%d", disp, 0x003ffff);
-       
-               /* patch the branch instruction before the mcodeptr */
-       
-               mcodeptr[-1] |= (disp & 0x007ffff);
-       }
-       /* check for BPr instruction */
-       else if (((mcode >> 16) & 0xd1c0) == 0x00c0) {
-
-               /* check branch displacement (16-bit)*/
-       
-               if ((disp < (s4) 0xffff8000) || (disp > (s4) 0x0007fff))
-                       vm_abort("branch displacement is out of range: %d > +/-%d", disp, 0x0007fff);
-                       
-               /* patch the upper 2-bit of the branch displacement */
-               mcodeptr[-1] |= ((disp & 0xc000) << 6);
-                       
-               /* patch the lower 14-bit of the branch displacement */
-               mcodeptr[-1] |= (disp & 0x003fff);
-               
-       }
-       else
-               assert(0);
-}
-
-
 /* md_stacktrace_get_returnaddress *********************************************
 
    Returns the return address of the current stackframe, specified by
@@ -274,67 +225,81 @@ u1 *md_get_method_patch_address(u1 *ra, stackframeinfo *sfi, u1 *mptr)
 {
        u4  mcode, mcode_masked;
        s4  offset;
-       u1 *pa;
+       u1 *pa, *iptr;
 
-       /* go back to the actual load instruction (1 instruction before jump) */
-       /* ra is the address of the jump instruction on SPARC                 */
-       ra -= 1 * 4;
+       /* go back to the location of a possible sethi (3 instruction before jump) */
+       /* note: ra is the address of the jump instruction on SPARC                */
+       iptr = ra - 3 * 4;
 
        /* get first instruction word on current PC */
 
-       mcode = *((u4 *) ra);
-
+       mcode = *((u4 *) iptr);
 
-       /* check if we have 2 instructions (lui) */
+       /* check for sethi instruction */
 
        if (IS_SETHI(mcode)) {
                /* XXX write a regression for this */
-               assert(0);
 
-               /* get displacement of first instruction (lui) */
+               /* get 22-bit displacement of sethi instruction */
 
-               offset = (s4) (mcode << 16);
+               offset = (s4) (mcode & 0x3fffff);
+               offset = offset << 10;
+               
+               /* goto next instruction */
+               iptr += 4;
+               mcode = *((u4 *) iptr);
+               
+               /* make sure it's a sub instruction (pv - big_disp) */
+               assert(IS_SUB(mcode));
+               offset = -offset;
 
-               /* get displacement of second instruction (daddiu) */
+               /* get displacement of load instruction */
 
-               mcode = *((u4 *) (ra + 1 * 4));
+               mcode = *((u4 *) (ra - 1 * 4));
+               assert(IS_LDX_IMM(mcode));
 
-               assert((mcode >> 16) != 0x6739);
+               offset += decode_13bit_imm(mcode);
+               
+               pa = sfi->pv + offset;
 
-               offset += (s2) (mcode & 0x0000ffff);
+               return pa;
+       }
 
-       } else {
 
-               /* shift and maks rd */
+       /* simple (one-instruction) load */
+       iptr = ra - 1 * 4;
+       mcode = *((u4 *) iptr);
 
-               mcode_masked = (mcode >> 13) & 0x060fff;
-               
-               /* get the offset from the instruction */
+       /* shift and mask rd */
 
-               offset = decode_13bit_imm(mcode);
+       mcode_masked = (mcode >> 13) & 0x060fff;
+       
+       /* get the offset from the instruction */
 
-               /* check for call with rs1 == REG_METHODPTR: ldx [g2+x],pv_caller */
+       offset = decode_13bit_imm(mcode);
 
-               if (mcode_masked == 0x0602c5) {
-                       /* in this case we use the passed method pointer */
+       /* check for call with rs1 == REG_METHODPTR: ldx [g2+x],pv_caller */
 
-                       /* return NULL if no mptr was specified (used for replacement) */
+       if (mcode_masked == 0x0602c5) {
+               /* in this case we use the passed method pointer */
 
-                       if (mptr == NULL)
-                               return NULL;
+               /* return NULL if no mptr was specified (used for replacement) */
 
-                       pa = mptr + offset;
+               if (mptr == NULL)
+                       return NULL;
 
-               } else {
-                       /* in the normal case we check for a `ldx [i5+x],pv_caller' instruction */
+               pa = mptr + offset;
 
-                       assert(mcode_masked  == 0x0602fb);
+       } else {
+               /* in the normal case we check for a `ldx [i5+x],pv_caller' instruction */
 
-                       /* and get the final data segment address */
+               assert(mcode_masked  == 0x0602fb);
 
-                       pa = sfi->pv + offset;
-               }
+               /* and get the final data segment address */
+
+               pa = sfi->pv + offset;
        }
+       
 
        return pa;
 }
index 9f76e1ffeab6d065d71f98629b7414643390df66..e9467d192a458a845388223da9c84351e8ff2c54 100644 (file)
@@ -614,12 +614,6 @@ bool patcher_checkcast_interface(u1 *sp)
 
        /* if we show disassembly, we have to skip the nop's */
 
-       if (opt_shownops)
-               ra = ra + PATCHER_CALL_SIZE;
-
-
-       /* if we show disassembly, we have to skip the nop's */
-
        if (opt_shownops)
                ra = ra + PATCHER_CALL_SIZE;
 
@@ -627,15 +621,16 @@ bool patcher_checkcast_interface(u1 *sp)
 
        *((s4 *) (ra + 2 * 4)) |= (s4) (-(c->index) & 0x00001fff);
 
-       *((s4 *) (ra + 5 * 4)) |= (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
-                                                                        c->index * sizeof(methodptr*)) & 0x00001fff);
+       *((s4 *) (ra + (3 + EXCEPTION_CHECK_INSTRUCTIONS) * 4)) |= 
+               (s4) ((OFFSET(vftbl_t, interfacetable[0])
+               - c->index * sizeof(methodptr*)) & 0x00001fff);
 
        /* synchronize instruction cache */
 
        if (opt_shownops)
-               md_icacheflush(ra - 2 * 4, 8 * 4);
+               md_icacheflush(ra - 2 * 4, (6 + EXCEPTION_CHECK_INSTRUCTIONS) * 4);
        else
-               md_icacheflush(ra, 6 * 4);
+               md_icacheflush(ra, (4 + EXCEPTION_CHECK_INSTRUCTIONS) * 4);
 
        return true;
 }
@@ -660,8 +655,6 @@ bool patcher_instanceof_interface(u1 *sp)
        constant_classref *cr;
        classinfo         *c;
 
-       assert(0); /* test this one !!! */
-
        /* get stuff from the stack */
 
        ra = (u1 *)                *((ptrint *) (sp + 5 * 8));
index 0e3e4df10794a726d9d935bb0f2e52eca0545847..c540b0347a9750ada69c30fc45f49339acf535f4 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: stacktrace.c 7343 2007-02-13 02:36:29Z ajordan $
+   $Id: stacktrace.c 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 */
index bad9f4af6d2d29f9d41cb5c2cf4b72ea4ac8e67d..1e4ee26ddcab552e2883adb471a7ddd41d49c7dd 100644 (file)
@@ -26,8 +26,6 @@
 
    Authors: Edwin Steiner
 
-   Changes: 
-
    $Id$
 
 */
                if ((state->iptr->opc == ICMD_INVOKEVIRTUAL)
                        && (mi->flags & (ACC_FINAL | ACC_PRIVATE)))
                {
-                       state->iptr->opc = ICMD_INVOKESPECIAL;
+                       state->iptr->opc         = ICMD_INVOKESPECIAL;
+                       state->iptr->flags.bits |= INS_FLAG_CHECK;
                }
        }
        else {
index 25f8a0747509920a68e3e305d7c78048ea04d30a..4db3d27a94e5e8acd3c951665da094343b096224 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: arch.h 7241 2007-01-27 15:52:01Z twisti $
+   $Id: arch.h 7596 2007-03-28 21:05:53Z twisti $
 
 */
 
 #define CONSECUTIVE_FLOAT_ARGS
 
 
+/* branches *******************************************************************/
+
+#define SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER       1
+#define SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER     0
+#define SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS    0
+#define SUPPORT_BRANCH_CONDITIONAL_UNSIGNED_CONDITIONS      1
+
+
 /* exceptions *****************************************************************/
 
 #define SUPPORT_HARDWARE_DIVIDE_BY_ZERO  1
index 79d21ea83f91f3b5c4750f68248a3b872cac7877..fc54876a26dea67bf85f97c4ef10748705daa8c0 100644 (file)
@@ -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 *****************************
 *                                                                              *
index d6915b2a071462d0edc444cb5058e04edcd649c1..0ddd91b45c04af339de29cb7e4da6f24eb75574f 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: codegen.c 7281 2007-02-03 19:51:36Z twisti $
+   $Id: codegen.c 7596 2007-03-28 21:05:53Z twisti $
 
 */
 
 #include "vmcore/statistics.h"
 
 
-/* codegen *********************************************************************
+/* codegen_emit ****************************************************************
 
    Generates machine code.
 
 *******************************************************************************/
 
-bool codegen(jitdata *jd)
+bool codegen_emit(jitdata *jd)
 {
        methodinfo         *m;
        codeinfo           *code;
@@ -297,8 +297,8 @@ bool codegen(jitdata *jd)
                }
                else {
                        M_TEST(REG_A0);
-                       M_BEQ(0);
-                       codegen_add_nullpointerexception_ref(cd);
+                       M_BNE(8);
+                       M_ALD_MEM(REG_A0, EXCEPTION_HARDWARE_NULLPOINTER);
                }
 
                M_AST(REG_A0, REG_SP, s1 * 8);
@@ -1448,8 +1448,8 @@ bool codegen(jitdata *jd)
                        M_MOV_IMM(1, REG_ITMP1);
                        M_MOV_IMM(-1, REG_ITMP2);
                        emit_ucomiss_reg_reg(cd, s1, s2);
-                       M_CMOVB(REG_ITMP1, d);
-                       M_CMOVA(REG_ITMP2, d);
+                       M_CMOVULT(REG_ITMP1, d);
+                       M_CMOVUGT(REG_ITMP2, d);
                        M_CMOVP(REG_ITMP2, d);                   /* treat unordered as GT */
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1464,8 +1464,8 @@ bool codegen(jitdata *jd)
                        M_MOV_IMM(1, REG_ITMP1);
                        M_MOV_IMM(-1, REG_ITMP2);
                        emit_ucomiss_reg_reg(cd, s1, s2);
-                       M_CMOVB(REG_ITMP1, d);
-                       M_CMOVA(REG_ITMP2, d);
+                       M_CMOVULT(REG_ITMP1, d);
+                       M_CMOVUGT(REG_ITMP2, d);
                        M_CMOVP(REG_ITMP1, d);                   /* treat unordered as LT */
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1480,8 +1480,8 @@ bool codegen(jitdata *jd)
                        M_MOV_IMM(1, REG_ITMP1);
                        M_MOV_IMM(-1, REG_ITMP2);
                        emit_ucomisd_reg_reg(cd, s1, s2);
-                       M_CMOVB(REG_ITMP1, d);
-                       M_CMOVA(REG_ITMP2, d);
+                       M_CMOVULT(REG_ITMP1, d);
+                       M_CMOVUGT(REG_ITMP2, d);
                        M_CMOVP(REG_ITMP2, d);                   /* treat unordered as GT */
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1496,8 +1496,8 @@ bool codegen(jitdata *jd)
                        M_MOV_IMM(1, REG_ITMP1);
                        M_MOV_IMM(-1, REG_ITMP2);
                        emit_ucomisd_reg_reg(cd, s1, s2);
-                       M_CMOVB(REG_ITMP1, d);
-                       M_CMOVA(REG_ITMP2, d);
+                       M_CMOVULT(REG_ITMP1, d);
+                       M_CMOVUGT(REG_ITMP2, d);
                        M_CMOVP(REG_ITMP1, d);                   /* treat unordered as LT */
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1509,7 +1509,7 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
-                       emit_nullpointer_check(cd, iptr, s1);
+                       /* implicit null-pointer check */
                        M_ILD(d, s1, OFFSET(java_arrayheader, size));
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1519,7 +1519,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        emit_movsbq_memindex_reg(cd, OFFSET(java_bytearray, data[0]), s1, s2, 0, d);
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1529,7 +1530,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        emit_movzwq_memindex_reg(cd, OFFSET(java_chararray, data[0]), s1, s2, 1, d);
                        emit_store_dst(jd, iptr, d);
                        break;                  
@@ -1539,7 +1541,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        emit_movswq_memindex_reg(cd, OFFSET(java_shortarray, data[0]), s1, s2, 1, d);
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1549,7 +1552,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        emit_movl_memindex_reg(cd, OFFSET(java_intarray, data[0]), s1, s2, 2, d);
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1559,7 +1563,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        emit_mov_memindex_reg(cd, OFFSET(java_longarray, data[0]), s1, s2, 3, d);
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1569,7 +1574,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        emit_movss_memindex_reg(cd, OFFSET(java_floatarray, data[0]), s1, s2, 2, d);
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1579,7 +1585,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        emit_movsd_memindex_reg(cd, OFFSET(java_doublearray, data[0]), s1, s2, 3, d);
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1589,7 +1596,8 @@ bool codegen(jitdata *jd)
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        emit_mov_memindex_reg(cd, OFFSET(java_objectarray, data[0]), s1, s2, 3, d);
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -1599,7 +1607,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
                        emit_movb_reg_memindex(cd, s3, OFFSET(java_bytearray, data[0]), s1, s2, 0);
                        break;
@@ -1608,7 +1617,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
                        emit_movw_reg_memindex(cd, s3, OFFSET(java_chararray, data[0]), s1, s2, 1);
                        break;
@@ -1617,7 +1627,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
                        emit_movw_reg_memindex(cd, s3, OFFSET(java_shortarray, data[0]), s1, s2, 1);
                        break;
@@ -1626,7 +1637,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
                        emit_movl_reg_memindex(cd, s3, OFFSET(java_intarray, data[0]), s1, s2, 2);
                        break;
@@ -1635,7 +1647,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
                        emit_mov_reg_memindex(cd, s3, OFFSET(java_longarray, data[0]), s1, s2, 3);
                        break;
@@ -1644,7 +1657,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_FTMP3);
                        emit_movss_reg_memindex(cd, s3, OFFSET(java_floatarray, data[0]), s1, s2, 2);
                        break;
@@ -1653,7 +1667,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_FTMP3);
                        emit_movsd_reg_memindex(cd, s3, OFFSET(java_doublearray, data[0]), s1, s2, 3);
                        break;
@@ -1662,16 +1677,15 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        s3 = emit_load_s3(jd, iptr, REG_ITMP3);
 
                        M_MOV(s1, REG_A0);
                        M_MOV(s3, REG_A1);
                        M_MOV_IMM(BUILTIN_canstore, REG_ITMP1);
                        M_CALL(REG_ITMP1);
-                       M_TEST(REG_RESULT);
-                       M_BEQ(0);
-                       codegen_add_arraystoreexception_ref(cd);
+                       emit_exception_check(cd, iptr);
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
@@ -1684,7 +1698,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        emit_movb_imm_memindex(cd, iptr->sx.s23.s3.constval, OFFSET(java_bytearray, data[0]), s1, s2, 0);
                        break;
 
@@ -1692,7 +1707,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        emit_movw_imm_memindex(cd, iptr->sx.s23.s3.constval, OFFSET(java_chararray, data[0]), s1, s2, 1);
                        break;
 
@@ -1700,7 +1716,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        emit_movw_imm_memindex(cd, iptr->sx.s23.s3.constval, OFFSET(java_shortarray, data[0]), s1, s2, 1);
                        break;
 
@@ -1708,7 +1725,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        emit_movl_imm_memindex(cd, iptr->sx.s23.s3.constval, OFFSET(java_intarray, data[0]), s1, s2, 2);
                        break;
 
@@ -1716,11 +1734,13 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
 
                        if (IS_IMM32(iptr->sx.s23.s3.constval)) {
                                emit_mov_imm_memindex(cd, (u4) (iptr->sx.s23.s3.constval & 0x00000000ffffffff), OFFSET(java_longarray, data[0]), s1, s2, 3);
-                       } else {
+                       }
+                       else {
                                emit_movl_imm_memindex(cd, (u4) (iptr->sx.s23.s3.constval & 0x00000000ffffffff), OFFSET(java_longarray, data[0]), s1, s2, 3);
                                emit_movl_imm_memindex(cd, (u4) (iptr->sx.s23.s3.constval >> 32), OFFSET(java_longarray, data[0]) + 4, s1, s2, 3);
                        }
@@ -1730,7 +1750,8 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       emit_array_checks(cd, iptr, s1, s2);
+                       /* implicit null-pointer check */
+                       emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
                        emit_mov_imm_memindex(cd, 0, OFFSET(java_objectarray, data[0]), s1, s2, 3);
                        break;
 
@@ -1741,7 +1762,7 @@ bool codegen(jitdata *jd)
                                uf        = iptr->sx.s23.s3.uf;
                                fieldtype = uf->fieldref->parseddesc.fd->type;
                                disp      = dseg_add_unique_address(cd, NULL);
-                               disp      = -((cd->mcodeptr + 7) - cd->mcodebase) + disp;
+                               disp      = disp + -((cd->mcodeptr + 7) - cd->mcodebase);
 
                                /* must be calculated before codegen_add_patch_ref */
 
@@ -1758,17 +1779,17 @@ bool codegen(jitdata *jd)
                                fi        = iptr->sx.s23.s3.fmiref->p.field;
                                fieldtype = fi->type;
                                disp      = dseg_add_address(cd, &(fi->value));
-                               disp      = -((cd->mcodeptr + 7) - cd->mcodebase) + disp;
+                               disp      = disp + -((cd->mcodeptr + 7) - cd->mcodebase);
 
                                if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
                                        PROFILE_CYCLE_STOP;
 
                                        codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, 0);
 
+                                       PROFILE_CYCLE_START;
+
                                        if (opt_shownops)
                                                disp -= PATCHER_CALL_SIZE;
-
-                                       PROFILE_CYCLE_START;
                                }
                        }
 
@@ -1805,7 +1826,7 @@ bool codegen(jitdata *jd)
                                uf        = iptr->sx.s23.s3.uf;
                                fieldtype = uf->fieldref->parseddesc.fd->type;
                                disp      = dseg_add_unique_address(cd, NULL);
-                               disp      = -((cd->mcodeptr + 7) - cd->mcodebase) + disp;
+                               disp      = disp + -((cd->mcodeptr + 7) - cd->mcodebase);
 
                                /* must be calculated before codegen_add_patch_ref */
 
@@ -1822,17 +1843,17 @@ bool codegen(jitdata *jd)
                                fi        = iptr->sx.s23.s3.fmiref->p.field;
                                fieldtype = fi->type;
                                disp      = dseg_add_address(cd, &(fi->value));
-                               disp      = -((cd->mcodeptr + 7) - cd->mcodebase) + disp;
+                               disp      = disp + -((cd->mcodeptr + 7) - cd->mcodebase);
 
                                if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
                                        PROFILE_CYCLE_STOP;
 
                                        codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, 0);
 
+                                       PROFILE_CYCLE_START;
+
                                        if (opt_shownops)
                                                disp -= PATCHER_CALL_SIZE;
-
-                                       PROFILE_CYCLE_START;
                                }
                        }
 
@@ -1870,14 +1891,13 @@ bool codegen(jitdata *jd)
                                uf        = iptr->sx.s23.s3.uf;
                                fieldtype = uf->fieldref->parseddesc.fd->type;
                                disp      = dseg_add_unique_address(cd, NULL);
-                               disp      = -((cd->mcodeptr + 7) - cd->mcodebase) + disp;
+                               disp      = disp + -((cd->mcodeptr + 7) - cd->mcodebase);
 
                                /* must be calculated before codegen_add_patch_ref */
 
                                if (opt_shownops)
                                        disp -= PATCHER_CALL_SIZE;
 
-
 /*                             PROFILE_CYCLE_STOP; */
 
                                codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp);
@@ -1888,17 +1908,17 @@ bool codegen(jitdata *jd)
                                fi        = iptr->sx.s23.s3.fmiref->p.field;
                                fieldtype = fi->type;
                                disp      = dseg_add_address(cd, &(fi->value));
-                               disp      = -((cd->mcodeptr + 7) - cd->mcodebase) + disp;
+                               disp      = disp + -((cd->mcodeptr + 7) - cd->mcodebase);
 
                                if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
                                        PROFILE_CYCLE_STOP;
 
                                        codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, 0);
 
+                                       PROFILE_CYCLE_START;
+
                                        if (opt_shownops)
                                                disp -= PATCHER_CALL_SIZE;
-
-                                       PROFILE_CYCLE_START;
                                }
                        }
 
@@ -1928,7 +1948,6 @@ bool codegen(jitdata *jd)
                case ICMD_GETFIELD:   /* ...  ==> ..., value                          */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       emit_nullpointer_check(cd, iptr, s1);
 
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
                                uf        = iptr->sx.s23.s3.uf;
@@ -1947,6 +1966,7 @@ bool codegen(jitdata *jd)
                                disp      = fi->offset;
                        }
 
+                       /* implicit null-pointer check */
                        switch (fieldtype) {
                        case TYPE_INT:
                                d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
@@ -1973,7 +1993,6 @@ bool codegen(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_IFTMP); /* REG_IFTMP == REG_ITMP2 */
-                       emit_nullpointer_check(cd, iptr, s1);
 
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
                                uf        = iptr->sx.s23.s3.uf;
@@ -1992,6 +2011,7 @@ bool codegen(jitdata *jd)
                                disp      = fi->offset;
                        }
 
+                       /* implicit null-pointer check */
                        switch (fieldtype) {
                        case TYPE_INT:
                                M_IST32(s2, s1, disp);
@@ -2014,7 +2034,6 @@ bool codegen(jitdata *jd)
                                          /* following NOP)                           */
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       emit_nullpointer_check(cd, iptr, s1);
 
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
                                uf        = iptr->sx.s23.s3.uf;
@@ -2033,6 +2052,7 @@ bool codegen(jitdata *jd)
                                disp      = fi->offset;
                        }
 
+                       /* implicit null-pointer check */
                        switch (fieldtype) {
                        case TYPE_INT:
                        case TYPE_FLT:
@@ -2074,83 +2094,44 @@ bool codegen(jitdata *jd)
                        break;
 
                case ICMD_GOTO:         /* ... ==> ...                                */
-               case ICMD_RET:          /* ... ==> ...                                */
+               case ICMD_RET:
 
-                       M_JMP_IMM(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                       emit_br(cd, iptr->dst.block);
+                       ALIGNCODENOP;
                        break;
 
                case ICMD_JSR:          /* ... ==> ...                                */
 
-                       M_JMP_IMM(0);
-                       codegen_add_branch_ref(cd, iptr->sx.s23.s3.jsrtarget.block);
+                       emit_br(cd, iptr->sx.s23.s3.jsrtarget.block);
+                       ALIGNCODENOP;
                        break;
                        
                case ICMD_IFNULL:       /* ..., value ==> ...                         */
+               case ICMD_IFNONNULL:
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        M_TEST(s1);
-                       M_BEQ(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IFNONNULL:    /* ..., value ==> ...                         */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       M_TEST(s1);
-                       M_BNE(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                       emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IFNULL, BRANCH_OPT_NONE);
                        break;
 
                case ICMD_IFEQ:         /* ..., value ==> ...                         */
+               case ICMD_IFLT:
+               case ICMD_IFLE:
+               case ICMD_IFNE:
+               case ICMD_IFGT:
+               case ICMD_IFGE:
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        M_ICMP_IMM(iptr->sx.val.i, s1);
-                       M_BEQ(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IFLT:         /* ..., value ==> ...                         */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       M_ICMP_IMM(iptr->sx.val.i, s1);
-                       M_BLT(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IFLE:         /* ..., value ==> ...                         */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       M_ICMP_IMM(iptr->sx.val.i, s1);
-                       M_BLE(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IFNE:         /* ..., value ==> ...                         */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       M_ICMP_IMM(iptr->sx.val.i, s1);
-                       M_BNE(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IFGT:         /* ..., value ==> ...                         */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       M_ICMP_IMM(iptr->sx.val.i, s1);
-                       M_BGT(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IFGE:         /* ..., value ==> ...                         */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       M_ICMP_IMM(iptr->sx.val.i, s1);
-                       M_BGE(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                       emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IFEQ, BRANCH_OPT_NONE);
                        break;
 
                case ICMD_IF_LEQ:       /* ..., value ==> ...                         */
+               case ICMD_IF_LNE:
+               case ICMD_IF_LLT:
+               case ICMD_IF_LGE:
+               case ICMD_IF_LGT:
+               case ICMD_IF_LLE:
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        if (IS_IMM32(iptr->sx.val.l))
@@ -2159,183 +2140,42 @@ bool codegen(jitdata *jd)
                                M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
                                M_LCMP(REG_ITMP2, s1);
                        }
-                       M_BEQ(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IF_LLT:       /* ..., value ==> ...                         */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (IS_IMM32(iptr->sx.val.l))
-                               M_LCMP_IMM(iptr->sx.val.l, s1);
-                       else {
-                               M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
-                               M_LCMP(REG_ITMP2, s1);
-                       }
-                       M_BLT(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IF_LLE:       /* ..., value ==> ...                         */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (IS_IMM32(iptr->sx.val.l))
-                               M_LCMP_IMM(iptr->sx.val.l, s1);
-                       else {
-                               M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
-                               M_LCMP(REG_ITMP2, s1);
-                       }
-                       M_BLE(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IF_LNE:       /* ..., value ==> ...                         */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (IS_IMM32(iptr->sx.val.l))
-                               M_LCMP_IMM(iptr->sx.val.l, s1);
-                       else {
-                               M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
-                               M_LCMP(REG_ITMP2, s1);
-                       }
-                       M_BNE(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IF_LGT:       /* ..., value ==> ...                         */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (IS_IMM32(iptr->sx.val.l))
-                               M_LCMP_IMM(iptr->sx.val.l, s1);
-                       else {
-                               M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
-                               M_LCMP(REG_ITMP2, s1);
-                       }
-                       M_BGT(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IF_LGE:       /* ..., value ==> ...                         */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       if (IS_IMM32(iptr->sx.val.l))
-                               M_LCMP_IMM(iptr->sx.val.l, s1);
-                       else {
-                               M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
-                               M_LCMP(REG_ITMP2, s1);
-                       }
-                       M_BGE(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                       emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IF_LEQ, BRANCH_OPT_NONE);
                        break;
 
                case ICMD_IF_ICMPEQ:    /* ..., value, value ==> ...                  */
+               case ICMD_IF_ICMPNE:
+               case ICMD_IF_ICMPLT:
+               case ICMD_IF_ICMPGE:
+               case ICMD_IF_ICMPGT:
+               case ICMD_IF_ICMPLE:
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_ICMP(s2, s1);
-                       M_BEQ(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                       emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IF_ICMPEQ, BRANCH_OPT_NONE);
                        break;
 
-               case ICMD_IF_LCMPEQ:    /* ..., value, value ==> ...                  */
-               case ICMD_IF_ACMPEQ:    /* op1 = target JavaVM pc                     */
+               case ICMD_IF_ACMPEQ:    /* ..., value, value ==> ...                  */
+               case ICMD_IF_ACMPNE:
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_LCMP(s2, s1);
-                       M_BEQ(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                       emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IF_ACMPEQ, BRANCH_OPT_NONE);
                        break;
 
-               case ICMD_IF_ICMPNE:    /* ..., value, value ==> ...                  */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       M_ICMP(s2, s1);
-                       M_BNE(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IF_LCMPNE:    /* ..., value, value ==> ...                  */
-               case ICMD_IF_ACMPNE:    /* op1 = target JavaVM pc                     */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       M_LCMP(s2, s1);
-                       M_BNE(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IF_ICMPLT:    /* ..., value, value ==> ...                  */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       M_ICMP(s2, s1);
-                       M_BLT(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IF_LCMPLT:    /* ..., value, value ==> ...                  */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       M_LCMP(s2, s1);
-                       M_BLT(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IF_ICMPGT:    /* ..., value, value ==> ...                  */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       M_ICMP(s2, s1);
-                       M_BGT(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IF_LCMPGT:    /* ..., value, value ==> ...                  */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       M_LCMP(s2, s1);
-                       M_BGT(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IF_ICMPLE:    /* ..., value, value ==> ...                  */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       M_ICMP(s2, s1);
-                       M_BLE(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IF_LCMPLE:    /* ..., value, value ==> ...                  */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       M_LCMP(s2, s1);
-                       M_BLE(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IF_ICMPGE:    /* ..., value, value ==> ...                  */
-
-                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
-                       M_ICMP(s2, s1);
-                       M_BGE(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
-                       break;
-
-               case ICMD_IF_LCMPGE:    /* ..., value, value ==> ...                  */
+               case ICMD_IF_LCMPEQ:    /* ..., value, value ==> ...                  */
+               case ICMD_IF_LCMPNE:
+               case ICMD_IF_LCMPLT:
+               case ICMD_IF_LCMPGE:
+               case ICMD_IF_LCMPGT:
+               case ICMD_IF_LCMPLE:
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2(jd, iptr, REG_ITMP2);
                        M_LCMP(s2, s1);
-                       M_BGE(0);
-                       codegen_add_branch_ref(cd, iptr->dst.block);
+                       emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IF_LCMPEQ, BRANCH_OPT_NONE);
                        break;
 
                case ICMD_IRETURN:      /* ..., retvalue ==> ...                      */
@@ -2466,10 +2306,9 @@ nowperformreturn:
                                i = i - l + 1;
 
                 /* range check */
-                               M_ICMP_IMM(i - 1, REG_ITMP1);
-                               M_BA(0);
 
-                               codegen_add_branch_ref(cd, table[0].block); /* default target */
+                               M_ICMP_IMM(i - 1, REG_ITMP1);
+                               emit_bugt(cd, table[0].block);
 
                                /* build jump table top down and use address of lowest entry */
 
@@ -2505,14 +2344,12 @@ nowperformreturn:
 
                                while (--i >= 0) {
                                        M_ICMP_IMM(lookup->value, s1);
-                                       M_BEQ(0);
-                                       codegen_add_branch_ref(cd, lookup->target.block);
+                                       emit_beq(cd, lookup->target.block);
                                        lookup++;
                                }
 
-                               M_JMP_IMM(0);
-                       
-                               codegen_add_branch_ref(cd, iptr->sx.s23.s3.lookupdefault.block);
+                               emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
+                               ALIGNCODENOP;
                        }
                        break;
 
@@ -2593,24 +2430,17 @@ gen_method:
                                M_MOV_IMM(bte->fp, REG_ITMP1);
                                M_CALL(REG_ITMP1);
 
-                               if (INSTRUCTION_MUST_CHECK(iptr)) {
-                                       M_TEST(REG_RESULT);
-                                       M_BEQ(0);
-                                       codegen_add_fillinstacktrace_ref(cd);
-                               }
+                               emit_exception_check(cd, iptr);
                                break;
 
                        case ICMD_INVOKESPECIAL:
-                               M_TEST(REG_A0);
-                               M_BEQ(0);
-                               codegen_add_nullpointerexception_ref(cd);
-
+                               emit_nullpointer_check(cd, iptr, REG_A0);
                                /* fall through */
 
                        case ICMD_INVOKESTATIC:
                                if (lm == NULL) {
                                        disp = dseg_add_unique_address(cd, NULL);
-                                       disp = -((cd->mcodeptr + 7) - cd->mcodebase) + disp;
+                                       disp = disp + -((cd->mcodeptr + 7) - cd->mcodebase);
 
                                        /* must be calculated before codegen_add_patch_ref */
 
@@ -2624,7 +2454,7 @@ gen_method:
                                }
                                else {
                                        disp = dseg_add_functionptr(cd, lm->stubroutine);
-                                       disp = -((cd->mcodeptr + 7) - cd->mcodebase) + disp;
+                                       disp = disp + -((cd->mcodeptr + 7) - cd->mcodebase);
 
 /*                                     a = (ptrint) lm->stubroutine; */
                                }
@@ -2635,26 +2465,23 @@ gen_method:
                                break;
 
                        case ICMD_INVOKEVIRTUAL:
-                               emit_nullpointer_check(cd, iptr, REG_A0);
-
                                if (lm == NULL) {
                                        codegen_add_patch_ref(cd, PATCHER_invokevirtual, um, 0);
 
                                        s1 = 0;
                                }
-                               else
+                               else {
                                        s1 = OFFSET(vftbl_t, table[0]) +
                                                sizeof(methodptr) * lm->vftblindex;
+                               }
 
-                               M_ALD(REG_METHODPTR, REG_A0,
-                                         OFFSET(java_objectheader, vftbl));
+                               /* implicit null-pointer check */
+                               M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_objectheader, vftbl));
                                M_ALD32(REG_ITMP3, REG_METHODPTR, s1);
                                M_CALL(REG_ITMP3);
                                break;
 
                        case ICMD_INVOKEINTERFACE:
-                               emit_nullpointer_check(cd, iptr, REG_A0);
-
                                if (lm == NULL) {
                                        codegen_add_patch_ref(cd, PATCHER_invokeinterface, um, 0);
 
@@ -2668,8 +2495,8 @@ gen_method:
                                        s2 = sizeof(methodptr) * (lm - lm->class->methods);
                                }
 
-                               M_ALD(REG_METHODPTR, REG_A0,
-                                         OFFSET(java_objectheader, vftbl));
+                               /* implicit null-pointer check */
+                               M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_objectheader, vftbl));
                                M_ALD32(REG_METHODPTR, REG_METHODPTR, s1);
                                M_ALD32(REG_ITMP3, REG_METHODPTR, s2);
                                M_CALL(REG_ITMP3);
@@ -2686,39 +2513,29 @@ gen_method:
 
                        /* store return value */
 
-                       d = md->returntype.type;
-
-                       if (d != TYPE_VOID) {
-                               if (IS_INT_LNG_TYPE(d)) {
-                                       s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
-                                       M_INTMOVE(REG_RESULT, s1);
-                               }
-                               else {
-                                       s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
-                                       M_FLTMOVE(REG_FRESULT, s1);
-                               }
+                       switch (md->returntype.type) {
+                       case TYPE_INT:
+                       case TYPE_LNG:
+                       case TYPE_ADR:
+                               s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
+                               M_INTMOVE(REG_RESULT, s1);
+                               emit_store_dst(jd, iptr, s1);
+                               break;
+                       case TYPE_FLT:
+                       case TYPE_DBL:
+                               s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
+                               M_FLTMOVE(REG_FRESULT, s1);
                                emit_store_dst(jd, iptr, s1);
+                               break;
+                       default:
+                               /* TYPE_VOID */
+                               break;
                        }
                        break;
 
 
                case ICMD_CHECKCAST:  /* ..., objectref ==> ..., objectref            */
 
-                                     /* val.a: (classinfo *) superclass              */
-
-                       /*  superclass is an interface:
-                        *      
-                        *  OK if ((sub == NULL) ||
-                        *         (sub->vftbl->interfacetablelength > super->index) &&
-                        *         (sub->vftbl->interfacetable[-super->index] != NULL));
-                        *      
-                        *  superclass is a class:
-                        *      
-                        *  OK if ((sub == NULL) || (0
-                        *         <= (sub->vftbl->baseval - super->vftbl->baseval) <=
-                        *         super->vftbl->diffval));
-                        */
-
                        if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
                                /* object type cast-check */
 
@@ -2727,12 +2544,12 @@ gen_method:
                                s4         superindex;
 
                                if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
-                                       super = NULL;
+                                       super      = NULL;
                                        superindex = 0;
                                        supervftbl = NULL;
                                }
                                else {
-                                       super = iptr->sx.s23.s3.c.cls;
+                                       super      = iptr->sx.s23.s3.c.cls;
                                        superindex = super->index;
                                        supervftbl = super->vftbl;
                                }
@@ -2742,57 +2559,18 @@ gen_method:
 #endif
                                s1 = emit_load_s1(jd, iptr, REG_ITMP1);
 
-                               /* calculate interface checkcast code size */
-
-                               s2 = 3; /* mov_membase_reg */
-                               CALCOFFSETBYTES(s2, s1, OFFSET(java_objectheader, vftbl));
-
-                               s2 += 3 + 4 /* movl_membase32_reg */ + 3 + 4 /* sub imm32 */ +
-                                       3 /* test */ + 6 /* jcc */ + 3 + 4 /* mov_membase32_reg */ +
-                                       3 /* test */ + 6 /* jcc */;
-
-                               if (super == NULL)
-                                       s2 += (opt_shownops ? 5 : 0);
-
-                               /* calculate class checkcast code size */
-
-                               s3 = 3; /* mov_membase_reg */
-                               CALCOFFSETBYTES(s3, s1, OFFSET(java_objectheader, vftbl));
-                               s3 += 10 /* mov_imm_reg */ + 3 + 4 /* movl_membase32_reg */;
-
-#if 0
-                               if (s1 != REG_ITMP1) {
-                                       a += 3;    /* movl_membase_reg - only if REG_ITMP3 == R11 */
-                                       CALCOFFSETBYTES(a, REG_ITMP3, OFFSET(vftbl_t, baseval));
-                                       a += 3;    /* movl_membase_reg - only if REG_ITMP3 == R11 */
-                                       CALCOFFSETBYTES(a, REG_ITMP3, OFFSET(vftbl_t, diffval));
-                                       a += 3;    /* sub */
-                               
-                               } else
-#endif
-                                       {
-                                               s3 += 3 + 4 /* movl_membase32_reg */ + 3 /* sub */ +
-                                                       10 /* mov_imm_reg */ + 3 /* movl_membase_reg */;
-                                               CALCOFFSETBYTES(s3, REG_ITMP3, OFFSET(vftbl_t, diffval));
-                                       }
-                       
-                               s3 += 3 /* cmp */ + 6 /* jcc */;
-
-                               if (super == NULL)
-                                       s3 += (opt_shownops ? 5 : 0);
-
                                /* if class is not resolved, check which code to call */
 
                                if (super == NULL) {
                                        M_TEST(s1);
-                                       M_BEQ(6 + (opt_shownops ? 5 : 0) + 7 + 6 + s2 + 5 + s3);
+                                       emit_label_beq(cd, BRANCH_LABEL_1);
 
                                        codegen_add_patch_ref(cd, PATCHER_checkcast_instanceof_flags,
                                                                                  iptr->sx.s23.s3.c.ref, 0);
 
                                        M_IMOV_IMM(0, REG_ITMP2);                 /* super->flags */
                                        M_IAND_IMM(ACC_INTERFACE, REG_ITMP2);
-                                       M_BEQ(s2 + 5);
+                                       emit_label_beq(cd, BRANCH_LABEL_2);
                                }
 
                                /* interface checkcast code */
@@ -2800,44 +2578,43 @@ gen_method:
                                if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
                                        if (super != NULL) {
                                                M_TEST(s1);
-                                               M_BEQ(s2);
+                                               emit_label_beq(cd, BRANCH_LABEL_3);
                                        }
 
                                        M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
 
                                        if (super == NULL) {
-                                               codegen_add_patch_ref(cd,
-                                                                                         PATCHER_checkcast_instanceof_interface,
+                                               codegen_add_patch_ref(cd, PATCHER_checkcast_interface,
                                                                                          iptr->sx.s23.s3.c.ref,
                                                                                          0);
                                        }
 
-                                       emit_movl_membase32_reg(cd, REG_ITMP2,
-                                                                                         OFFSET(vftbl_t, interfacetablelength),
-                                                                                         REG_ITMP3);
-                                       /* XXX TWISTI: should this be int arithmetic? */
-                                       M_LSUB_IMM32(superindex, REG_ITMP3);
-                                       M_TEST(REG_ITMP3);
-                                       M_BLE(0);
-                                       codegen_add_classcastexception_ref(cd, s1);
-                                       emit_mov_membase32_reg(cd, REG_ITMP2,
-                                                                                        OFFSET(vftbl_t, interfacetable[0]) -
-                                                                                        superindex * sizeof(methodptr*),
-                                                                                        REG_ITMP3);
+                                       M_ILD32(REG_ITMP3,
+                                                       REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
+                                       M_ICMP_IMM32(superindex, REG_ITMP3);
+                                       emit_classcast_check(cd, iptr, BRANCH_LE, REG_ITMP3, s1);
+
+                                       M_ALD32(REG_ITMP3, REG_ITMP2, 
+                                                       OFFSET(vftbl_t, interfacetable[0]) -
+                                                       superindex * sizeof(methodptr*));
                                        M_TEST(REG_ITMP3);
-                                       M_BEQ(0);
-                                       codegen_add_classcastexception_ref(cd, s1);
+                                       emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ITMP3, s1);
 
                                        if (super == NULL)
-                                               M_JMP_IMM(s3);
+                                               emit_label_br(cd, BRANCH_LABEL_4);
+                                       else
+                                               emit_label(cd, BRANCH_LABEL_3);
                                }
 
                                /* class checkcast code */
 
                                if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
-                                       if (super != NULL) {
+                                       if (super == NULL) {
+                                               emit_label(cd, BRANCH_LABEL_2);
+                                       }
+                                       else {
                                                M_TEST(s1);
-                                               M_BEQ(s3);
+                                               emit_label_beq(cd, BRANCH_LABEL_5);
                                        }
 
                                        M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
@@ -2852,9 +2629,8 @@ gen_method:
 #if defined(ENABLE_THREADS)
                                        codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
 #endif
-                                       emit_movl_membase32_reg(cd, REG_ITMP2,
-                                                                                         OFFSET(vftbl_t, baseval),
-                                                                                         REG_ITMP2);
+                                       M_ILD32(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
+
                                        /*                                      if (s1 != REG_ITMP1) { */
                                        /*                                              emit_movl_membase_reg(cd, REG_ITMP3, */
                                        /*                                                                                              OFFSET(vftbl_t, baseval), */
@@ -2868,19 +2644,25 @@ gen_method:
                                        /*                                              emit_alu_reg_reg(cd, ALU_SUB, REG_ITMP1, REG_ITMP2); */
 
                                        /*                                      } else { */
-                                       emit_movl_membase32_reg(cd, REG_ITMP3,
-                                                                                         OFFSET(vftbl_t, baseval),
-                                                                                         REG_ITMP3);
-                                       M_LSUB(REG_ITMP3, REG_ITMP2);
+
+                                       M_ILD32(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
+                                       M_ISUB(REG_ITMP3, REG_ITMP2);
                                        M_MOV_IMM(supervftbl, REG_ITMP3);
                                        M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
                                        /*                                      } */
 #if defined(ENABLE_THREADS)
                                        codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
 #endif
-                                       M_LCMP(REG_ITMP3, REG_ITMP2);
-                                       M_BA(0);         /* (u) REG_ITMP1 > (u) REG_ITMP2 -> jump */
-                                       codegen_add_classcastexception_ref(cd, s1);
+                                       M_ICMP(REG_ITMP3, REG_ITMP2);
+                                       emit_classcast_check(cd, iptr, BRANCH_UGT, REG_ITMP3, s1);
+
+                                       if (super != NULL)
+                                               emit_label(cd, BRANCH_LABEL_5);
+                               }
+
+                               if (super == NULL) {
+                                       emit_label(cd, BRANCH_LABEL_1);
+                                       emit_label(cd, BRANCH_LABEL_4);
                                }
 
                                d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
@@ -2903,8 +2685,7 @@ gen_method:
                                /* s1 may have been destroyed over the function call */
                                s1 = emit_load_s1(jd, iptr, REG_ITMP2);
                                M_TEST(REG_RESULT);
-                               M_BEQ(0);
-                               codegen_add_classcastexception_ref(cd, s1);
+                               emit_classcast_check(cd, iptr, BRANCH_EQ, REG_RESULT, s1);
 
                                d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
                        }
@@ -2915,33 +2696,18 @@ gen_method:
 
                case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult            */
 
-                                     /* val.a: (classinfo *) superclass              */
-
-                       /*  superclass is an interface:
-                        *      
-                        *  return (sub != NULL) &&
-                        *         (sub->vftbl->interfacetablelength > super->index) &&
-                        *         (sub->vftbl->interfacetable[-super->index] != NULL);
-                        *      
-                        *  superclass is a class:
-                        *      
-                        *  return ((sub != NULL) && (0
-                        *          <= (sub->vftbl->baseval - super->vftbl->baseval) <=
-                        *          super->vftbl->diffvall));
-                        */
-
                        {
                        classinfo *super;
                        vftbl_t   *supervftbl;
                        s4         superindex;
 
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
-                               super = NULL;
+                               super      = NULL;
                                superindex = 0;
                                supervftbl = NULL;
 
                        } else {
-                               super = iptr->sx.s23.s3.c.cls;
+                               super      = iptr->sx.s23.s3.c.cls;
                                superindex = super->index;
                                supervftbl = super->vftbl;
                        }
@@ -2952,131 +2718,108 @@ gen_method:
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+
                        if (s1 == d) {
                                M_INTMOVE(s1, REG_ITMP1);
                                s1 = REG_ITMP1;
                        }
 
-                       /* calculate interface instanceof code size */
-
-                       s2 = 3; /* mov_membase_reg */
-                       CALCOFFSETBYTES(s2, s1, OFFSET(java_objectheader, vftbl));
-                       s2 += 3 + 4 /* movl_membase32_reg */ + 3 + 4 /* sub_imm32 */ +
-                               3 /* test */ + 6 /* jcc */ + 3 + 4 /* mov_membase32_reg */ +
-                               3 /* test */ + 4 /* setcc */;
-
-                       if (!super)
-                               s2 += (opt_shownops ? 5 : 0);
-
-                       /* calculate class instanceof code size */
-                       
-                       s3 = 3; /* mov_membase_reg */
-                       CALCOFFSETBYTES(s3, s1, OFFSET(java_objectheader, vftbl));
-                       s3 += 10; /* mov_imm_reg */
-                       s3 += 2; /* movl_membase_reg - only if REG_ITMP1 == RAX */
-                       CALCOFFSETBYTES(s3, REG_ITMP1, OFFSET(vftbl_t, baseval));
-                       s3 += 3; /* movl_membase_reg - only if REG_ITMP2 == R10 */
-                       CALCOFFSETBYTES(s3, REG_ITMP2, OFFSET(vftbl_t, baseval));
-                       s3 += 3; /* movl_membase_reg - only if REG_ITMP2 == R10 */
-                       CALCOFFSETBYTES(s3, REG_ITMP2, OFFSET(vftbl_t, diffval));
-                       s3 += 3 /* sub */ + 3 /* xor */ + 3 /* cmp */ + 4 /* setcc */;
-
-                       if (super == NULL)
-                               s3 += (opt_shownops ? 5 : 0);
-
-                       emit_alu_reg_reg(cd, ALU_XOR, d, d);
+                       M_CLR(d);
 
                        /* if class is not resolved, check which code to call */
 
                        if (super == NULL) {
-                               emit_test_reg_reg(cd, s1, s1);
-                               emit_jcc(cd, CC_Z, (6 + (opt_shownops ? 5 : 0) +
-                                                                                        7 + 6 + s2 + 5 + s3));
+                               M_TEST(s1);
+                               emit_label_beq(cd, BRANCH_LABEL_1);
 
                                codegen_add_patch_ref(cd, PATCHER_checkcast_instanceof_flags,
                                                                          iptr->sx.s23.s3.c.ref, 0);
 
-                               emit_movl_imm_reg(cd, 0, REG_ITMP3); /* super->flags */
-                               emit_alul_imm_reg(cd, ALU_AND, ACC_INTERFACE, REG_ITMP3);
-                               emit_jcc(cd, CC_Z, s2 + 5);
+                               M_IMOV_IMM(0, REG_ITMP3);                     /* super->flags */
+                               M_IAND_IMM(ACC_INTERFACE, REG_ITMP3);
+                               emit_label_beq(cd, BRANCH_LABEL_2);
                        }
 
                        /* interface instanceof code */
 
                        if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
                                if (super != NULL) {
-                                       emit_test_reg_reg(cd, s1, s1);
-                                       emit_jcc(cd, CC_Z, s2);
+                                       M_TEST(s1);
+                                       emit_label_beq(cd, BRANCH_LABEL_3);
                                }
 
-                               emit_mov_membase_reg(cd, s1,
-                                                                        OFFSET(java_objectheader, vftbl),
-                                                                        REG_ITMP1);
+                               M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
 
                                if (super == NULL) {
-                                       codegen_add_patch_ref(cd,
-                                                                                 PATCHER_checkcast_instanceof_interface,
+                                       codegen_add_patch_ref(cd, PATCHER_instanceof_interface,
                                                                                  iptr->sx.s23.s3.c.ref, 0);
                                }
 
-                               emit_movl_membase32_reg(cd, REG_ITMP1,
-                                                                                 OFFSET(vftbl_t, interfacetablelength),
-                                                                                 REG_ITMP3);
-                               emit_alu_imm32_reg(cd, ALU_SUB, superindex, REG_ITMP3);
-                               emit_test_reg_reg(cd, REG_ITMP3, REG_ITMP3);
+                               M_ILD32(REG_ITMP3,
+                                               REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
+                               M_ICMP_IMM32(superindex, REG_ITMP3);
 
                                a = 3 + 4 /* mov_membase32_reg */ + 3 /* test */ + 4 /* setcc */;
 
-                               emit_jcc(cd, CC_LE, a);
-                               emit_mov_membase32_reg(cd, REG_ITMP1,
-                                                                                OFFSET(vftbl_t, interfacetable[0]) -
-                                                                                superindex * sizeof(methodptr*),
-                                                                                REG_ITMP1);
-                               emit_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
-                               emit_setcc_reg(cd, CC_NE, d);
+                               M_BLE(a);
+                               M_ALD32(REG_ITMP1, REG_ITMP1,
+                                               OFFSET(vftbl_t, interfacetable[0]) -
+                                               superindex * sizeof(methodptr*));
+                               M_TEST(REG_ITMP1);
+                               M_SETNE(d);
 
-                               if (!super)
-                                       emit_jmp_imm(cd, s3);
+                               if (super == NULL)
+                                       emit_label_br(cd, BRANCH_LABEL_4);
+                               else
+                                       emit_label(cd, BRANCH_LABEL_3);
                        }
 
                        /* class instanceof code */
 
                        if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
-                               if (super != NULL) {
-                                       emit_test_reg_reg(cd, s1, s1);
-                                       emit_jcc(cd, CC_E, s3);
+                               if (super == NULL) {
+                                       emit_label(cd, BRANCH_LABEL_2);
+                               }
+                               else {
+                                       M_TEST(s1);
+                                       emit_label_beq(cd, BRANCH_LABEL_5);
                                }
 
-                               emit_mov_membase_reg(cd, s1,
-                                                                          OFFSET(java_objectheader, vftbl),
-                                                                          REG_ITMP1);
+                               M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
 
                                if (super == NULL) {
                                        codegen_add_patch_ref(cd, PATCHER_instanceof_class,
                                                                                  iptr->sx.s23.s3.c.ref, 0);
                                }
 
-                               emit_mov_imm_reg(cd, (ptrint) supervftbl, REG_ITMP2);
+                               M_MOV_IMM(supervftbl, REG_ITMP2);
+
 #if defined(ENABLE_THREADS)
                                codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
 #endif
-                               emit_movl_membase_reg(cd, REG_ITMP1,
-                                                                               OFFSET(vftbl_t, baseval),
-                                                                               REG_ITMP1);
-                               emit_movl_membase_reg(cd, REG_ITMP2,
-                                                                               OFFSET(vftbl_t, diffval),
-                                                                               REG_ITMP3);
-                               emit_movl_membase_reg(cd, REG_ITMP2,
-                                                                               OFFSET(vftbl_t, baseval),
-                                                                               REG_ITMP2);
+
+                               M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
+                               M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, diffval));
+                               M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
+
 #if defined(ENABLE_THREADS)
                                codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
 #endif
-                               emit_alu_reg_reg(cd, ALU_SUB, REG_ITMP2, REG_ITMP1);
-                               emit_alu_reg_reg(cd, ALU_XOR, d, d); /* may be REG_ITMP2 */
-                               emit_alu_reg_reg(cd, ALU_CMP, REG_ITMP3, REG_ITMP1);
-                               emit_setcc_reg(cd, CC_BE, d);
+
+                               M_ISUB(REG_ITMP2, REG_ITMP1);
+                               M_CLR(d); /* may be REG_ITMP2 */
+                               M_ICMP(REG_ITMP3, REG_ITMP1);
+                               M_SETULE(d);
+
+                               if (super != NULL)
+                                       emit_label(cd, BRANCH_LABEL_5);
+                       }
+
+                       if (super == NULL) {
+                               emit_label(cd, BRANCH_LABEL_1);
+                               emit_label(cd, BRANCH_LABEL_4);
                        }
+
                        emit_store_dst(jd, iptr, d);
                        }
                        break;
@@ -3123,9 +2866,7 @@ gen_method:
 
                        /* check for exception before result assignment */
 
-                       M_TEST(REG_RESULT);
-                       M_BEQ(0);
-                       codegen_add_fillinstacktrace_ref(cd);
+                       emit_exception_check(cd, iptr);
 
                        s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
                        M_INTMOVE(REG_RESULT, s1);
@@ -3160,12 +2901,9 @@ gen_method:
 
        /* generate stubs */
 
-       emit_exception_stubs(jd);
        emit_patcher_stubs(jd);
        REPLACEMENT_EMIT_STUBS(jd);
 
-       codegen_finish(jd);
-
        /* everything's ok */
 
        return true;
index 8b9e96a310382e7b19ea96bb5001aa2a727cf7eb..2e81403807bfd93b24d52c01424ef3643201efb2 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: codegen.h 7281 2007-02-03 19:51:36Z twisti $
+   $Id: codegen.h 7596 2007-03-28 21:05:53Z twisti $
 
 */
 
 
 /* additional functions and macros to generate code ***************************/
 
-#define CALCOFFSETBYTES(var, reg, val) \
-    if ((s4) (val) < -128 || (s4) (val) > 127) (var) += 4; \
-    else if ((s4) (val) != 0) (var) += 1; \
-    else if ((reg) == RBP || (reg) == RSP || (reg) == R12 || (reg) == R13) (var) += 1;
-
-
-#define CALCIMMEDIATEBYTES(var, val) \
-    if ((s4) (val) < -128 || (s4) (val) > 127) (var) += 4; \
-    else (var) += 1;
-
-
 /* MCODECHECK(icnt) */
 
 #define MCODECHECK(icnt) \
 
 
 #define ALIGNCODENOP \
-    if ((s4) (((ptrint) cd->mcodeptr) & 7)) { \
-        M_NOP; \
-    }
+    do { \
+        for (s1 = 0; s1 < (s4) (((ptrint) cd->mcodeptr) & 7); s1++) \
+            M_NOP; \
+    } while (0)
 
 
 /* M_INTMOVE:
 
 /* branch defines *************************************************************/
 
+#define BRANCH_UNCONDITIONAL_SIZE    5  /* size in bytes of a branch          */
+#define BRANCH_CONDITIONAL_SIZE      6  /* size in bytes of a branch          */
+
 #define BRANCH_NOPS \
     do { \
         M_NOP; \
         M_NOP; \
         M_NOP; \
         M_NOP; \
+        M_NOP; \
     } while (0)
 
 
 #define M_ALD(a,b,disp)         M_LLD(a,b,disp)
 #define M_ALD32(a,b,disp)       M_LLD32(a,b,disp)
 
+#define M_ALD_MEM(a,disp)       emit_mov_mem_reg(cd, (disp), (a))
+
+#define M_ALD_MEM_GET_OPC(p)     (  *(        (p) + 1))
+#define M_ALD_MEM_GET_MOD(p)     (((*(        (p) + 2)) >> 6) & 0x03)
+#define M_ALD_MEM_GET_REG(p)    ((((*(        (p) + 2)) >> 3) & 0x07) + (((*(p) >> 2) & 0x01) << 3))
+#define M_ALD_MEM_GET_RM(p)      (((*(        (p) + 2))     ) & 0x07)
+#define M_ALD_MEM_GET_DISP(p)    (  *((u4 *) ((p) + 4)))
+
 #define M_AST(a,b,c)            M_LST(a,b,c)
 #define M_AST_IMM32(a,b,c)      M_LST_IMM32(a,b,c)
 
 #define M_AADD_IMM(a,b)         M_LADD_IMM(a,b)
 #define M_ASUB_IMM(a,b)         M_LSUB_IMM(a,b)
 
+#define M_ISUB_IMM32(a,b)       emit_alul_imm32_reg(cd, ALU_SUB, (a), (b))
+
 #define M_LADD_IMM32(a,b)       emit_alu_imm32_reg(cd, ALU_ADD, (a), (b))
-#define M_AADD_IMM32(a,b)       M_LADD_IMM32(a,b)
 #define M_LSUB_IMM32(a,b)       emit_alu_imm32_reg(cd, ALU_SUB, (a), (b))
 
+#define M_AADD_IMM32(a,b)       M_LADD_IMM32(a,b)
+
 #define M_ILEA(a,b,c)           emit_leal_membase_reg(cd, (a), (b), (c))
 #define M_LLEA(a,b,c)           emit_lea_membase_reg(cd, (a), (b), (c))
 #define M_ALEA(a,b,c)           M_LLEA(a,b,c)
 
 #define M_ICMP(a,b)             emit_alul_reg_reg(cd, ALU_CMP, (a), (b))
 #define M_ICMP_IMM(a,b)         emit_alul_imm_reg(cd, ALU_CMP, (a), (b))
+#define M_ICMP_IMM32(a,b)       emit_alul_imm32_reg(cd, ALU_CMP, (a), (b))
 #define M_ICMP_IMM_MEMBASE(a,b,c) emit_alul_imm_membase(cd, ALU_CMP, (a), (b), (c))
 #define M_ICMP_MEMBASE(a,b,c)   emit_alul_membase_reg(cd, ALU_CMP, (a), (b), (c))
 
 #define M_BLE(disp)             emit_jcc(cd, CC_LE, (disp))
 #define M_BGE(disp)             emit_jcc(cd, CC_GE, (disp))
 #define M_BGT(disp)             emit_jcc(cd, CC_G, (disp))
-#define M_BAE(disp)             emit_jcc(cd, CC_AE, (disp))
-#define M_BA(disp)              emit_jcc(cd, CC_A, (disp))
+
+#define M_BULT(disp)            emit_jcc(cd, CC_B, (disp))
+#define M_BULE(disp)            emit_jcc(cd, CC_BE, (disp))
+#define M_BUGE(disp)            emit_jcc(cd, CC_AE, (disp))
+#define M_BUGT(disp)            emit_jcc(cd, CC_A, (disp))
+
+#define M_SETNE(a)              emit_setcc_reg(cd, CC_NE, (a))
+#define M_SETULE(a)             emit_setcc_reg(cd, CC_BE, (a))
 
 #define M_CMOVEQ(a,b)           emit_cmovcc_reg_reg(cd, CC_E, (a), (b))
 #define M_CMOVNE(a,b)           emit_cmovcc_reg_reg(cd, CC_NE, (a), (b))
 #define M_CMOVGE(a,b)           emit_cmovcc_reg_reg(cd, CC_GE, (a), (b))
 #define M_CMOVGT(a,b)           emit_cmovcc_reg_reg(cd, CC_G, (a), (b))
 
-#define M_CMOVEQ_MEMBASE(a,b,c) emit_cmovcc_reg_membase(cd, CC_E, (a), (b))
-#define M_CMOVNE_MEMBASE(a,b,c) emit_cmovcc_reg_membase(cd, CC_NE, (a), (b))
-#define M_CMOVLT_MEMBASE(a,b,c) emit_cmovcc_reg_membase(cd, CC_L, (a), (b))
-#define M_CMOVLE_MEMBASE(a,b,c) emit_cmovcc_reg_membase(cd, CC_LE, (a), (b))
-#define M_CMOVGE_MEMBASE(a,b,c) emit_cmovcc_reg_membase(cd, CC_GE, (a), (b))
-#define M_CMOVGT_MEMBASE(a,b,c) emit_cmovcc_reg_membase(cd, CC_G, (a), (b))
-
-#define M_CMOVB(a,b)            emit_cmovcc_reg_reg(cd, CC_B, (a), (b))
-#define M_CMOVA(a,b)            emit_cmovcc_reg_reg(cd, CC_A, (a), (b))
+#define M_CMOVULT(a,b)          emit_cmovcc_reg_reg(cd, CC_B, (a), (b))
+#define M_CMOVUGT(a,b)          emit_cmovcc_reg_reg(cd, CC_A, (a), (b))
 #define M_CMOVP(a,b)            emit_cmovcc_reg_reg(cd, CC_P, (a), (b))
 
 #define M_PUSH(a)               emit_push_reg(cd, (a))
index 6c6be8218abe0a59eff60eae3e1619a02c869f2a..70e52f9a7d9ef8cfc75a2a7caff861e3597e3208 100644 (file)
@@ -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));
index ce88f97b75cb4dd43aea2be6c10582fdd69476aa..5296dd2591f8f203b180bfe3b495212ada2d0d5e 100644 (file)
@@ -1,6 +1,6 @@
-/* src/vm/jit/x86_64/md-emit.h - machine dependent emit function prototypes
+/* src/vm/jit/x86_64/emit.h - machine dependent emit function prototypes
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
    J. Wenninger, Institut f. Computersprachen - TU Wien
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Christian Thalinger
-
-   Changes:
-
-   $Id: emit.h 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);
index 298c8586676ca654ec7401603a570c735c16cfd9..c8ec58b42ea59aa505851de338839cb9ff30be89 100644 (file)
 #include <stdlib.h>
 #include <ucontext.h>
 
+#include "vm/types.h"
+
+#include "vm/jit/x86_64/codegen.h"
+
 #if defined(ENABLE_THREADS)
 # include "threads/native/threads.h"
 #endif
 
+#include "vm/exceptions.h"
 #include "vm/signallocal.h"
 
 #include "vm/jit/asmpart.h"
 
 /* md_signal_handler_sigsegv ***************************************************
 
-   NullPointerException signal handler for hardware null pointer
-   check.
+   Signal handler for hardware exception.
 
 *******************************************************************************/
 
 void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
 {
-       ucontext_t *_uc;
-       mcontext_t *_mc;
-       u1         *sp;
-       u1         *ra;
-       u1         *xpc;
+       ucontext_t        *_uc;
+       mcontext_t        *_mc;
+       u1                *sp;
+       u1                *ra;
+       u1                *xpc;
+       u1                 opc;
+       u1                 mod;
+       u1                 rm;
+       s4                 d;
+       s4                 disp;
+       ptrint             val;
+       s4                 type;
+       java_objectheader *o;
 
        _uc = (ucontext_t *) _p;
        _mc = &_uc->uc_mcontext;
@@ -76,9 +88,82 @@ void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
        threads_check_stackoverflow(sp);
 #endif
 
-       _mc->gregs[REG_RAX] =
-               (ptrint) stacktrace_hardware_nullpointerexception(NULL, sp, ra, xpc);
-
+       /* get exception-throwing instruction */
+
+       opc = M_ALD_MEM_GET_OPC(xpc);
+       mod = M_ALD_MEM_GET_MOD(xpc);
+       rm  = M_ALD_MEM_GET_RM(xpc);
+
+       /* for values see emit_mov_mem_reg and emit_mem */
+
+       if ((opc == 0x8b) && (mod == 0) && (rm == 4)) {
+               /* this was a hardware-exception */
+
+               d    = M_ALD_MEM_GET_REG(xpc);
+               disp = M_ALD_MEM_GET_DISP(xpc);
+
+               /* we use the exception type as load displacement */
+
+               type = disp;
+
+               /* XXX FIX ME! */
+
+               /* ATTENTION: The _mc->gregs layout is even worse than on
+                  i386! See /usr/include/sys/ucontext.h.  We need a
+                  switch-case here... */
+
+               switch (d) {
+               case 0:  /* REG_RAX == 13 */
+                       d = REG_RAX;
+                       break;
+               case 1:  /* REG_RCX == 14 */
+                       d = REG_RCX;
+                       break;
+               case 2:  /* REG_RDX == 12 */
+                       d = REG_RDX;
+                       break;
+               case 3:  /* REG_RBX == 11 */
+                       d = REG_RBX;
+                       break;
+               case 4:  /* REG_RSP == 15 */
+                       d = REG_RSP;
+                       break;
+               case 5:  /* REG_RBP == 10 */
+                       d = REG_RBP;
+                       break;
+               case 6:  /* REG_RSI == 9  */
+                       d = REG_RSI;
+                       break;
+               case 7:  /* REG_RDI == 8  */
+                       d = REG_RDI;
+                       break;
+               case 8:  /* REG_R8  == 0  */
+               case 9:  /* REG_R9  == 1  */
+               case 10: /* REG_R10 == 2  */
+               case 11: /* REG_R11 == 3  */
+               case 12: /* REG_R12 == 4  */
+               case 13: /* REG_R13 == 5  */
+               case 14: /* REG_R14 == 6  */
+               case 15: /* REG_R15 == 7  */
+                       d = d - 8;
+                       break;
+               }
+
+               val = _mc->gregs[d];
+       }
+       else {
+               /* this was a normal NPE */
+
+               type = EXCEPTION_HARDWARE_NULLPOINTER;
+       }
+
+       /* generate appropriate exception */
+
+       o = exceptions_new_hardware_exception(NULL, sp, ra, xpc, type, val);
+
+       /* set registers */
+
+       _mc->gregs[REG_RAX] = (ptrint) o;
        _mc->gregs[REG_R10] = (ptrint) xpc;                      /* REG_ITMP2_XPC */
        _mc->gregs[REG_RIP] = (ptrint) asm_handle_exception;
 }
index e59e81f58bf2d2f874f4a2ebc5b3c9d3a461e4d2..7514f1edb368a229cce522fe724ce7b77e56405b 100644 (file)
@@ -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
index c0623969bc5ba39efd6ed29118a5d0004a08cde1..ef1551844c5ff95f16829d8d2c31cf1c1b87b1b7 100644 (file)
@@ -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:
 
    <patched call position>
    45 8b 9a 1c 00 00 00             mov    0x1c(%r10),%r11d
-   49 81 eb 00 00 00 00             sub    $0x0,%r11
-   4d 85 db                         test   %r11,%r11
-   0f 8e 94 04 00 00                jle    0x00002aaaaab018f8
+   41 81 fb 00 00 00 00             cmp    $0x0,%r11d
+   0f 8f 08 00 00 00                jg     0x00002aaaaae511d5
+   48 8b 0c 25 03 00 00 00          mov    0x3,%rcx
    4d 8b 9a 00 00 00 00             mov    0x0(%r10),%r11
 
 *******************************************************************************/
 
-bool patcher_checkcast_instanceof_interface(u1 *sp)
+bool patcher_checkcast_interface(u1 *sp)
 {
        u1                *ra;
        u8                 mcode;
@@ -678,13 +678,13 @@ bool patcher_checkcast_instanceof_interface(u1 *sp)
        /* if we show disassembly, we have to skip the nop's */
 
        if (opt_shownops)
-               ra = ra + 5;
+               ra = ra + PATCHER_CALL_SIZE;
 
        /* patch super class index */
 
        *((s4 *) (ra + 7 + 3)) = (s4) c->index;
 
-       *((s4 *) (ra + 7 + 7 + 3 + 6 + 3)) =
+       *((s4 *) (ra + 7 + 7 + 6 + 8 + 3)) =
                (s4) (OFFSET(vftbl_t, interfacetable[0]) -
                          c->index * sizeof(methodptr*));
 
@@ -741,6 +741,57 @@ bool patcher_checkcast_class(u1 *sp)
 }
 
 
+/* patcher_instanceof_interface ************************************************
+
+   Machine code:
+
+   <patched call position>
+   45 8b 9a 1c 00 00 00             mov    0x1c(%r10),%r11d
+   41 81 fb 00 00 00 00             cmp    $0x0,%r11d
+   0f 8e 94 04 00 00                jle    0x00002aaaaab018f8
+   4d 8b 9a 00 00 00 00             mov    0x0(%r10),%r11
+
+*******************************************************************************/
+
+bool patcher_instanceof_interface(u1 *sp)
+{
+       u1                *ra;
+       u8                 mcode;
+       constant_classref *cr;
+       classinfo         *c;
+
+       /* get stuff from the stack */
+
+       ra    = (u1 *)                *((ptrint *) (sp + 5 * 8));
+       mcode =                       *((u8 *)     (sp + 3 * 8));
+       cr    = (constant_classref *) *((ptrint *) (sp + 2 * 8));
+
+       /* get the fieldinfo */
+
+       if (!(c = resolve_classref_eager(cr)))
+               return false;
+
+       /* patch back original code */
+
+       *((u8 *) ra) = mcode;
+
+       /* if we show disassembly, we have to skip the nop's */
+
+       if (opt_shownops)
+               ra = ra + PATCHER_CALL_SIZE;
+
+       /* patch super class index */
+
+       *((s4 *) (ra + 7 + 3)) = (s4) c->index;
+
+       *((s4 *) (ra + 7 + 7 + 6 + 3)) =
+               (s4) (OFFSET(vftbl_t, interfacetable[0]) -
+                         c->index * sizeof(methodptr*));
+
+       return true;
+}
+
+
 /* patcher_instanceof_class ****************************************************
 
    Machine code:
index 4425ae87194309fcf6d8467b85f5d81759f2294c..096bb0c93a09b8605a67c6e397026f237c5e4ecf 100644 (file)
@@ -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
index 0ded4eafbda307ac47a8e596f3749153be58a27d..eaef44b327111940d1840534589d1439783d7555 100644 (file)
@@ -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);
index 20749900eb8d1344f7a27febeb9c25fd22775605..a9b1d1a334d08f90a7864eb2a02aacb565f594d3 100644 (file)
@@ -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;
index 541fbb8dde5f5eacd1aeb6ce841474f0df73df11..5d1cc1e49031606ff24df2ae3298a25e508baf82 100644 (file)
@@ -175,7 +175,6 @@ enum {
 
        OPT_VERBOSE1,
        OPT_NOIEEE,
-       OPT_SOFTNULL,
 
 #if defined(ENABLE_STATISTICS)
        OPT_TIME,
@@ -298,7 +297,6 @@ opt_struct opts[] = {
 #if defined(__ALPHA__)
        { "noieee",            false, OPT_NOIEEE },
 #endif
-       { "softnull",          false, OPT_SOFTNULL },
 #if defined(ENABLE_STATISTICS)
        { "time",              false, OPT_TIME },
        { "stat",              false, OPT_STAT },
@@ -500,7 +498,6 @@ static void XXusage(void)
 #if defined(ENABLE_VERIFIER)
        puts("    -noverify                don't verify classfiles");
 #endif
-       puts("    -softnull                use software nullpointer check");
 #if defined(ENABLE_STATISTICS)
        puts("    -time                    measure the runtime");
        puts("    -stat                    detailed compiler statistics");
@@ -889,7 +886,6 @@ bool vm_create(JavaVMInitArgs *vm_args)
        opt_version       = false;
        opt_exit          = false;
 
-       checknull         = false;
        opt_noieee        = false;
 
        opt_heapmaxsize   = HEAP_MAXSIZE;
@@ -1152,10 +1148,6 @@ bool vm_create(JavaVMInitArgs *vm_args)
                        break;
 #endif
 
-               case OPT_SOFTNULL:
-                       checknull = true;
-                       break;
-
 #if defined(ENABLE_STATISTICS)
                case OPT_TIME:
                        opt_getcompilingtime = true;
@@ -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,
index c90c8d31a2c70e8ef947a2c170e596e4570b90c3..b7c014f75116047dff9dabaae314fd7e58231399 100644 (file)
@@ -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.
index e28d03b9ff2d9ce6b599cd593fcee2004e072991..68bf1d8e74e4a8a15e400e30a2250f4a73a14088 100644 (file)
@@ -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 */
 
index 11a6669078b793583b96bea78ce96426e4fb214e..0b26cc5c1e99b8b9cbdd133021c8267083c89087 100644 (file)
@@ -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();
                        }
                }
 
index 294429cf8c1bc144c0c912d7c521e237fd43b786..f6dec16a7c7343c4644378314fd51e89c9cd4d6c 100644 (file)
@@ -22,7 +22,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: descriptor.h 7329 2007-02-11 21:24:14Z twisti $
+   $Id: descriptor.h 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       */
index e9c3c249d2bb4f242f6152bf2cd0f49cf03e3018..4bd8aacf82faa09ea6bc8d30e7d9df61ad933862 100644 (file)
@@ -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;
        }
 
index 4239fbd223d433afe3507d4dd74d6585d87c7095..bbd577bc00df0879cf0be4926dc9ad8bdfc1432c 100644 (file)
@@ -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) */
 
index 274008a3750a63eac62b1547ed2494141d70e54a..f9dc0924e77fa14e44936be839ea374ff66ade46 100644 (file)
@@ -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(&paramtypes[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
index 208f8a57a3201180e80877eb1425144ba90a8545..ea02e1a3959bea4ad4dc70f68cc90779d9aa5285 100644 (file)
@@ -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);
 
index 51f9c8b32d9aab7193a3de5d3b4245e1b209bfc6..13f56a7e71f94480b6a9d5e4c0e0e11a9bbf3ff8 100644 (file)
@@ -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)
index ee06449b4d8d925cf146c746dd214578cda34034..2409cabc480bc93f0b0da373c9e0e884734b8042 100644 (file)
@@ -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)
index 8cf56b9f8ea13752c3d4a11a5f48427b0b27de7e..9d6a67b32ca4fad35c9439f3ac1b401b055f7f32 100644 (file)
@@ -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");
index 597d3be9af3132f93251cbc63012079f3df4541e..f0254801000840e98b9624dd1419ea48deda84d4 100644 (file)
@@ -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;
index 2ee7f2b60a606bdd9f81c9562deff5a7af61f670..84511522d62a73cbc18bb652f3e02e1d39b130a2 100644 (file)
@@ -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 */
index 90768984c56cf50bf3fdbf76d3008a1b67be1387..ece0e5ba84647d001073ee4c694c7d95a55a3b52 100644 (file)
@@ -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 \