powerpc64 compiles
authortbfg <none@none>
Thu, 6 Jul 2006 13:59:01 +0000 (13:59 +0000)
committertbfg <none@none>
Thu, 6 Jul 2006 13:59:01 +0000 (13:59 +0000)
arch.h and md-abi.h: modified PV register assignment

--HG--
rename : src/vm/jit/powerpc/Makefile.am => src/vm/jit/powerpc64/Makefile.am
rename : src/vm/jit/powerpc/asmpart.S => src/vm/jit/powerpc64/asmpart.S
rename : src/vm/jit/powerpc/codegen.c => src/vm/jit/powerpc64/codegen.c
rename : src/vm/jit/powerpc/codegen.h => src/vm/jit/powerpc64/codegen.h
rename : src/vm/jit/powerpc/disass.c => src/vm/jit/powerpc64/disass.c
rename : src/vm/jit/powerpc/emit.c => src/vm/jit/powerpc64/emit.c
rename : src/vm/jit/powerpc/linux/Makefile.am => src/vm/jit/powerpc64/linux/Makefile.am
rename : src/vm/jit/powerpc/linux/md-abi.c => src/vm/jit/powerpc64/linux/md-abi.c
rename : src/vm/jit/powerpc/linux/md-asm.h => src/vm/jit/powerpc64/linux/md-asm.h
rename : src/vm/jit/powerpc/linux/md-os.c => src/vm/jit/powerpc64/linux/md-os.c
rename : src/vm/jit/powerpc/machine-instr.h => src/vm/jit/powerpc64/machine-instr.h
rename : src/vm/jit/powerpc/md.c => src/vm/jit/powerpc64/md.c
rename : src/vm/jit/powerpc/patcher.c => src/vm/jit/powerpc64/patcher.c

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

index 5a48967570aa26453daf82225d4fdd73d936d89c..77be62674644c93773b01d131136f6bd8cc916c8 100644 (file)
@@ -340,7 +340,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 )
+        arm | i386 | powerpc | x86_64 | sparc64 | powerpc64)
             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)])
@@ -818,6 +818,8 @@ AC_CONFIG_FILES([Makefile]
                [src/vm/jit/powerpc/darwin/Makefile]
                [src/vm/jit/powerpc/linux/Makefile]
                [src/vm/jit/powerpc/netbsd/Makefile]
+               [src/vm/jit/powerpc64/Makefile]
+               [src/vm/jit/powerpc64/linux/Makefile]
                [src/vm/jit/profile/Makefile]
                [src/vm/jit/schedule/Makefile]
                [src/vm/jit/sparc64/Makefile]
index 03919780ce37302b8ff0f5f3cf5b75ebfae0b148..6aba53588725b31f48d5866d7daee0fda2df91fe 100644 (file)
@@ -28,7 +28,7 @@
 
    Changes: Edwin Steiner
 
-   $Id: patcher.h 5077 2006-07-04 19:06:56Z twisti $
+   $Id: patcher.h 5081 2006-07-06 13:59:01Z tbfg $
 
 */
 
@@ -150,7 +150,7 @@ bool patcher_checkcast_instanceof_flags(u1 *sp);
 bool patcher_checkcast_instanceof_interface(u1 *sp);
 #define PATCHER_checkcast_instanceof_interface (functionptr) patcher_checkcast_instanceof_interface
 
-#if defined(__I386__) || defined(__X86_64__) || defined(__POWERPC__)
+#if defined(__I386__) || defined(__X86_64__) || defined(__POWERPC__) || defined(__POWERPC64__)
 
 bool patcher_checkcast_class(u1 *sp);
 #define PATCHER_checkcast_class (functionptr) patcher_checkcast_class
@@ -158,12 +158,12 @@ bool patcher_checkcast_class(u1 *sp);
 bool patcher_instanceof_class(u1 *sp);
 #define PATCHER_instanceof_class (functionptr) patcher_instanceof_class
 
-#else /* defined(__I386__) || defined(__X86_64__) || defined(__POWERPC__) */
+#else /* defined(__I386__) || defined(__X86_64__) || defined(__POWERPC__) || defined(__POWERPC64__)*/
 
 bool patcher_checkcast_instanceof_class(u1 *sp);
 #define PATCHER_checkcast_instanceof_class (functionptr) patcher_checkcast_instanceof_class
 
-#endif /* defined(__I386__) || defined(__X86_64__) || defined(__POWERPC__) */
+#endif /* defined(__I386__) || defined(__X86_64__) || defined(__POWERPC__) || defined(__POWERPC64__)*/
 
 bool patcher_clinit(u1 *sp);
 #define PATCHER_clinit (functionptr) patcher_clinit
diff --git a/src/vm/jit/powerpc64/Makefile.am b/src/vm/jit/powerpc64/Makefile.am
new file mode 100644 (file)
index 0000000..84504b8
--- /dev/null
@@ -0,0 +1,84 @@
+## src/vm/jit/powerpc/Makefile.am
+##
+## Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+## C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
+## E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
+## J. Wenninger, Institut f. Computersprachen - TU Wien
+##
+## This file is part of CACAO.
+##
+## This program is free software; you can redistribute it and/or
+## modify it under the terms of the GNU General Public License as
+## published by the Free Software Foundation; either version 2, or (at
+## your option) any later version.
+##
+## This program is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+## 02110-1301, USA.
+##
+## Contact: cacao@cacaojvm.org
+##
+## Authors: Christian Thalinger
+##
+## Changes:
+##
+## $Id: Makefile.am 5081 2006-07-06 13:59:01Z tbfg $
+
+## Process this file with automake to produce Makefile.in
+
+DIST_SUBDIRS = \
+       linux 
+
+SUBDIRS = $(OS_DIR)
+
+AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_builddir) -I$(top_builddir)/src -I$(top_srcdir)/src/vm/jit/$(ARCH_DIR)/$(OS_DIR)
+AM_CCASFLAGS = $(AM_CPPFLAGS)
+
+LIBS =
+
+BUILT_SOURCES = offsets.h
+
+CLEANFILES = offsets.h
+
+noinst_HEADERS = \
+       arch.h \
+       machine-instr.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 \
+       md.c \
+       patcher.c
+
+libarch_la_LIBADD = \
+       $(OS_DIR)/libmd.la
+
+$(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:
index 5f0853409717245f314459034ed46acad60f2409..bc5bea25e2491cfd8ac364e493f12a6c8a41b02e 100644 (file)
@@ -28,7 +28,7 @@
 
    Changes:
 
-   $Id: arch.h 4912 2006-05-14 12:22:25Z edwin $
+   $Id: arch.h 5081 2006-07-06 13:59:01Z tbfg $
 
 */
 
 
 #define SUPPORT_FMOD                     0
 #define SUPPORT_FICVT                    1
-#define SUPPORT_IFCVT                    0
+#define SUPPORT_IFCVT                    1
 
 #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               0
-#define SUPPORT_LONG_MUL                 0
-#define SUPPORT_LONG_DIV                 0
-#define SUPPORT_LONG_ICVT                0
-#define SUPPORT_LONG_FCVT                0
+#define SUPPORT_LONG_SHIFT               1
+#define SUPPORT_LONG_MUL                 1
+#define SUPPORT_LONG_DIV                 1
+#define SUPPORT_LONG_ICVT                1
+#define SUPPORT_LONG_FCVT                1
 
 #define SUPPORT_CONST_LOGICAL            1  /* AND, OR, XOR with immediates   */
 #define SUPPORT_CONST_MUL                1  /* mutiply with immediate         */
diff --git a/src/vm/jit/powerpc64/asmpart.S b/src/vm/jit/powerpc64/asmpart.S
new file mode 100644 (file)
index 0000000..ae9a00f
--- /dev/null
@@ -0,0 +1,1581 @@
+/* src/vm/jit/powerpc/asmpart.S - Java-C interface functions for PowerPC
+               
+   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.text;  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
+            Stefan Ring
+
+   Changes: Christian Thalinger
+            Edwin Steiner
+
+   $Id: asmpart.S 5081 2006-07-06 13:59:01Z tbfg $
+
+*/
+
+
+#include "config.h"
+
+#include "md-abi.h"
+#include "md-asm.h"
+
+#include "vm/jit/abi-asm.h"
+#include "vm/jit/methodheader.h"
+#include "vm/jit/powerpc64/offsets.h"
+
+
+       .text
+
+       .align 2
+
+
+/* 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_nat_exception
+       .globl asm_handle_exception
+
+       .globl asm_abstractmethoderror
+
+       .globl asm_wrapper_patcher
+
+       .globl asm_replacement_out
+       .globl asm_replacement_in
+
+       .globl asm_cacheflush
+       .globl asm_criticalsections
+       .globl asm_getclassvalues_atomic
+
+
+/* asm_vm_call_method **********************************************************
+*                                                                              *
+*   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 2
+
+       .long   0                         /* catch type all                       */
+       .long   0                         /* exception handler pc                 */
+       .long   0                         /* end pc                               */
+       .long   0                         /* start pc                             */
+       .long   1                         /* extable size                         */
+       .long   0                         /* line number table start              */
+       .long   0                         /* line number table size               */
+       .long   0                         /* fltsave                              */
+       .long   0                         /* intsave                              */
+       .long   0                         /* isleaf                               */
+       .long   0                         /* IsSync                               */
+       .long   0                         /* frame size                           */
+       .long   0                         /* codeinfo pointer                     */
+
+asm_vm_call_method:
+asm_vm_call_method_int:
+asm_vm_call_method_long:
+asm_vm_call_method_float:
+asm_vm_call_method_double:
+       mflr    r0
+       stw     r0,LA_LR_OFFSET(r1)
+       stwu    r1,-40*4(r1)
+
+       stw     s0,8*4(sp)                /* save used callee saved registers     */
+       stw     a0,9*4(sp)                /* save method pointer for compiler     */
+
+#if defined(__DARWIN__)
+       stw     itmp1,10*4(sp)            /* register r11 is callee saved         */
+#endif
+       stw     pv,11*4(sp)               /* save PV register                     */
+
+       stw     itmp3,12*4(sp)            /* registers r14-r31 are callee saved   */
+       stfd    ftmp1,14*4(sp)            /* registers f14-f31 are callee saved   */
+       stfd    ftmp2,16*4(sp)
+
+#if defined(__DARWIN__)
+       stw     t1,18*4(r1)
+       stw     t2,19*4(r1)
+       stw     t3,20*4(r1)
+       stw     t4,21*4(r1)
+       stw     t5,22*4(r1)
+       stw     t6,23*4(r1)
+       stw     t7,24*4(r1)
+
+       stfd    ft0,26*4(r1)
+       stfd    ft1,28*4(r1)
+       stfd    ft2,30*4(r1)
+       stfd    ft3,32*4(r1)
+       stfd    ft4,34*4(r1)
+       stfd    ft5,36*4(r1)
+#else
+       SAVE_TEMPORARY_REGISTERS(18)      /* the offset has to be even            */
+#endif
+
+       mr      itmp2,a1                  /* arg count                            */
+       mr      itmp1,a2                  /* pointer to arg block                 */
+
+       mr      t4,itmp2                  /* save argument count                  */
+       mr      t5,itmp1                  /* save argument block pointer          */
+
+       mr      s0,sp                     /* save current sp to s0                */
+
+       addi    itmp1,itmp1,-sizevmarg    /* initialize pointer (smaller code)    */
+       addi    itmp2,itmp2,1             /* initialize argument count            */
+       li      t0,0                      /* initialize integer argument counter  */
+       li      t1,0                      /* initialize float argument counter    */
+       li      t6,0                      /* initialize integer register counter  */
+#if defined(__DARWIN__)
+       li      t7,0                      /* initialize stack slot counter        */
+#endif
+
+       mflr    r0                        /* save link register (PIC code)        */
+       bl      L_asm_vm_call_method_get_pc
+L_asm_vm_call_method_get_pc:
+       mflr    t3                        /* t3 contains the current pc           */
+       mtlr    r0
+
+L_register_copy:
+       addi    itmp1,itmp1,sizevmarg     /* goto next argument block             */
+       addi    itmp2,itmp2,-1            /* argument count - 1                   */
+       mr.     itmp2,itmp2
+       beq     L_register_copy_done
+
+       lwz     itmp3,offvmargtype+4(itmp1)
+       andi.   r0,itmp3,0x0002           /* is this a float/double type?         */
+       bne     L_register_handle_float
+       
+L_register_handle_int:
+       cmpwi   t6,INT_ARG_CNT            /* are we out of integer argument       */
+       beq     L_register_copy           /* registers? yes, next loop            */
+
+       andi.   r0,itmp3,0x0001           /* is this a 2-word type?               */
+       bne     L_register_handle_long
+
+#if defined(__DARWIN__)
+       addis   itmp3,t3,ha16(L_jumptable_int - L_asm_vm_call_method_get_pc)
+       la      itmp3,lo16(L_jumptable_int - L_asm_vm_call_method_get_pc)(itmp3)
+#else
+       lis     itmp3,L_jumptable_int@ha
+       addi    itmp3,itmp3,L_jumptable_int@l
+#endif
+
+       slwi    t2,t6,2                   /* multiple of 4-bytes                  */
+       add     itmp3,itmp3,t2            /* calculate address of jumptable       */
+       lwz     itmp3,0(itmp3)            /* load function address                */
+       mtctr   itmp3
+       addi    t0,t0,1                   /* integer argument counter             */
+       addi    t6,t6,1                   /* integer argument register counter    */
+#if defined(__DARWIN__)
+       addi    t7,t7,1                   /* stack slot counter                   */
+#endif
+       bctr
+
+L_register_handle_long:
+#if defined(__DARWIN__)
+       addis   itmp3,t3,ha16(L_jumptable_long - L_asm_vm_call_method_get_pc)
+       la      itmp3,lo16(L_jumptable_long - L_asm_vm_call_method_get_pc)(itmp3)
+#else
+       lis     itmp3,L_jumptable_long@ha
+       addi    itmp3,itmp3,L_jumptable_long@l
+#endif
+#if !defined(__DARWIN__)
+       addi    t6,t6,1                   /* align to even numbers                */
+       andi.   t6,t6,0xfffe
+#endif
+
+       cmpwi   t6,(INT_ARG_CNT - 1)      /* are we out of integer argument       */
+       blt     L_register_handle_long_continue /* registers?                     */
+
+       li      t6,INT_ARG_CNT            /* yes, set integer argument register   */
+       b       L_register_copy           /* count to max and next loop           */
+
+L_register_handle_long_continue:
+       slwi    t2,t6,2                   /* multiple of 4-bytes                  */
+       add     itmp3,itmp3,t2            /* calculate address of jumptable       */
+       lwz     itmp3,0(itmp3)            /* load function address                */
+       mtctr   itmp3
+       addi    t0,t0,1                   /* integer argument counter             */
+       addi    t6,t6,2                   /* integer argument register counter    */
+#if defined(__DARWIN__)
+       addi    t7,t7,2                   /* stack slot counter                   */
+#endif
+       bctr
+
+L_register_handle_float:
+       cmpwi   t1,FLT_ARG_CNT            /* are we out of float argument         */
+       beq     L_register_copy           /* registers? yes, next loop            */
+
+       andi.   r0,itmp3,0x0001           /* is this a 2-word type?               */
+       bne     L_register_handle_double
+
+#if defined(__DARWIN__)
+       addis   itmp3,t3,ha16(L_jumptable_float - L_asm_vm_call_method_get_pc)
+       la      itmp3,lo16(L_jumptable_float - L_asm_vm_call_method_get_pc)(itmp3)
+#else
+       lis     itmp3,L_jumptable_float@ha
+       addi    itmp3,itmp3,L_jumptable_float@l
+#endif
+
+       slwi    t2,t1,2                   /* multiple of 4-bytes                  */
+       add     itmp3,itmp3,t2            /* calculate address of jumptable       */
+       lwz     itmp3,0(itmp3)            /* load function address                */
+       mtctr   itmp3
+       addi    t1,t1,1                   /* float argument counter               */
+#if defined(__DARWIN__)
+       addi    t7,t7,1                   /* stack slot counter                   */
+       addi    t6,t6,1                   /* skip 1 integer argument register     */
+#endif
+       bctr
+
+L_register_handle_double:
+#if defined(__DARWIN__)
+       addis   itmp3,t3,ha16(L_jumptable_double - L_asm_vm_call_method_get_pc)
+       la      itmp3,lo16(L_jumptable_double - L_asm_vm_call_method_get_pc)(itmp3)
+#else
+       lis     itmp3,L_jumptable_double@ha
+       addi    itmp3,itmp3,L_jumptable_double@l
+#endif
+
+       slwi    t2,t1,2                   /* multiple of 4-bytes                  */
+       add     itmp3,itmp3,t2            /* calculate address of jumptable       */
+       lwz     itmp3,0(itmp3)            /* load function address                */
+       mtctr   itmp3
+       addi    t1,t1,1                   /* float argument counter               */
+#if defined(__DARWIN__)
+       addi    t7,t7,2                   /* stack slot counter                   */
+       addi    t6,t6,2                   /* skip 2 integer argument registers    */
+#endif
+       bctr
+
+L_register_copy_done:
+                                         /* calculate remaining arguments        */
+       sub     itmp3,t4,t0               /* - integer arguments in registers     */
+       sub     itmp3,itmp3,t1            /* - float arguments in registers       */
+       mr.     itmp3,itmp3
+       beq     L_stack_copy_done
+
+       mr      itmp2,t4                  /* restore argument count               */
+       mr      itmp1,t5                  /* restore argument block pointer       */
+
+       slwi    t4,itmp3,3                /* XXX use 8-bytes slots for now        */
+       addi    t4,t4,LA_SIZE             /* add size of linkage area             */
+
+#if defined(__DARWIN__)
+       slwi    t5,t7,2                   /* add stack space for arguments        */
+       add     t4,t4,t5
+#endif
+
+       sub     sp,sp,t4
+
+       mr      t6,sp                     /* use t6 as temporary sp               */
+       addi    t6,t6,LA_SIZE             /* skip linkage area                    */
+#if defined(__DARWIN__)
+       add     t6,t6,t5                  /* skip stack space for arguments       */
+#endif
+
+       addi    itmp1,itmp1,-sizevmarg    /* initialize pointer (smaller code)    */
+       addi    itmp2,itmp2,1             /* initialize argument count            */
+       
+L_stack_copy_loop:
+       addi    itmp1,itmp1,sizevmarg     /* goto next argument block             */
+       addi    itmp2,itmp2,-1            /* argument count - 1                   */
+       mr.     itmp2,itmp2
+       beq     L_stack_copy_done
+       
+       lwz     itmp3,offvmargtype+4(itmp1)
+       andi.   r0,itmp3,0x0002           /* is this a float/double type?         */
+       bne     L_stack_handle_float
+
+L_stack_handle_int:
+       addi    t0,t0,-1                  /* arguments assigned to registers      */
+       mr.     t0,t0
+       bge     L_stack_copy_loop
+
+       andi.   r0,itmp3,0x0001           /* is this a 2-word type?               */
+       bne     L_stack_handle_long
+
+       lwz     itmp3,offvmargdata+4(itmp1) /* get integer argument               */
+       stw     itmp3,0(t6)               /* and store it on the stack            */
+       addi    t6,t6,4                   /* increase temporary sp by 1 slot      */
+       b       L_stack_copy_loop
+
+L_stack_handle_long:
+#if !defined(__DARWIN__)
+       addi    t6,t6,4                   /* align stack to 8-bytes               */
+       rlwinm  t6,t6,0,30,28             /* clear lower 4-bits                   */
+#endif
+
+       lwz     itmp3,offvmargdata+0(itmp1) /* get long argument                  */
+       stw     itmp3,0(t6)               /* and store it on the stack            */
+       lwz     itmp3,offvmargdata+4(itmp1)
+       stw     itmp3,4(t6)
+       addi    t6,t6,8                   /* increase temporary sp by 2 slots     */
+       b       L_stack_copy_loop
+               
+L_stack_handle_float:
+       addi    t1,t1,-1                  /* arguments assigned to registers      */
+       mr.     t1,t1
+       bge     L_stack_copy_loop
+
+       andi.   r0,itmp3,0x0001           /* is this a 2-word type?               */
+       bne     L_stack_handle_double
+
+       lfs     ftmp3,offvmargdata(itmp1) /* get float argument                   */
+       stfs    ftmp3,0(t6)               /* and store it on the stack            */
+       addi    t6,t6,4                   /* increase temporary sp by 1 slot      */
+       b       L_stack_copy_loop
+
+L_stack_handle_double:
+#if !defined(__DARWIN__)
+       addi    t6,t6,4                   /* align stack to 8-bytes               */
+       rlwinm  t6,t6,0,30,28             /* clear lower 4-bits                   */
+#endif
+
+       lfd     ftmp3,offvmargdata(itmp1) /* get double argument                  */
+       stfd    ftmp3,0(t6)               /* and store it on the stack            */
+       addi    t6,t6,8                   /* increase temporary sp by 2 slots     */
+       b       L_stack_copy_loop
+
+L_stack_copy_done:
+       lwz     itmp1,9*4(s0)             /* pass method pointer via tmp1         */
+
+#if defined(__DARWIN__)
+       addis   mptr,t3,ha16(L_asm_call_jit_compiler - L_asm_vm_call_method_get_pc)
+       la      mptr,lo16(L_asm_call_jit_compiler - L_asm_vm_call_method_get_pc)(mptr)
+#else
+       lis     mptr,L_asm_call_jit_compiler@ha
+       addi    mptr,mptr,L_asm_call_jit_compiler@l
+#endif
+       stw     mptr,7*4(s0)
+       addi    mptr,s0,7*4
+
+       lwz     pv,0*4(mptr)
+       mtctr   pv
+       bctrl
+1:
+       mflr    itmp1
+#if defined(__DARWIN__)
+       addi    pv,itmp1,lo16(asm_vm_call_method - 1b)
+#else
+       addi    pv,itmp1,(asm_vm_call_method - 1b)@l
+#endif
+
+L_asm_vm_call_method_return:
+       mr      sp,s0                     /* restore the function's sp            */
+
+       lwz     s0,8*4(sp)                /* restore used callee saved registers  */
+
+#if defined(__DARWIN__)
+       lwz     itmp1,10*4(sp)            /* register r11 is callee saved         */
+#endif
+       lwz     pv,11*4(sp)               /* save PV register                     */
+
+       lwz     itmp3,12*4(sp)
+       lfd     ftmp1,14*4(sp)            /* registers f14-f31 are callee saved   */
+       lfd     ftmp2,16*4(sp)
+
+#if defined(__DARWIN__)
+       lwz     t1,18*4(r1)
+       lwz     t2,19*4(r1)
+       lwz     t3,20*4(r1)
+       lwz     t4,21*4(r1)
+       lwz     t5,22*4(r1)
+       lwz     t6,23*4(r1)
+       lwz     t7,24*4(r1)
+
+       lfd     ft0,26*4(r1)
+       lfd     ft1,28*4(r1)
+       lfd     ft2,30*4(r1)
+       lfd     ft3,32*4(r1)
+       lfd     ft4,34*4(r1)
+       lfd     ft5,36*4(r1)
+#else
+       RESTORE_TEMPORARY_REGISTERS(18)   /* the offset has to be even            */
+#endif
+
+       lwz     r0,40*4+LA_LR_OFFSET(r1)
+       mtlr    r0
+       addi    r1,r1,40*4
+       blr
+
+asm_vm_call_method_exception_handler:
+       mr      r3,itmp1
+       bl      builtin_throw_exception
+       b       L_asm_vm_call_method_return
+
+
+       .data
+       .align  2
+
+L_jumptable_int:
+       .long   L_handle_a0
+       .long   L_handle_a1
+       .long   L_handle_a2
+       .long   L_handle_a3
+       .long   L_handle_a4
+       .long   L_handle_a5
+       .long   L_handle_a6
+       .long   L_handle_a7
+
+       .text
+       .align  2
+
+L_handle_a0:
+       lwz     a0,offvmargdata+4(itmp1)
+       b       L_register_copy
+L_handle_a1:
+       lwz     a1,offvmargdata+4(itmp1)
+       b       L_register_copy
+L_handle_a2:
+       lwz     a2,offvmargdata+4(itmp1)
+       b       L_register_copy
+L_handle_a3:
+       lwz     a3,offvmargdata+4(itmp1)
+       b       L_register_copy
+L_handle_a4:
+       lwz     a4,offvmargdata+4(itmp1)
+       b       L_register_copy
+L_handle_a5:
+       lwz     a5,offvmargdata+4(itmp1)
+       b       L_register_copy
+L_handle_a6:
+       lwz     a6,offvmargdata+4(itmp1)
+       b       L_register_copy
+L_handle_a7:
+       lwz     a7,offvmargdata+4(itmp1)
+       b       L_register_copy
+
+
+       .data
+       .align  2
+
+L_jumptable_long:
+#if defined(__DARWIN__)
+       .long   L_handle_a0_a1
+       .long   L_handle_a1_a2
+       .long   L_handle_a2_a3
+       .long   L_handle_a3_a4
+       .long   L_handle_a4_a5
+       .long   L_handle_a5_a6
+       .long   L_handle_a6_a7
+#else
+       /* we have two entries here, so we get the even argument register
+       alignment for linux */
+
+       .long   L_handle_a0_a1
+       .long   0
+       .long   L_handle_a2_a3
+       .long   0
+       .long   L_handle_a4_a5
+       .long   0
+       .long   L_handle_a6_a7
+#endif
+
+       .text
+       .align  2
+
+L_handle_a0_a1:
+       lwz     a0,offvmargdata+0(itmp1)
+       lwz     a1,offvmargdata+4(itmp1)
+       b       L_register_copy
+#if defined(__DARWIN__)
+L_handle_a1_a2:
+       lwz     a1,offvmargdata+0(itmp1)
+       lwz     a2,offvmargdata+4(itmp1)
+       b       L_register_copy
+#endif
+L_handle_a2_a3:
+       lwz     a2,offvmargdata+0(itmp1)
+       lwz     a3,offvmargdata+4(itmp1)
+       b       L_register_copy
+#if defined(__DARWIN__)
+L_handle_a3_a4:
+       lwz     a3,offvmargdata+0(itmp1)
+       lwz     a4,offvmargdata+4(itmp1)
+       b       L_register_copy
+#endif
+L_handle_a4_a5:
+       lwz     a4,offvmargdata+0(itmp1)
+       lwz     a5,offvmargdata+4(itmp1)
+       b       L_register_copy
+#if defined(__DARWIN__)
+L_handle_a5_a6:
+       lwz     a5,offvmargdata+0(itmp1)
+       lwz     a6,offvmargdata+4(itmp1)
+       b       L_register_copy
+#endif
+L_handle_a6_a7:
+       lwz     a6,offvmargdata+0(itmp1)
+       lwz     a7,offvmargdata+4(itmp1)
+       b       L_register_copy
+
+
+       .data
+       .align  2
+
+L_jumptable_float:
+       .long   L_handle_fa0
+       .long   L_handle_fa1
+       .long   L_handle_fa2
+       .long   L_handle_fa3
+       .long   L_handle_fa4
+       .long   L_handle_fa5
+       .long   L_handle_fa6
+       .long   L_handle_fa7
+
+#if defined(__DARWIN__)
+       .long   L_handle_fa8
+       .long   L_handle_fa9
+       .long   L_handle_fa10
+       .long   L_handle_fa11
+       .long   L_handle_fa12
+#endif
+
+       .text
+       .align  2
+
+L_handle_fa0:
+       lfs     fa0,offvmargdata(itmp1)
+       b       L_register_copy
+L_handle_fa1:
+       lfs     fa1,offvmargdata(itmp1)
+       b       L_register_copy
+L_handle_fa2:
+       lfs     fa2,offvmargdata(itmp1)
+       b       L_register_copy
+L_handle_fa3:
+       lfs     fa3,offvmargdata(itmp1)
+       b       L_register_copy
+L_handle_fa4:
+       lfs     fa4,offvmargdata(itmp1)
+       b       L_register_copy
+L_handle_fa5:
+       lfs     fa5,offvmargdata(itmp1)
+       b       L_register_copy
+L_handle_fa6:
+       lfs     fa6,offvmargdata(itmp1)
+       b       L_register_copy
+L_handle_fa7:
+       lfs     fa7,offvmargdata(itmp1)
+       b       L_register_copy
+
+#if defined(__DARWIN__)
+L_handle_fa8:
+       lfs     fa8,offvmargdata(itmp1)
+       b       L_register_copy
+L_handle_fa9:
+       lfs     fa9,offvmargdata(itmp1)
+       b       L_register_copy
+L_handle_fa10:
+       lfs     fa10,offvmargdata(itmp1)
+       b       L_register_copy
+L_handle_fa11:
+       lfs     fa11,offvmargdata(itmp1)
+       b       L_register_copy
+L_handle_fa12:
+       lfs     fa12,offvmargdata(itmp1)
+       b       L_register_copy
+#endif
+
+
+       .data
+       .align  2
+
+L_jumptable_double:
+       .long   L_handle_fda0
+       .long   L_handle_fda1
+       .long   L_handle_fda2
+       .long   L_handle_fda3
+       .long   L_handle_fda4
+       .long   L_handle_fda5
+       .long   L_handle_fda6
+       .long   L_handle_fda7
+
+#if defined(__DARWIN__)
+       .long   L_handle_fda8
+       .long   L_handle_fda9
+       .long   L_handle_fda10
+       .long   L_handle_fda11
+       .long   L_handle_fda12
+#endif
+
+       .text
+       .align  2
+
+L_handle_fda0:
+       lfd     fa0,offvmargdata(itmp1)
+       b       L_register_copy
+L_handle_fda1:
+       lfd     fa1,offvmargdata(itmp1)
+       b       L_register_copy
+L_handle_fda2:
+       lfd     fa2,offvmargdata(itmp1)
+       b       L_register_copy
+L_handle_fda3:
+       lfd     fa3,offvmargdata(itmp1)
+       b       L_register_copy
+L_handle_fda4:
+       lfd     fa4,offvmargdata(itmp1)
+       b       L_register_copy
+L_handle_fda5:
+       lfd     fa5,offvmargdata(itmp1)
+       b       L_register_copy
+L_handle_fda6:
+       lfd     fa6,offvmargdata(itmp1)
+       b       L_register_copy
+L_handle_fda7:
+       lfd     fa7,offvmargdata(itmp1)
+       b       L_register_copy
+
+#if defined(__DARWIN__)
+L_handle_fda8:
+       lfd     fa8,offvmargdata(itmp1)
+       b       L_register_copy
+L_handle_fda9:
+       lfd     fa9,offvmargdata(itmp1)
+       b       L_register_copy
+L_handle_fda10:
+       lfd     fa10,offvmargdata(itmp1)
+       b       L_register_copy
+L_handle_fda11:
+       lfd     fa11,offvmargdata(itmp1)
+       b       L_register_copy
+L_handle_fda12:
+       lfd     fa12,offvmargdata(itmp1)
+       b       L_register_copy
+#endif
+
+
+/* asm_call_jit_compiler *******************************************************
+
+   Invokes the compiler for untranslated JavaVM methods.
+
+*******************************************************************************/
+
+asm_call_jit_compiler:
+L_asm_call_jit_compiler:                /* required for PIC code              */
+       mflr    r0
+       stw     r0,LA_LR_OFFSET(r1)         /* save return address                */
+       stwu    r1,-(LA_SIZE + 5*4 + INT_ARG_CNT*4 + FLT_ARG_CNT*8)(r1)
+
+#if defined(__DARWIN__)
+       stw     a0,(LA_WORD_SIZE+5+0)*4(r1)
+       stw     a1,(LA_WORD_SIZE+5+1)*4(r1)
+       stw     a2,(LA_WORD_SIZE+5+2)*4(r1)
+       stw     a3,(LA_WORD_SIZE+5+3)*4(r1)
+       stw     a4,(LA_WORD_SIZE+5+4)*4(r1)
+       stw     a5,(LA_WORD_SIZE+5+5)*4(r1)
+       stw     a6,(LA_WORD_SIZE+5+6)*4(r1)
+       stw     a7,(LA_WORD_SIZE+5+7)*4(r1)
+
+       stfd    fa0,(LA_WORD_SIZE+5+8)*4(r1)
+       stfd    fa1,(LA_WORD_SIZE+5+10)*4(r1)
+       stfd    fa2,(LA_WORD_SIZE+5+12)*4(r1)
+       stfd    fa3,(LA_WORD_SIZE+5+14)*4(r1)
+       stfd    fa4,(LA_WORD_SIZE+5+16)*4(r1)
+       stfd    fa5,(LA_WORD_SIZE+5+18)*4(r1)
+       stfd    fa6,(LA_WORD_SIZE+5+20)*4(r1)
+       stfd    fa7,(LA_WORD_SIZE+5+22)*4(r1)
+       stfd    fa8,(LA_WORD_SIZE+5+24)*4(r1)
+       stfd    fa9,(LA_WORD_SIZE+5+26)*4(r1)
+       stfd    fa10,(LA_WORD_SIZE+5+28)*4(r1)
+       stfd    fa11,(LA_WORD_SIZE+5+30)*4(r1)
+       stfd    fa12,(LA_WORD_SIZE+5+32)*4(r1)
+#else
+       SAVE_ARGUMENT_REGISTERS(LA_WORD_SIZE+1)
+#endif
+
+       mr      a0,itmp1
+       mr      a1,mptr
+       addi    a2,sp,(LA_SIZE + 5*4 + INT_ARG_CNT*4 + FLT_ARG_CNT*8)
+       lwz     a3,(LA_SIZE + 5*4 + INT_ARG_CNT*4 + FLT_ARG_CNT*8)+LA_LR_OFFSET(sp)
+       bl      jit_asm_compile
+       mr      pv,v0                       /* move address to pv register        */
+
+#if defined(__DARWIN__)
+       lwz     a0,(LA_WORD_SIZE+5+0)*4(r1)
+       lwz     a1,(LA_WORD_SIZE+5+1)*4(r1)
+       lwz     a2,(LA_WORD_SIZE+5+2)*4(r1)
+       lwz     a3,(LA_WORD_SIZE+5+3)*4(r1)
+       lwz     a4,(LA_WORD_SIZE+5+4)*4(r1)
+       lwz     a5,(LA_WORD_SIZE+5+5)*4(r1)
+       lwz     a6,(LA_WORD_SIZE+5+6)*4(r1)
+       lwz     a7,(LA_WORD_SIZE+5+7)*4(r1)
+
+       lfd     fa0,(LA_WORD_SIZE+5+8)*4(r1)
+       lfd     fa1,(LA_WORD_SIZE+5+10)*4(r1)
+       lfd     fa2,(LA_WORD_SIZE+5+12)*4(r1)
+       lfd     fa3,(LA_WORD_SIZE+5+14)*4(r1)
+       lfd     fa4,(LA_WORD_SIZE+5+16)*4(r1)
+       lfd     fa5,(LA_WORD_SIZE+5+18)*4(r1)
+       lfd     fa6,(LA_WORD_SIZE+5+20)*4(r1)
+       lfd     fa7,(LA_WORD_SIZE+5+22)*4(r1)
+       lfd     fa8,(LA_WORD_SIZE+5+24)*4(r1)
+       lfd     fa9,(LA_WORD_SIZE+5+26)*4(r1)
+       lfd     fa10,(LA_WORD_SIZE+5+28)*4(r1)
+       lfd     fa11,(LA_WORD_SIZE+5+30)*4(r1)
+       lfd     fa12,(LA_WORD_SIZE+5+32)*4(r1)
+#else
+       RESTORE_ARGUMENT_REGISTERS(LA_WORD_SIZE+1)
+#endif
+
+       lwz     itmp1,(LA_SIZE + 5*4 + INT_ARG_CNT*4 + FLT_ARG_CNT*8)+LA_LR_OFFSET(r1)
+       mtlr    itmp1
+
+       addi    sp,sp,(LA_SIZE + 5*4 + INT_ARG_CNT*4 + FLT_ARG_CNT*8)
+
+       mr.     pv,pv                       /* test for exception                 */
+       beq     L_asm_call_jit_compiler_exception
+
+       mtctr   pv                          /* move method address to control reg */
+       bctr                                /* and call the Java method           */
+
+L_asm_call_jit_compiler_exception:
+       mflr    r0
+       stw     r0,LA_LR_OFFSET(sp)
+       stwu    sp,-LA_SIZE_ALIGNED(sp)     /* preserve linkage area              */
+       bl      exceptions_get_and_clear_exception
+       lwz     xpc,LA_SIZE_ALIGNED+LA_LR_OFFSET(sp)
+       mtlr    xpc     
+       addi    sp,sp,LA_SIZE_ALIGNED
+
+       mr      xptr,v0                     /* get exception                      */
+       addi    xpc,xpc,-4                  /* exception address is ra - 4        */
+       b       L_asm_handle_nat_exception
+
+
+/********************* function 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.                                *
+*                                                                              *
+*   void asm_handle_exception (exceptionptr, exceptionpc);                     *
+*                                                                              *
+*******************************************************************************/
+               
+asm_handle_nat_exception:
+L_asm_handle_nat_exception:             /* required for PIC code              */
+       mflr    r9
+       lwz     itmp3,4(r9)
+       extsh   itmp3,itmp3
+       add     pv,itmp3,r9
+       lwz     itmp3,8(r9)
+       srwi    itmp3,itmp3,16
+       cmpwi   itmp3,0x3dad
+       bne     L_asm_handle_exception
+       lwz     itmp3,8(r9)
+       slwi    itmp3,itmp3,16
+       add     pv,pv,itmp3
+
+asm_handle_exception:
+L_asm_handle_exception:                 /* required for PIC code              */
+       addi    sp,sp,-(ARG_CNT+TMP_CNT)*8  /* create maybe-leaf stackframe       */
+
+#if defined(__DARWIN__)
+#else
+       SAVE_ARGUMENT_REGISTERS(0)          /* we save arg and temp registers in  */
+       SAVE_TEMPORARY_REGISTERS(ARG_CNT)   /* case this is a leaf method         */
+#endif
+
+       li      a3,(ARG_CNT+TMP_CNT)*8      /* prepare a3 for handle_exception    */
+       li      a4,1                        /* set maybe-leaf flag                */
+
+L_asm_handle_exception_stack_loop:
+       addi    sp,sp,-(LA_WORD_SIZE+4+5)*4 /* allocate stack                     */
+       stw     xptr,LA_SIZE+4*4(sp)        /* save exception pointer             */
+       stw     xpc,LA_SIZE+5*4(sp)         /* save exception pc                  */
+       stw     pv,LA_SIZE+6*4(sp)          /* save data segment pointer          */
+       mflr    r0                          /* save return address                */
+       stw     r0,LA_SIZE+5*4(sp)
+       add     a3,a3,sp                    /* calculate Java sp into a3...       */
+       addi    a3,a3,(LA_WORD_SIZE+4+5)*4
+       stw     a4,LA_SIZE+8*4(sp)          /* save maybe-leaf flag               */
+
+       mr      a0,xptr                     /* pass exception pointer             */
+       mr      a1,xpc                      /* pass exception pc                  */
+       mr      a2,pv                       /* pass data segment pointer          */
+                                           /* a3 is still set                    */
+       bl      exceptions_handle_exception
+
+       mr.     v0,v0
+       beq     L_asm_handle_exception_not_catched
+
+       mr      xpc,v0                      /* move handlerpc into xpc            */
+       lwz     xptr,LA_SIZE+4*4(sp)        /* restore exception pointer          */
+       lwz     pv,LA_SIZE+6*4(sp)          /* restore data segment pointer       */
+       lwz     r0,LA_SIZE+5*4(sp)          /* restore return address             */
+       mtlr    r0
+       lwz     a4,LA_SIZE+8*4(sp)          /* get maybe-leaf flag                */
+       addi    sp,sp,(LA_WORD_SIZE+4+5)*4  /* free stack frame                   */
+
+       mr.     a4,a4
+       beq     L_asm_handle_exception_no_leaf
+
+#if defined(__DARWIN__)
+#else
+       RESTORE_ARGUMENT_REGISTERS(0)       /* if this is a leaf method, we have  */
+       RESTORE_TEMPORARY_REGISTERS(ARG_CNT)/* to restore arg and temp registers  */
+#endif
+
+       addi    sp,sp,(ARG_CNT+TMP_CNT)*8   /* remove maybe-leaf stackframe       */
+
+L_asm_handle_exception_no_leaf:
+       mtctr   xpc                         /* jump to the handler                */
+       bctr
+
+L_asm_handle_exception_not_catched:
+       lwz     xptr,LA_SIZE+4*4(sp)        /* restore exception pointer          */
+       lwz     pv,LA_SIZE+6*4(sp)          /* restore data segment pointer       */
+       lwz     r0,LA_SIZE+5*4(sp)          /* restore return address             */
+       mtlr    r0
+       lwz     a4,LA_SIZE+8*4(sp)          /* get maybe-leaf flag                */
+       addi    sp,sp,(LA_WORD_SIZE+4+5)*4  /* free stack frame                   */
+
+       mr.     a4,a4
+       beq     L_asm_handle_exception_no_leaf_stack
+
+       addi    sp,sp,(ARG_CNT+TMP_CNT)*8   /* remove maybe-leaf stackframe       */
+       li      a4,0                        /* clear the maybe-leaf flag          */
+
+L_asm_handle_exception_no_leaf_stack:
+       lwz     t0,FrameSize(pv)            /* get frame size                     */
+       add     t0,sp,t0                    /* pointer to save area               */
+
+       lwz     t1,IsLeaf(pv)               /* is leaf procedure                  */
+       mr.     t1,t1
+       bne     L_asm_handle_exception_no_ra_restore
+
+       lwz     r0,LA_LR_OFFSET(t0)         /* restore ra                         */
+       mtlr    r0
+
+L_asm_handle_exception_no_ra_restore:
+       mflr    xpc                         /* the new xpc is ra                  */
+       lwz     t1,IntSave(pv)              /* t1 = saved int register count      */
+       bl      ex_int1
+ex_int1:
+       mflr    t2                          /* t2 = current pc                    */
+#if defined(__DARWIN__)
+       addi    t2,t2,lo16(ex_int2-ex_int1)
+#else
+       addi    t2,t2,(ex_int2-ex_int1)@l
+#endif
+       slwi    t1,t1,2                     /* t1 = register count * 4            */
+       subf    t2,t1,t2                    /* t2 = IntSave - t1                  */
+       mtctr   t2
+       bctr
+
+       lwz     s0,-10*4(t0)
+       lwz     s1,-9*4(t0)
+       lwz     s2,-8*4(t0)
+       lwz     s3,-7*4(t0)
+       lwz     s4,-6*4(t0)
+       lwz     s5,-5*4(t0)
+       lwz     s6,-4*4(t0)
+       lwz     s7,-3*4(t0)
+       lwz     s8,-2*4(t0)
+       lwz     s9,-1*4(t0)
+
+ex_int2:
+       subf    t0,t1,t0                    /* t0 = t0 - register count * 4       */
+
+       lwz     t1,FltSave(pv)
+       bl      ex_flt1
+ex_flt1:
+       mflr    t2
+#if defined(__DARWIN__)
+       addi    t2,t2,lo16(ex_flt2-ex_flt1)
+#else
+       addi    t2,t2,(ex_flt2-ex_flt1)@l
+#endif
+       slwi    t1,t1,2                     /* t1 = register count * 4            */
+       subf    t2,t1,t2                    /* t2 = FltSave - t1                  */
+       mtctr   t2
+       bctr
+
+       lfd     fs0,-10*8(t0)
+       lfd     fs1,-9*8(t0)
+       lfd     fs2,-8*8(t0)
+       lfd     fs3,-7*8(t0)
+       lfd     fs4,-6*8(t0)
+       lfd     fs5,-5*8(t0)
+       lfd     fs6,-4*8(t0)
+       lfd     fs7,-3*8(t0)
+       lfd     fs8,-2*8(t0)
+       lfd     fs9,-1*8(t0)
+
+ex_flt2:
+       lwz     t0,FrameSize(pv)            /* get frame size                     */
+       add     sp,sp,t0                    /* unwind stack                       */
+       li      a3,0                        /* prepare a3 for handle_exception    */
+
+       mtlr    xpc
+       lwz     itmp3,4(xpc)
+       extsh   itmp3,itmp3
+       add     pv,itmp3,xpc
+       lwz     itmp3,8(xpc)
+       srwi    itmp3,itmp3,16
+       cmpwi   itmp3,0x3dad
+       bne     L_asm_handle_exception_stack_loop
+       lwz     itmp3,8(xpc)
+       slwi    itmp3,itmp3,16
+       add     pv,pv,itmp3
+
+       b       L_asm_handle_exception_stack_loop
+
+
+/* asm_abstractmethoderror *****************************************************
+
+   Creates and throws an AbstractMethodError.
+
+*******************************************************************************/
+
+asm_abstractmethoderror:
+       mflr    r0
+       stw     r0,LA_LR_OFFSET(sp)
+       stwu    sp,-LA_SIZE_ALIGNED(sp)     /* preserve linkage area              */
+       addi    a0,sp,LA_SIZE_ALIGNED       /* pass java sp                       */
+       mr      a1,r0                       /* pass exception address             */
+       bl      exceptions_asm_new_abstractmethoderror
+       lwz     r0,LA_SIZE_ALIGNED+LA_LR_OFFSET(sp)
+       mtlr    r0                          /* restore return address             */
+       addi    sp,sp,LA_SIZE_ALIGNED
+
+       mr      xptr,v0                     /* get exception pointer              */
+       mr      xpc,r0                      /* we can't use r0 directly in addi   */
+       addi    xpc,xpc,-4                  /* exception address is ra - 4        */
+       b       L_asm_handle_nat_exception
+
+
+/* asm_wrapper_patcher *********************************************************
+
+   XXX
+
+   Stack layout:
+     20   return address into JIT code (patch position)
+     16   pointer to virtual java_objectheader
+     12   machine code (which is patched back later)
+      8   unresolved class/method/field reference
+      4   data segment displacement from load instructions
+      0   patcher function pointer to call (pv is saved here afterwards)
+
+*******************************************************************************/
+
+asm_wrapper_patcher:
+       mflr    r0                    /* get Java return address (leaf)           */
+       stw     r0,6*4(sp)            /* store it in the stub stackframe          */
+                                     /* keep stack 16-bytes aligned: 6+1+37 = 44 */
+       stwu    sp,-(LA_SIZE+(5+58)*4)(sp)
+
+#if defined(__DARWIN__)
+       stw     a0,LA_SIZE+(5+0)*4(r1)      /* save argument registers            */
+       stw     a1,LA_SIZE+(5+1)*4(r1)      /* preserve linkage area (24 bytes)   */
+       stw     a2,LA_SIZE+(5+2)*4(r1)      /* and 4 bytes for 4 argument         */
+       stw     a3,LA_SIZE+(5+3)*4(r1)
+       stw     a4,LA_SIZE+(5+4)*4(r1)
+       stw     a5,LA_SIZE+(5+5)*4(r1)
+       stw     a6,LA_SIZE+(5+6)*4(r1)
+       stw     a7,LA_SIZE+(5+7)*4(r1)
+
+       stfd    fa0,LA_SIZE+(5+8)*4(sp)
+       stfd    fa1,LA_SIZE+(5+10)*4(sp)
+       stfd    fa2,LA_SIZE+(5+12)*4(sp)
+       stfd    fa3,LA_SIZE+(5+14)*4(sp)
+       stfd    fa4,LA_SIZE+(5+16)*4(sp)
+       stfd    fa5,LA_SIZE+(5+18)*4(sp)
+       stfd    fa6,LA_SIZE+(5+20)*4(sp)
+       stfd    fa7,LA_SIZE+(5+22)*4(sp)
+       stfd    fa8,LA_SIZE+(5+24)*4(sp)
+       stfd    fa9,LA_SIZE+(5+26)*4(sp)
+       stfd    fa10,LA_SIZE+(5+28)*4(sp)
+       stfd    fa11,LA_SIZE+(5+30)*4(sp)
+       stfd    fa12,LA_SIZE+(5+32)*4(sp)
+
+       stw     t0,(LA_WORD_SIZE+5+33)*4(r1)
+       stw     t1,(LA_WORD_SIZE+5+34)*4(r1)
+       stw     t2,(LA_WORD_SIZE+5+35)*4(r1)
+       stw     t3,(LA_WORD_SIZE+5+36)*4(r1)
+       stw     t4,(LA_WORD_SIZE+5+37)*4(r1)
+       stw     t5,(LA_WORD_SIZE+5+38)*4(r1)
+       stw     t6,(LA_WORD_SIZE+5+39)*4(r1)
+       stw     t7,(LA_WORD_SIZE+5+40)*4(r1)
+
+       stfd    ft0,(LA_WORD_SIZE+5+42)*4(r1)
+       stfd    ft1,(LA_WORD_SIZE+5+44)*4(r1)
+       stfd    ft2,(LA_WORD_SIZE+5+46)*4(r1)
+       stfd    ft3,(LA_WORD_SIZE+5+48)*4(r1)
+       stfd    ft4,(LA_WORD_SIZE+5+50)*4(r1)
+       stfd    ft5,(LA_WORD_SIZE+5+52)*4(r1)
+#else
+       SAVE_ARGUMENT_REGISTERS(LA_WORD_SIZE+1) /* save 8 int/8 float arguments   */
+       SAVE_TEMPORARY_REGISTERS(LA_WORD_SIZE+1+24)
+#endif
+
+       stw     itmp1,LA_SIZE+(5+54)*4(sp)
+       stw     itmp2,LA_SIZE+(5+55)*4(sp)
+       stw     pv,LA_SIZE+(5+56)*4(sp)
+
+       addi    a0,sp,LA_SIZE+(5+58)*4      /* pass SP of patcher stub            */
+       mr      a1,pv                       /* pass PV                            */
+       mr      a2,r0                       /* pass RA (correct for leafs)        */
+       bl      patcher_wrapper
+       stw     v0,LA_SIZE+(5+57)*4(sp)     /* save return value                  */
+
+#if defined(__DARWIN__)
+       lwz     a0,LA_SIZE+(5+0)*4(r1)
+       lwz     a1,LA_SIZE+(5+1)*4(r1)
+       lwz     a2,LA_SIZE+(5+2)*4(r1)
+       lwz     a3,LA_SIZE+(5+3)*4(r1)
+       lwz     a4,LA_SIZE+(5+4)*4(r1)
+       lwz     a5,LA_SIZE+(5+5)*4(r1)
+       lwz     a6,LA_SIZE+(5+6)*4(r1)
+       lwz     a7,LA_SIZE+(5+7)*4(r1)
+
+       lfd     fa0,LA_SIZE+(5+8)*4(sp)
+       lfd     fa1,LA_SIZE+(5+10)*4(sp)
+       lfd     fa2,LA_SIZE+(5+12)*4(sp)
+       lfd     fa3,LA_SIZE+(5+14)*4(sp)
+       lfd     fa4,LA_SIZE+(5+16)*4(sp)
+       lfd     fa5,LA_SIZE+(5+18)*4(sp)
+       lfd     fa6,LA_SIZE+(5+20)*4(sp)
+       lfd     fa7,LA_SIZE+(5+22)*4(sp)
+       lfd     fa8,LA_SIZE+(5+24)*4(sp)
+       lfd     fa9,LA_SIZE+(5+26)*4(sp)
+       lfd     fa10,LA_SIZE+(5+28)*4(sp)
+       lfd     fa11,LA_SIZE+(5+30)*4(sp)
+       lfd     fa12,LA_SIZE+(5+32)*4(sp)
+
+       lwz     t0,(LA_WORD_SIZE+5+33)*4(r1)
+       lwz     t1,(LA_WORD_SIZE+5+34)*4(r1)
+       lwz     t2,(LA_WORD_SIZE+5+35)*4(r1)
+       lwz     t3,(LA_WORD_SIZE+5+36)*4(r1)
+       lwz     t4,(LA_WORD_SIZE+5+37)*4(r1)
+       lwz     t5,(LA_WORD_SIZE+5+38)*4(r1)
+       lwz     t6,(LA_WORD_SIZE+5+39)*4(r1)
+       lwz     t7,(LA_WORD_SIZE+5+40)*4(r1)
+
+       lfd     ft0,(LA_WORD_SIZE+5+42)*4(r1)
+       lfd     ft1,(LA_WORD_SIZE+5+44)*4(r1)
+       lfd     ft2,(LA_WORD_SIZE+5+46)*4(r1)
+       lfd     ft3,(LA_WORD_SIZE+5+48)*4(r1)
+       lfd     ft4,(LA_WORD_SIZE+5+50)*4(r1)
+       lfd     ft5,(LA_WORD_SIZE+5+52)*4(r1)
+#else
+       RESTORE_ARGUMENT_REGISTERS(LA_WORD_SIZE+1) /* restore 8 int/8 float args  */
+       RESTORE_TEMPORARY_REGISTERS(LA_WORD_SIZE+1+24)
+#endif
+
+       lwz     itmp1,LA_SIZE+(5+54)*4(sp)
+       lwz     itmp2,LA_SIZE+(5+55)*4(sp)
+       lwz     pv,LA_SIZE+(5+56)*4(sp)
+       lwz     itmp3,LA_SIZE+(5+57)*4(sp)  /* restore return value into temp reg.*/
+
+       lwz     r0,(6+LA_WORD_SIZE+5+58)*4(sp) /* restore RA                      */
+       mtlr    r0
+
+       mr.     itmp3,itmp3           /* check for an exception                   */
+       bne     L_asm_wrapper_patcher_exception
+
+                                     /* get return address (into JIT code)       */
+       lwz     itmp3,(5+LA_WORD_SIZE+5+58)*4(sp)
+
+                                     /* remove stack frame + patcher stub stack  */
+       addi    sp,sp,(8+LA_WORD_SIZE+5+58)*4
+
+       mtctr   itmp3
+       bctr                          /* jump to new patched code                 */
+
+L_asm_wrapper_patcher_exception:
+       mr      xptr,itmp3                  /* get exception                      */
+       lwz     xpc,(5+LA_WORD_SIZE+5+58)*4(sp)
+       addi    sp,sp,(8+LA_WORD_SIZE+5+58)*4
+       b       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:
+      16                start of stack inside method to replace
+      0   rplpoint *    info on the replacement point that was reached
+
+   NOTE: itmp3 has been clobbered by the replacement-out stub!
+
+*******************************************************************************/
+
+/* 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 */
+       addi    sp,sp,-(sizeexecutionstate + REPLACEMENT_ROOM) /* XXX align */
+
+       /* save link register */
+       mflr    r16
+
+       /* save registers in execution state */
+       stw     r0 ,( 0*8+offes_intregs)(sp)
+       stw     r1 ,( 1*8+offes_intregs)(sp)
+       stw     r2 ,( 2*8+offes_intregs)(sp)
+       stw     r3 ,( 3*8+offes_intregs)(sp)
+       stw     r4 ,( 4*8+offes_intregs)(sp)
+       stw     r5 ,( 5*8+offes_intregs)(sp)
+       stw     r6 ,( 6*8+offes_intregs)(sp)
+       stw     r7 ,( 7*8+offes_intregs)(sp)
+       stw     r8 ,( 8*8+offes_intregs)(sp)
+       stw     r9 ,( 9*8+offes_intregs)(sp)
+       stw     r10,(10*8+offes_intregs)(sp)
+       stw     r11,(11*8+offes_intregs)(sp)
+       stw     r12,(12*8+offes_intregs)(sp)
+       stw     r13,(13*8+offes_intregs)(sp)
+       stw     r14,(14*8+offes_intregs)(sp)
+       stw     r15,(15*8+offes_intregs)(sp)
+       stw     r16,(16*8+offes_intregs)(sp) /* link register */
+       stw     r17,(17*8+offes_intregs)(sp)
+       stw     r18,(18*8+offes_intregs)(sp)
+       stw     r19,(19*8+offes_intregs)(sp)
+       stw     r20,(20*8+offes_intregs)(sp)
+       stw     r21,(21*8+offes_intregs)(sp)
+       stw     r22,(22*8+offes_intregs)(sp)
+       stw     r23,(23*8+offes_intregs)(sp)
+       stw     r24,(24*8+offes_intregs)(sp)
+       stw     r25,(25*8+offes_intregs)(sp)
+       stw     r26,(26*8+offes_intregs)(sp)
+       stw     r27,(27*8+offes_intregs)(sp)
+       stw     r28,(28*8+offes_intregs)(sp)
+       stw     r29,(29*8+offes_intregs)(sp)
+       stw     r30,(30*8+offes_intregs)(sp)
+       stw     r31,(31*8+offes_intregs)(sp)
+       
+       stfd    fr0 ,( 0*8+offes_fltregs)(sp)
+       stfd    fr1 ,( 1*8+offes_fltregs)(sp)
+       stfd    fr2 ,( 2*8+offes_fltregs)(sp)
+       stfd    fr3 ,( 3*8+offes_fltregs)(sp)
+       stfd    fr4 ,( 4*8+offes_fltregs)(sp)
+       stfd    fr5 ,( 5*8+offes_fltregs)(sp)
+       stfd    fr6 ,( 6*8+offes_fltregs)(sp)
+       stfd    fr7 ,( 7*8+offes_fltregs)(sp)
+       stfd    fr8 ,( 8*8+offes_fltregs)(sp)
+       stfd    fr9 ,( 9*8+offes_fltregs)(sp)
+       stfd    fr10,(10*8+offes_fltregs)(sp)
+       stfd    fr11,(11*8+offes_fltregs)(sp)
+       stfd    fr12,(12*8+offes_fltregs)(sp)
+       stfd    fr13,(13*8+offes_fltregs)(sp)
+       stfd    fr14,(14*8+offes_fltregs)(sp)
+       stfd    fr15,(15*8+offes_fltregs)(sp)
+       stfd    fr16,(16*8+offes_fltregs)(sp)
+       stfd    fr17,(17*8+offes_fltregs)(sp)
+       stfd    fr18,(18*8+offes_fltregs)(sp)
+       stfd    fr19,(19*8+offes_fltregs)(sp)
+       stfd    fr20,(20*8+offes_fltregs)(sp)
+       stfd    fr21,(21*8+offes_fltregs)(sp)
+       stfd    fr22,(22*8+offes_fltregs)(sp)
+       stfd    fr23,(23*8+offes_fltregs)(sp)
+       stfd    fr24,(24*8+offes_fltregs)(sp)
+       stfd    fr25,(25*8+offes_fltregs)(sp)
+       stfd    fr26,(26*8+offes_fltregs)(sp)
+       stfd    fr27,(27*8+offes_fltregs)(sp)
+       stfd    fr28,(28*8+offes_fltregs)(sp)
+       stfd    fr29,(29*8+offes_fltregs)(sp)
+       stfd    fr30,(30*8+offes_fltregs)(sp)
+       stfd    fr31,(31*8+offes_fltregs)(sp)
+       
+       /* calculate sp of method */
+       addi    itmp1,sp,(sizeexecutionstate + REPLACEMENT_ROOM + 4*4)
+       stw     itmp1,(offes_sp)(sp)
+
+       /* store pv */
+       stw     pv,(offes_pv)(sp)
+
+       /* call replace_me */
+       lwz     a0,-(4*4)(itmp1)            /* arg0: rplpoint *                   */
+       mr      a1,sp                       /* arg1: execution state              */
+       addi    sp,sp,-(LA_SIZE_ALIGNED)
+       b       replace_me                  /* call C function replace_me         */
+
+/* asm_replacement_in **********************************************************
+
+   This code writes the given execution state and jumps to the replacement
+   code.
+
+   This function never returns!
+
+   NOTE: itmp3 is not restored!
+
+   C prototype:
+      void asm_replacement_in(executionstate *es);
+
+*******************************************************************************/
+
+asm_replacement_in:
+       /* a0 == executionstate *es */
+
+       /* set new sp and pv */
+       lwz     sp,(offes_sp)(a0)
+       lwz     pv,(offes_pv)(a0)
+       
+       /* copy registers from execution state */
+       lwz     r0 ,( 0*8+offes_intregs)(a0)
+       /* r1 is sp                       */
+       /* r2 is reserved                 */
+       /* a0 is loaded below             */
+       lwz     r4 ,( 4*8+offes_intregs)(a0)
+       lwz     r5 ,( 5*8+offes_intregs)(a0)
+       lwz     r6 ,( 6*8+offes_intregs)(a0)
+       lwz     r7 ,( 7*8+offes_intregs)(a0)
+       lwz     r8 ,( 8*8+offes_intregs)(a0)
+       lwz     r9 ,( 9*8+offes_intregs)(a0)
+       lwz     r10,(10*8+offes_intregs)(a0)
+       lwz     r11,(11*8+offes_intregs)(a0)
+       lwz     r12,(12*8+offes_intregs)(a0)
+       /* r13 is pv                      */
+       lwz     r14,(14*8+offes_intregs)(a0)
+       lwz     r15,(15*8+offes_intregs)(a0)
+       lwz     r16,(16*8+offes_intregs)(a0) /* link register */
+       lwz     r17,(17*8+offes_intregs)(a0)
+       lwz     r18,(18*8+offes_intregs)(a0)
+       lwz     r19,(19*8+offes_intregs)(a0)
+       lwz     r20,(20*8+offes_intregs)(a0)
+       lwz     r21,(21*8+offes_intregs)(a0)
+       lwz     r22,(22*8+offes_intregs)(a0)
+       lwz     r23,(23*8+offes_intregs)(a0)
+       lwz     r24,(24*8+offes_intregs)(a0)
+       lwz     r25,(25*8+offes_intregs)(a0)
+       lwz     r26,(26*8+offes_intregs)(a0)
+       lwz     r27,(27*8+offes_intregs)(a0)
+       lwz     r28,(28*8+offes_intregs)(a0)
+       lwz     r29,(29*8+offes_intregs)(a0)
+       lwz     r30,(30*8+offes_intregs)(a0)
+       lwz     r31,(31*8+offes_intregs)(a0)
+       
+       lfd     fr0 ,( 0*8+offes_fltregs)(a0)
+       lfd     fr1 ,( 1*8+offes_fltregs)(a0)
+       lfd     fr2 ,( 2*8+offes_fltregs)(a0)
+       lfd     fr3 ,( 3*8+offes_fltregs)(a0)
+       lfd     fr4 ,( 4*8+offes_fltregs)(a0)
+       lfd     fr5 ,( 5*8+offes_fltregs)(a0)
+       lfd     fr6 ,( 6*8+offes_fltregs)(a0)
+       lfd     fr7 ,( 7*8+offes_fltregs)(a0)
+       lfd     fr8 ,( 8*8+offes_fltregs)(a0)
+       lfd     fr9 ,( 9*8+offes_fltregs)(a0)
+       lfd     fr10,(10*8+offes_fltregs)(a0)
+       lfd     fr11,(11*8+offes_fltregs)(a0)
+       lfd     fr12,(12*8+offes_fltregs)(a0)
+       lfd     fr13,(13*8+offes_fltregs)(a0)
+       lfd     fr14,(14*8+offes_fltregs)(a0)
+       lfd     fr15,(15*8+offes_fltregs)(a0)
+       lfd     fr16,(16*8+offes_fltregs)(a0)
+       lfd     fr17,(17*8+offes_fltregs)(a0)
+       lfd     fr18,(18*8+offes_fltregs)(a0)
+       lfd     fr19,(19*8+offes_fltregs)(a0)
+       lfd     fr20,(20*8+offes_fltregs)(a0)
+       lfd     fr21,(21*8+offes_fltregs)(a0)
+       lfd     fr22,(22*8+offes_fltregs)(a0)
+       lfd     fr23,(23*8+offes_fltregs)(a0)
+       lfd     fr24,(24*8+offes_fltregs)(a0)
+       lfd     fr25,(25*8+offes_fltregs)(a0)
+       lfd     fr26,(26*8+offes_fltregs)(a0)
+       lfd     fr27,(27*8+offes_fltregs)(a0)
+       lfd     fr28,(28*8+offes_fltregs)(a0)
+       lfd     fr29,(29*8+offes_fltregs)(a0)
+       lfd     fr30,(30*8+offes_fltregs)(a0)
+       lfd     fr31,(31*8+offes_fltregs)(a0)
+
+       /* restore link register */
+
+       mtlr    r16
+       
+       /* load new pc */
+
+       lwz     itmp3,offes_pc(a0)
+
+       /* load a0 */
+       
+       lwz     a0,(3*8+offes_intregs)(a0)
+
+       /* jump to new code */
+
+       mtctr   itmp3
+       bctr
+
+/*********************************************************************/
+
+asm_cacheflush:
+       add     r4,r3,r4
+       rlwinm  r3,r3,0,0,26
+       addi    r4,r4,31
+       rlwinm  r4,r4,0,0,26
+       mr      r5,r3
+1:
+       cmplw   r3,r4
+       bge     0f
+       dcbst   0,r3
+       addi    r3,r3,32
+       b       1b
+0:
+       sync
+1:
+       cmplw   r5,r4
+       bge     0f
+       icbi    0,r5
+       addi    r5,r5,32
+       b       1b
+0:
+       sync
+       isync
+       blr
+
+
+asm_getclassvalues_atomic:
+_crit_restart:
+_crit_begin:
+       lwz     r6,offbaseval(r3)
+       lwz     r7,offdiffval(r3)
+       lwz     r8,offbaseval(r4)
+_crit_end:
+       stw     r6,offcast_super_baseval(r5)
+       stw     r7,offcast_super_diffval(r5)
+       stw     r8,offcast_sub_baseval(r5)
+       blr
+
+       .data
+
+asm_criticalsections:
+#if defined(ENABLE_THREADS)
+       .long   _crit_begin
+       .long   _crit_end
+       .long   _crit_restart
+#endif
+       .long 0
+
+
+#if defined(__DARWIN__)
+
+.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
+       .align 2
+L_builtin_throw_exception$stub:
+       .indirect_symbol _builtin_throw_exception
+       mflr r0
+       bcl 20,31,L00$_builtin_throw_exception
+L00$_builtin_throw_exception:
+       mflr r11
+       addis r11,r11,ha16(L_builtin_throw_exception$lazy_ptr - L00$_builtin_throw_exception)
+       mtlr r0
+       lwzu r12,lo16(L_builtin_throw_exception$lazy_ptr - L00$_builtin_throw_exception)(r11)
+       mtctr r12
+       bctr
+.data
+.lazy_symbol_pointer
+L_builtin_throw_exception$lazy_ptr:
+       .indirect_symbol _builtin_throw_exception
+       .long dyld_stub_binding_helper
+
+
+.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
+       .align 2
+L_exceptions_handle_exception$stub:
+       .indirect_symbol _exceptions_handle_exception
+       mflr r0
+       bcl 20,31,L00$_exceptions_handle_exception
+L00$_exceptions_handle_exception:
+       mflr r11
+       addis r11,r11,ha16(L_exceptions_handle_exception$lazy_ptr - L00$_exceptions_handle_exception)
+       mtlr r0
+       lwzu r12,lo16(L_exceptions_handle_exception$lazy_ptr - L00$_exceptions_handle_exception)(r11)
+       mtctr r12
+       bctr
+.data
+.lazy_symbol_pointer
+L_exceptions_handle_exception$lazy_ptr:
+       .indirect_symbol _exceptions_handle_exception
+       .long dyld_stub_binding_helper
+
+
+.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
+       .align 2
+L_stacktrace_create_extern_stackframeinfo$stub:
+       .indirect_symbol _stacktrace_create_extern_stackframeinfo
+       mflr r0
+       bcl 20,31,L00$_stacktrace_create_extern_stackframeinfo
+L00$_stacktrace_create_extern_stackframeinfo:
+       mflr r11
+       addis r11,r11,ha16(L_stacktrace_create_extern_stackframeinfo$lazy_ptr - L00$_stacktrace_create_extern_stackframeinfo)
+       mtlr r0
+       lwzu r12,lo16(L_stacktrace_create_extern_stackframeinfo$lazy_ptr - L00$_stacktrace_create_extern_stackframeinfo)(r11)
+       mtctr r12
+       bctr
+.data
+.lazy_symbol_pointer
+L_stacktrace_create_extern_stackframeinfo$lazy_ptr:
+       .indirect_symbol _stacktrace_create_extern_stackframeinfo
+       .long dyld_stub_binding_helper
+
+
+.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
+       .align 2
+L_jit_asm_compile$stub:
+       .indirect_symbol _jit_asm_compile
+       mflr r0
+       bcl 20,31,L00$_jit_asm_compile
+L00$_jit_asm_compile:
+       mflr r11
+       addis r11,r11,ha16(L_jit_asm_compile$lazy_ptr - L00$_jit_asm_compile)
+       mtlr r0
+       lwzu r12,lo16(L_jit_asm_compile$lazy_ptr - L00$_jit_asm_compile)(r11)
+       mtctr r12
+       bctr
+.data
+.lazy_symbol_pointer
+L_jit_asm_compile$lazy_ptr:
+       .indirect_symbol _jit_asm_compile
+       .long dyld_stub_binding_helper
+
+
+.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
+       .align 2
+L_stacktrace_remove_stackframeinfo$stub:
+       .indirect_symbol _stacktrace_remove_stackframeinfo
+       mflr r0
+       bcl 20,31,L00$_stacktrace_remove_stackframeinfo
+L00$_stacktrace_remove_stackframeinfo:
+       mflr r11
+       addis r11,r11,ha16(L_stacktrace_remove_stackframeinfo$lazy_ptr - L00$_stacktrace_remove_stackframeinfo)
+       mtlr r0
+       lwzu r12,lo16(L_stacktrace_remove_stackframeinfo$lazy_ptr - L00$_stacktrace_remove_stackframeinfo)(r11)
+       mtctr r12
+       bctr
+.data
+.lazy_symbol_pointer
+L_stacktrace_remove_stackframeinfo$lazy_ptr:
+       .indirect_symbol _stacktrace_remove_stackframeinfo
+       .long dyld_stub_binding_helper
+
+
+.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
+       .align 2
+L_exceptions_get_and_clear_exception$stub:
+       .indirect_symbol _exceptions_get_and_clear_exception
+       mflr r0
+       bcl 20,31,L00$_exceptions_get_and_clear_exception
+L00$_exceptions_get_and_clear_exception:
+       mflr r11
+       addis r11,r11,ha16(L_exceptions_get_and_clear_exception$lazy_ptr - L00$_exceptions_get_and_clear_exception)
+       mtlr r0
+       lwzu r12,lo16(L_exceptions_get_and_clear_exception$lazy_ptr - L00$_exceptions_get_and_clear_exception)(r11)
+       mtctr r12
+       bctr
+.data
+.lazy_symbol_pointer
+L_exceptions_get_and_clear_exception$lazy_ptr:
+       .indirect_symbol _exceptions_get_and_clear_exception
+       .long dyld_stub_binding_helper
+
+
+.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
+       .align 2
+L_exceptions_asm_new_abstractmethoderror$stub:
+       .indirect_symbol _exceptions_asm_new_abstractmethoderror
+       mflr r0
+       bcl 20,31,L00$_exceptions_asm_new_abstractmethoderror
+L00$_exceptions_asm_new_abstractmethoderror:
+       mflr r11
+       addis r11,r11,ha16(L_exceptions_asm_new_abstractmethoderror$lazy_ptr - L00$_exceptions_asm_new_abstractmethoderror)
+       mtlr r0
+       lwzu r12,lo16(L_exceptions_asm_new_abstractmethoderror$lazy_ptr - L00$_exceptions_asm_new_abstractmethoderror)(r11)
+       mtctr r12
+       bctr
+.data
+.lazy_symbol_pointer
+L_exceptions_asm_new_abstractmethoderror$lazy_ptr:
+       .indirect_symbol _exceptions_asm_new_abstractmethoderror
+       .long dyld_stub_binding_helper
+
+
+.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
+       .align 2
+L_replace_me$stub:
+       .indirect_symbol _replace_me
+       mflr r0
+       bcl 20,31,L00$_replace_me
+L00$_replace_me:
+       mflr r11
+       addis r11,r11,ha16(L_replace_me$lazy_ptr - L00$_replace_me)
+       mtlr r0
+       lwzu r12,lo16(L_replace_me$lazy_ptr - L00$_replace_me)(r11)
+       mtctr r12
+       bctr
+.data
+.lazy_symbol_pointer
+L_replace_me$lazy_ptr:
+       .indirect_symbol _replace_me
+       .long dyld_stub_binding_helper
+
+#endif /* defined(__DARWIN__) */
+
+
+/* Disable exec-stacks, required for Gentoo ***********************************/
+
+#if defined(__GCC__) && defined(__ELF__)
+       .section .note.GNU-stack,"",@progbits
+#endif
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * 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/powerpc64/codegen.c b/src/vm/jit/powerpc64/codegen.c
new file mode 100644 (file)
index 0000000..ce3f324
--- /dev/null
@@ -0,0 +1,4371 @@
+/* src/vm/jit/powerpc/codegen.c - machine code generator for 32-bit PowerPC
+
+   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
+            Stefan Ring
+
+   Changes: Christian Thalinger
+            Christian Ullrich
+            Edwin Steiner
+
+   $Id: codegen.c 5081 2006-07-06 13:59:01Z tbfg $
+
+*/
+
+
+#include "config.h"
+
+#include <assert.h>
+#include <stdio.h>
+#include <signal.h>
+
+#include "vm/types.h"
+
+#include "md-abi.h"
+
+#include "vm/jit/powerpc64/arch.h"
+#include "vm/jit/powerpc64/codegen.h"
+
+#include "mm/memory.h"
+#include "native/native.h"
+#include "vm/builtin.h"
+#include "vm/exceptions.h"
+#include "vm/global.h"
+#include "vm/loader.h"
+#include "vm/options.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.h"
+#include "vm/jit/jit.h"
+#include "vm/jit/parse.h"
+#include "vm/jit/patcher.h"
+#include "vm/jit/reg.h"
+#include "vm/jit/replace.h"
+
+#if defined(ENABLE_LSRA)
+# include "vm/jit/allocator/lsra.h"
+#endif
+
+
+void codegen_trace_args(jitdata *jd, s4 stackframesize, bool nativestub);
+
+/* codegen *********************************************************************
+
+   Generates machine code.
+
+*******************************************************************************/
+
+bool codegen(jitdata *jd)
+{
+       methodinfo         *m;
+       codeinfo           *code;
+       codegendata        *cd;
+       registerdata       *rd;
+       s4                  len, s1, s2, s3, d, disp;
+       ptrint              a;
+       s4                  stackframesize;
+       stackptr            src;
+       varinfo            *var;
+       basicblock         *bptr;
+       instruction        *iptr;
+       exceptiontable     *ex;
+       u2                  currentline;
+       methodinfo         *lm;             /* local methodinfo for ICMD_INVOKE*  */
+       builtintable_entry *bte;
+       methoddesc         *md;
+       rplpoint           *replacementpoint;
+
+       /* get required compiler data */
+
+       m    = jd->m;
+       code = jd->code;
+       cd   = jd->cd;
+       rd   = jd->rd;
+
+       /* prevent compiler warnings */
+
+       d = 0;
+       lm = NULL;
+       bte = NULL;
+
+       {
+       s4 i, p, t, l;
+       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) * 2;
+
+       stackframesize = rd->memuse + savedregs_num;
+
+#if defined(ENABLE_THREADS)
+       /* space to save argument of monitor_enter and Return Values to survive */
+    /* monitor_exit. The stack position for the argument can not be shared  */
+       /* with place to save the return register on PPC, since both values     */
+       /* reside in R3 */
+       if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
+               /* reserve 2 slots for long/double return values for monitorexit */
+
+               if (IS_2_WORD_TYPE(m->parseddesc->returntype.type))
+                       stackframesize += 3;
+               else
+                       stackframesize += 2;
+       }
+
+#endif
+
+       /* create method header */
+
+       /* align stack to 16-bytes */
+
+/*     if (!m->isleafmethod || opt_verbosecall) */
+               stackframesize = (stackframesize + 3) & ~3;
+
+/*     else if (m->isleafmethod && (stackframesize == LA_WORD_SIZE)) */
+/*             stackframesize = 0; */
+
+       (void) dseg_addaddress(cd, code);                      /* CodeinfoPointer */
+       (void) dseg_adds4(cd, stackframesize * 4);             /* 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_adds4(cd, (rd->memuse + 1) * 4);       /* IsSync          */
+       else
+#endif
+               (void) dseg_adds4(cd, 0);                          /* IsSync          */
+                                              
+       (void) dseg_adds4(cd, m->isleafmethod);                /* IsLeaf          */
+       (void) dseg_adds4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave         */
+       (void) dseg_adds4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave         */
+
+       dseg_addlinenumbertablesize(cd);
+
+       (void) dseg_adds4(cd, cd->exceptiontablelength);       /* ExTableSize     */
+
+       /* create exception table */
+
+       for (ex = cd->exceptiontable; ex != NULL; ex = ex->down) {
+               dseg_addtarget(cd, ex->start);
+               dseg_addtarget(cd, ex->end);
+               dseg_addtarget(cd, ex->handler);
+               (void) dseg_addaddress(cd, ex->catchtype.cls);
+       }
+       
+       /* create stack frame (if necessary) */
+
+       if (!m->isleafmethod) {
+               M_MFLR(REG_ZERO);
+               M_AST(REG_ZERO, REG_SP, LA_LR_OFFSET);
+       }
+
+       if (stackframesize)
+               M_STWU(REG_SP, REG_SP, -stackframesize * 4);
+
+       /* save return address and used callee saved registers */
+
+       p = stackframesize;
+       for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
+               p--; M_IST(rd->savintregs[i], REG_SP, p * 4);
+       }
+       for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
+               p -= 2; M_DST(rd->savfltregs[i], REG_SP, p * 4);
+       }
+
+       /* 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;
+               var = &(rd->locals[l][t]);
+               l++;
+               if (IS_2_WORD_TYPE(t))    /* increment local counter for 2 word types */
+                       l++;
+               if (var->type < 0)
+                       continue;
+               s1 = md->params[p].regoff;
+               if (IS_INT_LNG_TYPE(t)) {                    /* integer args          */
+                       if (IS_2_WORD_TYPE(t))
+                               s2 = PACK_REGS(rd->argintregs[GET_LOW_REG(s1)],
+                                                          rd->argintregs[GET_HIGH_REG(s1)]);
+                       else
+                               s2 = rd->argintregs[s1];
+                       if (!md->params[p].inmemory) {           /* register arguments    */
+                               if (!(var->flags & INMEMORY)) {      /* reg arg -> register   */
+                                       if (IS_2_WORD_TYPE(t))
+                                               M_LNGMOVE(s2, var->regoff);
+                                       else
+                                               M_INTMOVE(s2, var->regoff);
+
+                               } else {                             /* reg arg -> spilled    */
+                                       if (IS_2_WORD_TYPE(t))
+                                               M_LST(s2, REG_SP, var->regoff * 4);
+                                       else
+                                               M_IST(s2, REG_SP, var->regoff * 4);
+                               }
+
+                       } else {                                 /* stack arguments       */
+                               if (!(var->flags & INMEMORY)) {      /* stack arg -> register */
+                                       if (IS_2_WORD_TYPE(t))
+                                               M_LLD(var->regoff, REG_SP, (stackframesize + s1) * 4);
+                                       else
+                                               M_ILD(var->regoff, REG_SP, (stackframesize + s1) * 4);
+
+                               } else {                             /* stack arg -> spilled  */
+#if 1
+                                       M_ILD(REG_ITMP1, REG_SP, (stackframesize + s1) * 4);
+                                       M_IST(REG_ITMP1, REG_SP, var->regoff * 4);
+                                       if (IS_2_WORD_TYPE(t)) {
+                                               M_ILD(REG_ITMP1, REG_SP, (stackframesize + s1) * 4 +4);
+                                               M_IST(REG_ITMP1, REG_SP, var->regoff * 4 + 4);
+                                       }
+#else
+                                       /* Reuse Memory Position on Caller Stack */
+                                       var->regoff = stackframesize + s1;
+#endif
+                               }
+                       }
+
+               } else {                                     /* floating args         */
+                       if (!md->params[p].inmemory) {           /* register arguments    */
+                               s2 = rd->argfltregs[s1];
+                               if (!(var->flags & INMEMORY)) {      /* reg arg -> register   */
+                                       M_FLTMOVE(s2, var->regoff);
+
+                               } else {                                         /* reg arg -> spilled    */
+                                       if (IS_2_WORD_TYPE(t))
+                                               M_DST(s2, REG_SP, var->regoff * 4);
+                                       else
+                                               M_FST(s2, REG_SP, var->regoff * 4);
+                               }
+
+                       } else {                                 /* stack arguments       */
+                               if (!(var->flags & INMEMORY)) {      /* stack-arg -> register */
+                                       if (IS_2_WORD_TYPE(t))
+                                               M_DLD(var->regoff, REG_SP, (stackframesize + s1) * 4);
+
+                                       else
+                                               M_FLD(var->regoff, REG_SP, (stackframesize + s1) * 4);
+
+                               } else {                             /* stack-arg -> spilled  */
+#if 1
+                                       if (IS_2_WORD_TYPE(t)) {
+                                               M_DLD(REG_FTMP1, REG_SP, (stackframesize + s1) * 4);
+                                               M_DST(REG_FTMP1, REG_SP, var->regoff * 4);
+                                               var->regoff = stackframesize + s1;
+
+                                       } else {
+                                               M_FLD(REG_FTMP1, REG_SP, (stackframesize + s1) * 4);
+                                               M_FST(REG_FTMP1, REG_SP, var->regoff * 4);
+                                       }
+#else
+                                       /* Reuse Memory Position on Caller Stack */
+                                       var->regoff = stackframesize + s1;
+#endif
+                               }
+                       }
+               }
+       } /* end for */
+
+       /* save monitorenter argument */
+
+#if defined(ENABLE_THREADS)
+       if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
+               p = dseg_addaddress(cd, BUILTIN_monitorenter);
+               M_ALD(REG_ITMP3, REG_PV, p);
+               M_MTCTR(REG_ITMP3);
+
+               /* get or test the lock object */
+
+               if (m->flags & ACC_STATIC) {
+                       p = dseg_addaddress(cd, &m->class->object.header);
+                       M_ALD(rd->argintregs[0], REG_PV, p);
+               }
+               else {
+                       M_TST(rd->argintregs[0]);
+                       M_BEQ(0);
+                       codegen_add_nullpointerexception_ref(cd);
+               }
+
+               M_AST(rd->argintregs[0], REG_SP, rd->memuse * 4);
+               M_JSR;
+       }
+#endif
+
+       /* call trace function */
+
+       if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
+               codegen_trace_args(jd, stackframesize, false);
+       }
+
+       /* end of header generation */
+
+       replacementpoint = jd->code->rplpoints;
+
+       /* walk through all basic blocks */
+       for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
+
+               bptr->mpc = (s4) (cd->mcodeptr - cd->mcodebase);
+
+               if (bptr->flags >= BBREACHED) {
+
+               /* branch resolving */
+
+               {
+               branchref *brefs;
+               for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
+                       gen_resolvebranch((u1*) cd->mcodebase + brefs->branchpos, 
+                                         brefs->branchpos,
+                                                         bptr->mpc);
+                       }
+               }
+
+               /* handle replacement points */
+
+               if (bptr->bitflags & BBFLAG_REPLACEMENT) {
+                       replacementpoint->pc = (u1*)(ptrint)bptr->mpc; /* will be resolved later */
+                       
+                       replacementpoint++;
+               }
+
+               /* copy interface registers to their destination */
+
+               src = bptr->instack;
+               len = bptr->indepth;
+               MCODECHECK(64+len);
+
+#if defined(ENABLE_LSRA)
+               if (opt_lsra) {
+                       while (src != NULL) {
+                               len--;
+                               if ((len == 0) && (bptr->type != BBTYPE_STD)) {
+                                       /* d = reg_of_var(m, src, REG_ITMP1); */
+                                       if (!(src->flags & INMEMORY))
+                                               d = src->regoff;
+                                       else
+                                               d = REG_ITMP1;
+                                       M_INTMOVE(REG_ITMP1, d);
+                                       emit_store(jd, NULL, src, d);
+                               }
+                               src = src->prev;
+                       }
+               } else {
+#endif
+               while (src != NULL) {
+                       len--;
+                       if ((len == 0) && (bptr->type != BBTYPE_STD)) {
+                               d = codegen_reg_of_var(rd, 0, src, REG_ITMP1);
+                               M_INTMOVE(REG_ITMP1, d);
+                               emit_store(jd, NULL, src, d);
+                       } else {
+                               if (src->type == TYPE_LNG)
+                                       d = codegen_reg_of_var(rd, 0, src, PACK_REGS(REG_ITMP2, REG_ITMP1));
+                               else
+                                       d = codegen_reg_of_var(rd, 0, src, REG_IFTMP);
+                               if ((src->varkind != STACKVAR)) {
+                                       s2 = src->type;
+                                       if (IS_FLT_DBL_TYPE(s2)) {
+                                               if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
+                                                       s1 = rd->interfaces[len][s2].regoff;
+                                                       M_FLTMOVE(s1, d);
+                                               } else {
+                                                       if (IS_2_WORD_TYPE(s2)) {
+                                                               M_DLD(d, REG_SP,
+                                                                         rd->interfaces[len][s2].regoff * 4);
+                                                       } else {
+                                                               M_FLD(d, REG_SP,
+                                                                         rd->interfaces[len][s2].regoff * 4);
+                                                       }       
+                                               }
+
+                                               emit_store(jd, NULL, src, d);
+
+                                       } else {
+                                               if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
+                                                       s1 = rd->interfaces[len][s2].regoff;
+                                                       if (IS_2_WORD_TYPE(s2))
+                                                               M_LNGMOVE(s1, d);
+                                                       else
+                                                               M_INTMOVE(s1, d);
+                                               } else {
+                                                       if (IS_2_WORD_TYPE(s2))
+                                                               M_LLD(d, REG_SP,
+                                                                         rd->interfaces[len][s2].regoff * 4);
+                                                       else
+                                                               M_ILD(d, REG_SP,
+                                                                         rd->interfaces[len][s2].regoff * 4);
+                                               }
+
+                                               emit_store(jd, NULL, src, d);
+                                       }
+                               }
+                       }
+                       src = src->prev;
+               }
+
+#if defined(ENABLE_LSRA)
+               }
+#endif
+               /* walk through all instructions */
+               
+               src = bptr->instack;
+               len = bptr->icount;
+               currentline = 0;
+
+               for (iptr = bptr->iinstr; len > 0; src = iptr->dst, len--, iptr++) {
+                       if (iptr->line != currentline) {
+                               dseg_addlinenumber(cd, iptr->line);
+                               currentline = iptr->line;
+                       }
+
+                       MCODECHECK(64);   /* an instruction usually needs < 64 words      */
+
+                       switch (iptr->opc) {
+                       case ICMD_NOP:    /* ...  ==> ...                                 */
+                       case ICMD_INLINE_START:
+                       case ICMD_INLINE_END:
+                               break;
+
+               case ICMD_CHECKNULL:  /* ..., objectref  ==> ..., objectref           */
+
+                       s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
+                       M_TST(s1);
+                       M_BEQ(0);
+                       codegen_add_nullpointerexception_ref(cd);
+                       break;
+
+               /* constant operations ************************************************/
+
+               case ICMD_ICONST:     /* ...  ==> ..., constant                       */
+                                     /* op1 = 0, val.i = constant                    */
+
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
+                       ICONST(d, iptr->val.i);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_LCONST:     /* ...  ==> ..., constant                       */
+                                     /* op1 = 0, val.l = constant                    */
+
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP1));
+                       LCONST(d, iptr->val.l);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_FCONST:     /* ...  ==> ..., constant                       */
+                                     /* op1 = 0, val.f = constant                    */
+
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
+                       a = dseg_addfloat(cd, iptr->val.f);
+                       M_FLD(d, REG_PV, a);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+                       
+               case ICMD_DCONST:     /* ...  ==> ..., constant                       */
+                                     /* op1 = 0, val.d = constant                    */
+
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
+                       a = dseg_adddouble(cd, iptr->val.d);
+                       M_DLD(d, REG_PV, a);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_ACONST:     /* ...  ==> ..., constant                       */
+                                     /* op1 = 0, val.a = constant                    */
+
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
+                       disp = dseg_addaddress(cd, iptr->val.a);
+
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                               codegen_addpatchref(cd, PATCHER_aconst,
+                                                                       ICMD_ACONST_UNRESOLVED_CLASSREF(iptr),
+                                                                   disp);
+
+                               if (opt_showdisassemble)
+                                       M_NOP;
+                       }
+
+                       M_ALD(d, REG_PV, disp);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+
+               /* load/store operations **********************************************/
+
+               case ICMD_ILOAD:      /* ...  ==> ..., content of local variable      */
+               case ICMD_ALOAD:      /* op1 = local variable                         */
+
+                       var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
+                       if ((iptr->dst->varkind == LOCALVAR) &&
+                           (iptr->dst->varnum == iptr->op1))
+                               break;
+                       if (var->flags & INMEMORY)
+                               M_ILD(d, REG_SP, var->regoff * 4);
+                       else
+                               M_INTMOVE(var->regoff, d);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_LLOAD:      /* ...  ==> ..., content of local variable      */
+                                     /* op1 = local variable                         */
+
+                       var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP1));
+                       if ((iptr->dst->varkind == LOCALVAR) &&
+                               (iptr->dst->varnum == iptr->op1))
+                               break;
+                       if (var->flags & INMEMORY)
+                               M_LLD(d, REG_SP, var->regoff * 4);
+                       else
+                               M_LNGMOVE(var->regoff, d);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_FLOAD:      /* ...  ==> ..., content of local variable      */
+                                     /* op1 = local variable                         */
+
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
+                       if ((iptr->dst->varkind == LOCALVAR) &&
+                               (iptr->dst->varnum == iptr->op1))
+                               break;
+                       var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
+                       if (var->flags & INMEMORY)
+                               M_FLD(d, REG_SP, var->regoff * 4);
+                       else
+                               M_FLTMOVE(var->regoff, d);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_DLOAD:      /* ...  ==> ..., content of local variable      */
+                                     /* op1 = local variable                         */
+
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
+                       if ((iptr->dst->varkind == LOCALVAR) &&
+                               (iptr->dst->varnum == iptr->op1))
+                               break;
+                       var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
+                       if (var->flags & INMEMORY)
+                               M_DLD(d, REG_SP, var->regoff * 4);
+                       else
+                               M_FLTMOVE(var->regoff, d);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+
+               case ICMD_ISTORE:     /* ..., value  ==> ...                          */
+               case ICMD_ASTORE:     /* op1 = local variable                         */
+
+                       if ((src->varkind == LOCALVAR) && (src->varnum == iptr->op1))
+                               break;
+                       var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
+                       if (var->flags & INMEMORY) {
+                               s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
+                               M_IST(s1, REG_SP, var->regoff * 4);
+                       } else {
+                               s1 = emit_load_s1(jd, iptr, src, var->regoff);
+                               M_INTMOVE(s1, var->regoff);
+                       }
+                       break;
+
+               case ICMD_LSTORE:     /* ..., value  ==> ...                          */
+                                     /* op1 = local variable                         */
+
+                       if ((src->varkind == LOCALVAR) && (src->varnum == iptr->op1))
+                               break;
+                       var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
+                       if (var->flags & INMEMORY) {
+                               s1 = emit_load_s1(jd, iptr, src, PACK_REGS(REG_ITMP2, REG_ITMP1));
+                               M_LST(s1, REG_SP, var->regoff * 4);
+                       } else {
+                               s1 = emit_load_s1(jd, iptr, src, var->regoff);
+                               M_LNGMOVE(s1, var->regoff);
+                       }
+                       break;
+
+               case ICMD_FSTORE:     /* ..., value  ==> ...                          */
+                                     /* op1 = local variable                         */
+
+                       if ((src->varkind == LOCALVAR) && (src->varnum == iptr->op1))
+                               break;
+                       var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
+                       if (var->flags & INMEMORY) {
+                               s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
+                               M_FST(s1, REG_SP, var->regoff * 4);
+                       } else {
+                               s1 = emit_load_s1(jd, iptr, src, var->regoff);
+                               M_FLTMOVE(s1, var->regoff);
+                       }
+                       break;
+
+               case ICMD_DSTORE:     /* ..., value  ==> ...                          */
+                                     /* op1 = local variable                         */
+
+                       if ((src->varkind == LOCALVAR) && (src->varnum == iptr->op1))
+                               break;
+                       var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
+                       if (var->flags & INMEMORY) {
+                               s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
+                               M_DST(s1, REG_SP, var->regoff * 4);
+                       } else {
+                               s1 = emit_load_s1(jd, iptr, src, var->regoff);
+                               M_FLTMOVE(s1, var->regoff);
+                       }
+                       break;
+
+
+               /* pop/dup/swap operations ********************************************/
+
+               /* attention: double and longs are only one entry in CACAO ICMDs      */
+
+               case ICMD_POP:        /* ..., value  ==> ...                          */
+               case ICMD_POP2:       /* ..., value, value  ==> ...                   */
+                       break;
+
+               case ICMD_DUP:        /* ..., a ==> ..., a, a                         */
+                       M_COPY(src, iptr->dst);
+                       break;
+
+               case ICMD_DUP_X1:     /* ..., a, b ==> ..., b, a, b                   */
+
+                       M_COPY(src,       iptr->dst);
+                       M_COPY(src->prev, iptr->dst->prev);
+                       M_COPY(iptr->dst, iptr->dst->prev->prev);
+                       break;
+
+               case ICMD_DUP_X2:     /* ..., a, b, c ==> ..., c, a, b, c             */
+
+                       M_COPY(src,             iptr->dst);
+                       M_COPY(src->prev,       iptr->dst->prev);
+                       M_COPY(src->prev->prev, iptr->dst->prev->prev);
+                       M_COPY(iptr->dst,       iptr->dst->prev->prev->prev);
+                       break;
+
+               case ICMD_DUP2:       /* ..., a, b ==> ..., a, b, a, b                */
+
+                       M_COPY(src,       iptr->dst);
+                       M_COPY(src->prev, iptr->dst->prev);
+                       break;
+
+               case ICMD_DUP2_X1:    /* ..., a, b, c ==> ..., b, c, a, b, c          */
+
+                       M_COPY(src,             iptr->dst);
+                       M_COPY(src->prev,       iptr->dst->prev);
+                       M_COPY(src->prev->prev, iptr->dst->prev->prev);
+                       M_COPY(iptr->dst,       iptr->dst->prev->prev->prev);
+                       M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev);
+                       break;
+
+               case ICMD_DUP2_X2:    /* ..., a, b, c, d ==> ..., c, d, a, b, c, d    */
+
+                       M_COPY(src,                   iptr->dst);
+                       M_COPY(src->prev,             iptr->dst->prev);
+                       M_COPY(src->prev->prev,       iptr->dst->prev->prev);
+                       M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
+                       M_COPY(iptr->dst,             iptr->dst->prev->prev->prev->prev);
+                       M_COPY(iptr->dst->prev,       iptr->dst->prev->prev->prev->prev->prev);
+                       break;
+
+               case ICMD_SWAP:       /* ..., a, b ==> ..., b, a                      */
+
+                       M_COPY(src,       iptr->dst->prev);
+                       M_COPY(src->prev, iptr->dst);
+                       break;
+
+
+               /* integer operations *************************************************/
+
+               case ICMD_INEG:       /* ..., value  ==> ..., - value                 */
+
+                       s1 = emit_load_s1(jd, iptr, src, REG_ITMP1); 
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
+                       M_NEG(s1, d);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_LNEG:       /* ..., value  ==> ..., - value                 */
+
+                       s1 = emit_load_s1(jd, iptr, src, PACK_REGS(REG_ITMP2, REG_ITMP1));
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP1));
+                       M_SUBFIC(GET_LOW_REG(s1), 0, GET_LOW_REG(d));
+                       M_SUBFZE(GET_HIGH_REG(s1), GET_HIGH_REG(d));
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_I2L:        /* ..., value  ==> ..., value                   */
+
+                       s1 = emit_load_s1(jd, iptr, src, REG_ITMP2);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP1));
+                       M_INTMOVE(s1, GET_LOW_REG(d));
+                       M_SRA_IMM(GET_LOW_REG(d), 31, GET_HIGH_REG(d));
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_L2I:        /* ..., value  ==> ..., value                   */
+
+                       s1 = emit_load_s1_low(jd, iptr, src, REG_ITMP2);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
+                       M_INTMOVE(s1, d);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_INT2BYTE:   /* ..., value  ==> ..., value                   */
+
+                       s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
+                       M_BSEXT(s1, d);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_INT2CHAR:   /* ..., value  ==> ..., value                   */
+
+                       s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
+                       M_CZEXT(s1, d);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_INT2SHORT:  /* ..., value  ==> ..., value                   */
+
+                       s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
+                       M_SSEXT(s1, d);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+
+               case ICMD_IADD:       /* ..., val1, val2  ==> ..., val1 + val2        */
+
+                       s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
+                       M_IADD(s1, s2, d);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_IADDCONST:  /* ..., value  ==> ..., value + constant        */
+                                     /* val.i = constant                             */
+
+                       s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
+                       if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
+                               M_IADD_IMM(s1, iptr->val.i, d);
+                       } else {
+                               ICONST(REG_ITMP2, iptr->val.i);
+                               M_IADD(s1, REG_ITMP2, d);
+                       }
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_LADD:       /* ..., val1, val2  ==> ..., val1 + val2        */
+
+                       s1 = emit_load_s1_low(jd, iptr, src->prev, REG_ITMP1);
+                       s2 = emit_load_s2_low(jd, iptr, src, REG_ITMP2);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP1));
+                       M_ADDC(s1, s2, GET_LOW_REG(d));
+                       s1 = emit_load_s1_high(jd, iptr, src->prev, REG_ITMP1);
+                       s2 = emit_load_s2_high(jd, iptr, src, REG_ITMP3);   /* don't use REG_ITMP2 */
+                       M_ADDE(s1, s2, GET_HIGH_REG(d));
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_LADDCONST:  /* ..., value  ==> ..., value + constant        */
+                                     /* val.l = constant                             */
+
+                       s3 = iptr->val.l & 0xffffffff;
+                       s1 = emit_load_s1_low(jd, iptr, src, REG_ITMP1);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP1));
+                       if ((s3 >= -32768) && (s3 <= 32767)) {
+                               M_ADDIC(s1, s3, GET_LOW_REG(d));
+                       } else {
+                               ICONST(REG_ITMP2, s3);
+                               M_ADDC(s1, REG_ITMP2, GET_LOW_REG(d));
+                       }
+                       s1 = emit_load_s1_high(jd, iptr, src, REG_ITMP1);
+                       s3 = iptr->val.l >> 32;
+                       if (s3 == -1) {
+                               M_ADDME(s1, GET_HIGH_REG(d));
+                       } else if (s3 == 0) {
+                               M_ADDZE(s1, GET_HIGH_REG(d));
+                       } else {
+                               ICONST(REG_ITMP3, s3);                 /* don't use REG_ITMP2 */
+                               M_ADDE(s1, REG_ITMP3, GET_HIGH_REG(d));
+                       }
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_ISUB:       /* ..., val1, val2  ==> ..., val1 - val2        */
+
+                       s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
+                       M_ISUB(s1, s2, d);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_ISUBCONST:  /* ..., value  ==> ..., value + constant        */
+                                     /* val.i = constant                             */
+
+                       s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
+                       if ((iptr->val.i >= -32767) && (iptr->val.i <= 32768)) {
+                               M_IADD_IMM(s1, -iptr->val.i, d);
+                       } else {
+                               ICONST(REG_ITMP2, -iptr->val.i);
+                               M_IADD(s1, REG_ITMP2, d);
+                       }
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_LSUB:       /* ..., val1, val2  ==> ..., val1 - val2        */
+
+                       s1 = emit_load_s1_low(jd, iptr, src->prev, REG_ITMP1);
+                       s2 = emit_load_s2_low(jd, iptr, src, REG_ITMP2);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP1));
+                       M_SUBC(s1, s2, GET_LOW_REG(d));
+                       s1 = emit_load_s1_high(jd, iptr, src->prev, REG_ITMP1);
+                       s2 = emit_load_s2_high(jd, iptr, src, REG_ITMP3);   /* don't use REG_ITMP2 */
+                       M_SUBE(s1, s2, GET_HIGH_REG(d));
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_LSUBCONST:  /* ..., value  ==> ..., value - constant        */
+                                     /* val.l = constant                             */
+
+                       s3 = (-iptr->val.l) & 0xffffffff;
+                       s1 = emit_load_s1_low(jd, iptr, src, REG_ITMP1);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP1));
+                       if ((s3 >= -32768) && (s3 <= 32767)) {
+                               M_ADDIC(s1, s3, GET_LOW_REG(d));
+                       } else {
+                               ICONST(REG_ITMP2, s3);
+                               M_ADDC(s1, REG_ITMP2, GET_LOW_REG(d));
+                       }
+                       s1 = emit_load_s1_high(jd, iptr, src, REG_ITMP1);
+                       s3 = (-iptr->val.l) >> 32;
+                       if (s3 == -1)
+                               M_ADDME(s1, GET_HIGH_REG(d));
+                       else if (s3 == 0)
+                               M_ADDZE(s1, GET_HIGH_REG(d));
+                       else {
+                               ICONST(REG_ITMP3, s3);                 /* don't use REG_ITMP2 */
+                               M_ADDE(s1, REG_ITMP3, GET_HIGH_REG(d));
+                       }
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_IDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
+
+                       s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
+                       M_TST(s2);
+                       M_BEQ(0);
+                       codegen_add_arithmeticexception_ref(cd);
+                       M_LDAH(REG_ITMP3, REG_ZERO, 0x8000);
+                       M_CMP(REG_ITMP3, s1);
+                       M_BNE(3 + (s1 != d));
+                       M_CMPI(s2, -1);
+                       M_BNE(1 + (s1 != d));
+                       M_INTMOVE(s1, d);
+                       M_BR(1);
+                       M_IDIV(s1, s2, d);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_IREM:       /* ..., val1, val2  ==> ..., val1 % val2        */
+
+                       s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
+                       M_TST(s2);
+                       M_BEQ(0);
+                       codegen_add_arithmeticexception_ref(cd);
+                       M_LDAH(REG_ITMP3, REG_ZERO, 0x8000);
+                       M_CMP(REG_ITMP3, s1);
+                       M_BNE(4);
+                       M_CMPI(s2, -1);
+                       M_BNE(2);
+                       M_CLR(d);
+                       M_BR(3);
+                       M_IDIV(s1, s2, REG_ITMP3);
+                       M_IMUL(REG_ITMP3, s2, REG_ITMP3);
+                       M_ISUB(s1, REG_ITMP3, d);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_LDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
+               case ICMD_LREM:       /* ..., val1, val2  ==> ..., val1 % val2        */
+
+                       bte = iptr->val.a;
+                       md = bte->md;
+
+                       s2 = emit_load_s2(jd, iptr, src, PACK_REGS(REG_ITMP2, REG_ITMP1));
+                       M_OR_TST(GET_HIGH_REG(s2), GET_LOW_REG(s2), REG_ITMP3);
+                       M_BEQ(0);
+                       codegen_add_arithmeticexception_ref(cd);
+
+                       disp = dseg_addaddress(cd, bte->fp);
+                       M_ALD(REG_ITMP3, REG_PV, disp);
+                       M_MTCTR(REG_ITMP3);
+
+                       s3 = PACK_REGS(rd->argintregs[GET_LOW_REG(md->params[1].regoff)],
+                                                  rd->argintregs[GET_HIGH_REG(md->params[1].regoff)]);
+                       M_LNGMOVE(s2, s3);
+
+                       s1 = emit_load_s1(jd, iptr, src->prev, PACK_REGS(REG_ITMP2, REG_ITMP1));
+                       s3 = PACK_REGS(rd->argintregs[GET_LOW_REG(md->params[0].regoff)],
+                                                  rd->argintregs[GET_HIGH_REG(md->params[0].regoff)]);
+                       M_LNGMOVE(s1, s3);
+
+                       M_JSR;
+
+                       /*d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, PACK_REGS(REG_RESULT2, REG_RESULT)); //FIXME */
+                       /*M_LNGMOVE(PACK_REGS(REG_RESULT2, REG_RESULT), d); FIXME*/
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_IMUL:       /* ..., val1, val2  ==> ..., val1 * val2        */
+
+                       s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
+                       M_IMUL(s1, s2, d);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_IMULCONST:  /* ..., value  ==> ..., value * constant        */
+                                     /* val.i = constant                             */
+
+                       s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
+                       if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
+                               M_IMUL_IMM(s1, iptr->val.i, d);
+                       } else {
+                               ICONST(REG_ITMP3, iptr->val.i);
+                               M_IMUL(s1, REG_ITMP3, d);
+                       }
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_IDIVPOW2:   /* ..., value  ==> ..., value << constant       */
+                                     
+                       s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
+                       M_SRA_IMM(s1, iptr->val.i, d);
+                       M_ADDZE(d, d);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_ISHL:       /* ..., val1, val2  ==> ..., val1 << val2       */
+
+                       s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
+                       M_AND_IMM(s2, 0x1f, REG_ITMP3);
+                       M_SLL(s1, REG_ITMP3, d);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_ISHLCONST:  /* ..., value  ==> ..., value << constant       */
+                                     /* val.i = constant                             */
+
+                       s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
+                       M_SLL_IMM(s1, iptr->val.i & 0x1f, d);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_ISHR:       /* ..., val1, val2  ==> ..., val1 >> val2       */
+
+                       s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
+                       M_AND_IMM(s2, 0x1f, REG_ITMP3);
+                       M_SRA(s1, REG_ITMP3, d);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_ISHRCONST:  /* ..., value  ==> ..., value >> constant       */
+                                     /* val.i = constant                             */
+
+                       s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
+                       M_SRA_IMM(s1, iptr->val.i & 0x1f, d);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_IUSHR:      /* ..., val1, val2  ==> ..., val1 >>> val2      */
+
+                       s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
+                       M_AND_IMM(s2, 0x1f, REG_ITMP2);
+                       M_SRL(s1, REG_ITMP2, d);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_IUSHRCONST: /* ..., value  ==> ..., value >>> constant      */
+                                     /* val.i = constant                             */
+
+                       s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
+                       if (iptr->val.i & 0x1f) {
+                               M_SRL_IMM(s1, iptr->val.i & 0x1f, d);
+                       } else {
+                               M_INTMOVE(s1, d);
+                       }
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_IAND:       /* ..., val1, val2  ==> ..., val1 & val2        */
+
+                       s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
+                       M_AND(s1, s2, d);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_IANDCONST:  /* ..., value  ==> ..., value & constant        */
+                                     /* val.i = constant                             */
+
+                       s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
+                       if ((iptr->val.i >= 0) && (iptr->val.i <= 65535)) {
+                               M_AND_IMM(s1, iptr->val.i, d);
+                               }
+                       /*
+                       else if (iptr->val.i == 0xffffff) {
+                               M_RLWINM(s1, 0, 8, 31, d);
+                               }
+                       */
+                       else {
+                               ICONST(REG_ITMP3, iptr->val.i);
+                               M_AND(s1, REG_ITMP3, d);
+                       }
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_LAND:       /* ..., val1, val2  ==> ..., val1 & val2        */
+
+                       s1 = emit_load_s1_low(jd, iptr, src->prev, REG_ITMP1);
+                       s2 = emit_load_s2_low(jd, iptr, src, REG_ITMP2);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP1));
+                       M_AND(s1, s2, GET_LOW_REG(d));
+                       s1 = emit_load_s1_high(jd, iptr, src->prev, REG_ITMP1);
+                       s2 = emit_load_s2_high(jd, iptr, src, REG_ITMP3);   /* don't use REG_ITMP2 */
+                       M_AND(s1, s2, GET_HIGH_REG(d));
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_LANDCONST:  /* ..., value  ==> ..., value & constant        */
+                                     /* val.l = constant                             */
+
+                       s3 = iptr->val.l & 0xffffffff;
+                       s1 = emit_load_s1_low(jd, iptr, src, REG_ITMP1);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP1));
+                       if ((s3 >= 0) && (s3 <= 65535)) {
+                               M_AND_IMM(s1, s3, GET_LOW_REG(d));
+                       } else {
+                               ICONST(REG_ITMP3, s3);
+                               M_AND(s1, REG_ITMP3, GET_LOW_REG(d));
+                       }
+                       s1 = emit_load_s1_high(jd, iptr, src, REG_ITMP1);
+                       s3 = iptr->val.l >> 32;
+                       if ((s3 >= 0) && (s3 <= 65535)) {
+                               M_AND_IMM(s1, s3, GET_HIGH_REG(d));
+                       } else {
+                               ICONST(REG_ITMP3, s3);                 /* don't use REG_ITMP2 */
+                               M_AND(s1, REG_ITMP3, GET_HIGH_REG(d));
+                       }
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_IREMPOW2:   /* ..., value  ==> ..., value % constant        */
+                                     /* val.i = constant                             */
+
+                       s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
+                       M_MOV(s1, REG_ITMP2);
+                       M_CMPI(s1, 0);
+                       M_BGE(1 + 2*(iptr->val.i >= 32768));
+                       if (iptr->val.i >= 32768) {
+                               M_ADDIS(REG_ZERO, iptr->val.i >> 16, REG_ITMP2);
+                               M_OR_IMM(REG_ITMP2, iptr->val.i, REG_ITMP2);
+                               M_IADD(s1, REG_ITMP2, REG_ITMP2);
+                       } else {
+                               M_IADD_IMM(s1, iptr->val.i, REG_ITMP2);
+                       }
+                       {
+                               int b=0, m = iptr->val.i;
+                               while (m >>= 1)
+                                       ++b;
+                               M_RLWINM(REG_ITMP2, 0, 0, 30-b, REG_ITMP2);
+                       }
+                       M_ISUB(s1, REG_ITMP2, d);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_IOR:        /* ..., val1, val2  ==> ..., val1 | val2        */
+
+                       s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
+                       M_OR(s1, s2, d);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_IORCONST:   /* ..., value  ==> ..., value | constant        */
+                                     /* val.i = constant                             */
+
+                       s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
+                       if ((iptr->val.i >= 0) && (iptr->val.i <= 65535)) {
+                               M_OR_IMM(s1, iptr->val.i, d);
+                       } else {
+                               ICONST(REG_ITMP3, iptr->val.i);
+                               M_OR(s1, REG_ITMP3, d);
+                       }
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_LOR:       /* ..., val1, val2  ==> ..., val1 | val2        */
+
+                       s1 = emit_load_s1_low(jd, iptr, src->prev, REG_ITMP1);
+                       s2 = emit_load_s2_low(jd, iptr, src, REG_ITMP2);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP1));
+                       M_OR(s1, s2, GET_LOW_REG(d));
+                       s1 = emit_load_s1_high(jd, iptr, src->prev, REG_ITMP1);
+                       s2 = emit_load_s2_high(jd, iptr, src, REG_ITMP3);   /* don't use REG_ITMP2 */
+                       M_OR(s1, s2, GET_HIGH_REG(d));
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_LORCONST:   /* ..., value  ==> ..., value | constant        */
+                                     /* val.l = constant                             */
+
+                       s3 = iptr->val.l & 0xffffffff;
+                       s1 = emit_load_s1_low(jd, iptr, src, REG_ITMP1);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP1));
+                       if ((s3 >= 0) && (s3 <= 65535)) {
+                               M_OR_IMM(s1, s3, GET_LOW_REG(d));
+                       } else {
+                               ICONST(REG_ITMP3, s3);
+                               M_OR(s1, REG_ITMP3, GET_LOW_REG(d));
+                       }
+                       s1 = emit_load_s1_high(jd, iptr, src, REG_ITMP1);
+                       s3 = iptr->val.l >> 32;
+                       if ((s3 >= 0) && (s3 <= 65535)) {
+                               M_OR_IMM(s1, s3, GET_HIGH_REG(d));
+                       } else {
+                               ICONST(REG_ITMP3, s3);                 /* don't use REG_ITMP2 */
+                               M_OR(s1, REG_ITMP3, GET_HIGH_REG(d));
+                       }
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_IXOR:       /* ..., val1, val2  ==> ..., val1 ^ val2        */
+
+                       s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
+                       M_XOR(s1, s2, d);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_IXORCONST:  /* ..., value  ==> ..., value ^ constant        */
+                                     /* val.i = constant                             */
+
+                       s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
+                       if ((iptr->val.i >= 0) && (iptr->val.i <= 65535)) {
+                               M_XOR_IMM(s1, iptr->val.i, d);
+                       } else {
+                               ICONST(REG_ITMP3, iptr->val.i);
+                               M_XOR(s1, REG_ITMP3, d);
+                       }
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_LXOR:       /* ..., val1, val2  ==> ..., val1 ^ val2        */
+
+                       s1 = emit_load_s1_low(jd, iptr, src->prev, REG_ITMP1);
+                       s2 = emit_load_s2_low(jd, iptr, src, REG_ITMP2);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP1));
+                       M_XOR(s1, s2, GET_LOW_REG(d));
+                       s1 = emit_load_s1_high(jd, iptr, src->prev, REG_ITMP1);
+                       s2 = emit_load_s2_high(jd, iptr, src, REG_ITMP3);   /* don't use REG_ITMP2 */
+                       M_XOR(s1, s2, GET_HIGH_REG(d));
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_LXORCONST:  /* ..., value  ==> ..., value ^ constant        */
+                                     /* val.l = constant                             */
+
+                       s3 = iptr->val.l & 0xffffffff;
+                       s1 = emit_load_s1_low(jd, iptr, src, REG_ITMP1);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP1));
+                       if ((s3 >= 0) && (s3 <= 65535)) {
+                               M_XOR_IMM(s1, s3, GET_LOW_REG(d));
+                       } else {
+                               ICONST(REG_ITMP3, s3);
+                               M_XOR(s1, REG_ITMP3, GET_LOW_REG(d));
+                       }
+                       s1 = emit_load_s1_high(jd, iptr, src, REG_ITMP1);
+                       s3 = iptr->val.l >> 32;
+                       if ((s3 >= 0) && (s3 <= 65535)) {
+                               M_XOR_IMM(s1, s3, GET_HIGH_REG(d));
+                       } else {
+                               ICONST(REG_ITMP3, s3);                 /* don't use REG_ITMP2 */
+                               M_XOR(s1, REG_ITMP3, GET_HIGH_REG(d));
+                       }
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_LCMP:       /* ..., val1, val2  ==> ..., val1 cmp val2      */
+                       /*******************************************************************
+                TODO: CHANGE THIS TO A VERSION THAT WORKS !!!
+                       *******************************************************************/
+                       s1 = emit_load_s1_high(jd, iptr, src->prev, REG_ITMP3);
+                       s2 = emit_load_s2_high(jd, iptr, src, REG_ITMP2);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
+                       {
+                               int tempreg = false;
+                               int dreg;
+                               u1  *br1;
+
+                               if (src->prev->flags & INMEMORY) {
+                                       tempreg = tempreg || (d == REG_ITMP3) || (d == REG_ITMP2);
+                               } else {
+                                       tempreg = tempreg || (d == GET_HIGH_REG(src->prev->regoff))
+                                                       || (d == GET_LOW_REG(src->prev->regoff));
+                               }
+                               if (src->flags & INMEMORY) {
+                                       tempreg = tempreg || (d == REG_ITMP3) || (d == REG_ITMP2);
+                               } else {
+                                       tempreg = tempreg || (d == GET_HIGH_REG(src->regoff))
+                                 || (d == GET_LOW_REG(src->regoff));
+                               }
+
+                               dreg = tempreg ? REG_ITMP1 : d;
+                               M_IADD_IMM(REG_ZERO, 1, dreg);
+                               M_CMP(s1, s2);
+                               M_BGT(0);
+                               br1 = cd->mcodeptr;
+                               M_BLT(0);
+                               s1 = emit_load_s1_low(jd, iptr, src->prev, REG_ITMP3);
+                               s2 = emit_load_s2_low(jd, iptr, src, REG_ITMP2);
+                               M_CMPU(s1, s2);
+                               M_BGT(3);
+                               M_BEQ(1);
+                               M_IADD_IMM(dreg, -1, dreg);
+                               M_IADD_IMM(dreg, -1, dreg);
+                               gen_resolvebranch(br1, br1, cd->mcodeptr);
+                               gen_resolvebranch(br1 + 1 * 4, br1 + 1 * 4, cd->mcodeptr - 2 * 4);
+                               M_INTMOVE(dreg, d);
+                       }
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_IINC:       /* ..., value  ==> ..., value + constant        */
+                                     /* op1 = variable, val.i = constant             */
+
+                       var = &(rd->locals[iptr->op1][TYPE_INT]);
+                       if (var->flags & INMEMORY) {
+                               s1 = REG_ITMP1;
+                               M_ILD(s1, REG_SP, var->regoff * 4);
+                       } else
+                               s1 = var->regoff;
+                       {
+                               u4 m = iptr->val.i;
+                               if (m & 0x8000)
+                                       m += 65536;
+                               if (m & 0xffff0000)
+                                       M_ADDIS(s1, m >> 16, s1);
+                               if (m & 0xffff)
+                                       M_IADD_IMM(s1, m & 0xffff, s1);
+                       }
+                       if (var->flags & INMEMORY)
+                               M_IST(s1, REG_SP, var->regoff * 4);
+                       break;
+
+
+               /* floating operations ************************************************/
+
+               case ICMD_FNEG:       /* ..., value  ==> ..., - value                 */
+
+                       s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
+                       M_FMOVN(s1, d);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_DNEG:       /* ..., value  ==> ..., - value                 */
+
+                       s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
+                       M_FMOVN(s1, d);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_FADD:       /* ..., val1, val2  ==> ..., val1 + val2        */
+
+                       s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
+                       s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
+                       M_FADD(s1, s2, d);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_DADD:       /* ..., val1, val2  ==> ..., val1 + val2        */
+
+                       s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
+                       s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
+                       M_DADD(s1, s2, d);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_FSUB:       /* ..., val1, val2  ==> ..., val1 - val2        */
+
+                       s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
+                       s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
+                       M_FSUB(s1, s2, d);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_DSUB:       /* ..., val1, val2  ==> ..., val1 - val2        */
+
+                       s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
+                       s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
+                       M_DSUB(s1, s2, d);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_FMUL:       /* ..., val1, val2  ==> ..., val1 * val2        */
+
+                       s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
+                       s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
+                       M_FMUL(s1, s2, d);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_DMUL:       /* ..., val1, val2  ==> ..., val1 * val2        */
+
+                       s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
+                       s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
+                       M_DMUL(s1, s2, d);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_FDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
+
+                       s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
+                       s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
+                       M_FDIV(s1, s2, d);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_DDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
+
+                       s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
+                       s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
+                       M_DDIV(s1, s2, d);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+               
+               case ICMD_F2I:       /* ..., value  ==> ..., (int) value              */
+               case ICMD_D2I:
+
+                       s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
+                       M_CLR(d);
+                       disp = dseg_addfloat(cd, 0.0);
+                       M_FLD(REG_FTMP2, REG_PV, disp);
+                       M_FCMPU(s1, REG_FTMP2);
+                       M_BNAN(4);
+                       disp = dseg_adds4(cd, 0);
+                       M_CVTDL_C(s1, REG_FTMP1);
+                       M_LDA(REG_ITMP1, REG_PV, disp);
+                       M_STFIWX(REG_FTMP1, 0, REG_ITMP1);
+                       M_ILD(d, REG_PV, disp);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+               
+               case ICMD_F2D:       /* ..., value  ==> ..., (double) value           */
+
+                       s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
+                       M_FLTMOVE(s1, d);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+                                       
+               case ICMD_D2F:       /* ..., value  ==> ..., (double) value           */
+
+                       s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
+                       M_CVTDF(s1, d);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+               
+               case ICMD_FCMPL:      /* ..., val1, val2  ==> ..., val1 fcmpg val2    */
+               case ICMD_DCMPL:      /* == => 0, < => 1, > => -1                     */
+
+
+                       s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
+                       s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
+                       M_FCMPU(s2, s1);
+                       M_IADD_IMM(REG_ZERO, -1, d);
+                       M_BNAN(4);
+                       M_BGT(3);
+                       M_IADD_IMM(REG_ZERO, 0, d);
+                       M_BGE(1);
+                       M_IADD_IMM(REG_ZERO, 1, d);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_FCMPG:      /* ..., val1, val2  ==> ..., val1 fcmpl val2    */
+               case ICMD_DCMPG:      /* == => 0, < => 1, > => -1                     */
+
+                       s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
+                       s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
+                       M_FCMPU(s1, s2);
+                       M_IADD_IMM(REG_ZERO, 1, d);
+                       M_BNAN(4);
+                       M_BGT(3);
+                       M_IADD_IMM(REG_ZERO, 0, d);
+                       M_BGE(1);
+                       M_IADD_IMM(REG_ZERO, -1, d);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+                       
+               case ICMD_IF_FCMPEQ:    /* ..., value, value ==> ...                  */
+               case ICMD_IF_DCMPEQ:
+
+                       s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
+                       s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
+                       M_FCMPU(s1, s2);
+                       M_BNAN(1);
+                       M_BEQ(0);
+                       codegen_addreference(cd, (basicblock *) iptr->target);
+                       break;
+
+               case ICMD_IF_FCMPNE:    /* ..., value, value ==> ...                  */
+               case ICMD_IF_DCMPNE:
+
+                       s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
+                       s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
+                       M_FCMPU(s1, s2);
+                       M_BNAN(0);
+                       codegen_addreference(cd, (basicblock *) iptr->target);
+                       M_BNE(0);
+                       codegen_addreference(cd, (basicblock *) iptr->target);
+                       break;
+
+
+               case ICMD_IF_FCMPL_LT:  /* ..., value, value ==> ...                  */
+               case ICMD_IF_DCMPL_LT:
+
+                       s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
+                       s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
+                       M_FCMPU(s1, s2);
+                       M_BNAN(0);
+                       codegen_addreference(cd, (basicblock *) iptr->target);
+                       M_BLT(0);
+                       codegen_addreference(cd, (basicblock *) iptr->target);
+                       break;
+
+               case ICMD_IF_FCMPL_GT:  /* ..., value, value ==> ...                  */
+               case ICMD_IF_DCMPL_GT:
+
+                       s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
+                       s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
+                       M_FCMPU(s1, s2);
+                       M_BNAN(1);
+                       M_BGT(0);
+                       codegen_addreference(cd, (basicblock *) iptr->target);
+                       break;
+
+               case ICMD_IF_FCMPL_LE:  /* ..., value, value ==> ...                  */
+               case ICMD_IF_DCMPL_LE:
+
+                       s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
+                       s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
+                       M_FCMPU(s1, s2);
+                       M_BNAN(0);
+                       codegen_addreference(cd, (basicblock *) iptr->target);
+                       M_BLE(0);
+                       codegen_addreference(cd, (basicblock *) iptr->target);
+                       break;
+
+               case ICMD_IF_FCMPL_GE:  /* ..., value, value ==> ...                  */
+               case ICMD_IF_DCMPL_GE:
+
+                       s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
+                       s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
+                       M_FCMPU(s1, s2);
+                       M_BNAN(1);
+                       M_BGE(0);
+                       codegen_addreference(cd, (basicblock *) iptr->target);
+                       break;
+
+               case ICMD_IF_FCMPG_LT:  /* ..., value, value ==> ...                  */
+               case ICMD_IF_DCMPG_LT:
+
+                       s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
+                       s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
+                       M_FCMPU(s1, s2);
+                       M_BNAN(1);
+                       M_BLT(0);
+                       codegen_addreference(cd, (basicblock *) iptr->target);
+                       break;
+
+               case ICMD_IF_FCMPG_GT:  /* ..., value, value ==> ...                  */
+               case ICMD_IF_DCMPG_GT:
+
+                       s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
+                       s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
+                       M_FCMPU(s1, s2);
+                       M_BNAN(0);
+                       codegen_addreference(cd, (basicblock *) iptr->target);
+                       M_BGT(0);
+                       codegen_addreference(cd, (basicblock *) iptr->target);
+                       break;
+
+               case ICMD_IF_FCMPG_LE:  /* ..., value, value ==> ...                  */
+               case ICMD_IF_DCMPG_LE:
+
+                       s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
+                       s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
+                       M_FCMPU(s1, s2);
+                       M_BNAN(1);
+                       M_BLE(0);
+                       codegen_addreference(cd, (basicblock *) iptr->target);
+                       break;
+
+               case ICMD_IF_FCMPG_GE:  /* ..., value, value ==> ...                  */
+               case ICMD_IF_DCMPG_GE:
+
+                       s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
+                       s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
+                       M_FCMPU(s1, s2);
+                       M_BNAN(0);
+                       codegen_addreference(cd, (basicblock *) iptr->target);
+                       M_BGE(0);
+                       codegen_addreference(cd, (basicblock *) iptr->target);
+                       break;
+
+
+               /* memory operations **************************************************/
+
+               case ICMD_ARRAYLENGTH: /* ..., arrayref  ==> ..., length              */
+
+                       s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
+                       gen_nullptr_check(s1);
+                       M_ILD(d, s1, OFFSET(java_arrayheader, size));
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_BALOAD:     /* ..., arrayref, index  ==> ..., value         */
+
+                       s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
+                       if (iptr->op1 == 0) {
+                               gen_nullptr_check(s1);
+                               gen_bound_check;
+                       }
+                       M_IADD_IMM(s2, OFFSET(java_chararray, data[0]), REG_ITMP2);
+                       M_LBZX(d, s1, REG_ITMP2);
+                       M_BSEXT(d, d);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;                  
+
+               case ICMD_CALOAD:     /* ..., arrayref, index  ==> ..., value         */
+
+                       s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
+                       if (iptr->op1 == 0) {
+                               gen_nullptr_check(s1);
+                               gen_bound_check;
+                       }
+                       M_SLL_IMM(s2, 1, REG_ITMP2);
+                       M_IADD_IMM(REG_ITMP2, OFFSET(java_chararray, data[0]), REG_ITMP2);
+                       M_LHZX(d, s1, REG_ITMP2);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_SALOAD:     /* ..., arrayref, index  ==> ..., value         */
+
+                       s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
+                       if (iptr->op1 == 0) {
+                               gen_nullptr_check(s1);
+                               gen_bound_check;
+                       }
+                       M_SLL_IMM(s2, 1, REG_ITMP2);
+                       M_IADD_IMM(REG_ITMP2, OFFSET(java_shortarray, data[0]), REG_ITMP2);
+                       M_LHAX(d, s1, REG_ITMP2);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_IALOAD:     /* ..., arrayref, index  ==> ..., value         */
+
+                       s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
+                       if (iptr->op1 == 0) {
+                               gen_nullptr_check(s1);
+                               gen_bound_check;
+                       }
+                       M_SLL_IMM(s2, 2, REG_ITMP2);
+                       M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray, data[0]), REG_ITMP2);
+                       M_LWZX(d, s1, REG_ITMP2);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_LALOAD:     /* ..., arrayref, index  ==> ..., value         */
+
+                       s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP1));
+                       if (iptr->op1 == 0) {
+                               gen_nullptr_check(s1);
+                               gen_bound_check;
+                       }
+                       M_SLL_IMM(s2, 3, REG_ITMP2);
+                       M_IADD(s1, REG_ITMP2, REG_ITMP2);
+                       M_LLD_INTERN(d, REG_ITMP2, OFFSET(java_longarray, data[0]));
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_FALOAD:     /* ..., arrayref, index  ==> ..., value         */
+
+                       s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
+                       if (iptr->op1 == 0) {
+                               gen_nullptr_check(s1);
+                               gen_bound_check;
+                       }
+                       M_SLL_IMM(s2, 2, REG_ITMP2);
+                       M_IADD_IMM(REG_ITMP2, OFFSET(java_floatarray, data[0]), REG_ITMP2);
+                       M_LFSX(d, s1, REG_ITMP2);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_DALOAD:     /* ..., arrayref, index  ==> ..., value         */
+
+                       s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
+                       if (iptr->op1 == 0) {
+                               gen_nullptr_check(s1);
+                               gen_bound_check;
+                       }
+                       M_SLL_IMM(s2, 3, REG_ITMP2);
+                       M_IADD_IMM(REG_ITMP2, OFFSET(java_doublearray, data[0]), REG_ITMP2);
+                       M_LFDX(d, s1, REG_ITMP2);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_AALOAD:     /* ..., arrayref, index  ==> ..., value         */
+
+                       s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
+                       if (iptr->op1 == 0) {
+                               gen_nullptr_check(s1);
+                               gen_bound_check;
+                       }
+                       M_SLL_IMM(s2, 2, REG_ITMP2);
+                       M_IADD_IMM(REG_ITMP2, OFFSET(java_objectarray, data[0]), REG_ITMP2);
+                       M_LWZX(d, s1, REG_ITMP2);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+
+               case ICMD_BASTORE:    /* ..., arrayref, index, value  ==> ...         */
+
+                       s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
+                       if (iptr->op1 == 0) {
+                               gen_nullptr_check(s1);
+                               gen_bound_check;
+                       }
+                       s3 = emit_load_s3(jd, iptr, src, REG_ITMP3);
+                       M_IADD_IMM(s2, OFFSET(java_bytearray, data[0]), REG_ITMP2);
+                       M_STBX(s3, s1, REG_ITMP2);
+                       break;
+
+               case ICMD_CASTORE:    /* ..., arrayref, index, value  ==> ...         */
+
+                       s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
+                       if (iptr->op1 == 0) {
+                               gen_nullptr_check(s1);
+                               gen_bound_check;
+                       }
+                       s3 = emit_load_s3(jd, iptr, src, REG_ITMP3);
+                       M_SLL_IMM(s2, 1, REG_ITMP2);
+                       M_IADD_IMM(REG_ITMP2, OFFSET(java_chararray, data[0]), REG_ITMP2);
+                       M_STHX(s3, s1, REG_ITMP2);
+                       break;
+
+               case ICMD_SASTORE:    /* ..., arrayref, index, value  ==> ...         */
+
+                       s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
+                       if (iptr->op1 == 0) {
+                               gen_nullptr_check(s1);
+                               gen_bound_check;
+                       }
+                       s3 = emit_load_s3(jd, iptr, src, REG_ITMP3);
+                       M_SLL_IMM(s2, 1, REG_ITMP2);
+                       M_IADD_IMM(REG_ITMP2, OFFSET(java_shortarray, data[0]), REG_ITMP2);
+                       M_STHX(s3, s1, REG_ITMP2);
+                       break;
+
+               case ICMD_IASTORE:    /* ..., arrayref, index, value  ==> ...         */
+
+                       s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
+                       if (iptr->op1 == 0) {
+                               gen_nullptr_check(s1);
+                               gen_bound_check;
+                       }
+                       s3 = emit_load_s3(jd, iptr, src, REG_ITMP3);
+                       M_SLL_IMM(s2, 2, REG_ITMP2);
+                       M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray, data[0]), REG_ITMP2);
+                       M_STWX(s3, s1, REG_ITMP2);
+                       break;
+
+               case ICMD_LASTORE:    /* ..., arrayref, index, value  ==> ...         */
+
+                       s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
+                       if (iptr->op1 == 0) {
+                               gen_nullptr_check(s1);
+                               gen_bound_check;
+                       }
+                       s3 = emit_load_s3_high(jd, iptr, src, REG_ITMP3);
+                       M_SLL_IMM(s2, 3, REG_ITMP2);
+                       M_IADD_IMM(REG_ITMP2, OFFSET(java_longarray, data[0]), REG_ITMP2);
+                       M_STWX(s3, s1, REG_ITMP2);
+                       M_IADD_IMM(REG_ITMP2, 4, REG_ITMP2);
+                       s3 = emit_load_s3_low(jd, iptr, src, REG_ITMP3);
+                       M_STWX(s3, s1, REG_ITMP2);
+                       break;
+
+               case ICMD_FASTORE:    /* ..., arrayref, index, value  ==> ...         */
+
+                       s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
+                       if (iptr->op1 == 0) {
+                               gen_nullptr_check(s1);
+                               gen_bound_check;
+                       }
+                       s3 = emit_load_s3(jd, iptr, src, REG_FTMP3);
+                       M_SLL_IMM(s2, 2, REG_ITMP2);
+                       M_IADD_IMM(REG_ITMP2, OFFSET(java_floatarray, data[0]), REG_ITMP2);
+                       M_STFSX(s3, s1, REG_ITMP2);
+                       break;
+
+               case ICMD_DASTORE:    /* ..., arrayref, index, value  ==> ...         */
+
+                       s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
+                       if (iptr->op1 == 0) {
+                               gen_nullptr_check(s1);
+                               gen_bound_check;
+                       }
+                       s3 = emit_load_s3(jd, iptr, src, REG_FTMP3);
+                       M_SLL_IMM(s2, 3, REG_ITMP2);
+                       M_IADD_IMM(REG_ITMP2, OFFSET(java_doublearray, data[0]), REG_ITMP2);
+                       M_STFDX(s3, s1, REG_ITMP2);
+                       break;
+
+               case ICMD_AASTORE:    /* ..., arrayref, index, value  ==> ...         */
+
+                       s1 = emit_load_s1(jd, iptr, src->prev->prev, rd->argintregs[0]);
+                       s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
+                       if (iptr->op1 == 0) {
+                               gen_nullptr_check(s1);
+                               gen_bound_check;
+                       }
+                       s3 = emit_load_s3(jd, iptr, src, rd->argintregs[1]);
+
+                       disp = dseg_addaddress(cd, BUILTIN_canstore);
+                       M_ALD(REG_ITMP3, REG_PV, disp);
+                       M_MTCTR(REG_ITMP3);
+
+                       M_INTMOVE(s1, rd->argintregs[0]);
+                       M_INTMOVE(s3, rd->argintregs[1]);
+
+                       M_JSR;
+                       M_TST(REG_RESULT);
+                       M_BEQ(0);
+                       codegen_add_arraystoreexception_ref(cd);
+
+                       s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
+                       s3 = emit_load_s3(jd, iptr, src, REG_ITMP3);
+                       M_SLL_IMM(s2, 2, REG_ITMP2);
+                       M_IADD_IMM(REG_ITMP2, OFFSET(java_objectarray, data[0]), REG_ITMP2);
+                       M_STWX(s3, s1, REG_ITMP2);
+                       break;
+
+
+               case ICMD_GETSTATIC:  /* ...  ==> ..., value                          */
+                                     /* op1 = type, val.a = field address            */
+
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                               disp = dseg_addaddress(cd, NULL);
+
+                               codegen_addpatchref(cd, PATCHER_get_putstatic,
+                                                                       INSTRUCTION_UNRESOLVED_FIELD(iptr), disp);
+
+                               if (opt_showdisassemble)
+                                       M_NOP;
+
+                       } else {
+                               fieldinfo *fi = INSTRUCTION_RESOLVED_FIELDINFO(iptr);
+
+                               disp = dseg_addaddress(cd, &(fi->value));
+
+                               if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
+                                       codegen_addpatchref(cd, PATCHER_clinit, fi->class, disp);
+
+                                       if (opt_showdisassemble)
+                                               M_NOP;
+                               }
+                       }
+
+                       M_ALD(REG_ITMP1, REG_PV, disp);
+                       switch (iptr->op1) {
+                       case TYPE_INT:
+                               d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
+                               M_ILD_INTERN(d, REG_ITMP1, 0);
+                               break;
+                       case TYPE_LNG:
+                               d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP1));
+                               M_ILD_INTERN(GET_LOW_REG(d), REG_ITMP1, 4);/* keep this order */
+                               M_ILD_INTERN(GET_HIGH_REG(d), REG_ITMP1, 0);/*keep this order */
+                               break;
+                       case TYPE_ADR:
+                               d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
+                               M_ALD_INTERN(d, REG_ITMP1, 0);
+                               break;
+                       case TYPE_FLT:
+                               d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
+                               M_FLD_INTERN(d, REG_ITMP1, 0);
+                               break;
+                       case TYPE_DBL:                          
+                               d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
+                               M_DLD_INTERN(d, REG_ITMP1, 0);
+                               break;
+                       }
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_PUTSTATIC:  /* ..., value  ==> ...                          */
+                                     /* op1 = type, val.a = field address            */
+
+
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                               disp = dseg_addaddress(cd, NULL);
+
+                               codegen_addpatchref(cd, PATCHER_get_putstatic,
+                                                                       INSTRUCTION_UNRESOLVED_FIELD(iptr), disp);
+
+                               if (opt_showdisassemble)
+                                       M_NOP;
+
+                       } else {
+                               fieldinfo *fi = INSTRUCTION_RESOLVED_FIELDINFO(iptr);
+
+                               disp = dseg_addaddress(cd, &(fi->value));
+
+                               if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
+                                       codegen_addpatchref(cd, PATCHER_clinit, fi->class, disp);
+
+                                       if (opt_showdisassemble)
+                                               M_NOP;
+                               }
+                       }
+
+                       M_ALD(REG_ITMP1, REG_PV, disp);
+                       switch (iptr->op1) {
+                       case TYPE_INT:
+                               s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
+                               M_IST_INTERN(s2, REG_ITMP1, 0);
+                               break;
+                       case TYPE_LNG:
+                               s2 = emit_load_s2(jd, iptr, src, PACK_REGS(REG_ITMP2, REG_ITMP3));
+                               M_LST_INTERN(s2, REG_ITMP1, 0);
+                               break;
+                       case TYPE_ADR:
+                               s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
+                               M_AST_INTERN(s2, REG_ITMP1, 0);
+                               break;
+                       case TYPE_FLT:
+                               s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
+                               M_FST_INTERN(s2, REG_ITMP1, 0);
+                               break;
+                       case TYPE_DBL:
+                               s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
+                               M_DST_INTERN(s2, REG_ITMP1, 0);
+                               break;
+                       }
+                       break;
+
+
+               case ICMD_GETFIELD:   /* ...  ==> ..., value                          */
+                                     /* op1 = type, val.i = field offset             */
+
+                       s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
+                       gen_nullptr_check(s1);
+
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                               codegen_addpatchref(cd, PATCHER_get_putfield,
+                                                                       INSTRUCTION_UNRESOLVED_FIELD(iptr), 0);
+
+                               if (opt_showdisassemble)
+                                       M_NOP;
+
+                               disp = 0;
+
+                       } else {
+                               disp = INSTRUCTION_RESOLVED_FIELDINFO(iptr)->offset;
+                       }
+
+                       switch (iptr->op1) {
+                       case TYPE_INT:
+                               d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
+                               M_ILD(d, s1, disp);
+                               break;
+                       case TYPE_LNG:
+                               d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP1));
+                               if (GET_HIGH_REG(d) == s1) {
+                                       M_ILD(GET_LOW_REG(d), s1, disp + 4);
+                                       M_ILD(GET_HIGH_REG(d), s1, disp);
+                               } else {
+                                       M_ILD(GET_HIGH_REG(d), s1, disp);
+                                       M_ILD(GET_LOW_REG(d), s1, disp + 4);
+                               }
+                               break;
+                       case TYPE_ADR:
+                               d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
+                               M_ALD(d, s1, disp);
+                               break;
+                       case TYPE_FLT:
+                               d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
+                               M_FLD(d, s1, disp);
+                               break;
+                       case TYPE_DBL:                          
+                               d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
+                               M_DLD(d, s1, disp);
+                               break;
+                       }
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_PUTFIELD:   /* ..., value  ==> ...                          */
+                                     /* op1 = type, val.i = field offset             */
+
+                       s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
+                       gen_nullptr_check(s1);
+
+                       if (!IS_FLT_DBL_TYPE(iptr->op1)) {
+                               if (IS_2_WORD_TYPE(iptr->op1)) {
+                                       s2 = emit_load_s2(jd, iptr, src, PACK_REGS(REG_ITMP2, REG_ITMP3));
+                               } else {
+                                       s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
+                               }
+                       } else {
+                               s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
+                       }
+
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                               codegen_addpatchref(cd, PATCHER_get_putfield,
+                                                                       INSTRUCTION_UNRESOLVED_FIELD(iptr), 0);
+
+                               if (opt_showdisassemble)
+                                       M_NOP;
+
+                               disp = 0;
+
+                       } else {
+                               disp = INSTRUCTION_RESOLVED_FIELDINFO(iptr)->offset;
+                       }
+
+                       switch (iptr->op1) {
+                       case TYPE_INT:
+                               M_IST(s2, s1, disp);
+                               break;
+                       case TYPE_LNG:
+                               M_IST(GET_LOW_REG(s2), s1, disp + 4);      /* keep this order */
+                               M_IST(GET_HIGH_REG(s2), s1, disp);         /* keep this order */
+                               break;
+                       case TYPE_ADR:
+                               M_AST(s2, s1, disp);
+                               break;
+                       case TYPE_FLT:
+                               M_FST(s2, s1, disp);
+                               break;
+                       case TYPE_DBL:
+                               M_DST(s2, s1, disp);
+                               break;
+                       }
+                       break;
+
+
+               /* branch operations **************************************************/
+
+               case ICMD_ATHROW:       /* ..., objectref ==> ... (, objectref)       */
+
+                       s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
+                       M_INTMOVE(s1, REG_ITMP1_XPTR);
+
+#ifdef ENABLE_VERIFIER
+                       if (iptr->val.a) {
+                               codegen_addpatchref(cd, PATCHER_athrow_areturn,
+                                                                       (unresolved_class *) iptr->val.a, 0);
+
+                               if (opt_showdisassemble)
+                                       M_NOP;
+                       }
+#endif /* ENABLE_VERIFIER */
+
+                       disp = dseg_addaddress(cd, asm_handle_exception);
+                       M_ALD(REG_ITMP2, REG_PV, disp);
+                       M_MTCTR(REG_ITMP2);
+
+                       if (m->isleafmethod) M_MFLR(REG_ITMP3);         /* save LR        */
+                       M_BL(0);                                        /* get current PC */
+                       M_MFLR(REG_ITMP2_XPC);
+                       if (m->isleafmethod) M_MTLR(REG_ITMP3);         /* restore LR     */
+                       M_RTS;                                          /* jump to CTR    */
+
+                       ALIGNCODENOP;
+                       break;
+
+               case ICMD_GOTO:         /* ... ==> ...                                */
+                                       /* op1 = target JavaVM pc                     */
+                       M_BR(0);
+                       codegen_addreference(cd, (basicblock *) iptr->target);
+                       ALIGNCODENOP;
+                       break;
+
+               case ICMD_JSR:          /* ... ==> ...                                */
+                                       /* op1 = target JavaVM pc                     */
+
+                       if (m->isleafmethod)
+                               M_MFLR(REG_ITMP2);
+                       M_BL(0);
+                       M_MFLR(REG_ITMP1);
+                       M_IADD_IMM(REG_ITMP1, m->isleafmethod ? 4*4 : 3*4, REG_ITMP1);
+                       if (m->isleafmethod)
+                               M_MTLR(REG_ITMP2);
+                       M_BR(0);
+                       codegen_addreference(cd, (basicblock *) iptr->target);
+                       break;
+                       
+               case ICMD_RET:          /* ... ==> ...                                */
+                                       /* op1 = local variable                       */
+
+                       var = &(rd->locals[iptr->op1][TYPE_ADR]);
+                       if (var->flags & INMEMORY) {
+                               M_ALD(REG_ITMP1, REG_SP, var->regoff * 4);
+                               M_MTCTR(REG_ITMP1);
+                       } else {
+                               M_MTCTR(var->regoff);
+                       }
+                       M_RTS;
+                       ALIGNCODENOP;
+                       break;
+
+               case ICMD_IFNULL:       /* ..., value ==> ...                         */
+                                       /* op1 = target JavaVM pc                     */
+
+                       s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
+                       M_TST(s1);
+                       M_BEQ(0);
+                       codegen_addreference(cd, (basicblock *) iptr->target);
+                       break;
+
+               case ICMD_IFNONNULL:    /* ..., value ==> ...                         */
+                                       /* op1 = target JavaVM pc                     */
+
+                       s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
+                       M_TST(s1);
+                       M_BNE(0);
+                       codegen_addreference(cd, (basicblock *) iptr->target);
+                       break;
+
+               case ICMD_IFLT:
+               case ICMD_IFLE:
+               case ICMD_IFNE:
+               case ICMD_IFGT:
+               case ICMD_IFGE:
+               case ICMD_IFEQ:         /* ..., value ==> ...                         */
+                                       /* op1 = target JavaVM pc, val.i = constant   */
+
+                       s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
+                       if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767))
+                               M_CMPI(s1, iptr->val.i);
+                       else {
+                               ICONST(REG_ITMP2, iptr->val.i);
+                               M_CMP(s1, REG_ITMP2);
+                       }
+                       switch (iptr->opc) {
+                       case ICMD_IFLT:
+                               M_BLT(0);
+                               break;
+                       case ICMD_IFLE:
+                               M_BLE(0);
+                               break;
+                       case ICMD_IFNE:
+                               M_BNE(0);
+                               break;
+                       case ICMD_IFGT:
+                               M_BGT(0);
+                               break;
+                       case ICMD_IFGE:
+                               M_BGE(0);
+                               break;
+                       case ICMD_IFEQ:
+                               M_BEQ(0);
+                               break;
+                       }
+                       codegen_addreference(cd, (basicblock *) iptr->target);
+                       break;
+
+
+               case ICMD_IF_LEQ:       /* ..., value ==> ...                         */
+                                       /* op1 = target JavaVM pc, val.l = constant   */
+
+                       s1 = emit_load_s1_low(jd, iptr, src, REG_ITMP1);
+                       s2 = emit_load_s2_high(jd, iptr, src, REG_ITMP2);
+                       if (iptr->val.l == 0) {
+                               M_OR_TST(s1, s2, REG_ITMP3);
+                       } else if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
+                               M_XOR_IMM(s2, 0, REG_ITMP2);
+                               M_XOR_IMM(s1, iptr->val.l & 0xffff, REG_ITMP1);
+                               M_OR_TST(REG_ITMP1, REG_ITMP2, REG_ITMP3);
+                       } else {
+                               ICONST(REG_ITMP3, iptr->val.l & 0xffffffff);
+                               M_XOR(s1, REG_ITMP3, REG_ITMP1);
+                               ICONST(REG_ITMP3, iptr->val.l >> 32);
+                               M_XOR(s2, REG_ITMP3, REG_ITMP2);
+                               M_OR_TST(REG_ITMP1, REG_ITMP2, REG_ITMP3);
+                       }
+                       M_BEQ(0);
+                       codegen_addreference(cd, (basicblock *) iptr->target);
+                       break;
+                       
+               case ICMD_IF_LLT:       /* ..., value ==> ...                         */
+                                       /* op1 = target JavaVM pc, val.l = constant   */
+                       s1 = emit_load_s1_low(jd, iptr, src, REG_ITMP1);
+                       s2 = emit_load_s2_high(jd, iptr, src, REG_ITMP2);
+                       if (iptr->val.l == 0) {
+                               /* if high word is less than zero, the whole long is too */
+                               M_CMPI(s2, 0);
+                       } else if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
+                               M_CMPI(s2, 0);
+                               M_BLT(0);
+                               codegen_addreference(cd, (basicblock *) iptr->target);
+                               M_BGT(2);
+                               M_CMPUI(s1, iptr->val.l & 0xffff);
+                       } else {
+                               ICONST(REG_ITMP3, iptr->val.l >> 32);
+                               M_CMP(s2, REG_ITMP3);
+                               M_BLT(0);
+                               codegen_addreference(cd, (basicblock *) iptr->target);
+                               M_BGT(3);
+                               ICONST(REG_ITMP3, iptr->val.l & 0xffffffff);
+                               M_CMPU(s1, REG_ITMP3);
+                       }
+                       M_BLT(0);
+                       codegen_addreference(cd, (basicblock *) iptr->target);
+                       break;
+                       
+               case ICMD_IF_LLE:       /* ..., value ==> ...                         */
+                                       /* op1 = target JavaVM pc, val.l = constant   */
+
+                       s1 = emit_load_s1_low(jd, iptr, src, REG_ITMP1);
+                       s2 = emit_load_s2_high(jd, iptr, src, REG_ITMP2);
+/*                     if (iptr->val.l == 0) { */
+/*                             M_OR(s1, s2, REG_ITMP3); */
+/*                             M_CMPI(REG_ITMP3, 0); */
+
+/*                     } else  */
+                       if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
+                               M_CMPI(s2, 0);
+                               M_BLT(0);
+                               codegen_addreference(cd, (basicblock *) iptr->target);
+                               M_BGT(2);
+                               M_CMPUI(s1, iptr->val.l & 0xffff);
+                       } else {
+                               ICONST(REG_ITMP3, iptr->val.l >> 32);
+                               M_CMP(s2, REG_ITMP3);
+                               M_BLT(0);
+                               codegen_addreference(cd, (basicblock *) iptr->target);
+                               M_BGT(3);
+                               ICONST(REG_ITMP3, iptr->val.l & 0xffffffff);
+                               M_CMPU(s1, REG_ITMP3);
+                       }
+                       M_BLE(0);
+                       codegen_addreference(cd, (basicblock *) iptr->target);
+                       break;
+                       
+               case ICMD_IF_LNE:       /* ..., value ==> ...                         */
+                                       /* op1 = target JavaVM pc, val.l = constant   */
+
+                       s1 = emit_load_s1_low(jd, iptr, src, REG_ITMP1);
+                       s2 = emit_load_s2_high(jd, iptr, src, REG_ITMP2);
+                       if (iptr->val.l == 0) {
+                               M_OR_TST(s1, s2, REG_ITMP3);
+                       } else if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
+                               M_XOR_IMM(s2, 0, REG_ITMP2);
+                               M_XOR_IMM(s1, iptr->val.l & 0xffff, REG_ITMP1);
+                               M_OR_TST(REG_ITMP1, REG_ITMP2, REG_ITMP3);
+                       } else {
+                               ICONST(REG_ITMP3, iptr->val.l & 0xffffffff);
+                               M_XOR(s1, REG_ITMP3, REG_ITMP1);
+                               ICONST(REG_ITMP3, iptr->val.l >> 32);
+                               M_XOR(s2, REG_ITMP3, REG_ITMP2);
+                               M_OR_TST(REG_ITMP1, REG_ITMP2, REG_ITMP3);
+                       }
+                       M_BNE(0);
+                       codegen_addreference(cd, (basicblock *) iptr->target);
+                       break;
+                       
+               case ICMD_IF_LGT:       /* ..., value ==> ...                         */
+                                       /* op1 = target JavaVM pc, val.l = constant   */
+
+                       s1 = emit_load_s1_low(jd, iptr, src, REG_ITMP1);
+                       s2 = emit_load_s2_high(jd, iptr, src, REG_ITMP2);
+/*                     if (iptr->val.l == 0) { */
+/*                             M_OR(s1, s2, REG_ITMP3); */
+/*                             M_CMPI(REG_ITMP3, 0); */
+
+/*                     } else  */
+                       if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
+                               M_CMPI(s2, 0);
+                               M_BGT(0);
+                               codegen_addreference(cd, (basicblock *) iptr->target);
+                               M_BLT(2);
+                               M_CMPUI(s1, iptr->val.l & 0xffff);
+                       } else {
+                               ICONST(REG_ITMP3, iptr->val.l >> 32);
+                               M_CMP(s2, REG_ITMP3);
+                               M_BGT(0);
+                               codegen_addreference(cd, (basicblock *) iptr->target);
+                               M_BLT(3);
+                               ICONST(REG_ITMP3, iptr->val.l & 0xffffffff);
+                               M_CMPU(s1, REG_ITMP3);
+                       }
+                       M_BGT(0);
+                       codegen_addreference(cd, (basicblock *) iptr->target);
+                       break;
+                       
+               case ICMD_IF_LGE:       /* ..., value ==> ...                         */
+                                       /* op1 = target JavaVM pc, val.l = constant   */
+
+                       s1 = emit_load_s1_low(jd, iptr, src, REG_ITMP1);
+                       s2 = emit_load_s2_high(jd, iptr, src, REG_ITMP2);
+                       if (iptr->val.l == 0) {
+                               /* if high word is greater equal zero, the whole long is too */
+                               M_CMPI(s2, 0);
+                       } else if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
+                               M_CMPI(s2, 0);
+                               M_BGT(0);
+                               codegen_addreference(cd, (basicblock *) iptr->target);
+                               M_BLT(2);
+                               M_CMPUI(s1, iptr->val.l & 0xffff);
+                       } else {
+                               ICONST(REG_ITMP3, iptr->val.l >> 32);
+                               M_CMP(s2, REG_ITMP3);
+                               M_BGT(0);
+                               codegen_addreference(cd, (basicblock *) iptr->target);
+                               M_BLT(3);
+                               ICONST(REG_ITMP3, iptr->val.l & 0xffffffff);
+                               M_CMPU(s1, REG_ITMP3);
+                       }
+                       M_BGE(0);
+                       codegen_addreference(cd, (basicblock *) iptr->target);
+                       break;
+
+               case ICMD_IF_ICMPEQ:    /* ..., value, value ==> ...                  */
+               case ICMD_IF_ACMPEQ:    /* op1 = target JavaVM pc                     */
+
+                       s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
+                       M_CMP(s1, s2);
+                       M_BEQ(0);
+                       codegen_addreference(cd, (basicblock *) iptr->target);
+                       break;
+
+               case ICMD_IF_LCMPEQ:    /* ..., value, value ==> ...                  */
+                                       /* op1 = target JavaVM pc                     */
+
+                       s1 = emit_load_s1_high(jd, iptr, src->prev, REG_ITMP1);
+                       s2 = emit_load_s2_high(jd, iptr, src, REG_ITMP2);
+                       M_CMP(s1, s2);
+                       /* load low-bits before the branch, so we know the distance */
+                       s1 = emit_load_s1_low(jd, iptr, src->prev, REG_ITMP1);
+                       s2 = emit_load_s2_low(jd, iptr, src, REG_ITMP2);
+                       M_BNE(2);
+                       M_CMP(s1, s2);
+                       M_BEQ(0);
+                       codegen_addreference(cd, (basicblock *) iptr->target);
+                       break;
+
+               case ICMD_IF_ICMPNE:    /* ..., value, value ==> ...                  */
+               case ICMD_IF_ACMPNE:    /* op1 = target JavaVM pc                     */
+
+                       s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
+                       M_CMP(s1, s2);
+                       M_BNE(0);
+                       codegen_addreference(cd, (basicblock *) iptr->target);
+                       break;
+
+               case ICMD_IF_LCMPNE:    /* ..., value, value ==> ...                  */
+                                       /* op1 = target JavaVM pc                     */
+
+                       s1 = emit_load_s1_high(jd, iptr, src->prev, REG_ITMP1);
+                       s2 = emit_load_s2_high(jd, iptr, src, REG_ITMP2);
+                       M_CMP(s1, s2);
+                       M_BNE(0);
+                       codegen_addreference(cd, (basicblock *) iptr->target);
+                       s1 = emit_load_s1_low(jd, iptr, src->prev, REG_ITMP1);
+                       s2 = emit_load_s2_low(jd, iptr, src, REG_ITMP2);
+                       M_CMP(s1, s2);
+                       M_BNE(0);
+                       codegen_addreference(cd, (basicblock *) iptr->target);
+                       break;
+
+               case ICMD_IF_ICMPLT:    /* ..., value, value ==> ...                  */
+                                       /* op1 = target JavaVM pc                     */
+
+                       s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
+                       M_CMP(s1, s2);
+                       M_BLT(0);
+                       codegen_addreference(cd, (basicblock *) iptr->target);
+                       break;
+
+               case ICMD_IF_LCMPLT:    /* ..., value, value ==> ...                  */
+                                       /* op1 = target JavaVM pc                     */
+
+                       s1 = emit_load_s1_high(jd, iptr, src->prev, REG_ITMP1);
+                       s2 = emit_load_s2_high(jd, iptr, src, REG_ITMP2);
+                       M_CMP(s1, s2);
+                       M_BLT(0);
+                       codegen_addreference(cd, (basicblock *) iptr->target);
+                       /* load low-bits before the branch, so we know the distance */
+                       s1 = emit_load_s1_low(jd, iptr, src->prev, REG_ITMP1);
+                       s2 = emit_load_s2_low(jd, iptr, src, REG_ITMP2);
+                       M_BGT(2);
+                       M_CMPU(s1, s2);
+                       M_BLT(0);
+                       codegen_addreference(cd, (basicblock *) iptr->target);
+                       break;
+
+               case ICMD_IF_ICMPGT:    /* ..., value, value ==> ...                  */
+                                       /* op1 = target JavaVM pc                     */
+
+                       s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
+                       M_CMP(s1, s2);
+                       M_BGT(0);
+                       codegen_addreference(cd, (basicblock *) iptr->target);
+                       break;
+
+               case ICMD_IF_LCMPGT:    /* ..., value, value ==> ...                  */
+                                       /* op1 = target JavaVM pc                     */
+
+                       s1 = emit_load_s1_high(jd, iptr, src->prev, REG_ITMP1);
+                       s2 = emit_load_s2_high(jd, iptr, src, REG_ITMP2);
+                       M_CMP(s1, s2);
+                       M_BGT(0);
+                       codegen_addreference(cd, (basicblock *) iptr->target);
+                       /* load low-bits before the branch, so we know the distance */  
+                       s1 = emit_load_s1_low(jd, iptr, src->prev, REG_ITMP1);
+                       s2 = emit_load_s2_low(jd, iptr, src, REG_ITMP2);
+                       M_BLT(2);
+                       M_CMPU(s1, s2);
+                       M_BGT(0);
+                       codegen_addreference(cd, (basicblock *) iptr->target);
+                       break;
+
+               case ICMD_IF_ICMPLE:    /* ..., value, value ==> ...                  */
+                                       /* op1 = target JavaVM pc                     */
+
+                       s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
+                       M_CMP(s1, s2);
+                       M_BLE(0);
+                       codegen_addreference(cd, (basicblock *) iptr->target);
+                       break;
+
+               case ICMD_IF_LCMPLE:    /* ..., value, value ==> ...                  */
+                                       /* op1 = target JavaVM pc                     */
+
+                       s1 = emit_load_s1_high(jd, iptr, src->prev, REG_ITMP1);
+                       s2 = emit_load_s2_high(jd, iptr, src, REG_ITMP2);
+                       M_CMP(s1, s2);
+                       M_BLT(0);
+                       codegen_addreference(cd, (basicblock *) iptr->target);
+                       /* load low-bits before the branch, so we know the distance */
+                       s1 = emit_load_s1_low(jd, iptr, src->prev, REG_ITMP1);
+                       s2 = emit_load_s2_low(jd, iptr, src, REG_ITMP2);
+                       M_BGT(2);
+                       M_CMPU(s1, s2);
+                       M_BLE(0);
+                       codegen_addreference(cd, (basicblock *) iptr->target);
+                       break;
+
+               case ICMD_IF_ICMPGE:    /* ..., value, value ==> ...                  */
+                                       /* op1 = target JavaVM pc                     */
+
+                       s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
+                       M_CMP(s1, s2);
+                       M_BGE(0);
+                       codegen_addreference(cd, (basicblock *) iptr->target);
+                       break;
+
+               case ICMD_IF_LCMPGE:    /* ..., value, value ==> ...                  */
+                                       /* op1 = target JavaVM pc                     */
+
+                       s1 = emit_load_s1_high(jd, iptr, src->prev, REG_ITMP1);
+                       s2 = emit_load_s2_high(jd, iptr, src, REG_ITMP2);
+                       M_CMP(s1, s2);
+                       M_BGT(0);
+                       codegen_addreference(cd, (basicblock *) iptr->target);
+                       /* load low-bits before the branch, so we know the distance */
+                       s1 = emit_load_s1_low(jd, iptr, src->prev, REG_ITMP1);
+                       s2 = emit_load_s2_low(jd, iptr, src, REG_ITMP2);
+                       M_BLT(2);
+                       M_CMPU(s1, s2);
+                       M_BGE(0);
+                       codegen_addreference(cd, (basicblock *) iptr->target);
+                       break;
+
+               case ICMD_IRETURN:      /* ..., retvalue ==> ...                      */
+
+                       s1 = emit_load_s1(jd, iptr, src, REG_RESULT);
+                       M_INTMOVE(s1, REG_RESULT);
+                       goto nowperformreturn;
+
+               case ICMD_ARETURN:      /* ..., retvalue ==> ...                      */
+
+                       s1 = emit_load_s1(jd, iptr, src, REG_RESULT);
+                       M_INTMOVE(s1, REG_RESULT);
+
+#ifdef ENABLE_VERIFIER
+                       if (iptr->val.a) {
+                               codegen_addpatchref(cd, PATCHER_athrow_areturn,
+                                                                       (unresolved_class *) iptr->val.a, 0);
+
+                               if (opt_showdisassemble)
+                                       M_NOP;
+                       }
+#endif /* ENABLE_VERIFIER */
+                       goto nowperformreturn;
+
+               case ICMD_LRETURN:      /* ..., retvalue ==> ...                      */
+
+                       /*s1 = emit_load_s1(jd, iptr, src, PACK_REGS(REG_RESULT2, REG_RESULT)); FIXME*/
+                       /*M_LNGMOVE(s1, PACK_REGS(REG_RESULT2, REG_RESULT)); FIXME*/
+                       goto nowperformreturn;
+
+               case ICMD_FRETURN:      /* ..., retvalue ==> ...                      */
+               case ICMD_DRETURN:
+
+                       s1 = emit_load_s1(jd, iptr, src, REG_FRESULT);
+                       M_FLTMOVE(s1, REG_FRESULT);
+                       goto nowperformreturn;
+
+               case ICMD_RETURN:      /* ...  ==> ...                                */
+
+nowperformreturn:
+                       {
+                       s4 i, p;
+                       
+                       p = stackframesize;
+
+                       /* call trace function */
+
+                       if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) {
+                               M_MFLR(REG_ZERO);
+                               M_LDA(REG_SP, REG_SP, -10 * 8);
+                               M_DST(REG_FRESULT, REG_SP, 48+0);
+                               M_IST(REG_RESULT, REG_SP, 48+8);
+                               M_AST(REG_ZERO, REG_SP, 48+12);
+                               /*M_IST(REG_RESULT2, REG_SP, 48+16); FIXME*/
+
+                               /* keep this order */
+                               switch (iptr->opc) {
+                               case ICMD_IRETURN:
+                               case ICMD_ARETURN:
+#if defined(__DARWIN__)
+                                       M_MOV(REG_RESULT, rd->argintregs[2]);
+                                       M_CLR(rd->argintregs[1]);
+#else
+                                       M_MOV(REG_RESULT, rd->argintregs[3]);
+                                       M_CLR(rd->argintregs[2]);
+#endif
+                                       break;
+
+                               case ICMD_LRETURN:
+#if defined(__DARWIN__)
+                                       /*M_MOV(REG_RESULT2, rd->argintregs[2]); FIXME */
+                                       M_MOV(REG_RESULT, rd->argintregs[1]);
+#else
+                                       /*M_MOV(REG_RESULT2, rd->argintregs[3]); FIXME*/
+                                       M_MOV(REG_RESULT, rd->argintregs[2]);
+#endif
+                                       break;
+                               }
+
+                               disp = dseg_addaddress(cd, m);
+                               M_ALD(rd->argintregs[0], REG_PV, disp);
+
+                               M_FLTMOVE(REG_FRESULT, rd->argfltregs[0]);
+                               M_FLTMOVE(REG_FRESULT, rd->argfltregs[1]);
+                               disp = dseg_addaddress(cd, builtin_displaymethodstop);
+                               M_ALD(REG_ITMP2, REG_PV, disp);
+                               M_MTCTR(REG_ITMP2);
+                               M_JSR;
+
+                               M_DLD(REG_FRESULT, REG_SP, 48+0);
+                               M_ILD(REG_RESULT, REG_SP, 48+8);
+                               M_ALD(REG_ZERO, REG_SP, 48+12);
+                               /*M_ILD(REG_RESULT2, REG_SP, 48+16); FIXME*/
+                               M_LDA(REG_SP, REG_SP, 10 * 8);
+                               M_MTLR(REG_ZERO);
+                       }
+                       
+#if defined(ENABLE_THREADS)
+                       if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
+                               disp = dseg_addaddress(cd, BUILTIN_monitorexit);
+                               M_ALD(REG_ITMP3, REG_PV, disp);
+                               M_MTCTR(REG_ITMP3);
+
+                               /* we need to save the proper return value */
+
+                               switch (iptr->opc) {
+                               case ICMD_LRETURN:
+                                       /*M_IST(REG_RESULT2, REG_SP, rd->memuse * 4 + 8); FIXME*/
+                                       /* fall through */
+                               case ICMD_IRETURN:
+                               case ICMD_ARETURN:
+                                       M_IST(REG_RESULT , REG_SP, rd->memuse * 4 + 4);
+                                       break;
+                               case ICMD_FRETURN:
+                                       M_FST(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
+                                       break;
+                               case ICMD_DRETURN:
+                                       M_DST(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
+                                       break;
+                               }
+
+                               M_ALD(rd->argintregs[0], REG_SP, rd->memuse * 4);
+                               M_JSR;
+
+                               /* and now restore the proper return value */
+
+                               switch (iptr->opc) {
+                               case ICMD_LRETURN:
+                                       /*M_ILD(REG_RESULT2, REG_SP, rd->memuse * 4 + 8); FIXME*/
+                                       /* fall through */
+                               case ICMD_IRETURN:
+                               case ICMD_ARETURN:
+                                       M_ILD(REG_RESULT , REG_SP, rd->memuse * 4 + 4);
+                                       break;
+                               case ICMD_FRETURN:
+                                       M_FLD(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
+                                       break;
+                               case ICMD_DRETURN:
+                                       M_DLD(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
+                                       break;
+                               }
+                       }
+#endif
+
+                       /* restore return address                                         */
+
+                       if (!m->isleafmethod) {
+                               /* ATTENTION: Don't use REG_ZERO (r0) here, as M_ALD
+                                  may have a displacement overflow. */
+
+                               M_ALD(REG_ITMP1, REG_SP, p * 4 + LA_LR_OFFSET);
+                               M_MTLR(REG_ITMP1);
+                       }
+
+                       /* restore saved registers                                        */
+
+                       for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
+                               p--; M_ILD(rd->savintregs[i], REG_SP, p * 4);
+                       }
+                       for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
+                               p -= 2; M_DLD(rd->savfltregs[i], REG_SP, p * 4);
+                       }
+
+                       /* deallocate stack                                               */
+
+                       if (stackframesize)
+                               M_LDA(REG_SP, REG_SP, stackframesize * 4);
+
+                       M_RET;
+                       ALIGNCODENOP;
+                       }
+                       break;
+
+
+               case ICMD_TABLESWITCH:  /* ..., index ==> ...                         */
+                       {
+                       s4 i, l, *s4ptr;
+                       void **tptr;
+
+                       tptr = (void **) iptr->target;
+
+                       s4ptr = iptr->val.a;
+                       l = s4ptr[1];                          /* low     */
+                       i = s4ptr[2];                          /* high    */
+                       
+                       s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
+                       if (l == 0) {
+                               M_INTMOVE(s1, REG_ITMP1);
+                       } else if (l <= 32768) {
+                               M_LDA(REG_ITMP1, s1, -l);
+                       } else {
+                               ICONST(REG_ITMP2, l);
+                               M_ISUB(s1, REG_ITMP2, REG_ITMP1);
+                       }
+                       i = i - l + 1;
+
+                       /* range check */
+
+                       M_CMPUI(REG_ITMP1, i - 1);
+                       M_BGT(0);
+                       codegen_addreference(cd, (basicblock *) tptr[0]);
+
+                       /* build jump table top down and use address of lowest entry */
+
+                       /* s4ptr += 3 + i; */
+                       tptr += i;
+
+                       while (--i >= 0) {
+                               dseg_addtarget(cd, (basicblock *) tptr[0]); 
+                               --tptr;
+                       }
+                       }
+
+                       /* length of dataseg after last dseg_addtarget is used by load */
+
+                       M_SLL_IMM(REG_ITMP1, 2, REG_ITMP1);
+                       M_IADD(REG_ITMP1, REG_PV, REG_ITMP2);
+                       M_ALD(REG_ITMP2, REG_ITMP2, -(cd->dseglen));
+                       M_MTCTR(REG_ITMP2);
+                       M_RTS;
+                       ALIGNCODENOP;
+                       break;
+
+
+               case ICMD_LOOKUPSWITCH: /* ..., key ==> ...                           */
+                       {
+                       s4 i, l, val, *s4ptr;
+                       void **tptr;
+
+                       tptr = (void **) iptr->target;
+
+                       s4ptr = iptr->val.a;
+                       l = s4ptr[0];                          /* default  */
+                       i = s4ptr[1];                          /* count    */
+                       
+                       MCODECHECK((i<<2)+8);
+                       s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
+                       while (--i >= 0) {
+                               s4ptr += 2;
+                               ++tptr;
+
+                               val = s4ptr[0];
+                               if ((val >= -32768) && (val <= 32767)) {
+                                       M_CMPI(s1, val);
+                               } else {
+                                       a = dseg_adds4(cd, val);
+                                       M_ILD(REG_ITMP2, REG_PV, a);
+                                       M_CMP(s1, REG_ITMP2);
+                               }
+                               M_BEQ(0);
+                               codegen_addreference(cd, (basicblock *) tptr[0]); 
+                       }
+
+                       M_BR(0);
+                       tptr = (void **) iptr->target;
+                       codegen_addreference(cd, (basicblock *) tptr[0]);
+
+                       ALIGNCODENOP;
+                       break;
+                       }
+
+
+               case ICMD_BUILTIN:      /* ..., [arg1, [arg2 ...]] ==> ...            */
+                                       /* op1 = arg count val.a = builtintable entry */
+
+                       bte = iptr->val.a;
+                       md = bte->md;
+                       goto gen_method;
+
+               case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ...            */
+                                       /* op1 = arg count, val.a = method pointer    */
+
+               case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
+               case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer    */
+               case ICMD_INVOKEINTERFACE:
+
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                               md = INSTRUCTION_UNRESOLVED_METHOD(iptr)->methodref->parseddesc.md;
+                               lm = NULL;
+                       }
+                       else {
+                               lm = INSTRUCTION_RESOLVED_METHODINFO(iptr);
+                               md = lm->parseddesc;
+                       }
+
+gen_method:
+                       s3 = md->paramcount;
+
+                       MCODECHECK((s3 << 1) + 64);
+
+                       /* copy arguments to registers or stack location */
+
+                       for (s3 = s3 - 1; s3 >= 0; s3--, src = src->prev) {
+                               if (src->varkind == ARGVAR)
+                                       continue;
+                               if (IS_INT_LNG_TYPE(src->type)) {
+                                       if (!md->params[s3].inmemory) {
+                                               if (IS_2_WORD_TYPE(src->type)) {
+                                                       s1 = PACK_REGS(
+                                                  rd->argintregs[GET_LOW_REG(md->params[s3].regoff)],
+                                                  rd->argintregs[GET_HIGH_REG(md->params[s3].regoff)]);
+                                                       d = emit_load_s1(jd, iptr, src, s1);
+                                                       M_LNGMOVE(d, s1);
+                                               } else {
+                                                       s1 = rd->argintregs[md->params[s3].regoff];
+                                                       d = emit_load_s1(jd, iptr, src, s1);
+                                                       M_INTMOVE(d, s1);
+                                               }
+
+                                       } else {
+                                               if (IS_2_WORD_TYPE(src->type)) {
+                                                       d = emit_load_s1(jd, iptr, src, PACK_REGS(REG_ITMP2, REG_ITMP1));
+                                                       M_LST(d, REG_SP, md->params[s3].regoff * 4);
+                                               } else {
+                                                       d = emit_load_s1(jd, iptr, src, REG_ITMP1);
+                                                       M_IST(d, REG_SP, md->params[s3].regoff * 4);
+                                               }
+                                       }
+                                               
+                               } else {
+                                       if (!md->params[s3].inmemory) {
+                                               s1 = rd->argfltregs[md->params[s3].regoff];
+                                               d = emit_load_s1(jd, iptr, src, s1);
+                                               M_FLTMOVE(d, s1);
+
+                                       } else {
+                                               d = emit_load_s1(jd, iptr, src, REG_FTMP1);
+                                               if (IS_2_WORD_TYPE(src->type))
+                                                       M_DST(d, REG_SP, md->params[s3].regoff * 4);
+                                               else
+                                                       M_FST(d, REG_SP, md->params[s3].regoff * 4);
+                                       }
+                               }
+                       } /* end of for */
+
+                       switch (iptr->opc) {
+                       case ICMD_BUILTIN:
+                               disp = dseg_addaddress(cd, bte->fp);
+                               d = md->returntype.type;
+
+                               M_ALD(REG_PV, REG_PV, disp);  /* pointer to built-in-function */
+                               M_MTCTR(REG_PV);
+                               M_JSR;
+                               disp = (s4) (cd->mcodeptr - cd->mcodebase);
+                               M_MFLR(REG_ITMP1);
+                               M_LDA(REG_PV, REG_ITMP1, -disp);
+
+                               /* if op1 == true, we need to check for an exception */
+
+                               if (iptr->op1 == true) {
+                                       M_CMPI(REG_RESULT, 0);
+                                       M_BEQ(0);
+                                       codegen_add_fillinstacktrace_ref(cd);
+                               }
+                               break;
+
+                       case ICMD_INVOKESPECIAL:
+                               gen_nullptr_check(rd->argintregs[0]);
+                               M_ILD(REG_ITMP1, rd->argintregs[0], 0); /* hardware nullptr   */
+                               /* fall through */
+
+                       case ICMD_INVOKESTATIC:
+                               if (lm == NULL) {
+                                       unresolved_method *um = INSTRUCTION_UNRESOLVED_METHOD(iptr);
+
+                                       disp = dseg_addaddress(cd, NULL);
+
+                                       codegen_addpatchref(cd, PATCHER_invokestatic_special,
+                                                                               um, disp);
+
+                                       if (opt_showdisassemble)
+                                               M_NOP;
+
+                                       d = md->returntype.type;
+
+                               } else {
+                                       disp = dseg_addaddress(cd, lm->stubroutine);
+                                       d = md->returntype.type;
+                               }
+
+                               M_ALD(REG_PV, REG_PV, disp);
+                               M_MTCTR(REG_PV);
+                               M_JSR;
+                               disp = (s4) (cd->mcodeptr - cd->mcodebase);
+                               M_MFLR(REG_ITMP1);
+                               M_LDA(REG_PV, REG_ITMP1, -disp);
+                               break;
+
+                       case ICMD_INVOKEVIRTUAL:
+                               gen_nullptr_check(rd->argintregs[0]);
+
+                               if (lm == NULL) {
+                                       unresolved_method *um = INSTRUCTION_UNRESOLVED_METHOD(iptr);
+
+                                       codegen_addpatchref(cd, PATCHER_invokevirtual, um, 0);
+
+                                       if (opt_showdisassemble)
+                                               M_NOP;
+
+                                       s1 = 0;
+                                       d = md->returntype.type;
+
+                               } else {
+                                       s1 = OFFSET(vftbl_t, table[0]) +
+                                               sizeof(methodptr) * lm->vftblindex;
+                                       d = md->returntype.type;
+                               }
+
+                               M_ALD(REG_METHODPTR, rd->argintregs[0],
+                                         OFFSET(java_objectheader, vftbl));
+                               M_ALD(REG_PV, REG_METHODPTR, s1);
+                               M_MTCTR(REG_PV);
+                               M_JSR;
+                               disp = (s4) (cd->mcodeptr - cd->mcodebase);
+                               M_MFLR(REG_ITMP1);
+                               M_LDA(REG_PV, REG_ITMP1, -disp);
+                               break;
+
+                       case ICMD_INVOKEINTERFACE:
+                               gen_nullptr_check(rd->argintregs[0]);
+
+                               if (lm == NULL) {
+                                       unresolved_method *um = INSTRUCTION_UNRESOLVED_METHOD(iptr);
+
+                                       codegen_addpatchref(cd, PATCHER_invokeinterface, um, 0);
+
+                                       if (opt_showdisassemble)
+                                               M_NOP;
+
+                                       s1 = 0;
+                                       s2 = 0;
+                                       d = md->returntype.type;
+
+                               } else {
+                                       s1 = OFFSET(vftbl_t, interfacetable[0]) -
+                                               sizeof(methodptr*) * lm->class->index;
+
+                                       s2 = sizeof(methodptr) * (lm - lm->class->methods);
+
+                                       d = md->returntype.type;
+                               }
+
+                               M_ALD(REG_METHODPTR, rd->argintregs[0],
+                                         OFFSET(java_objectheader, vftbl));    
+                               M_ALD(REG_METHODPTR, REG_METHODPTR, s1);
+                               M_ALD(REG_PV, REG_METHODPTR, s2);
+                               M_MTCTR(REG_PV);
+                               M_JSR;
+                               disp = (s4) (cd->mcodeptr - cd->mcodebase);
+                               M_MFLR(REG_ITMP1);
+                               M_LDA(REG_PV, REG_ITMP1, -disp);
+                               break;
+                       }
+
+                       /* d contains return type */
+
+                       if (d != TYPE_VOID) {
+                               if (IS_INT_LNG_TYPE(iptr->dst->type)) {
+                                       if (IS_2_WORD_TYPE(iptr->dst->type)) {
+                                               /*s1 = codegen_reg_of_var(rd, iptr->opc, iptr->dst, 
+                                                                               PACK_REGS(REG_RESULT2, REG_RESULT)); FIXME*/
+                                               /*M_LNGMOVE(PACK_REGS(REG_RESULT2, REG_RESULT), s1); FIXME*/
+                                       } else {
+                                               s1 = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_RESULT);
+                                               M_INTMOVE(REG_RESULT, s1);
+                                       }
+                               } else {
+                                       s1 = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FRESULT);
+                                       M_FLTMOVE(REG_FRESULT, s1);
+                               }
+                               emit_store(jd, iptr, iptr->dst, s1);
+                       }
+                       break;
+
+
+               case ICMD_CHECKCAST:  /* ..., objectref ==> ..., objectref            */
+                                     /* op1:   0 == array, 1 == class                */
+                                     /* val.a: (classinfo*) superclass               */
+
+                       /*  superclass is an interface:
+                        *
+                        *  OK if ((sub == NULL) ||
+                        *         (sub->vftbl->interfacetablelength > super->index) &&
+                        *         (sub->vftbl->interfacetable[-super->index] != NULL));
+                        *
+                        *  superclass is a class:
+                        *
+                        *  OK if ((sub == NULL) || (0
+                        *         <= (sub->vftbl->baseval - super->vftbl->baseval) <=
+                        *         super->vftbl->diffvall));
+                        */
+
+                       if (iptr->op1 == 1) {
+                               /* object type cast-check */
+
+                               classinfo *super;
+                               vftbl_t   *supervftbl;
+                               s4         superindex;
+
+                               super = (classinfo *) iptr->val.a;
+
+                               if (!super) {
+                                       superindex = 0;
+                                       supervftbl = NULL;
+
+                               } else {
+                                       superindex = super->index;
+                                       supervftbl = super->vftbl;
+                               }
+                       
+#if defined(ENABLE_THREADS)
+                               codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
+#endif
+                               s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
+
+                               /* calculate interface checkcast code size */
+
+                               s2 = 7;
+                               if (!super)
+                                       s2 += (opt_showdisassemble ? 1 : 0);
+
+                               /* calculate class checkcast code size */
+
+                               s3 = 8 + (s1 == REG_ITMP1);
+                               if (!super)
+                                       s3 += (opt_showdisassemble ? 1 : 0);
+
+                               /* if class is not resolved, check which code to call */
+
+                               if (!super) {
+                                       M_TST(s1);
+                                       M_BEQ(3 + (opt_showdisassemble ? 1 : 0) + s2 + 1 + s3);
+
+                                       disp = dseg_adds4(cd, 0);                     /* super->flags */
+
+                                       codegen_addpatchref(cd,
+                                                                               PATCHER_checkcast_instanceof_flags,
+                                                                               (constant_classref *) iptr->target,
+                                                                               disp);
+
+                                       if (opt_showdisassemble)
+                                               M_NOP;
+
+                                       M_ILD(REG_ITMP2, REG_PV, disp);
+                                       M_AND_IMM(REG_ITMP2, ACC_INTERFACE, REG_ITMP2);
+                                       M_BEQ(s2 + 1);
+                               }
+
+                               /* interface checkcast code */
+
+                               if (!super || (super->flags & ACC_INTERFACE)) {
+                                       if (super) {
+                                               M_TST(s1);
+                                               M_BEQ(s2);
+
+                                       } else {
+                                               codegen_addpatchref(cd,
+                                                                                       PATCHER_checkcast_instanceof_interface,
+                                                                                       (constant_classref *) iptr->target,
+                                                                                       0);
+
+                                               if (opt_showdisassemble)
+                                                       M_NOP;
+                                       }
+
+                                       M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
+                                       M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
+                                       M_LDATST(REG_ITMP3, REG_ITMP3, -superindex);
+                                       M_BLE(0);
+                                       codegen_add_classcastexception_ref(cd);
+                                       M_ALD(REG_ITMP3, REG_ITMP2,
+                                                 OFFSET(vftbl_t, interfacetable[0]) -
+                                                 superindex * sizeof(methodptr*));
+                                       M_TST(REG_ITMP3);
+                                       M_BEQ(0);
+                                       codegen_add_classcastexception_ref(cd);
+
+                                       if (!super)
+                                               M_BR(s3);
+                               }
+
+                               /* class checkcast code */
+
+                               if (!super || !(super->flags & ACC_INTERFACE)) {
+                                       disp = dseg_addaddress(cd, supervftbl);
+
+                                       if (super) {
+                                               M_TST(s1);
+                                               M_BEQ(s3);
+
+                                       } else {
+                                               codegen_addpatchref(cd, PATCHER_checkcast_class,
+                                                                                       (constant_classref *) iptr->target,
+                                                                                       disp);
+
+                                               if (opt_showdisassemble)
+                                                       M_NOP;
+                                       }
+
+                                       M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
+#if defined(ENABLE_THREADS)
+                                       codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
+#endif
+                                       M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
+                                       M_ALD(REG_ITMP2, REG_PV, disp);
+                                       if (s1 != REG_ITMP1) {
+                                               M_ILD(REG_ITMP1, REG_ITMP2, OFFSET(vftbl_t, baseval));
+                                               M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
+#if defined(ENABLE_THREADS)
+                                               codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
+#endif
+                                               M_ISUB(REG_ITMP3, REG_ITMP1, REG_ITMP3);
+                                       } else {
+                                               M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
+                                               M_ISUB(REG_ITMP3, REG_ITMP2, REG_ITMP3);
+                                               M_ALD(REG_ITMP2, REG_PV, disp);
+                                               M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
+#if defined(ENABLE_THREADS)
+                                               codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
+#endif
+                                       }
+                                       M_CMPU(REG_ITMP3, REG_ITMP2);
+                                       M_BGT(0);
+                                       codegen_add_classcastexception_ref(cd);
+                               }
+                               d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, s1);
+
+                       } else {
+                               /* array type cast-check */
+
+                               s1 = emit_load_s1(jd, iptr, src, rd->argintregs[0]);
+                               M_INTMOVE(s1, rd->argintregs[0]);
+
+                               disp = dseg_addaddress(cd, iptr->val.a);
+
+                               if (iptr->val.a == NULL) {
+                                       codegen_addpatchref(cd, PATCHER_builtin_arraycheckcast,
+                                                                               (constant_classref *) iptr->target,
+                                                                               disp);
+
+                                       if (opt_showdisassemble)
+                                               M_NOP;
+                               }
+
+                               M_ALD(rd->argintregs[1], REG_PV, disp);
+                               disp = dseg_addaddress(cd, BUILTIN_arraycheckcast);
+                               M_ALD(REG_ITMP2, REG_PV, disp);
+                               M_MTCTR(REG_ITMP2);
+                               M_JSR;
+                               M_TST(REG_RESULT);
+                               M_BEQ(0);
+                               codegen_add_classcastexception_ref(cd);
+
+                               s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
+                               d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, s1);
+                       }
+                       M_INTMOVE(s1, d);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult            */
+                                     /* val.a: (classinfo*) superclass               */
+
+                       /*  superclass is an interface:
+                        *
+                        *  return (sub != NULL) &&
+                        *         (sub->vftbl->interfacetablelength > super->index) &&
+                        *         (sub->vftbl->interfacetable[-super->index] != NULL);
+                        *
+                        *  superclass is a class:
+                        *
+                        *  return ((sub != NULL) && (0
+                        *          <= (sub->vftbl->baseval - super->vftbl->baseval) <=
+                        *          super->vftbl->diffvall));
+                        */
+
+                       {
+                       classinfo *super;
+                       vftbl_t   *supervftbl;
+                       s4         superindex;
+
+                       super = (classinfo *) iptr->val.a;
+
+                       if (!super) {
+                               superindex = 0;
+                               supervftbl = NULL;
+
+                       } else {
+                               superindex = super->index;
+                               supervftbl = super->vftbl;
+                       }
+                       
+#if defined(ENABLE_THREADS)
+            codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
+#endif
+                       s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
+                       if (s1 == d) {
+                               M_MOV(s1, REG_ITMP1);
+                               s1 = REG_ITMP1;
+                       }
+
+                       /* calculate interface instanceof code size */
+
+                       s2 = 8;
+                       if (!super)
+                               s2 += (opt_showdisassemble ? 1 : 0);
+
+                       /* calculate class instanceof code size */
+
+                       s3 = 10;
+                       if (!super)
+                               s3 += (opt_showdisassemble ? 1 : 0);
+
+                       M_CLR(d);
+
+                       /* if class is not resolved, check which code to call */
+
+                       if (!super) {
+                               M_TST(s1);
+                               M_BEQ(3 + (opt_showdisassemble ? 1 : 0) + s2 + 1 + s3);
+
+                               disp = dseg_adds4(cd, 0);                     /* super->flags */
+
+                               codegen_addpatchref(cd, PATCHER_checkcast_instanceof_flags,
+                                                                       (constant_classref *) iptr->target, disp);
+
+                               if (opt_showdisassemble)
+                                       M_NOP;
+
+                               M_ILD(REG_ITMP3, REG_PV, disp);
+                               M_AND_IMM(REG_ITMP3, ACC_INTERFACE, REG_ITMP3);
+                               M_BEQ(s2 + 1);
+                       }
+
+                       /* interface instanceof code */
+
+                       if (!super || (super->flags & ACC_INTERFACE)) {
+                               if (super) {
+                                       M_TST(s1);
+                                       M_BEQ(s2);
+
+                               } else {
+                                       codegen_addpatchref(cd,
+                                                                               PATCHER_checkcast_instanceof_interface,
+                                                                               (constant_classref *) iptr->target, 0);
+
+                                       if (opt_showdisassemble)
+                                               M_NOP;
+                               }
+
+                               M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
+                               M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
+                               M_LDATST(REG_ITMP3, REG_ITMP3, -superindex);
+                               M_BLE(4);
+                               M_ALD(REG_ITMP1, REG_ITMP1,
+                                         OFFSET(vftbl_t, interfacetable[0]) -
+                                         superindex * sizeof(methodptr*));
+                               M_TST(REG_ITMP1);
+                               M_BEQ(1);
+                               M_IADD_IMM(REG_ZERO, 1, d);
+
+                               if (!super)
+                                       M_BR(s3);
+                       }
+
+                       /* class instanceof code */
+
+                       if (!super || !(super->flags & ACC_INTERFACE)) {
+                               disp = dseg_addaddress(cd, supervftbl);
+
+                               if (super) {
+                                       M_TST(s1);
+                                       M_BEQ(s3);
+
+                               } else {
+                                       codegen_addpatchref(cd, PATCHER_instanceof_class,
+                                                                               (constant_classref *) iptr->target,
+                                                                               disp);
+
+                                       if (opt_showdisassemble) {
+                                               M_NOP;
+                                       }
+                               }
+
+                               M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
+                               M_ALD(REG_ITMP2, REG_PV, disp);
+#if defined(ENABLE_THREADS)
+                               codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
+#endif
+                               M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
+                               M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
+                               M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
+#if defined(ENABLE_THREADS)
+                               codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
+#endif
+                               M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
+                               M_CMPU(REG_ITMP1, REG_ITMP2);
+                               M_CLR(d);
+                               M_BGT(1);
+                               M_IADD_IMM(REG_ZERO, 1, d);
+                       }
+                       emit_store(jd, iptr, iptr->dst, d);
+                       }
+                       break;
+
+               case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref  */
+                                     /* op1 = dimension, val.a = class               */
+
+                       /* check for negative sizes and copy sizes to stack if necessary  */
+
+                       MCODECHECK((iptr->op1 << 1) + 64);
+
+                       for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
+                               /* copy SAVEDVAR sizes to stack */
+
+                               if (src->varkind != ARGVAR) {
+                                       s2 = emit_load_s2(jd, iptr, src, REG_ITMP1);
+#if defined(__DARWIN__)
+                                       M_IST(s2, REG_SP, LA_SIZE + (s1 + INT_ARG_CNT) * 4);
+#else
+                                       M_IST(s2, REG_SP, LA_SIZE + (s1 + 3) * 4);
+#endif
+                               }
+                       }
+
+                       /* a0 = dimension count */
+
+                       ICONST(rd->argintregs[0], iptr->op1);
+
+                       /* is patcher function set? */
+
+                       if (iptr->val.a == NULL) {
+                               disp = dseg_addaddress(cd, NULL);
+
+                               codegen_addpatchref(cd, PATCHER_builtin_multianewarray,
+                                                                       (constant_classref *) iptr->target, disp);
+
+                               if (opt_showdisassemble)
+                                       M_NOP;
+
+                       } else {
+                               disp = dseg_addaddress(cd, iptr->val.a);
+                       }
+
+                       /* a1 = arraydescriptor */
+
+                       M_ALD(rd->argintregs[1], REG_PV, disp);
+
+                       /* a2 = pointer to dimensions = stack pointer */
+
+#if defined(__DARWIN__)
+                       M_LDA(rd->argintregs[2], REG_SP, LA_SIZE + INT_ARG_CNT * 4);
+#else
+                       M_LDA(rd->argintregs[2], REG_SP, LA_SIZE + 3 * 4);
+#endif
+
+                       disp = dseg_addaddress(cd, BUILTIN_multianewarray);
+                       M_ALD(REG_ITMP3, REG_PV, disp);
+                       M_MTCTR(REG_ITMP3);
+                       M_JSR;
+
+                       /* check for exception before result assignment */
+
+                       M_CMPI(REG_RESULT, 0);
+                       M_BEQ(0);
+                       codegen_add_fillinstacktrace_ref(cd);
+
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_RESULT);
+                       M_INTMOVE(REG_RESULT, d);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               default:
+                       *exceptionptr =
+                               new_internalerror("Unknown ICMD %d during code generation",
+                                                                 iptr->opc);
+                       return false;
+       } /* switch */
+               
+       } /* for instruction */
+               
+       /* copy values to interface registers */
+
+       src = bptr->outstack;
+       len = bptr->outdepth;
+       MCODECHECK(64 + len);
+#if defined(ENABLE_LSRA)
+       if (!opt_lsra)
+#endif
+       while (src) {
+               len--;
+               if ((src->varkind != STACKVAR)) {
+                       s2 = src->type;
+                       if (IS_FLT_DBL_TYPE(s2)) {
+                               s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
+                               if (!(rd->interfaces[len][s2].flags & INMEMORY))
+                                       M_FLTMOVE(s1, rd->interfaces[len][s2].regoff);
+                               else
+                                       M_DST(s1, REG_SP, rd->interfaces[len][s2].regoff * 4);
+
+                       } else {
+                               s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
+                               if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
+                                       if (IS_2_WORD_TYPE(s2))
+                                               M_LNGMOVE(s1, rd->interfaces[len][s2].regoff);
+                                       else
+                                               M_INTMOVE(s1, rd->interfaces[len][s2].regoff);
+
+                               } else {
+                                       if (IS_2_WORD_TYPE(s2))
+                                               M_LST(s1, REG_SP, rd->interfaces[len][s2].regoff * 4);
+                                       else
+                                               M_IST(s1, REG_SP, rd->interfaces[len][s2].regoff * 4);
+                               }
+                       }
+               }
+               src = src->prev;
+       }
+       } /* if (bptr -> flags >= BBREACHED) */
+       } /* for basic block */
+
+       dseg_createlinenumbertable(cd);
+
+
+       /* generate exception and patcher stubs */
+
+       {
+               exceptionref *eref;
+               patchref     *pref;
+               u4            mcode;
+               u1           *savedmcodeptr;
+               u1           *tmpmcodeptr;
+
+               savedmcodeptr = NULL;
+
+               /* generate exception stubs */
+
+               for (eref = cd->exceptionrefs; eref != NULL; eref = eref->next) {
+                       gen_resolvebranch(cd->mcodebase + eref->branchpos, 
+                                                         eref->branchpos, cd->mcodeptr - cd->mcodebase);
+
+                       MCODECHECK(100);
+
+                       /* Check if the exception is an
+                          ArrayIndexOutOfBoundsException.  If so, move index register
+                          into REG_ITMP1. */
+
+                       if (eref->reg != -1)
+                               M_MOV(eref->reg, REG_ITMP1);
+
+                       /* calcuate exception address */
+
+                       M_LDA(REG_ITMP2_XPC, REG_PV, eref->branchpos - 4);
+
+                       /* move function to call into REG_ITMP3 */
+
+                       disp = dseg_addaddress(cd, eref->function);
+                       M_ALD(REG_ITMP3, REG_PV, disp);
+
+                       if (savedmcodeptr != NULL) {
+                               disp = ((u4 *) savedmcodeptr) - (((u4 *) cd->mcodeptr) + 1);
+                               M_BR(disp);
+
+                       } else {
+                               savedmcodeptr = cd->mcodeptr;
+
+                               if (m->isleafmethod) {
+                                       M_MFLR(REG_ZERO);
+                                       M_AST(REG_ZERO, REG_SP, stackframesize * 4 + LA_LR_OFFSET);
+                               }
+
+                               M_MOV(REG_PV, rd->argintregs[0]);
+                               M_MOV(REG_SP, rd->argintregs[1]);
+
+                               if (m->isleafmethod)
+                                       M_MOV(REG_ZERO, rd->argintregs[2]);
+                               else
+                                       M_ALD(rd->argintregs[2],
+                                                 REG_SP, stackframesize * 4 + LA_LR_OFFSET);
+
+                               M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
+                               M_MOV(REG_ITMP1, rd->argintregs[4]);
+
+                               M_STWU(REG_SP, REG_SP, -(LA_SIZE + 6 * 4));
+                               M_AST(REG_ITMP2_XPC, REG_SP, LA_SIZE + 5 * 4);
+
+                               M_MTCTR(REG_ITMP3);
+                               M_JSR;
+                               M_MOV(REG_RESULT, REG_ITMP1_XPTR);
+
+                               M_ALD(REG_ITMP2_XPC, REG_SP, LA_SIZE + 5 * 4);
+                               M_IADD_IMM(REG_SP, LA_SIZE + 6 * 4, REG_SP);
+
+                               if (m->isleafmethod) {
+                                       /* XXX FIXME: REG_ZERO can cause problems here! */
+                                       assert(stackframesize * 4 <= 32767);
+
+                                       M_ALD(REG_ZERO, REG_SP, stackframesize * 4 + LA_LR_OFFSET);
+                                       M_MTLR(REG_ZERO);
+                               }
+
+                               disp = dseg_addaddress(cd, asm_handle_exception);
+                               M_ALD(REG_ITMP3, REG_PV, disp);
+                               M_MTCTR(REG_ITMP3);
+                               M_RTS;
+                       }
+               }
+
+
+               /* generate code patching stub call code */
+
+               for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
+                       /* check code segment size */
+
+                       MCODECHECK(16);
+
+                       /* Get machine code which is patched back in later. The
+                          call is 1 instruction word long. */
+
+                       tmpmcodeptr = (u1 *) (cd->mcodebase + pref->branchpos);
+
+                       mcode = *((u4 *) tmpmcodeptr);
+
+                       /* Patch in the call to call the following code (done at
+                          compile time). */
+
+                       savedmcodeptr = cd->mcodeptr;   /* save current mcodeptr          */
+                       cd->mcodeptr  = tmpmcodeptr;    /* set mcodeptr to patch position */
+
+                       disp = ((u4 *) savedmcodeptr) - (((u4 *) tmpmcodeptr) + 1);
+                       M_BR(disp);
+
+                       cd->mcodeptr = savedmcodeptr;   /* restore the current mcodeptr   */
+
+                       /* create stack frame - keep stack 16-byte aligned */
+
+                       M_AADD_IMM(REG_SP, -8 * 4, REG_SP);
+
+                       /* calculate return address and move it onto the stack */
+
+                       M_LDA(REG_ITMP3, REG_PV, pref->branchpos);
+                       M_AST_INTERN(REG_ITMP3, REG_SP, 5 * 4);
+
+                       /* move pointer to java_objectheader onto stack */
+
+#if defined(ENABLE_THREADS)
+                       /* order reversed because of data segment layout */
+
+                       (void) dseg_addaddress(cd, NULL);                         /* flcword    */
+                       (void) dseg_addaddress(cd, lock_get_initial_lock_word()); /* monitorPtr */
+                       disp = dseg_addaddress(cd, NULL);                         /* vftbl      */
+
+                       M_LDA(REG_ITMP3, REG_PV, disp);
+                       M_AST_INTERN(REG_ITMP3, REG_SP, 4 * 4);
+#else
+                       /* do nothing */
+#endif
+
+                       /* move machine code onto stack */
+
+                       disp = dseg_adds4(cd, mcode);
+                       M_ILD(REG_ITMP3, REG_PV, disp);
+                       M_IST_INTERN(REG_ITMP3, REG_SP, 3 * 4);
+
+                       /* move class/method/field reference onto stack */
+
+                       disp = dseg_addaddress(cd, pref->ref);
+                       M_ALD(REG_ITMP3, REG_PV, disp);
+                       M_AST_INTERN(REG_ITMP3, REG_SP, 2 * 4);
+
+                       /* move data segment displacement onto stack */
+
+                       disp = dseg_addaddress(cd, pref->disp);
+                       M_ILD(REG_ITMP3, REG_PV, disp);
+                       M_IST_INTERN(REG_ITMP3, REG_SP, 1 * 4);
+
+                       /* move patcher function pointer onto stack */
+
+                       disp = dseg_addaddress(cd, pref->patcher);
+                       M_ALD(REG_ITMP3, REG_PV, disp);
+                       M_AST_INTERN(REG_ITMP3, REG_SP, 0 * 4);
+
+                       disp = dseg_addaddress(cd, asm_wrapper_patcher);
+                       M_ALD(REG_ITMP3, REG_PV, disp);
+                       M_MTCTR(REG_ITMP3);
+                       M_RTS;
+               }
+
+               /* generate replacement-out stubs */
+
+               {
+                       int i;
+
+                       replacementpoint = jd->code->rplpoints;
+
+                       for (i = 0; i < jd->code->rplpointcount; ++i, ++replacementpoint) {
+                               /* check code segment size */
+
+                               MCODECHECK(100);
+
+                               /* note start of stub code */
+
+                               replacementpoint->outcode = (u1 *) (cd->mcodeptr - cd->mcodebase);
+
+                               /* make machine code for patching */
+
+                               tmpmcodeptr  = cd->mcodeptr;
+                               cd->mcodeptr = (u1 *) &(replacementpoint->mcode) + 1 /* big-endian */;
+
+                               disp = (ptrint)((s4*)replacementpoint->outcode - (s4*)replacementpoint->pc) - 1;
+                               M_BR(disp);
+
+                               cd->mcodeptr = tmpmcodeptr;
+
+                               /* create stack frame - keep 16-byte aligned */
+
+                               M_AADD_IMM(REG_SP, -4 * 4, REG_SP);
+
+                               /* push address of `rplpoint` struct */
+
+                               disp = dseg_addaddress(cd, replacementpoint);
+                               M_ALD(REG_ITMP3, REG_PV, disp);
+                               M_AST_INTERN(REG_ITMP3, REG_SP, 0 * 4);
+
+                               /* jump to replacement function */
+
+                               disp = dseg_addaddress(cd, asm_replacement_out);
+                               M_ALD(REG_ITMP3, REG_PV, disp);
+                               M_MTCTR(REG_ITMP3);
+                               M_RTS;
+                       }
+               }
+       }
+
+       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    4 * 4
+
+#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;
+
+       M_ALD_INTERN(REG_ITMP1, REG_PV, -2 * SIZEOF_VOID_P);
+       M_ALD_INTERN(REG_PV, REG_PV, -3 * SIZEOF_VOID_P);
+       M_MTCTR(REG_PV);
+       M_RTS;
+
+       md_cacheflush((u1 *) d, COMPILERSTUB_SIZE);
+
+#if defined(ENABLE_STATISTICS)
+       if (opt_stat)
+               count_cstub_len += COMPILERSTUB_SIZE;
+#endif
+
+       /* release dump area */
+
+       dump_release(dumpsize);
+
+       return s;
+}
+
+
+/* createnativestub ************************************************************
+
+   Creates a stub routine which calls a native method.
+
+*******************************************************************************/
+
+u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd)
+{
+       methodinfo   *m;
+       codeinfo     *code;
+       codegendata  *cd;
+       registerdata *rd;
+       s4            stackframesize;       /* size of stackframe if needed       */
+       methoddesc   *md;
+       s4            nativeparams;
+       s4            i, j;                 /* count variables                    */
+       s4            t;
+       s4            s1, s2, disp;
+       s4            funcdisp;
+
+       /* get required compiler data */
+
+       m    = jd->m;
+       code = jd->code;
+       cd   = jd->cd;
+       rd   = jd->rd;
+
+       /* set some variables */
+
+       md = m->parseddesc;
+       nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
+
+       /* calculate stackframe size */
+
+       stackframesize =
+               sizeof(stackframeinfo) / SIZEOF_VOID_P +
+               sizeof(localref_table) / SIZEOF_VOID_P +
+               4 +                             /* 4 stackframeinfo arguments (darwin)*/
+               nmd->paramcount * 2 +           /* assume all arguments are doubles   */
+               nmd->memuse;
+
+       stackframesize = (stackframesize + 3) & ~3; /* keep stack 16-byte aligned */
+
+       /* create method header */
+
+       (void) dseg_addaddress(cd, code);                      /* CodeinfoPointer */
+       (void) dseg_adds4(cd, stackframesize * 4);             /* FrameSize       */
+       (void) dseg_adds4(cd, 0);                              /* IsSync          */
+       (void) dseg_adds4(cd, 0);                              /* IsLeaf          */
+       (void) dseg_adds4(cd, 0);                              /* IntSave         */
+       (void) dseg_adds4(cd, 0);                              /* FltSave         */
+       (void) dseg_addlinenumbertablesize(cd);
+       (void) dseg_adds4(cd, 0);                              /* ExTableSize     */
+
+       /* generate code */
+
+       M_MFLR(REG_ZERO);
+       M_AST_INTERN(REG_ZERO, REG_SP, LA_LR_OFFSET);
+       M_STWU(REG_SP, REG_SP, -(stackframesize * 4));
+
+       if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
+               /* parent_argbase == stackframesize * 4 */
+               codegen_trace_args(jd, stackframesize * 4 , true);
+
+       /* get function address (this must happen before the stackframeinfo) */
+
+       funcdisp = dseg_addaddress(cd, f);
+
+#if !defined(WITH_STATIC_CLASSPATH)
+       if (f == NULL) {
+               codegen_addpatchref(cd, PATCHER_resolve_native, m, funcdisp);
+
+               if (opt_showdisassemble)
+                       M_NOP;
+       }
+#endif
+
+       /* save integer and float argument registers */
+
+       j = 0;
+
+       for (i = 0; i < md->paramcount; i++) {
+               t = md->paramtypes[i].type;
+
+               if (IS_INT_LNG_TYPE(t)) {
+                       if (!md->params[i].inmemory) {
+                               s1 = md->params[i].regoff;
+                               if (IS_2_WORD_TYPE(t)) {
+                                       M_IST(rd->argintregs[GET_HIGH_REG(s1)], REG_SP, LA_SIZE + 4 * 4 + j * 4);
+                                       j++;
+                                       M_IST(rd->argintregs[GET_LOW_REG(s1)], REG_SP, LA_SIZE + 4 * 4 + j * 4);
+                               } else {
+                                       M_IST(rd->argintregs[s1], REG_SP, LA_SIZE + 4 * 4 + j * 4);
+                               }
+                               j++;
+                       }
+               }
+       }
+
+       for (i = 0; i < md->paramcount; i++) {
+               if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
+                       if (!md->params[i].inmemory) {
+                               s1 = md->params[i].regoff;
+                               M_DST(rd->argfltregs[s1], REG_SP, LA_SIZE + 4 * 4 + j * 8);
+                               j++;
+                       }
+               }
+       }
+
+       /* create native stack info */
+
+       M_AADD_IMM(REG_SP, stackframesize * 4, rd->argintregs[0]);
+       M_MOV(REG_PV, rd->argintregs[1]);
+       M_AADD_IMM(REG_SP, stackframesize * 4, rd->argintregs[2]);
+       M_ALD(rd->argintregs[3], REG_SP, stackframesize * 4 + LA_LR_OFFSET);
+       disp = dseg_addaddress(cd, codegen_start_native_call);
+       M_ALD(REG_ITMP1, REG_PV, disp);
+       M_MTCTR(REG_ITMP1);
+       M_JSR;
+
+       /* restore integer and float argument registers */
+
+       j = 0;
+
+       for (i = 0; i < md->paramcount; i++) {
+               t = md->paramtypes[i].type;
+
+               if (IS_INT_LNG_TYPE(t)) {
+                       if (!md->params[i].inmemory) {
+                               s1 = md->params[i].regoff;
+
+                               if (IS_2_WORD_TYPE(t)) {
+                                       M_ILD(rd->argintregs[GET_HIGH_REG(s1)], REG_SP, LA_SIZE + 4 * 4 + j * 4);
+                                       j++;
+                                       M_ILD(rd->argintregs[GET_LOW_REG(s1)], REG_SP, LA_SIZE + 4 * 4 + j * 4);
+                               } else {
+                                       M_ILD(rd->argintregs[s1], REG_SP, LA_SIZE + 4 * 4 + j * 4);
+                               }
+                               j++;
+                       }
+               }
+       }
+
+       for (i = 0; i < md->paramcount; i++) {
+               if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
+                       if (!md->params[i].inmemory) {
+                               s1 = md->params[i].regoff;
+                               M_DLD(rd->argfltregs[s1], REG_SP, LA_SIZE + 4 * 4 + j * 8);
+                               j++;
+                       }
+               }
+       }
+       
+       /* 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) {
+                               if (IS_2_WORD_TYPE(t))
+                                       s1 = PACK_REGS(
+                                               rd->argintregs[GET_LOW_REG(md->params[i].regoff)],
+                                           rd->argintregs[GET_HIGH_REG(md->params[i].regoff)]);
+                               else
+                                       s1 = rd->argintregs[md->params[i].regoff];
+
+                               if (!nmd->params[j].inmemory) {
+                                       if (IS_2_WORD_TYPE(t)) {
+                                               s2 = PACK_REGS(
+                                                  rd->argintregs[GET_LOW_REG(nmd->params[j].regoff)],
+                                                  rd->argintregs[GET_HIGH_REG(nmd->params[j].regoff)]);
+                                               M_LNGMOVE(s1, s2);
+                                       } else {
+                                               s2 = rd->argintregs[nmd->params[j].regoff];
+                                               M_INTMOVE(s1, s2);
+                                       }
+
+                               } else {
+                                       s2 = nmd->params[j].regoff;
+                                       if (IS_2_WORD_TYPE(t))
+                                               M_LST(s1, REG_SP, s2 * 4);
+                                       else
+                                               M_IST(s1, REG_SP, s2 * 4);
+                               }
+
+                       } else {
+                               s1 = md->params[i].regoff + stackframesize;
+                               s2 = nmd->params[j].regoff;
+
+                               M_ILD(REG_ITMP1, REG_SP, s1 * 4);
+                               if (IS_2_WORD_TYPE(t))
+                                       M_ILD(REG_ITMP2, REG_SP, s1 * 4 + 4);
+
+                               M_IST(REG_ITMP1, REG_SP, s2 * 4);
+                               if (IS_2_WORD_TYPE(t))
+                                       M_IST(REG_ITMP2, REG_SP, s2 * 4 + 4);
+                       }
+
+               } else {
+                       /* We only copy spilled float arguments, as the float
+                          argument registers keep unchanged. */
+
+                       if (md->params[i].inmemory) {
+                               s1 = md->params[i].regoff + stackframesize;
+                               s2 = nmd->params[j].regoff;
+
+                               if (IS_2_WORD_TYPE(t)) {
+                                       M_DLD(REG_FTMP1, REG_SP, s1 * 4);
+                                       M_DST(REG_FTMP1, REG_SP, s2 * 4);
+
+                               } else {
+                                       M_FLD(REG_FTMP1, REG_SP, s1 * 4);
+                                       M_FST(REG_FTMP1, REG_SP, s2 * 4);
+                               }
+                       }
+               }
+       }
+
+       /* put class into second argument register */
+
+       if (m->flags & ACC_STATIC) {
+               disp = dseg_addaddress(cd, m->class);
+               M_ALD(rd->argintregs[1], REG_PV, disp);
+       }
+
+       /* put env into first argument register */
+
+       disp = dseg_addaddress(cd, _Jv_env);
+       M_ALD(rd->argintregs[0], REG_PV, disp);
+
+       /* generate the actual native call */
+
+       M_ALD(REG_ITMP3, REG_PV, funcdisp);
+       M_MTCTR(REG_ITMP3);
+       M_JSR;
+
+       /* save return value */
+
+       if (md->returntype.type != TYPE_VOID) {
+               if (IS_INT_LNG_TYPE(md->returntype.type)) {
+                       if (IS_2_WORD_TYPE(md->returntype.type))
+                               /*M_IST(REG_RESULT2, REG_SP, LA_SIZE + 2 * 4); // FIXME*/
+                       M_IST(REG_RESULT, REG_SP, LA_SIZE + 1 * 4);
+               }
+               else {
+                       if (IS_2_WORD_TYPE(md->returntype.type))
+                               M_DST(REG_FRESULT, REG_SP, LA_SIZE + 1 * 4);
+                       else
+                               M_FST(REG_FRESULT, REG_SP, LA_SIZE + 1 * 4);
+               }
+       }
+
+       /* print call trace */
+
+       if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) {
+                /* just restore the value we need, don't care about the other */
+
+               if (md->returntype.type != TYPE_VOID) {
+                       if (IS_INT_LNG_TYPE(md->returntype.type)) {
+                               if (IS_2_WORD_TYPE(md->returntype.type))
+                                       /*M_ILD(REG_RESULT2, REG_SP, LA_SIZE + 2 * 4); FIXME*/
+                               M_ILD(REG_RESULT, REG_SP, LA_SIZE + 1 * 4);
+                       }
+                       else {
+                               if (IS_2_WORD_TYPE(md->returntype.type))
+                                       M_DLD(REG_FRESULT, REG_SP, LA_SIZE + 1 * 4);
+                               else
+                                       M_FLD(REG_FRESULT, REG_SP, LA_SIZE + 1 * 4);
+                       }
+               }
+
+               M_LDA(REG_SP, REG_SP, -(LA_SIZE + (1 + 2 + 2 + 1) * 4));
+
+               /* keep this order */
+               switch (md->returntype.type) {
+               case TYPE_INT:
+               case TYPE_ADR:
+#if defined(__DARWIN__)
+                       M_MOV(REG_RESULT, rd->argintregs[2]);
+                       M_CLR(rd->argintregs[1]);
+#else
+                       M_MOV(REG_RESULT, rd->argintregs[3]);
+                       M_CLR(rd->argintregs[2]);
+#endif
+                       break;
+
+               case TYPE_LNG:
+#if defined(__DARWIN__)
+                       /*M_MOV(REG_RESULT2, rd->argintregs[2]);FIXME*/
+                       M_MOV(REG_RESULT, rd->argintregs[1]);
+#else
+                       /*M_MOV(REG_RESULT2, rd->argintregs[3]);FIXME*/
+                       M_MOV(REG_RESULT, rd->argintregs[2]);
+#endif
+                       break;
+               }
+
+               M_FLTMOVE(REG_FRESULT, rd->argfltregs[0]);
+               M_FLTMOVE(REG_FRESULT, rd->argfltregs[1]);
+               disp = dseg_addaddress(cd, m);
+               M_ALD(rd->argintregs[0], REG_PV, disp);
+
+               disp = dseg_addaddress(cd, builtin_displaymethodstop);
+               M_ALD(REG_ITMP2, REG_PV, disp);
+               M_MTCTR(REG_ITMP2);
+               M_JSR;
+
+               M_LDA(REG_SP, REG_SP, LA_SIZE + (1 + 2 + 2 + 1) * 4);
+       }
+
+       /* remove native stackframe info */
+
+       M_AADD_IMM(REG_SP, stackframesize * 4, rd->argintregs[0]);
+       disp = dseg_addaddress(cd, codegen_finish_native_call);
+       M_ALD(REG_ITMP1, REG_PV, disp);
+       M_MTCTR(REG_ITMP1);
+       M_JSR;
+       M_MOV(REG_RESULT, REG_ITMP1_XPTR);
+
+       /* restore return value */
+
+       if (md->returntype.type != TYPE_VOID) {
+               if (IS_INT_LNG_TYPE(md->returntype.type)) {
+                       if (IS_2_WORD_TYPE(md->returntype.type))
+                               /*M_ILD(REG_RESULT2, REG_SP, LA_SIZE + 2 * 4);FIXME*/
+                       M_ILD(REG_RESULT, REG_SP, LA_SIZE + 1 * 4);
+               }
+               else {
+                       if (IS_2_WORD_TYPE(md->returntype.type))
+                               M_DLD(REG_FRESULT, REG_SP, LA_SIZE + 1 * 4);
+                       else
+                               M_FLD(REG_FRESULT, REG_SP, LA_SIZE + 1 * 4);
+               }
+       }
+
+       M_ALD(REG_ITMP2_XPC, REG_SP, stackframesize * 4 + LA_LR_OFFSET);
+       M_MTLR(REG_ITMP2_XPC);
+       M_LDA(REG_SP, REG_SP, stackframesize * 4); /* remove stackframe           */
+
+       /* check for exception */
+
+       M_TST(REG_ITMP1_XPTR);
+       M_BNE(1);                           /* if no exception then return        */
+
+       M_RET;
+
+       /* handle exception */
+
+       M_IADD_IMM(REG_ITMP2_XPC, -4, REG_ITMP2_XPC);  /* exception address       */
+
+       disp = dseg_addaddress(cd, asm_handle_nat_exception);
+       M_ALD(REG_ITMP3, REG_PV, disp);
+       M_MTCTR(REG_ITMP3);
+       M_RTS;
+
+       /* generate patcher stub call code */
+
+       {
+               patchref *pref;
+               u4        mcode;
+               u1       *savedmcodeptr;
+               u1       *tmpmcodeptr;
+
+               for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
+                       /* Get machine code which is patched back in later. The
+                          call is 1 instruction word long. */
+
+                       tmpmcodeptr = cd->mcodebase + pref->branchpos;
+
+                       mcode = *((u4 *) tmpmcodeptr);
+
+                       /* Patch in the call to call the following code (done at
+                          compile time). */
+
+                       savedmcodeptr = cd->mcodeptr;   /* save current mcodeptr          */
+                       cd->mcodeptr  = tmpmcodeptr;    /* set mcodeptr to patch position */
+
+                       disp = ((u4 *) savedmcodeptr) - (((u4 *) tmpmcodeptr) + 1);
+                       M_BL(disp);
+
+                       cd->mcodeptr = savedmcodeptr;   /* restore the current mcodeptr   */
+
+                       /* create stack frame - keep stack 16-byte aligned */
+
+                       M_AADD_IMM(REG_SP, -8 * 4, REG_SP);
+
+                       /* move return address onto stack */
+
+                       M_MFLR(REG_ZERO);
+                       M_AST(REG_ZERO, REG_SP, 5 * 4);
+
+                       /* move pointer to java_objectheader onto stack */
+
+#if defined(ENABLE_THREADS)
+                       /* order reversed because of data segment layout */
+
+                       (void) dseg_addaddress(cd, NULL);                         /* flcword    */
+                       (void) dseg_addaddress(cd, lock_get_initial_lock_word()); /* monitorPtr */
+                       disp = dseg_addaddress(cd, NULL);                         /* vftbl      */
+
+                       M_LDA(REG_ITMP3, REG_PV, disp);
+                       M_AST(REG_ITMP3, REG_SP, 4 * 4);
+#else
+                       /* do nothing */
+#endif
+
+                       /* move machine code onto stack */
+
+                       disp = dseg_adds4(cd, mcode);
+                       M_ILD(REG_ITMP3, REG_PV, disp);
+                       M_IST(REG_ITMP3, REG_SP, 3 * 4);
+
+                       /* move class/method/field reference onto stack */
+
+                       disp = dseg_addaddress(cd, pref->ref);
+                       M_ALD(REG_ITMP3, REG_PV, disp);
+                       M_AST(REG_ITMP3, REG_SP, 2 * 4);
+
+                       /* move data segment displacement onto stack */
+
+                       disp = dseg_addaddress(cd, pref->disp);
+                       M_ILD(REG_ITMP3, REG_PV, disp);
+                       M_IST(REG_ITMP3, REG_SP, 1 * 4);
+
+                       /* move patcher function pointer onto stack */
+
+                       disp = dseg_addaddress(cd, pref->patcher);
+                       M_ALD(REG_ITMP3, REG_PV, disp);
+                       M_AST(REG_ITMP3, REG_SP, 0 * 4);
+
+                       disp = dseg_addaddress(cd, asm_wrapper_patcher);
+                       M_ALD(REG_ITMP3, REG_PV, disp);
+                       M_MTCTR(REG_ITMP3);
+                       M_RTS;
+               }
+       }
+
+       codegen_finish(jd);
+
+       return jd->code->entrypoint;
+}
+
+
+void codegen_trace_args(jitdata *jd, s4 stackframesize, bool nativestub)
+{
+       methodinfo   *m;
+       codegendata  *cd;
+       registerdata *rd;
+       s4 s1, p, t, d;
+       int stack_off;
+       int stack_size;
+       methoddesc *md;
+
+       /* get required compiler data */
+
+       m  = jd->m;
+       cd = jd->cd;
+       rd = jd->rd;
+
+       md = m->parseddesc;
+       
+       if (!nativestub)
+               M_MFLR(REG_ITMP3);
+       /* Build up Stackframe for builtin_trace_args call (a multiple of 16) */
+       /* For Darwin:                                                        */
+       /* LA + TRACE_ARGS_NUM u8 args + methodinfo + LR                      */
+       /* LA_SIZE(=6*4) + 8*8         + 4          + 4  + 0(Padding)         */
+       /* 6 * 4 + 8 * 8 + 2 * 4 = 12 * 8 = 6 * 16                            */
+       /* For Linux:                                                         */
+       /* LA + (TRACE_ARGS_NUM - INT_ARG_CNT/2) u8 args + methodinfo         */
+       /* + INT_ARG_CNT * 4 ( save integer registers) + LR + 8 + 8 (Padding) */
+       /* LA_SIZE(=2*4) + 4 * 8 + 4 + 8 * 4 + 4 + 8                          */
+       /* 2 * 4 + 4 * 8 + 10 * 4 + 1 * 8 + 8= 12 * 8 = 6 * 16                */
+       
+       /* in nativestubs no Place to save the LR (Link Register) would be needed */
+       /* but since the stack frame has to be aligned the 4 Bytes would have to  */
+       /* be padded again */
+
+#if defined(__DARWIN__)
+       stack_size = LA_SIZE + (TRACE_ARGS_NUM + 1) * 8;
+#else
+       stack_size = 6 * 16;
+#endif
+       M_LDA(REG_SP, REG_SP, -stack_size);
+
+       /* Save LR */
+       if (!nativestub)
+               M_IST(REG_ITMP3, REG_SP, LA_SIZE + TRACE_ARGS_NUM * 8 + 1 * 4);
+
+       M_CLR(REG_ITMP1);    /* clear help register */
+
+       /* save up to TRACE_ARGS_NUM arguments into the reserved stack space */
+#if defined(__DARWIN__)
+       /* Copy Params starting from first to Stack                          */
+       /* since TRACE_ARGS == INT_ARG_CNT all used integer argument regs    */ 
+       /* are saved                                                         */
+       p = 0;
+#else
+       /* Copy Params starting from fifth to Stack (INT_ARG_CNT/2) are in   */
+       /* integer argument regs                                             */
+       /* all integer argument registers have to be saved                   */
+       for (p = 0; p < 8; p++) {
+               d = rd->argintregs[p];
+               /* save integer argument registers */
+               M_IST(d, REG_SP, LA_SIZE + 4 * 8 + 4 + p * 4);
+       }
+       p = 4;
+#endif
+       stack_off = LA_SIZE;
+       for (; p < md->paramcount && p < TRACE_ARGS_NUM; p++, stack_off += 8) {
+               t = md->paramtypes[p].type;
+               if (IS_INT_LNG_TYPE(t)) {
+                       if (!md->params[p].inmemory) { /* Param in Arg Reg */
+                               if (IS_2_WORD_TYPE(t)) {
+                                       M_IST(rd->argintregs[GET_HIGH_REG(md->params[p].regoff)]
+                                                 , REG_SP, stack_off);
+                                       M_IST(rd->argintregs[GET_LOW_REG(md->params[p].regoff)]
+                                                 , REG_SP, stack_off + 4);
+                               } else {
+                                       M_IST(REG_ITMP1, REG_SP, stack_off);
+                                       M_IST(rd->argintregs[md->params[p].regoff]
+                                                 , REG_SP, stack_off + 4);
+                               }
+                       } else { /* Param on Stack */
+                               s1 = (md->params[p].regoff + stackframesize) * 4 
+                                       + stack_size;
+                               if (IS_2_WORD_TYPE(t)) {
+                                       M_ILD(REG_ITMP2, REG_SP, s1);
+                                       M_IST(REG_ITMP2, REG_SP, stack_off);
+                                       M_ILD(REG_ITMP2, REG_SP, s1 + 4);
+                                       M_IST(REG_ITMP2, REG_SP, stack_off + 4);
+                               } else {
+                                       M_IST(REG_ITMP1, REG_SP, stack_off);
+                                       M_ILD(REG_ITMP2, REG_SP, s1);
+                                       M_IST(REG_ITMP2, REG_SP, stack_off + 4);
+                               }
+                       }
+               } else { /* IS_FLT_DBL_TYPE(t) */
+                       if (!md->params[p].inmemory) { /* in Arg Reg */
+                               s1 = rd->argfltregs[md->params[p].regoff];
+                               if (!IS_2_WORD_TYPE(t)) {
+                                       M_IST(REG_ITMP1, REG_SP, stack_off);
+                                       M_FST(s1, REG_SP, stack_off + 4);
+                               } else {
+                                       M_DST(s1, REG_SP, stack_off);
+                               }
+                       } else { /* on Stack */
+                               /* this should not happen */
+                       }
+               }
+       }
+
+       /* load first 4 (==INT_ARG_CNT/2) arguments into integer registers */
+#if defined(__DARWIN__)
+       for (p = 0; p < 8; p++) {
+               d = rd->argintregs[p];
+               M_ILD(d, REG_SP, LA_SIZE + p * 4);
+       }
+#else
+       /* LINUX */
+       /* Set integer and float argument registers vor trace_args call */
+       /* offset to saved integer argument registers                   */
+       stack_off = LA_SIZE + 4 * 8 + 4;
+       for (p = 0; (p < 4) && (p < md->paramcount); p++) {
+               t = md->paramtypes[p].type;
+               if (IS_INT_LNG_TYPE(t)) {
+                       /* "stretch" int types */
+                       if (!IS_2_WORD_TYPE(t)) {
+                               M_CLR(rd->argintregs[2 * p]);
+                               M_ILD(rd->argintregs[2 * p + 1], REG_SP,stack_off);
+                               stack_off += 4;
+                       } else {
+                               M_ILD(rd->argintregs[2 * p + 1], REG_SP,stack_off + 4);
+                               M_ILD(rd->argintregs[2 * p], REG_SP,stack_off);
+                               stack_off += 8;
+                       }
+               } else { /* Float/Dbl */
+                       if (!md->params[p].inmemory) { /* Param in Arg Reg */
+                               /* use reserved Place on Stack (sp + 5 * 16) to copy  */
+                               /* float/double arg reg to int reg                    */
+                               s1 = rd->argfltregs[md->params[p].regoff];
+                               if (!IS_2_WORD_TYPE(t)) {
+                                       M_FST(s1, REG_SP, 5 * 16);
+                                       M_ILD(rd->argintregs[2 * p + 1], REG_SP, 5 * 16);
+                                       M_CLR(rd->argintregs[2 * p]);
+                               } else {
+                                       M_DST(s1, REG_SP, 5 * 16);
+                                       M_ILD(rd->argintregs[2 * p + 1], REG_SP,  5 * 16 + 4);
+                                       M_ILD(rd->argintregs[2 * p], REG_SP, 5 * 16);
+                               }
+                       }
+               }
+       }
+#endif
+
+       /* put methodinfo pointer on Stackframe */
+       p = dseg_addaddress(cd, m);
+       M_ALD(REG_ITMP1, REG_PV, p);
+#if defined(__DARWIN__)
+       M_AST(REG_ITMP1, REG_SP, LA_SIZE + TRACE_ARGS_NUM * 8); 
+#else
+       M_AST(REG_ITMP1, REG_SP, LA_SIZE + 4 * 8);
+#endif
+       p = dseg_addaddress(cd, builtin_trace_args);
+       M_ALD(REG_ITMP2, REG_PV, p);
+       M_MTCTR(REG_ITMP2);
+       M_JSR;
+
+#if defined(__DARWIN__)
+       /* restore integer argument registers from the reserved stack space */
+
+       stack_off = LA_SIZE;
+       for (p = 0; p < md->paramcount && p < TRACE_ARGS_NUM; 
+                p++, stack_off += 8) {
+               t = md->paramtypes[p].type;
+
+               if (IS_INT_LNG_TYPE(t)) {
+                       if (!md->params[p].inmemory) {
+                               if (IS_2_WORD_TYPE(t)) {
+                                       M_ILD(rd->argintregs[GET_HIGH_REG(md->params[p].regoff)]
+                                                 , REG_SP, stack_off);
+                                       M_ILD(rd->argintregs[GET_LOW_REG(md->params[p].regoff)]
+                                                 , REG_SP, stack_off + 4);
+                               } else {
+                                       M_ILD(rd->argintregs[md->params[p].regoff]
+                                                 , REG_SP, stack_off + 4);
+                               }
+                       }
+               }
+       }
+#else
+       /* LINUX */
+       for (p = 0; p < 8; p++) {
+               d = rd->argintregs[p];
+               /* save integer argument registers */
+               M_ILD(d, REG_SP, LA_SIZE + 4 * 8 + 4 + p * 4);
+       }
+#endif
+
+       if (!nativestub)
+               M_ILD(REG_ITMP3, REG_SP, LA_SIZE + TRACE_ARGS_NUM * 8 + 1 * 4);
+
+       M_LDA(REG_SP, REG_SP, stack_size);
+
+       if (!nativestub)
+               M_MTLR(REG_ITMP3);
+}
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
diff --git a/src/vm/jit/powerpc64/codegen.h b/src/vm/jit/powerpc64/codegen.h
new file mode 100644 (file)
index 0000000..5546037
--- /dev/null
@@ -0,0 +1,483 @@
+/* src/vm/jit/powerpc/codegen.h - code generation macros and definitions for
+                                  32-bit PowerPC
+
+   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   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
+            Stefan Ring
+
+   Changes: Christian Thalinger
+            Christian Ullrich
+
+   $Id: codegen.h 5081 2006-07-06 13:59:01Z tbfg $
+
+*/
+
+
+#ifndef _CODEGEN_H
+#define _CODEGEN_H
+
+#include "config.h"
+
+#include "md-abi.h"
+
+#include "vm/global.h"
+#include "vm/jit/jit.h"
+#include "vm/jit/reg.h"
+
+
+/* additional functions and macros to generate code ***************************/
+
+/* gen_nullptr_check(objreg) */
+
+#define gen_nullptr_check(objreg) \
+    if (checknull) { \
+        M_TST((objreg)); \
+        M_BEQ(0); \
+        codegen_add_nullpointerexception_ref(cd); \
+    }
+
+#define gen_bound_check \
+    if (checkbounds) { \
+        M_ILD(REG_ITMP3, s1, OFFSET(java_arrayheader, size));\
+        M_CMPU(s2, REG_ITMP3);\
+        M_BGE(0);\
+        codegen_add_arrayindexoutofboundsexception_ref(cd, s2); \
+    }
+
+
+/* MCODECHECK(icnt) */
+
+#define MCODECHECK(icnt) \
+    do { \
+        if ((cd->mcodeptr + (icnt) * 4) > cd->mcodeend) \
+            codegen_increase(cd); \
+    } while (0)
+
+
+/* M_INTMOVE:
+     generates an integer-move from register a to b.
+     if a and b are the same int-register, no code will be generated.
+*/ 
+
+#define M_INTMOVE(a,b) \
+    do { \
+        if ((a) != (b)) { \
+            M_MOV(a, b); \
+        } \
+    } while (0)
+
+#define M_LNGMOVE(a,b) \
+    do { \
+        if (GET_HIGH_REG(a) == GET_LOW_REG(b)) { \
+            assert((GET_LOW_REG(a) != GET_HIGH_REG(b))); \
+            M_INTMOVE(GET_HIGH_REG(a), GET_HIGH_REG(b)); \
+            M_INTMOVE(GET_LOW_REG(a), GET_LOW_REG(b)); \
+        } else { \
+            M_INTMOVE(GET_LOW_REG(a), GET_LOW_REG(b)); \
+            M_INTMOVE(GET_HIGH_REG(a), GET_HIGH_REG(b)); \
+        } \
+    } 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(a,b) \
+    do { \
+        if ((a) != (b)) { \
+            M_FMOV(a, b); \
+        } \
+    } while (0)
+
+
+#define M_COPY(s,d)                     emit_copy(jd, iptr, (s), (d))
+#define ICONST(d,c)                     emit_iconst(cd, (d), (c))
+
+#define LCONST(reg,c) \
+    ICONST(GET_HIGH_REG((reg)), (s4) ((s8) (c) >> 32));        \
+    ICONST(GET_LOW_REG((reg)), (s4) ((s8) (c)));
+
+
+#define ALIGNCODENOP \
+    if ((s4) ((ptrint) cd->mcodeptr & 7)) { \
+        M_NOP; \
+    }
+
+
+/* macros to create code ******************************************************/
+
+#define M_OP3(opcode,y,oe,rc,d,a,b) \
+    do { \
+        *((u4 *) cd->mcodeptr) = (((opcode) << 26) | ((d) << 21) | ((a) << 16) | ((b) << 11) | ((oe) << 10) | ((y) << 1) | (rc)); \
+        cd->mcodeptr += 4; \
+    } while (0)
+
+#define M_OP4(x,y,rc,d,a,b,c) \
+    do { \
+        *((u4 *) cd->mcodeptr) = (((x) << 26) | ((d) << 21) | ((a) << 16) | ((b) << 11) | ((c) << 6) | ((y) << 1) | (rc)); \
+        cd->mcodeptr += 4; \
+    } while (0)
+
+#define M_OP2_IMM(x,d,a,i) \
+    do { \
+        *((u4 *) cd->mcodeptr) = (((x) << 26) | ((d) << 21) | ((a) << 16) | ((i) & 0xffff)); \
+        cd->mcodeptr += 4; \
+    } while (0)
+
+#define M_BRMASK     0x0000fffc                     /* (((1 << 16) - 1) & ~3) */
+#define M_BRAMASK    0x03fffffc                     /* (((1 << 26) - 1) & ~3) */
+
+#define M_BRA(x,i,a,l) \
+    do { \
+        *((u4 *) cd->mcodeptr) = (((x) << 26) | ((((i) * 4) + 4) & M_BRAMASK) | ((a) << 1) | (l)); \
+        cd->mcodeptr += 4; \
+    } while (0)
+
+#define M_BRAC(x,bo,bi,i,a,l) \
+    do { \
+        *((u4 *) cd->mcodeptr) = (((x) << 26) | ((bo) << 21) | ((bi) << 16) | (((i) * 4 + 4) & M_BRMASK) | ((a) << 1) | (l)); \
+        cd->mcodeptr += 4; \
+    } while (0)
+
+
+/* instruction macros *********************************************************/
+
+#define M_IADD(a,b,c)                   M_OP3(31, 266, 0, 0, c, a, b)
+#define M_IADD_IMM(a,b,c)               M_OP2_IMM(14, c, a, b)
+#define M_ADDC(a,b,c)                   M_OP3(31, 10, 0, 0, c, a, b)
+#define M_ADDIC(a,b,c)                  M_OP2_IMM(12, c, a, b)
+#define M_ADDICTST(a,b,c)               M_OP2_IMM(13, c, a, b)
+#define M_ADDE(a,b,c)                   M_OP3(31, 138, 0, 0, c, a, b)
+#define M_ADDZE(a,b)                    M_OP3(31, 202, 0, 0, b, a, 0)
+#define M_ADDME(a,b)                    M_OP3(31, 234, 0, 0, b, a, 0)
+#define M_ISUB(a,b,c)                   M_OP3(31, 40, 0, 0, c, b, a)
+#define M_ISUBTST(a,b,c)                M_OP3(31, 40, 0, 1, c, b, a)
+#define M_SUBC(a,b,c)                   M_OP3(31, 8, 0, 0, c, b, a)
+#define M_SUBIC(a,b,c)                  M_OP2_IMM(8, c, b, a)
+#define M_SUBE(a,b,c)                   M_OP3(31, 136, 0, 0, c, b, a)
+#define M_SUBZE(a,b)                    M_OP3(31, 200, 0, 0, b, a, 0)
+#define M_SUBME(a,b)                    M_OP3(31, 232, 0, 0, b, a, 0)
+
+#define M_AND(a,b,c)                    M_OP3(31, 28, 0, 0, a, c, b)
+#define M_AND_IMM(a,b,c)                M_OP2_IMM(28, a, c, b)
+#define M_ANDIS(a,b,c)                  M_OP2_IMM(29, a, c, b)
+#define M_OR(a,b,c)                     M_OP3(31, 444, 0, 0, a, c, b)
+#define M_OR_TST(a,b,c)                 M_OP3(31, 444, 0, 1, a, c, b)
+#define M_OR_IMM(a,b,c)                 M_OP2_IMM(24, a, c, b)
+#define M_ORIS(a,b,c)                   M_OP2_IMM(25, a, c, b)
+#define M_XOR(a,b,c)                    M_OP3(31, 316, 0, 0, a, c, b)
+#define M_XOR_IMM(a,b,c)                M_OP2_IMM(26, a, c, b)
+#define M_XORIS(a,b,c)                  M_OP2_IMM(27, a, c, b)
+
+#define M_SLL(a,b,c)                    M_OP3(31, 24, 0, 0, a, c, b)
+#define M_SRL(a,b,c)                    M_OP3(31, 536, 0, 0, a, c, b)
+#define M_SRA(a,b,c)                    M_OP3(31, 792, 0, 0, a, c, b)
+#define M_SRA_IMM(a,b,c)                M_OP3(31, 824, 0, 0, a, c, b)
+
+#define M_IMUL(a,b,c)                   M_OP3(31, 235, 0, 0, c, a, b)
+#define M_IMUL_IMM(a,b,c)               M_OP2_IMM(7, c, a, b)
+#define M_IDIV(a,b,c)                   M_OP3(31, 491, 0, 0, c, a, b)
+
+#define M_NEG(a,b)                      M_OP3(31, 104, 0, 0, b, a, 0)
+#define M_NOT(a,b)                      M_OP3(31, 124, 0, 0, a, b, a)
+
+#define M_SUBFIC(a,b,c)                 M_OP2_IMM(8, c, a, b)
+#define M_SUBFZE(a,b)                   M_OP3(31, 200, 0, 0, b, a, 0)
+#define M_RLWINM(a,b,c,d,e)             M_OP4(21, d, 0, a, e, b, c)
+#define M_ADDZE(a,b)                    M_OP3(31, 202, 0, 0, b, a, 0)
+#define M_SLL_IMM(a,b,c)                M_RLWINM(a,b,0,31-(b),c)
+#define M_SRL_IMM(a,b,c)                M_RLWINM(a,32-(b),b,31,c)
+#define M_ADDIS(a,b,c)                  M_OP2_IMM(15, c, a, b)
+#define M_STFIWX(a,b,c)                 M_OP3(31, 983, 0, 0, a, b, c)
+#define M_LWZX(a,b,c)                   M_OP3(31, 23, 0, 0, a, b, c)
+#define M_LHZX(a,b,c)                   M_OP3(31, 279, 0, 0, a, b, c)
+#define M_LHAX(a,b,c)                   M_OP3(31, 343, 0, 0, a, b, c)
+#define M_LBZX(a,b,c)                   M_OP3(31, 87, 0, 0, a, b, c)
+#define M_LFSX(a,b,c)                   M_OP3(31, 535, 0, 0, a, b, c)
+#define M_LFDX(a,b,c)                   M_OP3(31, 599, 0, 0, a, b, c)
+#define M_STWX(a,b,c)                   M_OP3(31, 151, 0, 0, a, b, c)
+#define M_STHX(a,b,c)                   M_OP3(31, 407, 0, 0, a, b, c)
+#define M_STBX(a,b,c)                   M_OP3(31, 215, 0, 0, a, b, c)
+#define M_STFSX(a,b,c)                  M_OP3(31, 663, 0, 0, a, b, c)
+#define M_STFDX(a,b,c)                  M_OP3(31, 727, 0, 0, a, b, c)
+
+#define M_STWU_INTERN(a,b,disp)         M_OP2_IMM(37,a,b,disp)
+
+#define M_STWU(a,b,disp) \
+    do { \
+        s4 lo = (disp) & 0x0000ffff; \
+        s4 hi = ((disp) >> 16); \
+        if (((disp) >= -32678) && ((disp) <= 32767)) { \
+            M_STWU_INTERN(a,b,lo); \
+        } else { \
+            M_ADDIS(REG_ZERO,hi,REG_ITMP3); \
+            M_OR_IMM(REG_ITMP3,lo,REG_ITMP3); \
+            M_STWUX(REG_SP,REG_SP,REG_ITMP3); \
+        } \
+    } while (0)
+
+#define M_STWUX(a,b,c)                  M_OP3(31,183,0,0,a,b,c)
+
+#define M_LDAH(a,b,c)                   M_ADDIS(b, c, a)
+#define M_TRAP                          M_OP3(31, 4, 0, 0, 31, 0, 0)
+
+#define M_NOP                           M_OR_IMM(0, 0, 0)
+#define M_MOV(a,b)                      M_OR(a, a, b)
+#define M_TST(a)                        M_OP3(31, 444, 0, 1, a, a, a)
+
+#define M_DADD(a,b,c)                   M_OP3(63, 21, 0, 0, c, a, b)
+#define M_FADD(a,b,c)                   M_OP3(59, 21, 0, 0, c, a, b)
+#define M_DSUB(a,b,c)                   M_OP3(63, 20, 0, 0, c, a, b)
+#define M_FSUB(a,b,c)                   M_OP3(59, 20, 0, 0, c, a, b)
+#define M_DMUL(a,b,c)                   M_OP4(63, 25, 0, c, a, 0, b)
+#define M_FMUL(a,b,c)                   M_OP4(59, 25, 0, c, a, 0, b)
+#define M_DDIV(a,b,c)                   M_OP3(63, 18, 0, 0, c, a, b)
+#define M_FDIV(a,b,c)                   M_OP3(59, 18, 0, 0, c, a, b)
+
+#define M_FABS(a,b)                     M_OP3(63, 264, 0, 0, b, 0, a)
+#define M_CVTDL(a,b)                    M_OP3(63, 14, 0, 0, b, 0, a)
+#define M_CVTDL_C(a,b)                  M_OP3(63, 15, 0, 0, b, 0, a)
+#define M_CVTDF(a,b)                    M_OP3(63, 12, 0, 0, b, 0, a)
+#define M_FMOV(a,b)                     M_OP3(63, 72, 0, 0, b, 0, a)
+#define M_FMOVN(a,b)                    M_OP3(63, 40, 0, 0, b, 0, a)
+#define M_DSQRT(a,b)                    M_OP3(63, 22, 0, 0, b, 0, a)
+#define M_FSQRT(a,b)                    M_OP3(59, 22, 0, 0, b, 0, a)
+
+#define M_FCMPU(a,b)                    M_OP3(63, 0, 0, 0, 0, a, b)
+#define M_FCMPO(a,b)                    M_OP3(63, 32, 0, 0, 0, a, b)
+
+#define M_BLDU(a,b,c)                   M_OP2_IMM(34, a, b, c)
+#define M_SLDU(a,b,c)                   M_OP2_IMM(40, a, b, c)
+
+#define M_ILD_INTERN(a,b,disp)          M_OP2_IMM(32,a,b,disp)
+
+#define M_ILD(a,b,disp) \
+    do { \
+        s4 lo = (short) (disp); \
+        s4 hi = (short) (((disp) - lo) >> 16); \
+        if (hi == 0) { \
+            M_ILD_INTERN(a,b,lo); \
+        } else { \
+            M_ADDIS(b,hi,a); \
+            M_ILD_INTERN(a,a,lo); \
+        } \
+    } while (0)
+
+#define M_LLD_INTERN(a,b,disp) \
+    do { \
+        M_ILD_INTERN(GET_HIGH_REG(a), b, disp); \
+        M_ILD_INTERN(GET_LOW_REG(a), b, disp + 4); \
+    } while (0)
+
+#define M_LLD(a,b,disp) \
+    do { \
+        s4 lo = (short) (disp); \
+        s4 hi = (short) (((disp) - lo) >> 16); \
+        if (hi == 0) { \
+            M_LLD_INTERN(a,b,lo); \
+        } else { \
+            M_ADDIS(b,hi,a); \
+            M_LLD_INTERN(a,GET_LOW_REG(a),lo); \
+        } \
+    } while (0)
+
+#define M_ALD_INTERN(a,b,disp)          M_ILD_INTERN(a,b,disp)
+#define M_ALD(a,b,disp)                 M_ILD(a,b,disp)
+
+#define M_BST(a,b,c)                    M_OP2_IMM(38, a, b, c)
+#define M_SST(a,b,c)                    M_OP2_IMM(44, a, b, c)
+
+#define M_IST_INTERN(a,b,disp)          M_OP2_IMM(36,a,b,disp)
+
+/* Stores with displacement overflow should only happen with PUTFIELD
+   or on the stack. The PUTFIELD instruction does not use REG_ITMP3
+   and a reg_of_var call should not use REG_ITMP3!!! */
+
+#define M_IST(a,b,disp) \
+    do { \
+        s4 lo = (short) (disp); \
+        s4 hi = (short) (((disp) - lo) >> 16); \
+        if (hi == 0) { \
+            M_IST_INTERN(a,b,lo); \
+        } else { \
+            M_ADDIS(b,hi,REG_ITMP3); \
+            M_IST_INTERN(a,REG_ITMP3,lo); \
+        } \
+    } while (0)
+
+#define M_LST_INTERN(a,b,disp) \
+    do { \
+        M_IST_INTERN(GET_HIGH_REG(a), b, disp); \
+        M_IST_INTERN(GET_LOW_REG(a), b, disp + 4); \
+    } while (0)
+
+#define M_LST(a,b,disp) \
+    do { \
+        s4 lo = (short) (disp); \
+        s4 hi = (short) (((disp) - lo) >> 16); \
+        if (hi == 0) { \
+            M_LST_INTERN(a,b,lo); \
+        } else { \
+            M_ADDIS(b,hi,REG_ITMP3); \
+            M_LST_INTERN(a,REG_ITMP3, lo); \
+        } \
+    } while (0)
+
+#define M_AST_INTERN(a,b,disp)          M_IST_INTERN(a,b,disp)
+#define M_AST(a,b,disp)                 M_IST(a,b,disp)
+
+#define M_BSEXT(a,b)                    M_OP3(31, 954, 0, 0, a, b, 0)
+#define M_SSEXT(a,b)                    M_OP3(31, 922, 0, 0, a, b, 0)
+#define M_CZEXT(a,b)                    M_RLWINM(a,0,16,31,b)
+
+#define M_BR(a)                         M_BRA(18, a, 0, 0)
+#define M_BL(a)                         M_BRA(18, a, 0, 1)
+#define M_RET                           M_OP3(19, 16, 0, 0, 20, 0, 0)
+#define M_JSR                           M_OP3(19, 528, 0, 1, 20, 0, 0)
+#define M_RTS                           M_OP3(19, 528, 0, 0, 20, 0, 0)
+
+#define M_CMP(a,b)                      M_OP3(31, 0, 0, 0, 0, a, b)
+#define M_CMPU(a,b)                     M_OP3(31, 32, 0, 0, 0, a, b)
+#define M_CMPI(a,b)                     M_OP2_IMM(11, 0, a, b)
+#define M_CMPUI(a,b)                    M_OP2_IMM(10, 0, a, b)
+
+#define M_BLT(a)                        M_BRAC(16, 12, 0, a, 0, 0)
+#define M_BLE(a)                        M_BRAC(16, 4, 1, a, 0, 0)
+#define M_BGT(a)                        M_BRAC(16, 12, 1, a, 0, 0)
+#define M_BGE(a)                        M_BRAC(16, 4, 0, a, 0, 0)
+#define M_BEQ(a)                        M_BRAC(16, 12, 2, a, 0, 0)
+#define M_BNE(a)                        M_BRAC(16, 4, 2, a, 0, 0)
+#define M_BNAN(a)                       M_BRAC(16, 12, 3, a, 0, 0)
+
+#define M_FLD_INTERN(a,b,disp)          M_OP2_IMM(48,a,b,disp)
+#define M_DLD_INTERN(a,b,disp)          M_OP2_IMM(50,a,b,disp)
+
+#define M_FLD(a,b,disp) \
+    do { \
+        s4 lo = (short) (disp); \
+        s4 hi = (short) (((disp) - lo) >> 16); \
+        if (hi == 0) { \
+            M_FLD_INTERN(a,b,lo); \
+        } else { \
+            M_ADDIS(b,hi,REG_ITMP3); \
+            M_FLD_INTERN(a,REG_ITMP3,lo); \
+        } \
+    } while (0)
+
+#define M_DLD(a,b,disp) \
+    do { \
+        s4 lo = (short) (disp); \
+        s4 hi = (short) (((disp) - lo) >> 16); \
+        if (hi == 0) { \
+            M_DLD_INTERN(a,b,lo); \
+        } else { \
+            M_ADDIS(b,hi,REG_ITMP3); \
+            M_DLD_INTERN(a,REG_ITMP3,lo); \
+        } \
+    } while (0)
+
+#define M_FST_INTERN(a,b,disp)          M_OP2_IMM(52,a,b,disp)
+#define M_DST_INTERN(a,b,disp)          M_OP2_IMM(54,a,b,disp)
+
+#define M_FST(a,b,disp) \
+    do { \
+        s4 lo = (short) (disp); \
+        s4 hi = (short) (((disp) - lo) >> 16); \
+        if (hi == 0) { \
+            M_FST_INTERN(a,b,lo); \
+        } else { \
+            M_ADDIS(b,hi,REG_ITMP3); \
+            M_FST_INTERN(a,REG_ITMP3,lo); \
+        } \
+    } while (0)
+
+#define M_DST(a,b,disp) \
+    do { \
+        s4 lo = (short) (disp); \
+        s4 hi = (short) (((disp) - lo) >> 16); \
+        if (hi == 0) { \
+            M_DST_INTERN(a,b,lo); \
+        } else { \
+            M_ADDIS(b,hi,REG_ITMP3); \
+            M_DST_INTERN(a,REG_ITMP3,lo); \
+        } \
+    } while (0)
+
+#define M_MFLR(a)                       M_OP3(31, 339, 0, 0, a, 8, 0)
+#define M_MFXER(a)                      M_OP3(31, 339, 0, 0, a, 1, 0)
+#define M_MFCTR(a)                      M_OP3(31, 339, 0, 0, a, 9, 0)
+#define M_MTLR(a)                       M_OP3(31, 467, 0, 0, a, 8, 0)
+#define M_MTXER(a)                      M_OP3(31, 467, 0, 0, a, 1, 0)
+#define M_MTCTR(a)                      M_OP3(31, 467, 0, 0, a, 9, 0)
+
+#define M_LDA_INTERN(a,b,c)             M_IADD_IMM(b, c, a)
+
+#define M_LDA(a,b,disp) \
+    do { \
+        s4 lo = (short) (disp); \
+        s4 hi = (short) (((disp) - lo) >> 16); \
+        if (hi == 0) { \
+            M_LDA_INTERN(a,b,lo); \
+        } else { \
+            M_ADDIS(b,hi,a); \
+            M_LDA_INTERN(a,a,lo); \
+        } \
+    } while (0)
+
+
+#define M_LDATST(a,b,c)                 M_ADDICTST(b, c, a)
+#define M_CLR(a)                        M_IADD_IMM(0, 0, a)
+#define M_AADD_IMM(a,b,c)               M_IADD_IMM(a, b, c)
+
+
+/* function gen_resolvebranch **************************************************
+
+       parameters: ip ... pointer to instruction after branch (void*)
+                   so ... offset of instruction after branch  (s4)
+                   to ... offset of branch target             (s4)
+
+*******************************************************************************/
+
+#define gen_resolvebranch(ip,so,to) \
+       *((s4*)(ip)-1)=(*((s4*)(ip)-1) & ~M_BRMASK) | (((s4)((to)-(so))+4)&((((*((s4*)(ip)-1)>>26)&63)==18)?M_BRAMASK:M_BRMASK))
+
+#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/powerpc64/disass.c b/src/vm/jit/powerpc64/disass.c
new file mode 100644 (file)
index 0000000..f7ad860
--- /dev/null
@@ -0,0 +1,92 @@
+/* src/vm/jit/powerpc/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: Stefan Ring
+            Christian Thalinger
+
+   $Id: disass.c 5081 2006-07-06 13:59:01Z tbfg $
+
+*/
+
+
+#include "config.h"
+
+#include <dis-asm.h>
+#include <stdio.h>
+
+#include "vm/types.h"
+
+#include "vm/global.h"
+#include "vm/jit/disass.h"
+
+
+/* disassinstr *****************************************************************
+
+   Outputs a disassembler listing of one machine code instruction on
+   `stdout'.
+
+   code: pointer to machine code
+
+*******************************************************************************/
+
+u1 *disassinstr(u1 *code)
+{
+       if (!disass_initialized) {
+               INIT_DISASSEMBLE_INFO(info, NULL, disass_printf);
+
+               /* setting the struct members must be done after
+                  INIT_DISASSEMBLE_INFO */
+
+               info.read_memory_func = &disass_buffer_read_memory;
+
+               disass_initialized = true;
+       }
+
+       printf("0x%08x:   %08x    ", (s4) code, *((s4 *) code));
+
+       print_insn_big_powerpc((bfd_vma) code, &info);
+
+       printf("\n");
+
+       return code + 4;
+}
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
diff --git a/src/vm/jit/powerpc64/emit.c b/src/vm/jit/powerpc64/emit.c
new file mode 100644 (file)
index 0000000..ec9ad6e
--- /dev/null
@@ -0,0 +1,488 @@
+/* src/vm/jit/powerpc/emit.c - PowerPC 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
+
+   Changes:
+
+   $Id: emitfuncs.c 4398 2006-01-31 23:43:08Z twisti $
+
+*/
+
+
+#include "config.h"
+
+#include <assert.h>
+
+#include "vm/types.h"
+
+#include "md-abi.h"
+
+#include "vm/jit/emit.h"
+#include "vm/jit/jit.h"
+#include "vm/jit/powerpc/codegen.h"
+
+
+/* code generation functions **************************************************/
+
+/* emit_load_s1 ****************************************************************
+
+   Emits a possible load of the first source operand.
+
+*******************************************************************************/
+
+s4 emit_load_s1(jitdata *jd, instruction *iptr, stackptr src, s4 tempreg)
+{
+       codegendata  *cd;
+       s4            disp;
+       s4            reg;
+
+       /* get required compiler data */
+
+       cd = jd->cd;
+
+       if (src->flags & INMEMORY) {
+               COUNT_SPILLS;
+
+               disp = src->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->regoff;
+
+       return reg;
+}
+
+
+/* emit_load_s2 ****************************************************************
+
+   Emits a possible load of the second source operand.
+
+*******************************************************************************/
+
+s4 emit_load_s2(jitdata *jd, instruction *iptr, stackptr src, s4 tempreg)
+{
+       codegendata  *cd;
+       s4            disp;
+       s4            reg;
+
+       /* get required compiler data */
+
+       cd = jd->cd;
+
+       if (src->flags & INMEMORY) {
+               COUNT_SPILLS;
+
+               disp = src->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->regoff;
+
+       return reg;
+}
+
+
+/* emit_load_s3 ****************************************************************
+
+   Emits a possible load of the third source operand.
+
+*******************************************************************************/
+
+s4 emit_load_s3(jitdata *jd, instruction *iptr, stackptr src, s4 tempreg)
+{
+       codegendata  *cd;
+       s4            disp;
+       s4            reg;
+
+       /* get required compiler data */
+
+       cd = jd->cd;
+
+       if (src->flags & INMEMORY) {
+               COUNT_SPILLS;
+
+               disp = src->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->regoff;
+
+       return reg;
+}
+
+
+/* emit_load_s1_low ************************************************************
+
+   Emits a possible load of the low 32-bits of the first long source
+   operand.
+
+*******************************************************************************/
+
+s4 emit_load_s1_low(jitdata *jd, instruction *iptr, stackptr src, s4 tempreg)
+{
+       codegendata  *cd;
+       s4            disp;
+       s4            reg;
+
+       assert(src->type == TYPE_LNG);
+
+       /* get required compiler data */
+
+       cd = jd->cd;
+
+       if (src->flags & INMEMORY) {
+               COUNT_SPILLS;
+
+               disp = src->regoff * 4;
+
+               M_ILD(tempreg, REG_SP, disp + 4);
+
+               reg = tempreg;
+       } else
+               reg = GET_LOW_REG(src->regoff);
+
+       return reg;
+}
+
+
+/* emit_load_s2_low ************************************************************
+
+   Emits a possible load of the low 32-bits of the second long source
+   operand.
+
+*******************************************************************************/
+
+s4 emit_load_s2_low(jitdata *jd, instruction *iptr, stackptr src, s4 tempreg)
+{
+       codegendata  *cd;
+       s4            disp;
+       s4            reg;
+
+       assert(src->type == TYPE_LNG);
+
+       /* get required compiler data */
+
+       cd = jd->cd;
+
+       if (src->flags & INMEMORY) {
+               COUNT_SPILLS;
+
+               disp = src->regoff * 4;
+
+               M_ILD(tempreg, REG_SP, disp + 4);
+
+               reg = tempreg;
+       } else
+               reg = GET_LOW_REG(src->regoff);
+
+       return reg;
+}
+
+
+/* emit_load_s3_low ************************************************************
+
+   Emits a possible load of the low 32-bits of the third long source
+   operand.
+
+*******************************************************************************/
+
+s4 emit_load_s3_low(jitdata *jd, instruction *iptr, stackptr src, s4 tempreg)
+{
+       codegendata  *cd;
+       s4            disp;
+       s4            reg;
+
+       assert(src->type == TYPE_LNG);
+
+       /* get required compiler data */
+
+       cd = jd->cd;
+
+       if (src->flags & INMEMORY) {
+               COUNT_SPILLS;
+
+               disp = src->regoff * 4;
+
+               M_ILD(tempreg, REG_SP, disp + 4);
+
+               reg = tempreg;
+       } else
+               reg = GET_LOW_REG(src->regoff);
+
+       return reg;
+}
+
+
+/* emit_load_s1_high ***********************************************************
+
+   Emits a possible load of the high 32-bits of the first long source
+   operand.
+
+*******************************************************************************/
+
+s4 emit_load_s1_high(jitdata *jd, instruction *iptr, stackptr src, s4 tempreg)
+{
+       codegendata  *cd;
+       s4            disp;
+       s4            reg;
+
+       assert(src->type == TYPE_LNG);
+
+       /* get required compiler data */
+
+       cd = jd->cd;
+
+       if (src->flags & INMEMORY) {
+               COUNT_SPILLS;
+
+               disp = src->regoff * 4;
+
+               M_ILD(tempreg, REG_SP, disp);
+
+               reg = tempreg;
+       } else
+               reg = GET_HIGH_REG(src->regoff);
+
+       return reg;
+}
+
+
+/* emit_load_s2_high ***********************************************************
+
+   Emits a possible load of the high 32-bits of the second long source
+   operand.
+
+*******************************************************************************/
+
+s4 emit_load_s2_high(jitdata *jd, instruction *iptr, stackptr src, s4 tempreg)
+{
+       codegendata  *cd;
+       s4            disp;
+       s4            reg;
+
+       assert(src->type == TYPE_LNG);
+
+       /* get required compiler data */
+
+       cd = jd->cd;
+
+       if (src->flags & INMEMORY) {
+               COUNT_SPILLS;
+
+               disp = src->regoff * 4;
+
+               M_ILD(tempreg, REG_SP, disp);
+
+               reg = tempreg;
+       } else
+               reg = GET_HIGH_REG(src->regoff);
+
+       return reg;
+}
+
+
+/* emit_load_s3_high ***********************************************************
+
+   Emits a possible load of the high 32-bits of the third long source
+   operand.
+
+*******************************************************************************/
+
+s4 emit_load_s3_high(jitdata *jd, instruction *iptr, stackptr src, s4 tempreg)
+{
+       codegendata  *cd;
+       s4            disp;
+       s4            reg;
+
+       assert(src->type == TYPE_LNG);
+
+       /* get required compiler data */
+
+       cd = jd->cd;
+
+       if (src->flags & INMEMORY) {
+               COUNT_SPILLS;
+
+               disp = src->regoff * 4;
+
+               M_ILD(tempreg, REG_SP, disp);
+
+               reg = tempreg;
+       } else
+               reg = GET_HIGH_REG(src->regoff);
+
+       return reg;
+}
+
+
+/* emit_store ******************************************************************
+
+   XXX
+
+*******************************************************************************/
+
+void emit_store(jitdata *jd, instruction *iptr, stackptr dst, s4 d)
+{
+       codegendata  *cd;
+
+       /* get required compiler data */
+
+       cd = jd->cd;
+
+       if (dst->flags & INMEMORY) {
+               COUNT_SPILLS;
+
+               if (IS_FLT_DBL_TYPE(dst->type)) {
+                       if (IS_2_WORD_TYPE(dst->type))
+                               M_DST(d, REG_SP, dst->regoff * 4);
+                       else
+                               M_FST(d, REG_SP, dst->regoff * 4);
+
+               } else {
+                       if (IS_2_WORD_TYPE(dst->type))
+                               M_LST(d, REG_SP, dst->regoff * 4);
+                       else
+                               M_IST(d, REG_SP, dst->regoff * 4);
+               }
+       }
+}
+
+
+/* emit_copy *******************************************************************
+
+   XXX
+
+*******************************************************************************/
+
+void emit_copy(jitdata *jd, instruction *iptr, stackptr src, stackptr dst)
+{
+       codegendata  *cd;
+       registerdata *rd;
+       s4            s1, d;
+
+       /* get required compiler data */
+
+       cd = jd->cd;
+       rd = jd->rd;
+
+       if (src->type == TYPE_LNG)
+               d = codegen_reg_of_var(rd, iptr->opc, dst, PACK_REGS(REG_ITMP2, REG_ITMP1));
+       else
+               d = codegen_reg_of_var(rd, iptr->opc, dst, REG_IFTMP);
+
+       if ((src->regoff != dst->regoff) ||
+               ((src->flags ^ dst->flags) & INMEMORY)) {
+               s1 = emit_load_s1(jd, iptr, src, d);
+
+               if (s1 != d) {
+                       if (IS_FLT_DBL_TYPE(src->type))
+                               M_FMOV(s1, d);
+                       else {
+                               if (IS_2_WORD_TYPE(src->type)) {
+                                       M_MOV(GET_LOW_REG(s1), GET_LOW_REG(d));
+                                       M_MOV(GET_HIGH_REG(s1), GET_HIGH_REG(d));
+                } else
+                    M_MOV(s1, d);
+                       }
+               }
+
+               emit_store(jd, iptr, dst, d);
+       }
+}
+
+
+/* emit_iconst *****************************************************************
+
+   XXX
+
+*******************************************************************************/
+
+void emit_iconst(codegendata *cd, s4 d, s4 value)
+{
+       s4 disp;
+
+       if ((value >= -32768) && (value <= 32767))
+               M_LDA_INTERN(d, REG_ZERO, value);
+       else {
+               disp = dseg_adds4(cd, value);
+               M_ILD(d, REG_PV, disp);
+       }
+}
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
diff --git a/src/vm/jit/powerpc64/linux/Makefile.am b/src/vm/jit/powerpc64/linux/Makefile.am
new file mode 100644 (file)
index 0000000..5207e3d
--- /dev/null
@@ -0,0 +1,56 @@
+## src/vm/jit/powerpc64/linux/Makefile.am
+##
+## Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+## C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
+## E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
+## J. Wenninger, Institut f. Computersprachen - TU Wien
+##
+## This file is part of CACAO.
+##
+## This program is free software; you can redistribute it and/or
+## modify it under the terms of the GNU General Public License as
+## published by the Free Software Foundation; either version 2, or (at
+## your option) any later version.
+##
+## This program is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+## 02110-1301, USA.
+##
+## Contact: cacao@cacaojvm.org
+##
+## Authors: Christian Thalinger
+##
+## Changes:
+##
+## $Id: Makefile.am 5081 2006-07-06 13:59:01Z tbfg $
+
+## Process this file with automake to produce Makefile.in
+
+AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/src/vm/jit/$(ARCH_DIR)
+
+LIBS =
+
+noinst_HEADERS = \
+       md-asm.h
+
+noinst_LTLIBRARIES = libmd.la
+
+libmd_la_SOURCES = \
+       md-abi.c \
+       md-abi.h \
+       md-os.c
+
+
+## Local variables:
+## mode: Makefile
+## indent-tabs-mode: t
+## c-basic-offset: 4
+## tab-width: 8
+## compile-command: "automake --add-missing"
+## End:
diff --git a/src/vm/jit/powerpc64/linux/md-abi.c b/src/vm/jit/powerpc64/linux/md-abi.c
new file mode 100644 (file)
index 0000000..5ebf87e
--- /dev/null
@@ -0,0 +1,273 @@
+/* src/vm/jit/powerpc64/linux/md-abi.c - functions for PowerPC64 Linux ABI
+
+   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
+   E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
+   J. Wenninger, Institut f. Computersprachen - TU Wien
+
+   This file is part of CACAO.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
+
+   Contact: cacao@cacaojvm.org
+
+   Authors: Roland Lezuo
+
+   Changes: 
+
+   $Id: md-abi.c 5081 2006-07-06 13:59:01Z tbfg $
+
+*/
+
+
+#include "config.h"
+#include "vm/types.h"
+
+#include "vm/jit/powerpc64/linux/md-abi.h"
+
+#include "vm/descriptor.h"
+#include "vm/global.h"
+
+
+#define _ALIGN(a)    do { if ((a) & 1) (a)++; } while (0)
+
+
+/* register descripton array **************************************************/
+
+s4 nregdescint[] = {
+        /* zero,      sp,     TOC,   a0/v0,   a0/v1,      a2,      a3,      a4,   */
+        REG_RES, REG_RES, REG_RES, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG,
+
+        /*   a5,      a6,      a7,   itmp1,   itmp2, NO(SYS),      pv,      s0,   */
+        REG_ARG, REG_ARG, REG_ARG, REG_RES, REG_RES, REG_RES, REG_SAV, REG_SAV,
+
+        /*itmp3,      t0,      t1,      t2,      t3,      t4,      t5,      t6,   */
+        REG_RES, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
+
+        /*   s1,      s2,      s3,      s4,      s5,      s6,      s7,      s8,   */
+        REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
+
+        REG_END
+};
+
+char *regs[] = {
+        "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7",
+        "r8",  "r9",  "r10", "r11", "r12", "r13", "r14", "r15",
+        "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
+        "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
+};
+
+
+s4 nregdescfloat[] = {
+        /*ftmp3,  fa0/v0,     fa1,     fa2,     fa3,     fa4,     fa5,     fa6,   */
+        REG_RES, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG,
+
+        /*  fa7,     ft0,     ft1,     ft2,     ft3,     ft4,     fs0,     fs1,   */
+        REG_ARG, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_SAV, REG_SAV,
+
+        /*ftmp1,   ftmp2,     ft5,     ft6,     ft7,     ft8,     ft9,    ft10,   */
+        REG_RES, REG_RES, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
+
+        /*  fs2,     fs3,     fs4,     fs5,     fs6,     fs7,     fs8,     fs9    */
+        REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
+
+        REG_END
+};
+
+/* md_param_alloc **************************************************************
+
+   Allocate Arguments to Stackslots according the Calling Conventions
+
+   --- in
+   md->paramcount:           Number of arguments for this method
+   md->paramtypes[].type:    Argument types
+
+   --- out
+   md->params[].inmemory:    Argument spilled on stack
+   md->params[].regoff:      Stack offset or rd->arg[int|flt]regs index
+   md->memuse:               Stackslots needed for argument spilling
+   md->argintreguse:         max number of integer arguments used
+   md->argfltreguse:         max number of float arguments used
+
+*******************************************************************************/
+
+void md_param_alloc(methoddesc *md)
+{
+       paramdesc *pd;
+       s4         i;
+       s4         iarg;
+       s4         farg;
+       s4         stacksize;
+
+       /* set default values */
+
+       iarg = 0;
+       farg = 0;
+       stacksize = LA_WORD_SIZE;
+
+       /* 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:
+                       if (iarg < INT_ARG_CNT) {
+                               pd->inmemory = false;
+                               pd->regoff = iarg;
+                               iarg++;
+                       } else {
+                               pd->inmemory = true;
+                               pd->regoff = stacksize;
+                               stacksize++;
+                       }
+                       break;
+               case TYPE_LNG:
+                       if (iarg < INT_ARG_CNT - 1) {
+                               _ALIGN(iarg);
+                               pd->inmemory = false;
+                                                            /* rd->arg[int|flt]regs index !! */
+                               pd->regoff = PACK_REGS(iarg + 1, iarg); 
+                               iarg += 2;
+                       } else {
+                               _ALIGN(stacksize);
+                               pd->inmemory = true;
+                               pd->regoff = stacksize;
+                               iarg = INT_ARG_CNT;
+                               stacksize += 2;
+                       }
+                       break;
+               case TYPE_FLT:
+                       if (farg < FLT_ARG_CNT) {
+                               pd->inmemory = false;
+                               pd->regoff = farg;
+                               farg++;
+                       } else {
+                               pd->inmemory = true;
+                               pd->regoff = stacksize;
+                               stacksize++;
+                       }
+                       break;
+               case TYPE_DBL:
+                       if (farg < FLT_ARG_CNT) {
+                               pd->inmemory = false;
+                               pd->regoff = farg;
+                               farg++;
+                       } else {
+                               _ALIGN(stacksize);
+                               pd->inmemory = true;
+                               pd->regoff = stacksize;
+                               stacksize += 2;
+                       }
+                       break;
+               }
+       }
+
+       /* Since R3/R4, F1 (==A0/A1, A0) are used for passing return values, this */
+       /* argument register usage has to be regarded, too                        */
+       if (IS_INT_LNG_TYPE(md->returntype.type)) {
+               if (iarg < (IS_2_WORD_TYPE(md->returntype.type) ? 2 : 1))
+                       iarg = IS_2_WORD_TYPE(md->returntype.type) ? 2 : 1;
+       } else {
+               if (IS_FLT_DBL_TYPE(md->returntype.type))
+                       if (farg < 1)
+                               farg = 1;
+       }
+
+       /* fill register and stack usage */
+
+       md->argintreguse = iarg;
+       md->argfltreguse = farg;
+       md->memuse = stacksize;
+}
+
+
+/* md_return_alloc *************************************************************
+
+   Precolor the Java Stackelement containing the Return Value, if
+   possible.  (R3==a00 for int/adr, R4/R3 == a01/a00 for long, F1==a00
+   for float/double)
+
+   --- in
+   m:                       Methodinfo of current method
+   return_type:             Return Type of the Method (TYPE_INT.. TYPE_ADR)
+                            TYPE_VOID is not allowed!
+   stackslot:               Java Stackslot to contain the Return Value
+
+   --- out
+   if precoloring was possible:
+   stackslot->varkind       =ARGVAR
+            ->varnum        =-1
+               ->flags         =0
+               ->regoff        =[REG_RESULT, (REG_RESULT2/REG_RESULT), REG_FRESULT]
+   rd->arg[flt|int]reguse   set to a value according the register usage
+
+*******************************************************************************/
+
+void md_return_alloc(methodinfo *m, registerdata *rd, s4 return_type,
+                                        stackptr stackslot)
+{
+       /* In Leafmethods Local Vars holding parameters are precolored to
+          their argument register -> so leafmethods with paramcount > 0
+          could already use R3 == a00! */
+
+       if (!m->isleafmethod || (m->parseddesc->paramcount == 0)) {
+               /* Only precolor the stackslot, if it is not a SAVEDVAR <->
+                  has not to survive method invokations. */
+
+               if (!(stackslot->flags & SAVEDVAR)) {
+                       stackslot->varkind = ARGVAR;
+                       stackslot->varnum = -1;
+                       stackslot->flags = 0;
+
+                       if (IS_INT_LNG_TYPE(return_type)) {
+                               if (!IS_2_WORD_TYPE(return_type)) {
+                                       if (rd->argintreguse < 1)
+                                               rd->argintreguse = 1;
+
+                                       stackslot->regoff = REG_RESULT;
+
+                               } else {
+                                       if (rd->argintreguse < 2)
+                                               rd->argintreguse = 2;
+
+       /*                                      stackslot->regoff = PACK_REGS(REG_RESULT2, REG_RESULT); // FIXME */
+                               }
+
+                       } else { /* float/double */
+                               if (rd->argfltreguse < 1)
+                                       rd->argfltreguse = 1;
+
+                               stackslot->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:
+ */
index fba1168ef9c871cae21b8a7f6eac08145e32849a..a7f6651aeaf7b3a43082b0862dabf48801434691 100644 (file)
@@ -28,7 +28,7 @@
 
    Changes:
 
-   $Id: md-abi.h 4357 2006-01-22 23:33:38Z twisti $
+   $Id: md-abi.h 5081 2006-07-06 13:59:01Z tbfg $
 
 */
 
@@ -42,7 +42,7 @@
   
 #define REG_RESULT       3   /* to deliver method results                     */
 
-#define REG_PV          13   /* procedure vector, must be provided by caller  */
+#define REG_PV          14   /* procedure vector, must be provided by caller  */
 #define REG_METHODPTR   12   /* pointer to the place from where the procedure */
                              /* vector has been fetched                       */
 #define REG_ITMP1       11   /* temporary register                            */
diff --git a/src/vm/jit/powerpc64/linux/md-asm.h b/src/vm/jit/powerpc64/linux/md-asm.h
new file mode 100644 (file)
index 0000000..36f18b2
--- /dev/null
@@ -0,0 +1,222 @@
+/* src/vm/jit/powerpc64/linux/md-asm.h - assembler defines for PowerPC 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 5081 2006-07-06 13:59:01Z tbfg $
+
+*/
+
+
+#ifndef _MD_ASM_H
+#define _MD_ASM_H
+
+#include <asm/ppc_asm.h>
+
+
+/* register defines ***********************************************************/
+
+#define zero  r0
+#define sp    r1
+
+/* #define XXX   r2  -  system reserved register */
+
+#define a0    r3
+#define a1    r4
+#define a2    r5
+#define a3    r6
+#define a4    r7
+#define a5    r8
+#define a6    r9
+#define a7    r10
+
+#define itmp1 r11
+#define itmp2 r12
+#define pv    r13
+
+#define s0    r14
+#define s1    r15
+
+#define itmp3 r16
+#define t0    r17
+#define t1    r18
+#define t2    r19
+#define t3    r20
+#define t4    r21
+#define t5    r22
+#define t6    r23
+
+#define s2    r24
+#define s3    r25
+#define s4    r26
+#define s5    r27
+#define s6    r28
+#define s7    r29
+#define s8    r30
+#define s9    r31
+
+#define v0    a0
+#define v1    a1
+
+#define xptr  itmp1
+#define xpc   itmp2
+
+#define mptr  r12
+#define mptrn 12
+
+
+#define ftmp3 fr0
+
+#define fa0   fr1
+#define fa1   fr2
+#define fa2   fr3
+#define fa3   fr4
+#define fa4   fr5
+#define fa5   fr6
+#define fa6   fr7
+#define fa7   fr8
+
+#define fa8   fr9
+#define fa9   fr10
+#define fa10  fr11
+#define fa11  fr12
+#define fa12  fr13
+
+#define fs0   fr14
+#define fs1   fr15
+
+#define ftmp1 fr16
+#define ftmp2 fr17
+
+#define ft0   fr18
+#define ft1   fr19
+#define ft2   fr20
+#define ft3   fr21
+#define ft4   fr22
+#define ft5   fr23
+
+#define fs2   fr24
+#define fs3   fr25
+#define fs4   fr26
+#define fs5   fr27
+#define fs6   fr28
+#define fs7   fr29
+#define fs8   fr30
+#define fs9   fr31
+
+#define fv0   fa0
+
+
+/* save and restore macros ****************************************************/
+
+#define SAVE_ARGUMENT_REGISTERS(off) \
+       stw     a0,(0+(off))*4(sp); \
+       stw     a1,(1+(off))*4(sp); \
+       stw     a2,(2+(off))*4(sp); \
+       stw     a3,(3+(off))*4(sp); \
+       stw     a4,(4+(off))*4(sp); \
+       stw     a5,(5+(off))*4(sp); \
+       stw     a6,(6+(off))*4(sp); \
+       stw     a7,(7+(off))*4(sp); \
+       \
+       stfd    fa0,(8+(off))*4(sp); \
+       stfd    fa1,(10+(off))*4(sp); \
+       stfd    fa2,(12+(off))*4(sp); \
+       stfd    fa3,(14+(off))*4(sp); \
+       stfd    fa4,(16+(off))*4(sp); \
+       stfd    fa5,(18+(off))*4(sp); \
+       stfd    fa6,(20+(off))*4(sp); \
+       stfd    fa7,(22+(off))*4(sp);
+
+#define RESTORE_ARGUMENT_REGISTERS(off) \
+       lwz     a0,(0+(off))*4(sp); \
+       lwz     a1,(1+(off))*4(sp); \
+       lwz     a2,(2+(off))*4(sp); \
+       lwz     a3,(3+(off))*4(sp); \
+       lwz     a4,(4+(off))*4(sp); \
+       lwz     a5,(5+(off))*4(sp); \
+       lwz     a6,(6+(off))*4(sp); \
+       lwz     a7,(7+(off))*4(sp); \
+       \
+       lfd     fa0,(8+(off))*4(sp); \
+       lfd     fa1,(10+(off))*4(sp); \
+       lfd     fa2,(12+(off))*4(sp); \
+       lfd     fa3,(14+(off))*4(sp); \
+       lfd     fa4,(16+(off))*4(sp); \
+       lfd     fa5,(18+(off))*4(sp); \
+       lfd     fa6,(20+(off))*4(sp); \
+       lfd     fa7,(22+(off))*4(sp);
+
+
+#define SAVE_TEMPORARY_REGISTERS(off) \
+       stw     t0,(0+(off))*4(sp); \
+       stw     t1,(1+(off))*4(sp); \
+       stw     t2,(2+(off))*4(sp); \
+       stw     t3,(3+(off))*4(sp); \
+       stw     t4,(4+(off))*4(sp); \
+       stw     t5,(5+(off))*4(sp); \
+       stw     t6,(6+(off))*4(sp); \
+       \
+       stfd    ft0,(8+(off))*4(sp); \
+       stfd    ft1,(10+(off))*4(sp); \
+       stfd    ft2,(12+(off))*4(sp); \
+       stfd    ft3,(14+(off))*4(sp); \
+       stfd    ft4,(16+(off))*4(sp); \
+       stfd    ft5,(18+(off))*4(sp);
+
+#define RESTORE_TEMPORARY_REGISTERS(off) \
+       lwz     t0,(0+(off))*4(sp); \
+       lwz     t1,(1+(off))*4(sp); \
+       lwz     t2,(2+(off))*4(sp); \
+       lwz     t3,(3+(off))*4(sp); \
+       lwz     t4,(4+(off))*4(sp); \
+       lwz     t5,(5+(off))*4(sp); \
+       lwz     t6,(6+(off))*4(sp); \
+       \
+       lfd     ft0,(8+(off))*4(sp); \
+       lfd     ft1,(10+(off))*4(sp); \
+       lfd     ft2,(12+(off))*4(sp); \
+       lfd     ft3,(14+(off))*4(sp); \
+       lfd     ft4,(16+(off))*4(sp); \
+       lfd     ft5,(18+(off))*4(sp);
+
+#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/powerpc64/linux/md-os.c b/src/vm/jit/powerpc64/linux/md-os.c
new file mode 100644 (file)
index 0000000..3b63ad6
--- /dev/null
@@ -0,0 +1,167 @@
+/* src/vm/jit/powerpc64/linux/md-os.c - machine dependent PowerPC 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:
+
+   $Id: md-os.c 5081 2006-07-06 13:59:01Z tbfg $
+
+*/
+
+
+#include "config.h"
+
+#include <assert.h>
+#include <ucontext.h>
+
+#include "vm/types.h"
+
+#include "vm/jit/powerpc64/linux/md-abi.h"
+
+#if defined(ENABLE_THREADS)
+# include "threads/native/threads.h"
+#endif
+
+#include "vm/exceptions.h"
+#include "vm/signallocal.h"
+#include "vm/stringlocal.h"
+#include "vm/jit/asmpart.h"
+
+#if defined(ENABLE_PROFILING)
+# include "vm/jit/profile/profile.h"
+#endif
+
+#include "vm/jit/stacktrace.h"
+
+
+/* md_signal_handler_sigsegv ***************************************************
+
+   NullPointerException signal handler for hardware null pointer
+   check.
+
+*******************************************************************************/
+
+void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p) {}
+void md_signal_handler_sigusr2(int sig, siginfo_t *siginfo, void *_p) {}
+void thread_restartcriticalsection(ucontext_t *_uc) {}
+
+#if 0
+void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
+{
+       ucontext_t  *_uc;
+       mcontext_t  *_mc;
+       u4           instr;
+       s4           reg;
+       ptrint       addr;
+       u1          *pv;
+       u1          *sp;
+       u1          *ra;
+       u1          *xpc;
+
+       _uc = (ucontext_t *) _p;
+       _mc = _uc->uc_mcontext.uc_regs;
+
+       instr = *((u4 *) _mc->gregs[PT_NIP]);
+       reg = (instr >> 16) & 0x1f;
+       addr = _mc->gregs[reg];
+
+       if (addr == 0) {
+               pv  = (u1 *) _mc->gregs[REG_PV];
+               sp  = (u1 *) _mc->gregs[REG_SP];
+               ra  = (u1 *) _mc->gregs[PT_LNK];         /* this is correct for leafs */
+               xpc = (u1 *) _mc->gregs[PT_NIP];
+
+               _mc->gregs[REG_ITMP1_XPTR] =
+                       (ptrint) stacktrace_hardware_nullpointerexception(pv, sp, ra, xpc);
+
+               _mc->gregs[REG_ITMP2_XPC] = (ptrint) xpc;
+               _mc->gregs[PT_NIP] = (ptrint) asm_handle_exception;
+
+       } else {
+               throw_cacao_exception_exit(string_java_lang_InternalError,
+                                                                  "Segmentation fault: 0x%08lx at 0x%08lx",
+                                                                  addr, _mc->gregs[PT_NIP]);
+       }               
+}
+
+
+/* md_signal_handler_sigusr2 ***************************************************
+
+   Signal handler for profiling sampling.
+
+*******************************************************************************/
+
+void md_signal_handler_sigusr2(int sig, siginfo_t *siginfo, void *_p)
+{
+       threadobject *tobj;
+       ucontext_t   *_uc;
+       mcontext_t   *_mc;
+       u1           *pc;
+
+       tobj = THREADOBJECT;
+
+       _uc = (ucontext_t *) _p;
+       _mc = _uc->uc_mcontext.uc_regs;
+
+       pc = (u1 *) _mc->gregs[PT_NIP];
+
+       tobj->pc = pc;
+}
+
+
+#if defined(ENABLE_THREADS)
+void thread_restartcriticalsection(ucontext_t *_uc)
+{
+       mcontext_t *_mc;
+       u1         *pc;
+       void       *critical;
+
+       _mc = _uc->uc_mcontext.uc_regs;
+
+       pc = (u1 *) _mc->gregs[PT_NIP];
+
+       critical = critical_find_restart_point(pc);
+
+       if (critical)
+               _mc->gregs[PT_NIP] = (ptrint) critical;
+}
+#endif
+
+#endif
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * 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/powerpc64/machine-instr.h b/src/vm/jit/powerpc64/machine-instr.h
new file mode 100644 (file)
index 0000000..10cf5b6
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef _MACHINE_INSTR_H
+#define _MACHINE_INSTR_H
+
+static inline void
+atomic_add(int *mem, int val)
+{
+       int temp;
+
+  __asm__ __volatile__ ("\n\
+1:  lwarx  %0,0,%2 \n\
+    add    %0,%0,%1 \n\
+       stwcx. %0,0,%2 \n\
+       bne-   1b \n\
+"   : "=&r"(temp)
+    : "r"(val), "r"(mem) : "cr0", "memory");
+}
+
+static inline long compare_and_swap(long *p, long oldval, long newval)
+{
+  long ret, temp;
+
+  __asm__ __volatile__ ("\n\
+1:  lwarx  %0,0,%4 \n\
+    subf.  %1,%0,%2 \n\
+    bne-   2f \n\
+    or     %1,%3,%3 \n\
+    stwcx. %1,0,%4 \n\
+    bne-   1b \n\
+2: \n\
+"   : "=&r"(ret), "=&r"(temp)
+    : "r"(oldval), "r"(newval), "r"(p) : "cr0", "memory");
+
+  return ret;
+}
+
+#define STORE_ORDER_BARRIER() __asm__ __volatile__ ("" : : : "memory");
+#define MEMORY_BARRIER_BEFORE_ATOMIC() __asm__ __volatile__ ("sync" : : : "memory");
+#define MEMORY_BARRIER_AFTER_ATOMIC() __asm__ __volatile__ ("isync" : : : "memory");
+#define MEMORY_BARRIER() __asm__ __volatile__ ( "sync" : : : "memory" );
+
+#endif
diff --git a/src/vm/jit/powerpc64/md.c b/src/vm/jit/powerpc64/md.c
new file mode 100644 (file)
index 0000000..28750b6
--- /dev/null
@@ -0,0 +1,312 @@
+/* src/vm/jit/powerpc/md.c - machine dependent PowerPC 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 5081 2006-07-06 13:59:01Z tbfg $
+
+*/
+
+#include "config.h"
+
+#include <assert.h>
+
+#include "vm/types.h"
+
+#include "md-abi.h"
+
+#include "vm/global.h"
+#include "vm/jit/asmpart.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_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 PowerPC the return address is located in the linkage area */
+
+       ra = *((u1 **) (sp + framesize + LA_LR_OFFSET));
+
+       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:
+
+   81adffd4    lwz     r13,-44(r13)
+   7da903a6    mtctr   r13
+   4e800421    bctrl
+
+   INVOKEVIRTUAL:
+
+   81830000    lwz     r12,0(r3)
+   81ac0000    lwz     r13,0(r12)
+   7da903a6    mtctr   r13
+   4e800421    bctrl
+
+   INVOKEINTERFACE:
+
+   81830000    lwz     r12,0(r3)
+   818c0000    lwz     r12,0(r12)
+   81ac0000    lwz     r13,0(r12)
+   7da903a6    mtctr   r13
+   4e800421    bctrl
+
+*******************************************************************************/
+
+u1 *md_get_method_patch_address(u1 *ra, stackframeinfo *sfi, u1 *mptr)
+{
+       u4  mcode;
+       s4  offset;
+       u1 *pa;
+
+       /* go back to the actual load instruction (3 instructions) */
+
+       ra = ra - 3 * 4;
+
+       /* get first instruction word (lwz) */
+
+       mcode = *((u4 *) ra);
+
+       /* check if we have 2 instructions (addis, addi) */
+
+       if ((mcode >> 16) == 0x3c19) {
+               /* XXX write a regression for this */
+               assert(0);
+
+               /* get displacement of first instruction (addis) */
+
+               offset = (s4) (mcode << 16);
+
+               /* get displacement of second instruction (addi) */
+
+               mcode = *((u4 *) (ra + 1 * 4));
+
+               assert((mcode >> 16) != 0x6739);
+
+               offset += (s2) (mcode & 0x0000ffff);
+
+       } else {
+               /* get the offset from the instruction */
+
+               offset = (s2) (mcode & 0x0000ffff);
+
+               /* check for load from PV */
+
+               if ((mcode >> 16) == 0x81ad) {
+                       /* get the final data segment address */
+
+                       pa = sfi->pv + offset;
+
+               } else if ((mcode >> 16) == 0x81ac) {
+                       /* in this case we use the passed method pointer */
+
+                       pa = mptr + offset;
+
+               } else {
+                       /* catch any problems */
+
+                       assert(0);
+               }
+       }
+
+       return pa;
+}
+
+
+/* md_codegen_findmethod *******************************************************
+
+   Machine code:
+
+   7d6802a6    mflr    r11
+   39abffe0    addi    r13,r11,-32
+
+   or
+
+   7d6802a6    mflr    r11
+   3dabffff    addis   r13,r11,-1
+   39ad68b0    addi    r13,r13,26800
+
+*******************************************************************************/
+
+u1 *md_codegen_findmethod(u1 *ra)
+{
+       u1 *pv;
+       u4  mcode;
+       s4  offset;
+
+       /* get first instruction word after jump */
+
+       mcode = *((u4 *) (ra + 1 * 4));
+
+       /* check if we have 2 instructions (addis, addi) */
+
+       if ((mcode >> 16) == 0x3dab) {
+               /* get displacement of first instruction (addis) */
+
+               offset = (s4) (mcode << 16);
+
+               /* get displacement of second instruction (addi) */
+
+               mcode = *((u4 *) (ra + 2 * 4));
+
+               /* check for addi instruction */
+
+               assert((mcode >> 16) == 0x39ad);
+
+               offset += (s2) (mcode & 0x0000ffff);
+
+       } else {
+               /* check for addi instruction */
+
+               assert((mcode >> 16) == 0x39ab);
+
+               /* get offset of first instruction (addi) */
+
+               offset = (s2) (mcode & 0x0000ffff);
+       }
+
+       /* calculate PV via RA + offset */
+
+       pv = ra + offset;
+
+       return pv;
+}
+
+
+/* md_cacheflush ***************************************************************
+
+   Calls the system's function to flush the instruction and data
+   cache.
+
+*******************************************************************************/
+
+void md_cacheflush(u1 *addr, s4 nbytes)
+{
+       asm_cacheflush(addr, nbytes);
+}
+
+
+/* md_icacheflush **************************************************************
+
+   Calls the system's function to flush the instruction cache.
+
+*******************************************************************************/
+
+void md_icacheflush(u1 *addr, s4 nbytes)
+{
+       asm_cacheflush(addr, nbytes);
+}
+
+
+/* md_dcacheflush **************************************************************
+
+   Calls the system's function to flush the data cache.
+
+*******************************************************************************/
+
+void md_dcacheflush(u1 *addr, s4 nbytes)
+{
+       asm_cacheflush(addr, nbytes);
+}
+
+
+/* md_patch_replacement_point **************************************************
+
+   Patch the given replacement point.
+
+*******************************************************************************/
+
+void md_patch_replacement_point(rplpoint *rp)
+{
+    u8 mcode;
+
+       /* save the current machine code */
+       mcode = *(u4*)rp->pc;
+
+       /* write the new machine code */
+    *(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
+                       
+       /* flush instruction cache */
+    md_icacheflush(rp->pc,4);
+}
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
diff --git a/src/vm/jit/powerpc64/patcher.c b/src/vm/jit/powerpc64/patcher.c
new file mode 100644 (file)
index 0000000..34c4bdd
--- /dev/null
@@ -0,0 +1,954 @@
+/* src/vm/jit/powerpc/patcher.c - PowerPC 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 5081 2006-07-06 13:59:01Z tbfg $
+
+*/
+
+
+#include "config.h"
+
+#include <assert.h>
+
+#include "vm/types.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/resolve.h"
+#include "vm/references.h"
+#include "vm/jit/asmpart.h"
+#include "vm/jit/patcher.h"
+#include "vm/jit/methodheader.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 *);
+
+       assert(pv != NULL);
+
+       /* get stuff from the stack */
+
+       xpc = (u1 *)                *((ptrint *) (sp + 5 * 4));
+       o   = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
+       f   = (functionptr)         *((ptrint *) (sp + 0 * 4));
+
+       /* store PV into the patcher function position */
+
+       *((ptrint *) (sp + 0 * 4)) = (ptrint) pv;
+
+       /* 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 */
+
+       stacktrace_create_extern_stackframeinfo(&sfi, pv, sp + 8 * 4, ra, 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>
+   816dffc8    lwz   r11,-56(r13)
+   80ab0000    lwz   r5,0(r11)
+
+*******************************************************************************/
+
+bool patcher_get_putstatic(u1 *sp)
+{
+       u1               *ra;
+       u4                mcode;
+       unresolved_field *uf;
+       s4                disp;
+       u1               *pv;
+       fieldinfo        *fi;
+
+       /* get stuff from the stack */
+
+       ra    = (u1 *)                *((ptrint *) (sp + 5 * 4));
+       mcode =                       *((u4 *)     (sp + 3 * 4));
+       uf    = (unresolved_field *)  *((ptrint *) (sp + 2 * 4));
+       disp  =                       *((s4 *)     (sp + 1 * 4));
+       pv    = (u1 *)                *((ptrint *) (sp + 0 * 4));
+
+       /* get the fieldinfo */
+
+       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 */
+
+       *((u4 *) ra) = mcode;
+
+       /* synchronize instruction cache */
+
+       md_icacheflush(ra, 4);
+
+       /* patch the field value's address */
+
+       *((ptrint *) (pv + disp)) = (ptrint) &(fi->value);
+
+       /* synchronize data cache */
+
+       md_dcacheflush(pv + disp, SIZEOF_VOID_P);
+
+       return true;
+}
+
+
+/* patcher_get_putfield ********************************************************
+
+   Machine code:
+
+   <patched call position>
+   811f0014    lwz   r8,20(r31)
+
+*******************************************************************************/
+
+bool patcher_get_putfield(u1 *sp)
+{
+       u1               *ra;
+       u4                mcode;
+       unresolved_field *uf;
+       u1               *pv;
+       fieldinfo        *fi;
+
+       ra    = (u1 *)                *((ptrint *) (sp + 5 * 4));
+       mcode =                       *((u4 *)     (sp + 3 * 4));
+       uf    = (unresolved_field *)  *((ptrint *) (sp + 2 * 4));
+       pv    = (u1 *)                *((ptrint *) (sp + 1 * 4));
+
+       /* get the fieldinfo */
+
+       if (!(fi = resolve_field_eager(uf)))
+               return false;
+
+       /* patch back original code */
+
+       *((u4 *) ra) = mcode;
+
+       /* if we show disassembly, we have to skip the nop */
+
+       if (opt_showdisassemble)
+               ra = ra + 4;
+
+       /* patch the field's offset */
+
+       if (fi->type == TYPE_LNG) {
+               s2 disp;
+
+               /* If the field has type long, we have to patch two
+                  instructions.  But we have to check which instruction is
+                  first.  We do that with the offset of the first
+                  instruction. */
+
+               disp = *((u4 *) (ra + 0));
+
+#if WORDS_BIGENDIAN == 1
+               if (disp == 4) {
+                       *((u4 *) (ra + 0)) |= (s2) ((fi->offset + 4) & 0x0000ffff);
+                       *((u4 *) (ra + 4)) |= (s2) ((fi->offset + 0) & 0x0000ffff);
+
+               } else {
+                       *((u4 *) (ra + 0)) |= (s2) ((fi->offset + 0) & 0x0000ffff);
+                       *((u4 *) (ra + 4)) |= (s2) ((fi->offset + 4) & 0x0000ffff);
+               }
+#else
+#error Fix me for LE
+#endif
+       }
+       else {
+               *((u4 *) ra) |= (s2) (fi->offset & 0x0000ffff);
+       }
+
+       /* synchronize instruction cache */
+
+       md_icacheflush(ra, 8);
+
+       return true;
+}
+
+
+/* patcher_aconst **************************************************************
+
+   Machine code:
+
+   <patched call postition>
+   806dffc4    lwz   r3,-60(r13)
+   81adffc0    lwz   r13,-64(r13)
+   7da903a6    mtctr r13
+   4e800421    bctrl
+
+*******************************************************************************/
+
+bool patcher_aconst(u1 *sp)
+{
+       u1                *ra;
+       u4                 mcode;
+       constant_classref *cr;
+       s4                 disp;
+       u1                *pv;
+       classinfo         *c;
+
+       /* get stuff from the stack */
+
+       ra    = (u1 *)                *((ptrint *) (sp + 5 * 4));
+       mcode =                       *((u4 *)     (sp + 3 * 4));
+       cr    = (constant_classref *) *((ptrint *) (sp + 2 * 4));
+       disp  =                       *((s4 *)     (sp + 1 * 4));
+       pv    = (u1 *)                *((ptrint *) (sp + 0 * 4));
+
+       /* get the classinfo */
+
+       if (!(c = resolve_classref_eager(cr)))
+               return false;
+
+       /* patch back original code */
+
+       *((u4 *) ra) = mcode;
+
+       /* synchronize instruction cache */
+
+       md_icacheflush(ra, 4);
+
+       /* patch the classinfo pointer */
+
+       *((ptrint *) (pv + disp)) = (ptrint) c;
+
+       /* synchronize data cache */
+
+       md_dcacheflush(pv + disp, SIZEOF_VOID_P);
+
+       return true;
+}
+
+
+/* patcher_builtin_multianewarray **********************************************
+
+   Machine code:
+
+   <patched call position>
+   808dffc0    lwz   r4,-64(r13)
+   38a10038    addi  r5,r1,56
+   81adffbc    lwz   r13,-68(r13)
+   7da903a6    mtctr r13
+   4e800421    bctrl
+
+*******************************************************************************/
+
+bool patcher_builtin_multianewarray(u1 *sp)
+{
+       u1                *ra;
+       u4                 mcode;
+       constant_classref *cr;
+       s4                 disp;
+       u1                *pv;
+       classinfo         *c;
+
+       /* get stuff from the stack */
+
+       ra    = (u1 *)                *((ptrint *) (sp + 5 * 4));
+       mcode =                       *((u4 *)     (sp + 3 * 4));
+       cr    = (constant_classref *) *((ptrint *) (sp + 2 * 4));
+       disp  =                       *((s4 *)     (sp + 1 * 4));
+       pv    = (u1 *)                *((ptrint *) (sp + 0 * 4));
+
+       /* get the classinfo */
+
+       if (!(c = resolve_classref_eager(cr)))
+               return false;
+
+       /* patch back original code */
+
+       *((u4 *) ra) = mcode;
+
+       /* synchronize instruction cache */
+
+       md_icacheflush(ra, 4);
+
+       /* patch the classinfo pointer */
+
+       *((ptrint *) (pv + disp)) = (ptrint) c;
+
+       /* synchronize data cache */
+
+       md_dcacheflush(pv + disp, SIZEOF_VOID_P);
+
+       return true;
+}
+
+
+/* patcher_builtin_arraycheckcast **********************************************
+
+   Machine code:
+
+   <patched call position>
+   808dffd8    lwz   r4,-40(r13)
+   81adffd4    lwz   r13,-44(r13)
+   7da903a6    mtctr r13
+   4e800421    bctrl
+
+*******************************************************************************/
+
+bool patcher_builtin_arraycheckcast(u1 *sp)
+{
+       u1                *ra;
+       u4                 mcode;
+       constant_classref *cr;
+       s4                 disp;
+       u1                *pv;
+       classinfo         *c;
+
+       /* get stuff from the stack */
+
+       ra    = (u1 *)                *((ptrint *) (sp + 5 * 4));
+       mcode =                       *((u4 *)     (sp + 3 * 4));
+       cr    = (constant_classref *) *((ptrint *) (sp + 2 * 4));
+       disp  =                       *((s4 *)     (sp + 1 * 4));
+       pv    = (u1 *)                *((ptrint *) (sp + 0 * 4));
+
+       /* get the classinfo */
+
+       if (!(c = resolve_classref_eager(cr)))
+               return false;
+
+       /* patch back original code */
+
+       *((u4 *) ra) = mcode;
+
+       /* synchronize instruction cache */
+
+       md_icacheflush(ra, 4);
+
+       /* patch the classinfo pointer */
+
+       *((ptrint *) (pv + disp)) = (ptrint) c;
+
+       /* synchronize data cache */
+
+       md_dcacheflush(pv + disp, SIZEOF_VOID_P);
+
+       return true;
+}
+
+
+/* patcher_invokestatic_special ************************************************
+
+   Machine code:
+
+   <patched call position>
+   81adffd8    lwz   r13,-40(r13)
+   7da903a6    mtctr r13
+   4e800421    bctrl
+
+******************************************************************************/
+
+bool patcher_invokestatic_special(u1 *sp)
+{
+       u1                *ra;
+       u4                 mcode;
+       unresolved_method *um;
+       s4                 disp;
+       u1                *pv;
+       methodinfo        *m;
+
+       /* get stuff from the stack */
+
+       ra    = (u1 *)                *((ptrint *) (sp + 5 * 4));
+       mcode =                       *((u4 *)     (sp + 3 * 4));
+       um    = (unresolved_method *) *((ptrint *) (sp + 2 * 4));
+       disp  =                       *((s4 *)     (sp + 1 * 4));
+       pv    = (u1 *)                *((ptrint *) (sp + 0 * 4));
+
+       /* get the fieldinfo */
+
+       if (!(m = resolve_method_eager(um)))
+               return false;
+
+       /* patch back original code */
+
+       *((u4 *) ra) = mcode;
+
+       /* synchronize instruction cache */
+
+       md_icacheflush(ra, 4);
+
+       /* patch stubroutine */
+
+       *((ptrint *) (pv + disp)) = (ptrint) m->stubroutine;
+
+       /* synchronize data cache */
+
+       md_dcacheflush(pv + disp, SIZEOF_VOID_P);
+
+       return true;
+}
+
+
+/* patcher_invokevirtual *******************************************************
+
+   Machine code:
+
+   <patched call position>
+   81830000    lwz   r12,0(r3)
+   81ac0088    lwz   r13,136(r12)
+   7da903a6    mtctr r13
+   4e800421    bctrl
+
+*******************************************************************************/
+
+bool patcher_invokevirtual(u1 *sp)
+{
+       u1                *ra;
+       u4                 mcode;
+       unresolved_method *um;
+       methodinfo        *m;
+       s4                 disp;
+
+       /* get stuff from the stack */
+
+       ra    = (u1 *)                *((ptrint *) (sp + 5 * 4));
+       mcode =                       *((u4 *)     (sp + 3 * 4));
+       um    = (unresolved_method *) *((ptrint *) (sp + 2 * 4));
+
+       /* get the fieldinfo */
+
+       if (!(m = resolve_method_eager(um)))
+               return false;
+
+       /* patch back original code */
+
+       *((u4 *) ra) = mcode;
+
+       /* if we show disassembly, we have to skip the nop */
+
+       if (opt_showdisassemble)
+               ra = ra + 4;
+
+       /* patch vftbl index */
+
+       disp = (OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex);
+
+       *((s4 *) (ra + 4)) |= (disp & 0x0000ffff);
+
+       /* synchronize instruction cache */
+
+       md_icacheflush(ra, 2 * 4);
+
+       return true;
+}
+
+
+/* patcher_invokeinterface *****************************************************
+
+   Machine code:
+
+   <patched call position>
+   81830000    lwz   r12,0(r3)
+   818cffd0    lwz   r12,-48(r12)
+   81ac000c    lwz   r13,12(r12)
+   7da903a6    mtctr r13
+   4e800421    bctrl
+
+*******************************************************************************/
+
+bool patcher_invokeinterface(u1 *sp)
+{
+       u1                *ra;
+       u4                 mcode;
+       unresolved_method *um;
+       methodinfo        *m;
+       s4                 disp;
+
+       /* get stuff from the stack */
+
+       ra    = (u1 *)                *((ptrint *) (sp + 5 * 4));
+       mcode =                       *((u4 *)     (sp + 3 * 4));
+       um    = (unresolved_method *) *((ptrint *) (sp + 2 * 4));
+
+       /* get the fieldinfo */
+
+       if (!(m = resolve_method_eager(um)))
+               return false;
+
+       /* patch back original code */
+
+       *((u4 *) ra) = mcode;
+
+       /* if we show disassembly, we have to skip the nop */
+
+       if (opt_showdisassemble)
+               ra = ra + 4;
+
+       /* patch interfacetable index */
+
+       disp = OFFSET(vftbl_t, interfacetable[0]) -
+               sizeof(methodptr*) * m->class->index;
+
+       /* XXX TWISTI: check displacement */
+
+       *((s4 *) (ra + 1 * 4)) |= (disp & 0x0000ffff);
+
+       /* patch method offset */
+
+       disp = sizeof(methodptr) * (m - m->class->methods);
+
+       /* XXX TWISTI: check displacement */
+
+       *((s4 *) (ra + 2 * 4)) |= (disp & 0x0000ffff);
+
+       /* synchronize instruction cache */
+
+       md_icacheflush(ra, 3 * 4);
+
+       return true;
+}
+
+
+/* patcher_checkcast_instanceof_flags ******************************************
+
+   Machine code:
+
+   <patched call position>
+   818dff7c    lwz   r12,-132(r13)
+
+*******************************************************************************/
+
+bool patcher_checkcast_instanceof_flags(u1 *sp)
+{
+       u1                *ra;
+       u4                 mcode;
+       constant_classref *cr;
+       s4                 disp;
+       u1                *pv;
+       classinfo         *c;
+
+       /* get stuff from the stack */
+
+       ra    = (u1 *)                *((ptrint *) (sp + 5 * 4));
+       mcode =                       *((u4 *)     (sp + 3 * 4));
+       cr    = (constant_classref *) *((ptrint *) (sp + 2 * 4));
+       disp  =                       *((s4 *)     (sp + 1 * 4));
+       pv    = (u1 *)                *((ptrint *) (sp + 0 * 4));
+
+       /* get the fieldinfo */
+
+       if (!(c = resolve_classref_eager(cr)))
+               return false;
+
+       /* patch back original code */
+
+       *((u4 *) ra) = mcode;
+
+       /* synchronize instruction cache */
+
+       md_icacheflush(ra, 4);
+
+       /* patch class flags */
+
+       *((s4 *) (pv + disp)) = (s4) c->flags;
+
+       /* synchronize data cache */
+
+       md_dcacheflush(pv + disp, SIZEOF_VOID_P);
+
+       return true;
+}
+
+
+/* patcher_checkcast_instanceof_interface **************************************
+
+   Machine code:
+
+   <patched call position>
+   81870000    lwz   r12,0(r7)
+   800c0010    lwz   r0,16(r12)
+   34000000    addic.        r0,r0,0
+   408101fc    ble-  0x3002e518
+   800c0000    lwz   r0,0(r12)
+
+*******************************************************************************/
+
+bool patcher_checkcast_instanceof_interface(u1 *sp)
+{
+       u1                *ra;
+       u4                 mcode;
+       constant_classref *cr;
+       classinfo         *c;
+       s4                 disp;
+
+       /* get stuff from the stack */
+
+       ra    = (u1 *)                *((ptrint *) (sp + 5 * 4));
+       mcode =                       *((u4 *)     (sp + 3 * 4));
+       cr    = (constant_classref *) *((ptrint *) (sp + 2 * 4));
+
+       /* get the fieldinfo */
+
+       if (!(c = resolve_classref_eager(cr)))
+               return false;
+
+       /* patch back original code */
+
+       *((u4 *) ra) = mcode;
+
+       /* if we show disassembly, we have to skip the nop */
+
+       if (opt_showdisassemble)
+               ra = ra + 4;
+
+       /* patch super class index */
+
+       disp = -(c->index);
+
+       *((s4 *) (ra + 2 * 4)) |= (disp & 0x0000ffff);
+
+       disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
+
+       *((s4 *) (ra + 4 * 4)) |= (disp & 0x0000ffff);
+
+       /* synchronize instruction cache */
+
+       md_icacheflush(ra, 5 * 4);
+
+       return true;
+}
+
+
+/* patcher_checkcast_class *****************************************************
+
+   Machine code:
+
+   <patched call position>
+   81870000    lwz   r12,0(r7)
+   800c0014    lwz   r0,20(r12)
+   818dff78    lwz   r12,-136(r13)
+
+*******************************************************************************/
+
+bool patcher_checkcast_class(u1 *sp)
+{
+       u1                *ra;
+       u4                 mcode;
+       constant_classref *cr;
+       s4                 disp;
+       u1                *pv;
+       classinfo         *c;
+
+       /* get stuff from the stack */
+
+       ra    = (u1 *)                *((ptrint *) (sp + 5 * 4));
+       mcode =                       *((u4 *)     (sp + 3 * 4));
+       cr    = (constant_classref *) *((ptrint *) (sp + 2 * 4));
+       disp  =                       *((s4 *)     (sp + 1 * 4));
+       pv    = (u1 *)                *((ptrint *) (sp + 0 * 4));
+
+       /* get the fieldinfo */
+
+       if (!(c = resolve_classref_eager(cr)))
+               return false;
+
+       /* patch back original code */
+
+       *((u4 *) ra) = mcode;
+
+       /* synchronize instruction cache */
+
+       md_icacheflush(ra, 4);
+
+       /* patch super class' vftbl */
+
+       *((ptrint *) (pv + disp)) = (ptrint) c->vftbl;
+
+       /* synchronize data cache */
+
+       md_dcacheflush(pv + disp, SIZEOF_VOID_P);
+
+       return true;
+}
+
+
+/* patcher_instanceof_class ****************************************************
+
+   Machine code:
+
+   <patched call position>
+   817d0000    lwz   r11,0(r29)
+   818dff8c    lwz   r12,-116(r13)
+
+*******************************************************************************/
+
+bool patcher_instanceof_class(u1 *sp)
+{
+       u1                *ra;
+       u4                 mcode;
+       constant_classref *cr;
+       s4                 disp;
+       u1                *pv;
+       classinfo         *c;
+
+       /* get stuff from the stack */
+
+       ra    = (u1 *)                *((ptrint *) (sp + 5 * 4));
+       mcode =                       *((u4 *)     (sp + 3 * 4));
+       cr    = (constant_classref *) *((ptrint *) (sp + 2 * 4));
+       disp  =                       *((s4 *)     (sp + 1 * 4));
+       pv    = (u1 *)                *((ptrint *) (sp + 0 * 4));
+
+       /* get the fieldinfo */
+
+       if (!(c = resolve_classref_eager(cr)))
+               return false;
+
+       /* patch back original code */
+
+       *((u4 *) ra) = mcode;
+
+       /* synchronize instruction cache */
+
+       md_icacheflush(ra, 4);
+
+       /* patch super class' vftbl */
+
+       *((ptrint *) (pv + disp)) = (ptrint) c->vftbl;
+
+       /* synchronize data cache */
+
+       md_dcacheflush(pv + disp, SIZEOF_VOID_P);
+
+       return true;
+}
+
+
+/* patcher_clinit **************************************************************
+
+   XXX
+
+*******************************************************************************/
+
+bool patcher_clinit(u1 *sp)
+{
+       u1        *ra;
+       u4         mcode;
+       classinfo *c;
+
+       /* get stuff from the stack */
+
+       ra    = (u1 *)        *((ptrint *) (sp + 5 * 4));
+       mcode =               *((u4 *)     (sp + 3 * 4));
+       c     = (classinfo *) *((ptrint *) (sp + 2 * 4));
+
+       /* check if the class is initialized */
+
+       if (!(c->state & CLASS_INITIALIZED))
+               if (!initialize_class(c))
+                       return false;
+
+       /* patch back original code */
+
+       *((u4 *) ra) = mcode;
+
+       /* synchronize instruction cache */
+
+       md_icacheflush(ra, 4);
+
+       return true;
+}
+
+
+/* patcher_athrow_areturn ******************************************************
+
+   Machine code:
+
+   <patched call position>
+
+*******************************************************************************/
+
+#ifdef ENABLE_VERIFIER
+bool patcher_athrow_areturn(u1 *sp)
+{
+       u1               *ra;
+       u4                mcode;
+       unresolved_class *uc;
+       classinfo        *c;
+
+       /* get stuff from the stack */
+
+       ra    = (u1 *)               *((ptrint *) (sp + 5 * 4));
+       mcode =                      *((u4 *)     (sp + 3 * 4));
+       uc    = (unresolved_class *) *((ptrint *) (sp + 2 * 4));
+
+       /* resolve the class */
+
+       if (!resolve_class(uc, resolveEager, false, &c))
+               return false;
+
+       /* patch back original code */
+
+       *((u4 *) ra) = mcode;
+
+       /* synchronize instruction cache */
+
+       md_icacheflush(ra, 4);
+
+       return true;
+}
+#endif /* ENABLE_VERIFIER */
+
+
+/* patcher_resolve_native ******************************************************
+
+   XXX
+
+*******************************************************************************/
+
+#if !defined(WITH_STATIC_CLASSPATH)
+bool patcher_resolve_native(u1 *sp)
+{
+       u1          *ra;
+       u4           mcode;
+       methodinfo  *m;
+       s4           disp;
+       u1          *pv;
+       functionptr  f;
+
+       /* get stuff from the stack */
+
+       ra    = (u1 *)                *((ptrint *) (sp + 5 * 4));
+       mcode =                       *((u4 *)     (sp + 3 * 4));
+       m     = (methodinfo *)        *((ptrint *) (sp + 2 * 4));
+       disp  =                       *((s4 *)     (sp + 1 * 4));
+       pv    = (u1 *)                *((ptrint *) (sp + 0 * 4));
+
+       /* calculate and set the new return address */
+
+       ra = ra - 1 * 4;
+       *((ptrint *) (sp + 5 * 4)) = (ptrint) ra;
+
+       /* resolve native function */
+
+       if (!(f = native_resolve_function(m)))
+               return false;
+
+       /* patch back original code */
+
+       *((u4 *) ra) = mcode;
+
+       /* synchronize instruction cache */
+
+       md_icacheflush(ra, 4);
+
+       /* patch native function pointer */
+
+       *((ptrint *) (pv + disp)) = (ptrint) f;
+
+       /* synchronize data cache */
+
+       md_dcacheflush(pv + disp, SIZEOF_VOID_P);
+
+       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:
+ */