Initial import of s390 codegen, codebase is copyed from x86_64.
authorpm <none@none>
Tue, 16 Jan 2007 22:18:57 +0000 (22:18 +0000)
committerpm <none@none>
Tue, 16 Jan 2007 22:18:57 +0000 (22:18 +0000)
--HG--
rename : src/vm/jit/x86_64/.cvsignore => src/vm/jit/s390/.cvsignore
rename : src/vm/jit/x86_64/Makefile.am => src/vm/jit/s390/Makefile.am
rename : src/vm/jit/x86_64/arch.h => src/vm/jit/s390/arch.h
rename : src/vm/jit/x86_64/asmpart.S => src/vm/jit/s390/asmpart.S
rename : src/vm/jit/x86_64/codegen.c => src/vm/jit/s390/codegen.c
rename : src/vm/jit/x86_64/codegen.h => src/vm/jit/s390/codegen.h
rename : src/vm/jit/x86_64/disass.c => src/vm/jit/s390/disass.c
rename : src/vm/jit/x86_64/emit.c => src/vm/jit/s390/emit.c
rename : src/vm/jit/x86_64/emit.h => src/vm/jit/s390/emit.h
rename : src/vm/jit/x86_64/machine-instr.h => src/vm/jit/s390/machine-instr.h
rename : src/vm/jit/x86_64/md-abi.c => src/vm/jit/s390/md-abi.c
rename : src/vm/jit/x86_64/md-abi.h => src/vm/jit/s390/md-abi.h
rename : src/vm/jit/x86_64/md-asm.h => src/vm/jit/s390/md-asm.h
rename : src/vm/jit/x86_64/md.c => src/vm/jit/s390/md.c
rename : src/vm/jit/x86_64/patcher.c => src/vm/jit/s390/patcher.c

19 files changed:
configure.ac
src/vm/jit/Makefile.am
src/vm/jit/disass-common.c
src/vm/jit/disass.h
src/vm/jit/s390/.cvsignore [new file with mode: 0644]
src/vm/jit/s390/Makefile.am [new file with mode: 0644]
src/vm/jit/s390/arch.h [new file with mode: 0644]
src/vm/jit/s390/asmpart.S [new file with mode: 0644]
src/vm/jit/s390/codegen.c [new file with mode: 0644]
src/vm/jit/s390/codegen.h [new file with mode: 0644]
src/vm/jit/s390/disass.c [new file with mode: 0644]
src/vm/jit/s390/emit.c [new file with mode: 0644]
src/vm/jit/s390/emit.h [new file with mode: 0644]
src/vm/jit/s390/machine-instr.h [new file with mode: 0644]
src/vm/jit/s390/md-abi.c [new file with mode: 0644]
src/vm/jit/s390/md-abi.h [new file with mode: 0644]
src/vm/jit/s390/md-asm.h [new file with mode: 0644]
src/vm/jit/s390/md.c [new file with mode: 0644]
src/vm/jit/s390/patcher.c [new file with mode: 0644]

index 3d5348993ec316cf7fce84d68efa4ca4b898fcce..6de3d7a35aadb7ab2d1f723872fc8509f8b39349 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 6595 2007-01-11 14:19:48Z twisti $
+dnl $Id: configure.ac 7219 2007-01-16 22:18:57Z pm $
 
 dnl Process this file with autoconf to produce a configure script.
 
@@ -105,6 +105,12 @@ xdspcore )
     USE_SCHEDULER="1"
     ;;
 
+s390 )
+    ARCH_DIR="s390"
+    ARCH_CFLAGS="-D__S390__"
+    ;;
+
+
 * )
     AC_MSG_ERROR($host_cpu systems are not supported at this time)
     ;;
@@ -475,7 +481,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)
+        arm | i386 | powerpc | x86_64 | sparc64 | powerpc64 | s390)
             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)])
@@ -1059,6 +1065,7 @@ AC_CONFIG_FILES([Makefile]
                [src/vm/jit/tools/Makefile]
                [src/vm/jit/verify/Makefile]
                [src/vm/jit/x86_64/Makefile]
+               [src/vm/jit/s390/Makefile]
                [tests/Makefile]
                [tests/regression/Makefile]
                [tests/regression/codepatching/Makefile]
index 0dfa665f9ba6493bd941be6b3523977074418cef..9cfb3b0a6dcf4b23182aaf1008007ad9e093879a 100644 (file)
@@ -28,7 +28,7 @@
 ##
 ## Changes: Edwin Steiner
 ##
-## $Id: Makefile.am 6595 2007-01-11 14:19:48Z twisti $
+## $Id: Makefile.am 7219 2007-01-16 22:18:57Z pm $
 
 ## Process this file with automake to produce Makefile.in
 
@@ -54,7 +54,8 @@ DIST_SUBDIRS = \
        powerpc \
        powerpc64 \
        sparc64 \
-       x86_64
+       x86_64 \
+       s390
 
 SUBDIRS = \
        optimizing \
index 78e74f50cb44a6a7d7ebe92f70f0b64035233ea2..e87c704a8b429d09a3d0cfb160331da63411151f 100644 (file)
@@ -28,7 +28,7 @@
 
    Changes:
 
-   $Id: disass-common.c 4844 2006-04-25 18:02:15Z edwin $
+   $Id: disass-common.c 7219 2007-01-16 22:18:57Z pm $
 
 */
 
@@ -59,7 +59,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__)
+#if defined(__I386__) || defined(__X86_64__) || defined(__S390__)
 char disass_buf[512];
 s4   disass_len;
 #endif
@@ -99,7 +99,7 @@ void disass_printf(PTR p, const char *fmt, ...)
 
        va_start(ap, fmt);
 
-#if defined(__I386__) || defined(__X86_64__)
+#if defined(__I386__) || defined(__X86_64__) || defined(__S390__)
        disass_len += vsprintf(disass_buf + disass_len, fmt, ap);
 #else
        vprintf(fmt, ap);
index 269e834a5acca27be76920896892bf76ea0c93f6..f5192658a7fd726c0c54bcdef9e04c79a3504b12 100644 (file)
@@ -28,7 +28,7 @@
 
    Changes:
 
-   $Id: disass.h 4709 2006-03-30 10:14:22Z twisti $
+   $Id: disass.h 7219 2007-01-16 22:18:57Z pm $
 
 */
 
@@ -96,7 +96,7 @@ extern bool disass_initialized;
 
 extern char *regs[];
 
-#if defined(__I386__) || defined(__X86_64__)
+#if defined(__I386__) || defined(__X86_64__) || defined(__S390__)
 extern char disass_buf[512];
 extern s4   disass_len;
 #endif
diff --git a/src/vm/jit/s390/.cvsignore b/src/vm/jit/s390/.cvsignore
new file mode 100644 (file)
index 0000000..1f83cf9
--- /dev/null
@@ -0,0 +1,10 @@
+*.a
+*.o
+*.la
+*.lo
+.deps
+.libs
+Makefile
+Makefile.in
+TAGS
+offsets.h
diff --git a/src/vm/jit/s390/Makefile.am b/src/vm/jit/s390/Makefile.am
new file mode 100644 (file)
index 0000000..1bac4da
--- /dev/null
@@ -0,0 +1,82 @@
+## src/vm/jit/x86_64/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 5830 2006-10-26 11:04:31Z twisti $
+
+## Process this file with automake to produce Makefile.in
+
+AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_builddir) -I$(top_builddir)/src
+AM_CCASFLAGS = $(AM_CPPFLAGS) $(AM_LDFLAGS)
+
+LIBS =
+
+BUILT_SOURCES = offsets.h
+
+CLEANFILES = offsets.h
+
+noinst_HEADERS = \
+       arch.h \
+       machine-instr.h \
+       \
+       md-asm.h
+
+noinst_LTLIBRARIES = libarch.la
+
+if ENABLE_DISASSEMBLER
+DISASS_SOURCES = \
+       disass.c
+endif
+
+libarch_la_SOURCES = \
+       asmpart.S \
+       codegen.c \
+       codegen.h \
+       $(DISASS_SOURCES) \
+       emit.c \
+       emit.h \
+       patcher.c \
+       \
+       md-abi.c \
+       md-abi.h \
+       md.c
+
+$(srcdir)/asmpart.S: $(top_builddir)/config.h offsets.h
+
+offsets.h: $(top_builddir)/src/vm/jit/tools/genoffsets $(top_builddir)/config.h
+       $(top_builddir)/src/vm/jit/tools/genoffsets > offsets.h
+
+
+## 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/s390/arch.h b/src/vm/jit/s390/arch.h
new file mode 100644 (file)
index 0000000..dfdaa9a
--- /dev/null
@@ -0,0 +1,97 @@
+/* src/vm/jit/x86_64/arch.h - architecture defines for x86_64
+
+   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: arch.h 7219 2007-01-16 22:18:57Z pm $
+
+*/
+
+
+#ifndef _ARCH_H
+#define _ARCH_H
+
+/* define architecture features ***********************************************/
+
+#define U8_AVAILABLE                     1
+
+/* #define USEBUILTINTABLE */
+
+#define SUPPORT_DIVISION                 1
+#define SUPPORT_LONG                     1
+#define SUPPORT_FLOAT                    1
+#define SUPPORT_DOUBLE                   1
+
+#define SUPPORT_I2F                      1
+#define SUPPORT_I2D                      1
+#define SUPPORT_L2F                      1
+#define SUPPORT_L2D                      1
+
+/* ATTENTION: x86_64 architectures support these conversions, but we
+   need the builtin functions in corner cases */
+#define SUPPORT_F2I                      0
+#define SUPPORT_F2L                      0
+#define SUPPORT_D2I                      0
+#define SUPPORT_D2L                      0
+
+#define SUPPORT_LONG_ADD                 1
+#define SUPPORT_LONG_CMP                 1
+#define SUPPORT_LONG_CMP_CONST           1
+#define SUPPORT_LONG_LOGICAL             1
+#define SUPPORT_LONG_SHIFT               1
+#define SUPPORT_LONG_MUL                 1
+#define SUPPORT_LONG_DIV                 1
+
+#define SUPPORT_LONG_DIV_POW2            1
+#define SUPPORT_LONG_REM_POW2            1
+
+#define SUPPORT_CONST_LOGICAL            1  /* AND, OR, XOR with immediates   */
+#define SUPPORT_CONST_MUL                1  /* mutiply with immediate         */
+
+#define SUPPORT_CONST_STORE              1  /* do we support const stores     */
+#define SUPPORT_CONST_STORE_ZERO_ONLY    0  /* on some risc machines we can   */
+                                            /* only store REG_ZERO            */
+
+#define CONSECUTIVE_INTEGER_ARGS
+#define CONSECUTIVE_FLOAT_ARGS
+
+#endif /* _ARCH_H */
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
diff --git a/src/vm/jit/s390/asmpart.S b/src/vm/jit/s390/asmpart.S
new file mode 100644 (file)
index 0000000..05585a3
--- /dev/null
@@ -0,0 +1,1252 @@
+/* src/vm/jit/x86_64/asmpart.S - Java-C interface functions for x86_64
+
+   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: Andreas Krall
+            Reinhard Grafl
+            Christian Thalinger
+
+   Changes: Edwin Steiner
+
+   $Id: asmpart.S 7219 2007-01-16 22:18:57Z pm $
+
+*/
+
+
+#include "config.h"
+
+#include "vm/jit/s390/arch.h"
+#include "vm/jit/s390/md-abi.h"
+#include "vm/jit/s390/md-asm.h"
+#include "vm/jit/s390/offsets.h"
+
+#include "vm/jit/abi-asm.h"
+#include "vm/jit/methodheader.h"
+
+/* Copy a call to a PIC function from gcc -S
+ * We setup a temporary literal pool pointer.
+ */
+
+#define PIC_CALL(fun, magic)                                  \
+       bras itmp3, L_##magic##_lp_end                          ; \
+L_##magic##_lp:                                             ; \
+L_##magic##_lp_5:                                           ; \
+       .long fun@PLTOFF                                        ; \
+L_##magic##_lp_4:                                           ; \
+       .long _GLOBAL_OFFSET_TABLE_-L_##magic##_lp              ; \
+L_##magic##_lp_end:                                         ; \
+       l       itmp2,L_##magic##_lp_4-L_##magic##_lp(itmp3)    ; \
+       la      itmp2,0(itmp2,itmp3)                            ; \
+       l       itmp1,L_##magic##_lp_5-L_##magic##_lp(itmp3)    ; \
+       bas     %r14,0(itmp1,itmp2)                             
+
+       .text
+
+
+/* export functions ***********************************************************/
+
+       .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_exception_handler
+
+       .globl asm_call_jit_compiler
+
+       .globl asm_handle_exception
+       .globl asm_handle_nat_exception
+
+       .globl asm_abstractmethoderror
+
+       .globl asm_patcher_wrapper
+
+       .globl asm_replacement_out
+       .globl asm_replacement_in
+
+       .globl asm_builtin_f2i
+       .globl asm_builtin_f2l
+       .globl asm_builtin_d2i
+       .globl asm_builtin_d2l
+
+       .globl asm_criticalsections
+       .globl asm_getclassvalues_atomic
+
+
+#if 0
+asm_vm_call_method:
+asm_vm_call_method_int:
+asm_vm_call_method_long:
+asm_vm_call_method_float:
+asm_vm_call_method_double:
+#endif
+asm_vm_call_method_exception_handler:
+#if 0
+asm_call_jit_compiler:
+#endif
+asm_handle_exception:
+asm_handle_nat_exception:
+asm_abstractmethoderror:
+asm_patcher_wrapper:
+asm_replacement_out:
+asm_replacement_in:
+asm_builtin_f2i:
+asm_builtin_f2l:
+asm_builtin_d2i:
+asm_builtin_d2l:
+asm_criticalsections:
+asm_getclassvalues_atomic:
+       .long 0
+
+/********************* function asm_calljavafunction ***************************
+*                                                                              *
+*   This function calls a Java-method (which possibly needs compilation)       *
+*   with up to 4 address parameters.                                           *
+*                                                                              *
+*   This functions calls the JIT-compiler which eventually translates the      *
+*   method into machine code.                                                  *
+*                                                                              *
+*   C-prototype:                                                               *
+*    javaobject_header *asm_calljavamethod (methodinfo *m,                     *
+*         void *arg1, void *arg2, void *arg3, void *arg4);                     *
+*                                                                              *
+*******************************************************************************/
+       .align  8
+
+       .quad   0                           /* catch type all                     */
+       .quad   0                           /* handler pc                         */
+       .quad   0                           /* end pc                             */
+       .quad   0                           /* start pc                           */
+       .long   1                           /* extable size                       */
+       .long   0                           /* ALIGNMENT PADDING                  */
+       .quad   0                           /* line number table  start           */
+       .quad   0                           /* line number table  size            */
+       .long   0                           /* ALIGNMENT PADDING                  */
+       .long   0                           /* fltsave                            */
+       .long   0                           /* intsave                            */
+       .long   0                           /* isleaf                             */
+       .long   0                           /* IsSync                             */
+       .long   0                           /* frame size                         */
+       .quad   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:
+
+/*
+
+a0:   methodinfo *m
+a1:   s4 vmargscount   ---> v0: java_objectheader *
+a2:   vm_arg *vmargs
+r14:  return address
+
+96 ...     on stack parameters (none)
+0 - 96     register save area
+-------------------------------------------------- <- SP on asm_vm_... entry
+           arguments on stack
+---------------------------------------------------- <- SP on JIT code entry
+           saved return address (callee saved)
+
+*/
+
+
+/*
+       Regiser usage:
+       itmp1: argument block pointer
+       itmp2: argument counter
+       s0: integer argument counter
+       s1: float argument counter
+       s2: integer register counter
+       s3: backup argument block pointer
+       s4: backup argument count
+*/
+
+       stm   %r6, %r15, 24(sp)               /* save callers regiters */
+       ahi   sp, -16                         /* allocate stack space for local variables */
+       stm   a0, a2, 0(sp)                   /* save arguments */
+
+       ltr   a1, a1                          /* maybe we have no args... */
+       je    L_no_args
+
+       lr    itmp2, a1                       /* load arg count */
+       lr    itmp1, a2                       /* load arg pointer */
+
+       ahi   itmp1, -sizevmarg               /* initialize arg pointer */
+       ahi   itmp2, 1                        /* initialize arg count */ 
+       lhi   s0, 0                           /* initialize integer arg counter */
+       lhi   s2, 0                           /* initialize integer register counter */
+       lhi   s1, 0                           /* initialize float arg counter */
+
+       lr    s4, a1                          /* backup arg count */
+       lr    s3, a2                          /* backup arg pointer */
+
+L_register_copy:
+
+       ahi   itmp1, sizevmarg                /* forward arg pointer */
+       ahi   itmp2, -1                       /* decrement arg count */
+       je    L_register_copy_done            /* no arguments left */
+
+       tm    offvmargtype(itmp1), 0x02       /* is this a float/double type? */
+       jne   L_register_handle_float
+
+L_register_handle_int:
+
+       chi   s2, INT_ARG_CNT                 /* are we out of integer arg registers ? */
+       je    L_register_copy                 /* yes, next loop */
+
+       tm    offvmargtype(itmp1), 0x01       /* is this a 2 word type ? */
+       jne   L_register_handle_long
+
+       ahi   s0, 1                           /* increment integer arg counter */
+       ahi   s2, 1                           /* increment integer register counter */
+
+       /* handle argument */
+
+       chi   s2, 1
+       je    L_handle_i0
+       chi   s2, 2
+       je    L_handle_i1
+       chi   s2, 3
+       je    L_handle_i2
+       chi   s2, 4
+       je    L_handle_i3
+       chi   s2, 5
+       je    L_handle_i4
+
+L_register_handle_long:
+
+       chi   s2, (INT_ARG_CNT - 1)           /* are there 2 integer arg registers left ? */
+       jl    L_register_handle_long_continue /* yes */
+       lhi   s2, INT_ARG_CNT                 /* no, drop last register */
+       j     L_register_copy
+
+L_register_handle_long_continue:
+
+       ahi   s0, 1                           /* increment integer arg counter */
+       ahi   s2, 2                           /* consume 2 integer arg registers */
+
+       /* handle argument */
+
+       chi   s2, 1
+       je    L_handle_l0
+       chi   s2, 2
+       je    L_handle_l1
+       chi   s2, 3
+       je    L_handle_l2
+       chi   s2, 4
+       je    L_handle_l3
+
+L_register_handle_float:
+
+       chi   s1, FLT_ARG_CNT                 /* are we out of float arg registers */
+       je    L_register_copy                 /* no arg regisers left */
+
+       ahi   s1, 1                           /* increment float argument counter */
+
+       tm    offvmargtype(itmp1), 0x01       /* is this a 2 word type ? */
+       jne   L_register_handle_double
+
+       /* handle argument */
+
+       chi   s1, 1
+       je    L_handle_f0
+       chi   s1, 2
+       je    L_handle_f1
+
+L_register_handle_double:
+
+       /* handle argument */
+
+       chi   s1, 1
+       je    L_handle_d0
+       chi   s1, 2
+       je    L_handle_d1
+
+L_register_copy_done:
+
+/*
+       Regiser usage:
+       itmp1: argument block pointer
+       itmp2: argument counter
+       s0: integer argument counter (initialized by previous code) 
+       s1: float argument counter (initialized by previous code)
+       s2: pointer to current argument on stack
+       s3: backup argument block pointer (used to initialize itmp1)
+           after used as backup of original stack pointer
+       s4: backup argument count (used to initialize itmp2)
+           after used as size of parameters on stack
+*/
+
+       lr    itmp2, s4                     /* restore argument counter */
+       lr    itmp1, s3                     /* restore argument block pointer */
+
+                                           /* calculate remaining arguments */
+       sr    s4, s0                        /* - integer arguments in registers */
+       sr    s4, s1                        /* - float arguments in registers */
+
+       je    L_copy_done                   /* no arguments left for stack */
+
+       sll   s4, 3                         /* allocate 8 bytes per parameter on stack */       
+       lr    s3, sp                        /* backup stack pointer */
+       sr    sp, s4                        /* allocate stack space for arguments */ 
+
+       lr    s2, sp                        /* points now to current argument on stack */
+
+       ahi   itmp1, -sizevmarg             /* initialize argument block pointer */
+       ahi   itmp2, 1                      /* initialize argument counter */
+
+L_stack_copy_loop:
+
+       ahi   itmp1, sizevmarg              /* forward argument block pointer */
+       ahi   itmp2, -1                     /* decrement argument counter */
+       je    L_copy_done                   /* all arguments done */
+
+       tm    offvmargtype(itmp1), 0x0      /* is this a float/double type? */
+       jne   L_stack_handle_float
+
+L_stack_handle_int:
+
+       ahi   s0, -1                         /* decrement number of integer arguments in regs */
+       jhe   L_stack_copy_loop              /* argument is in register */
+
+       tm    offvmargtype(itmp1), 0x01      /* is this a 2 word type ? */
+       jne   L_stack_handle_long
+
+       mvc   0(4, s2), offvmargdata(itmp1)  /* copy integer value */
+       ahi   s2, 4
+       j     L_stack_copy_loop
+
+L_stack_handle_long:
+
+       mvc   0(8, s2), offvmargdata(itmp1)  /* copy long value */
+       ahi   s2, 8
+       j     L_stack_copy_loop
+
+L_stack_handle_float:
+
+       ahi   s1, -1                         /* decrement number of float arguments in regs */
+       jhe   L_stack_copy_loop              /* argument is in register */
+
+       tm    offvmargtype(itmp1), 0x01      /* is this a 2 word type ? */
+       jne   L_stack_handle_double
+
+       mvc   0(4, s2), offvmargdata(itmp1)  /* copy float value */
+       ahi   s2, 4
+       j     L_stack_copy_loop
+
+L_stack_handle_double:
+
+       mvc   0(8, s2), offvmargdata(itmp1)  /* copy double value */
+       ahi   s2, 8
+       j     L_stack_copy_loop
+
+L_copy_done:
+
+       /* Now we call the compiler in a rather questionable way i needed
+        * some days to understand:
+        *
+        * We can't simply call asm_call_jit_compiler, but we have to call an 
+        * address loaded from memory like it is done in JIT code.
+        *
+        * This is because the compiler will intercept the instruction before 
+        * the call instruction, extract the address where the function pointer
+        * has been loaded from and overwrite it with the code entry.
+        *
+        * Arguments are passed in temporary registers.
+        */
+
+       /* load address of L_asm_call_jit_compiler into memory */
+
+       basr  mptr, 0                         /* store PC */
+L_basr:
+       la    mptr, L_asm_call_jit_compiler-L_basr(mptr) /* add offset to PC */
+       st    mptr, 12(s3)                    /* store on stack */
+
+       l     itmp1, 0(s3)                    /* load methodinfo for compiler */
+       la    mptr, 12(s3)                    /* store **function in mptr for compiler */
+
+       /* call L_asm_call_jit_compiler like JIT code would do */
+
+       l     itmp3, 12(s3)                   /* load address of target from memory */
+       basr  %r14, itmp3                     /* jump to target */
+
+       /* todo will s4 survive the call? */
+       ar    sp, s4                          /* remove stack space for arguments */
+
+L_asm_vm_call_method_return:
+
+       ahi   sp, 16                          /* remove stack space for local variables */
+       lm    %r6, %r15, 24(sp)               /* restore callers registers */
+       br    %r14                            /* return */
+
+/* .... */
+
+L_no_args:
+       lr    s3, sp
+       j     L_copy_done
+
+L_handle_i0:
+       l     a0, offvmargdata(itmp1)
+       j     L_register_copy
+L_handle_i1:
+       l     a1, offvmargdata(itmp1)
+       j     L_register_copy
+L_handle_i2:
+       l     a2, offvmargdata(itmp1)
+       j     L_register_copy
+L_handle_i3:
+       l     a3, offvmargdata(itmp1)
+       j     L_register_copy
+L_handle_i4:
+       l     a4, offvmargdata(itmp1)
+       j     L_register_copy
+
+L_handle_l0:
+       lm    a0, a1, offvmargdata(itmp1)
+       j     L_register_copy
+L_handle_l1:
+       lm    a1, a2, offvmargdata(itmp1)
+       j     L_register_copy
+L_handle_l2:
+       lm    a2, a3, offvmargdata(itmp1)
+       j     L_register_copy
+L_handle_l3:
+       lm    a3, a4, offvmargdata(itmp1)
+       j     L_register_copy
+
+L_handle_f0:
+       le    fa0, offvmargdata(itmp1)
+       j     L_register_copy
+L_handle_f1:
+       le    fa1, offvmargdata(itmp1)
+       j     L_register_copy
+
+L_handle_d0:
+       ld    fa0, offvmargdata(itmp1)
+       j     L_register_copy
+L_handle_d1:
+       ld    fa1, offvmargdata(itmp1)
+       j     L_register_copy
+
+
+/* .... */
+
+#if 0
+
+       .align  8
+
+       .quad   0                           /* catch type all                     */
+       .quad   0                           /* handler pc                         */
+       .quad   0                           /* end pc                             */
+       .quad   0                           /* start pc                           */
+       .long   1                           /* extable size                       */
+       .long   0                           /* ALIGNMENT PADDING                  */
+       .quad   0                           /* line number table  start           */
+       .quad   0                           /* line number table  size            */
+       .long   0                           /* ALIGNMENT PADDING                  */
+       .long   0                           /* fltsave                            */
+       .long   0                           /* intsave                            */
+       .long   0                           /* isleaf                             */
+       .long   0                           /* IsSync                             */
+       .long   0                           /* frame size                         */
+       .quad   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:
+
+       stm %r6,%r15,24(sp)                /* save callers regiters */
+
+       ahi sp, -12  /* allocate space on stack for local variables */
+
+       st a0, 0(sp) /* store method info */
+       st a1, 4(sp) /* store arg count */
+       st a2, 8(sp) /* store args */
+
+
+#      define r_methodinfo  itmp1
+#      define r_vmargscount itmp2
+#      define r_vmargs      s0
+
+#      define r_arg_ctr     s1
+#      define r_arg_ptr     s2
+
+#      define r_int_ctr     s3
+#      define r_float_ctr   s4
+#   define r_int_extra_ctr    itmp3
+
+       /* save arguments */
+
+       lr      r_methodinfo,a0                    /* move method pointer for compiler   */
+       lr      r_vmargscount,a1
+       lr      r_vmargs,a2                    
+
+       ltr     a1,a1                       /* maybe we have no args...           */
+       je      L_copy_done
+
+       lr      r_arg_ctr,r_vmargscount         /* arg count                          */
+       lr      r_arg_ptr,r_vmargs              /* pointer to arg block               */
+
+       ahi     r_arg_ptr,-sizevmarg            /* initialize pointer (smaller code)  */
+       ahi     r_arg_ctr,1                     /* initialize argument count          */
+
+       lhi     r_int_ctr,0                      /* initialize integer argument counter*/
+       lhi     r_float_ctr,0                      /* initialize float argument counter  */
+       lhi     r_int_extra_ctr,0
+
+L_register_copy:
+       ahi     r_arg_ptr,sizevmarg             /* goto next argument block           */
+       ahi     r_arg_ctr,-1                    /* argument count - 1                 */
+       je      L_register_copy_done
+
+       tm      offvmargtype(r_arg_ptr),0x02    /* is this a float/double type?       */
+       jne     L_register_handle_float     /* yes, handle it                     */
+
+       cli     offvmargtype(r_arg_ptr),0x01
+       je      L_register_handle_long
+
+L_register_handle_int:
+
+       chi     r_int_ctr,INT_ARG_CNT            /* are we out of integer argument     */
+       je      L_register_copy             /* register? yes, next loop           */
+
+       ahi     r_int_ctr,1
+
+       chi     r_int_ctr,1
+       je      L_handle_a0
+       chi     r_int_ctr,2
+       je      L_handle_a1
+       chi     r_int_ctr,3
+       je      L_handle_a2
+       chi     r_int_ctr,4
+       je      L_handle_a3
+       chi     r_int_ctr,5
+       je      L_handle_a4
+
+L_register_handle_long:
+
+       chi     r_int_ctr,INT_ARG_CNT-1 /* only one integer register left ? */
+       je      L_register_handle_long_last_reg
+
+       chi     r_int_ctr,INT_ARG_CNT /* no registers left */
+       je     L_register_copy
+
+       ahi     r_int_ctr,2
+       ahi     r_int_extra_ctr,1
+
+       chi     r_int_ctr,2
+       je      L_handle_al0
+       chi     r_int_ctr,3
+       je      L_handle_al1
+       chi     r_int_ctr,4
+       je      L_handle_al2
+       chi     r_int_ctr,5
+       je      L_handle_al3
+
+L_register_handle_long_last_reg:
+       ahi     r_int_ctr,1 /* skip the integer register */
+       ahi     r_int_extra_ctr,1
+       j       L_register_copy
+
+L_register_handle_float:
+       chi     r_float_ctr,FLT_ARG_CNT         /* are we out of float argument         */
+       je      L_register_copy           /* register? yes, next loop             */
+
+       ahi     r_float_ctr,1
+
+       chi     r_int_ctr,1
+       je      L_handle_af0
+       chi     r_int_ctr,2
+       je      L_handle_af1
+
+L_register_copy_done:
+
+       lr      r_arg_ctr, r_vmargscount
+       sr      r_arg_ctr, r_int_ctr
+       ar      r_arg_ctr, r_int_extra_ctr
+       sr      r_arg_ctr, r_float_ctr
+       jle     L_copy_done 
+
+       /* now allocate the parameter area on the stack
+        * the register save area will be allocated later
+        */
+
+#      define r_arg_stack_ptr r_arg_ptr
+
+       sll     r_arg_ctr, 3 /* 8 bytes per parameter on stack */
+       sr      sp,r_arg_ctr /* allocate stack space for parameters */
+       lr      r_arg_stack_ptr,sp /* points now to arguments on stack */
+
+       ahi     r_vmargs,-sizevmarg            /* initialize pointer (smaller code)  */
+       ahi     r_vmargscount,1                     /* initialize argument count          */
+               
+L_stack_copy_loop:
+       ahi     r_vmargs,sizevmarg             /* goto next argument block           */
+       ahi     r_vmargscount,-1                    /* argument count - 1                 */
+       jz      L_copy_done               /* no test needed after dec             */
+
+       tm      offvmargtype(r_vmargs),0x02    /* is this a float/double type?       */
+       jne     L_stack_handle_float     /* yes, handle it                     */
+
+       cli     offvmargtype(r_vmargs),0x01
+       je      L_stack_handle_long
+
+L_stack_handle_int:
+
+       ahi     r_int_ctr,-1                        /* arguments assigned to registers    */
+       jhe     L_stack_copy_loop
+       j       L_stack_copy
+
+L_stack_handle_long:
+
+       ahi     r_int_ctr,-2
+       jhe     L_stack_copy_loop
+       j       L_stack_copy
+
+L_stack_handle_float:
+       ahi     r_float_ctr,-1                        /* arguments assigned to registers    */
+       jhe     L_stack_copy_loop
+
+L_stack_copy:
+       mvc     0(8,r_arg_stack_ptr),offvmargdata(r_vmargs) /* copy s8 argument onto stack        */
+
+       ahi     r_arg_stack_ptr,8                     /* increase sp to next argument       */
+       j       L_stack_copy_loop
+
+L_copy_done:
+#if 0
+                                           /* itmp1 still contains method pointer*/
+       lea     L_asm_call_jit_compiler(%rip),mptr
+       mov     sp,itmp3                    /* calculate the old stack pointer    */
+       add     bp,itmp3
+       mov     mptr,6*8(itmp3) /* store mptr on stack */
+       lea     (6*8-256)(itmp3),mptr       /* We subtract 256 to force the next  */
+                                           /* move instruction to have a 32-bit  */
+                                           /* offset.                            */
+
+       mov     (0*8+256)(mptr),itmp3       /* method call as in Java             */
+       call    *itmp3                      /* call JIT compiler                  */
+
+       add     bp,sp                       /* remove argument stack frame if any */
+#endif
+
+                                           /* itmp1 still contains method pointer*/
+       
+       bras %r14, L_asm_call_jit_compiler
+       ar      sp,r_arg_ctr                /* r_arg_ctr in callee saved regiter */
+
+L_asm_vm_call_method_return:
+
+       ahi sp, 12                        /* free stack space */
+       lm %r6,%r15,24(sp)                /* restore registers */
+       br %r14                           /* branch to return address */
+               
+#if 0
+asm_vm_call_method_exception_handler:
+       mov     xptr,a0                     /* pass exception pointer             */
+       call    builtin_throw_exception@PLT
+       jmp     L_asm_vm_call_method_return
+#endif
+
+L_handle_a0:
+       l       a0,offvmargdata(r_arg_ptr)
+       j       L_register_copy
+L_handle_a1:
+       l       a1,offvmargdata(r_arg_ptr)
+       j       L_register_copy
+L_handle_a2:
+       l       a2,offvmargdata(r_arg_ptr)
+       j       L_register_copy
+L_handle_a3:
+       l       a3,offvmargdata(r_arg_ptr)
+       j       L_register_copy
+L_handle_a4:
+       l       a4,offvmargdata(r_arg_ptr)
+       j       L_register_copy
+
+L_handle_al0:
+       l       a0,offvmargdata(r_arg_ptr)
+       l       a1,offvmargdata+4(r_arg_ptr)
+       j       L_register_copy
+L_handle_al1:
+       l       a1,offvmargdata(r_arg_ptr)
+       l       a2,offvmargdata+4(r_arg_ptr)
+       j       L_register_copy
+L_handle_al2:
+       l       a2,offvmargdata(r_arg_ptr)
+       l       a3,offvmargdata+4(r_arg_ptr)
+       j       L_register_copy
+L_handle_al3:
+       l       a3,offvmargdata(r_arg_ptr)
+       l       a4,offvmargdata+4(r_arg_ptr)
+       j       L_register_copy
+
+L_handle_af0:
+       ld    fa0,offvmargdata(r_arg_ptr)
+       j     L_register_copy
+L_handle_af1:
+       ld    fa1,offvmargdata(r_arg_ptr)
+       j     L_register_copy
+
+#endif
+
+/****************** function asm_call_jit_compiler *****************************
+*                                                                              *
+*   invokes the compiler for untranslated JavaVM methods.                      *
+*                                                                              *
+*   itmp1: methodinfo pointer                                                  *
+*   itmp2: method pointer                                                      *
+*                                                                              *
+*******************************************************************************/
+
+/*
+
+argument registers: arguments (like in JIT)
+
+        arguments on stack (like in JIT)
+------------------------------------------------------------- <- SP on entry
+
+        saved return address                                           \
+        stored volatile (in terms of C ABI) floag argument registers   | 
+96      stored volatile (in terms of C ABI) integer argument registers | ACJC_STACKFRAME
+0 - 96  register save area (C ABI)                                     /
+-------------------------------------------------- <- SP for jit_asm_compile
+*/
+
+/* This is called from a compiler stub.
+ * Arguments are already in registers and the stack is setup like in CACAO.
+ */
+
+asm_call_jit_compiler:
+L_asm_call_jit_compiler:
+
+#      define ACJC_STACKFRAME (4 + (4 * 4) + (2 * 8) + 96)
+
+       ahi     sp,-ACJC_STACKFRAME        /* allocate stack space */
+
+       stm         %r2,%r5,96(sp)             /* store volatile int arg regs */
+       std     %f0,96+16(sp)              /* store volatile float arg regs */
+       std     %f2,96+24(sp)              
+       st      %r14,96+32(sp)             /* store return address */
+
+       /* load arguments */
+
+       lr      a0,itmp1                   /* pass methodinfo pointer            */
+       lr      a1,itmp2                   /* pass method pointer                */
+       la      a2,ACJC_STACKFRAME(sp)     /* pass java sp                       */
+       la      a3,0(%r14)                 /* pass return address, make sure bit 32 is 0 */
+
+       /* call jit_asm_compile in a PIC way */
+
+       bras    itmp3, L_bras_jac
+       .long   jit_asm_compile
+L_bras_jac:
+       l       itmp3, 0(itmp3)
+       basr    %r14, itmp3
+
+       lm     %r2,%r5,96(sp)             /* restore volatile int arg regs */
+       ld     %f0,96+16(sp)              /* store volatile float arg regs */
+       ld     %f2,96+24(sp)              /* store volatile float arg regs */
+       ld     %r14,96+32(sp)             /* restore return address */
+
+#if 0
+       ltr     v0,v0
+       je      L_asm_call_jit_compiler_exception
+#endif
+
+       b       0(v0)                      /* call the method, it will return to the caller */
+
+
+L_asm_call_jit_compiler_exception:
+#if 0
+       call    exceptions_get_and_clear_exception@PLT
+       pop     xpc                         /* delete return address              */
+       sub     $3,xpc                      /* faulting address is ra - 3         */
+       jmp     L_asm_handle_exception
+#endif
+       .long 0
+
+
+#if 0
+/* asm_handle_exception ********************************************************
+*                                                                              *
+*   This function handles an exception. It does not use the usual calling      *
+*   conventions. The exception pointer is passed in REG_ITMP1 and the          *
+*   pc from the exception raising position is passed in REG_ITMP2. It searches *
+*   the local exception table for a handler. If no one is found, it unwinds    *
+*   stacks and continues searching the callers.                                *
+*                                                                              *
+*******************************************************************************/
+
+asm_handle_nat_exception:
+       add     $8,sp                       /* clear return address of native stub*/
+               
+asm_handle_exception:
+L_asm_handle_exception:                 /* required for PIC code              */
+       sub     $((ARG_CNT+TMP_CNT)*8),sp   /* create maybe-leaf stackframe       */
+
+       SAVE_ARGUMENT_REGISTERS(0)          /* we save arg and temp registers in  */
+       SAVE_TEMPORARY_REGISTERS(ARG_CNT)   /* case this is a leaf method         */
+
+       mov     $((ARG_CNT+TMP_CNT)*8),a3   /* prepare a3 for handle_exception    */
+       mov     $1,t0                       /* set maybe-leaf flag                */
+
+L_asm_handle_exception_stack_loop:
+       sub     $(6*8),sp
+       mov     xptr,0*8(sp)                /* save exception pointer             */
+       mov     xpc,1*8(sp)                 /* save exception pc                  */
+       add     sp,a3                       /* calculate Java sp into a3...       */
+       add     $(6*8),a3
+       mov     a3,3*8(sp)                  /* ...and save it                     */
+       mov     t0,4*8(sp)                  /* save maybe-leaf flag               */
+
+       mov     xpc,a0                      /* exception pc                       */
+       call    codegen_get_pv_from_pc@PLT
+       mov     v0,2*8(sp)                  /* save data segment pointer          */
+        
+       mov     0*8(sp),a0                  /* pass exception pointer             */
+       mov     1*8(sp),a1                  /* pass exception pc                  */
+       mov     v0,a2                       /* pass data segment pointer          */
+       mov     3*8(sp),a3                  /* pass Java stack pointer            */
+       call    exceptions_handle_exception@PLT
+
+       test    v0,v0
+       jz      L_asm_handle_exception_not_catched
+
+       mov     v0,xpc                      /* move handlerpc into xpc            */
+       mov     0*8(sp),xptr                /* restore exception pointer          */
+       mov     4*8(sp),t0                  /* get maybe-leaf flag                */
+       add     $(6*8),sp                   /* free stack frame                   */
+
+       test    t0,t0                       /* test for maybe-leaf flag           */
+       jz      L_asm_handle_exception_no_leaf
+
+       RESTORE_ARGUMENT_REGISTERS(0)       /* if this is a leaf method, we have  */
+       RESTORE_TEMPORARY_REGISTERS(ARG_CNT)/* to restore arg and temp registers  */
+
+       add     $((ARG_CNT+TMP_CNT)*8),sp   /* remove maybe-leaf stackframe       */
+
+L_asm_handle_exception_no_leaf:
+       jmp     *xpc                        /* jump to the handler                */
+
+L_asm_handle_exception_not_catched:
+       mov     0*8(sp),xptr                /* restore exception pointer          */
+       mov     2*8(sp),itmp3               /* restore data segment pointer       */
+       mov     4*8(sp),t0                  /* get maybe-leaf flag                */
+       add     $(6*8),sp
+
+       test    t0,t0
+       jz      L_asm_handle_exception_no_leaf_stack
+
+       add     $((ARG_CNT+TMP_CNT)*8),sp   /* remove maybe-leaf stackframe       */
+       xor     t0,t0                       /* clear the isleaf flags             */
+
+L_asm_handle_exception_no_leaf_stack:
+       mov     FrameSize(itmp3),itmp2l     /* get frame size                     */
+       add     sp,itmp2                    /* pointer to save area               */
+       
+       mov     IntSave(itmp3),a0l          /* a0l = saved int register count     */
+       test    a0l,a0l
+       je      noint
+       
+       cmp     $1,a0l
+       je      int1
+       cmp     $2,a0l
+       je      int2
+       cmp     $3,a0l
+       je      int3
+       cmp     $4,a0l
+       je      int4
+       
+       mov     -5*8(itmp2),s0
+int4:   
+       mov     -4*8(itmp2),s1
+int3:   
+       mov     -3*8(itmp2),s2
+int2:   
+       mov     -2*8(itmp2),s3
+int1:   
+       mov     -1*8(itmp2),s4
+
+       shl     $3,a0l                      /* multiply by 8 bytes                */
+       sub     a0,itmp2
+               
+noint:
+#if 0
+       mov     FltSave(itmp3),a0l          /* a0l = saved flt register count     */
+       test    a0l,a0l
+       je      noflt
+       
+       cmpl    $1,a0l
+       je      flt1
+       cmpl    $2,a0l
+       je      flt2
+       cmpl    $3,a0l
+       je      flt3
+       cmpl    $4,a0l
+       je      flt4
+
+       movq    -5*8(itmp2),%xmm11
+flt4:   
+       movq    -4*8(itmp2),%xmm12
+flt3:   
+       movq    -3*8(itmp2),%xmm13
+flt2:   
+       movq    -2*8(itmp2),%xmm14
+flt1:   
+       movq    -1*8(itmp2),%xmm15
+                
+noflt:
+#endif
+       mov     FrameSize(itmp3),itmp2l     /* get frame size                     */
+       add     itmp2,sp                    /* unwind stack                       */
+
+                                           /* exception pointer is still set     */
+       pop     xpc                         /* the new xpc is return address      */
+       sub     $3,xpc                      /* subtract 3 bytes for call          */
+
+       xor     a3,a3                       /* prepare a3 for handle_exception    */
+       
+       jmp             L_asm_handle_exception_stack_loop
+
+
+/* asm_abstractmethoderror *****************************************************
+
+   Creates and throws an AbstractMethodError.
+
+*******************************************************************************/
+
+asm_abstractmethoderror:
+       mov     sp,a0                       /* pass java sp                       */
+       add     $1*8,a0
+       mov     0*8(sp),a1                  /* pass exception address             */
+       sub     $3,a1
+       call    exceptions_asm_new_abstractmethoderror@PLT
+                                           /* exception pointer is return value  */
+       pop     xpc                         /* get exception address              */
+       sub     $3,xpc                      /* exception address is ra - 3        */
+       jmp     L_asm_handle_exception
+
+
+/* asm_patcher_wrapper *********************************************************
+
+   XXX
+
+   Stack layout:
+     40   return address
+     32   pointer to virtual java_objectheader
+     24   machine code (which is patched back later)
+     16   unresolved class/method/field reference
+      8   data segment displacement from load instructions
+      0   pointer to patcher function
+     -8   bp
+
+*******************************************************************************/
+
+asm_patcher_wrapper:
+       push    bp                          /* save base pointer                  */
+       mov     sp,bp                       /* move actual sp to bp               */
+       sub     $((3+ARG_CNT+TMP_CNT)*8+sizestackframeinfo),sp
+       and     $0xfffffffffffffff0,sp      /* align sp to 16-byte (this is for   */
+                                           /* leaf functions)                    */
+
+       SAVE_ARGUMENT_REGISTERS(3)
+       SAVE_TEMPORARY_REGISTERS(3+ARG_CNT)
+
+       mov     itmp1,0*8(sp)               /* save itmp1 and itmp2               */
+       mov     itmp2,1*8(sp)               /* can be used by some instructions   */
+
+       mov     bp,a0                       /* pass SP of patcher stub            */
+       add     $(1*8),a0
+       mov     $0,a1                       /* pass PV (if NULL, use findmethod)  */
+       mov     $0,a2                       /* pass RA (it's on the stack)        */
+       call    patcher_wrapper@PLT
+       mov     v0,2*8(sp)                  /* save return value                  */
+
+       RESTORE_ARGUMENT_REGISTERS(3)
+       RESTORE_TEMPORARY_REGISTERS(3+ARG_CNT)
+
+       mov     0*8(sp),itmp1               /* restore itmp1 and itmp2            */
+       mov     1*8(sp),itmp2               /* can be used by some instructions   */
+       mov     2*8(sp),itmp3               /* restore return value               */
+
+       mov     bp,sp                       /* restore original sp                */
+       pop     bp                          /* restore bp                         */
+       add     $(5*8),sp                   /* remove patcher stackframe, keep RA */
+
+       test    itmp3,itmp3                 /* exception thrown?                  */
+       jne     L_asm_patcher_wrapper_exception
+       ret                                 /* call new patched code              */
+
+L_asm_patcher_wrapper_exception:
+       mov     itmp3,xptr                  /* get exception                      */
+       pop     xpc                         /* get and remove return address      */
+       jmp     L_asm_handle_exception
+
+
+/* asm_replacement_out *********************************************************
+
+   This code is jumped to from the replacement-out stubs that are executed
+   when a thread reaches an activated replacement point.
+
+   The purpose of asm_replacement_out is to read out the parts of the
+   execution state that cannot be accessed from C code, store this state,
+   and then call the C function replace_me.
+
+   Stack layout:
+      8                 start of stack inside method to replace
+      0   rplpoint *    info on the replacement point that was reached
+
+*******************************************************************************/
+
+/* some room to accomodate changes of the stack frame size during replacement */
+       /* XXX we should find a cleaner solution here */
+#define REPLACEMENT_ROOM  512
+
+asm_replacement_out:
+    /* create stack frame */
+       sub     $(sizeexecutionstate + REPLACEMENT_ROOM),sp
+
+       /* save registers in execution state */
+       mov     %rax,(RAX*8+offes_intregs)(sp)
+       mov     %rbx,(RBX*8+offes_intregs)(sp)
+       mov     %rcx,(RCX*8+offes_intregs)(sp)
+       mov     %rdx,(RDX*8+offes_intregs)(sp)
+       mov     %rsi,(RSI*8+offes_intregs)(sp)
+       mov     %rdi,(RDI*8+offes_intregs)(sp)
+       mov     %rbp,(RBP*8+offes_intregs)(sp)
+       movq    $0  ,(RSP*8+offes_intregs)(sp) /* not used */
+       mov     %r8 ,(R8 *8+offes_intregs)(sp)
+       mov     %r9 ,(R9 *8+offes_intregs)(sp)
+       mov     %r10,(R10*8+offes_intregs)(sp)
+       mov     %r11,(R11*8+offes_intregs)(sp)
+       mov     %r12,(R12*8+offes_intregs)(sp)
+       mov     %r13,(R13*8+offes_intregs)(sp)
+       mov     %r14,(R14*8+offes_intregs)(sp)
+       mov     %r15,(R15*8+offes_intregs)(sp)
+
+       movq    %xmm0 ,(XMM0 *8+offes_fltregs)(sp)
+       movq    %xmm1 ,(XMM1 *8+offes_fltregs)(sp)
+       movq    %xmm2 ,(XMM2 *8+offes_fltregs)(sp)
+       movq    %xmm3 ,(XMM3 *8+offes_fltregs)(sp)
+       movq    %xmm4 ,(XMM4 *8+offes_fltregs)(sp)
+       movq    %xmm5 ,(XMM5 *8+offes_fltregs)(sp)
+       movq    %xmm6 ,(XMM6 *8+offes_fltregs)(sp)
+       movq    %xmm7 ,(XMM7 *8+offes_fltregs)(sp)
+       movq    %xmm8 ,(XMM8 *8+offes_fltregs)(sp)
+       movq    %xmm9 ,(XMM9 *8+offes_fltregs)(sp)
+       movq    %xmm10,(XMM10*8+offes_fltregs)(sp)
+       movq    %xmm11,(XMM11*8+offes_fltregs)(sp)
+       movq    %xmm12,(XMM12*8+offes_fltregs)(sp)
+       movq    %xmm13,(XMM13*8+offes_fltregs)(sp)
+       movq    %xmm14,(XMM14*8+offes_fltregs)(sp)
+       movq    %xmm15,(XMM15*8+offes_fltregs)(sp)
+
+       /* calculate sp of method */
+       mov     sp,itmp1
+       add     $(sizeexecutionstate + REPLACEMENT_ROOM + 8),itmp1
+       mov     itmp1,(offes_sp)(sp)
+
+       /* pv must be looked up via AVL tree */
+       movq    $0,(offes_pv)(sp)
+
+       /* call replace_me */
+       mov     -8(itmp1),a0                /* rplpoint *                         */
+    mov     sp,a1                       /* arg1: execution state              */
+    call    replace_me@PLT              /* call C function replace_me         */
+    call    abort@PLT                   /* NEVER REACHED                      */
+
+/* asm_replacement_in **********************************************************
+
+   This code writes the given execution state and jumps to the replacement
+   code.
+
+   This function never returns!
+
+   C prototype:
+      void asm_replacement_in(executionstate *es);
+
+*******************************************************************************/
+
+asm_replacement_in:
+       mov     a0,%rbp                     /* executionstate *es                 */
+
+       /* set new sp */
+       mov     (offes_sp)(%rbp),%rsp
+       
+       /* store address of new code */
+       push    (offes_pc)(%rbp)
+       
+       /* copy registers from execution state */
+       movq    (XMM0 *8+offes_fltregs)(%rbp),%xmm0
+       movq    (XMM1 *8+offes_fltregs)(%rbp),%xmm1
+       movq    (XMM2 *8+offes_fltregs)(%rbp),%xmm2
+       movq    (XMM3 *8+offes_fltregs)(%rbp),%xmm3
+       movq    (XMM4 *8+offes_fltregs)(%rbp),%xmm4
+       movq    (XMM5 *8+offes_fltregs)(%rbp),%xmm5
+       movq    (XMM6 *8+offes_fltregs)(%rbp),%xmm6
+       movq    (XMM7 *8+offes_fltregs)(%rbp),%xmm7
+       movq    (XMM8 *8+offes_fltregs)(%rbp),%xmm8
+       movq    (XMM9 *8+offes_fltregs)(%rbp),%xmm9
+       movq    (XMM10*8+offes_fltregs)(%rbp),%xmm10
+       movq    (XMM11*8+offes_fltregs)(%rbp),%xmm11
+       movq    (XMM12*8+offes_fltregs)(%rbp),%xmm12
+       movq    (XMM13*8+offes_fltregs)(%rbp),%xmm13
+       movq    (XMM14*8+offes_fltregs)(%rbp),%xmm14
+       movq    (XMM15*8+offes_fltregs)(%rbp),%xmm15
+
+       mov     (RAX*8+offes_intregs)(%rbp),%rax
+       mov     (RBX*8+offes_intregs)(%rbp),%rbx
+       mov     (RCX*8+offes_intregs)(%rbp),%rcx
+       mov     (RDX*8+offes_intregs)(%rbp),%rdx
+       mov     (RSI*8+offes_intregs)(%rbp),%rsi
+       mov     (RDI*8+offes_intregs)(%rbp),%rdi
+       mov     (R8 *8+offes_intregs)(%rbp),%r8
+       mov     (R9 *8+offes_intregs)(%rbp),%r9
+       mov     (R10*8+offes_intregs)(%rbp),%r10
+       mov     (R11*8+offes_intregs)(%rbp),%r11
+       mov     (R12*8+offes_intregs)(%rbp),%r12
+       mov     (R13*8+offes_intregs)(%rbp),%r13
+       mov     (R14*8+offes_intregs)(%rbp),%r14
+       mov     (R15*8+offes_intregs)(%rbp),%r15
+
+       mov     (RBP*8+offes_intregs)(%rbp),%rbp
+
+       /* jump to new code */
+       ret
+
+
+/* asm_builtin_x2x *************************************************************
+*                                                                              *
+*   Wrapper functions for float to int corner cases                            *
+*                                                                              *
+*******************************************************************************/
+
+asm_builtin_f2i:
+       sub     $(ARG_CNT*8),sp
+       
+       SAVE_ARGUMENT_REGISTERS(0)
+       
+       movq    ftmp1,fa0
+       call    builtin_f2i@PLT
+       
+       RESTORE_ARGUMENT_REGISTERS(0)
+       
+       add     $(ARG_CNT*8),sp
+       ret
+
+
+asm_builtin_f2l:
+       sub     $(ARG_CNT*8),sp
+       
+       SAVE_ARGUMENT_REGISTERS(0)
+       
+       movq    ftmp1,fa0
+       call    builtin_f2l@PLT
+       
+       RESTORE_ARGUMENT_REGISTERS(0)
+       
+       add     $(ARG_CNT*8),sp
+       ret
+
+
+asm_builtin_d2i:
+       sub     $(ARG_CNT*8),sp
+       
+       SAVE_ARGUMENT_REGISTERS(0)
+       
+       movq    ftmp1,fa0
+       call    builtin_d2i@PLT
+       
+       RESTORE_ARGUMENT_REGISTERS(0)
+       
+       add     $(ARG_CNT*8),sp
+       ret
+
+
+asm_builtin_d2l:
+       sub     $(ARG_CNT*8),sp
+       
+       SAVE_ARGUMENT_REGISTERS(0)
+       
+       movq    ftmp1,fa0
+       call    builtin_d2l@PLT
+       
+       RESTORE_ARGUMENT_REGISTERS(0)
+       
+       add     $(ARG_CNT*8),sp
+       ret
+
+
+asm_getclassvalues_atomic:
+_crit_restart:
+_crit_begin:
+       movl    offbaseval(a0),itmp1l
+       movl    offdiffval(a0),itmp2l
+       movl    offbaseval(a1),itmp3l
+_crit_end:
+       movl    itmp1l,offcast_super_baseval(a2)
+       movl    itmp2l,offcast_super_diffval(a2)
+       movl    itmp3l,offcast_sub_baseval(a2)
+       ret
+
+       .data
+               
+asm_criticalsections:
+#if defined(ENABLE_THREADS)
+       .quad   _crit_begin
+       .quad   _crit_end
+       .quad   _crit_restart
+#endif
+       .quad 0
+
+
+/* Disable exec-stacks, required for Gentoo ***********************************/
+
+#if defined(__GCC__) && defined(__ELF__)
+       .section .note.GNU-stack,"",@progbits
+#endif
+
+
+#endif /* if 0 */
+
+/*
+ * 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: asm
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
diff --git a/src/vm/jit/s390/codegen.c b/src/vm/jit/s390/codegen.c
new file mode 100644 (file)
index 0000000..ff8e83c
--- /dev/null
@@ -0,0 +1,4088 @@
+/* src/vm/jit/x86_64/codegen.c - machine code generator for x86_64
+
+   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: Andreas Krall
+            Christian Thalinger
+            Christian Ullrich
+            Edwin Steiner
+
+   $Id: codegen.c 7219 2007-01-16 22:18:57Z pm $
+
+*/
+
+
+#include "config.h"
+
+#include <assert.h>
+#include <stdio.h>
+
+#include "vm/types.h"
+
+#include "md-abi.h"
+
+#include "vm/jit/s390/arch.h"
+#include "vm/jit/s390/codegen.h"
+#include "vm/jit/s390/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/loader.h"
+#include "vm/options.h"
+#include "vm/statistics.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/methodheader.h"
+#include "vm/jit/parse.h"
+#include "vm/jit/patcher.h"
+#include "vm/jit/reg.h"
+#include "vm/jit/replace.h"
+
+#if defined(ENABLE_LSRA)
+# include "vm/jit/allocator/lsra.h"
+#endif
+
+#define OOPS() assert(0);
+
+#if 0
+u1 *createcompilerstub(methodinfo *m) {
+       OOPS();
+       u1 *stub = malloc(8);
+       bzero(stub, 8);
+       return stub;
+}
+#endif
+
+#if 0
+u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd) {
+       OOPS();
+       return createcompilerstub(NULL);
+}
+#endif
+
+
+
+/* codegen *********************************************************************
+
+   Generates machine code.
+
+*******************************************************************************/
+
+
+bool codegen(jitdata *jd)
+{
+       methodinfo         *m;
+       codeinfo           *code;
+       codegendata        *cd;
+       registerdata       *rd;
+       s4                  len, s1, s2, s3, d, disp;
+       u2                  currentline;
+       ptrint              a;
+       varinfo            *var, *var1, *var2, *dst;
+       basicblock         *bptr;
+       instruction        *iptr;
+       exception_entry    *ex;
+       constant_classref  *cr;
+       unresolved_class   *uc;
+       methodinfo         *lm;             /* local methodinfo for ICMD_INVOKE*  */
+       unresolved_method  *um;
+       builtintable_entry *bte;
+       methoddesc         *md;
+       fieldinfo          *fi;
+       unresolved_field   *uf;
+       s4                  fieldtype;
+       rplpoint           *replacementpoint;
+       s4                 varindex;
+
+       /* get required compiler data */
+
+       m    = jd->m;
+       code = jd->code;
+       cd   = jd->cd;
+       rd   = jd->rd;
+
+       /* prevent compiler warnings */
+
+       d   = 0;
+       lm  = NULL;
+       um  = NULL;
+       bte = NULL;
+
+       {
+       s4 i, p, t, l;
+       s4 savedregs_num;
+
+       savedregs_num = 0;
+
+       /* space to save used callee saved registers */
+
+       savedregs_num += (INT_SAV_CNT - rd->savintreguse);
+       savedregs_num += (FLT_SAV_CNT - rd->savfltreguse);
+
+       cd->stackframesize = rd->memuse + savedregs_num;
+
+#if defined(ENABLE_THREADS)
+       /* space to save argument of monitor_enter */
+
+       if (checksync && (m->flags & ACC_SYNCHRONIZED))
+               cd->stackframesize++;
+#endif
+
+       /* Keep stack of non-leaf functions 16-byte aligned for calls into
+          native code e.g. libc or jni (alignment problems with
+          movaps). */
+
+       if (!jd->isleafmethod || opt_verbosecall)
+               cd->stackframesize |= 0x1;
+
+       /* create method header */
+
+       (void) dseg_add_unique_address(cd, code);              /* CodeinfoPointer */
+       (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize       */
+
+#if defined(ENABLE_THREADS)
+       /* IsSync contains the offset relative to the stack pointer for the
+          argument of monitor_exit used in the exception handler. Since the
+          offset could be zero and give a wrong meaning of the flag it is
+          offset by one.
+       */
+
+       if (checksync && (m->flags & ACC_SYNCHRONIZED))
+               (void) dseg_add_unique_s4(cd, (rd->memuse + 1) * 8); /* 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 */
+
+       (void) 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);
+       }
+       
+       /* generate method profiling code */
+
+       if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
+               /* count frequency */
+
+               M_MOV_IMM(code, REG_ITMP3);
+               M_IINC_MEMBASE(REG_ITMP3, OFFSET(codeinfo, frequency));
+
+               PROFILE_CYCLE_START;
+       }
+
+       /* create stack frame (if necessary) */
+
+       if (cd->stackframesize)
+               M_ASUB_IMM(cd->stackframesize * 8, REG_SP);
+
+       /* save used callee saved registers */
+
+       p = cd->stackframesize;
+       for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
+               p--; M_LST(rd->savintregs[i], REG_SP, p * 8);
+       }
+       for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
+               p--; M_DST(rd->savfltregs[i], REG_SP, p * 8);
+       }
+
+       /* take arguments out of register or 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;
+
+               if (IS_INT_LNG_TYPE(t)) {                    /* integer args          */
+                       s2 = rd->argintregs[s1];
+                       if (!md->params[p].inmemory) {           /* register arguments    */
+                               if (!IS_INMEMORY(var->flags)) {      /* reg arg -> register   */
+                                       M_INTMOVE(s2, var->vv.regoff);
+
+                               } else {                             /* reg arg -> spilled    */
+                                   M_LST(s2, REG_SP, var->vv.regoff * 8);
+                               }
+
+                       } else {                                 /* stack arguments       */
+                               if (!IS_INMEMORY(var->flags)) {      /* stack arg -> register */
+                                       /* + 8 for return address */
+                                       M_LLD(var->vv.regoff, REG_SP, (cd->stackframesize + s1) * 8 + 8);
+
+                               } else {                             /* stack arg -> spilled  */
+                                       var->vv.regoff = cd->stackframesize + s1 + 1;
+                               }
+                       }
+
+               } else {                                     /* floating args         */
+                       if (!md->params[p].inmemory) {           /* register arguments    */
+                               s2 = rd->argfltregs[s1];
+                               if (!IS_INMEMORY(var->flags)) {      /* reg arg -> register   */
+                                       M_FLTMOVE(s2, var->vv.regoff);
+
+                               } else {                                         /* reg arg -> spilled    */
+                                       M_DST(s2, REG_SP, var->vv.regoff * 8);
+                               }
+
+                       } else {                                 /* stack arguments       */
+                               if (!IS_INMEMORY(var->flags)) {      /* stack-arg -> register */
+                                       M_DLD(var->vv.regoff, REG_SP, (cd->stackframesize + s1) * 8 + 8);
+
+                               } else {
+                                       var->vv.regoff = cd->stackframesize + s1 + 1;
+                               }
+                       }
+               }
+       }  /* end for */
+
+       /* save monitorenter argument */
+
+#if defined(ENABLE_THREADS)
+       if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
+               /* stack offset for monitor argument */
+
+               s1 = rd->memuse;
+
+               if (opt_verbosecall) {
+                       M_LSUB_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
+
+                       for (p = 0; p < INT_ARG_CNT; p++)
+                               M_LST(rd->argintregs[p], REG_SP, p * 8);
+
+                       for (p = 0; p < FLT_ARG_CNT; p++)
+                               M_DST(rd->argfltregs[p], REG_SP, (INT_ARG_CNT + p) * 8);
+
+                       s1 += INT_ARG_CNT + FLT_ARG_CNT;
+               }
+
+               /* decide which monitor enter function to call */
+
+               if (m->flags & ACC_STATIC) {
+                       M_MOV_IMM(&m->class->object.header, REG_A0);
+               }
+               else {
+                       M_TEST(REG_A0);
+                       M_BEQ(0);
+                       codegen_add_nullpointerexception_ref(cd);
+               }
+
+               M_AST(REG_A0, REG_SP, s1 * 8);
+               M_MOV_IMM(LOCK_monitor_enter, REG_ITMP1);
+               M_CALL(REG_ITMP1);
+
+               if (opt_verbosecall) {
+                       for (p = 0; p < INT_ARG_CNT; p++)
+                               M_LLD(rd->argintregs[p], REG_SP, p * 8);
+
+                       for (p = 0; p < FLT_ARG_CNT; p++)
+                               M_DLD(rd->argfltregs[p], REG_SP, (INT_ARG_CNT + p) * 8);
+
+                       M_LADD_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
+               }
+       }
+#endif
+
+#if !defined(NDEBUG)
+       if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
+               emit_verbosecall_enter(jd);
+#endif /* !defined(NDEBUG) */
+
+       }
+
+       /* end of header generation */
+
+       replacementpoint = jd->code->rplpoints;
+
+       /* walk through all basic blocks */
+
+       for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
+
+               bptr->mpc = (u4) ((u1 *) cd->mcodeptr - cd->mcodebase);
+
+               if (bptr->flags >= BBREACHED) {
+
+               /* branch resolving */
+
+               codegen_resolve_branchrefs(cd, bptr);
+
+               /* handle replacement points */
+
+#if 0
+               if (bptr->bitflags & BBFLAG_REPLACEMENT) {
+                       replacementpoint->pc = (u1*)(ptrint)bptr->mpc; /* will be resolved later */
+                       
+                       replacementpoint++;
+
+                       assert(cd->lastmcodeptr <= cd->mcodeptr);
+                       cd->lastmcodeptr = cd->mcodeptr + 5; /* 5 byte jmp patch */
+               }
+#endif
+
+               /* copy interface registers to their destination */
+
+               len = bptr->indepth;
+               MCODECHECK(512);
+
+               /* generate basicblock profiling code */
+
+               if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
+                       /* count frequency */
+
+                       M_MOV_IMM(code->bbfrequency, REG_ITMP3);
+                       M_IINC_MEMBASE(REG_ITMP3, bptr->nr * 4);
+
+                       /* if this is an exception handler, start profiling again */
+
+                       if (bptr->type == BBTYPE_EXH)
+                               PROFILE_CYCLE_START;
+               }
+
+#if defined(ENABLE_LSRA)
+               if (opt_lsra) {
+                       while (len) {
+                               len--;
+                               src = bptr->invars[len];
+                               if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
+                                       if (bptr->type == BBTYPE_EXH) {
+/*                                     d = reg_of_var(rd, src, REG_ITMP1); */
+                                               if (!IS_INMEMORY(src->flags))
+                                                       d= src->vv.regoff;
+                                               else
+                                                       d=REG_ITMP1;
+                                               M_INTMOVE(REG_ITMP1, d);
+                                               emit_store(jd, NULL, src, d);
+                                       }
+                               }
+                       }
+                       
+               } else {
+#endif
+
+               while (len) {
+                       len--;
+                       var = VAR(bptr->invars[len]);
+                       if ((len ==  bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
+                               if (bptr->type == BBTYPE_EXH) {
+                                       d = codegen_reg_of_var(0, var, REG_ITMP1);
+                                       M_INTMOVE(REG_ITMP1, d);
+                                       emit_store(jd, NULL, var, d);
+                               }
+                       } 
+                       else {
+                               assert((var->flags & INOUT));
+                       }
+               }
+#if defined(ENABLE_LSRA)
+               }
+#endif
+               /* 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  ==> ...                   */
+               case ICMD_INLINE_START: /* internal ICMDs                         */
+               case ICMD_INLINE_END:
+                       break;
+
+               case ICMD_CHECKNULL:  /* ..., objectref  ==> ..., objectref           */
+                       OOPS();
+#if 0
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       M_TEST(s1);
+                       M_BEQ(0);
+                       codegen_add_nullpointerexception_ref(cd);
+#endif
+                       break;
+
+               /* constant operations ************************************************/
+
+               case ICMD_ICONST:     /* ...  ==> ..., constant                       */
+                       OOPS();
+#if 0
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+                       ICONST(d, iptr->sx.val.i);
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       break;
+
+               case ICMD_LCONST:     /* ...  ==> ..., constant                       */
+                       OOPS();
+#if 0
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+                       LCONST(d, iptr->sx.val.l);
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       break;
+
+               case ICMD_FCONST:     /* ...  ==> ..., constant                       */
+                       OOPS();
+#if 0
+                       d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
+                       disp = dseg_add_float(cd, iptr->sx.val.f);
+                       emit_movdl_membase_reg(cd, RIP, -((cd->mcodeptr + ((d > 7) ? 9 : 8)) - cd->mcodebase) + disp, d);
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       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);
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       break;
+
+               case ICMD_ACONST:     /* ...  ==> ..., constant                       */
+                       OOPS();
+#if 0
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                               cr = iptr->sx.val.c.ref;
+
+/*                             PROFILE_CYCLE_STOP; */
+
+                               codegen_add_patch_ref(cd, PATCHER_aconst, cr, 0);
+
+/*                             PROFILE_CYCLE_START; */
+
+                               M_MOV_IMM(NULL, d);
+
+                       } else {
+                               if (iptr->sx.val.anyptr == 0)
+                                       M_CLR(d);
+                               else
+                                       M_MOV_IMM(iptr->sx.val.anyptr, d);
+                       }
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       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:
+                       OOPS();
+#if 0          
+                       emit_copy(jd, iptr, VAROP(iptr->s1), VAROP(iptr->dst));
+#endif
+                       break;
+
+               case ICMD_ASTORE:
+                       OOPS();
+#if 0
+                       if (!(iptr->flags.bits & INS_FLAG_RETADDR))
+                               emit_copy(jd, iptr, VAROP(iptr->s1), VAROP(iptr->dst));
+#endif
+                       break;
+
+               /* integer operations *************************************************/
+
+               case ICMD_INEG:       /* ..., value  ==> ..., - value                 */
+                       OOPS();
+#if 0
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1); 
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+                       M_INTMOVE(s1, d);
+                       M_INEG(d);
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       break;
+
+               case ICMD_LNEG:       /* ..., value  ==> ..., - value                 */
+                       OOPS();
+#if 0
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1); 
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+                       M_INTMOVE(s1, d);
+                       M_LNEG(d);
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       break;
+
+               case ICMD_I2L:        /* ..., value  ==> ..., value                   */
+                       OOPS();
+#if 0
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
+                       M_ISEXT(s1, d);
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       break;
+
+               case ICMD_L2I:        /* ..., value  ==> ..., value                   */
+                       OOPS();
+#if 0
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+                       M_IMOV(s1, d);
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       break;
+
+               case ICMD_INT2BYTE:   /* ..., value  ==> ..., value                   */
+                       OOPS();
+#if 0
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
+                       M_BSEXT(s1, d);
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       break;
+
+               case ICMD_INT2CHAR:   /* ..., value  ==> ..., value                   */
+                       OOPS();
+#if 0
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
+                       M_CZEXT(s1, d);
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       break;
+
+               case ICMD_INT2SHORT:  /* ..., value  ==> ..., value                   */
+                       OOPS();
+#if 0
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
+                       M_SSEXT(s1, d);
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       break;
+
+
+               case ICMD_IADD:       /* ..., 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_IADD(s1, d);
+                       else {
+                               M_INTMOVE(s1, d);
+                               M_IADD(s2, d);
+                       }
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       break;
+
+               case ICMD_IINC:
+               case ICMD_IADDCONST:  /* ..., value  ==> ..., value + constant        */
+                                     /* sx.val.i = constant                             */
+                       OOPS();
+#if 0
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+
+                       /* Using inc and dec is not faster than add (tested with
+                          sieve). */
+
+                       M_INTMOVE(s1, d);
+                       M_IADD_IMM(iptr->sx.val.i, d);
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       break;
+
+               case ICMD_LADD:       /* ..., 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_LADD(s1, d);
+                       else {
+                               M_INTMOVE(s1, d);
+                               M_LADD(s2, d);
+                       }
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       break;
+
+               case ICMD_LADDCONST:  /* ..., value  ==> ..., value + constant        */
+                                     /* sx.val.l = constant                             */
+                       OOPS();
+#if 0
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+                       M_INTMOVE(s1, d);
+                       if (IS_IMM32(iptr->sx.val.l))
+                               M_LADD_IMM(iptr->sx.val.l, d);
+                       else {
+                               M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
+                               M_LADD(REG_ITMP2, d);
+                       }
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       break;
+
+               case ICMD_ISUB:       /* ..., 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_INTMOVE(s1, REG_ITMP1);
+                               M_ISUB(s2, REG_ITMP1);
+                               M_INTMOVE(REG_ITMP1, d);
+                       } else {
+                               M_INTMOVE(s1, d);
+                               M_ISUB(s2, d);
+                       }
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       break;
+
+               case ICMD_ISUBCONST:  /* ..., value  ==> ..., value + constant        */
+                                     /* sx.val.i = constant                             */
+                       OOPS();
+#if 0
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+                       M_INTMOVE(s1, d);
+                       M_ISUB_IMM(iptr->sx.val.i, d);
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       break;
+
+               case ICMD_LSUB:       /* ..., 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_INTMOVE(s1, REG_ITMP1);
+                               M_LSUB(s2, REG_ITMP1);
+                               M_INTMOVE(REG_ITMP1, d);
+                       } else {
+                               M_INTMOVE(s1, d);
+                               M_LSUB(s2, d);
+                       }
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       break;
+
+               case ICMD_LSUBCONST:  /* ..., value  ==> ..., value - constant        */
+                                     /* sx.val.l = constant                             */
+                       OOPS();
+#if 0
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+                       M_INTMOVE(s1, d);
+                       if (IS_IMM32(iptr->sx.val.l))
+                               M_LSUB_IMM(iptr->sx.val.l, d);
+                       else {
+                               M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
+                               M_LSUB(REG_ITMP2, d);
+                       }
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       break;
+
+               case ICMD_IMUL:       /* ..., 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_IMUL(s1, d);
+                       else {
+                               M_INTMOVE(s1, d);
+                               M_IMUL(s2, d);
+                       }
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       break;
+
+               case ICMD_IMULCONST:  /* ..., value  ==> ..., value * constant        */
+                                     /* sx.val.i = constant                             */
+                       OOPS();
+#if 0
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+                       if (iptr->sx.val.i == 2) {
+                               M_INTMOVE(s1, d);
+                               M_ISLL_IMM(1, d);
+                       } else
+                               M_IMUL_IMM(s1, iptr->sx.val.i, d);
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       break;
+
+               case ICMD_LMUL:       /* ..., 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_LMUL(s1, d);
+                       else {
+                               M_INTMOVE(s1, d);
+                               M_LMUL(s2, d);
+                       }
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       break;
+
+               case ICMD_LMULCONST:  /* ..., value  ==> ..., value * constant        */
+                                     /* sx.val.l = constant                             */
+                       OOPS();
+#if 0
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+                       if (IS_IMM32(iptr->sx.val.l))
+                               M_LMUL_IMM(s1, iptr->sx.val.l, d);
+                       else {
+                               M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
+                               M_INTMOVE(s1, d);
+                               M_LMUL(REG_ITMP2, d);
+                       }
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       break;
+
+               case ICMD_IDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
+                       OOPS();
+#if 0
+                       var1 = VAROP(iptr->s1);
+                       var2 = VAROP(iptr->sx.s23.s2);
+                       dst  = VAROP(iptr->dst);
+
+                       d = codegen_reg_of_dst(jd, iptr, REG_NULL);
+                       if (IS_INMEMORY(var1->flags))
+                               M_ILD(RAX, REG_SP, var1->vv.regoff * 8);
+                       else
+                               M_INTMOVE(var1->vv.regoff, RAX);
+                       
+                       if (IS_INMEMORY(var2->flags))
+                               M_ILD(REG_ITMP3, REG_SP, var2->vv.regoff * 8);
+                       else
+                               M_INTMOVE(var2->vv.regoff, REG_ITMP3);
+                       
+                       if (checknull) {
+                               M_ITEST(REG_ITMP3);
+                               M_BEQ(0);
+                               codegen_add_arithmeticexception_ref(cd);
+                       }
+
+                       emit_alul_imm_reg(cd, ALU_CMP, 0x80000000, RAX); /* check as described in jvm spec */
+                       emit_jcc(cd, CC_NE, 4 + 6);
+                       emit_alul_imm_reg(cd, ALU_CMP, -1, REG_ITMP3);    /* 4 bytes */
+                       emit_jcc(cd, CC_E, 3 + 1 + 3);                /* 6 bytes */
+
+                       emit_mov_reg_reg(cd, RDX, REG_ITMP2); /* save %rdx, cause it's an argument register */
+                       emit_cltd(cd);
+                       emit_idivl_reg(cd, REG_ITMP3);
+
+                       if (IS_INMEMORY(dst->flags)) {
+                               emit_mov_reg_membase(cd, RAX, REG_SP, dst->vv.regoff * 8);
+                               emit_mov_reg_reg(cd, REG_ITMP2, RDX);       /* restore %rdx */
+
+                       } else {
+                               M_INTMOVE(RAX, dst->vv.regoff);
+
+                               if (dst->vv.regoff != RDX) {
+                                       emit_mov_reg_reg(cd, REG_ITMP2, RDX);   /* restore %rdx */
+                               }
+                       }
+#endif
+                       break;
+
+               case ICMD_IREM:       /* ..., val1, val2  ==> ..., val1 % val2        */
+                       OOPS();
+#if 0
+                       var1 = VAROP(iptr->s1);
+                       var2 = VAROP(iptr->sx.s23.s2);
+                       dst  = VAROP(iptr->dst);
+
+                       d = codegen_reg_of_dst(jd, iptr, REG_NULL);
+                       if (IS_INMEMORY(var1->flags))
+                               M_ILD(RAX, REG_SP, var1->vv.regoff * 8);
+                       else
+                               M_INTMOVE(var1->vv.regoff, RAX);
+                       
+                       if (IS_INMEMORY(var2->flags))
+                               M_ILD(REG_ITMP3, REG_SP, var2->vv.regoff * 8);
+                       else
+                               M_INTMOVE(var2->vv.regoff, REG_ITMP3);
+
+                       if (checknull) {
+                               M_ITEST(REG_ITMP3);
+                               M_BEQ(0);
+                               codegen_add_arithmeticexception_ref(cd);
+                       }
+
+                       emit_mov_reg_reg(cd, RDX, REG_ITMP2); /* save %rdx, cause it's an argument register */
+
+                       emit_alul_imm_reg(cd, ALU_CMP, 0x80000000, RAX); /* check as described in jvm spec */
+                       emit_jcc(cd, CC_NE, 2 + 4 + 6);
+
+
+                       emit_alul_reg_reg(cd, ALU_XOR, RDX, RDX);         /* 2 bytes */
+                       emit_alul_imm_reg(cd, ALU_CMP, -1, REG_ITMP3);    /* 4 bytes */
+                       emit_jcc(cd, CC_E, 1 + 3);                    /* 6 bytes */
+
+                       emit_cltd(cd);
+                       emit_idivl_reg(cd, REG_ITMP3);
+
+                       if (IS_INMEMORY(dst->flags)) {
+                               emit_mov_reg_membase(cd, RDX, REG_SP, dst->vv.regoff * 8);
+                               emit_mov_reg_reg(cd, REG_ITMP2, RDX);       /* restore %rdx */
+
+                       } else {
+                               M_INTMOVE(RDX, dst->vv.regoff);
+
+                               if (dst->vv.regoff != RDX) {
+                                       emit_mov_reg_reg(cd, REG_ITMP2, RDX);   /* restore %rdx */
+                               }
+                       }
+#endif
+                       break;
+
+               case ICMD_IDIVPOW2:   /* ..., value  ==> ..., value >> constant       */
+                                     /* sx.val.i = constant                             */
+                       OOPS();
+#if 0
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
+                       M_INTMOVE(s1, REG_ITMP1);
+                       emit_alul_imm_reg(cd, ALU_CMP, -1, REG_ITMP1);
+                       emit_leal_membase_reg(cd, REG_ITMP1, (1 << iptr->sx.val.i) - 1, REG_ITMP2);
+                       emit_cmovccl_reg_reg(cd, CC_LE, REG_ITMP2, REG_ITMP1);
+                       emit_shiftl_imm_reg(cd, SHIFT_SAR, iptr->sx.val.i, REG_ITMP1);
+                       emit_mov_reg_reg(cd, REG_ITMP1, d);
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       break;
+
+               case ICMD_IREMPOW2:   /* ..., value  ==> ..., value % constant        */
+                                     /* sx.val.i = constant                             */
+                       OOPS();
+#if 0
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
+                       M_INTMOVE(s1, REG_ITMP1);
+                       emit_alul_imm_reg(cd, ALU_CMP, -1, REG_ITMP1);
+                       emit_leal_membase_reg(cd, REG_ITMP1, iptr->sx.val.i, REG_ITMP2);
+                       emit_cmovccl_reg_reg(cd, CC_G, REG_ITMP1, REG_ITMP2);
+                       emit_alul_imm_reg(cd, ALU_AND, -1 - (iptr->sx.val.i), REG_ITMP2);
+                       emit_alul_reg_reg(cd, ALU_SUB, REG_ITMP2, REG_ITMP1);
+                       emit_mov_reg_reg(cd, REG_ITMP1, d);
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       break;
+
+
+               case ICMD_LDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
+                       OOPS();
+#if 0
+                       var1 = VAROP(iptr->s1);
+                       var2 = VAROP(iptr->sx.s23.s2);
+                       dst  = VAROP(iptr->dst);
+
+                       d = codegen_reg_of_dst(jd, iptr, REG_NULL);
+
+               if (IS_INMEMORY(var1->flags))
+                               M_LLD(RAX, REG_SP, var1->vv.regoff * 8);
+                       else
+                               M_INTMOVE(var1->vv.regoff, RAX);
+                       
+                       if (IS_INMEMORY(var2->flags))
+                               M_LLD(REG_ITMP3, REG_SP, var2->vv.regoff * 8);
+                       else
+                               M_INTMOVE(var2->vv.regoff, REG_ITMP3);
+
+                       if (checknull) {
+                               M_TEST(REG_ITMP3);
+                               M_BEQ(0);
+                               codegen_add_arithmeticexception_ref(cd);
+                       }
+
+                       /* check as described in jvm spec */
+                       disp = dseg_add_s8(cd, 0x8000000000000000LL);
+                       M_LCMP_MEMBASE(RIP, -((cd->mcodeptr + 7) - cd->mcodebase) + disp, RAX);
+                       M_BNE(4 + 6);
+                       M_LCMP_IMM(-1, REG_ITMP3);                              /* 4 bytes */
+                       M_BEQ(3 + 2 + 3);                                      /* 6 bytes */
+
+                       M_MOV(RDX, REG_ITMP2); /* save %rdx, cause it's an argument register */
+                       emit_cqto(cd);
+                       emit_idiv_reg(cd, REG_ITMP3);
+
+                       if (IS_INMEMORY(dst->flags)) {
+                               M_LST(RAX, REG_SP, dst->vv.regoff * 8);
+                               M_MOV(REG_ITMP2, RDX);                        /* restore %rdx */
+
+                       } else {
+                               M_INTMOVE(RAX, dst->vv.regoff);
+
+                               if (dst->vv.regoff != RDX) {
+                                       M_MOV(REG_ITMP2, RDX);                    /* restore %rdx */
+                               }
+                       }
+#endif
+                       break;
+
+               case ICMD_LREM:       /* ..., val1, val2  ==> ..., val1 % val2        */
+                       OOPS();
+#if 0
+                       var1 = VAROP(iptr->s1);
+                       var2 = VAROP(iptr->sx.s23.s2);
+                       dst  = VAROP(iptr->dst);
+
+                       d = codegen_reg_of_dst(jd, iptr, REG_NULL);
+                       
+                       if (IS_INMEMORY(var1->flags))
+                               M_LLD(REG_ITMP1, REG_SP, var1->vv.regoff * 8);
+                       else
+                               M_INTMOVE(var1->vv.regoff, REG_ITMP1);
+                       
+                       if (IS_INMEMORY(var2->flags))
+                               M_LLD(REG_ITMP3, REG_SP, var2->vv.regoff * 8);
+                       else
+                               M_INTMOVE(var2->vv.regoff, REG_ITMP3);
+                       /*
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       M_INTMOVE(s1, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP3);
+                       M_INTMOVE(s2, REG_ITMP3);
+                       */
+                       if (checknull) {
+                               M_ITEST(REG_ITMP3);
+                               M_BEQ(0);
+                               codegen_add_arithmeticexception_ref(cd);
+                       }
+
+                       M_MOV(RDX, REG_ITMP2); /* save %rdx, cause it's an argument register */
+
+                       /* check as described in jvm spec */
+                       disp = dseg_add_s8(cd, 0x8000000000000000LL);
+                       M_LCMP_MEMBASE(RIP, -((cd->mcodeptr + 7) - cd->mcodebase) + disp, REG_ITMP1);
+                       M_BNE(3 + 4 + 6);
+
+#if 0
+                       emit_alul_reg_reg(cd, ALU_XOR, RDX, RDX);         /* 2 bytes */
+#endif
+                       M_LXOR(RDX, RDX);                                      /* 3 bytes */
+                       M_LCMP_IMM(-1, REG_ITMP3);                              /* 4 bytes */
+                       M_BEQ(2 + 3);                                          /* 6 bytes */
+
+                       emit_cqto(cd);
+                       emit_idiv_reg(cd, REG_ITMP3);
+
+                       if (IS_INMEMORY(dst->flags)) {
+                               M_LST(RDX, REG_SP, dst->vv.regoff * 8);
+                               M_MOV(REG_ITMP2, RDX);                        /* restore %rdx */
+
+                       } else {
+                               M_INTMOVE(RDX, dst->vv.regoff);
+
+                               if (dst->vv.regoff != RDX) {
+                                       M_MOV(REG_ITMP2, RDX);                    /* restore %rdx */
+                               }
+                       }
+#endif
+                       break;
+
+               case ICMD_LDIVPOW2:   /* ..., value  ==> ..., value >> constant       */
+                                     /* sx.val.i = constant                             */
+                       OOPS();
+#if 0
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
+                       M_INTMOVE(s1, REG_ITMP1);
+                       emit_alu_imm_reg(cd, ALU_CMP, -1, REG_ITMP1);
+                       emit_lea_membase_reg(cd, REG_ITMP1, (1 << iptr->sx.val.i) - 1, REG_ITMP2);
+                       emit_cmovcc_reg_reg(cd, CC_LE, REG_ITMP2, REG_ITMP1);
+                       emit_shift_imm_reg(cd, SHIFT_SAR, iptr->sx.val.i, REG_ITMP1);
+                       emit_mov_reg_reg(cd, REG_ITMP1, d);
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       break;
+
+               case ICMD_LREMPOW2:   /* ..., value  ==> ..., value % constant        */
+                                     /* sx.val.l = constant                             */
+                       OOPS();
+#if 0
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
+                       M_INTMOVE(s1, REG_ITMP1);
+                       emit_alu_imm_reg(cd, ALU_CMP, -1, REG_ITMP1);
+                       emit_lea_membase_reg(cd, REG_ITMP1, iptr->sx.val.i, REG_ITMP2);
+                       emit_cmovcc_reg_reg(cd, CC_G, REG_ITMP1, REG_ITMP2);
+                       emit_alu_imm_reg(cd, ALU_AND, -1 - (iptr->sx.val.i), REG_ITMP2);
+                       emit_alu_reg_reg(cd, ALU_SUB, REG_ITMP2, REG_ITMP1);
+                       emit_mov_reg_reg(cd, REG_ITMP1, d);
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       break;
+
+               case ICMD_ISHL:       /* ..., val1, val2  ==> ..., val1 << val2       */
+                       OOPS();
+#if 0
+                       d = codegen_reg_of_dst(jd, iptr, REG_NULL);
+                       emit_ishift(jd, SHIFT_SHL, iptr);
+#endif
+                       break;
+
+               case ICMD_ISHLCONST:  /* ..., value  ==> ..., value << constant       */
+                                     /* sx.val.i = constant                             */
+                       OOPS();
+#if 0
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+                       M_INTMOVE(s1, d);
+                       M_ISLL_IMM(iptr->sx.val.i, d);
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       break;
+
+               case ICMD_ISHR:       /* ..., val1, val2  ==> ..., val1 >> val2       */
+                       OOPS();
+#if 0
+                       d = codegen_reg_of_dst(jd, iptr, REG_NULL);
+                       emit_ishift(jd, SHIFT_SAR, iptr);
+#endif
+                       break;
+
+               case ICMD_ISHRCONST:  /* ..., value  ==> ..., value >> constant       */
+                                     /* sx.val.i = constant                             */
+                       OOPS();
+#if 0
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+                       M_INTMOVE(s1, d);
+                       M_ISRA_IMM(iptr->sx.val.i, d);
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       break;
+
+               case ICMD_IUSHR:      /* ..., val1, val2  ==> ..., val1 >>> val2      */
+                       OOPS();
+#if 0
+                       d = codegen_reg_of_dst(jd, iptr, REG_NULL);
+                       emit_ishift(jd, SHIFT_SHR, iptr);
+#endif
+                       break;
+
+               case ICMD_IUSHRCONST: /* ..., value  ==> ..., value >>> constant      */
+                                     /* sx.val.i = constant                             */
+                       OOPS();
+#if 0
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+                       M_INTMOVE(s1, d);
+                       M_ISRL_IMM(iptr->sx.val.i, d);
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       break;
+
+               case ICMD_LSHL:       /* ..., val1, val2  ==> ..., val1 << val2       */
+                       OOPS();
+#if 0
+                       d = codegen_reg_of_dst(jd, iptr, REG_NULL);
+                       emit_lshift(jd, SHIFT_SHL, iptr);
+#endif
+                       break;
+
+        case ICMD_LSHLCONST:  /* ..., value  ==> ..., value << constant       */
+                                         /* sx.val.i = constant                             */
+                       OOPS();
+#if 0
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+                       M_INTMOVE(s1, d);
+                       M_LSLL_IMM(iptr->sx.val.i, d);
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       break;
+
+               case ICMD_LSHR:       /* ..., val1, val2  ==> ..., val1 >> val2       */
+                       OOPS();
+#if 0
+                       d = codegen_reg_of_dst(jd, iptr, REG_NULL);
+                       emit_lshift(jd, SHIFT_SAR, iptr);
+#endif
+                       break;
+
+               case ICMD_LSHRCONST:  /* ..., value  ==> ..., value >> constant       */
+                                     /* sx.val.i = constant                             */
+                       OOPS();
+#if 0
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+                       M_INTMOVE(s1, d);
+                       M_LSRA_IMM(iptr->sx.val.i, d);
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       break;
+
+               case ICMD_LUSHR:      /* ..., val1, val2  ==> ..., val1 >>> val2      */
+                       OOPS();
+#if 0
+                       d = codegen_reg_of_dst(jd, iptr, REG_NULL);
+                       emit_lshift(jd, SHIFT_SHR, iptr);
+#endif
+                       break;
+
+               case ICMD_LUSHRCONST: /* ..., value  ==> ..., value >>> constant      */
+                                     /* sx.val.l = constant                             */
+                       OOPS();
+#if 0
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+                       M_INTMOVE(s1, d);
+                       M_LSRL_IMM(iptr->sx.val.i, d);
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       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);
+                       if (s2 == d)
+                               M_IAND(s1, d);
+                       else {
+                               M_INTMOVE(s1, d);
+                               M_IAND(s2, d);
+                       }
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       break;
+
+               case ICMD_IANDCONST:  /* ..., value  ==> ..., value & constant        */
+                                     /* sx.val.i = constant                             */
+                       OOPS();
+#if 0
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+                       M_INTMOVE(s1, d);
+                       M_IAND_IMM(iptr->sx.val.i, d);
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       break;
+
+               case ICMD_LAND:       /* ..., 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_LAND(s1, d);
+                       else {
+                               M_INTMOVE(s1, d);
+                               M_LAND(s2, d);
+                       }
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       break;
+
+               case ICMD_LANDCONST:  /* ..., value  ==> ..., value & constant        */
+                                     /* sx.val.l = constant                             */
+                       OOPS();
+#if 0
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+                       M_INTMOVE(s1, d);
+                       if (IS_IMM32(iptr->sx.val.l))
+                               M_LAND_IMM(iptr->sx.val.l, d);
+                       else {
+                               M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
+                               M_LAND(REG_ITMP2, d);
+                       }
+                       emit_store_dst(jd, iptr, d);
+#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();
+#if 0
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+                       M_INTMOVE(s1, d);
+                       M_IOR_IMM(iptr->sx.val.i, d);
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       break;
+
+               case ICMD_LOR:        /* ..., 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_LOR(s1, d);
+                       else {
+                               M_INTMOVE(s1, d);
+                               M_LOR(s2, d);
+                       }
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       break;
+
+               case ICMD_LORCONST:   /* ..., value  ==> ..., value | constant        */
+                                     /* sx.val.l = constant                             */
+                       OOPS();
+#if 0
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+                       M_INTMOVE(s1, d);
+                       if (IS_IMM32(iptr->sx.val.l))
+                               M_LOR_IMM(iptr->sx.val.l, d);
+                       else {
+                               M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
+                               M_LOR(REG_ITMP2, d);
+                       }
+                       emit_store_dst(jd, iptr, d);
+#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();
+#if 0
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+                       M_INTMOVE(s1, d);
+                       M_IXOR_IMM(iptr->sx.val.i, d);
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       break;
+
+               case ICMD_LXOR:       /* ..., 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_LXOR(s1, d);
+                       else {
+                               M_INTMOVE(s1, d);
+                               M_LXOR(s2, d);
+                       }
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       break;
+
+               case ICMD_LXORCONST:  /* ..., value  ==> ..., value ^ constant        */
+                                     /* sx.val.l = constant                             */
+                       OOPS();
+#if 0
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+                       M_INTMOVE(s1, d);
+                       if (IS_IMM32(iptr->sx.val.l))
+                               M_LXOR_IMM(iptr->sx.val.l, d);
+                       else {
+                               M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
+                               M_LXOR(REG_ITMP2, d);
+                       }
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       break;
+
+
+               /* floating operations ************************************************/
+
+               case ICMD_FNEG:       /* ..., value  ==> ..., - value                 */
+                       OOPS();
+#if 0
+                       s1 = emit_load_s1(jd, iptr, REG_FTMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
+                       disp = dseg_add_s4(cd, 0x80000000);
+                       M_FLTMOVE(s1, d);
+                       emit_movss_membase_reg(cd, RIP, -((cd->mcodeptr + 9) - cd->mcodebase) + disp, REG_FTMP2);
+                       emit_xorps_reg_reg(cd, REG_FTMP2, d);
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       break;
+
+               case ICMD_DNEG:       /* ..., value  ==> ..., - value                 */
+                       OOPS();
+#if 0
+                       s1 = emit_load_s1(jd, iptr, REG_FTMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
+                       disp = dseg_add_s8(cd, 0x8000000000000000);
+                       M_FLTMOVE(s1, d);
+                       emit_movd_membase_reg(cd, RIP, -((cd->mcodeptr + 9) - cd->mcodebase) + disp, REG_FTMP2);
+                       emit_xorpd_reg_reg(cd, REG_FTMP2, d);
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       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);
+                       if (s2 == d)
+                               M_FADD(s1, d);
+                       else {
+                               M_FLTMOVE(s1, d);
+                               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);
+                       if (s2 == d)
+                               M_DADD(s1, d);
+                       else {
+                               M_FLTMOVE(s1, d);
+                               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;
+                       }
+                       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;
+                       }
+                       M_FLTMOVE(s1, d);
+                       M_DSUB(s2, d);
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       break;
+
+               case ICMD_FMUL:       /* ..., 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_FMUL(s1, d);
+                       else {
+                               M_FLTMOVE(s1, d);
+                               M_FMUL(s2, d);
+                       }
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       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);
+                       if (s2 == d)
+                               M_DMUL(s1, d);
+                       else {
+                               M_FLTMOVE(s1, d);
+                               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;
+                       }
+                       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;
+                       }
+                       M_FLTMOVE(s1, d);
+                       M_DDIV(s2, d);
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       break;
+
+               case ICMD_I2F:       /* ..., value  ==> ..., (float) value            */
+                       OOPS();
+#if 0
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
+                       M_CVTIF(s1, d);
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       break;
+
+               case ICMD_I2D:       /* ..., value  ==> ..., (double) value           */
+                       OOPS();
+#if 0
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
+                       M_CVTID(s1, d);
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       break;
+
+               case ICMD_L2F:       /* ..., value  ==> ..., (float) value            */
+                       OOPS();
+#if 0
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
+                       M_CVTLF(s1, d);
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       break;
+                       
+               case ICMD_L2D:       /* ..., value  ==> ..., (double) value           */
+                       OOPS();
+#if 0
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
+                       M_CVTLD(s1, d);
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       break;
+                       
+               case ICMD_F2I:       /* ..., value  ==> ..., (int) value              */
+                       OOPS();
+#if 0
+                       s1 = emit_load_s1(jd, iptr, REG_FTMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+                       M_CVTFI(s1, d);
+                       M_ICMP_IMM(0x80000000, d);                        /* corner cases */
+                       disp = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 +
+                               ((REG_RESULT == d) ? 0 : 3);
+                       M_BNE(disp);
+                       M_FLTMOVE(s1, REG_FTMP1);
+                       M_MOV_IMM(asm_builtin_f2i, REG_ITMP2);
+                       M_CALL(REG_ITMP2);
+                       M_INTMOVE(REG_RESULT, d);
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       break;
+
+               case ICMD_D2I:       /* ..., value  ==> ..., (int) value              */
+                       OOPS();
+#if 0
+                       s1 = emit_load_s1(jd, iptr, REG_FTMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+                       M_CVTDI(s1, d);
+                       M_ICMP_IMM(0x80000000, d);                        /* corner cases */
+                       disp = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 +
+                               ((REG_RESULT == d) ? 0 : 3);
+                       M_BNE(disp);
+                       M_FLTMOVE(s1, REG_FTMP1);
+                       M_MOV_IMM(asm_builtin_d2i, REG_ITMP2);
+                       M_CALL(REG_ITMP2);
+                       M_INTMOVE(REG_RESULT, d);
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       break;
+
+               case ICMD_F2L:       /* ..., value  ==> ..., (long) value             */
+                       OOPS();
+#if 0
+                       s1 = emit_load_s1(jd, iptr, REG_FTMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+                       M_CVTFL(s1, d);
+                       M_MOV_IMM(0x8000000000000000, REG_ITMP2);
+                       M_LCMP(REG_ITMP2, d);                             /* corner cases */
+                       disp = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 +
+                               ((REG_RESULT == d) ? 0 : 3);
+                       M_BNE(disp);
+                       M_FLTMOVE(s1, REG_FTMP1);
+                       M_MOV_IMM(asm_builtin_f2l, REG_ITMP2);
+                       M_CALL(REG_ITMP2);
+                       M_INTMOVE(REG_RESULT, d);
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       break;
+
+               case ICMD_D2L:       /* ..., value  ==> ..., (long) value             */
+                       OOPS();
+#if 0
+                       s1 = emit_load_s1(jd, iptr, REG_FTMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+                       M_CVTDL(s1, d);
+                       M_MOV_IMM(0x8000000000000000, REG_ITMP2);
+                       M_LCMP(REG_ITMP2, d);                             /* corner cases */
+                       disp = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 +
+                               ((REG_RESULT == d) ? 0 : 3);
+                       M_BNE(disp);
+                       M_FLTMOVE(s1, REG_FTMP1);
+                       M_MOV_IMM(asm_builtin_d2l, REG_ITMP2);
+                       M_CALL(REG_ITMP2);
+                       M_INTMOVE(REG_RESULT, d);
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       break;
+
+               case ICMD_F2D:       /* ..., value  ==> ..., (double) value           */
+                       OOPS();
+#if 0
+                       s1 = emit_load_s1(jd, iptr, REG_FTMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
+                       M_CVTFD(s1, d);
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       break;
+
+               case ICMD_D2F:       /* ..., value  ==> ..., (float) value            */
+                       OOPS();
+#if 0
+                       s1 = emit_load_s1(jd, iptr, REG_FTMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
+                       M_CVTDF(s1, d);
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       break;
+
+               case ICMD_FCMPL:      /* ..., 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_ucomiss_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_FCMPG:      /* ..., 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_ucomiss_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;
+
+               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 **************************************************/
+
+               case ICMD_ARRAYLENGTH: /* ..., arrayref  ==> ..., (int) length        */
+                       OOPS();
+#if 0
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
+                       gen_nullptr_check(s1);
+                       M_ILD(d, s1, OFFSET(java_arrayheader, size));
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       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);
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       break;
+
+               case ICMD_CALOAD:     /* ..., 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_movzwq_memindex_reg(cd, OFFSET(java_chararray, data[0]), s1, s2, 1, d);
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       break;                  
+
+               case ICMD_SALOAD:     /* ..., 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_movswq_memindex_reg(cd, OFFSET(java_shortarray, data[0]), s1, s2, 1, d);
+                       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);
+                       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);
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       break;
+
+               case ICMD_LALOAD:     /* ..., 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_mov_memindex_reg(cd, OFFSET(java_longarray, data[0]), s1, s2, 3, d);
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       break;
+
+               case ICMD_FALOAD:     /* ..., 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_FTMP3);
+                       if (INSTRUCTION_MUST_CHECK(iptr)) {
+                               gen_nullptr_check(s1);
+                               gen_bound_check;
+                       }
+                       emit_movss_memindex_reg(cd, OFFSET(java_floatarray, data[0]), s1, s2, 2, d);
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       break;
+
+               case ICMD_DALOAD:     /* ..., 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_FTMP3);
+                       if (INSTRUCTION_MUST_CHECK(iptr)) {
+                               gen_nullptr_check(s1);
+                               gen_bound_check;
+                       }
+                       emit_movsd_memindex_reg(cd, OFFSET(java_doublearray, data[0]), s1, s2, 3, d);
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       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_ITMP2);
+                       emit_array_checks(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);
+                       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;
+                       }
+                       s3 = emit_load_s3(jd, iptr, REG_ITMP3);
+                       emit_movb_reg_memindex(cd, s3, OFFSET(java_bytearray, data[0]), s1, s2, 0);
+#endif
+                       break;
+
+               case ICMD_CASTORE:    /* ..., 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;
+                       }
+                       s3 = emit_load_s3(jd, iptr, REG_ITMP3);
+                       emit_movw_reg_memindex(cd, s3, OFFSET(java_chararray, data[0]), s1, s2, 1);
+#endif
+                       break;
+
+               case ICMD_SASTORE:    /* ..., 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;
+                       }
+                       s3 = emit_load_s3(jd, iptr, REG_ITMP3);
+                       emit_movw_reg_memindex(cd, s3, OFFSET(java_shortarray, data[0]), s1, s2, 1);
+#endif
+                       break;
+
+               case ICMD_IASTORE:    /* ..., 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;
+                       }
+                       s3 = emit_load_s3(jd, iptr, REG_ITMP3);
+                       emit_movl_reg_memindex(cd, s3, OFFSET(java_intarray, data[0]), s1, s2, 2);
+#endif
+                       break;
+
+               case ICMD_LASTORE:    /* ..., 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;
+                       }
+                       s3 = emit_load_s3(jd, iptr, REG_ITMP3);
+                       emit_mov_reg_memindex(cd, s3, OFFSET(java_longarray, data[0]), s1, s2, 3);
+#endif
+                       break;
+
+               case ICMD_FASTORE:    /* ..., 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;
+                       }
+                       s3 = emit_load_s3(jd, iptr, REG_FTMP3);
+                       emit_movss_reg_memindex(cd, s3, OFFSET(java_floatarray, data[0]), s1, s2, 2);
+#endif
+                       break;
+
+               case ICMD_DASTORE:    /* ..., 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;
+                       }
+                       s3 = emit_load_s3(jd, iptr, REG_FTMP3);
+                       emit_movsd_reg_memindex(cd, s3, OFFSET(java_doublearray, data[0]), s1, s2, 3);
+#endif
+                       break;
+
+               case ICMD_AASTORE:    /* ..., 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;
+                       }
+                       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);
+
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+                       s3 = emit_load_s3(jd, iptr, REG_ITMP3);
+                       emit_mov_reg_memindex(cd, s3, OFFSET(java_objectarray, data[0]), s1, s2, 3);
+#endif
+                       break;
+
+
+               case ICMD_BASTORECONST: /* ..., arrayref, index  ==> ...              */
+                       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;
+                       }
+                       emit_movb_imm_memindex(cd, iptr->sx.s23.s3.constval, OFFSET(java_bytearray, data[0]), s1, s2, 0);
+#endif
+                       break;
+
+               case ICMD_CASTORECONST:   /* ..., arrayref, index  ==> ...            */
+                       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;
+                       }
+                       emit_movw_imm_memindex(cd, iptr->sx.s23.s3.constval, OFFSET(java_chararray, data[0]), s1, s2, 1);
+#endif
+                       break;
+
+               case ICMD_SASTORECONST:   /* ..., arrayref, index  ==> ...            */
+                       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;
+                       }
+                       emit_movw_imm_memindex(cd, iptr->sx.s23.s3.constval, OFFSET(java_shortarray, data[0]), s1, s2, 1);
+#endif
+                       break;
+
+               case ICMD_IASTORECONST: /* ..., arrayref, index  ==> ...              */
+                       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;
+                       }
+                       emit_movl_imm_memindex(cd, iptr->sx.s23.s3.constval, OFFSET(java_intarray, data[0]), s1, s2, 2);
+#endif
+                       break;
+
+               case ICMD_LASTORECONST: /* ..., arrayref, index  ==> ...              */
+                       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;
+                       }
+
+                       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 {
+                               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);
+                       }
+#endif
+                       break;
+
+               case ICMD_AASTORECONST: /* ..., arrayref, index  ==> ...              */
+                       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;
+                       }
+                       emit_mov_imm_memindex(cd, 0, OFFSET(java_objectarray, data[0]), s1, s2, 3);
+#endif
+                       break;
+
+
+               case ICMD_GETSTATIC:  /* ...  ==> ..., value                          */
+
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                               uf        = iptr->sx.s23.s3.uf;
+                               fieldtype = uf->fieldref->parseddesc.fd->type;
+                               disp      = dseg_add_unique_address(cd, NULL);
+
+                               /* 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);
+
+/*                             PROFILE_CYCLE_START; */
+                       }
+                       else {
+                               fi        = iptr->sx.s23.s3.fmiref->p.field;
+                               fieldtype = fi->type;
+                               disp      = dseg_add_address(cd, &(fi->value));
+
+                               if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
+                                       PROFILE_CYCLE_STOP;
+
+                                       codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, 0);
+
+                                       if (opt_shownops)
+                                               disp -= PATCHER_CALL_SIZE;
+
+                                       PROFILE_CYCLE_START;
+                               }
+                       }
+
+                       M_ALD(REG_ITMP1, REG_PV, disp);
+
+                       switch (fieldtype) {
+                       case TYPE_INT:
+                               d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+                               M_ILD(d, REG_ITMP1, 0);
+                               break;
+                       case TYPE_LNG:
+                               d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
+                               M_LLD(d, REG_ITMP1, 0);
+                               break;
+                       case TYPE_ADR:
+                               d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+                               M_ALD(d, REG_ITMP1, 0);
+                               break;
+                       case TYPE_FLT:
+                               d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
+                               M_FLD(d, REG_ITMP1, 0);
+                               break;
+                       case TYPE_DBL:                          
+                               d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
+                               M_DLD(d, REG_ITMP1, 0);
+                               break;
+                       }
+
+                       emit_store_dst(jd, iptr, d);
+
+                       break;
+
+               case ICMD_PUTSTATIC:  /* ..., value  ==> ...                          */
+                       OOPS();
+#if 0
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                               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;
+
+                               /* 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);
+
+/*                             PROFILE_CYCLE_START; */
+                       }
+                       else {
+                               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;
+
+                               if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
+                                       PROFILE_CYCLE_STOP;
+
+                                       codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, 0);
+
+                                       if (opt_shownops)
+                                               disp -= PATCHER_CALL_SIZE;
+
+                                       PROFILE_CYCLE_START;
+                               }
+                       }
+
+                       /* This approach is much faster than moving the field
+                          address inline into a register. */
+
+                       M_ALD(REG_ITMP1, RIP, disp);
+
+                       switch (fieldtype) {
+                       case TYPE_INT:
+                               s1 = emit_load_s1(jd, iptr, REG_ITMP2);
+                               M_IST(s1, REG_ITMP1, 0);
+                               break;
+                       case TYPE_LNG:
+                       case TYPE_ADR:
+                               s1 = emit_load_s1(jd, iptr, REG_ITMP2);
+                               M_LST(s1, REG_ITMP1, 0);
+                               break;
+                       case TYPE_FLT:
+                               s1 = emit_load_s1(jd, iptr, REG_FTMP1);
+                               M_FST(s1, REG_ITMP1, 0);
+                               break;
+                       case TYPE_DBL:
+                               s1 = emit_load_s1(jd, iptr, REG_FTMP1);
+                               M_DST(s1, REG_ITMP1, 0);
+                               break;
+                       }
+#endif
+                       break;
+
+               case ICMD_PUTSTATICCONST: /* ...  ==> ...                             */
+                                         /* val = value (in current instruction)     */
+                                         /* following NOP)                           */
+                       OOPS();
+#if 0
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                               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;
+
+                               /* 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);
+
+/*                             PROFILE_CYCLE_START; */
+                       }
+                       else {
+                               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;
+
+                               if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
+                                       PROFILE_CYCLE_STOP;
+
+                                       codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, 0);
+
+                                       if (opt_shownops)
+                                               disp -= PATCHER_CALL_SIZE;
+
+                                       PROFILE_CYCLE_START;
+                               }
+                       }
+
+                       /* This approach is much faster than moving the field
+                          address inline into a register. */
+
+                       M_ALD(REG_ITMP1, RIP, disp);
+
+                       switch (fieldtype) {
+                       case TYPE_INT:
+                       case TYPE_FLT:
+                               M_IST_IMM(iptr->sx.s23.s2.constval, REG_ITMP1, 0);
+                               break;
+                       case TYPE_LNG:
+                       case TYPE_ADR:
+                       case TYPE_DBL:
+                               if (IS_IMM32(iptr->sx.s23.s2.constval))
+                                       M_LST_IMM32(iptr->sx.s23.s2.constval, REG_ITMP1, 0);
+                               else {
+                                       M_IST_IMM(iptr->sx.s23.s2.constval, REG_ITMP1, 0);
+                                       M_IST_IMM(iptr->sx.s23.s2.constval >> 32, REG_ITMP1, 4);
+                               }
+                               break;
+                       }
+#endif
+                       break;
+
+               case ICMD_GETFIELD:   /* ...  ==> ..., value                          */
+                       OOPS();
+#if 0
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       gen_nullptr_check(s1);
+
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                               uf        = iptr->sx.s23.s3.uf;
+                               fieldtype = uf->fieldref->parseddesc.fd->type;
+                               disp      = 0;
+
+/*                             PROFILE_CYCLE_STOP; */
+
+                               codegen_add_patch_ref(cd, PATCHER_get_putfield, uf, 0);
+
+/*                             PROFILE_CYCLE_START; */
+                       }
+                       else {
+                               fi        = iptr->sx.s23.s3.fmiref->p.field;
+                               fieldtype = fi->type;
+                               disp      = fi->offset;
+                       }
+
+                       switch (fieldtype) {
+                       case TYPE_INT:
+                               d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+                               M_ILD32(d, s1, disp);
+                               break;
+                       case TYPE_LNG:
+                       case TYPE_ADR:
+                               d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+                               M_LLD32(d, s1, disp);
+                               break;
+                       case TYPE_FLT:
+                               d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
+                               M_FLD32(d, s1, disp);
+                               break;
+                       case TYPE_DBL:                          
+                               d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
+                               M_DLD32(d, s1, disp);
+                               break;
+                       }
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       break;
+
+               case ICMD_PUTFIELD:   /* ..., objectref, value  ==> ...               */
+                       OOPS();
+#if 0
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       gen_nullptr_check(s1);
+
+                       s2 = emit_load_s2(jd, iptr, REG_IFTMP);
+
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                               uf        = iptr->sx.s23.s3.uf;
+                               fieldtype = uf->fieldref->parseddesc.fd->type;
+                               disp      = 0;
+
+/*                             PROFILE_CYCLE_STOP; */
+
+                               codegen_add_patch_ref(cd, PATCHER_get_putfield, uf, 0);
+
+/*                             PROFILE_CYCLE_START; */
+                       } 
+                       else {
+                               fi        = iptr->sx.s23.s3.fmiref->p.field;
+                               fieldtype = fi->type;
+                               disp      = fi->offset;
+                       }
+
+                       switch (fieldtype) {
+                       case TYPE_INT:
+                               M_IST32(s2, s1, disp);
+                               break;
+                       case TYPE_LNG:
+                       case TYPE_ADR:
+                               M_LST32(s2, s1, disp);
+                               break;
+                       case TYPE_FLT:
+                               M_FST32(s2, s1, disp);
+                               break;
+                       case TYPE_DBL:
+                               M_DST32(s2, s1, disp);
+                               break;
+                       }
+#endif
+                       break;
+
+               case ICMD_PUTFIELDCONST:  /* ..., objectref, value  ==> ...           */
+                                         /* val = value (in current instruction)     */
+                                         /* following NOP)                           */
+                       OOPS();
+#if 0
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       gen_nullptr_check(s1);
+
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                               uf        = iptr->sx.s23.s3.uf;
+                               fieldtype = uf->fieldref->parseddesc.fd->type;
+                               disp      = 0;
+
+/*                             PROFILE_CYCLE_STOP; */
+
+                               codegen_add_patch_ref(cd, PATCHER_putfieldconst, uf, 0);
+
+/*                             PROFILE_CYCLE_START; */
+                       } 
+                       else {
+                               fi        = iptr->sx.s23.s3.fmiref->p.field;
+                               fieldtype = fi->type;
+                               disp      = fi->offset;
+                       }
+
+                       switch (fieldtype) {
+                       case TYPE_INT:
+                       case TYPE_FLT:
+                               M_IST32_IMM(iptr->sx.s23.s2.constval, s1, disp);
+                               break;
+                       case TYPE_LNG:
+                       case TYPE_ADR:
+                       case TYPE_DBL:
+                               /* XXX why no check for IS_IMM32? */
+                               M_IST32_IMM(iptr->sx.s23.s2.constval, s1, disp);
+                               M_IST32_IMM(iptr->sx.s23.s2.constval >> 32, s1, disp + 4);
+                               break;
+                       }
+#endif
+                       break;
+
+
+               /* branch operations **************************************************/
+
+               case ICMD_ATHROW:       /* ..., objectref ==> ... (, objectref)       */
+                       OOPS();
+#if 0
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       M_INTMOVE(s1, REG_ITMP1_XPTR);
+
+                       PROFILE_CYCLE_STOP;
+
+#ifdef ENABLE_VERIFIER
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                               uc = iptr->sx.s23.s2.uc;
+
+                               codegen_add_patch_ref(cd, PATCHER_athrow_areturn, uc, 0);
+                       }
+#endif /* ENABLE_VERIFIER */
+
+                       M_CALL_IMM(0);                            /* passing exception pc */
+                       M_POP(REG_ITMP2_XPC);
+
+                       M_MOV_IMM(asm_handle_exception, REG_ITMP3);
+                       M_JMP(REG_ITMP3);
+#endif
+                       break;
+
+               case ICMD_GOTO:         /* ... ==> ...                                */
+               case ICMD_RET:          /* ... ==> ...                                */
+                       OOPS();
+#if 0
+                       M_JMP_IMM(0);
+                       codegen_add_branch_ref(cd, iptr->dst.block);
+#endif
+                       break;
+
+               case ICMD_JSR:          /* ... ==> ...                                */
+                       OOPS();
+#if 0
+                       M_JMP_IMM(0);
+                       codegen_add_branch_ref(cd, iptr->sx.s23.s3.jsrtarget.block);
+#endif
+                       break;
+                       
+               case ICMD_IFNULL:       /* ..., value ==> ...                         */
+                       OOPS();
+#if 0
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       M_TEST(s1);
+                       M_BEQ(0);
+                       codegen_add_branch_ref(cd, iptr->dst.block);
+#endif
+                       break;
+
+               case ICMD_IFNONNULL:    /* ..., value ==> ...                         */
+                       OOPS();
+#if 0
+                       s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+                       M_TEST(s1);
+                       M_BNE(0);
+                       codegen_add_branch_ref(cd, iptr->dst.block);
+#endif
+                       break;
+
+               case ICMD_IFEQ:         /* ..., value ==> ...                         */
+                       OOPS();
+#if 0
+                       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);
+#endif
+                       break;
+
+               case ICMD_IFLT:         /* ..., value ==> ...                         */
+                       OOPS();
+#if 0
+                       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);
+#endif
+                       break;
+
+               case ICMD_IFLE:         /* ..., value ==> ...                         */
+                       OOPS();
+#if 0
+                       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);
+#endif
+                       break;
+
+               case ICMD_IFNE:         /* ..., value ==> ...                         */
+                       OOPS();
+#if 0
+                       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);
+#endif
+                       break;
+
+               case ICMD_IFGT:         /* ..., value ==> ...                         */
+                       OOPS();
+#if 0
+                       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);
+#endif
+                       break;
+
+               case ICMD_IFGE:         /* ..., value ==> ...                         */
+                       OOPS();
+#if 0
+                       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);
+#endif
+                       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
+
+                       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;
+
+               case ICMD_IF_LLE:       /* ..., 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_BLE(0);
+                       codegen_add_branch_ref(cd, iptr->dst.block);
+#endif
+                       break;
+
+               case ICMD_IF_LNE:       /* ..., 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_BNE(0);
+                       codegen_add_branch_ref(cd, iptr->dst.block);
+#endif
+                       break;
+
+               case ICMD_IF_LGT:       /* ..., 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_BGT(0);
+                       codegen_add_branch_ref(cd, iptr->dst.block);
+#endif
+                       break;
+
+               case ICMD_IF_LGE:       /* ..., 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_BGE(0);
+                       codegen_add_branch_ref(cd, iptr->dst.block);
+#endif
+                       break;
+
+               case ICMD_IF_ICMPEQ:    /* ..., value, value ==> ...                  */
+                       OOPS();
+#if 0
+
+                       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);
+#endif
+                       break;
+
+               case ICMD_IF_LCMPEQ:    /* ..., value, value ==> ...                  */
+               case ICMD_IF_ACMPEQ:    /* op1 = target JavaVM pc                     */
+                       OOPS();
+#if 0
+
+                       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);
+#endif
+                       break;
+
+               case ICMD_IF_ICMPNE:    /* ..., value, value ==> ...                  */
+                       OOPS();
+#if 0
+
+                       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);
+#endif
+                       break;
+
+               case ICMD_IF_LCMPNE:    /* ..., value, value ==> ...                  */
+               case ICMD_IF_ACMPNE:    /* op1 = target JavaVM pc                     */
+                       OOPS();
+#if 0
+
+                       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;
+
+               case ICMD_IF_ICMPLT:    /* ..., value, value ==> ...                  */
+                       OOPS();
+#if 0
+
+                       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);
+#endif
+                       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_ICMPGT:    /* ..., value, value ==> ...                  */
+                       OOPS();
+#if 0
+
+                       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);
+#endif
+                       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 ==> ...                  */
+
+                       OOPS();
+#if 0
+                       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);
+#endif
+                       break;
+
+               case ICMD_IF_LCMPLE:    /* ..., 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_BLE(0);
+                       codegen_add_branch_ref(cd, iptr->dst.block);
+#endif
+                       break;
+
+               case ICMD_IF_ICMPGE:    /* ..., value, value ==> ...                  */
+
+                       OOPS();
+#if 0
+                       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);
+#endif
+                       break;
+
+               case ICMD_IF_LCMPGE:    /* ..., 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_BGE(0);
+                       codegen_add_branch_ref(cd, iptr->dst.block);
+#endif
+                       break;
+
+               case ICMD_IRETURN:      /* ..., retvalue ==> ...                      */
+               case ICMD_LRETURN:
+
+                       OOPS();
+#if 0
+                       s1 = emit_load_s1(jd, iptr, REG_RESULT);
+                       M_INTMOVE(s1, REG_RESULT);
+#endif
+                       goto nowperformreturn;
+
+               case ICMD_ARETURN:      /* ..., retvalue ==> ...                      */
+
+                       OOPS();
+#if 0
+                       s1 = emit_load_s1(jd, iptr, REG_RESULT);
+                       M_INTMOVE(s1, REG_RESULT);
+
+#ifdef ENABLE_VERIFIER
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                               uc = iptr->sx.s23.s2.uc;
+
+                               PROFILE_CYCLE_STOP;
+
+                               codegen_add_patch_ref(cd, PATCHER_athrow_areturn, uc, 0);
+
+                               PROFILE_CYCLE_START;
+                       }
+#endif /* ENABLE_VERIFIER */
+#endif
+                       goto nowperformreturn;
+
+               case ICMD_FRETURN:      /* ..., retvalue ==> ...                      */
+               case ICMD_DRETURN:
+
+                       OOPS();
+#if 0
+                       s1 = emit_load_s1(jd, iptr, REG_FRESULT);
+                       M_FLTMOVE(s1, REG_FRESULT);
+#endif
+                       goto nowperformreturn;
+
+               case ICMD_RETURN:      /* ...  ==> ...                                */
+
+nowperformreturn:
+                       OOPS();
+#if 0
+                       {
+                       s4 i, p;
+
+                       p = cd->stackframesize;
+
+#if !defined(NDEBUG)
+                       if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
+                               emit_verbosecall_exit(jd);
+#endif /* !defined(NDEBUG) */
+
+#if defined(ENABLE_THREADS)
+                       if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
+                               M_ALD(REG_A0, REG_SP, rd->memuse * 8);
+       
+                               /* we need to save the proper return value */
+                               switch (iptr->opc) {
+                               case ICMD_IRETURN:
+                               case ICMD_ARETURN:
+                               case ICMD_LRETURN:
+                                       M_LST(REG_RESULT, REG_SP, rd->memuse * 8);
+                                       break;
+                               case ICMD_FRETURN:
+                               case ICMD_DRETURN:
+                                       M_DST(REG_FRESULT, REG_SP, rd->memuse * 8);
+                                       break;
+                               }
+
+                               M_MOV_IMM(LOCK_monitor_exit, REG_ITMP1);
+                               M_CALL(REG_ITMP1);
+
+                               /* and now restore the proper return value */
+                               switch (iptr->opc) {
+                               case ICMD_IRETURN:
+                               case ICMD_ARETURN:
+                               case ICMD_LRETURN:
+                                       M_LLD(REG_RESULT, REG_SP, rd->memuse * 8);
+                                       break;
+                               case ICMD_FRETURN:
+                               case ICMD_DRETURN:
+                                       M_DLD(REG_FRESULT, REG_SP, rd->memuse * 8);
+                                       break;
+                               }
+                       }
+#endif
+
+                       /* restore saved registers */
+
+                       for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
+                               p--; M_LLD(rd->savintregs[i], REG_SP, p * 8);
+                       }
+                       for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
+                               p--; M_DLD(rd->savfltregs[i], REG_SP, p * 8);
+                       }
+
+                       /* deallocate stack */
+
+                       if (cd->stackframesize)
+                               M_AADD_IMM(cd->stackframesize * 8, REG_SP);
+
+                       /* generate method profiling code */
+
+                       PROFILE_CYCLE_STOP;
+
+                       M_RET;
+                       }
+#endif
+                       break;
+
+
+               case ICMD_TABLESWITCH:  /* ..., index ==> ...                         */
+                       OOPS();
+#if 0
+                       {
+                               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);
+
+                               /* number of targets */
+                               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 */
+
+                               /* 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_MOV_IMM(0, REG_ITMP2);
+                               dseg_adddata(cd);
+                               emit_mov_memindex_reg(cd, -(cd->dseglen), REG_ITMP2, REG_ITMP1, 3, REG_ITMP1);
+                               M_JMP(REG_ITMP1);
+                       }
+#endif
+                       break;
+
+
+               case ICMD_LOOKUPSWITCH: /* ..., key ==> ...                           */
+                       OOPS();
+#if 0
+                       {
+                               s4 i;
+                               lookup_target_t *lookup;
+
+                               lookup = iptr->dst.lookup;
+
+                               i = iptr->sx.s23.s2.lookupcount;
+                       
+                               MCODECHECK(8 + ((7 + 6) * i) + 5);
+                               s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+
+                               while (--i >= 0) {
+                                       M_ICMP_IMM(lookup->value, s1);
+                                       M_BEQ(0);
+                                       codegen_add_branch_ref(cd, lookup->target.block);
+                                       lookup++;
+                               }
+
+                               M_JMP_IMM(0);
+                       
+                               codegen_add_branch_ref(cd, iptr->sx.s23.s3.lookupdefault.block);
+                       }
+#endif
+                       break;
+
+
+               case ICMD_BUILTIN:      /* ..., [arg1, [arg2 ...]] ==> ...            */
+                       OOPS();
+#if 0
+
+                       bte = iptr->sx.s23.s3.bte;
+                       md  = bte->md;
+#endif
+                       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:
+                       OOPS();
+#if 0
+
+                       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;
+                       }
+#endif
+gen_method:
+#if 0
+                       s3 = md->paramcount;
+
+                       MCODECHECK((20 * s3) + 128);
+
+                       /* copy arguments to registers or stack location */
+
+                       for (s3 = s3 - 1; s3 >= 0; s3--) {
+                               var = VAR(iptr->sx.s23.s2.args[s3]);
+
+                               /* Already Preallocated (ARGVAR) ? */
+                               if (var->flags & PREALLOC)
+                                       continue;
+
+                               if (IS_INT_LNG_TYPE(var->type)) {
+                                       if (!md->params[s3].inmemory) {
+                                               s1 = rd->argintregs[md->params[s3].regoff];
+                                               d = emit_load(jd, iptr, var, s1);
+                                               M_INTMOVE(d, s1);
+                                       }
+                                       else {
+                                               d = emit_load(jd, iptr, var, REG_ITMP1);
+                                               M_LST(d, REG_SP, md->params[s3].regoff * 8);
+                                       }
+                               }
+                               else {
+                                       if (!md->params[s3].inmemory) {
+                                               s1 = rd->argfltregs[md->params[s3].regoff];
+                                               d = emit_load(jd, iptr, var, s1);
+                                               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_FST(d, REG_SP, md->params[s3].regoff * 8);
+                                       }
+                               }
+                       }
+
+                       /* generate method profiling code */
+
+                       PROFILE_CYCLE_STOP;
+
+                       switch (iptr->opc) {
+                       case ICMD_BUILTIN:
+                               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);
+                               }
+                               break;
+
+                       case ICMD_INVOKESPECIAL:
+                               M_TEST(REG_A0);
+                               M_BEQ(0);
+                               codegen_add_nullpointerexception_ref(cd);
+
+                               /* fall through */
+
+                       case ICMD_INVOKESTATIC:
+                               if (lm == NULL) {
+                                       disp = dseg_add_unique_address(cd, NULL);
+                                       disp = -((cd->mcodeptr + 7) - cd->mcodebase) + disp;
+
+                                       /* must be calculated before codegen_add_patch_ref */
+
+                                       if (opt_shownops)
+                                               disp -= PATCHER_CALL_SIZE;
+
+                                       codegen_add_patch_ref(cd, PATCHER_invokestatic_special,
+                                                                                 um, disp);
+
+/*                                     a = 0; */
+                               }
+                               else {
+                                       disp = dseg_add_functionptr(cd, lm->stubroutine);
+                                       disp = -((cd->mcodeptr + 7) - cd->mcodebase) + disp;
+
+/*                                     a = (ptrint) lm->stubroutine; */
+                               }
+
+/*                             M_MOV_IMM(a, REG_ITMP2); */
+                               M_ALD(REG_ITMP2, RIP, disp);
+                               M_CALL(REG_ITMP2);
+                               break;
+
+                       case ICMD_INVOKEVIRTUAL:
+                               gen_nullptr_check(REG_A0);
+
+                               if (lm == NULL) {
+                                       codegen_add_patch_ref(cd, PATCHER_invokevirtual, um, 0);
+
+                                       s1 = 0;
+                               }
+                               else
+                                       s1 = OFFSET(vftbl_t, table[0]) +
+                                               sizeof(methodptr) * lm->vftblindex;
+
+                               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:
+                               gen_nullptr_check(REG_A0);
+
+                               if (lm == NULL) {
+                                       codegen_add_patch_ref(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);
+                               }
+
+                               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);
+                               break;
+                       }
+
+                       /* generate method profiling code */
+
+                       PROFILE_CYCLE_START;
+
+                       /* 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);
+                               }
+                               emit_store_dst(jd, iptr, s1);
+                       }
+#endif
+                       break;
+
+
+               case ICMD_CHECKCAST:  /* ..., objectref ==> ..., objectref            */
+                       OOPS();
+#if 0
+
+                                     /* 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 */
+
+                               classinfo *super;
+                               vftbl_t   *supervftbl;
+                               s4         superindex;
+
+                               if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                                       super = NULL;
+                                       superindex = 0;
+                                       supervftbl = NULL;
+                               }
+                               else {
+                                       super = iptr->sx.s23.s3.c.cls;
+                                       superindex = super->index;
+                                       supervftbl = super->vftbl;
+                               }
+
+#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 = 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);
+
+                                       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);
+                               }
+
+                               /* interface checkcast code */
+
+                               if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
+                                       if (super != NULL) {
+                                               M_TEST(s1);
+                                               M_BEQ(s2);
+                                       }
+
+                                       M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
+
+                                       if (super == NULL) {
+                                               codegen_add_patch_ref(cd,
+                                                                                         PATCHER_checkcast_instanceof_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_TEST(REG_ITMP3);
+                                       M_BEQ(0);
+                                       codegen_add_classcastexception_ref(cd, s1);
+
+                                       if (super == NULL)
+                                               M_JMP_IMM(s3);
+                               }
+
+                               /* class checkcast code */
+
+                               if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
+                                       if (super != NULL) {
+                                               M_TEST(s1);
+                                               M_BEQ(s3);
+                                       }
+
+                                       M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
+
+                                       if (super == NULL) {
+                                               codegen_add_patch_ref(cd, PATCHER_checkcast_class,
+                                                                                         iptr->sx.s23.s3.c.ref,
+                                                                                         0);
+                                       }
+
+                                       M_MOV_IMM(supervftbl, REG_ITMP3);
+#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);
+                                       /*                                      if (s1 != REG_ITMP1) { */
+                                       /*                                              emit_movl_membase_reg(cd, REG_ITMP3, */
+                                       /*                                                                                              OFFSET(vftbl_t, baseval), */
+                                       /*                                                                                              REG_ITMP1); */
+                                       /*                                              emit_movl_membase_reg(cd, REG_ITMP3, */
+                                       /*                                                                                              OFFSET(vftbl_t, diffval), */
+                                       /*                                                                                              REG_ITMP3); */
+                                       /*  #if defined(ENABLE_THREADS) */
+                                       /*                                              codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase); */
+                                       /*  #endif */
+                                       /*                                              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_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);
+                               }
+
+                               d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
+                       }
+                       else {
+                               /* array type cast-check */
+
+                               s1 = emit_load_s1(jd, iptr, REG_ITMP2);
+                               M_INTMOVE(s1, REG_A0);
+
+                               if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                                       codegen_add_patch_ref(cd, PATCHER_builtin_arraycheckcast,
+                                                                                 iptr->sx.s23.s3.c.ref, 0);
+                               }
+
+                               M_MOV_IMM(iptr->sx.s23.s3.c.cls, REG_A1);
+                               M_MOV_IMM(BUILTIN_arraycheckcast, REG_ITMP1);
+                               M_CALL(REG_ITMP1);
+
+                               /* 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);
+
+                               d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+                       }
+
+                       M_INTMOVE(s1, d);
+                       emit_store_dst(jd, iptr, d);
+#endif
+                       break;
+
+               case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult            */
+                       OOPS();
+#if 0
+
+                                     /* 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;
+                               superindex = 0;
+                               supervftbl = NULL;
+
+                       } else {
+                               super = iptr->sx.s23.s3.c.cls;
+                               superindex = super->index;
+                               supervftbl = super->vftbl;
+                       }
+
+#if defined(ENABLE_THREADS)
+            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_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);
+
+                       /* 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));
+
+                               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);
+                       }
+
+                       /* 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);
+                               }
+
+                               emit_mov_membase_reg(cd, s1,
+                                                                        OFFSET(java_objectheader, vftbl),
+                                                                        REG_ITMP1);
+
+                               if (super == NULL) {
+                                       codegen_add_patch_ref(cd,
+                                                                                 PATCHER_checkcast_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);
+
+                               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);
+
+                               if (!super)
+                                       emit_jmp_imm(cd, s3);
+                       }
+
+                       /* 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);
+                               }
+
+                               emit_mov_membase_reg(cd, s1,
+                                                                          OFFSET(java_objectheader, vftbl),
+                                                                          REG_ITMP1);
+
+                               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);
+#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);
+#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);
+                       }
+                       emit_store_dst(jd, iptr, d);
+                       }
+#endif
+                       break;
+
+               case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref  */
+                       OOPS();
+#if 0
+
+                       /* check for negative sizes and copy sizes to stack if necessary  */
+
+                       MCODECHECK((10 * 4 * iptr->s1.argcount) + 5 + 10 * 8);
+
+                       for (s1 = iptr->s1.argcount; --s1 >= 0; ) {
+
+                               /* copy SAVEDVAR sizes to stack */
+                               var = VAR(iptr->sx.s23.s2.args[s1]);
+
+                               /* Already Preallocated? */
+                               if (!(var->flags & PREALLOC)) {
+                                       s2 = emit_load(jd, iptr, var, REG_ITMP1);
+                                       M_LST(s2, REG_SP, s1 * 8);
+                               }
+                       }
+
+                       /* is a patcher function set? */
+
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                               codegen_add_patch_ref(cd, PATCHER_builtin_multianewarray,
+                                                                         iptr->sx.s23.s3.c.ref, 0);
+                       }
+
+                       /* a0 = dimension count */
+
+                       M_MOV_IMM(iptr->s1.argcount, REG_A0);
+
+                       /* a1 = classinfo */
+
+                       M_MOV_IMM(iptr->sx.s23.s3.c.cls, REG_A1);
+
+                       /* a2 = pointer to dimensions = stack pointer */
+
+                       M_MOV(REG_SP, REG_A2);
+
+                       M_MOV_IMM(BUILTIN_multianewarray, REG_ITMP1);
+                       M_CALL(REG_ITMP1);
+
+                       /* check for exception before result assignment */
+
+                       M_TEST(REG_RESULT);
+                       M_BEQ(0);
+                       codegen_add_fillinstacktrace_ref(cd);
+
+                       s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
+                       M_INTMOVE(REG_RESULT, s1);
+                       emit_store_dst(jd, iptr, s1);
+#endif
+                       break;
+
+               default:
+                       *exceptionptr = new_internalerror("Unknown ICMD %d", iptr->opc);
+                       return false;
+       } /* switch */
+
+       } /* for instruction */
+               
+       MCODECHECK(512); /* XXX require a lower number? */
+
+       /* At the end of a basic block we may have to append some nops,
+          because the patcher stub calling code might be longer than the
+          actual instruction. So codepatching does not change the
+          following block unintentionally. */
+
+       if (cd->mcodeptr < cd->lastmcodeptr) {
+               while (cd->mcodeptr < cd->lastmcodeptr) {
+                       M_NOP;
+               }
+       }
+
+       } /* if (bptr -> flags >= BBREACHED) */
+       } /* for basic block */
+
+       dseg_createlinenumbertable(cd);
+
+       /* generate stubs */
+
+       emit_exception_stubs(jd);
+       emit_patcher_stubs(jd);
+#if 0
+       emit_replacement_stubs(jd);
+#endif
+
+       codegen_finish(jd);
+
+       /* everything's ok */
+
+       return true;
+}
+
+
+/* createcompilerstub **********************************************************
+
+   Creates a stub routine which calls the compiler.
+       
+*******************************************************************************/
+
+#define COMPILERSTUB_DATASIZE    (3 * SIZEOF_VOID_P)
+#define COMPILERSTUB_CODESIZE    (SZ_BRAS + SZ_AHI + (2 * SZ_L) + SZ_BR)
+
+#define COMPILERSTUB_SIZE        (COMPILERSTUB_DATASIZE + COMPILERSTUB_CODESIZE)
+
+
+u1 *createcompilerstub(methodinfo *m)
+{
+       u1          *s;                     /* memory to hold the stub            */
+       ptrint      *d;
+       codeinfo    *code;
+       codegendata *cd;
+       s4           dumpsize;
+
+       s = CNEW(u1, COMPILERSTUB_SIZE);
+
+       /* set data pointer 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 the codeinfo pointer in the same place as in the
+          methodheader for compiled methods. */
+
+       code = code_codeinfo_new(m);
+
+       d[0] = (ptrint) asm_call_jit_compiler;
+       d[1] = (ptrint) m;
+       d[2] = (ptrint) code;
+
+       /* code for the stub */
+
+       /* don't touch ITMP3 as it cointains the return address */
+
+       N_L2(REG_ITMP1, -2 * 4, REG_PV); /* methodinfo  */
+       /* TODO where is methodpointer loaded into itmp2? is it already inside? */
+       N_L2(REG_PV, -3 * 4, REG_PV); /* compiler pointer */
+       N_BR(REG_PV);
+
+#if defined(ENABLE_STATISTICS)
+       if (opt_stat)
+               count_cstub_len += COMPILERSTUB_SIZE;
+#endif
+
+       /* release dump area */
+
+       dump_release(dumpsize);
+
+       return s;
+}
+
+
+/* createnativestub ************************************************************
+
+   Creates a stub routine which calls a native method.
+
+*******************************************************************************/
+
+/*
+           arguments on stack                   \
+-------------------------------------------------| <- SP on nativestub entry
+           return address                        |
+           callee saved int regs (none)          |
+           callee saved float regs (none)        | stack frame like in cacao
+           local variable slots (none)           |
+           arguments for calling methods (none) /
+------------------------------------------------------------------ <- datasp 
+           stackframe info
+           locaref table
+           integer arguments
+           float arguments
+96 - ...   on stack parameters (nmd->memuse slots) \ stack frame like in ABI         
+0 - 96     register save area for callee           /
+-------------------------------------------------------- <- SP native method
+                                                            ==
+                                                            SP after method entry
+*/
+
+u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd)
+{
+       methodinfo   *m;
+       codeinfo     *code;
+       codegendata  *cd;
+       registerdata *rd;
+       methoddesc   *md;
+       s4            nativeparams;
+       s4            i, j;                 /* count variables                    */
+       s4            t;
+       s4            s1, s2;
+       s4            disp;
+
+       /* get required compiler data */
+
+       m    = jd->m;
+       code = jd->code;
+       cd   = jd->cd;
+       rd   = jd->rd;
+
+       /* initialize variables */
+
+       md = m->parseddesc;
+       nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
+
+       /* calculate stack frame size */
+#if 0
+       cd->stackframesize =
+               sizeof(stackframeinfo) / SIZEOF_VOID_P +
+               sizeof(localref_table) / SIZEOF_VOID_P +
+               INT_ARG_CNT + FLT_ARG_CNT +
+               1 +                       /* functionptr, TODO: store in data segment */
+               nmd->memuse;
+
+       cd->stackframesize |= 0x1;                  /* keep stack 16-byte aligned */
+#endif
+
+       cd->stackframesize = 
+               1 + /* r14 - return address */ +
+               sizeof(stackframeinfo) / SIZEOF_VOID_P +
+               sizeof(localref_table) / SIZEOF_VOID_P +
+               1 + /* itmp3 */
+               (INT_ARG_CNT + FLT_ARG_CNT) * 2 +
+               nmd->memuse + /* parameter passing */
+               96 / SIZEOF_VOID_P /* required by ABI */;
+
+
+       /* create method header */
+
+       (void) dseg_add_unique_address(cd, code);              /* CodeinfoPointer */
+       (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* 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     */
+
+       /* generate native method profiling code */
+#if 0
+       if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
+               /* count frequency */
+
+               M_MOV_IMM(code, REG_ITMP3);
+               M_IINC_MEMBASE(REG_ITMP3, OFFSET(codeinfo, frequency));
+       }
+#endif
+
+       /* generate stub code */
+
+       N_AHI(REG_SP, -(cd->stackframesize * SIZEOF_VOID_P));
+
+       /* save return address */
+
+       N_ST(R14, (cd->stackframesize - 1) * SIZEOF_VOID_P, 0, REG_SP)
+
+#if 0
+#if !defined(NDEBUG)
+       if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
+               emit_verbosecall_enter(jd);
+#endif
+#endif
+
+       /* get function address (this must happen before the stackframeinfo) */
+
+#if !defined(WITH_STATIC_CLASSPATH)
+       if (f == NULL)
+               codegen_add_patch_ref(cd, PATCHER_resolve_native, m, 0);
+#endif
+
+       disp = dseg_add_functionptr(cd, f);
+       N_L2(REG_ITMP3, disp, REG_PV);
+
+       j = 96 + (nmd->memuse * 4);
+
+       /* todo some arg registers are not volatile in C-abi terms */
+
+       /* save integer and float argument registers */
+
+       for (i = 0; i < md->paramcount; i++) {
+               if (! md->params[i].inmemory) {
+                       s1 = md->params[i].regoff;
+
+                       if (IS_INT_LNG_TYPE(md->paramtypes[i].type)) {
+                               if (IS_2_WORD_TYPE(t)) {
+                                       /* todo store multiple */
+                                       N_ST(rd->argintregs[GET_HIGH_REG(s1)], j, 0, REG_SP);
+                                       N_ST(rd->argintregs[GET_LOW_REG(s1)], j + 4, 0, REG_SP);
+                               } else {
+                                       N_ST(rd->argintregs[s1], j, 0, REG_SP);
+                               }
+                       } else {
+                               if (IS_2_WORD_TYPE(t)) {
+                                       N_STD(rd->argfltregs[s1], j, 0, REG_SP);
+                               } else {
+                                       N_STE(rd->argfltregs[s1], j, 0, REG_SP);
+                               }
+                       }
+
+                       j += 8;
+               }
+       }
+
+       N_ST(REG_ITMP3, j, 0, REG_SP);
+
+       /* create dynamic stack info */
+
+       N_LAE(REG_A0, (cd->stackframesize - 1) * 4, 0, REG_SP); /* datasp */
+       N_LR(REG_A1, REG_PV) /* pv */
+       N_LAE(REG_A2, cd->stackframesize * 4, 0, REG_SP); /* old SP */
+       N_L(REG_A3, (cd->stackframesize - 1) * 4, 0, REG_SP); /* return address */
+
+       disp = dseg_add_functionptr(cd, codegen_start_native_call);
+       N_L2(REG_ITMP1, disp, REG_PV);
+
+       M_CALL(REG_ITMP1); /* call */
+
+       /* restore integer and float argument registers */
+
+       j = 96 + (nmd->memuse * 4);
+
+       for (i = 0; i < md->paramcount; i++) {
+               if (! md->params[i].inmemory) {
+                       s1 = md->params[i].regoff;
+
+                       if (IS_INT_LNG_TYPE(md->paramtypes[i].type)) {
+                               if (IS_2_WORD_TYPE(t)) {
+                                       /* todo load multiple ! */
+                                       N_L(rd->argintregs[GET_HIGH_REG(s1)], j, 0, REG_SP);
+                                       N_L(rd->argintregs[GET_LOW_REG(s1)], j + 4, 0, REG_SP);
+                               } else {
+                                       N_L(rd->argintregs[s1], j, 0, REG_SP);
+                               }
+                       } else {
+                               if (IS_2_WORD_TYPE(t)) {
+                                       N_LD(rd->argfltregs[s1], j, 0, REG_SP);
+                               } else {
+                                       N_LE(rd->argfltregs[s1], j, 0, REG_SP);
+                               }
+                       }
+
+                       j += 8;
+               }
+       }
+
+       N_L(REG_ITMP3, j, 0, REG_SP);
+
+       /* copy or spill arguments to new locations */
+
+       for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
+               t = md->paramtypes[i].type;
+
+               if (IS_INT_LNG_TYPE(t)) {
+
+                       if (!md->params[i].inmemory) {
+
+                               s1 = rd->argintregs[md->params[i].regoff];
+
+                               if (!nmd->params[j].inmemory) {
+                                       s2 = rd->argintregs[nmd->params[j].regoff];
+                                       if (IS_2_WORD_TYPE(t)) {
+                                               N_LR(GET_HIGH_REG(s2), GET_HIGH_REG(s1));
+                                               N_LR(GET_LOW_REG(s2), GET_LOW_REG(s1));
+                                       } else {
+                                               N_LR(s2, s1);
+                                       }
+                               } else {
+                                       s2 = nmd->params[j].regoff;
+                                       if (IS_2_WORD_TYPE(t)) {
+                                               N_LM(GET_LOW_REG(s1), GET_HIGH_REG(s1), 96 + (s2 * 4), REG_SP);
+                                       } else {
+                                               N_L(s1, 96 + (s2 * 4), 0, REG_SP);
+                                       }
+                               }
+
+                       } else {
+                               s1 = md->params[i].regoff + cd->stackframesize + 1;   /* + 1 (RA) */
+                               s2 = nmd->params[j].regoff;
+                               
+                               if (IS_2_WORD_TYPE(t)) {
+                                       N_MVC(96 + (s2 * 4), 8, REG_SP, s1, REG_SP);
+                               } else {
+                                       N_MVC(96 + (s2 * 4), 4, REG_SP, s1, REG_SP);
+                               }
+                       }
+
+               } else {
+                       /* We only copy spilled float arguments, as the float argument    */
+                       /* registers keep unchanged.                                      */
+
+                       if (md->params[i].inmemory) {
+                               s1 = md->params[i].regoff + cd->stackframesize + 1;   /* + 1 (RA) */
+                               s2 = nmd->params[j].regoff;
+
+                               if (IS_2_WORD_TYPE(t)) {
+                                       N_MVC(96 + (s2 * 4), 8, REG_SP, s1, REG_SP);
+                               } else {
+                                       N_MVC(96 + (s2 * 4), 4, REG_SP, s1, REG_SP);
+                               }
+                       }
+               }
+       }
+
+       /* put class into second argument register */
+
+       if (m->flags & ACC_STATIC) {
+               disp = dseg_add_address(cd, m->class);
+               N_L2(REG_A1, disp, REG_PV);
+       }
+
+       /* put env into first argument register */
+
+       disp = dseg_add_address(cd, _Jv_env);
+       N_L2(REG_A0, disp, REG_PV);
+
+       /* do the native function call */
+
+       M_CALL(REG_ITMP3); /* call */
+
+       /* save return value */
+
+       t = md->returntype.type;
+
+       if (t != TYPE_VOID) {
+               if (IS_INT_LNG_TYPE(t)) {
+                       if (IS_2_WORD_TYPE(t)) {
+                               N_STM(REG_RESULT, REG_RESULT2, 96, REG_SP);
+                       } else {
+                               N_ST(REG_RESULT, 96, 0, REG_SP);
+                       }
+               } else {
+                       if (IS_2_WORD_TYPE(t)) {
+                               N_STD(REG_FRESULT, 96, 0, REG_SP);
+                       } else {
+                               N_STE(REG_FRESULT, 96, 0, REG_SP);
+                       }
+               }
+       }
+
+#if 0
+#if !defined(NDEBUG)
+       if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
+               emit_verbosecall_exit(jd);
+#endif
+#endif
+
+       /* remove native stackframe info */
+
+       N_LAE(REG_A0, cd->stackframesize * 4, 0, REG_SP);
+       disp = dseg_add_functionptr(cd, codegen_finish_native_call);
+       N_L2(REG_ITMP1, disp, REG_PV);
+       M_CALL(REG_ITMP1);
+       N_LR(REG_ITMP3, REG_RESULT);
+
+       /* restore return value */
+
+       if (t != TYPE_VOID) {
+               if (IS_INT_LNG_TYPE(t)) {
+                       if (IS_2_WORD_TYPE(t)) {
+                               N_LM(REG_RESULT, REG_RESULT2, 96, REG_SP);
+                       } else {
+                               N_L(REG_RESULT, 96, 0, REG_SP);
+                       }
+               } else {
+                       if (IS_2_WORD_TYPE(t)) {
+                               N_LD(REG_FRESULT, 96, 0, REG_SP);
+                       } else {
+                               N_LE(REG_FRESULT, 96, 0, REG_SP);
+                       }
+               }
+       }
+
+       /* remove stackframe */
+
+       N_AHI(REG_SP, cd->stackframesize * 4);
+
+       /* test for exception */
+
+       N_LTR(REG_ITMP3, REG_ITMP3);
+       N_BRC(DD_NE, SZ_BRC + SZ_BC);
+       N_BC(DD_ANY, 0, 0, REG_SP); /* return */
+
+       /* handle exception */
+
+       N_LONG_0();
+
+#if 0
+       M_MOV(REG_ITMP3, REG_ITMP1_XPTR);
+       M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);     /* get return address from stack */
+       M_ASUB_IMM(3, REG_ITMP2_XPC);                                    /* callq */
+
+       M_MOV_IMM(asm_handle_nat_exception, REG_ITMP3);
+       M_JMP(REG_ITMP3);
+
+       /* generate patcher stubs */
+
+       emit_patcher_stubs(jd);
+
+#endif
+       codegen_finish(jd);
+
+       return code->entrypoint;
+       return NULL;
+}
+
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
diff --git a/src/vm/jit/s390/codegen.h b/src/vm/jit/s390/codegen.h
new file mode 100644 (file)
index 0000000..a34fa8f
--- /dev/null
@@ -0,0 +1,695 @@
+/* src/vm/jit/x86_64/codegen.h - code generation macros for x86_64
+
+   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: Andreas Krall
+            Christian Thalinger
+
+   $Id: codegen.h 7219 2007-01-16 22:18:57Z pm $
+
+*/
+
+
+#ifndef _CODEGEN_H
+#define _CODEGEN_H
+
+#include "config.h"
+
+#include <ucontext.h>
+
+#include "vm/types.h"
+
+#include "vm/jit/jit.h"
+
+
+/* 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;
+
+
+/* gen_nullptr_check(objreg) */
+
+#define gen_nullptr_check(objreg) \
+       if (checknull) { \
+        M_TEST(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_ICMP(REG_ITMP3, s2); \
+        M_BAE(0); \
+        codegen_add_arrayindexoutofboundsexception_ref(cd, s2); \
+    }
+
+
+/* MCODECHECK(icnt) */
+
+#define MCODECHECK(icnt) \
+    do { \
+        if ((cd->mcodeptr + (icnt)) > cd->mcodeend) \
+            codegen_increase(cd); \
+    } while (0)
+
+
+#define ALIGNCODENOP \
+    if ((s4) (((ptrint) cd->mcodeptr) & 7)) { \
+        M_NOP; \
+    }
+
+
+/* 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_INTMOVE(reg,dreg) \
+    do { \
+        if ((reg) != (dreg)) { \
+            M_MOV(reg, dreg); \
+        } \
+    } while (0)
+
+
+/* M_FLTMOVE:
+    generates a floating-point-move from register a to b.
+    if a and b are the same float-register, no code will be generated
+*/ 
+
+#define M_FLTMOVE(reg,dreg) \
+    do { \
+        if ((reg) != (dreg)) { \
+            M_FMOV(reg, dreg); \
+        } \
+    } while (0)
+
+
+#define ICONST(r,c) \
+    do { \
+        if ((c) == 0) \
+            M_CLR((d)); \
+        else \
+            M_IMOV_IMM((c), (d)); \
+    } while (0)
+/*     do { \ */
+/*        M_IMOV_IMM((c), (d)); \ */
+/*     } while (0) */
+
+
+#define LCONST(r,c) \
+    do { \
+        if ((c) == 0) \
+            M_CLR((d)); \
+        else \
+            M_MOV_IMM((c), (d)); \
+    } while (0)
+
+
+/* some patcher defines *******************************************************/
+
+#define PATCHER_CALL_SIZE    5          /* size in bytes of a patcher call    */
+
+#define PATCHER_NOPS \
+    do { \
+        M_NOP; \
+        M_NOP; \
+        M_NOP; \
+        M_NOP; \
+        M_NOP; \
+    } while (0)
+
+
+/* macros to create code ******************************************************/
+
+/* Conventions:
+ * N_foo:   defines the instrucition foo as in `ESA/390 Principles of operations'
+ * SZ_foo:  defines the size of the instruction N_foo
+ * DD_foo:  defines a condition code as used by s390 GCC
+ * M_foo:   defines the alpha like instruction used in cacao
+ *          the instruction is defined by an equivalent N_ instruction
+ * CC_foo:  defines a condition code as used
+ *          the instruction is defined as an equivalent DD_ condition code
+ */
+
+/* S390 specific code */
+
+/* Instruction formats */
+
+#define _CODE(t, code) \
+       do { \
+               *((t *) cd->mcodeptr) = (code); \
+               cd->mcodeptr += sizeof(t); \
+       } while (0);
+
+#define _CODE2(code) _CODE(u2, code)
+#define _CODE4(code) _CODE(u4, code)
+
+#define _IFNEG(val, neg, pos) \
+       do { if ((val) < 0) { neg ; } else { pos ; } } while (0)
+
+#define N_RR(op, r1, r2) \
+       _CODE2( (op << 8) | (r1 << 4) | (r2) )
+
+#define SZ_RR 2
+
+#define N_RR2(op, i) \
+       _CODE2( (op << 8) | (i) )
+
+#define N_RX(op, r1, d2, x2, b2) \
+       _CODE4( ((op) << 24) | ((r1) << 20) | ((x2) << 16) | ((b2) << 12) | ((d2) << 0) )
+
+#define SZ_RX 4
+
+#define N_RI(op1, op2, r1, i2) \
+       _CODE4( ((op1) << 24) | ((r1) << 20) | ((op2) << 16) | ((u2) i2) )
+
+#define SZ_RI 4
+
+#define N_SI(op, d1, b1, i2) \
+       _CODE4( ((op) << 24) | ((i2) << 16) | ((b1) << 12) | (d1) )
+
+#define SZ_SI 4
+
+#define N_SS(op, d1, l, b1, d2, b2) \
+       _CODE4( ((op) << 24) | ((l) << 16) | ((b1) << 12) | (d1) ) \
+       _CODE2( ((b2) << 12) | (d2) )
+
+#define SZ_SS 6
+
+#define N_SS2(op, d1, l1, b1, d2, l2, b2) \
+       N_SS(op, d1, ((l1) << 4) | (l2), b1, d2, l2)
+
+#define N_RS(op, r1, r3, d2, b2) \
+       _CODE4( ((op) << 24) | ((r1) << 20) | ((r3) << 16) | ((b2) << 12) | (d2) )
+
+#define SZ_RS 4
+
+#define N_RSI(op, r1, r2, i2) \
+       _CODE4( ((op) << 24) | ((r1) << 20) | ((r3) << 16) | ((u2)i2) )
+
+#define SZ_RSI 4
+
+#define N_RRE(op, r1, r2) \
+       _CODE4( ((op) << 16) | ((r1) << 4) | (r2) )
+
+#define SZ_RRE 4
+
+#define N_S2(d2, b2) \
+       _CODE4( ((op) << 16) | ((b2) << 12) | (d2)  )
+
+#define SZ_S2 4
+
+#define N_E(op) \
+       _CODE2( (op) )
+
+#define SZ_E 2
+
+/* Condition codes */
+
+#define DD_O 1
+#define DD_H 2
+#define DD_NLE 3
+#define DD_L 4
+#define DD_NHE 5
+#define DD_LH 6
+#define DD_NE 7
+#define DD_E 8
+#define DD_NLH 9
+#define DD_HE 10
+#define DD_NL 11
+#define DD_LE 12
+#define DD_NH 13
+#define DD_NO 14
+#define DD_ANY 15
+
+/* Misc */
+
+#define N_LONG_0() _CODE4(0)
+
+/* Chapter 7. General instructions */
+
+#define N_AR(r1, r2) N_RR(0x1A, r1, r2)
+#define N_A(r1, d2, x2, b2) N_RX(0x5A, r1, d2, x2, b2)
+#define N_AH(r1, d2, x2, b2) N_RX(0x4A, r1, d2, x2, b2)
+#define N_AHI(r1, i2) N_RI(0xA7, 0xA, r1, i2)
+#      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_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)
+#define N_BALR(r1, r2) N_RR(0x05, r1, r2)
+#define N_BAL(r1, d2, x2, b2) N_RX(0x45, r1, d2, x2, b2)
+#define N_BASR(r1, r2) N_RR(0x0D, r1, r2)
+#define N_BAS(r1, d2, x2, b2) N_RX(0x4D, r1, d2, x2, b2)
+#define N_BASSM(r1, r2) N_RR(0x0C, r1, r2)
+#define N_BSM(r1, r2) N_RR(0x0B, r1, r2)
+#define N_BCR(m1, r2) N_RR(0x07, m1, r2)
+#      define SZ_BCR SZ_RR
+#      define N_BR(r2) N_BCR(DD_ANY, r2)
+#      define SZ_BR SZ_BCR
+#define N_BC(m1, d2, x2, b2) N_RS(0x47, m1, d2, x2, b2)
+#      define SZ_BC SZ_RS
+#define N_BCTR(r1, r2) N_RR(0x06, r1, r2)
+#define N_BCT(r1, d2, x2, b2) N_RX(0x46, r1, d2, x2, b2)
+#define N_BHX(r1, r2, d2, b2) N_RS(0xB6, r1, r3, d2, b2)
+#define N_BXLE(r1, r3, d2, b2) N_RS(0xB7, r1, r3, d2, b2)
+#define N_BRAS(r1, i2) N_RI(0xA7, 0x5, r1, (i2) / 2)
+#      define SZ_BRAS SZ_RI
+#define N_BRC(m1, i2) N_RI(0xA7, 0x4, m1, (i2) / 2)
+#      define N_J(i2) N_BRC(DD_ANY, i2)
+#      define SZ_BRC SZ_RI
+#      define SZ_J SZ_RI
+#define N_BRCT(r1, i2) N_RI(0xA7, 0x6, r1, (i2) / 2)
+#define N_BRXH(r1, r3, i2) N_RSI(0x84, r1, r3, (i2) / 2)
+#define N_BRXLE(r1, r3, i2) N_RSI(0x85, r1, r2, (i2) / 2)
+#define N_CKSM(r1, r2) N_RRE(0xB241, r1, r2)
+#define N_CR(r1, r2), N_RR(0x19, r1, r2)
+#define N_C(r1, d2, x2, b2) N_RX(0x59, r1, d2, x2, b2)
+#define N_CFC(d2, b2) N_S2(0xB21A, d2, b2)
+#define N_CS(r1, r3, d2, b2) N_RS(0xBA, r1, r3, d2, b2)
+#define N_CDS(r1, r3, d2, b2) N_RS(0xBB, r1, r3, d2, b2)
+#define N_CH(r1, d2, x2, b2) N_CH(0x49, r1, d2, x2, b2)
+#define N_CHI(r1, i2) N_RI(0xA7, 0xE, r1, i2)
+#define N_CLR(r1, r2) N_RR(0x15, r1, r2)
+#define N_CL(r1, d2, x2, b2) N_RX(0x55, r1, d2, x2, b2)
+#define N_CLI(d1, b1, i2) N_SI(0x95, d1, b1, i2)
+#define N_CLC(d1, l, b1, d2, b2) N_SS(0xD5, d1, l, b1, d2, b2)
+#define N_CLM(r1, m3, d2, b2) N_RS(0xBD, r1, m3, d2, b2)
+#define N_CLCL(r1, r2) N_RR(0x0F, r1, r2)
+#define N_CLCLE(r1, r3, d2, b2) N_RS(0xA9, r1, r3, d2, b2)
+#define N_CLST(r1, r2) N_RRE(0xB25D, r1, r2)
+#define N_CUSE(r1, r2) N_RRE(0xB257, r1, r2)
+#define N_CVB(r1, d2, x2, b2) N_RX(0x4F, r1, r2, x2, b2)
+#define N_CVD(r1, d2, x2, b2) N_RX(0x4E, r1, d2, x2, b2)
+#define N_CUUTF(r1, r2) N_RRE(0xB2A6, r1, r2)
+#define N_CUTFU(r1, r2) N_RRE(0xB2A7, r1, r2)
+#define N_CPYA(r1, r2) N_RRE(0xB240, r1, r2)
+#define N_DR(r1, r2) N_RR(0x1D, r1, r2)
+#define N_D(r1, d2, x2, b2) N_RX(0x5D, r1, d2, x2, b2)
+#define N_XR(r1, r2) N_RR(0x17, r1, r2)
+#define N_X(r1, d2, x2, b2) N_RX(0x57, r1, d2, x2, b2)
+#define N_XI(d1, b1, i2) N_SI(0x97, d1, b1, i2)
+#define N_XC(d1, l, b1, d2, b2) N_SS(0xD7, d1, l, b1, d2, b2)
+#define N_EX(r1, d2, x2, b2) N_RX(0x44, r1, d2, x2, b2)
+#define N_EAR(r1, r2) N_RRE(0xB24F, r1, r2)
+#define N_IC(r1, d2, x2, b2) N_RX(0x43, r1, d2, x2, b2)
+#define N_ICM(r1, m3, d2, b2) N_RS(0xBF, r1, m3, d2, b2)
+#define N_IPM(r1) N_RRE(0xB222, r1, 0)
+#define N_LR(r1, r2) N_RR(0x18, r1, r2)
+#define N_L(r1, d2, x2, b2) N_RX(0x58, r1, d2, x2, b2)
+#      define SZ_L SZ_RX
+#      define N_L2(r1, d2, b2) \
+               do { N_LHI(r1, d2); N_L(r1, 0, r1, b2); } while (0)
+#define N_LAM(r1, r3, d2, b2) N_RS(0x9A, r1, r3, d2, b2)
+#define N_LA(r1, d2, x2, b2) N_RX(0x41, r1, d2, x2, b2)
+#      define N_LA2(r1, d2, b2) \
+               do { N_LHI(r1, d2); N_LA(r1, 0, r1, b2); } while (0)
+#define N_LAE(r1, d2, x2, b2) N_RX(0x51, r1, d2, x2, b2)
+#define N_LTR(r1, r2) N_RR(0x12, r1, r2)
+#define N_LCR(r1, r2) N_RR(0x13, r1, r2)
+#define N_LH(r1, d2, x2, b2) N_RX(0x48, r1, d2, x2, b2)
+#define N_LHI(r1, i2) N_RI(0xA7, 0x8, r1, i2)
+#define N_LM(r1, r3, d2, b2) N_RS(0x98, r1, r3, d2, b2)
+#define N_LNR(r1, r2) N_RR(0x11, r1, r2)
+#define N_LPR(r1, r2) N_RR(0x10, r1, r2)
+#define N_MC(d1, b1, i2) N_SI(0xAF, d1, b1, i2)
+#define N_MVI(d1, b1, i2) N_SI(0x92, d1, b1, i2)
+#define N_MVC(d1, l, b1, d2, b2) N_SS(0xD2, d1, l, b1, d2, b2)
+#define N_MVCIN(d1, l, b1, d2, b2) N_SS(0xEB, d1, l, b1, d2, b2)
+#define N_MVCL(r1, r2) N_RR(0x0E, r1, r2)
+#define N_MVCLE(r1, r3, d2, b2)  N_RS(0xAB, r1, r3, d2, b2)
+#define N_MVN(d1, l, b1, d2, b2) N_SS(0xD1, d1, l, b1, d2, b2)
+#define N_MVPG(r1, r2) N_RRE(0xB254, r1, r2)
+#define N_MVST(r1, r2) N_RRE(0xB255, r1, r2)
+#define N_MVO(d1, l1, b1, d2, l2, b2) N_SS2(0xF1, d1, l1, b1, d2, l2, b2)
+#define N_MVZ(d1, l, b1, d2, b2) N_SS(0xD3, d1, l, b1, d2, b2)
+#define N_MR(r1, r2) N_RR(0x1C, r1, r2)
+#define N_M(r1, d2, x2, b2) N_RX(0x5C, r1, d2, x2, b2)
+#define N_MH(r1, d2, x2, b2) N_RX(0x4C, r1, d2, x2, b2)
+#define N_MHI(r1, i2) N_RI(0xA7, 0xC, r1, i2)
+#define N_MSR(r1, r2) N_RRE(0xB252, r1, r2)
+#define N_MS(r1, d2, x2, b2) N_RX(0x71, r1, d2, x2, b2)
+#define N_OR(r1, r2) N_RR(0x16, r1, r2)
+#define N_O(r1, d2, x2, b2) N_RX(0x56, r1, d2, x2, b2)
+#define N_OI(d1, b1, i2) N_SI(0x96, d1, b1, i2)
+#define N_OC(d1, l, b1, d2, b2) N_SS(0xD6, d1, l, b1, d2, b2)
+#define N_PACK(d1, l1, b1, d2, l2, b2) N_SS2(0xF2, d1, l1, b1, d2, l2, b2)
+#define N_PLO(r1, d2, b2, r3, d4, b4) N_SS2(0xEE, d2, r1, b2, d4, r3, b4)
+#define N_SRST(r1, r2) N_RRE(0xB25E, r1, r2)
+#define N_SAR(r1, r2) N_RRE(0xB24E, r1, r2)
+#define N_SPM(r1) N_RR(0x04, r1, 0x00)
+#define N_SLDA(r1, d2, b2) N_RS(0x8F, r1, 0x00, d2, b2)
+#define N_SLDL(r1, d2, b2) N_RS(0x8D, r1, 0x00, d2, b2)
+#define N_SLA(r1, d2, b2) N_RS(0x8B, r1, 0x00, d2, b2)
+#define N_SLL(r1, d2, b2) N_RS(0x89, r1, 0x00, d2, b2)
+#define N_SRDA(r1, d2, b2) N_RS(0x8E, r1, 0x00, d2, b2)
+#define N_SRDL(r1, d2, b2) N_RS(0x8C, r1, 0x00, d2, b2)
+#define N_SRA(r1, d2, b2) N_RS(0x8A, r1, 0x00, d2, b2)
+#define N_SRL(r1, d2, b2) N_RS(0x88, r1, 0x00, d2, b2)
+#define N_ST(r1, d2, x2, b2) N_RX(0x50, r1, d2, x2, b2)
+#define N_STAM(r1, r3, d2, b2) N_RS(0x9B, r1, r3, d2, b2)
+#define N_STC(r1, d2, x2, b2) N_RX(0x42, r1, d2, x2, b2)
+#define N_STCM(r1, m3, d2, b2) N_RS(0xBE, r1, m3, d2, b2)
+#define N_STCK(d2, b2) N_S2(0xB205, d2, b2)
+#define N_STCKE(d2, b2) N_S2(0xB278, d2, b2)
+#define N_STH(r1, d2, x2, b2) N_RX(0x40, r1, d2, x2, b2)
+#define N_STM(r1, r3, d2, b2) N_RS(0x90, r1, r3, d2, b2)
+#define N_SR(r1, r2) N_RR(0x1B, r1, r2)
+#define N_S(r1, d2, x2, b2) N_RX(0x5B, r1, d2, x2, b2)
+#define N_SH(r1, d2, x2, b2) N_RX(0x4B, r1, d2, x2, b2)
+#define N_SLR(r1, r2) N_RR(0x1F, r1, r2)
+#define N_SL(r1, d2, x2, b2) N_RX(0x5F, r1, d2, x2, b2)
+#define N_SVC(i) N_RR2(0x0A, i)
+#define N_TS(d2, b2) N_S2(0x93, d2, b2)
+#define N_TM(d1, b1, i2) N_SI(0x91, d1, b1, i2)
+#define N_TMH(r1, i2) N_RI(0xA7, 0x00, r1, i2)
+#define N_TML(r1, i2) N_RI(0xA7, 0x01, r1, i2)
+#define N_TR(d1, l, b1, d2, b2) N_SS(0xDC, d1, l, b1, d2, b2)
+#define N_TRT(d1, l, b1, d2, b2) N_SS(0xDD, d1, l, b1, d2, b2)
+#define N_TRE(r1, r2) N_RRE(0xB2A5, r1, r2)
+#define N_UNPK(d1, l1, b1, d2, l2, b2) N_SS2(0xF3, d1, l1, b1, d2, l2, b2)
+#define N_UPT() N_E(0x0102)
+
+/* Chapter 9. Floating point instructions */
+
+#define N_LER(r1, r2) N_RR(0x38, r1, r2)
+#define N_LDR(r1, r2) N_RR(0x28, r1, r2)
+#define N_LXR(r1, r2) N_RRE(0xB365, r1, r2)
+#define N_LE(r1, d2, x2, b2) N_RX(0x78, r1, d2, x2, b2)
+#define N_LD(r1, d2, x2, b2) N_RX(0x68, r1, d2, x2, b2)
+#define N_LZER(r1) N_RRE(0xB374, r1, 0x0)
+#define N_LZDR(r1) N_RRE(0xB375, r1, 0x0)
+#define N_LZXR(r1) N_RRE(0xB376, r1, 0x0)
+#define N_STE(r1, d2, x2, b2) N_RX(0x70, r1, d2, x2, b2)
+#define N_STD(r1, d2, x2, b2) N_RX(0x60, r1, d2, x2, b2)
+
+/* chapter 19. Binary floating point instructions */
+
+/* Alpha like instructions */
+
+#define M_CALL(r2) N_BASR(R14, r2)
+
+#define M_ALD(r, b, d) _IFNEG(d, N_L2(r, d, b), N_L(r, d, 0, b))
+#define M_ILD(r, b, d) _IFNEG(d, N_LA2(r, d, b), N_LA(r, d, 0, b))
+#define M_FLD(r, b, d) _IFNEG(d, assert(0), N_LE(r, d, 0, b))
+#define M_DLD(r, b, d) _IFNEG(d, assert(0), N_LD(r, d, 0, b))
+/* TODO 3 instead of 4 instrs for d < 0 ! */
+#define M_LLD(r, b, d) \
+       do { M_ILD(GET_HIGH_REG(r), b, d); M_ILD(GET_LOW_REG(r), b, d + 4); } while(0)
+
+/* ----------------------------------------------- */
+
+#define M_MOV(a,b)              emit_mov_reg_reg(cd, (a), (b))
+#define M_MOV_IMM(a,b)          emit_mov_imm_reg(cd, (u8) (a), (b))
+
+#define M_IMOV(a,b)             emit_movl_reg_reg(cd, (a), (b))
+#define M_IMOV_IMM(a,b)         emit_movl_imm_reg(cd, (u4) (a), (b))
+
+#define M_FMOV(a,b)             emit_movq_reg_reg(cd, (a), (b))
+
+#define M__ILD(a,b,disp)         emit_movl_membase_reg(cd, (b), (disp), (a))
+#define M__LLD(a,b,disp)         emit_mov_membase_reg(cd, (b), (disp), (a))
+
+#define M_ILD32(a,b,disp)       emit_movl_membase32_reg(cd, (b), (disp), (a))
+#define M_LLD32(a,b,disp)       emit_mov_membase32_reg(cd, (b), (disp), (a))
+
+#define M_IST(a,b,disp)         emit_movl_reg_membase(cd, (a), (b), (disp))
+#define M_LST(a,b,disp)         emit_mov_reg_membase(cd, (a), (b), (disp))
+
+#define M_IST_IMM(a,b,disp)     emit_movl_imm_membase(cd, (a), (b), (disp))
+#define M_LST_IMM32(a,b,disp)   emit_mov_imm_membase(cd, (a), (b), (disp))
+
+#define M_IST32(a,b,disp)       emit_movl_reg_membase32(cd, (a), (b), (disp))
+#define M_LST32(a,b,disp)       emit_mov_reg_membase32(cd, (a), (b), (disp))
+
+#define M_IST32_IMM(a,b,disp)   emit_movl_imm_membase32(cd, (a), (b), (disp))
+#define M_LST32_IMM32(a,b,disp) emit_mov_imm_membase32(cd, (a), (b), (disp))
+
+#define M_IADD(a,b)             emit_alul_reg_reg(cd, ALU_ADD, (a), (b))
+#define M_ISUB(a,b)             emit_alul_reg_reg(cd, ALU_SUB, (a), (b))
+#define M_IMUL(a,b)             emit_imull_reg_reg(cd, (a), (b))
+
+#define M_IADD_IMM(a,b)         emit_alul_imm_reg(cd, ALU_ADD, (a), (b))
+#define M_ISUB_IMM(a,b)         emit_alul_imm_reg(cd, ALU_SUB, (a), (b))
+#define M_IMUL_IMM(a,b,c)       emit_imull_imm_reg_reg(cd, (b), (a), (c))
+
+#define M_LADD(a,b)             emit_alu_reg_reg(cd, ALU_ADD, (a), (b))
+#define M_LSUB(a,b)             emit_alu_reg_reg(cd, ALU_SUB, (a), (b))
+#define M_LMUL(a,b)             emit_imul_reg_reg(cd, (a), (b))
+
+#define M_LADD_IMM(a,b)         emit_alu_imm_reg(cd, ALU_ADD, (a), (b))
+#define M_LSUB_IMM(a,b)         emit_alu_imm_reg(cd, ALU_SUB, (a), (b))
+#define M_LMUL_IMM(a,b,c)       emit_imul_imm_reg_reg(cd, (b), (a), (c))
+
+#define M_IINC(a)               emit_incl_reg(cd, (a))
+#define M_IDEC(a)               emit_decl_reg(cd, (a))
+
+#define M__ALD(a,b,disp)         M_LLD(a,b,disp)
+#define M_ALD32(a,b,disp)       M_LLD32(a,b,disp)
+
+#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(a,b)             M_LADD(a,b)
+#define M_AADD_IMM(a,b)         M_LADD_IMM(a,b)
+#define M_ASUB_IMM(a,b)         M_LSUB_IMM(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_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_INEG(a)               emit_negl_reg(cd, (a))
+#define M_LNEG(a)               emit_neg_reg(cd, (a))
+
+#define M_IAND(a,b)             emit_alul_reg_reg(cd, ALU_AND, (a), (b))
+#define M_IOR(a,b)              emit_alul_reg_reg(cd, ALU_OR, (a), (b))
+#define M_IXOR(a,b)             emit_alul_reg_reg(cd, ALU_XOR, (a), (b))
+
+#define M_IAND_IMM(a,b)         emit_alul_imm_reg(cd, ALU_AND, (a), (b))
+#define M_IOR_IMM(a,b)          emit_alul_imm_reg(cd, ALU_OR, (a), (b))
+#define M_IXOR_IMM(a,b)         emit_alul_imm_reg(cd, ALU_XOR, (a), (b))
+
+#define M_LAND(a,b)             emit_alu_reg_reg(cd, ALU_AND, (a), (b))
+#define M_LOR(a,b)              emit_alu_reg_reg(cd, ALU_OR, (a), (b))
+#define M_LXOR(a,b)             emit_alu_reg_reg(cd, ALU_XOR, (a), (b))
+
+#define M_LAND_IMM(a,b)         emit_alu_imm_reg(cd, ALU_AND, (a), (b))
+#define M_LOR_IMM(a,b)          emit_alu_imm_reg(cd, ALU_OR, (a), (b))
+#define M_LXOR_IMM(a,b)         emit_alu_imm_reg(cd, ALU_XOR, (a), (b))
+
+#define M_BSEXT(a,b)            emit_movsbq_reg_reg(cd, (a), (b))
+#define M_SSEXT(a,b)            emit_movswq_reg_reg(cd, (a), (b))
+#define M_ISEXT(a,b)            emit_movslq_reg_reg(cd, (a), (b))
+
+#define M_CZEXT(a,b)            emit_movzwq_reg_reg(cd, (a), (b))
+
+#define M_ISLL_IMM(a,b)         emit_shiftl_imm_reg(cd, SHIFT_SHL, (a), (b))
+#define M_ISRA_IMM(a,b)         emit_shiftl_imm_reg(cd, SHIFT_SAR, (a), (b))
+#define M_ISRL_IMM(a,b)         emit_shiftl_imm_reg(cd, SHIFT_SHR, (a), (b))
+
+#define M_LSLL_IMM(a,b)         emit_shift_imm_reg(cd, SHIFT_SHL, (a), (b))
+#define M_LSRA_IMM(a,b)         emit_shift_imm_reg(cd, SHIFT_SAR, (a), (b))
+#define M_LSRL_IMM(a,b)         emit_shift_imm_reg(cd, SHIFT_SHR, (a), (b))
+
+#define M_TEST(a)               emit_test_reg_reg(cd, (a), (a))
+#define M_ITEST(a)              emit_testl_reg_reg(cd, (a), (a))
+
+#define M_LCMP(a,b)             emit_alu_reg_reg(cd, ALU_CMP, (a), (b))
+#define M_LCMP_IMM(a,b)         emit_alu_imm_reg(cd, ALU_CMP, (a), (b))
+#define M_LCMP_IMM_MEMBASE(a,b,c) emit_alu_imm_membase(cd, ALU_CMP, (a), (b), (c))
+#define M_LCMP_MEMBASE(a,b,c)   emit_alu_membase_reg(cd, ALU_CMP, (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_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_BEQ(disp)             emit_jcc(cd, CC_E, (disp))
+#define M_BNE(disp)             emit_jcc(cd, CC_NE, (disp))
+#define M_BLT(disp)             emit_jcc(cd, CC_L, (disp))
+#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_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_CMOVLT(a,b)           emit_cmovcc_reg_reg(cd, CC_L, (a), (b))
+#define M_CMOVLE(a,b)           emit_cmovcc_reg_reg(cd, CC_LE, (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_CMOVP(a,b)            emit_cmovcc_reg_reg(cd, CC_P, (a), (b))
+
+#define M_PUSH(a)               emit_push_reg(cd, (a))
+#define M_PUSH_IMM(a)           emit_push_imm(cd, (a))
+#define M_POP(a)                emit_pop_reg(cd, (a))
+
+#define M_JMP(a)                emit_jmp_reg(cd, (a))
+#define M_JMP_IMM(a)            emit_jmp_imm(cd, (a))
+#define M__CALL(a)               emit_call_reg(cd, (a))
+#define M_CALL_IMM(a)           emit_call_imm(cd, (a))
+#define M_RET                   emit_ret(cd)
+
+#define M_NOP                   emit_nop(cd)
+
+#define M_CLR(a)                M_LXOR(a,a)
+
+
+#define M__FLD(a,b,disp)         emit_movss_membase_reg(cd, (b), (disp), (a))
+#define M__DLD(a,b,disp)         emit_movsd_membase_reg(cd, (b), (disp), (a))
+
+#define M_FLD32(a,b,disp)       emit_movss_membase32_reg(cd, (b), (disp), (a))
+#define M_DLD32(a,b,disp)       emit_movsd_membase32_reg(cd, (b), (disp), (a))
+
+#define M_FST(a,b,disp)         emit_movss_reg_membase(cd, (a), (b), (disp))
+#define M_DST(a,b,disp)         emit_movsd_reg_membase(cd, (a), (b), (disp))
+
+#define M_FST32(a,b,disp)       emit_movss_reg_membase32(cd, (a), (b), (disp))
+#define M_DST32(a,b,disp)       emit_movsd_reg_membase32(cd, (a), (b), (disp))
+
+#define M_FADD(a,b)             emit_addss_reg_reg(cd, (a), (b))
+#define M_DADD(a,b)             emit_addsd_reg_reg(cd, (a), (b))
+#define M_FSUB(a,b)             emit_subss_reg_reg(cd, (a), (b))
+#define M_DSUB(a,b)             emit_subsd_reg_reg(cd, (a), (b))
+#define M_FMUL(a,b)             emit_mulss_reg_reg(cd, (a), (b))
+#define M_DMUL(a,b)             emit_mulsd_reg_reg(cd, (a), (b))
+#define M_FDIV(a,b)             emit_divss_reg_reg(cd, (a), (b))
+#define M_DDIV(a,b)             emit_divsd_reg_reg(cd, (a), (b))
+
+#define M_CVTIF(a,b)            emit_cvtsi2ss_reg_reg(cd, (a), (b))
+#define M_CVTID(a,b)            emit_cvtsi2sd_reg_reg(cd, (a), (b))
+#define M_CVTLF(a,b)            emit_cvtsi2ssq_reg_reg(cd, (a), (b))
+#define M_CVTLD(a,b)            emit_cvtsi2sdq_reg_reg(cd, (a), (b))
+#define M_CVTFI(a,b)            emit_cvttss2si_reg_reg(cd, (a), (b))
+#define M_CVTDI(a,b)            emit_cvttsd2si_reg_reg(cd, (a), (b))
+#define M_CVTFL(a,b)            emit_cvttss2siq_reg_reg(cd, (a), (b))
+#define M_CVTDL(a,b)            emit_cvttsd2siq_reg_reg(cd, (a), (b))
+
+#define M_CVTFD(a,b)            emit_cvtss2sd_reg_reg(cd, (a), (b))
+#define M_CVTDF(a,b)            emit_cvtsd2ss_reg_reg(cd, (a), (b))
+
+
+/* system instructions ********************************************************/
+
+#define M_RDTSC                 emit_rdtsc(cd)
+
+#define M_IINC_MEMBASE(a,b)     emit_incl_membase(cd, (a), (b))
+
+#define M_IADD_MEMBASE(a,b,c)   emit_alul_reg_membase(cd, ALU_ADD, (a), (b), (c))
+#define M_IADC_MEMBASE(a,b,c)   emit_alul_reg_membase(cd, ALU_ADC, (a), (b), (c))
+#define M_ISUB_MEMBASE(a,b,c)   emit_alul_reg_membase(cd, ALU_SUB, (a), (b), (c))
+#define M_ISBB_MEMBASE(a,b,c)   emit_alul_reg_membase(cd, ALU_SBB, (a), (b), (c))
+
+#define PROFILE_CYCLE_START
+#define __PROFILE_CYCLE_START \
+    do { \
+        if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) { \
+            M_PUSH(RAX); \
+            M_PUSH(RDX); \
+            \
+            M_MOV_IMM(code, REG_ITMP3); \
+            M_RDTSC; \
+            M_ISUB_MEMBASE(RAX, REG_ITMP3, OFFSET(codeinfo, cycles)); \
+            M_ISBB_MEMBASE(RDX, REG_ITMP3, OFFSET(codeinfo, cycles) + 4); \
+            \
+            M_POP(RDX); \
+            M_POP(RAX); \
+        } \
+    } while (0)
+
+#define PROFILE_CYCLE_STOP 
+#define __PROFILE_CYCLE_STOP \
+    do { \
+        if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) { \
+            M_PUSH(RAX); \
+            M_PUSH(RDX); \
+            \
+            M_MOV_IMM(code, REG_ITMP3); \
+            M_RDTSC; \
+            M_IADD_MEMBASE(RAX, REG_ITMP3, OFFSET(codeinfo, cycles)); \
+            M_IADC_MEMBASE(RDX, REG_ITMP3, OFFSET(codeinfo, cycles) + 4); \
+            \
+            M_POP(RDX); \
+            M_POP(RAX); \
+        } \
+    } while (0)
+
+
+/* function gen_resolvebranch **************************************************
+
+    backpatches a branch instruction
+
+    parameters: ip ... pointer to instruction after branch (void*)
+                so ... offset of instruction after branch  (s8)
+                to ... offset of branch target             (s8)
+
+*******************************************************************************/
+
+#define gen_resolvebranch(ip,so,to) \
+    *((s4*) ((ip) - 4)) = (s4) ((to) - (so));
+
+#endif /* _CODEGEN_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/s390/disass.c b/src/vm/jit/s390/disass.c
new file mode 100644 (file)
index 0000000..4077fe5
--- /dev/null
@@ -0,0 +1,129 @@
+/* src/vm/jit/x86_64/disass.c - wrapper functions for GNU binutils disassembler
+
+   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: Andreas  Krall
+            Reinhard Grafl
+
+   Changes: Christian Thalinger
+
+   $Id: disass.c 7219 2007-01-16 22:18:57Z pm $
+
+*/
+
+
+#include "config.h"
+
+#include <dis-asm.h>
+#include <stdio.h>
+
+#include "vm/types.h"
+
+#include "vm/global.h"
+#include "vm/jit/disass.h"
+
+
+/* global variables ***********************************************************/
+
+/* name table for 16 integer registers */
+
+char *regs[] = {
+       "r0",
+       "r1",
+       "r2",
+       "r3",
+       "r4",
+       "r5",
+       "r6",
+       "r7",
+    "r8",
+    "r9",
+    "r10",
+    "r11",
+    "r12",
+    "r13",
+    "r14",
+    "r15"
+};
+
+
+/* disassinstr *****************************************************************
+
+   Outputs a disassembler listing of one machine code instruction on
+   `stdout'.
+
+   code: pointer to machine code
+
+*******************************************************************************/
+
+u1 *disassinstr(u1 *code)
+{
+       s4 seqlen;
+       s4 i;
+
+       if (!disass_initialized) {
+               INIT_DISASSEMBLE_INFO(info, NULL, disass_printf);
+
+               /* setting the struct members must be done after
+                  INIT_DISASSEMBLE_INFO */
+
+               info.mach             = bfd_mach_s390_31;
+               info.read_memory_func = &disass_buffer_read_memory;
+
+               disass_initialized = true;
+       }
+
+       printf("0x%08x:   ", (s4) code);
+
+       disass_len = 0;
+
+       seqlen = print_insn_s390((bfd_vma) code, &info);
+
+       for (i = 0; i < seqlen; i++, code++) {
+               printf("%02x ", *code);
+       }
+       
+       for (; i < 10; i++) {
+               printf("   ");
+       }
+
+       printf("   %s\n", disass_buf);
+
+       return code;
+}
+
+
+/*
+ * 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/s390/emit.c b/src/vm/jit/s390/emit.c
new file mode 100644 (file)
index 0000000..d9a3c1f
--- /dev/null
@@ -0,0 +1,2237 @@
+/* src/vm/jit/x86_64/emit.c - x86_64 code emitter functions
+
+   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
+
+   $Id: emit.c 7219 2007-01-16 22:18:57Z pm $
+
+*/
+
+#include "config.h"
+
+#include "vm/types.h"
+
+#include "md-abi.h"
+
+#include "vm/jit/s390/codegen.h"
+#include "vm/jit/s390/emit.h"
+
+#if defined(ENABLE_THREADS)
+# include "threads/native/lock.h"
+#endif
+
+#include "vm/builtin.h"
+#include "vm/jit/abi-asm.h"
+#include "vm/jit/asmpart.h"
+#include "vm/jit/codegen-common.h"
+#include "vm/jit/emit-common.h"
+#include "vm/jit/jit.h"
+#include "vm/jit/replace.h"
+
+#define __PORTED__
+
+/* emit_load *******************************************************************
+
+   Emits a possible load of an operand.
+
+*******************************************************************************/
+
+__PORTED__ 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;
+
+               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);
+               }
+
+               reg = tempreg;
+       }
+       else
+               reg = src->vv.regoff;
+
+       return reg;
+}
+
+
+/* emit_store ******************************************************************
+
+   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.
+    
+*******************************************************************************/
+
+inline void emit_store(jitdata *jd, instruction *iptr, varinfo *dst, s4 d)
+{
+       codegendata  *cd;
+       s4            disp;
+#if 0
+       s4            s;
+       u2            opcode;
+#endif
+
+       /* get required compiler data */
+
+       cd = jd->cd;
+
+#if 0
+       /* do we have to generate a conditional move? */
+
+       if ((iptr != NULL) && (iptr->opc & ICMD_CONDITION_MASK)) {
+               /* the passed register d is actually the source register */
+
+               s = d;
+
+               /* Only pass the opcode to codegen_reg_of_var to get the real
+                  destination register. */
+
+               opcode = iptr->opc & ICMD_OPCODE_MASK;
+
+               /* get the real destination register */
+
+               d = codegen_reg_of_var(rd, opcode, dst, REG_ITMP1);
+
+               /* and emit the conditional move */
+
+               emit_cmovxx(cd, iptr, s, d);
+       }
+#endif
+
+       if (IS_INMEMORY(dst->flags)) {
+               COUNT_SPILLS;
+
+               disp = dst->vv.regoff * 8;
+
+               if (IS_FLT_DBL_TYPE(dst->type)) {
+                       if (IS_2_WORD_TYPE(dst->type))
+                               M_DST(d, REG_SP, disp);
+                       else
+                               M_FST(d, REG_SP, disp);
+               }
+               else
+                       M_LST(d, REG_SP, disp);
+       }
+}
+
+
+/* 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) ||
+               ((src->flags ^ dst->flags) & INMEMORY)) {
+
+               /* 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)) {
+                       d = codegen_reg_of_var(iptr->opc, dst, REG_IFTMP);
+                       s1 = emit_load(jd, iptr, src, d);
+               }
+               else {
+                       s1 = emit_load(jd, iptr, src, REG_IFTMP);
+                       d = codegen_reg_of_var(iptr->opc, dst, s1);
+               }
+
+               if (s1 != d) {
+                       if (IS_FLT_DBL_TYPE(src->type))
+                               M_FMOV(s1, d);
+                       else
+                               M_MOV(s1, d);
+               }
+
+               emit_store(jd, iptr, dst, d);
+       }
+}
+
+
+void emit_cmovxx(codegendata *cd, instruction *iptr, s4 s, s4 d)
+{
+#if 0
+       switch (iptr->flags.fields.condition) {
+       case ICMD_IFEQ:
+               M_CMOVEQ(s, d);
+               break;
+       case ICMD_IFNE:
+               M_CMOVNE(s, d);
+               break;
+       case ICMD_IFLT:
+               M_CMOVLT(s, d);
+               break;
+       case ICMD_IFGE:
+               M_CMOVGE(s, d);
+               break;
+       case ICMD_IFGT:
+               M_CMOVGT(s, d);
+               break;
+       case ICMD_IFLE:
+               M_CMOVLE(s, d);
+               break;
+       }
+#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;
+
+       /* 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));
+               }
+       }
+}
+
+
+/* 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 size of code segment */
+
+               MCODECHECK(512);
+
+               /* Get machine code which is patched back in later. A
+                  `call rel32' is 5 bytes long (but read 8 bytes). */
+
+               savedmcodeptr = cd->mcodebase + pref->branchpos;
+               mcode = *((u8 *) savedmcodeptr);
+
+               /* patch in `call rel32' to call the following code */
+
+               tmpmcodeptr  = cd->mcodeptr;    /* save current mcodeptr              */
+               cd->mcodeptr = savedmcodeptr;   /* set mcodeptr to patch position     */
+
+               M_CALL_IMM(tmpmcodeptr - (savedmcodeptr + PATCHER_CALL_SIZE));
+
+               cd->mcodeptr = tmpmcodeptr;     /* restore the current mcodeptr       */
+
+               /* move pointer to java_objectheader onto stack */
+
+#if defined(ENABLE_THREADS)
+               /* create a virtual java_objectheader */
+
+               (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   */
+
+               emit_lea_membase_reg(cd, RIP, -((cd->mcodeptr + 7) - cd->mcodebase) + disp, REG_ITMP3);
+               M_PUSH(REG_ITMP3);
+#else
+               M_PUSH_IMM(0);
+#endif
+
+               /* move machine code bytes and classinfo pointer into registers */
+
+               M_MOV_IMM(mcode, REG_ITMP3);
+               M_PUSH(REG_ITMP3);
+
+               M_MOV_IMM(pref->ref, REG_ITMP3);
+               M_PUSH(REG_ITMP3);
+
+               M_MOV_IMM(pref->disp, REG_ITMP3);
+               M_PUSH(REG_ITMP3);
+
+               M_MOV_IMM(pref->patcher, REG_ITMP3);
+               M_PUSH(REG_ITMP3);
+
+               if (targetdisp == 0) {
+                       targetdisp = cd->mcodeptr - cd->mcodebase;
+
+                       M_MOV_IMM(asm_patcher_wrapper, REG_ITMP3);
+                       M_JMP(REG_ITMP3);
+               }
+               else {
+                       M_JMP_IMM((cd->mcodebase + targetdisp) -
+                                         (cd->mcodeptr + PATCHER_CALL_SIZE));
+               }
+       }
+}
+
+
+/* emit_replacement_stubs ******************************************************
+
+   Generates the code for the replacement stubs.
+
+*******************************************************************************/
+
+void emit_replacement_stubs(jitdata *jd)
+{
+       codegendata *cd;
+       codeinfo    *code;
+       rplpoint    *rplp;
+       s4           disp;
+       s4           i;
+
+       /* get required compiler data */
+
+       cd   = jd->cd;
+       code = jd->code;
+
+       rplp = code->rplpoints;
+
+       for (i = 0; i < code->rplpointcount; ++i, ++rplp) {
+               /* check code segment size */
+
+               MCODECHECK(512);
+
+               /* note start of stub code */
+
+               rplp->outcode = (u1 *) (ptrint) (cd->mcodeptr - cd->mcodebase);
+
+               /* make machine code for patching */
+
+               disp = (ptrint) (rplp->outcode - rplp->pc) - 5;
+
+               rplp->mcode = 0xe9 | ((u8) disp << 8);
+
+               /* push address of `rplpoint` struct */
+                       
+               M_MOV_IMM(rplp, REG_ITMP3);
+               M_PUSH(REG_ITMP3);
+
+               /* jump to replacement function */
+
+               M_MOV_IMM(asm_replacement_out, REG_ITMP3);
+               M_JMP(REG_ITMP3);
+       }
+}
+       
+
+/* emit_verbosecall_enter ******************************************************
+
+   Generates the code for the call trace.
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void emit_verbosecall_enter(jitdata *jd)
+{
+       methodinfo   *m;
+       codegendata  *cd;
+       registerdata *rd;
+       methoddesc   *md;
+       s4            i, j, k;
+
+       /* get required compiler data */
+
+       m  = jd->m;
+       cd = jd->cd;
+       rd = jd->rd;
+
+       md = m->parseddesc;
+
+       /* mark trace code */
+
+       M_NOP;
+
+       /* additional +1 is for 16-byte stack alignment */
+
+       M_LSUB_IMM((ARG_CNT + TMP_CNT + 1 + 1) * 8, REG_SP);
+
+       /* save argument registers */
+
+       for (i = 0; i < INT_ARG_CNT; i++)
+               M_LST(rd->argintregs[i], REG_SP, (1 + i) * 8);
+
+       for (i = 0; i < FLT_ARG_CNT; i++)
+               M_DST(rd->argfltregs[i], REG_SP, (1 + INT_ARG_CNT + i) * 8);
+
+       /* save temporary registers for leaf methods */
+
+       if (jd->isleafmethod) {
+               for (i = 0; i < INT_TMP_CNT; i++)
+                       M_LST(rd->tmpintregs[i], REG_SP, (1 + ARG_CNT + i) * 8);
+
+               for (i = 0; i < FLT_TMP_CNT; i++)
+                       M_DST(rd->tmpfltregs[i], REG_SP, (1 + ARG_CNT + INT_TMP_CNT + i) * 8);
+       }
+
+       /* show integer hex code for float arguments */
+
+       for (i = 0, j = 0; i < md->paramcount && i < INT_ARG_CNT; i++) {
+               /* If the paramtype is a float, we have to right shift all
+                  following integer registers. */
+       
+               if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
+                       for (k = INT_ARG_CNT - 2; k >= i; k--)
+                               M_MOV(rd->argintregs[k], rd->argintregs[k + 1]);
+
+                       emit_movd_freg_reg(cd, rd->argfltregs[j], rd->argintregs[i]);
+                       j++;
+               }
+       }
+
+       M_MOV_IMM(m, REG_ITMP2);
+       M_AST(REG_ITMP2, REG_SP, 0 * 8);
+       M_MOV_IMM(builtin_trace_args, REG_ITMP1);
+       M_CALL(REG_ITMP1);
+
+       /* restore argument registers */
+
+       for (i = 0; i < INT_ARG_CNT; i++)
+               M_LLD(rd->argintregs[i], REG_SP, (1 + i) * 8);
+
+       for (i = 0; i < FLT_ARG_CNT; i++)
+               M_DLD(rd->argfltregs[i], REG_SP, (1 + INT_ARG_CNT + i) * 8);
+
+       /* restore temporary registers for leaf methods */
+
+       if (jd->isleafmethod) {
+               for (i = 0; i < INT_TMP_CNT; i++)
+                       M_LLD(rd->tmpintregs[i], REG_SP, (1 + ARG_CNT + i) * 8);
+
+               for (i = 0; i < FLT_TMP_CNT; i++)
+                       M_DLD(rd->tmpfltregs[i], REG_SP, (1 + ARG_CNT + INT_TMP_CNT + i) * 8);
+       }
+
+       M_LADD_IMM((ARG_CNT + TMP_CNT + 1 + 1) * 8, REG_SP);
+
+       /* mark trace code */
+
+       M_NOP;
+}
+#endif /* !defined(NDEBUG) */
+
+
+/* emit_verbosecall_exit *******************************************************
+
+   Generates the code for the call trace.
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void emit_verbosecall_exit(jitdata *jd)
+{
+       methodinfo   *m;
+       codegendata  *cd;
+       registerdata *rd;
+
+       /* get required compiler data */
+
+       m  = jd->m;
+       cd = jd->cd;
+       rd = jd->rd;
+
+       /* mark trace code */
+
+       M_NOP;
+
+       M_ASUB_IMM(2 * 8, REG_SP);
+
+       M_LST(REG_RESULT, REG_SP, 0 * 8);
+       M_DST(REG_FRESULT, REG_SP, 1 * 8);
+
+       M_MOV_IMM(m, rd->argintregs[0]);
+       M_MOV(REG_RESULT, rd->argintregs[1]);
+       M_FLTMOVE(REG_FRESULT, rd->argfltregs[0]);
+       M_FLTMOVE(REG_FRESULT, rd->argfltregs[1]);
+
+       M_MOV_IMM(builtin_displaymethodstop, REG_ITMP1);
+       M_CALL(REG_ITMP1);
+
+       M_LLD(REG_RESULT, REG_SP, 0 * 8);
+       M_DLD(REG_FRESULT, REG_SP, 1 * 8);
+
+       M_AADD_IMM(2 * 8, REG_SP);
+
+       /* mark trace code */
+
+       M_NOP;
+}
+#endif /* !defined(NDEBUG) */
+
+
+/* code generation functions **************************************************/
+
+static void emit_membase(codegendata *cd, s4 basereg, s4 disp, s4 dreg)
+{
+       if ((basereg == REG_SP) || (basereg == R12)) {
+               if (disp == 0) {
+                       emit_address_byte(0, dreg, REG_SP);
+                       emit_address_byte(0, REG_SP, REG_SP);
+
+               } else if (IS_IMM8(disp)) {
+                       emit_address_byte(1, dreg, REG_SP);
+                       emit_address_byte(0, REG_SP, REG_SP);
+                       emit_imm8(disp);
+
+               } else {
+                       emit_address_byte(2, dreg, REG_SP);
+                       emit_address_byte(0, REG_SP, REG_SP);
+                       emit_imm32(disp);
+               }
+
+       } else if ((disp) == 0 && (basereg) != RBP && (basereg) != R13) {
+               emit_address_byte(0,(dreg),(basereg));
+
+       } else if ((basereg) == RIP) {
+               emit_address_byte(0, dreg, RBP);
+               emit_imm32(disp);
+
+       } else {
+               if (IS_IMM8(disp)) {
+                       emit_address_byte(1, dreg, basereg);
+                       emit_imm8(disp);
+
+               } else {
+                       emit_address_byte(2, dreg, basereg);
+                       emit_imm32(disp);
+               }
+       }
+}
+
+
+static void emit_membase32(codegendata *cd, s4 basereg, s4 disp, s4 dreg)
+{
+       if ((basereg == REG_SP) || (basereg == R12)) {
+               emit_address_byte(2, dreg, REG_SP);
+               emit_address_byte(0, REG_SP, REG_SP);
+               emit_imm32(disp);
+       }
+       else {
+               emit_address_byte(2, dreg, basereg);
+               emit_imm32(disp);
+       }
+}
+
+
+static void emit_memindex(codegendata *cd, s4 reg, s4 disp, s4 basereg, s4 indexreg, s4 scale)
+{
+       if (basereg == -1) {
+               emit_address_byte(0, reg, 4);
+               emit_address_byte(scale, indexreg, 5);
+               emit_imm32(disp);
+       }
+       else if ((disp == 0) && (basereg != RBP) && (basereg != R13)) {
+               emit_address_byte(0, reg, 4);
+               emit_address_byte(scale, indexreg, basereg);
+       }
+       else if (IS_IMM8(disp)) {
+               emit_address_byte(1, reg, 4);
+               emit_address_byte(scale, indexreg, basereg);
+               emit_imm8(disp);
+       }
+       else {
+               emit_address_byte(2, reg, 4);
+               emit_address_byte(scale, indexreg, basereg);
+               emit_imm32(disp);
+       }
+}
+
+
+void emit_ishift(jitdata *jd, s4 shift_op, instruction *iptr)
+{
+       s4 s1, s2, d, d_old;
+       varinfo *v_s1,*v_s2,*v_dst;
+       codegendata *cd;
+
+       /* get required compiler data */
+
+       cd = jd->cd;
+
+       v_s1  = VAROP(iptr->s1);
+       v_s2  = VAROP(iptr->sx.s23.s2);
+       v_dst = VAROP(iptr->dst);
+
+       s1 = v_s1->vv.regoff;
+       s2 = v_s2->vv.regoff;
+       d  = v_dst->vv.regoff;
+
+       M_INTMOVE(RCX, REG_ITMP1);                                    /* save RCX */
+
+       if (IS_INMEMORY(v_dst->flags)) {
+               if (IS_INMEMORY(v_s2->flags) && IS_INMEMORY(v_s1->flags)) {
+                       if (s1 == d) {
+                               M_ILD(RCX, REG_SP, s2 * 8);
+                               emit_shiftl_membase(cd, shift_op, REG_SP, d * 8);
+
+                       } else {
+                               M_ILD(RCX, REG_SP, s2 * 8);
+                               M_ILD(REG_ITMP2, REG_SP, s1 * 8);
+                               emit_shiftl_reg(cd, shift_op, REG_ITMP2);
+                               M_IST(REG_ITMP2, REG_SP, d * 8);
+                       }
+
+               } else if (IS_INMEMORY(v_s2->flags) && !IS_INMEMORY(v_s1->flags)) {
+                       /* s1 may be equal to RCX */
+                       if (s1 == RCX) {
+                               if (s2 == d) {
+                                       M_ILD(REG_ITMP1, REG_SP, s2 * 8);
+                                       M_IST(s1, REG_SP, d * 8);
+                                       M_INTMOVE(REG_ITMP1, RCX);
+
+                               } else {
+                                       M_IST(s1, REG_SP, d * 8);
+                                       M_ILD(RCX, REG_SP, s2 * 8);
+                               }
+
+                       } else {
+                               M_ILD(RCX, REG_SP, s2 * 8);
+                               M_IST(s1, REG_SP, d * 8);
+                       }
+
+                       emit_shiftl_membase(cd, shift_op, REG_SP, d * 8);
+
+               } else if (!IS_INMEMORY(v_s2->flags) && IS_INMEMORY(v_s1->flags)) {
+                       if (s1 == d) {
+                               M_INTMOVE(s2, RCX);
+                               emit_shiftl_membase(cd, shift_op, REG_SP, d * 8);
+
+                       } else {
+                               M_INTMOVE(s2, RCX);
+                               M_ILD(REG_ITMP2, REG_SP, s1 * 8);
+                               emit_shiftl_reg(cd, shift_op, REG_ITMP2);
+                               M_IST(REG_ITMP2, REG_SP, d * 8);
+                       }
+
+               } else {
+                       /* s1 may be equal to RCX */
+                       M_IST(s1, REG_SP, d * 8);
+                       M_INTMOVE(s2, RCX);
+                       emit_shiftl_membase(cd, shift_op, REG_SP, d * 8);
+               }
+
+               M_INTMOVE(REG_ITMP1, RCX);                             /* restore RCX */
+
+       } else {
+               d_old = d;
+               if (d == RCX) {
+                       d = REG_ITMP3;
+               }
+                                       
+               if (IS_INMEMORY(v_s2->flags) && IS_INMEMORY(v_s1->flags)) {
+                       M_ILD(RCX, REG_SP, s2 * 8);
+                       M_ILD(d, REG_SP, s1 * 8);
+                       emit_shiftl_reg(cd, shift_op, d);
+
+               } else if (IS_INMEMORY(v_s2->flags) && !IS_INMEMORY(v_s1->flags)) {
+                       /* s1 may be equal to RCX */
+                       M_INTMOVE(s1, d);
+                       M_ILD(RCX, REG_SP, s2 * 8);
+                       emit_shiftl_reg(cd, shift_op, d);
+
+               } else if (!IS_INMEMORY(v_s2->flags) && IS_INMEMORY(v_s1->flags)) {
+                       M_INTMOVE(s2, RCX);
+                       M_ILD(d, REG_SP, s1 * 8);
+                       emit_shiftl_reg(cd, shift_op, d);
+
+               } else {
+                       /* s1 may be equal to RCX */
+                       if (s1 == RCX) {
+                               if (s2 == d) {
+                                       /* d cannot be used to backup s1 since this would
+                                          overwrite s2. */
+                                       M_INTMOVE(s1, REG_ITMP3);
+                                       M_INTMOVE(s2, RCX);
+                                       M_INTMOVE(REG_ITMP3, d);
+
+                               } else {
+                                       M_INTMOVE(s1, d);
+                                       M_INTMOVE(s2, RCX);
+                               }
+
+                       } else {
+                               /* d may be equal to s2 */
+                               M_INTMOVE(s2, RCX);
+                               M_INTMOVE(s1, d);
+                       }
+                       emit_shiftl_reg(cd, shift_op, d);
+               }
+
+               if (d_old == RCX)
+                       M_INTMOVE(REG_ITMP3, RCX);
+               else
+                       M_INTMOVE(REG_ITMP1, RCX);                         /* restore RCX */
+       }
+}
+
+
+void emit_lshift(jitdata *jd, s4 shift_op, instruction *iptr)
+{
+       s4 s1, s2, d, d_old;
+       varinfo *v_s1,*v_s2,*v_dst;
+       codegendata *cd;
+
+       /* get required compiler data */
+
+       cd = jd->cd;
+
+       v_s1  = VAROP(iptr->s1);
+       v_s2  = VAROP(iptr->sx.s23.s2);
+       v_dst = VAROP(iptr->dst);
+
+       s1 = v_s1->vv.regoff;
+       s2 = v_s2->vv.regoff;
+       d  = v_dst->vv.regoff;
+       
+       M_INTMOVE(RCX, REG_ITMP1);                                    /* save RCX */
+
+       if (IS_INMEMORY(v_dst->flags)) {
+               if (IS_INMEMORY(v_s2->flags) && IS_INMEMORY(v_s1->flags)) {
+                       if (s1 == d) {
+                               M_ILD(RCX, REG_SP, s2 * 8);
+                               emit_shift_membase(cd, shift_op, REG_SP, d * 8);
+
+                       } else {
+                               M_ILD(RCX, REG_SP, s2 * 8);
+                               M_LLD(REG_ITMP2, REG_SP, s1 * 8);
+                               emit_shift_reg(cd, shift_op, REG_ITMP2);
+                               M_LST(REG_ITMP2, REG_SP, d * 8);
+                       }
+
+               } else if (IS_INMEMORY(v_s2->flags) && !IS_INMEMORY(v_s1->flags)) {
+                       /* s1 may be equal to RCX */
+                       if (s1 == RCX) {
+                               if (s2 == d) {
+                                       M_ILD(REG_ITMP1, REG_SP, s2 * 8);
+                                       M_LST(s1, REG_SP, d * 8);
+                                       M_INTMOVE(REG_ITMP1, RCX);
+
+                               } else {
+                                       M_LST(s1, REG_SP, d * 8);
+                                       M_ILD(RCX, REG_SP, s2 * 8);
+                               }
+
+                       } else {
+                               M_ILD(RCX, REG_SP, s2 * 8);
+                               M_LST(s1, REG_SP, d * 8);
+                       }
+
+                       emit_shift_membase(cd, shift_op, REG_SP, d * 8);
+
+               } else if (!IS_INMEMORY(v_s2->flags) && IS_INMEMORY(v_s1->flags)) {
+                       if (s1 == d) {
+                               M_INTMOVE(s2, RCX);
+                               emit_shift_membase(cd, shift_op, REG_SP, d * 8);
+
+                       } else {
+                               M_INTMOVE(s2, RCX);
+                               M_LLD(REG_ITMP2, REG_SP, s1 * 8);
+                               emit_shift_reg(cd, shift_op, REG_ITMP2);
+                               M_LST(REG_ITMP2, REG_SP, d * 8);
+                       }
+
+               } else {
+                       /* s1 may be equal to RCX */
+                       M_LST(s1, REG_SP, d * 8);
+                       M_INTMOVE(s2, RCX);
+                       emit_shift_membase(cd, shift_op, REG_SP, d * 8);
+               }
+
+               M_INTMOVE(REG_ITMP1, RCX);                             /* restore RCX */
+
+       } else {
+               d_old = d;
+               if (d == RCX) {
+                       d = REG_ITMP3;
+               }
+
+               if (IS_INMEMORY(v_s2->flags) && IS_INMEMORY(v_s1->flags)) {
+                       M_ILD(RCX, REG_SP, s2 * 8);
+                       M_LLD(d, REG_SP, s1 * 8);
+                       emit_shift_reg(cd, shift_op, d);
+
+               } else if (IS_INMEMORY(v_s2->flags) && !IS_INMEMORY(v_s1->flags)) {
+                       /* s1 may be equal to RCX */
+                       M_INTMOVE(s1, d);
+                       M_ILD(RCX, REG_SP, s2 * 8);
+                       emit_shift_reg(cd, shift_op, d);
+
+               } else if (!IS_INMEMORY(v_s2->flags) && IS_INMEMORY(v_s1->flags)) {
+                       M_INTMOVE(s2, RCX);
+                       M_LLD(d, REG_SP, s1 * 8);
+                       emit_shift_reg(cd, shift_op, d);
+
+               } else {
+                       /* s1 may be equal to RCX */
+                       if (s1 == RCX) {
+                               if (s2 == d) {
+                                       /* d cannot be used to backup s1 since this would
+                                          overwrite s2. */
+                                       M_INTMOVE(s1, REG_ITMP3);
+                                       M_INTMOVE(s2, RCX);
+                                       M_INTMOVE(REG_ITMP3, d);
+
+                               } else {
+                                       M_INTMOVE(s1, d);
+                                       M_INTMOVE(s2, RCX);
+                               }
+
+                       } else {
+                               /* d may be equal to s2 */
+                               M_INTMOVE(s2, RCX);
+                               M_INTMOVE(s1, d);
+                       }
+                       emit_shift_reg(cd, shift_op, d);
+               }
+
+               if (d_old == RCX)
+                       M_INTMOVE(REG_ITMP3, RCX);
+               else
+                       M_INTMOVE(REG_ITMP1, RCX);                         /* restore RCX */
+       }
+}
+
+
+/* low-level code emitter functions *******************************************/
+
+void emit_mov_reg_reg(codegendata *cd, s8 reg, s8 dreg)
+{
+       emit_rex(1,(reg),0,(dreg));
+       *(cd->mcodeptr++) = 0x89;
+       emit_reg((reg),(dreg));
+}
+
+
+void emit_mov_imm_reg(codegendata *cd, s8 imm, s8 reg)
+{
+       emit_rex(1,0,0,(reg));
+       *(cd->mcodeptr++) = 0xb8 + ((reg) & 0x07);
+       emit_imm64((imm));
+}
+
+
+void emit_movl_reg_reg(codegendata *cd, s8 reg, s8 dreg)
+{
+       emit_rex(0,(reg),0,(dreg));
+       *(cd->mcodeptr++) = 0x89;
+       emit_reg((reg),(dreg));
+}
+
+
+void emit_movl_imm_reg(codegendata *cd, s8 imm, s8 reg) {
+       emit_rex(0,0,0,(reg));
+       *(cd->mcodeptr++) = 0xb8 + ((reg) & 0x07);
+       emit_imm32((imm));
+}
+
+
+void emit_mov_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 reg) {
+       emit_rex(1,(reg),0,(basereg));
+       *(cd->mcodeptr++) = 0x8b;
+       emit_membase(cd, (basereg),(disp),(reg));
+}
+
+
+/*
+ * this one is for INVOKEVIRTUAL/INVOKEINTERFACE to have a
+ * constant membase immediate length of 32bit
+ */
+void emit_mov_membase32_reg(codegendata *cd, s8 basereg, s8 disp, s8 reg) {
+       emit_rex(1,(reg),0,(basereg));
+       *(cd->mcodeptr++) = 0x8b;
+       emit_membase32(cd, (basereg),(disp),(reg));
+}
+
+
+void emit_movl_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 reg)
+{
+       emit_rex(0,(reg),0,(basereg));
+       *(cd->mcodeptr++) = 0x8b;
+       emit_membase(cd, (basereg),(disp),(reg));
+}
+
+
+/* ATTENTION: Always emit a REX byte, because the instruction size can
+   be smaller when all register indexes are smaller than 7. */
+void emit_movl_membase32_reg(codegendata *cd, s8 basereg, s8 disp, s8 reg)
+{
+       emit_byte_rex((reg),0,(basereg));
+       *(cd->mcodeptr++) = 0x8b;
+       emit_membase32(cd, (basereg),(disp),(reg));
+}
+
+
+void emit_mov_reg_membase(codegendata *cd, s8 reg, s8 basereg, s8 disp) {
+       emit_rex(1,(reg),0,(basereg));
+       *(cd->mcodeptr++) = 0x89;
+       emit_membase(cd, (basereg),(disp),(reg));
+}
+
+
+void emit_mov_reg_membase32(codegendata *cd, s8 reg, s8 basereg, s8 disp) {
+       emit_rex(1,(reg),0,(basereg));
+       *(cd->mcodeptr++) = 0x89;
+       emit_membase32(cd, (basereg),(disp),(reg));
+}
+
+
+void emit_movl_reg_membase(codegendata *cd, s8 reg, s8 basereg, s8 disp) {
+       emit_rex(0,(reg),0,(basereg));
+       *(cd->mcodeptr++) = 0x89;
+       emit_membase(cd, (basereg),(disp),(reg));
+}
+
+
+/* Always emit a REX byte, because the instruction size can be smaller when   */
+/* all register indexes are smaller than 7.                                   */
+void emit_movl_reg_membase32(codegendata *cd, s8 reg, s8 basereg, s8 disp) {
+       emit_byte_rex((reg),0,(basereg));
+       *(cd->mcodeptr++) = 0x89;
+       emit_membase32(cd, (basereg),(disp),(reg));
+}
+
+
+void emit_mov_memindex_reg(codegendata *cd, s8 disp, s8 basereg, s8 indexreg, s8 scale, s8 reg) {
+       emit_rex(1,(reg),(indexreg),(basereg));
+       *(cd->mcodeptr++) = 0x8b;
+       emit_memindex(cd, (reg),(disp),(basereg),(indexreg),(scale));
+}
+
+
+void emit_movl_memindex_reg(codegendata *cd, s8 disp, s8 basereg, s8 indexreg, s8 scale, s8 reg) {
+       emit_rex(0,(reg),(indexreg),(basereg));
+       *(cd->mcodeptr++) = 0x8b;
+       emit_memindex(cd, (reg),(disp),(basereg),(indexreg),(scale));
+}
+
+
+void emit_mov_reg_memindex(codegendata *cd, s8 reg, s8 disp, s8 basereg, s8 indexreg, s8 scale) {
+       emit_rex(1,(reg),(indexreg),(basereg));
+       *(cd->mcodeptr++) = 0x89;
+       emit_memindex(cd, (reg),(disp),(basereg),(indexreg),(scale));
+}
+
+
+void emit_movl_reg_memindex(codegendata *cd, s8 reg, s8 disp, s8 basereg, s8 indexreg, s8 scale) {
+       emit_rex(0,(reg),(indexreg),(basereg));
+       *(cd->mcodeptr++) = 0x89;
+       emit_memindex(cd, (reg),(disp),(basereg),(indexreg),(scale));
+}
+
+
+void emit_movw_reg_memindex(codegendata *cd, s8 reg, s8 disp, s8 basereg, s8 indexreg, s8 scale) {
+       *(cd->mcodeptr++) = 0x66;
+       emit_rex(0,(reg),(indexreg),(basereg));
+       *(cd->mcodeptr++) = 0x89;
+       emit_memindex(cd, (reg),(disp),(basereg),(indexreg),(scale));
+}
+
+
+void emit_movb_reg_memindex(codegendata *cd, s8 reg, s8 disp, s8 basereg, s8 indexreg, s8 scale) {
+       emit_byte_rex((reg),(indexreg),(basereg));
+       *(cd->mcodeptr++) = 0x88;
+       emit_memindex(cd, (reg),(disp),(basereg),(indexreg),(scale));
+}
+
+
+void emit_mov_imm_membase(codegendata *cd, s8 imm, s8 basereg, s8 disp) {
+       emit_rex(1,0,0,(basereg));
+       *(cd->mcodeptr++) = 0xc7;
+       emit_membase(cd, (basereg),(disp),0);
+       emit_imm32((imm));
+}
+
+
+void emit_mov_imm_membase32(codegendata *cd, s8 imm, s8 basereg, s8 disp) {
+       emit_rex(1,0,0,(basereg));
+       *(cd->mcodeptr++) = 0xc7;
+       emit_membase32(cd, (basereg),(disp),0);
+       emit_imm32((imm));
+}
+
+
+void emit_movl_imm_membase(codegendata *cd, s8 imm, s8 basereg, s8 disp) {
+       emit_rex(0,0,0,(basereg));
+       *(cd->mcodeptr++) = 0xc7;
+       emit_membase(cd, (basereg),(disp),0);
+       emit_imm32((imm));
+}
+
+
+/* Always emit a REX byte, because the instruction size can be smaller when   */
+/* all register indexes are smaller than 7.                                   */
+void emit_movl_imm_membase32(codegendata *cd, s8 imm, s8 basereg, s8 disp) {
+       emit_byte_rex(0,0,(basereg));
+       *(cd->mcodeptr++) = 0xc7;
+       emit_membase32(cd, (basereg),(disp),0);
+       emit_imm32((imm));
+}
+
+
+void emit_movsbq_reg_reg(codegendata *cd, s8 reg, s8 dreg)
+{
+       emit_rex(1,(dreg),0,(reg));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = 0xbe;
+       /* XXX: why do reg and dreg have to be exchanged */
+       emit_reg((dreg),(reg));
+}
+
+
+void emit_movswq_reg_reg(codegendata *cd, s8 reg, s8 dreg)
+{
+       emit_rex(1,(dreg),0,(reg));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = 0xbf;
+       /* XXX: why do reg and dreg have to be exchanged */
+       emit_reg((dreg),(reg));
+}
+
+
+void emit_movslq_reg_reg(codegendata *cd, s8 reg, s8 dreg)
+{
+       emit_rex(1,(dreg),0,(reg));
+       *(cd->mcodeptr++) = 0x63;
+       /* XXX: why do reg and dreg have to be exchanged */
+       emit_reg((dreg),(reg));
+}
+
+
+void emit_movzwq_reg_reg(codegendata *cd, s8 reg, s8 dreg)
+{
+       emit_rex(1,(dreg),0,(reg));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = 0xb7;
+       /* XXX: why do reg and dreg have to be exchanged */
+       emit_reg((dreg),(reg));
+}
+
+
+void emit_movswq_memindex_reg(codegendata *cd, s8 disp, s8 basereg, s8 indexreg, s8 scale, s8 reg) {
+       emit_rex(1,(reg),(indexreg),(basereg));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = 0xbf;
+       emit_memindex(cd, (reg),(disp),(basereg),(indexreg),(scale));
+}
+
+
+void emit_movsbq_memindex_reg(codegendata *cd, s8 disp, s8 basereg, s8 indexreg, s8 scale, s8 reg) {
+       emit_rex(1,(reg),(indexreg),(basereg));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = 0xbe;
+       emit_memindex(cd, (reg),(disp),(basereg),(indexreg),(scale));
+}
+
+
+void emit_movzwq_memindex_reg(codegendata *cd, s8 disp, s8 basereg, s8 indexreg, s8 scale, s8 reg) {
+       emit_rex(1,(reg),(indexreg),(basereg));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = 0xb7;
+       emit_memindex(cd, (reg),(disp),(basereg),(indexreg),(scale));
+}
+
+
+void emit_mov_imm_memindex(codegendata *cd, s4 imm, s4 disp, s4 basereg, s4 indexreg, s4 scale)
+{
+       emit_rex(1,0,(indexreg),(basereg));
+       *(cd->mcodeptr++) = 0xc7;
+       emit_memindex(cd, 0,(disp),(basereg),(indexreg),(scale));
+       emit_imm32((imm));
+}
+
+
+void emit_movl_imm_memindex(codegendata *cd, s4 imm, s4 disp, s4 basereg, s4 indexreg, s4 scale)
+{
+       emit_rex(0,0,(indexreg),(basereg));
+       *(cd->mcodeptr++) = 0xc7;
+       emit_memindex(cd, 0,(disp),(basereg),(indexreg),(scale));
+       emit_imm32((imm));
+}
+
+
+void emit_movw_imm_memindex(codegendata *cd, s4 imm, s4 disp, s4 basereg, s4 indexreg, s4 scale)
+{
+       *(cd->mcodeptr++) = 0x66;
+       emit_rex(0,0,(indexreg),(basereg));
+       *(cd->mcodeptr++) = 0xc7;
+       emit_memindex(cd, 0,(disp),(basereg),(indexreg),(scale));
+       emit_imm16((imm));
+}
+
+
+void emit_movb_imm_memindex(codegendata *cd, s4 imm, s4 disp, s4 basereg, s4 indexreg, s4 scale)
+{
+       emit_rex(0,0,(indexreg),(basereg));
+       *(cd->mcodeptr++) = 0xc6;
+       emit_memindex(cd, 0,(disp),(basereg),(indexreg),(scale));
+       emit_imm8((imm));
+}
+
+
+/*
+ * alu operations
+ */
+void emit_alu_reg_reg(codegendata *cd, s8 opc, s8 reg, s8 dreg)
+{
+       emit_rex(1,(reg),0,(dreg));
+       *(cd->mcodeptr++) = (((opc)) << 3) + 1;
+       emit_reg((reg),(dreg));
+}
+
+
+void emit_alul_reg_reg(codegendata *cd, s8 opc, s8 reg, s8 dreg)
+{
+       emit_rex(0,(reg),0,(dreg));
+       *(cd->mcodeptr++) = (((opc)) << 3) + 1;
+       emit_reg((reg),(dreg));
+}
+
+
+void emit_alu_reg_membase(codegendata *cd, s8 opc, s8 reg, s8 basereg, s8 disp)
+{
+       emit_rex(1,(reg),0,(basereg));
+       *(cd->mcodeptr++) = (((opc)) << 3) + 1;
+       emit_membase(cd, (basereg),(disp),(reg));
+}
+
+
+void emit_alul_reg_membase(codegendata *cd, s8 opc, s8 reg, s8 basereg, s8 disp)
+{
+       emit_rex(0,(reg),0,(basereg));
+       *(cd->mcodeptr++) = (((opc)) << 3) + 1;
+       emit_membase(cd, (basereg),(disp),(reg));
+}
+
+
+void emit_alu_membase_reg(codegendata *cd, s8 opc, s8 basereg, s8 disp, s8 reg)
+{
+       emit_rex(1,(reg),0,(basereg));
+       *(cd->mcodeptr++) = (((opc)) << 3) + 3;
+       emit_membase(cd, (basereg),(disp),(reg));
+}
+
+
+void emit_alul_membase_reg(codegendata *cd, s8 opc, s8 basereg, s8 disp, s8 reg)
+{
+       emit_rex(0,(reg),0,(basereg));
+       *(cd->mcodeptr++) = (((opc)) << 3) + 3;
+       emit_membase(cd, (basereg),(disp),(reg));
+}
+
+
+void emit_alu_imm_reg(codegendata *cd, s8 opc, s8 imm, s8 dreg) {
+       if (IS_IMM8(imm)) {
+               emit_rex(1,0,0,(dreg));
+               *(cd->mcodeptr++) = 0x83;
+               emit_reg((opc),(dreg));
+               emit_imm8((imm));
+       } else {
+               emit_rex(1,0,0,(dreg));
+               *(cd->mcodeptr++) = 0x81;
+               emit_reg((opc),(dreg));
+               emit_imm32((imm));
+       }
+}
+
+
+void emit_alu_imm32_reg(codegendata *cd, s8 opc, s8 imm, s8 dreg) {
+       emit_rex(1,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));
+               *(cd->mcodeptr++) = 0x83;
+               emit_reg((opc),(dreg));
+               emit_imm8((imm));
+       } else {
+               emit_rex(0,0,0,(dreg));
+               *(cd->mcodeptr++) = 0x81;
+               emit_reg((opc),(dreg));
+               emit_imm32((imm));
+       }
+}
+
+
+void emit_alu_imm_membase(codegendata *cd, s8 opc, s8 imm, s8 basereg, s8 disp) {
+       if (IS_IMM8(imm)) {
+               emit_rex(1,(basereg),0,0);
+               *(cd->mcodeptr++) = 0x83;
+               emit_membase(cd, (basereg),(disp),(opc));
+               emit_imm8((imm));
+       } else {
+               emit_rex(1,(basereg),0,0);
+               *(cd->mcodeptr++) = 0x81;
+               emit_membase(cd, (basereg),(disp),(opc));
+               emit_imm32((imm));
+       }
+}
+
+
+void emit_alul_imm_membase(codegendata *cd, s8 opc, s8 imm, s8 basereg, s8 disp) {
+       if (IS_IMM8(imm)) {
+               emit_rex(0,(basereg),0,0);
+               *(cd->mcodeptr++) = 0x83;
+               emit_membase(cd, (basereg),(disp),(opc));
+               emit_imm8((imm));
+       } else {
+               emit_rex(0,(basereg),0,0);
+               *(cd->mcodeptr++) = 0x81;
+               emit_membase(cd, (basereg),(disp),(opc));
+               emit_imm32((imm));
+       }
+}
+
+
+void emit_test_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
+       emit_rex(1,(reg),0,(dreg));
+       *(cd->mcodeptr++) = 0x85;
+       emit_reg((reg),(dreg));
+}
+
+
+void emit_testl_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
+       emit_rex(0,(reg),0,(dreg));
+       *(cd->mcodeptr++) = 0x85;
+       emit_reg((reg),(dreg));
+}
+
+
+void emit_test_imm_reg(codegendata *cd, s8 imm, s8 reg) {
+       *(cd->mcodeptr++) = 0xf7;
+       emit_reg(0,(reg));
+       emit_imm32((imm));
+}
+
+
+void emit_testw_imm_reg(codegendata *cd, s8 imm, s8 reg) {
+       *(cd->mcodeptr++) = 0x66;
+       *(cd->mcodeptr++) = 0xf7;
+       emit_reg(0,(reg));
+       emit_imm16((imm));
+}
+
+
+void emit_testb_imm_reg(codegendata *cd, s8 imm, s8 reg) {
+       *(cd->mcodeptr++) = 0xf6;
+       emit_reg(0,(reg));
+       emit_imm8((imm));
+}
+
+
+void emit_lea_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 reg) {
+       emit_rex(1,(reg),0,(basereg));
+       *(cd->mcodeptr++) = 0x8d;
+       emit_membase(cd, (basereg),(disp),(reg));
+}
+
+
+void emit_leal_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 reg) {
+       emit_rex(0,(reg),0,(basereg));
+       *(cd->mcodeptr++) = 0x8d;
+       emit_membase(cd, (basereg),(disp),(reg));
+}
+
+
+
+void emit_incl_membase(codegendata *cd, s8 basereg, s8 disp)
+{
+       emit_rex(0,0,0,(basereg));
+       *(cd->mcodeptr++) = 0xff;
+       emit_membase(cd, (basereg),(disp),0);
+}
+
+
+
+void emit_cltd(codegendata *cd) {
+    *(cd->mcodeptr++) = 0x99;
+}
+
+
+void emit_cqto(codegendata *cd) {
+       emit_rex(1,0,0,0);
+       *(cd->mcodeptr++) = 0x99;
+}
+
+
+
+void emit_imul_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
+       emit_rex(1,(dreg),0,(reg));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = 0xaf;
+       emit_reg((dreg),(reg));
+}
+
+
+void emit_imull_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
+       emit_rex(0,(dreg),0,(reg));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = 0xaf;
+       emit_reg((dreg),(reg));
+}
+
+
+void emit_imul_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 dreg) {
+       emit_rex(1,(dreg),0,(basereg));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = 0xaf;
+       emit_membase(cd, (basereg),(disp),(dreg));
+}
+
+
+void emit_imull_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 dreg) {
+       emit_rex(0,(dreg),0,(basereg));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = 0xaf;
+       emit_membase(cd, (basereg),(disp),(dreg));
+}
+
+
+void emit_imul_imm_reg(codegendata *cd, s8 imm, s8 dreg) {
+       if (IS_IMM8((imm))) {
+               emit_rex(1,0,0,(dreg));
+               *(cd->mcodeptr++) = 0x6b;
+               emit_reg(0,(dreg));
+               emit_imm8((imm));
+       } else {
+               emit_rex(1,0,0,(dreg));
+               *(cd->mcodeptr++) = 0x69;
+               emit_reg(0,(dreg));
+               emit_imm32((imm));
+       }
+}
+
+
+void emit_imul_imm_reg_reg(codegendata *cd, s8 imm, s8 reg, s8 dreg) {
+       if (IS_IMM8((imm))) {
+               emit_rex(1,(dreg),0,(reg));
+               *(cd->mcodeptr++) = 0x6b;
+               emit_reg((dreg),(reg));
+               emit_imm8((imm));
+       } else {
+               emit_rex(1,(dreg),0,(reg));
+               *(cd->mcodeptr++) = 0x69;
+               emit_reg((dreg),(reg));
+               emit_imm32((imm));
+       }
+}
+
+
+void emit_imull_imm_reg_reg(codegendata *cd, s8 imm, s8 reg, s8 dreg) {
+       if (IS_IMM8((imm))) {
+               emit_rex(0,(dreg),0,(reg));
+               *(cd->mcodeptr++) = 0x6b;
+               emit_reg((dreg),(reg));
+               emit_imm8((imm));
+       } else {
+               emit_rex(0,(dreg),0,(reg));
+               *(cd->mcodeptr++) = 0x69;
+               emit_reg((dreg),(reg));
+               emit_imm32((imm));
+       }
+}
+
+
+void emit_imul_imm_membase_reg(codegendata *cd, s8 imm, s8 basereg, s8 disp, s8 dreg) {
+       if (IS_IMM8((imm))) {
+               emit_rex(1,(dreg),0,(basereg));
+               *(cd->mcodeptr++) = 0x6b;
+               emit_membase(cd, (basereg),(disp),(dreg));
+               emit_imm8((imm));
+       } else {
+               emit_rex(1,(dreg),0,(basereg));
+               *(cd->mcodeptr++) = 0x69;
+               emit_membase(cd, (basereg),(disp),(dreg));
+               emit_imm32((imm));
+       }
+}
+
+
+void emit_imull_imm_membase_reg(codegendata *cd, s8 imm, s8 basereg, s8 disp, s8 dreg) {
+       if (IS_IMM8((imm))) {
+               emit_rex(0,(dreg),0,(basereg));
+               *(cd->mcodeptr++) = 0x6b;
+               emit_membase(cd, (basereg),(disp),(dreg));
+               emit_imm8((imm));
+       } else {
+               emit_rex(0,(dreg),0,(basereg));
+               *(cd->mcodeptr++) = 0x69;
+               emit_membase(cd, (basereg),(disp),(dreg));
+               emit_imm32((imm));
+       }
+}
+
+
+void emit_idiv_reg(codegendata *cd, s8 reg) {
+       emit_rex(1,0,0,(reg));
+       *(cd->mcodeptr++) = 0xf7;
+       emit_reg(7,(reg));
+}
+
+
+void emit_idivl_reg(codegendata *cd, s8 reg) {
+       emit_rex(0,0,0,(reg));
+       *(cd->mcodeptr++) = 0xf7;
+       emit_reg(7,(reg));
+}
+
+
+
+void emit_ret(codegendata *cd) {
+    *(cd->mcodeptr++) = 0xc3;
+}
+
+
+
+/*
+ * shift ops
+ */
+void emit_shift_reg(codegendata *cd, s8 opc, s8 reg) {
+       emit_rex(1,0,0,(reg));
+       *(cd->mcodeptr++) = 0xd3;
+       emit_reg((opc),(reg));
+}
+
+
+void emit_shiftl_reg(codegendata *cd, s8 opc, s8 reg) {
+       emit_rex(0,0,0,(reg));
+       *(cd->mcodeptr++) = 0xd3;
+       emit_reg((opc),(reg));
+}
+
+
+void emit_shift_membase(codegendata *cd, s8 opc, s8 basereg, s8 disp) {
+       emit_rex(1,0,0,(basereg));
+       *(cd->mcodeptr++) = 0xd3;
+       emit_membase(cd, (basereg),(disp),(opc));
+}
+
+
+void emit_shiftl_membase(codegendata *cd, s8 opc, s8 basereg, s8 disp) {
+       emit_rex(0,0,0,(basereg));
+       *(cd->mcodeptr++) = 0xd3;
+       emit_membase(cd, (basereg),(disp),(opc));
+}
+
+
+void emit_shift_imm_reg(codegendata *cd, s8 opc, s8 imm, s8 dreg) {
+       if ((imm) == 1) {
+               emit_rex(1,0,0,(dreg));
+               *(cd->mcodeptr++) = 0xd1;
+               emit_reg((opc),(dreg));
+       } else {
+               emit_rex(1,0,0,(dreg));
+               *(cd->mcodeptr++) = 0xc1;
+               emit_reg((opc),(dreg));
+               emit_imm8((imm));
+       }
+}
+
+
+void emit_shiftl_imm_reg(codegendata *cd, s8 opc, s8 imm, s8 dreg) {
+       if ((imm) == 1) {
+               emit_rex(0,0,0,(dreg));
+               *(cd->mcodeptr++) = 0xd1;
+               emit_reg((opc),(dreg));
+       } else {
+               emit_rex(0,0,0,(dreg));
+               *(cd->mcodeptr++) = 0xc1;
+               emit_reg((opc),(dreg));
+               emit_imm8((imm));
+       }
+}
+
+
+void emit_shift_imm_membase(codegendata *cd, s8 opc, s8 imm, s8 basereg, s8 disp) {
+       if ((imm) == 1) {
+               emit_rex(1,0,0,(basereg));
+               *(cd->mcodeptr++) = 0xd1;
+               emit_membase(cd, (basereg),(disp),(opc));
+       } else {
+               emit_rex(1,0,0,(basereg));
+               *(cd->mcodeptr++) = 0xc1;
+               emit_membase(cd, (basereg),(disp),(opc));
+               emit_imm8((imm));
+       }
+}
+
+
+void emit_shiftl_imm_membase(codegendata *cd, s8 opc, s8 imm, s8 basereg, s8 disp) {
+       if ((imm) == 1) {
+               emit_rex(0,0,0,(basereg));
+               *(cd->mcodeptr++) = 0xd1;
+               emit_membase(cd, (basereg),(disp),(opc));
+       } else {
+               emit_rex(0,0,0,(basereg));
+               *(cd->mcodeptr++) = 0xc1;
+               emit_membase(cd, (basereg),(disp),(opc));
+               emit_imm8((imm));
+       }
+}
+
+
+
+/*
+ * jump operations
+ */
+void emit_jmp_imm(codegendata *cd, s8 imm) {
+       *(cd->mcodeptr++) = 0xe9;
+       emit_imm32((imm));
+}
+
+
+void emit_jmp_reg(codegendata *cd, s8 reg) {
+       emit_rex(0,0,0,(reg));
+       *(cd->mcodeptr++) = 0xff;
+       emit_reg(4,(reg));
+}
+
+
+void emit_jcc(codegendata *cd, s8 opc, s8 imm) {
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = (0x80 + (opc));
+       emit_imm32((imm));
+}
+
+
+
+/*
+ * conditional set and move operations
+ */
+
+/* we need the rex byte to get all low bytes */
+void emit_setcc_reg(codegendata *cd, s8 opc, s8 reg) {
+       *(cd->mcodeptr++) = (0x40 | (((reg) >> 3) & 0x01));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = (0x90 + (opc));
+       emit_reg(0,(reg));
+}
+
+
+/* we need the rex byte to get all low bytes */
+void emit_setcc_membase(codegendata *cd, s8 opc, s8 basereg, s8 disp) {
+       *(cd->mcodeptr++) = (0x40 | (((basereg) >> 3) & 0x01));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = (0x90 + (opc));
+       emit_membase(cd, (basereg),(disp),0);
+}
+
+
+void emit_cmovcc_reg_reg(codegendata *cd, s8 opc, s8 reg, s8 dreg)
+{
+       emit_rex(1,(dreg),0,(reg));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = (0x40 + (opc));
+       emit_reg((dreg),(reg));
+}
+
+
+void emit_cmovccl_reg_reg(codegendata *cd, s8 opc, s8 reg, s8 dreg)
+{
+       emit_rex(0,(dreg),0,(reg));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = (0x40 + (opc));
+       emit_reg((dreg),(reg));
+}
+
+
+
+void emit_neg_reg(codegendata *cd, s8 reg)
+{
+       emit_rex(1,0,0,(reg));
+       *(cd->mcodeptr++) = 0xf7;
+       emit_reg(3,(reg));
+}
+
+
+void emit_negl_reg(codegendata *cd, s8 reg)
+{
+       emit_rex(0,0,0,(reg));
+       *(cd->mcodeptr++) = 0xf7;
+       emit_reg(3,(reg));
+}
+
+
+void emit_push_reg(codegendata *cd, s8 reg) {
+       emit_rex(0,0,0,(reg));
+       *(cd->mcodeptr++) = 0x50 + (0x07 & (reg));
+}
+
+
+void emit_push_imm(codegendata *cd, s8 imm) {
+       *(cd->mcodeptr++) = 0x68;
+       emit_imm32((imm));
+}
+
+
+void emit_pop_reg(codegendata *cd, s8 reg) {
+       emit_rex(0,0,0,(reg));
+       *(cd->mcodeptr++) = 0x58 + (0x07 & (reg));
+}
+
+
+void emit_xchg_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
+       emit_rex(1,(reg),0,(dreg));
+       *(cd->mcodeptr++) = 0x87;
+       emit_reg((reg),(dreg));
+}
+
+
+void emit_nop(codegendata *cd) {
+    *(cd->mcodeptr++) = 0x90;
+}
+
+
+
+/*
+ * call instructions
+ */
+void emit_call_reg(codegendata *cd, s8 reg) {
+       emit_rex(1,0,0,(reg));
+       *(cd->mcodeptr++) = 0xff;
+       emit_reg(2,(reg));
+}
+
+
+void emit_call_imm(codegendata *cd, s8 imm) {
+       *(cd->mcodeptr++) = 0xe8;
+       emit_imm32((imm));
+}
+
+
+void emit_call_mem(codegendata *cd, ptrint mem)
+{
+       *(cd->mcodeptr++) = 0xff;
+       emit_mem(2,(mem));
+}
+
+
+
+/*
+ * floating point instructions (SSE2)
+ */
+void emit_addsd_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
+       *(cd->mcodeptr++) = 0xf2;
+       emit_rex(0,(dreg),0,(reg));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = 0x58;
+       emit_reg((dreg),(reg));
+}
+
+
+void emit_addss_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
+       *(cd->mcodeptr++) = 0xf3;
+       emit_rex(0,(dreg),0,(reg));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = 0x58;
+       emit_reg((dreg),(reg));
+}
+
+
+void emit_cvtsi2ssq_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
+       *(cd->mcodeptr++) = 0xf3;
+       emit_rex(1,(dreg),0,(reg));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = 0x2a;
+       emit_reg((dreg),(reg));
+}
+
+
+void emit_cvtsi2ss_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
+       *(cd->mcodeptr++) = 0xf3;
+       emit_rex(0,(dreg),0,(reg));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = 0x2a;
+       emit_reg((dreg),(reg));
+}
+
+
+void emit_cvtsi2sdq_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
+       *(cd->mcodeptr++) = 0xf2;
+       emit_rex(1,(dreg),0,(reg));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = 0x2a;
+       emit_reg((dreg),(reg));
+}
+
+
+void emit_cvtsi2sd_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
+       *(cd->mcodeptr++) = 0xf2;
+       emit_rex(0,(dreg),0,(reg));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = 0x2a;
+       emit_reg((dreg),(reg));
+}
+
+
+void emit_cvtss2sd_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
+       *(cd->mcodeptr++) = 0xf3;
+       emit_rex(0,(dreg),0,(reg));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = 0x5a;
+       emit_reg((dreg),(reg));
+}
+
+
+void emit_cvtsd2ss_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
+       *(cd->mcodeptr++) = 0xf2;
+       emit_rex(0,(dreg),0,(reg));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = 0x5a;
+       emit_reg((dreg),(reg));
+}
+
+
+void emit_cvttss2siq_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
+       *(cd->mcodeptr++) = 0xf3;
+       emit_rex(1,(dreg),0,(reg));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = 0x2c;
+       emit_reg((dreg),(reg));
+}
+
+
+void emit_cvttss2si_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
+       *(cd->mcodeptr++) = 0xf3;
+       emit_rex(0,(dreg),0,(reg));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = 0x2c;
+       emit_reg((dreg),(reg));
+}
+
+
+void emit_cvttsd2siq_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
+       *(cd->mcodeptr++) = 0xf2;
+       emit_rex(1,(dreg),0,(reg));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = 0x2c;
+       emit_reg((dreg),(reg));
+}
+
+
+void emit_cvttsd2si_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
+       *(cd->mcodeptr++) = 0xf2;
+       emit_rex(0,(dreg),0,(reg));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = 0x2c;
+       emit_reg((dreg),(reg));
+}
+
+
+void emit_divss_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
+       *(cd->mcodeptr++) = 0xf3;
+       emit_rex(0,(dreg),0,(reg));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = 0x5e;
+       emit_reg((dreg),(reg));
+}
+
+
+void emit_divsd_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
+       *(cd->mcodeptr++) = 0xf2;
+       emit_rex(0,(dreg),0,(reg));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = 0x5e;
+       emit_reg((dreg),(reg));
+}
+
+
+void emit_movd_reg_freg(codegendata *cd, s8 reg, s8 freg) {
+       *(cd->mcodeptr++) = 0x66;
+       emit_rex(1,(freg),0,(reg));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = 0x6e;
+       emit_reg((freg),(reg));
+}
+
+
+void emit_movd_freg_reg(codegendata *cd, s8 freg, s8 reg) {
+       *(cd->mcodeptr++) = 0x66;
+       emit_rex(1,(freg),0,(reg));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = 0x7e;
+       emit_reg((freg),(reg));
+}
+
+
+void emit_movd_reg_membase(codegendata *cd, s8 reg, s8 basereg, s8 disp) {
+       *(cd->mcodeptr++) = 0x66;
+       emit_rex(0,(reg),0,(basereg));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = 0x7e;
+       emit_membase(cd, (basereg),(disp),(reg));
+}
+
+
+void emit_movd_reg_memindex(codegendata *cd, s8 reg, s8 disp, s8 basereg, s8 indexreg, s8 scale) {
+       *(cd->mcodeptr++) = 0x66;
+       emit_rex(0,(reg),(indexreg),(basereg));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = 0x7e;
+       emit_memindex(cd, (reg),(disp),(basereg),(indexreg),(scale));
+}
+
+
+void emit_movd_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 dreg) {
+       *(cd->mcodeptr++) = 0x66;
+       emit_rex(1,(dreg),0,(basereg));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = 0x6e;
+       emit_membase(cd, (basereg),(disp),(dreg));
+}
+
+
+void emit_movdl_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 dreg) {
+       *(cd->mcodeptr++) = 0x66;
+       emit_rex(0,(dreg),0,(basereg));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = 0x6e;
+       emit_membase(cd, (basereg),(disp),(dreg));
+}
+
+
+void emit_movd_memindex_reg(codegendata *cd, s8 disp, s8 basereg, s8 indexreg, s8 scale, s8 dreg) {
+       *(cd->mcodeptr++) = 0x66;
+       emit_rex(0,(dreg),(indexreg),(basereg));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = 0x6e;
+       emit_memindex(cd, (dreg),(disp),(basereg),(indexreg),(scale));
+}
+
+
+void emit_movq_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
+       *(cd->mcodeptr++) = 0xf3;
+       emit_rex(0,(dreg),0,(reg));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = 0x7e;
+       emit_reg((dreg),(reg));
+}
+
+
+void emit_movq_reg_membase(codegendata *cd, s8 reg, s8 basereg, s8 disp) {
+       *(cd->mcodeptr++) = 0x66;
+       emit_rex(0,(reg),0,(basereg));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = 0xd6;
+       emit_membase(cd, (basereg),(disp),(reg));
+}
+
+
+void emit_movq_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 dreg) {
+       *(cd->mcodeptr++) = 0xf3;
+       emit_rex(0,(dreg),0,(basereg));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = 0x7e;
+       emit_membase(cd, (basereg),(disp),(dreg));
+}
+
+
+void emit_movss_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
+       *(cd->mcodeptr++) = 0xf3;
+       emit_rex(0,(reg),0,(dreg));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = 0x10;
+       emit_reg((reg),(dreg));
+}
+
+
+void emit_movsd_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
+       *(cd->mcodeptr++) = 0xf2;
+       emit_rex(0,(reg),0,(dreg));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = 0x10;
+       emit_reg((reg),(dreg));
+}
+
+
+void emit_movss_reg_membase(codegendata *cd, s8 reg, s8 basereg, s8 disp) {
+       *(cd->mcodeptr++) = 0xf3;
+       emit_rex(0,(reg),0,(basereg));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = 0x11;
+       emit_membase(cd, (basereg),(disp),(reg));
+}
+
+
+/* Always emit a REX byte, because the instruction size can be smaller when   */
+/* all register indexes are smaller than 7.                                   */
+void emit_movss_reg_membase32(codegendata *cd, s8 reg, s8 basereg, s8 disp) {
+       *(cd->mcodeptr++) = 0xf3;
+       emit_byte_rex((reg),0,(basereg));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = 0x11;
+       emit_membase32(cd, (basereg),(disp),(reg));
+}
+
+
+void emit_movsd_reg_membase(codegendata *cd, s8 reg, s8 basereg, s8 disp) {
+       *(cd->mcodeptr++) = 0xf2;
+       emit_rex(0,(reg),0,(basereg));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = 0x11;
+       emit_membase(cd, (basereg),(disp),(reg));
+}
+
+
+/* Always emit a REX byte, because the instruction size can be smaller when   */
+/* all register indexes are smaller than 7.                                   */
+void emit_movsd_reg_membase32(codegendata *cd, s8 reg, s8 basereg, s8 disp) {
+       *(cd->mcodeptr++) = 0xf2;
+       emit_byte_rex((reg),0,(basereg));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = 0x11;
+       emit_membase32(cd, (basereg),(disp),(reg));
+}
+
+
+void emit_movss_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 dreg) {
+       *(cd->mcodeptr++) = 0xf3;
+       emit_rex(0,(dreg),0,(basereg));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = 0x10;
+       emit_membase(cd, (basereg),(disp),(dreg));
+}
+
+
+/* Always emit a REX byte, because the instruction size can be smaller when   */
+/* all register indexes are smaller than 7.                                   */
+void emit_movss_membase32_reg(codegendata *cd, s8 basereg, s8 disp, s8 dreg) {
+       *(cd->mcodeptr++) = 0xf3;
+       emit_byte_rex((dreg),0,(basereg));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = 0x10;
+       emit_membase32(cd, (basereg),(disp),(dreg));
+}
+
+
+void emit_movlps_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 dreg)
+{
+       emit_rex(0,(dreg),0,(basereg));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = 0x12;
+       emit_membase(cd, (basereg),(disp),(dreg));
+}
+
+
+void emit_movlps_reg_membase(codegendata *cd, s8 reg, s8 basereg, s8 disp)
+{
+       emit_rex(0,(reg),0,(basereg));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = 0x13;
+       emit_membase(cd, (basereg),(disp),(reg));
+}
+
+
+void emit_movsd_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 dreg) {
+       *(cd->mcodeptr++) = 0xf2;
+       emit_rex(0,(dreg),0,(basereg));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = 0x10;
+       emit_membase(cd, (basereg),(disp),(dreg));
+}
+
+
+/* Always emit a REX byte, because the instruction size can be smaller when   */
+/* all register indexes are smaller than 7.                                   */
+void emit_movsd_membase32_reg(codegendata *cd, s8 basereg, s8 disp, s8 dreg) {
+       *(cd->mcodeptr++) = 0xf2;
+       emit_byte_rex((dreg),0,(basereg));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = 0x10;
+       emit_membase32(cd, (basereg),(disp),(dreg));
+}
+
+
+void emit_movlpd_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 dreg)
+{
+       *(cd->mcodeptr++) = 0x66;
+       emit_rex(0,(dreg),0,(basereg));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = 0x12;
+       emit_membase(cd, (basereg),(disp),(dreg));
+}
+
+
+void emit_movlpd_reg_membase(codegendata *cd, s8 reg, s8 basereg, s8 disp)
+{
+       *(cd->mcodeptr++) = 0x66;
+       emit_rex(0,(reg),0,(basereg));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = 0x13;
+       emit_membase(cd, (basereg),(disp),(reg));
+}
+
+
+void emit_movss_reg_memindex(codegendata *cd, s8 reg, s8 disp, s8 basereg, s8 indexreg, s8 scale) {
+       *(cd->mcodeptr++) = 0xf3;
+       emit_rex(0,(reg),(indexreg),(basereg));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = 0x11;
+       emit_memindex(cd, (reg),(disp),(basereg),(indexreg),(scale));
+}
+
+
+void emit_movsd_reg_memindex(codegendata *cd, s8 reg, s8 disp, s8 basereg, s8 indexreg, s8 scale) {
+       *(cd->mcodeptr++) = 0xf2;
+       emit_rex(0,(reg),(indexreg),(basereg));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = 0x11;
+       emit_memindex(cd, (reg),(disp),(basereg),(indexreg),(scale));
+}
+
+
+void emit_movss_memindex_reg(codegendata *cd, s8 disp, s8 basereg, s8 indexreg, s8 scale, s8 dreg) {
+       *(cd->mcodeptr++) = 0xf3;
+       emit_rex(0,(dreg),(indexreg),(basereg));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = 0x10;
+       emit_memindex(cd, (dreg),(disp),(basereg),(indexreg),(scale));
+}
+
+
+void emit_movsd_memindex_reg(codegendata *cd, s8 disp, s8 basereg, s8 indexreg, s8 scale, s8 dreg) {
+       *(cd->mcodeptr++) = 0xf2;
+       emit_rex(0,(dreg),(indexreg),(basereg));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = 0x10;
+       emit_memindex(cd, (dreg),(disp),(basereg),(indexreg),(scale));
+}
+
+
+void emit_mulss_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
+       *(cd->mcodeptr++) = 0xf3;
+       emit_rex(0,(dreg),0,(reg));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = 0x59;
+       emit_reg((dreg),(reg));
+}
+
+
+void emit_mulsd_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
+       *(cd->mcodeptr++) = 0xf2;
+       emit_rex(0,(dreg),0,(reg));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = 0x59;
+       emit_reg((dreg),(reg));
+}
+
+
+void emit_subss_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
+       *(cd->mcodeptr++) = 0xf3;
+       emit_rex(0,(dreg),0,(reg));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = 0x5c;
+       emit_reg((dreg),(reg));
+}
+
+
+void emit_subsd_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
+       *(cd->mcodeptr++) = 0xf2;
+       emit_rex(0,(dreg),0,(reg));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = 0x5c;
+       emit_reg((dreg),(reg));
+}
+
+
+void emit_ucomiss_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
+       emit_rex(0,(dreg),0,(reg));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = 0x2e;
+       emit_reg((dreg),(reg));
+}
+
+
+void emit_ucomisd_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
+       *(cd->mcodeptr++) = 0x66;
+       emit_rex(0,(dreg),0,(reg));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = 0x2e;
+       emit_reg((dreg),(reg));
+}
+
+
+void emit_xorps_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
+       emit_rex(0,(dreg),0,(reg));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = 0x57;
+       emit_reg((dreg),(reg));
+}
+
+
+void emit_xorps_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 dreg) {
+       emit_rex(0,(dreg),0,(basereg));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = 0x57;
+       emit_membase(cd, (basereg),(disp),(dreg));
+}
+
+
+void emit_xorpd_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
+       *(cd->mcodeptr++) = 0x66;
+       emit_rex(0,(dreg),0,(reg));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = 0x57;
+       emit_reg((dreg),(reg));
+}
+
+
+void emit_xorpd_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 dreg) {
+       *(cd->mcodeptr++) = 0x66;
+       emit_rex(0,(dreg),0,(basereg));
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = 0x57;
+       emit_membase(cd, (basereg),(disp),(dreg));
+}
+
+
+/* system instructions ********************************************************/
+
+void emit_rdtsc(codegendata *cd)
+{
+       *(cd->mcodeptr++) = 0x0f;
+       *(cd->mcodeptr++) = 0x31;
+}
+
+
+/*
+ * 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/s390/emit.h b/src/vm/jit/s390/emit.h
new file mode 100644 (file)
index 0000000..fd72bc6
--- /dev/null
@@ -0,0 +1,374 @@
+/* src/vm/jit/x86_64/md-emit.h - machine dependent emit function prototypes
+
+   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: emit.h 7219 2007-01-16 22:18:57Z pm $
+
+*/
+
+
+#ifndef _MD_EMIT_H
+#define _MD_EMIT_H
+
+#include "vm/types.h"
+
+
+/* macros to create code ******************************************************/
+
+/* immediate data union */
+
+typedef union {
+    s4 i;
+    s8 l;
+    float f;
+    double d;
+    void *a;
+    u1 b[8];
+} imm_buf;
+
+
+/* opcodes for alu instructions */
+
+#define ALU_ADD      0
+#define ALU_OR       1
+#define ALU_ADC      2
+#define ALU_SBB      3
+#define ALU_AND      4
+#define ALU_SUB      5
+#define ALU_XOR      6
+#define ALU_CMP      7
+
+
+#define SHIFT_ROL    0
+#define SHIFT_ROR    1
+#define SHIFT_RCL    2
+#define SHIFT_RCR    3
+#define SHIFT_SHL    4
+#define SHIFT_SHR    5
+#define SHIFT_SAR    7
+
+#if 0
+#define CC_O         0
+#define CC_NO        1
+#define CC_B         2
+#define CC_C         2
+#define CC_NAE       2
+#define CC_AE        3
+#define CC_NB        3
+#define CC_NC        3
+#define CC_E         4
+#define CC_Z         4
+#define CC_NE        5
+#define CC_NZ        5
+#define CC_BE        6
+#define CC_NA        6
+#define CC_A         7
+#define CC_NBE       7
+#define CC_S         8
+#define CC_LZ        8
+#define CC_NS        9
+#define CC_GEZ       9
+#define CC_P         0x0a
+#define CC_PE        0x0a
+#define CC_NP        0x0b
+#define CC_PO        0x0b
+#define CC_L         0x0c
+#define CC_NGE       0x0c
+#define CC_GE        0x0d
+#define CC_NL        0x0d
+#define CC_LE        0x0e
+#define CC_NG        0x0e
+#define CC_G         0x0f
+#define CC_NLE       0x0f
+#endif
+
+
+/* modrm and stuff */
+
+#define emit_address_byte(mod,reg,rm) \
+    do { \
+        *(cd->mcodeptr++) = ((((mod) & 0x03) << 6) | (((reg) & 0x07) << 3) | ((rm) & 0x07)); \
+    } while (0);
+
+
+#define emit_rex(size,reg,index,rm) \
+    do { \
+        if (((size) == 1) || ((reg) > 7) || ((index) > 7) || ((rm) > 7)) \
+            *(cd->mcodeptr++) = (0x40 | (((size) & 0x01) << 3) | ((((reg) >> 3) & 0x01) << 2) | ((((index) >> 3) & 0x01) << 1) | (((rm) >> 3) & 0x01)); \
+    } while (0)
+
+
+#define emit_byte_rex(reg,index,rm) \
+    do { \
+        *(cd->mcodeptr++) = (0x40 | ((((reg) >> 3) & 0x01) << 2) | ((((index) >> 3) & 0x01) << 1) | (((rm) >> 3) & 0x01)); \
+    } while (0)
+
+
+#define emit_mem(r,disp) \
+    do { \
+        emit_address_byte(0,(r),5); \
+        emit_imm32((disp)); \
+    } while (0)
+
+
+#define emit_imm8(imm) \
+    do { \
+        *(cd->mcodeptr++) = (u1) ((imm) & 0xff); \
+    } while (0)
+
+
+#define emit_imm16(imm) \
+    do { \
+        imm_buf imb; \
+        imb.i = (s4) (imm); \
+        *(cd->mcodeptr++) = imb.b[0]; \
+        *(cd->mcodeptr++) = imb.b[1]; \
+    } while (0)
+
+
+#define emit_imm32(imm) \
+    do { \
+        imm_buf imb; \
+        imb.i = (s4) (imm); \
+        *(cd->mcodeptr++) = imb.b[0]; \
+        *(cd->mcodeptr++) = imb.b[1]; \
+        *(cd->mcodeptr++) = imb.b[2]; \
+        *(cd->mcodeptr++) = imb.b[3]; \
+    } while (0)
+
+
+#define emit_imm64(imm) \
+    do { \
+        imm_buf imb; \
+        imb.l = (s8) (imm); \
+        *(cd->mcodeptr++) = imb.b[0]; \
+        *(cd->mcodeptr++) = imb.b[1]; \
+        *(cd->mcodeptr++) = imb.b[2]; \
+        *(cd->mcodeptr++) = imb.b[3]; \
+        *(cd->mcodeptr++) = imb.b[4]; \
+        *(cd->mcodeptr++) = imb.b[5]; \
+        *(cd->mcodeptr++) = imb.b[6]; \
+        *(cd->mcodeptr++) = imb.b[7]; \
+    } while (0)
+
+
+/* convenience macros *********************************************************/
+
+#define emit_reg(reg,rm)                emit_address_byte(3,(reg),(rm))
+
+
+/* function prototypes ********************************************************/
+
+void emit_cmovxx(codegendata *cd, instruction *iptr, s4 s, s4 d);
+
+
+/* code generation prototypes */
+
+void emit_ishift(jitdata *jd, s4 shift_op, instruction *iptr);
+void emit_lshift(jitdata *jd, s4 shift_op, instruction *iptr);
+
+
+/* integer instructions */
+
+void emit_mov_reg_reg(codegendata *cd, s8 reg, s8 dreg);
+void emit_mov_imm_reg(codegendata *cd, s8 imm, s8 reg);
+void emit_movl_reg_reg(codegendata *cd, s8 reg, s8 dreg);
+void emit_movl_imm_reg(codegendata *cd, s8 imm, s8 reg);
+void emit_mov_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 reg);
+void emit_mov_membase32_reg(codegendata *cd, s8 basereg, s8 disp, s8 reg);
+void emit_movl_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 reg);
+void emit_movl_membase32_reg(codegendata *cd, s8 basereg, s8 disp, s8 reg);
+void emit_mov_reg_membase(codegendata *cd, s8 reg, s8 basereg, s8 disp);
+void emit_mov_reg_membase32(codegendata *cd, s8 reg, s8 basereg, s8 disp);
+void emit_movl_reg_membase(codegendata *cd, s8 reg, s8 basereg, s8 disp);
+void emit_movl_reg_membase32(codegendata *cd, s8 reg, s8 basereg, s8 disp);
+void emit_mov_memindex_reg(codegendata *cd, s8 disp, s8 basereg, s8 indexreg, s8 scale, s8 reg);
+void emit_movl_memindex_reg(codegendata *cd, s8 disp, s8 basereg, s8 indexreg, s8 scale, s8 reg);
+void emit_mov_reg_memindex(codegendata *cd, s8 reg, s8 disp, s8 basereg, s8 indexreg, s8 scale);
+void emit_movl_reg_memindex(codegendata *cd, s8 reg, s8 disp, s8 basereg, s8 indexreg, s8 scale);
+void emit_movw_reg_memindex(codegendata *cd, s8 reg, s8 disp, s8 basereg, s8 indexreg, s8 scale);
+void emit_movb_reg_memindex(codegendata *cd, s8 reg, s8 disp, s8 basereg, s8 indexreg, s8 scale);
+void emit_mov_imm_membase(codegendata *cd, s8 imm, s8 basereg, s8 disp);
+void emit_mov_imm_membase32(codegendata *cd, s8 imm, s8 basereg, s8 disp);
+void emit_movl_imm_membase(codegendata *cd, s8 imm, s8 basereg, s8 disp);
+void emit_movl_imm_membase32(codegendata *cd, s8 imm, s8 basereg, s8 disp);
+void emit_movsbq_reg_reg(codegendata *cd, s8 reg, s8 dreg);
+void emit_movsbq_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 dreg);
+void emit_movswq_reg_reg(codegendata *cd, s8 reg, s8 dreg);
+void emit_movswq_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 dreg);
+void emit_movslq_reg_reg(codegendata *cd, s8 reg, s8 dreg);
+void emit_movslq_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 dreg);
+void emit_movzwq_reg_reg(codegendata *cd, s8 reg, s8 dreg);
+void emit_movzwq_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 dreg);
+void emit_movswq_memindex_reg(codegendata *cd, s8 disp, s8 basereg, s8 indexreg, s8 scale, s8 reg);
+void emit_movsbq_memindex_reg(codegendata *cd, s8 disp, s8 basereg, s8 indexreg, s8 scale, s8 reg);
+void emit_movzwq_memindex_reg(codegendata *cd, s8 disp, s8 basereg, s8 indexreg, s8 scale, s8 reg);
+void emit_mov_imm_memindex(codegendata *cd, s4 imm, s4 disp, s4 basereg, s4 indexreg, s4 scale);
+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_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);
+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_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);
+void emit_test_reg_reg(codegendata *cd, s8 reg, s8 dreg);
+void emit_testl_reg_reg(codegendata *cd, s8 reg, s8 dreg);
+void emit_test_imm_reg(codegendata *cd, s8 imm, s8 reg);
+void emit_testw_imm_reg(codegendata *cd, s8 imm, s8 reg);
+void emit_testb_imm_reg(codegendata *cd, s8 imm, s8 reg);
+void emit_lea_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 reg);
+void emit_leal_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 reg);
+
+void emit_incl_membase(codegendata *cd, s8 basereg, s8 disp);
+
+void emit_cltd(codegendata *cd);
+void emit_cqto(codegendata *cd);
+void emit_imul_reg_reg(codegendata *cd, s8 reg, s8 dreg);
+void emit_imull_reg_reg(codegendata *cd, s8 reg, s8 dreg);
+void emit_imul_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 dreg);
+void emit_imull_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 dreg);
+void emit_imul_imm_reg(codegendata *cd, s8 imm, s8 dreg);
+void emit_imul_imm_reg_reg(codegendata *cd, s8 imm,s8 reg, s8 dreg);
+void emit_imull_imm_reg_reg(codegendata *cd, s8 imm, s8 reg, s8 dreg);
+void emit_imul_imm_membase_reg(codegendata *cd, s8 imm, s8 basereg, s8 disp, s8 dreg);
+void emit_imull_imm_membase_reg(codegendata *cd, s8 imm, s8 basereg, s8 disp, s8 dreg);
+void emit_idiv_reg(codegendata *cd, s8 reg);
+void emit_idivl_reg(codegendata *cd, s8 reg);
+void emit_ret(codegendata *cd);
+void emit_shift_reg(codegendata *cd, s8 opc, s8 reg);
+void emit_shiftl_reg(codegendata *cd, s8 opc, s8 reg);
+void emit_shift_membase(codegendata *cd, s8 opc, s8 basereg, s8 disp);
+void emit_shiftl_membase(codegendata *cd, s8 opc, s8 basereg, s8 disp);
+void emit_shift_imm_reg(codegendata *cd, s8 opc, s8 imm, s8 dreg);
+void emit_shiftl_imm_reg(codegendata *cd, s8 opc, s8 imm, s8 dreg);
+void emit_shift_imm_membase(codegendata *cd, s8 opc, s8 imm, s8 basereg, s8 disp);
+void emit_shiftl_imm_membase(codegendata *cd, s8 opc, s8 imm, s8 basereg, s8 disp);
+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_neg_reg(codegendata *cd, s8 reg);
+void emit_negl_reg(codegendata *cd, s8 reg);
+void emit_neg_membase(codegendata *cd, s8 basereg, s8 disp);
+void emit_negl_membase(codegendata *cd, s8 basereg, s8 disp);
+void emit_push_reg(codegendata *cd, s8 reg);
+void emit_push_imm(codegendata *cd, s8 imm);
+void emit_pop_reg(codegendata *cd, s8 reg);
+void emit_xchg_reg_reg(codegendata *cd, s8 reg, s8 dreg);
+void emit_nop(codegendata *cd);
+void emit_call_reg(codegendata *cd, s8 reg);
+void emit_call_imm(codegendata *cd, s8 imm);
+void emit_call_mem(codegendata *cd, ptrint mem);
+
+
+/* floating point instructions (SSE2) */
+
+void emit_addsd_reg_reg(codegendata *cd, s8 reg, s8 dreg);
+void emit_addss_reg_reg(codegendata *cd, s8 reg, s8 dreg);
+void emit_cvtsi2ssq_reg_reg(codegendata *cd, s8 reg, s8 dreg);
+void emit_cvtsi2ss_reg_reg(codegendata *cd, s8 reg, s8 dreg);
+void emit_cvtsi2sdq_reg_reg(codegendata *cd, s8 reg, s8 dreg);
+void emit_cvtsi2sd_reg_reg(codegendata *cd, s8 reg, s8 dreg);
+void emit_cvtss2sd_reg_reg(codegendata *cd, s8 reg, s8 dreg);
+void emit_cvtsd2ss_reg_reg(codegendata *cd, s8 reg, s8 dreg);
+void emit_cvttss2siq_reg_reg(codegendata *cd, s8 reg, s8 dreg);
+void emit_cvttss2si_reg_reg(codegendata *cd, s8 reg, s8 dreg);
+void emit_cvttsd2siq_reg_reg(codegendata *cd, s8 reg, s8 dreg);
+void emit_cvttsd2si_reg_reg(codegendata *cd, s8 reg, s8 dreg);
+void emit_divss_reg_reg(codegendata *cd, s8 reg, s8 dreg);
+void emit_divsd_reg_reg(codegendata *cd, s8 reg, s8 dreg);
+void emit_movd_reg_freg(codegendata *cd, s8 reg, s8 freg);
+void emit_movd_freg_reg(codegendata *cd, s8 freg, s8 reg);
+void emit_movd_reg_membase(codegendata *cd, s8 reg, s8 basereg, s8 disp);
+void emit_movd_reg_memindex(codegendata *cd, s8 reg, s8 disp, s8 basereg, s8 indexreg, s8 scale);
+void emit_movd_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 dreg);
+void emit_movdl_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 dreg);
+void emit_movd_memindex_reg(codegendata *cd, s8 disp, s8 basereg, s8 indexreg, s8 scale, s8 dreg);
+void emit_movq_reg_reg(codegendata *cd, s8 reg, s8 dreg);
+void emit_movq_reg_membase(codegendata *cd, s8 reg, s8 basereg, s8 disp);
+void emit_movq_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 dreg);
+void emit_movss_reg_reg(codegendata *cd, s8 reg, s8 dreg);
+void emit_movsd_reg_reg(codegendata *cd, s8 reg, s8 dreg);
+void emit_movss_reg_membase(codegendata *cd, s8 reg, s8 basereg, s8 disp);
+void emit_movss_reg_membase32(codegendata *cd, s8 reg, s8 basereg, s8 disp);
+void emit_movsd_reg_membase(codegendata *cd, s8 reg, s8 basereg, s8 disp);
+void emit_movsd_reg_membase32(codegendata *cd, s8 reg, s8 basereg, s8 disp);
+void emit_movss_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 dreg);
+void emit_movss_membase32_reg(codegendata *cd, s8 basereg, s8 disp, s8 dreg);
+void emit_movlps_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 dreg);
+void emit_movlps_reg_membase(codegendata *cd, s8 reg, s8 basereg, s8 disp);
+void emit_movsd_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 dreg);
+void emit_movsd_membase32_reg(codegendata *cd, s8 basereg, s8 disp, s8 dreg);
+void emit_movlpd_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 dreg);
+void emit_movlpd_reg_membase(codegendata *cd, s8 reg, s8 basereg, s8 disp);
+void emit_movss_reg_memindex(codegendata *cd, s8 reg, s8 disp, s8 basereg, s8 indexreg, s8 scale);
+void emit_movsd_reg_memindex(codegendata *cd, s8 reg, s8 disp, s8 basereg, s8 indexreg, s8 scale);
+void emit_movss_memindex_reg(codegendata *cd, s8 disp, s8 basereg, s8 indexreg, s8 scale, s8 dreg);
+void emit_movsd_memindex_reg(codegendata *cd, s8 disp, s8 basereg, s8 indexreg, s8 scale, s8 dreg);
+void emit_mulss_reg_reg(codegendata *cd, s8 reg, s8 dreg);
+void emit_mulsd_reg_reg(codegendata *cd, s8 reg, s8 dreg);
+void emit_subss_reg_reg(codegendata *cd, s8 reg, s8 dreg);
+void emit_subsd_reg_reg(codegendata *cd, s8 reg, s8 dreg);
+void emit_ucomiss_reg_reg(codegendata *cd, s8 reg, s8 dreg);
+void emit_ucomisd_reg_reg(codegendata *cd, s8 reg, s8 dreg);
+void emit_xorps_reg_reg(codegendata *cd, s8 reg, s8 dreg);
+void emit_xorps_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 dreg);
+void emit_xorpd_reg_reg(codegendata *cd, s8 reg, s8 dreg);
+void emit_xorpd_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 dreg);
+
+
+/* system instructions ********************************************************/
+
+void emit_rdtsc(codegendata *cd);
+
+#endif /* _MD_EMIT_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/s390/machine-instr.h b/src/vm/jit/s390/machine-instr.h
new file mode 100644 (file)
index 0000000..a9164c7
--- /dev/null
@@ -0,0 +1,42 @@
+#ifndef _MACHINE_INSTR_H
+#define _MACHINE_INSTR_H
+
+static inline void
+__attribute__ ((unused))
+atomic_add (volatile int *mem, int val)
+{
+#if 0
+  __asm__ __volatile__ ("lock; addl %1,%0"
+                                               : "=m" (*mem) 
+                                               : "ir" (val), "m" (*mem));
+#endif
+}
+
+static inline long
+__attribute__ ((unused))
+compare_and_swap (volatile long *p, long oldval, long newval)
+{
+#if 0
+  long ret;
+
+  __asm__ __volatile__ ("lock; cmpxchgq %2, %1"
+                        : "=a" (ret), "=m" (*p)
+                        : "r" (newval), "m" (*p), "0" (oldval));
+  return ret;
+#endif
+}
+
+#if 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__ ( \
+               "mfence" : : : "memory" )
+#endif
+
+#define STORE_ORDER_BARRIER()
+#define MEMORY_BARRIER_BEFORE_ATOMIC()
+#define MEMORY_BARRIER_AFTER_ATOMIC()
+#define MEMORY_BARRIER()
+
+#endif
diff --git a/src/vm/jit/s390/md-abi.c b/src/vm/jit/s390/md-abi.c
new file mode 100644 (file)
index 0000000..b270266
--- /dev/null
@@ -0,0 +1,219 @@
+/* src/vm/jit/x86_64/md-abi.c - functions for x86_64 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: Christian Thalinger
+
+   Changes:
+
+   $Id: md-abi.c 7219 2007-01-16 22:18:57Z pm $
+
+*/
+
+
+#include "config.h"
+#include "vm/types.h"
+
+#include "vm/jit/s390/md-abi.h"
+
+#include "vm/descriptor.h"
+#include "vm/global.h"
+
+
+/* register descripton array **************************************************/
+
+s4 nregdescint[] = {
+#if 0
+    REG_RET, REG_ARG, REG_ARG, REG_TMP, REG_RES, REG_SAV, REG_ARG, REG_ARG,
+    REG_ARG, REG_ARG, REG_RES, REG_RES, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
+#endif
+       REG_TMP, REG_TMP, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_SAV,
+       REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_RES, REG_TMP, REG_RES,
+    REG_END
+};
+
+
+s4 nregdescfloat[] = {
+#if 0
+    REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG,
+    REG_RES, REG_RES, REG_RES, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
+#endif
+       REG_ARG, REG_TMP, REG_ARG, REG_TMP, REG_SAV, REG_TMP, REG_SAV, REG_TMP,
+       REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
+    REG_END
+};
+
+
+/* md_param_alloc **************************************************************
+
+   XXX
+
+*******************************************************************************/
+
+void md_param_alloc(methoddesc *md)
+{
+       paramdesc *pd;
+       s4         i;
+       s4         iarg;
+       s4         farg;
+       s4         stacksize;
+
+       /* set default values */
+
+       iarg = 0;
+       farg = 0;
+       stacksize = 0;
+
+       /* get params field of methoddesc */
+
+       pd = md->params;
+
+       for (i = 0; i < md->paramcount; i++, pd++) {
+               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;
+                       }
+                       else {
+                               pd->inmemory = true;
+                               pd->regoff   = stacksize;
+                       }
+                       if (iarg < INT_ARG_CNT)
+                               iarg++;
+                       else
+                               stacksize++;
+                       break;
+
+               case TYPE_FLT:
+               case TYPE_DBL:
+                       if (farg < FLT_ARG_CNT) {
+                               pd->inmemory = false;
+                               pd->regoff   = farg;
+                       }
+                       else {
+                               pd->inmemory = true;
+                               pd->regoff   = stacksize;
+                       }
+                       if (farg < FLT_ARG_CNT)
+                               farg++;
+                       else
+                               stacksize++;
+                       break;
+               }
+       }
+
+       /* Since XMM0 (==A0) is 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;
+
+       /* fill register and stack usage */
+
+       md->argintreguse = iarg;
+       md->argfltreguse = farg;
+       md->memuse       = stacksize;
+}
+
+
+/* md_return_alloc *************************************************************
+
+   Precolor the Java Stackelement containing the Return Value. Only
+   for float/ double types straight forward possible, since INT_LNG
+   types use "reserved" registers Float/Double values use a00 as
+   return register.
+
+   --- in
+   jd:                      jitdata of the current method
+   stackslot:               Java Stackslot to contain the Return Value
+
+   --- out
+   if precoloring was possible:
+   VAR(stackslot->varnum)->flags     = PREALLOC
+                                    ->vv.regoff = [REG_RESULT|REG_FRESULT]
+   rd->arg[flt|int]reguse   set to a value according the register usage
+
+   NOTE: Do not pass a LOCALVAR in stackslot->varnum.
+
+*******************************************************************************/
+
+void md_return_alloc(jitdata *jd, stackptr stackslot)
+{
+       methodinfo   *m;
+       registerdata *rd;
+       methoddesc   *md;
+
+       /* get required compiler data */
+
+       m  = jd->m;
+       rd = jd->rd;
+
+       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" */
+
+       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 (!(stackslot->flags & SAVEDVAR)) {
+
+                               VAR(stackslot->varnum)->flags = PREALLOC;
+
+                           /* float/double */
+                               if (rd->argfltreguse < 1)
+                                       rd->argfltreguse = 1;
+
+                               VAR(stackslot->varnum)->vv.regoff = REG_FRESULT;
+                       }
+               }
+       }
+}
+
+
+/*
+ * 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/s390/md-abi.h b/src/vm/jit/s390/md-abi.h
new file mode 100644 (file)
index 0000000..466cb68
--- /dev/null
@@ -0,0 +1,200 @@
+/* src/vm/jit/x86_64/md-abi.h - defines for x86_64 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: Christian Thalinger
+
+   Changes:
+
+   $Id: md-abi.h 7219 2007-01-16 22:18:57Z pm $
+
+*/
+
+
+#ifndef _MD_ABI_H
+#define _MD_ABI_H
+
+/* keep old code happy */
+
+#define RIP    -1
+#define RAX    0
+#define RCX    1
+#define RDX    2
+#define RBX    3
+#define RSP    4
+#define RBP    5
+#define RSI    6
+#define RDI    7
+#define R8     8
+#define R9     9
+#define R10    10
+#define R11    11
+#define R12    12
+#define R13    13
+#define R14    14
+#define R15    15
+
+
+#define XMM0   0
+#define XMM1   1
+#define XMM2   2
+#define XMM3   3
+#define XMM4   4
+#define XMM5   5
+#define XMM6   6
+#define XMM7   7
+#define XMM8   8
+#define XMM9   9
+#define XMM10  10
+#define XMM11  11
+#define XMM12  12
+#define XMM13  13
+#define XMM14  14
+#define XMM15  15
+
+
+#define REG_IFTMP       10   /* temporary integer and floating point register */
+
+
+/* define registers ***********************************************************/
+
+#define R0     0
+#define R1     1
+#define R2     2
+#define R3     3
+#define R4     4
+#define R5     5
+#define R6     6 
+#define R7     7
+#define R8     8
+#define R9     9
+#define R10    10
+#define R11    11
+#define R12    12
+#define R13    13
+#define R14    14
+#define R15    15
+
+#define F0     0
+#define F1     1
+#define F2     2
+#define F3     3
+#define F4     4
+#define F5     5
+#define F6     6
+#define F7     7
+#define F8     8
+#define F9     9
+#define F10    10
+#define F11    11
+#define F12    12
+#define F13    13
+#define F14    14
+#define F15    15
+
+/* preallocated registers *****************************************************/
+
+/* integer registers */
+  
+#define REG_RESULT      R2       /* to deliver method results                 */
+#define REG_RESULT2     R3
+
+#define REG_ITMP1       R0       /* temporary register                        */
+#define REG_ITMP2       R1       /* temporary register and method pointer     */
+#define REG_ITMP3       R14      /* temporary register                        */
+
+#define REG_ITMP12_PACKED    PACK_REGS(REG_ITMP2, REG_ITMP1)
+#define REG_ITMP23_PACKED    PACK_REGS(REG_ITMP3, REG_ITMP2)
+#define REG_RESULT_PACKED    PACK_REGS(REG_RESULT2, REG_RESULT)
+
+#define REG_METHODPTR   REG_ITMP2/* pointer to the place from where the       */
+                                 /* procedure vector has been fetched         */
+
+#define REG_NULL        -1       /* used for reg_of_var where d is not needed */
+
+#define REG_ITMP1_XPTR  REG_ITMP1/* exception pointer = temporary register 1  */
+#define REG_ITMP2_XPC   REG_ITMP2/* exception pc = temporary register 2       */
+
+#define REG_SP          R15      /* stack pointer                             */
+
+#define REG_PV  R13
+
+#define REG_A0          R2      /* define some argument registers            */
+#define REG_A1          R3
+#define REG_A2          R4 
+#define REG_A3          R5
+#define REG_A4          R6
+
+/* floating point registers */
+
+#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_IFTMP       10       /* temporary integer and floating point register */
+
+
+#define INT_REG_CNT     16       /* number of integer registers               */
+#define INT_SAV_CNT     6        /* number of integer callee saved registers  */
+#define INT_ARG_CNT     5        /* number of integer argument registers      */
+#define INT_TMP_CNT     3        /* number of integer temporary registers     */
+#define INT_RES_CNT     2        /* 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_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 TRACE_ARGS_NUM  6
+
+
+
+
+
+
+
+
+
+
+
+
+#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/s390/md-asm.h b/src/vm/jit/s390/md-asm.h
new file mode 100644 (file)
index 0000000..0d673a2
--- /dev/null
@@ -0,0 +1,196 @@
+/* src/vm/jit/x86_64/md-asm.h - assembler defines for x86_64 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: Christian Thalinger
+
+   Changes:
+
+   $Id: md-asm.h 7219 2007-01-16 22:18:57Z pm $
+
+*/
+
+
+#ifndef _MD_ASM_H
+#define _MD_ASM_H
+
+/* register defines ***********************************************************/
+
+#if 0
+
+#define v0       %rax
+#define v0l      %eax
+#define itmp1    v0
+
+#define a3       %rcx
+#define a2       %rdx
+
+#define t0       %rbx
+#define t0l      %ebx
+
+#define sp       %rsp
+#define s0       %rbp
+
+#define a1       %rsi
+#define a0       %rdi
+#define a0l      %edi
+
+#define a4       %r8
+#define a5       %r9
+
+#define itmp2    %r10
+#define itmp3    %r14
+
+#define s1       %r12
+#define s2       %r13
+#define s3       %r14
+#define s4       %r15
+
+
+#define bp       s0
+
+#define itmp1l   %eax
+#define itmp2l   %r10d
+#define itmp3l   %r11d
+
+#define xptr     itmp1
+#define xpc      itmp2
+#define mptr     itmp2
+
+
+#define fa0      %xmm0
+#define fa1      %xmm1
+#define fa2      %xmm2
+#define fa3      %xmm3
+#define fa4      %xmm4
+#define fa5      %xmm5
+#define fa6      %xmm6
+#define fa7      %xmm7
+
+#define ftmp1    %xmm8
+#define ftmp2    %xmm9
+#define ftmp3    %xmm10
+
+#define ft0      %xmm11
+#define ft1      %xmm12
+#define ft2      %xmm13
+#define ft3      %xmm14
+#define ft4      %xmm15
+
+#endif
+
+#define a0       %r2
+#define a1       %r3
+#define a2       %r4
+#define a3       %r5
+#define a4       %r6
+
+#define sp       %r15
+#define itmp1    %r0
+#define itmp2    %r1
+#define itmp3    %r14
+#define v0       %r2
+#define pv       %r13
+
+#define mptr     itmp2
+
+#define s0 %r7
+#define s1 %r8
+#define s2 %r9
+#define s3 %r10
+#define s4 %r11
+#define s5 %r12
+
+#define fa0 %f0
+#define fa1 %f2
+
+/* save and restore macros ****************************************************/
+
+#define SAVE_ARGUMENT_REGISTERS(off) \
+       mov     a0,(0+(off))*8(sp)   ; \
+       mov     a1,(1+(off))*8(sp)   ; \
+       mov     a2,(2+(off))*8(sp)   ; \
+       mov     a3,(3+(off))*8(sp)   ; \
+       mov     a4,(4+(off))*8(sp)   ; \
+       mov     a5,(5+(off))*8(sp)   ; \
+       \
+       movq    fa0,(6+(off))*8(sp)  ; \
+       movq    fa1,(7+(off))*8(sp)  ; \
+       movq    fa2,(8+(off))*8(sp)  ; \
+       movq    fa3,(9+(off))*8(sp)  ; \
+       movq    fa4,(10+(off))*8(sp) ; \
+       movq    fa5,(11+(off))*8(sp) ; \
+       movq    fa6,(12+(off))*8(sp) ; \
+       movq    fa7,(13+(off))*8(sp) ;
+
+
+#define RESTORE_ARGUMENT_REGISTERS(off) \
+       mov     (0+(off))*8(sp),a0   ; \
+       mov     (1+(off))*8(sp),a1   ; \
+       mov     (2+(off))*8(sp),a2   ; \
+       mov     (3+(off))*8(sp),a3   ; \
+       mov     (4+(off))*8(sp),a4   ; \
+       mov     (5+(off))*8(sp),a5   ; \
+       \
+       movq    (6+(off))*8(sp),fa0  ; \
+       movq    (7+(off))*8(sp),fa1  ; \
+       movq    (8+(off))*8(sp),fa2  ; \
+       movq    (9+(off))*8(sp),fa3  ; \
+       movq    (10+(off))*8(sp),fa4 ; \
+       movq    (11+(off))*8(sp),fa5 ; \
+       movq    (12+(off))*8(sp),fa6 ; \
+       movq    (13+(off))*8(sp),fa7 ;
+
+
+#define SAVE_TEMPORARY_REGISTERS(off) \
+       mov     t0,(0+(off))*8(sp)   ; \
+       movq    ft0,(1+(off))*8(sp)  ; \
+       movq    ft1,(2+(off))*8(sp)  ; \
+       movq    ft2,(3+(off))*8(sp)  ; \
+       movq    ft3,(4+(off))*8(sp)  ;
+
+
+#define RESTORE_TEMPORARY_REGISTERS(off) \
+       mov     (0+(off))*8(sp),t0   ; \
+       movq    (1+(off))*8(sp),ft0  ; \
+       movq    (2+(off))*8(sp),ft1  ; \
+       movq    (3+(off))*8(sp),ft2  ; \
+       movq    (4+(off))*8(sp),ft3  ;
+
+#endif /* _MD_ASM_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/s390/md.c b/src/vm/jit/s390/md.c
new file mode 100644 (file)
index 0000000..949b133
--- /dev/null
@@ -0,0 +1,434 @@
+/* src/vm/jit/x86_64/md.c - machine dependent x86_64 Linux functions
+
+   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: Edwin Steiner
+
+   $Id: md.c 7219 2007-01-16 22:18:57Z pm $
+
+*/
+
+#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_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
+
+#include "config.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <ucontext.h>
+
+#include "vm/jit/s390/md-abi.h"
+
+#if defined(ENABLE_THREADS)
+# include "threads/native/threads.h"
+#endif
+
+#include "vm/exceptions.h"
+#include "vm/signallocal.h"
+#include "vm/jit/asmpart.h"
+#include "vm/jit/stacktrace.h"
+
+#if !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER)
+#include "vm/options.h" /* XXX debug */
+#include "vm/jit/disass.h" /* XXX debug */
+#endif
+
+
+/* md_init *********************************************************************
+
+   Do some machine dependent initialization.
+
+*******************************************************************************/
+
+void md_init(void)
+{
+       /* nothing to do */
+}
+
+
+/* md_signal_handler_sigsegv ***************************************************
+
+   NullPointerException signal handler for hardware null pointer
+   check.
+
+*******************************************************************************/
+
+void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
+{
+       ucontext_t *_uc;
+       mcontext_t *_mc;
+       u1         *sp;
+       u1         *ra;
+       u1         *xpc;
+
+       _uc = (ucontext_t *) _p;
+       _mc = &_uc->uc_mcontext;
+
+       /* ATTENTION: Don't use CACAO's internal REG_* defines as they are
+          different to the ones in <ucontext.h>. */
+
+       sp  = (u1 *) _mc->gregs[REG_RSP];
+       xpc = (u1 *) _mc->gregs[REG_RIP];
+       ra  = xpc;                          /* return address is equal to xpc     */
+
+#if 0
+       /* check for StackOverflowException */
+
+       threads_check_stackoverflow(sp);
+#endif
+
+       _mc->gregs[REG_RAX] =
+               (ptrint) stacktrace_hardware_nullpointerexception(NULL, sp, ra, xpc);
+
+       _mc->gregs[REG_R10] = (ptrint) xpc;                      /* REG_ITMP2_XPC */
+       _mc->gregs[REG_RIP] = (ptrint) asm_handle_exception;
+}
+
+
+/* md_signal_handler_sigfpe ****************************************************
+
+   ArithmeticException signal handler for hardware divide by zero
+   check.
+
+*******************************************************************************/
+
+void md_signal_handler_sigfpe(int sig, siginfo_t *siginfo, void *_p)
+{
+       ucontext_t  *_uc;
+       mcontext_t  *_mc;
+       u1          *sp;
+       u1          *ra;
+       u1          *xpc;
+
+       _uc = (ucontext_t *) _p;
+       _mc = &_uc->uc_mcontext;
+
+       /* ATTENTION: Don't use CACAO's internal REG_* defines as they are
+          different to the ones in <ucontext.h>. */
+
+       sp  = (u1 *) _mc->gregs[REG_RSP];
+       xpc = (u1 *) _mc->gregs[REG_RIP];
+       ra  = xpc;                          /* return address is equal to xpc     */
+
+       _mc->gregs[REG_RAX] =
+               (ptrint) stacktrace_hardware_arithmeticexception(NULL, sp, ra, xpc);
+
+       _mc->gregs[REG_R10] = (ptrint) xpc;                      /* REG_ITMP2_XPC */
+       _mc->gregs[REG_RIP] = (ptrint) asm_handle_exception;
+}
+
+
+/* md_signal_handler_sigusr2 ***************************************************
+
+   Signal handler for profiling sampling.
+
+*******************************************************************************/
+
+#if defined(ENABLE_THREADS)
+void md_signal_handler_sigusr2(int sig, siginfo_t *siginfo, void *_p)
+{
+       threadobject *t;
+       ucontext_t   *_uc;
+       mcontext_t   *_mc;
+       u1           *pc;
+
+       t = THREADOBJECT;
+
+       _uc = (ucontext_t *) _p;
+       _mc = &_uc->uc_mcontext;
+
+       /* ATTENTION: Don't use CACAO's internal REG_* defines as they are
+          different to the ones in <ucontext.h>. */
+
+       pc = (u1 *) _mc->gregs[REG_RIP];
+
+       t->pc = pc;
+}
+#endif
+
+
+#if defined(ENABLE_THREADS)
+void thread_restartcriticalsection(ucontext_t *_uc)
+{
+       mcontext_t *_mc;
+       void       *pc;
+
+       _mc = &_uc->uc_mcontext;
+
+       pc = critical_find_restart_point((void *) _mc->gregs[REG_RIP]);
+
+       if (pc != NULL)
+               _mc->gregs[REG_RIP] = (ptrint) pc;
+}
+#endif
+
+
+/* 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
+   the passed stack pointer and the stack frame size.
+
+*******************************************************************************/
+
+u1 *md_stacktrace_get_returnaddress(u1 *sp, u4 framesize)
+{
+       u1 *ra;
+
+       /* on x86_64 the return address is above the current stack frame */
+
+       ra = *((u1 **) (sp + framesize));
+
+       return ra;
+}
+
+
+/* md_get_method_patch_address *************************************************
+
+   Gets the patch address of the currently compiled method. The offset
+   is extracted from the load instruction(s) before the jump and added
+   to the right base address (PV or REG_METHODPTR).
+
+   INVOKESTATIC/SPECIAL:
+
+   4d 8b 15 e2 fe ff ff             mov    -286(%rip),%r10
+   49 ff d2                         rex64Z callq  *%r10
+
+   INVOKEVIRTUAL:
+
+   4c 8b 17                         mov    (%rdi),%r10
+   49 8b 82 00 00 00 00             mov    0x0(%r10),%rax
+   48 ff d3                         rex64 callq  *%rax
+
+   INVOKEINTERFACE:
+
+   4c 8b 17                         mov    (%rdi),%r10
+   4d 8b 92 00 00 00 00             mov    0x0(%r10),%r10
+   49 8b 82 00 00 00 00             mov    0x0(%r10),%rax
+   48 ff d3                         rex64 callq  *%r11
+
+*******************************************************************************/
+
+u1 *md_get_method_patch_address(u1 *ra, stackframeinfo *sfi, u1 *mptr)
+{
+       u1  mcode;
+       s4  offset;
+       u1 *pa;                             /* patch address                      */
+
+       /* go back to the actual call instruction (3-bytes) */
+
+       ra = ra - 3;
+
+       /* get the last byte of the call */
+
+       mcode = ra[2];
+
+       /* check for the different calls */
+
+       if (mcode == 0xd2) {
+               /* INVOKESTATIC/SPECIAL */
+
+               /* Get the offset from the instruction (the offset address is
+                  4-bytes before the call instruction). */
+
+               offset = *((s4 *) (ra - 4));
+
+               /* add the offset to the return address (IP-relative addressing) */
+
+               pa = ra + offset;
+       }
+       else if (mcode == 0xd3) {
+               /* INVOKEVIRTUAL/INTERFACE */
+
+               /* Get the offset from the instruction (the offset address is
+                  4-bytes before the call instruction). */
+
+               offset = *((s4 *) (ra - 4));
+
+               /* add the offset to the method pointer */
+
+               pa = mptr + offset;
+       }
+       else {
+               /* catch any problems */
+
+               assert(0);
+       }
+
+       return pa;
+}
+
+
+/* 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;
+
+       /* Get the start address of the function which contains this
+       address from the method table. */
+
+       pv = codegen_get_pv_from_pc(ra);
+
+       return pv;
+}
+
+
+/* md_cacheflush ***************************************************************
+
+   Calls the system's function to flush the instruction and data
+   cache.
+
+*******************************************************************************/
+
+void md_cacheflush(u1 *addr, s4 nbytes)
+{
+       /* do nothing */
+}
+
+
+/* md_icacheflush **************************************************************
+
+   Calls the system's function to flush the instruction cache.
+
+*******************************************************************************/
+
+void md_icacheflush(u1 *addr, s4 nbytes)
+{
+       /* do nothing */
+}
+
+
+/* md_dcacheflush **************************************************************
+
+   Calls the system's function to flush the data cache.
+
+*******************************************************************************/
+
+void md_dcacheflush(u1 *addr, s4 nbytes)
+{
+       /* do nothing */
+}
+
+
+/* md_patch_replacement_point **************************************************
+
+   Patch the given replacement point.
+
+*******************************************************************************/
+
+void md_patch_replacement_point(rplpoint *rp)
+{
+    u8 mcode;
+
+       /* XXX this is probably unsafe! */
+
+       /* save the current machine code */
+       mcode = *(u8*)rp->pc;
+
+       /* write spinning instruction */
+       *(u2*)(rp->pc) = 0xebfe;
+
+       /* write 5th byte */
+       rp->pc[4] = (rp->mcode >> 32);
+
+       /* write first word */
+    *(u4*)(rp->pc) = (u4) rp->mcode;
+
+       /* store saved mcode */
+       rp->mcode = mcode;
+       
+#if !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER)
+       {
+               u1* u1ptr = rp->pc;
+               DISASSINSTR(u1ptr);
+               fflush(stdout);
+       }
+#endif
+                       
+    /* XXX if required asm_cacheflush(rp->pc,8); */
+}
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
diff --git a/src/vm/jit/s390/patcher.c b/src/vm/jit/s390/patcher.c
new file mode 100644 (file)
index 0000000..c28528f
--- /dev/null
@@ -0,0 +1,922 @@
+/* src/vm/jit/x86_64/patcher.c - x86_64 code patching functions
+
+   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: patcher.c 7219 2007-01-16 22:18:57Z pm $
+
+*/
+
+
+#include "config.h"
+#include "vm/types.h"
+
+#include "vm/jit/s390/codegen.h"
+
+#include "mm/memory.h"
+#include "native/native.h"
+#include "vm/builtin.h"
+#include "vm/class.h"
+#include "vm/exceptions.h"
+#include "vm/field.h"
+#include "vm/initialize.h"
+#include "vm/options.h"
+#include "vm/references.h"
+#include "vm/resolve.h"
+#include "vm/jit/patcher.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;
+
+       /* define the patcher function */
+
+       bool (*patcher_function)(u1 *);
+
+       /* get stuff from the stack */
+
+       xpc = (u1 *)                *((ptrint *) (sp + 5 * 8));
+       o   = (java_objectheader *) *((ptrint *) (sp + 4 * 8));
+       f   = (functionptr)         *((ptrint *) (sp + 0 * 8));
+
+       /* calculate and set the new return address */
+
+       xpc = xpc - PATCHER_CALL_SIZE;
+
+       *((ptrint *) (sp + 5 * 8)) = (ptrint) xpc;
+
+       /* 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 + 6 * 8, 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_get_putstatic *******************************************************
+
+   Machine code:
+
+   <patched call position>
+   4d 8b 15 86 fe ff ff             mov    -378(%rip),%r10
+   49 8b 32                         mov    (%r10),%rsi
+
+*******************************************************************************/
+
+bool patcher_get_putstatic(u1 *sp)
+{
+       u1               *ra;
+       u8                mcode;
+       unresolved_field *uf;
+       s4                disp;
+       fieldinfo        *fi;
+
+       /* get stuff from the stack */
+
+       ra    = (u1 *)               *((ptrint *) (sp + 5 * 8));
+       mcode =                      *((u8 *)     (sp + 3 * 8));
+       uf    = (unresolved_field *) *((ptrint *) (sp + 2 * 8));
+       disp  =                      *((s4 *)     (sp + 1 * 8));
+
+       /* get the fieldinfo */
+
+       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 back original code */
+
+       *((u8 *) ra) = mcode;
+
+       /* if we show disassembly, we have to skip the nop's */
+
+       if (opt_shownops)
+               ra = ra + 5;
+
+       /* patch the field value's address */
+
+       *((ptrint *) (ra + 7 + disp)) = (ptrint) &(fi->value);
+
+       return true;
+}
+
+
+/* patcher_get_putfield ********************************************************
+
+   Machine code:
+
+   <patched call position>
+   45 8b 8f 00 00 00 00             mov    0x0(%r15),%r9d
+
+*******************************************************************************/
+
+bool patcher_get_putfield(u1 *sp)
+{
+       u1               *ra;
+       u8                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));
+
+       /* get the fieldinfo */
+
+       if (!(fi = resolve_field_eager(uf)))
+               return false;
+
+       /* patch back original code (instruction code is smaller than 8 bytes) */
+
+       *((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 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);
+       }
+
+       return true;
+}
+
+
+/* patcher_putfieldconst *******************************************************
+
+   Machine code:
+
+   <patched call position>
+   41 c7 85 00 00 00 00 7b 00 00 00    movl   $0x7b,0x0(%r13)
+
+*******************************************************************************/
+
+bool patcher_putfieldconst(u1 *sp)
+{
+       u1               *ra;
+       u8                mcode;
+       unresolved_field *uf;
+       fieldinfo        *fi;
+
+       /* get stuff from the stack */
+
+       ra    = (u1 *)               *((ptrint *) (sp + 5 * 8));
+       mcode =                      *((u8 *)     (sp + 3 * 8));
+       uf    = (unresolved_field *) *((ptrint *) (sp + 2 * 8));
+
+       /* get the fieldinfo */
+
+       if (!(fi = resolve_field_eager(uf)))
+               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 + 5;
+
+       /* patch the field's offset */
+
+       if (IS_2_WORD_TYPE(fi->type) || IS_ADR_TYPE(fi->type)) {
+               /* handle special case when the base register is %r12 */
+
+               if (*(ra + 2) == 0x84) {
+                       *((u4 *) (ra + 4))      = (u4) (fi->offset);
+                       *((u4 *) (ra + 12 + 4)) = (u4) (fi->offset + 4);
+               }
+               else {
+                       *((u4 *) (ra + 3))      = (u4) (fi->offset);
+                       *((u4 *) (ra + 11 + 3)) = (u4) (fi->offset + 4);
+               }
+       }
+       else {
+               /* handle special case when the base register is %r12 */
+
+               if (*(ra + 2) == 0x84)
+                       *((u4 *) (ra + 4)) = (u4) (fi->offset);
+               else
+                       *((u4 *) (ra + 3)) = (u4) (fi->offset);
+       }
+
+       return true;
+}
+
+
+/* patcher_aconst **************************************************************
+
+   Machine code:
+
+   <patched call position>
+   48 bf a0 f0 92 00 00 00 00 00    mov    $0x92f0a0,%rdi
+
+*******************************************************************************/
+
+bool patcher_aconst(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 classinfo */
+
+       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 + 5;
+
+       /* patch the classinfo pointer */
+
+       *((ptrint *) (ra + 2)) = (ptrint) c;
+
+       return true;
+}
+
+
+/* patcher_builtin_multianewarray **********************************************
+
+   Machine code:
+
+   <patched call position>
+   48 bf 02 00 00 00 00 00 00 00    mov    $0x2,%rdi
+   48 be 30 40 b2 00 00 00 00 00    mov    $0xb24030,%rsi
+   48 89 e2                         mov    %rsp,%rdx
+   48 b8 7c 96 4b 00 00 00 00 00    mov    $0x4b967c,%rax
+   48 ff d0                         callq  *%rax
+
+*******************************************************************************/
+
+bool patcher_builtin_multianewarray(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 classinfo */
+
+       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 + 5;
+
+       /* patch the classinfo pointer */
+
+       *((ptrint *) (ra + 10 + 2)) = (ptrint) c;
+
+       return true;
+}
+
+
+/* patcher_builtin_arraycheckcast **********************************************
+
+   Machine code:
+
+   <patched call position>
+   48 be b8 3f b2 00 00 00 00 00    mov    $0xb23fb8,%rsi
+   48 b8 00 00 00 00 00 00 00 00    mov    $0x0,%rax
+   48 ff d0                         callq  *%rax
+
+*******************************************************************************/
+
+bool patcher_builtin_arraycheckcast(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 classinfo */
+
+       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 + 5;
+
+       /* patch the classinfo pointer */
+
+       *((ptrint *) (ra + 2)) = (ptrint) c;
+
+       return true;
+}
+
+
+/* patcher_invokestatic_special ************************************************
+
+   Machine code:
+
+   <patched call position>
+   49 ba 00 00 00 00 00 00 00 00    mov    $0x0,%r10
+   49 ff d2                         callq  *%r10
+
+*******************************************************************************/
+
+bool patcher_invokestatic_special(u1 *sp)
+{
+       u1                *ra;
+       u8                 mcode;
+       unresolved_method *um;
+       s4                 disp;
+       methodinfo        *m;
+
+       /* get stuff from the stack */
+
+       ra    = (u1 *)                *((ptrint *) (sp + 5 * 8));
+       mcode =                       *((u8 *)     (sp + 3 * 8));
+       um    = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
+       disp  =                       *((s4 *)     (sp + 1 * 8));
+
+       /* get the fieldinfo */
+
+       if (!(m = resolve_method_eager(um)))
+               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 + 5;
+
+       /* patch stubroutine */
+
+/*     *((ptrint *) (ra + 2)) = (ptrint) m->stubroutine; */
+       *((ptrint *) (ra + 7 + disp)) = (ptrint) m->stubroutine;
+
+       return true;
+}
+
+
+/* patcher_invokevirtual *******************************************************
+
+   Machine code:
+
+   <patched call position>
+   4c 8b 17                         mov    (%rdi),%r10
+   49 8b 82 00 00 00 00             mov    0x0(%r10),%rax
+   48 ff d0                         callq  *%rax
+
+*******************************************************************************/
+
+bool patcher_invokevirtual(u1 *sp)
+{
+       u1                *ra;
+       u8                 mcode;
+       unresolved_method *um;
+       methodinfo        *m;
+
+       /* get stuff from the stack */
+
+       ra    = (u1 *)                *((ptrint *) (sp + 5 * 8));
+       mcode =                       *((u8 *)     (sp + 3 * 8));
+       um    = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
+
+       /* get the fieldinfo */
+
+       if (!(m = resolve_method_eager(um)))
+               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 + 5;
+
+       /* patch vftbl index */
+
+       *((s4 *) (ra + 3 + 3)) = (s4) (OFFSET(vftbl_t, table[0]) +
+                                                                  sizeof(methodptr) * m->vftblindex);
+
+       return true;
+}
+
+
+/* patcher_invokeinterface *****************************************************
+
+   Machine code:
+
+   <patched call position>
+   4c 8b 17                         mov    (%rdi),%r10
+   4d 8b 92 00 00 00 00             mov    0x0(%r10),%r10
+   49 8b 82 00 00 00 00             mov    0x0(%r10),%rax
+   48 ff d0                         callq  *%rax
+
+*******************************************************************************/
+
+bool patcher_invokeinterface(u1 *sp)
+{
+       u1                *ra;
+       u8                 mcode;
+       unresolved_method *um;
+       methodinfo        *m;
+
+       /* get stuff from the stack */
+
+       ra    = (u1 *)                *((ptrint *) (sp + 5 * 8));
+       mcode =                       *((u8 *)     (sp + 3 * 8));
+       um    = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
+
+       /* get the fieldinfo */
+
+       if (!(m = resolve_method_eager(um)))
+               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 + 5;
+
+       /* patch interfacetable index */
+
+       *((s4 *) (ra + 3 + 3)) = (s4) (OFFSET(vftbl_t, interfacetable[0]) -
+                                                                  sizeof(methodptr) * m->class->index);
+
+       /* patch method offset */
+
+       *((s4 *) (ra + 3 + 7 + 3)) =
+               (s4) (sizeof(methodptr) * (m - m->class->methods));
+
+       return true;
+}
+
+
+/* patcher_checkcast_instanceof_flags ******************************************
+
+   Machine code:
+
+   <patched call position>
+   41 ba 00 00 00 00                mov    $0x0,%r10d
+   41 81 e2 00 02 00 00             and    $0x200,%r10d
+   0f 84 35 00 00 00                je     0x00002aaaaab01479
+
+*******************************************************************************/
+
+bool patcher_checkcast_instanceof_flags(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 + 5;
+
+       /* patch class flags */
+
+       *((s4 *) (ra + 2)) = (s4) c->flags;
+
+       return true;
+}
+
+
+/* patcher_checkcast_instanceof_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
+   4d 8b 9a 00 00 00 00             mov    0x0(%r10),%r11
+
+*******************************************************************************/
+
+bool patcher_checkcast_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 + 5;
+
+       /* patch super class index */
+
+       *((s4 *) (ra + 7 + 3)) = (s4) c->index;
+
+       *((s4 *) (ra + 7 + 7 + 3 + 6 + 3)) =
+               (s4) (OFFSET(vftbl_t, interfacetable[0]) -
+                         c->index * sizeof(methodptr*));
+
+       return true;
+}
+
+
+/* patcher_checkcast_class *****************************************************
+
+   Machine code:
+
+   <patched call position>
+   49 bb 00 00 00 00 00 00 00 00    mov    $0x0,%r11
+   45 8b 92 20 00 00 00             mov    0x20(%r10),%r10d
+   45 8b 9b 20 00 00 00             mov    0x20(%r11),%r11d
+   4d 29 da                         sub    %r11,%r10
+   49 bb 00 00 00 00 00 00 00 00    mov    $0x0,%r11
+
+*******************************************************************************/
+
+bool patcher_checkcast_class(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 + 5;
+
+       /* patch super class' vftbl */
+
+       *((ptrint *) (ra + 2)) = (ptrint) c->vftbl;
+       *((ptrint *) (ra + 10 + 7 + 7 + 3 + 2)) = (ptrint) c->vftbl;
+
+       return true;
+}
+
+
+/* patcher_instanceof_class ****************************************************
+
+   Machine code:
+
+   <patched call position>
+   49 ba 00 00 00 00 00 00 00 00    mov    $0x0,%r10
+
+*******************************************************************************/
+
+bool patcher_instanceof_class(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 + 5;
+
+       /* patch super class' vftbl */
+
+       *((ptrint *) (ra + 2)) = (ptrint) c->vftbl;
+
+       return true;
+}
+
+
+/* patcher_clinit **************************************************************
+
+   May be used for GET/PUTSTATIC and in native stub.
+
+   Machine code:
+
+   <patched call position>
+   4d 8b 15 92 ff ff ff             mov    -110(%rip),%r10
+   49 89 1a                         mov    %rbx,(%r10)
+
+*******************************************************************************/
+
+bool patcher_clinit(u1 *sp)
+{
+       u1        *ra;
+       u8         mcode;
+       classinfo *c;
+
+       /* get stuff from the stack */
+
+       ra    = (u1 *)        *((ptrint *) (sp + 5 * 8));
+       mcode =               *((u8 *)     (sp + 3 * 8));
+       c     = (classinfo *) *((ptrint *) (sp + 2 * 8));
+
+       /* check if the class is initialized */
+
+       if (!(c->state & CLASS_INITIALIZED))
+               if (!initialize_class(c))
+                       return false;
+
+       /* patch back original code */
+
+       *((u8 *) ra) = mcode;
+
+       return true;
+}
+
+
+/* patcher_athrow_areturn ******************************************************
+
+   Machine code:
+
+   <patched call position>
+
+*******************************************************************************/
+
+#ifdef ENABLE_VERIFIER
+bool patcher_athrow_areturn(u1 *sp)
+{
+       u1               *ra;
+       u8                mcode;
+       unresolved_class *uc;
+       classinfo        *c;
+
+       /* get stuff from the stack */
+
+       ra    = (u1 *)               *((ptrint *) (sp + 5 * 8));
+       mcode =                      *((u8 *)     (sp + 3 * 8));
+       uc    = (unresolved_class *) *((ptrint *) (sp + 2 * 8));
+
+       /* resolve the class */
+
+       if (!resolve_class(uc, resolveEager, false, &c))
+               return false;
+
+       /* patch back original code */
+
+       *((u8 *) ra) = mcode;
+
+       return true;
+}
+#endif /* ENABLE_VERIFIER */
+
+
+/* patcher_resolve_native ******************************************************
+
+   Machine code:
+
+   <patched call position>
+   48 b8 00 00 00 00 00 00 00 00    mov    $0x0,%rax
+   48 ff d0                         callq  *%rax
+
+*******************************************************************************/
+
+#if !defined(WITH_STATIC_CLASSPATH)
+bool patcher_resolve_native(u1 *sp)
+{
+       u1          *ra;
+       u8           mcode;
+       methodinfo  *m;
+       functionptr  f;
+
+       /* get stuff from the stack */
+
+       ra    = (u1 *)         *((ptrint *) (sp + 5 * 8));
+       mcode =                *((u8 *)     (sp + 3 * 8));
+       m     = (methodinfo *) *((ptrint *) (sp + 2 * 8));
+
+       /* resolve native function */
+
+       if (!(f = native_resolve_function(m)))
+               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 + 5;
+
+       /* patch native function pointer */
+
+       *((ptrint *) (ra + 2)) = (ptrint) f;
+
+       return true;
+}
+#endif /* !defined(WITH_STATIC_CLASSPATH) */
+
+
+/*
+ * 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:
+ */