* configure.ac: Added support for compiling on sparc64
authorajordan <none@none>
Wed, 21 Jun 2006 16:29:29 +0000 (16:29 +0000)
committerajordan <none@none>
Wed, 21 Jun 2006 16:29:29 +0000 (16:29 +0000)
* src/vm/jit/Makefile.am: Added sparc64 subdirectory

* src/vm/jit/sparc64/*: Added files for the sparc64 JIT (which won't compile yet)

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

index eada0e101327dbd50fd2346fcdb71e62e6f462fd..2137a6b83d38ae4e21c139f34416fb3c234f299d 100644 (file)
@@ -61,6 +61,11 @@ xdspcore )
     USE_SCHEDULER="1"
     ;;
 
+sparc64 )
+    ARCH_DIR="sparc64"
+    CFLAGS="$CFLAGS -mcpu=v9 -m64 -D__SPARC_64__"
+    ;;
+
 * )
     AC_MSG_ERROR($host_cpu systems are not supported at this time)
     ;;
@@ -335,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 )
+        arm | i386 | powerpc | x86_64 | sparc64 )
             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)])
@@ -817,6 +822,8 @@ AC_CONFIG_FILES([Makefile]
                [src/vm/jit/powerpc/netbsd/Makefile]
                [src/vm/jit/profile/Makefile]
                [src/vm/jit/schedule/Makefile]
+               [src/vm/jit/sparc64/Makefile]
+               [src/vm/jit/sparc64/linux/Makefile]
                [src/vm/jit/tools/Makefile]
                [src/vm/jit/verify/Makefile]
                [src/vm/jit/x86_64/Makefile]
index af020aab87951ce178053a2b05a6d69f4d312473..ad05e388863708892a1aa4d9c7015ea95b4261e5 100644 (file)
@@ -28,7 +28,7 @@
 ##
 ## Changes: Edwin Steiner
 ##
-## $Id: Makefile.am 4998 2006-05-31 20:28:27Z edwin $
+## $Id: Makefile.am 5045 2006-06-21 16:29:29Z ajordan $
 
 ## Process this file with automake to produce Makefile.in
 
@@ -51,7 +51,8 @@ DIST_SUBDIRS = \
        i386 \
        mips \
        powerpc \
-       x86_64
+       x86_64 \
+       sparc64
 
 SUBDIRS = \
        allocator \
diff --git a/src/vm/jit/sparc64/.cvsignore b/src/vm/jit/sparc64/.cvsignore
new file mode 100644 (file)
index 0000000..1f83cf9
--- /dev/null
@@ -0,0 +1,10 @@
+*.a
+*.o
+*.la
+*.lo
+.deps
+.libs
+Makefile
+Makefile.in
+TAGS
+offsets.h
diff --git a/src/vm/jit/sparc64/Makefile.am b/src/vm/jit/sparc64/Makefile.am
new file mode 100644 (file)
index 0000000..aaa819e
--- /dev/null
@@ -0,0 +1,85 @@
+## src/vm/jit/sparc64/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
+##          Alexander Jordan
+##
+## Changes:
+##
+## $Id: Makefile.am 4563 2006-03-06 13:03:05Z twisti $
+
+## 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
+AM_CCASFLAGS = $(AM_CPPFLAGS)
+
+LIBS =
+
+BUILT_SOURCES = offsets.h
+
+CLEANFILES = offsets.h
+
+noinst_HEADERS = \
+       arch.h \
+       machine-instr.h 
+#      \
+#      md-asm.h
+
+noinst_LTLIBRARIES = libarch.la
+
+libarch_la_SOURCES = \
+       codegen.c \
+       codegen.h \
+       md.h \
+       md-abi.h \
+       md.c \
+       disass.c \
+       asmpart.S \
+       md-abi.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:
diff --git a/src/vm/jit/sparc64/arch.h b/src/vm/jit/sparc64/arch.h
new file mode 100644 (file)
index 0000000..a6f1202
--- /dev/null
@@ -0,0 +1,57 @@
+
+#ifndef _ARCH_H
+#define _ARCH_H
+
+/* define architecture features ***********************************************/
+
+#define U8_AVAILABLE                     1
+
+/*  #define USEBUILTINTABLE */
+
+#define SUPPORT_DIVISION                 0
+#define SUPPORT_LONG                     1
+#define SUPPORT_FLOAT                    1
+#define SUPPORT_DOUBLE                   1
+
+#define SUPPORT_I2F                      1
+#define SUPPORT_I2D                      1
+#define SUPPORT_L2F                      1
+#define SUPPORT_L2D                      1
+
+#define SUPPORT_F2I                      0
+#define SUPPORT_F2L                      0
+#define SUPPORT_D2I                      0
+#define SUPPORT_D2L                      0
+
+#define SUPPORT_LONG_ADD                 1
+#define SUPPORT_LONG_CMP                 1
+#define SUPPORT_LONG_CMP_CONST           1
+#define SUPPORT_LONG_LOGICAL             1
+#define SUPPORT_LONG_SHIFT               1
+#define SUPPORT_LONG_MUL                 1
+#define SUPPORT_LONG_DIV                 0
+
+#define SUPPORT_CONST_LOGICAL            1  /* AND, OR, XOR with immediates   */
+#define SUPPORT_CONST_MUL                1  /* mutiply with immediate         */
+
+#define SUPPORT_CONST_STORE              1  /* do we support const stores     */
+#define SUPPORT_CONST_STORE_ZERO_ONLY    1  /* on some risc machines we can   */
+                                            /* only store REG_ZERO            */
+
+#define CONDITIONAL_LOADCONST            1
+
+#endif /* _ARCH_H */
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
diff --git a/src/vm/jit/sparc64/asmpart.S b/src/vm/jit/sparc64/asmpart.S
new file mode 100644 (file)
index 0000000..43f0ad6
--- /dev/null
@@ -0,0 +1,243 @@
+/* src/vm/jit/sparc64/asmpart.S - Java-C interface functions for Sparc
+
+   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
+            Alexander Jordan
+
+   Changes: 
+
+   $Id: asmpart.S 4749 2006-04-11 10:20:18Z twisti $
+
+*/
+
+
+#include "config.h"
+#include "offsets.h"
+#include "md-asm.h"
+
+       .text
+
+/* export functions ***********************************************************/
+
+       .global asm_vm_call_method        
+       .global asm_vm_call_method_int    
+       .global asm_vm_call_method_long   
+       .global asm_vm_call_method_float  
+       .global asm_vm_call_method_double 
+       .global asm_vm_call_method_exception_handler
+
+
+/* asm_vm_call_method ******************************************************
+ *                                                                         *
+ * This function calls a Java-method (which possibly needs compilation)    *
+ *
+ * C-prototype:
+ *  java_objectheader *asm_vm_call_method(methodinfo *m, s4 vmargscount,
+ *                                              vm_arg *vmargs);
+ **************************************************************************/
+
+       .align 8        /* v9: All data types are aligned to their size */
+
+/*x*/  .xword 0                         /* catch type all */
+/*x*/  .word calljava_xhandler2        /* handler pc */
+/*x*/  .word calljava_xhandler2        /* end pc */
+/*x*/  .word asm_vm_call_method        /* start pc */
+       .word  1                         /* extable size */
+       .word  0                         /* ALIGNMENT PADDING */
+/*x*/  .xword 0                         /* line number table start */
+/*x*/  .xword 0                         /* line number table size */
+       .word  0                         /* ALIGNMENT PADDING */
+       .word  0                         /* fltsave */
+       .word  1                         /* intsave */
+       .word  0                         /* isleaf */
+       .word  0                         /* IsSync */
+       .word  0                         /* frame size */
+/*x*/  .xword 0                         /* method pointer (pointer to name)*/ 
+
+asm_vm_call_method:       
+asm_vm_call_method_int:   
+asm_vm_call_method_long:  
+asm_vm_call_method_float: 
+asm_vm_call_method_double:
+       
+       save %sp, -128, %sp             /* minimal (reg-window) frame */
+
+
+       /* todo: copy fp registers */
+
+       brlez %i1, calljava_argsloaded
+       dec %i1
+       ldx [%i2 + offvmargdata], %o0
+       brlez %i1, calljava_argsloaded
+
+       dec %i1
+       ldx [%i2 + (offvmargdata+sizevmarg*1)], %o1
+       brlez %i1, calljava_argsloaded
+
+       dec %i1
+       ldx [%i2 + (offvmargdata+sizevmarg*2)], %o2
+       brlez %i1, calljava_argsloaded
+
+       dec %i1
+       ldx [%i2 + (offvmargdata+sizevmarg*3)], %o3
+       brlez %i1, calljava_argsloaded
+
+       dec %i1
+       ldx [%i2 + (offvmargdata+sizevmarg*4)], %o4
+
+       /* todo: use more out registers ? */
+
+calljava_argsloaded:
+       /* todo: stack frame layout!! */
+       
+       brlez %i1, calljava_nocopy
+       sllx %i1, 3, %l0        /* remaining args * 8           */
+       mov %sp, %l1            /* right above window save area */
+       sub %sp, %l0, %sp       /* allocate more stack space    */
+       
+calljava_copyloop:
+       ldx [%i2 + (offvmargdata+sizevmarg*5)], %l0
+       stx %l0, [%l1]
+       inc sizevmarg, %i2      /* src++                        */
+       inc 8, %l1              /* dst++                        */
+       dec %i1                 /* arg_count--                  */
+       bnz %xcc, calljava_copyloop
+
+calljava_nocopy:
+
+       mov             %i0,itmp1               /* pass method pointer via itmp1 */
+       
+       addx    %sp,1*8,mptr_itmp2    /* set method pointer      ???          */
+
+       /* setx asm_call_jit_compiler, %l1, %l0 */
+       call    asm_call_jit_compiler   /* call JIT compiler                         */
+       nop
+calljava_jit2:
+       /* no need to restore pv */
+       
+calljava_return:
+       mov %o0, %i0            /* pass on the return value     */
+       return %i7 + 8          /* implicit window restore */
+       nop
+
+
+asm_vm_call_method_exception_handler:
+       mov             itmp1,%o0
+       call    builtin_throw_exception
+       return  %i7 + 8                          /* implicit window restore */
+       nop
+       
+       
+       
+       
+
+/****************** function asm_call_jit_compiler *****************************
+*                                                                              *
+*   invokes the compiler for untranslated JavaVM methods.                      *
+*                                                                              *
+*   Register R0 contains a pointer to the method info structure (prepared      *
+*   by createcompilerstub). Using the return address in R26 and the            *
+*   offset in the LDA instruction or using the value in methodptr R28 the      *
+*   patching address for storing the method address can be computed:           *
+*                                                                              *
+*   method address was either loaded using                                     *
+*   M_LDQ (REG_PV, REG_PV, a)        ; invokestatic/special    ($27)           *
+*   M_LDA (REG_PV, REG_RA, low)                                                *
+*   M_LDAH(REG_PV, REG_RA, high)     ; optional                                *
+*   or                                                                         *
+*   M_LDQ (REG_PV, REG_METHODPTR, m) ; invokevirtual/interface ($28)           *
+*   in the static case the method pointer can be computed using the            *
+*   return address and the lda function following the jmp instruction          *
+*                                                                              *
+*******************************************************************************/
+
+asm_call_jit_compiler:
+       
+       /* XXX save + reserve stack space          */
+       /* XXX save float arg registers */
+
+       mov     mptr_itmp2,%l0        /* save method pointer                      */
+       stq     itmp1,14*8(sp)        /* save methodinfo pointer                  */
+
+       addx    15*8,%sp,%o0          /* create stackframe info                   */
+       mov     zero,%o1              /* we don't have pv handy                   */
+       mov     %fp,%o2                           /* pass java sp (==fp)                          */
+       mov     %ra,%o3               /* pass Java ra                             */
+       mov     %o3,%o4               /* xpc is equal to ra                       */
+       call    stacktrace_create_extern_stackframeinfo
+
+       mov     itmp1,%o0,            /* pass methodinfo pointer                  */
+       call    jit_compile           /* call jit compiler                        */
+       mov     %o0,pv_callee         /* save return value into callee pv         */
+                                     /* the in's we have are also the in's of the*/
+                                     /* method that will be called               */
+
+       mov     %ra,%o0               /* pass return address                      */
+       addx    15*8,sp,%o1           /* pass stackframeinfo (for PV)             */
+       mov     %l0,%o2               /* pass method pointer                      */
+       jsr     ra,md_assembler_get_patch_address /* get address of patch position*/
+       mov     %o0,%l2               /* store patch address for later use        */
+
+       addx    15*8,sp,%o0           /* remove stackframe info                   */
+       call    stacktrace_remove_stackframeinfo
+       
+       
+       mov     %l2, itmp3            /* move patch address out of window         */
+       /* XXX do a window restore here ???  */
+       /* XXX restore float argument registers */
+
+       beq     pv_callee,L_asm_call_jit_compiler_exception
+
+       stx     pv_callee,[itmp3]     /* patch method entry point                 */
+
+       /* XXX synchronise instruction cache            */
+
+       jmpl    pv,zero               /* and call method, the method returns      */
+                                     /* directly to the caller (ra).             */    
+       
+L_asm_call_jit_compiler_exception:
+       /* XXX how to handle stack & window here? */
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+       /* itmpx shall be one of the application globals */
+       mov     %ra,itmpx             /* save return address (xpc)                */
+       
+       call    builtin_asm_get_exceptionptrptr
+#else
+       setx    v0,_exceptionptr
+#endif
+       ldq     xptr,0(v0)            /* get the exception pointer                */
+       stq     zero,0(v0)            /* clear the exception pointer              */
+
+       subq    ra,4,xpc
+       br      L_asm_handle_nat_exception
+
+
+
+
+
+
+
diff --git a/src/vm/jit/sparc64/codegen.c b/src/vm/jit/sparc64/codegen.c
new file mode 100644 (file)
index 0000000..0142cc3
--- /dev/null
@@ -0,0 +1,2439 @@
+/* src/vm/jit/sparc64/codegen.c - machine code generator for Sparc
+
+   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
+            Alexander Jordan
+
+   Changes:
+
+   $Id: codegen.c 4644 2006-03-16 18:44:46Z edwin $
+
+*/
+
+#include <stdio.h>
+
+#include "config.h"
+#include "vm/types.h"
+
+#include "md-abi.h"
+
+/* #include "vm/jit/sparc64/arch.h" */
+#include "vm/jit/sparc64/codegen.h"
+
+#include "mm/memory.h"
+
+#include "native/jni.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/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"
+
+
+#define REG_PV (own_window?REG_PV_CALLEE:REG_PV_CALLER)
+
+static int fabort(char *x)
+{
+    fprintf(stderr, "sparc64 abort because: %s\n", x);
+    exit(1);
+    abort();
+    return 0;
+                           
+}
+
+
+bool codegen(jitdata *jd)
+{
+       methodinfo         *m;
+       codegendata        *cd;
+       registerdata       *rd;
+       s4                  len, s1, s2, s3, d, disp;
+       s4                  stackframesize;
+       s4                 *mcodeptr;
+       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;
+
+       bool                            own_window = true; /* currently assumes immediate save*/
+       
+       /* get required compiler data */
+
+       m  = jd->m;
+       cd = jd->cd;
+       rd = jd->rd;
+       
+       
+       (void) dseg_addaddress(cd, m);                          /* MethodPointer  */
+       (void) dseg_adds4(cd, stackframesize * 8);              /* FrameSize      */
+
+#if defined(USE_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) * 8);        /* 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    */
+       
+       
+       
+       
+       /* XXX create exception table */
+       
+       /* initialize mcode variables */
+       mcodeptr = (s4 *) cd->mcodeptr;
+       
+       
+       /* XXX stack setup */
+       
+       
+       /* XXX copy arguments */
+       
+       
+       /* XXX monitor enter and tracing */
+       
+       
+       /* 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) ((u1 *) 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 {
+                                       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_DBLMOVE(s1, d);
+                                                       } else {
+                                                               M_DLD(d, REG_SP, rd->interfaces[len][s2].regoff * 8);
+                                                       }
+                                                       emit_store(jd, NULL, src, d);
+
+                                               } else {
+                                                       if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
+                                                               s1 = rd->interfaces[len][s2].regoff;
+                                                               M_INTMOVE(s1, d);
+                                                       } else {
+                                                               M_LDX(d, REG_SP, rd->interfaces[len][s2].regoff * 8);
+                                                       }
+                                                       emit_store(jd, NULL, src, d);
+                                               }
+                                       }
+                               }
+                               src = src->prev;
+                       }
+#if defined(ENABLE_LSRA)
+               }
+#endif
+
+               /* walk through all instructions */
+               
+               src = bptr->instack;
+               len = bptr->icount;
+
+               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_INLINE_START:
+               case ICMD_INLINE_END:
+                       break;
+
+               case ICMD_NOP:        /* ...  ==> ...                                 */
+                       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, 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);
+                       disp = dseg_addfloat(cd, iptr->val.f);
+                       M_FLD(d, REG_PV, disp);
+                       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);
+                       disp = dseg_adddouble(cd, iptr->val.d);
+                       M_DLD(d, REG_PV, disp);
+                       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);
+
+                       if ((iptr->target != NULL) && (iptr->val.a == NULL)) {
+                               disp = dseg_addaddress(cd, iptr->val.a);
+
+                               codegen_addpatchref(cd, PATCHER_aconst,
+                                                                       (unresolved_class *) iptr->target, disp);
+
+                               if (opt_showdisassemble) {
+                                       M_NOP;
+                               }
+
+                               M_ALD(REG_PV, disp, d);
+
+                       } else {
+                               if (iptr->val.a == NULL) {
+                                       M_INTMOVE(REG_ZERO, d);
+                               } else {
+                                       disp = dseg_addaddress(cd, iptr->val.a);
+                                       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_LLOAD:      /* op1 = local variable                         */
+               case ICMD_ALOAD:
+
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
+                       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_ALD(REG_SP, var->regoff * 8, d);
+                       } else {
+                               M_INTMOVE(var->regoff, d);
+                       }
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+       
+               case ICMD_FLOAD:      /* ...  ==> ..., content of local variable      */
+               case ICMD_DLOAD:      /* 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 * 8);
+                       } else {
+                               M_FLTMOVE(var->regoff, d);
+                       }
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+
+               case ICMD_ISTORE:     /* ..., value  ==> ...                          */
+               case ICMD_LSTORE:     /* op1 = local variable                         */
+               case ICMD_ASTORE:
+
+                       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_STX(s1, REG_SP, var->regoff * 8);
+                       } else {
+                               s1 = emit_load_s1(jd, iptr, src, var->regoff);
+                               M_INTMOVE(s1, var->regoff);
+                       }
+                       break;
+
+               case ICMD_FSTORE:     /* ..., value  ==> ...                          */
+               case ICMD_DSTORE:     /* 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 * 8);
+                       } 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                 */
+               case ICMD_LNEG:
+
+                       s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
+                       M_SUB(REG_ZERO, s1, d);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_I2L:        /* ..., value  ==> ..., value                   */
+
+                       s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
+                       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_L2I:        /* ..., value  ==> ..., value                   */
+
+                       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, 0, d); /* sign extend upper 32 bits */
+                       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_SLLX_IMM(s1, 56, d);
+                       M_SRAX_IMM( d, 56, d);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_INT2CHAR:   /* ..., value  ==> ..., value                   */
+               case ICMD_INT2SHORT:
+
+                       s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
+                       M_SLLX_IMM(s1, 48, d);
+                       M_SRAX_IMM( d, 48, d);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_IADD:       /* ..., val1, val2  ==> ..., val1 + val2        */
+               case ICMD_LADD:
+
+                       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_ADD(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 >= -4096) && (iptr->val.i <= 4095)) {
+                               M_ADD_IMM(s1, iptr->val.i, d);
+                       } else {
+                               ICONST(REG_ITMP2, iptr->val.i);
+                               M_ADD(s1, REG_ITMP2, d);
+                       }
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_LADDCONST:  /* ..., value  ==> ..., value + constant        */
+                                     /* val.l = 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.l >= -4096) && (iptr->val.l <= 4095)) {
+                               M_ADD_IMM(s1, iptr->val.l, d);
+                       } else {
+                               LCONST(REG_ITMP2, iptr->val.l);
+                               M_ADD(s1, REG_ITMP2, d);
+                       }
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_ISUB:       /* ..., val1, val2  ==> ..., val1 - val2        */
+               case ICMD_LSUB: 
+
+                       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_SUB(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 >= -4096) && (iptr->val.i <= 4095)) {
+                               M_SUB_IMM(s1, iptr->val.i, d);
+                       } else {
+                               ICONST(REG_ITMP2, iptr->val.i);
+                               M_SUB(s1, REG_ITMP2, d);
+                       }
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_LSUBCONST:  /* ..., value  ==> ..., value - constant        */
+                                     /* val.l = 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.l >= -4096) && (iptr->val.l <= 4095)) {
+                               M_SUB_IMM(s1, iptr->val.l, d);
+                       } else {
+                               LCONST(REG_ITMP2, iptr->val.l);
+                               M_SUB(s1, REG_ITMP2, d);
+                       }
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_IMUL:       /* ..., val1, val2  ==> ..., val1 * val2        */
+               case ICMD_LMUL:
+
+                       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_MULX(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 >= -4096) && (iptr->val.i <= 4095)) {
+                               M_MULX_IMM(s1, iptr->val.i, d);
+                       } else {
+                               ICONST(REG_ITMP2, iptr->val.i);
+                               M_MULX(s1, REG_ITMP2, d);
+                       }
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_LMULCONST:  /* ..., value  ==> ..., value * constant        */
+                                     /* val.l = 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.l >= -4096) && (iptr->val.l <= 4095)) {
+                               M_MULX_IMM(s1, iptr->val.l, d);
+                       } else {
+                               LCONST(REG_ITMP2, iptr->val.l);
+                               M_MULX(s1, REG_ITMP2, d);
+                       }
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_IDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
+/* XXX could also clear Y and use 32bit div */
+                       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);
+                       gen_div_check(s2);
+                       M_ISEXT(s1, s1);
+                       /* XXX trim s2 like s1 ? */
+                       M_DIVX(s1, s2, d);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_LDIV:       /* ..., 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);
+                       gen_div_check(s2);
+                       M_DIVX(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_ITMP3);
+                       gen_div_check(s2);
+                       M_ISEXT(s1, s1);
+                       /* XXX trim s2 like s1 ? */
+                       M_DIVX(s1, s2, d);
+                       M_MULX(s2, d, d);
+                       M_SUB(s1, d, d);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_LREM:       /* ..., 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_ITMP3);
+                       gen_div_check(s2);
+                       M_DIVX(s1, s2, d);
+                       M_MULX(s2, d, d);
+                       M_SUB(s1, d, d);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_IDIVPOW2:   /* ..., value  ==> ..., value << constant       */
+               case ICMD_LDIVPOW2:   /* 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_SRAX_IMM(s1, 63, REG_ITMP2);
+                       M_SRLX_IMM(REG_ITMP2, 64 - iptr->val.i, REG_ITMP2);
+                       M_ADD(s1, REG_ITMP2, REG_ITMP2);
+                       M_SRAX_IMM(REG_ITMP2, iptr->val.i, d);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_ISHL:       /* ..., val1, val2  ==> ..., val1 << val2       */
+               case ICMD_LSHL:
+
+                       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_SLLX(s1, s2, d);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_ISHLCONST:  /* ..., value  ==> ..., value << constant       */
+               case ICMD_LSHLCONST:  /* 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_SLLX_IMM(s1, iptr->val.i, 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_SRA(s1, s2, 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, 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_SRL(s1, s2, 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);
+                       M_SRL_IMM(s1, iptr->val.i, d);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_LSHR:       /* ..., 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_SRAX(s1, s2, d);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_LSHRCONST:  /* ..., 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_SRAX_IMM(s1, iptr->val.i, d);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_LUSHR:      /* ..., 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_SRLX(s1, s2, d);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_LUSHRCONST: /* ..., 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_SRLX_IMM(s1, iptr->val.i, d);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_IAND:       /* ..., val1, val2  ==> ..., val1 & val2        */
+               case ICMD_LAND:
+
+                       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 >= -4096) && (iptr->val.i <= 4095)) {
+                               M_AND_IMM(s1, iptr->val.i, d);
+                       } else {
+                               ICONST(REG_ITMP2, iptr->val.i);
+                               M_AND(s1, REG_ITMP2, 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_ISEXT(s1, s1); /* trim for 32-bit compare (BGEZ) */
+                       if (s1 == d) {
+                               M_MOV(s1, REG_ITMP1);
+                               s1 = REG_ITMP1;
+                       }
+                       if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
+                               M_AND_IMM(s1, iptr->val.i, d);
+                               M_BGEZ(s1, 4);
+                               M_NOP;
+                               M_SUB(REG_ZERO, s1, d);
+                               M_AND_IMM(d, iptr->val.i, d);
+                       } else {
+                               ICONST(REG_ITMP2, iptr->val.i);
+                               M_AND(s1, REG_ITMP2, d);
+                               M_BGEZ(s1, 4);
+                               M_NOP;
+                               M_SUB(REG_ZERO, s1, d);
+                               M_AND(d, REG_ITMP2, d);
+                       }
+                       M_SUB(REG_ZERO, d, d);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_LANDCONST:  /* ..., value  ==> ..., value & constant        */
+                                     /* val.l = 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.l >= -4096) && (iptr->val.l <= 4095)) {
+                               M_AND_IMM(s1, iptr->val.l, d);
+                       } else {
+                               LCONST(REG_ITMP2, iptr->val.l);
+                               M_AND(s1, REG_ITMP2, d);
+                       }
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_LREMPOW2:   /* ..., value  ==> ..., value % constant        */
+                                     /* val.l = constant                             */
+
+                       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;
+                       }
+                       if ((iptr->val.l >= -4096) && (iptr->val.l <= 4095)) {
+                               M_AND_IMM(s1, iptr->val.l, d);
+                               M_BGEZ(s1, 4);
+                               M_NOP;
+                               M_SUB(REG_ZERO, s1, d);
+                               M_AND_IMM(d, iptr->val.l, d);
+                       } else {
+                               LCONST(REG_ITMP2, iptr->val.l);
+                               M_AND(s1, REG_ITMP2, d);
+                               M_BGEZ(s1, 4);
+                               M_NOP;
+                               M_SUB(REG_ZERO, s1, d);
+                               M_AND(d, REG_ITMP2, d);
+                       }
+                       M_SUB(REG_ZERO, d, d);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_IOR:        /* ..., val1, val2  ==> ..., val1 | val2        */
+               case ICMD_LOR:
+
+                       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 >= -4096) && (iptr->val.i <= 4095)) {
+                               M_OR_IMM(s1, iptr->val.i, d);
+                       } else {
+                               ICONST(REG_ITMP2, iptr->val.i);
+                               M_OR(s1, REG_ITMP2, d);
+                       }
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_LORCONST:   /* ..., value  ==> ..., value | constant        */
+                                     /* val.l = 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.l >= -4096) && (iptr->val.l <= 4095)) {
+                               M_OR_IMM(s1, iptr->val.l, d);
+                       } else {
+                               LCONST(REG_ITMP2, iptr->val.l);
+                               M_OR(s1, REG_ITMP2, d);
+                       }
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_IXOR:       /* ..., val1, val2  ==> ..., val1 ^ val2        */
+               case ICMD_LXOR:
+
+                       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 >= -4096) && (iptr->val.i <= 4095)) {
+                               M_XOR_IMM(s1, iptr->val.i, d);
+                       } else {
+                               ICONST(REG_ITMP2, iptr->val.i);
+                               M_XOR(s1, REG_ITMP2, d);
+                       }
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_LXORCONST:  /* ..., value  ==> ..., value ^ constant        */
+                                     /* val.l = 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.l >= -4096) && (iptr->val.l <= 4095)) {
+                               M_XOR_IMM(s1, iptr->val.l, d);
+                       } else {
+                               LCONST(REG_ITMP2, iptr->val.l);
+                               M_XOR(s1, REG_ITMP2, d);
+                       }
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+
+               case ICMD_LCMP:       /* ..., val1, val2  ==> ..., val1 cmp 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_CMP(s1, s2);
+                       M_MOV(REG_ZERO, d);
+                       M_XCMOVLT_IMM(-1, d);
+                       M_XCMOVGT_IMM(1, 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_LDX(s1, REG_SP, var->regoff * 8);
+                       } else
+                               s1 = var->regoff;
+                       if ((iptr->val.i >= -4096) && (iptr->val.i <= 4095)) {
+                               M_ADD_IMM(s1, iptr->val.i, s1);
+                       } else {
+                               ICONST(REG_ITMP2, iptr->val.i);
+                               M_ADD(s1, REG_ITMP2, s1);
+                       }
+                       if (var->flags & INMEMORY)
+                               M_STX(s1, REG_SP, var->regoff * 8);
+                       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_FTMP2);
+                       M_FNEG(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_FTMP2);
+                       M_DNEG(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_FTMP2);
+                       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_FTMP2);
+                       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_FTMP2);
+                       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_FTMP2);
+                       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_FTMP2);
+                       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_FTMP2);
+                       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_FTMP2);
+                       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_FTMP2);
+                       M_DDIV(s1, s2, d);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;  
+
+               case ICMD_I2F:
+                       s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
+                       disp = dseg_addfloat(cd, 0.0);
+                       M_IST (s1, REG_PV_CALLEE, disp);
+                       M_FLD (d, REG_PV_CALLEE, disp);
+                       M_CVTIF (d, d); /* rd gets translated to double target register */
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+                       
+               case ICMD_I2D:
+                       s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
+                       disp = dseg_adddouble(cd, 0.0);
+                       M_STX (s1, REG_PV_CALLEE, disp);
+                       M_DLD (REG_FTMP2, REG_PV_CALLEE, disp); /* REG_FTMP2 needs to be a double temp */
+                       M_CVTLF (REG_FTMP2, d); /* rd gets translated to double target register */
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_F2I:       /* ..., value  ==> ..., (int) value              */
+                       s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
+                       disp = dseg_addfloat(cd, 0.0);
+                       M_CVTFI(s1, REG_FTMP2);
+                       M_FST(REG_FTMP2, REG_PV_CALLEE, disp);
+                       M_ILD(d, REG_PV, disp);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+                       
+                              
+               case ICMD_D2I:       /* ..., value  ==> ..., (int) value             */
+                       s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
+                       disp = dseg_addfloat(cd, 0.0);
+                       M_CVTDI(s1, REG_FTMP2);
+                       M_FST(REG_FTMP2, REG_PV, disp);
+                       M_ILD(d, REG_PV, disp);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_F2L:       /* ..., value  ==> ..., (long) value             */
+                       s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
+                       disp = dseg_adddouble(cd, 0.0);
+                       M_CVTFL(s1, REG_FTMP2); /* FTMP2 needs to be double reg */
+                       M_DST(REG_FTMP2, REG_PV, disp);
+                       M_LDX(d, REG_PV, disp);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+                       
+               case ICMD_D2L:       /* ..., value  ==> ..., (long) value             */
+                       s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
+                       d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
+                       disp = dseg_adddouble(cd, 0.0);
+                       M_CVTDL(s1, REG_FTMP2); /* FTMP2 needs to be double reg */
+                       M_DST(REG_FTMP2, REG_PV, disp);
+                       M_LDX(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_CVTFD(s1, d);
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+                                       
+               case ICMD_D2F:       /* ..., value  ==> ..., (float) 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;
+       
+       /* XXX merge F/D versions? only compare instr. is different */
+               case ICMD_FCMPL:      /* ..., val1, val2  ==> ..., val1 fcmpl 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_ITMP3);
+                       M_FCMP(s1,s2);
+                       M_OR_IMM(REG_ZERO, -1, REG_ITMP3); /* less by default (less or unordered) */
+                       M_CMOVFEQ_IMM(0, REG_ITMP3); /* 0 if equal */
+                       M_CMOVFGT_IMM(1, REG_ITMP3); /* 1 if greater */
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+                       
+               case ICMD_DCMPL:      /* ..., val1, val2  ==> ..., val1 fcmpl 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_ITMP3);
+                       M_DCMP(s1,s2);
+                       M_OR_IMM(REG_ZERO, -1, REG_ITMP3); /* less by default (less or unordered) */
+                       M_CMOVFEQ_IMM(0, REG_ITMP3); /* 0 if equal */
+                       M_CMOVFGT_IMM(1, REG_ITMP3); /* 1 if greater */
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+                       
+               case ICMD_FCMPG:      /* ..., val1, val2  ==> ..., val1 fcmpg 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_ITMP3);    
+                       M_FCMP(s1,s2);
+                       M_OR_IMM(REG_ZERO, 1, REG_ITMP3); /* greater by default (greater or unordered) */
+                       M_CMOVFEQ_IMM(0, REG_ITMP3); /* 0 if equal */
+                       M_CMOVFLT_IMM(-1, REG_ITMP3); /* -1 if less */
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+                       
+               case ICMD_DCMPG:      /* ..., val1, val2  ==> ..., val1 fcmpg 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_ITMP3);    
+                       M_DCMP(s1,s2);
+                       M_OR_IMM(REG_ZERO, 1, REG_ITMP3); /* greater by default (greater or unordered) */
+                       M_CMOVFEQ_IMM(0, REG_ITMP3); /* 0 if equal */
+                       M_CMOVFLT_IMM(-1, REG_ITMP3); /* -1 if less */
+                       emit_store(jd, iptr, iptr->dst, d);
+                       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_AADD(s2, s1, REG_ITMP3);
+                       M_BLDS(d, REG_ITMP3, OFFSET(java_chararray, data[0]));
+                       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_AADD(s2, s1, REG_ITMP3);
+                       M_AADD(s2, REG_ITMP3, REG_ITMP3);
+                       M_SLDU(d, REG_ITMP3, OFFSET(java_chararray, data[0]));
+                       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_AADD(s2, s1, REG_ITMP3);
+                       M_AADD(s2, REG_ITMP3, REG_ITMP3);
+                       M_SLDS(d, REG_ITMP3, OFFSET(java_chararray, data[0]));
+                       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_ASLL_IMM(s2, 2, REG_ITMP3);
+                       M_AADD(REG_ITMP3, s1, REG_ITMP3);
+                       M_ILD(d, REG_ITMP3, OFFSET(java_intarray, data[0]));
+                       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, REG_ITMP2);
+                       if (iptr->op1 == 0) {
+                               gen_nullptr_check(s1);
+                               gen_bound_check;
+                       }
+                       M_ASLL_IMM(s2, 3, REG_ITMP3);
+                       M_AADD(REG_ITMP3, s1, REG_ITMP3);
+                       M_LDX(d, REG_ITMP3, 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_ASLL_IMM(s2, 2, REG_ITMP3);
+                       M_AADD(REG_ITMP3, s1, REG_ITMP3);
+                       M_FLD(d, REG_ITMP3, OFFSET(java_floatarray, data[0]));
+                       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_ASLL_IMM(s2, 3, REG_ITMP3);
+                       M_AADD(REG_ITMP3, s1, REG_ITMP3);
+                       M_DLD(d, REG_ITMP3, OFFSET(java_doublearray, data[0]));
+                       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_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP3);
+                       M_AADD(REG_ITMP3, s1, REG_ITMP3);
+                       M_ALD(d, REG_ITMP3, OFFSET(java_objectarray, data[0]));
+                       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;
+                       }
+                       M_AADD(s2, s1, REG_ITMP1);
+                       s3 = emit_load_s3(jd, iptr, src, REG_ITMP3);
+                       M_BST(s3, REG_ITMP1, OFFSET(java_bytearray, data[0]));
+                       break;
+
+               case ICMD_CASTORE:    /* ..., arrayref, index, value  ==> ...         */
+               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;
+                       }
+                       M_AADD(s2, s1, REG_ITMP1);
+                       M_AADD(s2, REG_ITMP1, REG_ITMP1);
+                       s3 = emit_load_s3(jd, iptr, src, REG_ITMP3);
+                       M_SST(s3, REG_ITMP1, OFFSET(java_chararray, data[0]));
+                       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;
+                       }
+                       M_ASLL_IMM(s2, 2, REG_ITMP2);
+                       M_AADD(REG_ITMP2, s1, REG_ITMP1);
+                       s3 = emit_load_s3(jd, iptr, src, REG_ITMP3);
+                       M_IST_INTERN(s3, REG_ITMP1, OFFSET(java_intarray, data[0]));
+                       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;
+                       }
+                       M_ASLL_IMM(s2, 3, REG_ITMP2);
+                       M_AADD(REG_ITMP2, s1, REG_ITMP1);
+                       s3 = emit_load_s3(jd, iptr, src, REG_ITMP3);
+                       M_STX_INTERN(s3, REG_ITMP1, OFFSET(java_longarray, data[0]));
+                       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;
+                       }
+                       M_ASLL_IMM(s2, 2, REG_ITMP2);
+                       M_AADD(REG_ITMP2, s1, REG_ITMP1);
+                       s3 = emit_load_s3(jd, iptr, src, REG_FTMP1);
+                       M_FST_INTERN(s3, REG_ITMP1, OFFSET(java_floatarray, data[0]));
+                       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;
+                       }
+                       M_ASLL_IMM(s2, 3, REG_ITMP2);
+                       M_AADD(REG_ITMP2, s1, REG_ITMP1);
+                       s3 = emit_load_s3(jd, iptr, src, REG_FTMP1);
+                       M_DST_INTERN(s3, REG_ITMP1, OFFSET(java_doublearray, data[0]));
+                       break;
+
+
+               case ICMD_AASTORE:    /* ..., 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_MOV(s1, rd->argintregs[0]);
+                       M_MOV(s3, rd->argintregs[1]);
+                       disp = dseg_addaddress(cd, BUILTIN_canstore);
+                       M_ALD(REG_ITMP3, REG_PV, disp);
+                       M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
+                       M_NOP;
+
+                       M_BEQZ(REG_RESULT_CALLER, 0);
+                       codegen_add_arraystoreexception_ref(cd);
+                       M_NOP;
+
+                       s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
+                       M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
+                       M_AADD(REG_ITMP2, s1, REG_ITMP1);
+                       s3 = emit_load_s3(jd, iptr, src, REG_ITMP3);
+                       M_AST_INTERN(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
+                       break;
+
+
+               case ICMD_BASTORECONST:   /* ..., arrayref, index  ==> ...            */
+
+                       s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
+                       if (iptr->op1 == 0) {
+                               gen_nullptr_check(s1);
+                               gen_bound_check;
+                       }
+                       M_AADD(s2, s1, REG_ITMP1);
+                       M_BST(REG_ZERO, REG_ITMP1, OFFSET(java_bytearray, data[0]));
+                       break;
+
+               case ICMD_CASTORECONST:   /* ..., arrayref, index  ==> ...            */
+               case ICMD_SASTORECONST:   /* ..., arrayref, index  ==> ...            */
+
+                       s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
+                       if (iptr->op1 == 0) {
+                               gen_nullptr_check(s1);
+                               gen_bound_check;
+                       }
+                       M_AADD(s2, s1, REG_ITMP1);
+                       M_AADD(s2, REG_ITMP1, REG_ITMP1);
+                       M_SST(REG_ZERO, REG_ITMP1, OFFSET(java_chararray, data[0]));
+                       break;
+
+               case ICMD_IASTORECONST:   /* ..., arrayref, index  ==> ...            */
+
+                       s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
+                       if (iptr->op1 == 0) {
+                               gen_nullptr_check(s1);
+                               gen_bound_check;
+                       }
+                       M_ASLL_IMM(s2, 2, REG_ITMP2);
+                       M_AADD(REG_ITMP2, s1, REG_ITMP1);
+                       M_IST_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_intarray, data[0]));
+                       break;
+
+               case ICMD_LASTORECONST:   /* ..., arrayref, index  ==> ...            */
+
+                       s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
+                       if (iptr->op1 == 0) {
+                               gen_nullptr_check(s1);
+                               gen_bound_check;
+                       }
+                       M_ASLL_IMM(s2, 3, REG_ITMP2);
+                       M_AADD(REG_ITMP2, s1, REG_ITMP1);
+                       M_STX_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_longarray, data[0]));
+                       break;
+
+               case ICMD_AASTORECONST:   /* ..., arrayref, index  ==> ...            */
+
+                       s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
+                       s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
+                       if (iptr->op1 == 0) {
+                               gen_nullptr_check(s1);
+                               gen_bound_check;
+                       }
+                       M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
+                       M_AADD(REG_ITMP2, s1, REG_ITMP1);
+                       M_AST_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_objectarray, data[0]));
+                       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; 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, 0);
+
+                                       if (opt_showdisassemble) {
+                                               M_NOP; 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);
+                               emit_store(jd, iptr, iptr->dst, d);
+                               break;
+                       case TYPE_LNG:
+                               d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
+                               M_LDX_INTERN(d, REG_ITMP1, 0);
+                               emit_store(jd, iptr, iptr->dst, d);
+                               break;
+                       case TYPE_ADR:
+                               d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
+                               M_ALD_INTERN(d, REG_ITMP1, 0);
+                               emit_store(jd, iptr, iptr->dst, d);
+                               break;
+                       case TYPE_FLT:
+                               d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
+                               M_FLD_INTERN(d, REG_ITMP1, 0);
+                               emit_store(jd, iptr, iptr->dst, d);
+                               break;
+                       case TYPE_DBL:                          
+                               d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
+                               M_DLD_INTERN(d, REG_ITMP1, 0);
+                               emit_store(jd, iptr, iptr->dst, d);
+                               break;
+                       }
+                       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; 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, 0);
+
+                                       if (opt_showdisassemble) {
+                                               M_NOP; 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, REG_ITMP2);
+                               M_STX_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_PUTSTATICCONST: /* ...  ==> ...                             */
+                                         /* val = value (in current instruction)     */
+                                         /* op1 = type, val.a = field address (in    */
+                                         /* following NOP)                           */
+
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr + 1)) {
+                               disp = dseg_addaddress(cd, NULL);
+
+                               codegen_addpatchref(cd, PATCHER_get_putstatic,
+                                                                       INSTRUCTION_UNRESOLVED_FIELD(iptr + 1), disp);
+
+                               if (opt_showdisassemble) {
+                                       M_NOP; M_NOP;
+                               }
+
+                       } else {
+                               fieldinfo *fi = INSTRUCTION_RESOLVED_FIELDINFO(iptr + 1);
+
+                               disp = dseg_addaddress(cd, &(fi->value));
+
+                               if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
+                                       codegen_addpatchref(cd, PATCHER_clinit, fi->class, 0);
+
+                                       if (opt_showdisassemble) {
+                                               M_NOP; M_NOP;
+                                       }
+                               }
+                       }
+
+                       M_ALD(REG_ITMP1, REG_PV, disp);
+                       switch (iptr->op1) {
+                       case TYPE_INT:
+                               M_IST_INTERN(REG_ZERO, REG_ITMP1, 0);
+                               break;
+                       case TYPE_LNG:
+                               M_STX_INTERN(REG_ZERO, REG_ITMP1, 0);
+                               break;
+                       case TYPE_ADR:
+                               M_AST_INTERN(REG_ZERO, REG_ITMP1, 0);
+                               break;
+                       case TYPE_FLT:
+                               M_FST_INTERN(REG_ZERO, REG_ITMP1, 0);
+                               break;
+                       case TYPE_DBL:
+                               M_DST_INTERN(REG_ZERO, 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; 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);
+                               emit_store(jd, iptr, iptr->dst, d);
+                               break;
+                       case TYPE_LNG:
+                               d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
+                               M_LDX(d, s1, disp);
+                               emit_store(jd, iptr, iptr->dst, d);
+                               break;
+                       case TYPE_ADR:
+                               d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
+                               M_ALD(d, s1, disp);
+                               emit_store(jd, iptr, iptr->dst, d);
+                               break;
+                       case TYPE_FLT:
+                               d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
+                               M_FLD(d, s1, disp);
+                               emit_store(jd, iptr, iptr->dst, d);
+                               break;
+                       case TYPE_DBL:                          
+                               d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
+                               M_DLD(d, s1, disp);
+                               emit_store(jd, iptr, iptr->dst, d);
+                               break;
+                       }
+                       break;
+
+               case ICMD_PUTFIELD:   /* ..., objectref, value  ==> ...               */
+                                     /* op1 = type, val.a = field address            */
+
+                       s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP2);
+                       gen_nullptr_check(s1);
+
+                       /*if (!IS_FLT_DBL_TYPE(iptr->op1)) {
+                               s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
+                       } else {*/
+                               s2 = emit_load_s2(jd, iptr, src, REG_IFTMP);
+                       /*}*/
+
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                               codegen_addpatchref(cd, PATCHER_get_putfield,
+                                                                       INSTRUCTION_UNRESOLVED_FIELD(iptr), 0);
+
+                               if (opt_showdisassemble) {
+                                       M_NOP; 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_STX(s2, s1, disp);
+                               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;
+
+               case ICMD_PUTFIELDCONST:  /* ..., objectref  ==> ...                  */
+                                         /* val = value (in current instruction)     */
+                                         /* op1 = type, val.a = field address (in    */
+                                         /* following NOP)                           */
+
+                       s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
+                       gen_nullptr_check(s1);
+
+                       if (INSTRUCTION_IS_UNRESOLVED(iptr + 1)) {
+                               codegen_addpatchref(cd, PATCHER_get_putfield,
+                                                                       INSTRUCTION_UNRESOLVED_FIELD(iptr + 1), 0);
+
+                               if (opt_showdisassemble) {
+                                       M_NOP; M_NOP;
+                               }
+
+                               disp = 0;
+
+                       } else {
+                               disp = INSTRUCTION_RESOLVED_FIELDINFO(iptr + 1)->offset;
+                       }
+
+                       switch (iptr[1].op1) {
+                       case TYPE_INT:
+                               M_IST(REG_ZERO, s1, disp);
+                               break;
+                       case TYPE_LNG:
+                               M_STX(REG_ZERO, s1, disp);
+                               break;
+                       case TYPE_ADR:
+                               M_AST(REG_ZERO, s1, disp);
+                               break;
+                       case TYPE_FLT:
+                               M_FST(REG_ZERO, s1, disp);
+                               break;
+                       case TYPE_DBL:
+                               M_DST(REG_ZERO, s1, disp);
+                               break;
+                       }
+                       break;
+
+
+               /* branch operations **************************************************/
+
+               case ICMD_ATHROW:       /* ..., objectref ==> ... (, objectref)       */
+
+                       s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
+                       M_INTMOVE(s1, REG_ITMP2_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_JMP(REG_ITMP3_XPC, REG_ITMP2, REG_ZERO);
+                       M_NOP;
+                       M_NOP;              /* nop ensures that XPC is less than the end */
+                                           /* of basic block                            */
+                       ALIGNCODENOP;
+                       break;
+
+               case ICMD_GOTO:         /* ... ==> ...                                */
+                                       /* op1 = target JavaVM pc                     */
+                       M_BR(0);
+                       codegen_addreference(cd, (basicblock *) iptr->target);
+                       M_NOP;
+                       ALIGNCODENOP;
+                       break;
+
+               case ICMD_JSR:          /* ... ==> ...                                */
+                                       /* op1 = target JavaVM pc                     */
+
+                       dseg_addtarget(cd, (basicblock *) iptr->target);
+                       M_ALD(REG_ITMP1, REG_PV, -(cd->dseglen));
+                       M_JMP(REG_ITMP1, REG_ITMP1, REG_ZERO);        /* REG_ITMP1 = return address */
+                       M_NOP;
+                       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 * 8);
+                               M_RET(REG_ITMP1);
+                       } else
+                               M_RET(var->regoff);
+                       M_NOP;
+                       ALIGNCODENOP;
+                       break;
+
+               case ICMD_IFNULL:       /* ..., value ==> ...                         */
+                                       /* op1 = target JavaVM pc                     */
+
+                       s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
+                       M_BEQZ(s1, 0);
+                       codegen_addreference(cd, (basicblock *) iptr->target);
+                       M_NOP;
+                       break;
+
+               case ICMD_IFNONNULL:    /* ..., value ==> ...                         */
+                                       /* op1 = target JavaVM pc                     */
+
+                       s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
+                       M_BNEZ(s1, 0);
+                       codegen_addreference(cd, (basicblock *) iptr->target);
+                       M_NOP;
+                       break;
+/* XXX: CMP_IMM */
+               case ICMD_IFEQ:         /* ..., value ==> ...                         */
+                                       /* op1 = target JavaVM pc, val.i = constant   */
+
+                       s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
+                       if (iptr->val.i == 0) {
+                               M_BEQZ(s1, 0);
+                       } else {
+                               if ((iptr->val.i >= -4096) && (iptr->val.i <= 4095)) {
+                                       M_CMP_IMM(s1, iptr->val.i);
+                                       }
+                               else {
+                                       ICONST(REG_ITMP2, iptr->val.i);
+                                       M_CMP(s1, REG_ITMP2);
+                                       }
+                               M_BEQ(0);
+                               }
+                       codegen_addreference(cd, (basicblock *) iptr->target);
+                       M_NOP;
+                       break;
+
+               case ICMD_IFLT:         /* ..., value ==> ...                         */
+                                       /* op1 = target JavaVM pc, val.i = constant   */
+
+                       s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
+                       if (iptr->val.i == 0) {
+                               M_BLTZ(s1, 0);
+                       } else {
+                               if ((iptr->val.i >= -4096) && (iptr->val.i <= 4095)) {
+                                       M_CMP_IMM(s1, iptr->val.i);
+                               } else {
+                                       ICONST(REG_ITMP2, iptr->val.i);
+                                       M_CMP(s1, REG_ITMP2);
+                               }
+                               M_BLT(0);
+                       }
+                       codegen_addreference(cd, (basicblock *) iptr->target);
+                       M_NOP;
+                       break;
+
+               case ICMD_IFLE:         /* ..., value ==> ...                         */
+                                       /* op1 = target JavaVM pc, val.i = constant   */
+
+                       s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
+                       if (iptr->val.i == 0) {
+                               M_BLEZ(s1, 0);
+                               }
+                       else {
+                               if ((iptr->val.i >= -4096) && (iptr->val.i <= 4095)) {
+                                       M_CMP_IMM(s1, iptr->val.i);
+                                       }
+                               else {
+                                       ICONST(REG_ITMP2, iptr->val.i);
+                                       M_CMP(s1, REG_ITMP2);
+                               }
+                               M_BLE(0);
+                       }
+                       codegen_addreference(cd, (basicblock *) iptr->target);
+                       M_NOP;
+                       break;
+
+               case ICMD_IFNE:         /* ..., value ==> ...                         */
+                                       /* op1 = target JavaVM pc, val.i = constant   */
+
+                       s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
+                       if (iptr->val.i == 0) {
+                               M_BNEZ(s1, 0);
+                               }
+                       else {
+                               if ((iptr->val.i >= -4096) && (iptr->val.i <= 4095)) {
+                                       M_CMP_IMM(s1, iptr->val.i);
+                               }
+                               else {
+                                       ICONST(REG_ITMP2, iptr->val.i);
+                                       M_CMP(s1, REG_ITMP2);
+                               }
+                               M_BNE(0);
+                       }
+                       codegen_addreference(cd, (basicblock *) iptr->target);
+                       M_NOP;
+                       break;
+
+               case ICMD_IF_ACMPEQ:    /* ..., value, value ==> ...                  */
+               case ICMD_IF_LCMPEQ:    /* 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_XBEQ(0);
+                       codegen_addreference(cd, (basicblock *) iptr->target);
+                       M_NOP;
+                       break;
+
+               case ICMD_IF_ICMPEQ:    /* 32-bit compare                             */
+
+                       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);
+                       M_NOP;
+                       break;
+
+               case ICMD_IF_ACMPNE:    /* ..., value, value ==> ...                  */
+               case ICMD_IF_LCMPNE:    /* 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_XBNE(0);
+                       codegen_addreference(cd, (basicblock *) iptr->target);
+                       M_NOP;
+                       break;
+                       
+               case ICMD_IF_ICMPNE:    /* 32-bit compare                             */
+
+                       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);
+                       M_NOP;
+                       break;
+
+               case ICMD_IF_LCMPLT:    /* ..., 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_XBLT(0);
+                       codegen_addreference(cd, (basicblock *) iptr->target);
+                       M_NOP;
+                       break;
+                       
+               case ICMD_IF_ICMPLT:    /* 32-bit compare                             */
+
+                       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);
+                       M_NOP;
+                       break;
+
+               case ICMD_IF_LCMPGT:    /* ..., 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_XBGT(0);
+                       codegen_addreference(cd, (basicblock *) iptr->target);
+                       M_NOP;
+                       break;
+                       
+               case ICMD_IF_ICMPGT:    /* 32-bit compare                             */
+
+                       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);
+                       M_NOP;
+                       break;
+
+               case ICMD_IF_LCMPLE:    /* ..., 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);
+                       M_NOP;
+                       break;
+                       
+               case ICMD_IF_ICMPLE:    /* 32-bit compare                             */
+
+                       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);
+                       M_NOP;
+                       break;                  
+       
+
+               case ICMD_IF_LCMPGE:    /* ..., 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);
+                       M_NOP;
+                       break;
+                       
+               case ICMD_IF_ICMPGE:    /* 32-bit compare                             */
+
+                       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);
+                       M_NOP;
+                       break;
+
+               /* (value xx 0) ? IFxx_ICONST : ELSE_ICONST                           */
+
+               case ICMD_ELSE_ICONST:  /* handled by IFxx_ICONST                     */
+                       break;
+
+/* XXX: do all of these compare against an INT value on the stack ?? */
+               case ICMD_IFEQ_ICONST:  /* ..., 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);
+                       s3 = iptr->val.i;
+                       if (iptr[1].opc == ICMD_ELSE_ICONST) {
+                               if (s1 == d) {
+                                       M_MOV(s1, REG_ITMP1);
+                                       s1 = REG_ITMP1;
+                               }
+                               ICONST(d, iptr[1].val.i);
+                       }
+                       if ((s3 >= -512) && (s3 <= 511)) {
+                               M_CMOVREQ_IMM(s1, s3, d);
+                       } else {
+                               ICONST(REG_ITMP3, s3);
+                               M_CMOVREQ(s1, REG_ITMP3, d);
+                       }
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_IFNE_ICONST:  /* ..., 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);
+                       s3 = iptr->val.i;
+                       if (iptr[1].opc == ICMD_ELSE_ICONST) {
+                               if (s1 == d) {
+                                       M_MOV(s1, REG_ITMP1);
+                                       s1 = REG_ITMP1;
+                               }
+                               ICONST(d, iptr[1].val.i);
+                       }
+                       if ((s3 >= -512) && (s3 <= 511)) {
+                               M_CMOVRNE_IMM(s1, s3, d);
+                       } else {
+                               ICONST(REG_ITMP3, s3);
+                               M_CMOVRNE(s1, REG_ITMP3, d);
+                       }
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_IFLT_ICONST:  /* ..., 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);
+                       s3 = iptr->val.i;
+                       if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
+                               if (s1 == d) {
+                                       M_MOV(s1, REG_ITMP1);
+                                       s1 = REG_ITMP1;
+                               }
+                               ICONST(d, iptr[1].val.i);
+                       }
+                       if ((s3 >= -512) && (s3 <= 511)) {
+                               M_CMOVRLT_IMM(s1, s3, d);
+                       } else {
+                               ICONST(REG_ITMP3, s3);
+                               M_CMOVRLT(s1, REG_ITMP3, d);
+                       }
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_IFGE_ICONST:  /* ..., 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);
+                       s3 = iptr->val.i;
+                       if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
+                               if (s1 == d) {
+                                       M_MOV(s1, REG_ITMP1);
+                                       s1 = REG_ITMP1;
+                               }
+                               ICONST(d, iptr[1].val.i);
+                       }
+                       if ((s3 >= -512) && (s3 <= 511)) {
+                               M_CMOVRGE_IMM(s1, s3, d);
+                       } else {
+                               ICONST(REG_ITMP3, s3);
+                               M_CMOVRGE(s1, REG_ITMP3, d);
+                       }
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_IFGT_ICONST:  /* ..., 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);
+                       s3 = iptr->val.i;
+                       if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
+                               if (s1 == d) {
+                                       M_MOV(s1, REG_ITMP1);
+                                       s1 = REG_ITMP1;
+                               }
+                               ICONST(d, iptr[1].val.i);
+                       }
+                       if ((s3 >= -512) && (s3 <= 511)) {
+                               M_CMOVRGT_IMM(s1, s3, d);
+                       } else {
+                               ICONST(REG_ITMP3, s3);
+                               M_CMOVRGT(s1, REG_ITMP3, d);
+                       }
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+               case ICMD_IFLE_ICONST:  /* ..., 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);
+                       s3 = iptr->val.i;
+                       if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
+                               if (s1 == d) {
+                                       M_MOV(s1, REG_ITMP1);
+                                       s1 = REG_ITMP1;
+                               }
+                               ICONST(d, iptr[1].val.i);
+                       }
+                       if ((s3 >= -512) && (s3 <= 511)) {
+                               M_CMOVRLE_IMM(s1, s3, d);
+                       } else {
+                               ICONST(REG_ITMP3, s3);
+                               M_CMOVRLE(s1, REG_ITMP3, d);
+                       }
+                       emit_store(jd, iptr, iptr->dst, d);
+                       break;
+
+
+               case ICMD_IRETURN:      /* ..., retvalue ==> ...                      */
+               case ICMD_LRETURN:
+
+                       s1 = emit_load_s1(jd, iptr, src, REG_RESULT_CALLEE);
+                       M_INTMOVE(s1, REG_RESULT_CALLEE);
+                       goto nowperformreturn;
+
+               case ICMD_ARETURN:      /* ..., retvalue ==> ...                      */
+
+                       s1 = emit_load_s1(jd, iptr, src, REG_RESULT_CALLEE);
+                       M_INTMOVE(s1, REG_RESULT_CALLEE);
+
+#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_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 !defined(NDEBUG)
+                       if (opt_verbosecall) {
+                               M_LDA(REG_SP, REG_SP, -3 * 8);
+                               M_AST(REG_RA_CALLEE, REG_SP, 0 * 8); /* XXX: no need to save anything but FRES ? */
+               /*              M_STX(REG_RESULT, REG_SP, 1 * 8); */
+                               M_DST(REG_FRESULT, REG_SP, 2 * 8);
+
+                               disp = dseg_addaddress(cd, m);
+                               M_ALD(rd->argintregs[0], REG_PV, disp);
+                               M_MOV(REG_RESULT_CALLEE, rd->argintregs[1]);
+                               M_FLTMOVE(REG_FRESULT, rd->argfltregs[2]);
+                               M_FLTMOVE(REG_FRESULT, rd->argfltregs[3]);
+
+                               disp = dseg_addaddress(cd, (void *) builtin_displaymethodstop);
+                               M_ALD(REG_ITMP3, REG_PV, disp);
+                               M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
+                               M_NOP;
+
+                               M_DLD(REG_FRESULT, REG_SP, 2 * 8);
+               /*              M_LDX(REG_RESULT, REG_SP, 1 * 8); */
+                               M_ALD(REG_RA_CALLEE, REG_SP, 0 * 8);
+                               M_LDA(REG_SP, REG_SP, 3 * 8);
+                       }
+#endif
+
+#if defined(ENABLE_THREADS)
+                       if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
+/* XXX: REG_RESULT is save, but what about FRESULT? */
+                               M_ALD(rd->argintregs[0], REG_SP, rd->memuse * 8); /* XXX: what for ? */
+
+                               switch (iptr->opc) {
+                               case ICMD_FRETURN:
+                               case ICMD_DRETURN:
+                                       M_DST(REG_FRESULT, REG_SP, rd->memuse * 8);
+                                       break;
+                               }
+
+                               disp = dseg_addaddress(cd, BUILTIN_monitorexit);
+                               M_ALD(REG_ITMP3, REG_PV, disp);
+                               M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO); /*REG_RA_CALLER */
+
+                               switch (iptr->opc) {
+                               case ICMD_FRETURN:
+                               case ICMD_DRETURN:
+                                       M_DLD(REG_FRESULT, REG_SP, rd->memuse * 8);
+                                       break;
+                               }
+                       }
+#endif
+
+
+
+                       M_RETURN(REG_RA_CALLEE); /* implicit window restore */
+                       M_NOP;
+                       ALIGNCODENOP;
+                       }
+                       break;
+
+
+               default:
+                       *exceptionptr = new_internalerror("Unknown ICMD %d", 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)) {
+                               var_to_reg_flt(s1, src, REG_FTMP1);
+                               if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
+                                       M_FLTMOVE(s1,rd->interfaces[len][s2].regoff);
+                                       }
+                               else {
+                                       M_DST(s1, REG_SP, 8 * rd->interfaces[len][s2].regoff);
+                                       }
+                               }
+                       else {
+                               var_to_reg_int(s1, src, REG_ITMP1);
+                               if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
+                                       M_INTMOVE(s1,rd->interfaces[len][s2].regoff);
+                                       }
+                               else {
+                                       M_STX(s1, REG_SP, 8 * rd->interfaces[len][s2].regoff);
+                                       }
+                               }
+                       }
+               src = src->prev;
+               }
+       } /* if (bptr -> flags >= BBREACHED) */
+       } /* for basic block */
+       
+       
+       
+}
+
+
+
+
+
+/* createcompilerstub **********************************************************
+
+   Creates a stub routine which calls the compiler.
+       
+*******************************************************************************/
+
+#define COMPILERSTUB_DATASIZE    2 * SIZEOF_VOID_P
+#define COMPILERSTUB_CODESIZE    3 * 4
+
+#define COMPILERSTUB_SIZE        COMPILERSTUB_DATASIZE + COMPILERSTUB_CODESIZE
+
+
+u1 *createcompilerstub(methodinfo *m)
+{
+       u1     *s;                          /* memory to hold the stub            */
+       ptrint *d;
+       s4     *mcodeptr;                   /* code generation pointer            */
+
+       s = CNEW(u1, COMPILERSTUB_SIZE);
+
+       /* set data pointer and code pointer */
+
+       d = (ptrint *) s;
+       s = s + COMPILERSTUB_DATASIZE;
+
+       mcodeptr = (s4 *) s;
+       
+       /* Store the methodinfo* in the same place as in the methodheader
+          for compiled methods. */
+
+       d[0] = (ptrint) asm_call_jit_compiler;
+       d[1] = (ptrint) m;
+
+       /* code for the stub */
+
+       M_LDX(REG_ITMP1, REG_PV_CALLER, -1 * 8);   /* load methodinfo pointer            */
+       /* XXX CALLER PV ??? */
+       M_LDX(REG_PV_CALLER ,REG_PV_CALLER, -2 * 8);      /* load pointer to the compiler       */
+       M_JMP(REG_ZERO, REG_PV_CALLER, REG_ZERO);  /* jump to the compiler, RA is wasted */
+
+#if defined(ENABLE_STATISTICS)
+       if (opt_stat)
+               count_cstub_len += COMPILERSTUB_SIZE;
+#endif
+
+       return s;
+}
+
+
+
+/* createnativestub ************************************************************
+
+   Creates a stub routine which calls a native method.
+
+*******************************************************************************/
+
+u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd)
+{
+       fabort("help me!");
+       return NULL;
+}
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
diff --git a/src/vm/jit/sparc64/codegen.h b/src/vm/jit/sparc64/codegen.h
new file mode 100644 (file)
index 0000000..3672da1
--- /dev/null
@@ -0,0 +1,598 @@
+/* vm/jit/sparc64/codegen.h - code generation macros and definitions for Sparc
+
+   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
+            Alexander Jordan
+
+   Changes:
+
+   $Id: codegen.h 4722 2006-04-03 15:36:00Z twisti $
+
+*/
+
+#ifndef _CODEGEN_H
+#define _CODEGEN_H
+
+#include "config.h"
+#include "vm/types.h"
+
+#include "vm/jit/jit.h"
+
+
+/* additional functions and macros to generate code ***************************/
+
+#define gen_nullptr_check(objreg) \
+    if (checknull) { \
+        M_BEQZ(objreg, 0); \
+        codegen_add_nullpointerexception_ref(cd); \
+        M_NOP; \
+    }
+
+#define gen_bound_check \
+    if (checkbounds) { \
+        M_ILD(REG_ITMP3, s1, OFFSET(java_arrayheader, size)); \
+        M_CMP(s2, REG_ITMP3); \
+        M_XBUGE(0); \
+        codegen_add_arrayindexoutofboundsexception_ref(cd, s2); \
+        M_NOP; \
+    }
+
+#define gen_div_check(r) \
+    do { \
+        M_BEQZ((r), 0); \
+        codegen_add_arithmeticexception_ref(cd); \
+        M_NOP; \
+    } while (0)
+
+/* MCODECHECK(icnt) */
+
+#define MCODECHECK(icnt) \
+       do { \
+               if ((cd->mcodeptr + (icnt) * 4) > cd->mcodeend) \
+                       codegen_increase(cd); \
+       } while (0)
+
+
+#define ALIGNCODENOP \
+    if ((s4) ((ptrint) mcodeptr & 7)) { \
+        M_NOP; \
+    }
+
+
+/* M_INTMOVE:
+     generates an integer-move from register rs to rd.
+     if rs and rd are the same int-register, no code will be generated.
+*/ 
+
+#define M_INTMOVE(rs,rd) if (rs != rd) { M_MOV(rs, rd); }
+
+
+/* M_DBLMOVE:
+    generates a double floating-point-move from register (pair) rs to rd.
+    if rs and rd are the same double-register, no code will be generated
+*/ 
+
+#define M_DBLMOVE(rs, rd) if (rs != rd) { M_DMOV (rs, rd); }
+
+
+/* M_FLTMOVE:
+    generates a double floating-point-move from pseudo register rs to rd.
+       (ie. lower register of double rs pair to lower register of double rd pair)
+    if rs and rd are the same double-register, no code will be generated
+*/ 
+#define M_FLTMOVE(rs, rd) if (rs != rd) { M_FMOV (rs, rd); }
+
+
+
+#define M_COPY(s,d)                     emit_copy(jd, iptr, (s), (d))
+
+
+
+
+/********************** instruction formats ***********************************/
+
+#define REG    0
+#define IMM    1
+
+/* 3-address-operations: M_OP3
+ *       op  ..... opcode
+ *       op3 ..... operation
+ *       rs1 ..... register number source 1
+ *       rs2 ..... register number or constant integer source 2
+ *       rd  ..... register number destination
+ *       imm ..... switch to use rs2 as constant 13bit integer 
+ *                  (REG means: use b as register number)
+ *                  (IMM means: use b as signed immediate value)
+ *                                                                       */
+
+#define M_OP3(op,op3,rd,rs1,rs2,imm) \
+       *(mcodeptr++) =  ((((s4) (op)) << 30) | ((rd) << 25) | ((op3) << 19) | ((rs1) << 14) | ((imm)<<13) | (imm?((rs2)&0x1fff):(rs2)) )
+
+/* 3-address-operations: M_OP3C
+ *       rcond ... condition opcode
+ *       rs2 ..... register number or 10bit signed immediate
+ *
+ */
+#define M_OP3C(op,op3,rcond,rd,rs1,rs2,imm) \
+       *(mcodeptr++) =  ((((s4) (op)) << 30) | ((rd) << 25) | ((op3) << 19) | ((rs1) << 14) | ((imm)<<13) | \
+               ((rcond) << 10) | (imm?((rs2)&0x3ff):(rs2)) )
+       
+
+
+/* shift Format 3
+ *    op ..... opcode
+ *    op3..... op3 code
+ *    rs1 .... source 1
+ *    rs2 .... source 2 or constant
+ *    rd ..... dest reg
+ *    imm .... switch for constant
+ *    x ...... 0 => 32, 1 => 64 bit shift 
+ */
+#define M_SHFT(op,op3,rs1,rs2,rd,imm,x) \
+       *(mcodeptr++) =  ( (((s4)(op)) << 30) | ((op3) << 19) | ((rd) << 25) | ((rs1) << 14) | ((rs2) << 0) | \
+                     ((imm) << 13) | ((x) << 12)  )
+
+/* Format 4
+ *    op ..... opcode
+ *    op3..... op3 code
+ *    cond ... condition opcode
+ *    rs2 .... source 2 or signed 11-bit constant
+ *    rd ..... dest reg
+ *    imm .... switch for constant
+ *    cc{0-2}  32-bit 64-bit or fp condition
+ */
+ #define M_FMT4(op,op3,rd,rs2,cond,cc2,cc1,cc0,imm) \
+       *(mcodeptr++) =  ( (((s4)(op)) << 30) | ((op3) << 19) | ((rd) << 25) | ((cc2) << 18) |  ((cond) << 14) | \
+               ((imm) << 13) | ((cc1) << 12) | ((cc0) << 11) | ((rs2) << 0) )
+
+
+
+
+/* 3-address-floating-point-operation
+     op .... opcode
+     op3,opf .... function-number
+     XXX
+*/ 
+#define M_FOP3(op,op3,opf,rd,rs1,rs2) \
+       *(mcodeptr++) =  ( (((s4)(op))<<30) | ((rd)<<25) | ((op3)<<19) | ((rs1) << 14) | ((opf)<<5) | (rs2) )
+
+
+/**** format 2 operations ********/
+
+/* branch on integer reg instruction 
+      op ..... opcode
+      rcond ...... condition to be tested
+      disp16 ... 16-bit relative address to be jumped to (divided by 4)
+      rs1 ..... register to be tested
+      p ..... prediction bit
+      anul .... annullment bit
+*/
+#define M_BRAREG(op,rcond,rs1,disp16,p,anul) \
+       *(mcodeptr++) = ( (((s4)(op))<<30) | ((anul)<<29) | (0<<28) | ((rcond)<<25) | (3<<22) | \
+               ( ((disp16)& 0xC000) << 6 ) | (p << 19) | ((rs1) << 14) | ((disp16)&0x3fff) )
+               
+/* branch on integer reg instruction 
+      op,op2 .... opcodes
+      cond ...... condition to be tested
+      disp19 ... 19-bit relative address to be jumped to (divided by 4)
+      ccx ..... 32(0) or 64(2) bit test
+      p ..... prediction bit
+      anul .... annullment bit
+*/             
+#define M_BRACC(op,op2,cond,disp19,ccx,p,anul) \
+       *(mcodeptr++) = ( (((s4)(op))<<30) | ((anul)<<29) | ((cond)<<25) | (op2<<22) | (ccx<<20) | \
+               (p << 19 ) | (disp19)  )    
+        
+/************** end-user instructions (try to follow asm style) ***************/
+
+
+#define M_SETHI(imm22, rd) \
+       *(mcodeptr++) = ((((s4)(0x00)) << 30) | ((rd) << 25) | ((0x04)<<22) | ((imm22)&0x3FFFFF) )
+
+
+#define M_NOP (M_SETHI(0,0))   /* nop  */
+
+#define M_AND(rs1,rs2,rd)       M_OP3(0x02,0x01,rd,rs1,rs2,REG)     /* 64b c = a &  b */
+#define M_AND_IMM(rs1,rs2,rd)  M_OP3(0x02,0x01,rd,rs1,rs2,IMM)
+#define M_ANDCC(rs1,rs2,rd)            M_OP3(0x02,0x11,rd,rs1,rs2,REG)
+#define M_ANDCC_IMM(rs1,rs2,rd)        M_OP3(0x02,0x11,rd,rs1,rs2,IMM)
+
+#define M_OR(rs1,rs2,rd)        M_OP3(0x02,0x02,rd,rs1,rs2,REG)     /* rd = rs1 | rs2     */
+#define M_OR_IMM(rs1,rs2,rd)    M_OP3(0x02,0x02,rd,rs1,rs2,IMM)
+#define M_XOR(rs1,rs2,rd)       M_OP3(0x02,0x03,rs1,rs2,rd,REG)     /* rd = rs1 ^  rs2    */
+#define M_XOR_IMM(rs1,rs2,rd)   M_OP3(0x02,0x03,rs1,rs2,rd,IMM)
+
+#define M_MOV(rs,rd)            M_OR(REG_ZERO, rs, rd)              /* rd = rs            */
+
+
+
+#define M_SLLX(rs1,rs2,rd)             M_SHFT(0x02,0x25,rs1,rs2,rd,REG,1)      /* 64b rd = rs << rs2 */
+#define M_SLLX_IMM(rs1,rs2,rd) M_SHFT(0x02,0x25,rs1,rs2,rd,IMM,1)
+#define M_SRLX(rs1,rs2,rd)             M_SHFT(0x02,0x26,rs1,rs2,rd,REG,1)      /* 64b rd = rs >>>rs2 */
+#define M_SRLX_IMM(rs1,rs2,rd) M_SHFT(0x02,0x26,rs1,rs2,rd,IMM,1)
+#define M_SRL(rs1,rs2,rd)              M_SHFT(0x02,0x26,rs1,rs2,rd,REG,0)      /* 32b rd = rs >>>rs2 */
+#define M_SRL_IMM(rs1,rs2,rd)  M_SHFT(0x02,0x26,rs1,rs2,rd,IMM,0)
+#define M_SRAX(rs1,rs2,rd)             M_SHFT(0x02,0x27,rs1,rs2,rd,REG,1)      /* 64b rd = rs >> rs2 */
+#define M_SRAX_IMM(rs1,rs2,rd) M_SHFT(0x02,0x27,rs1,rs2,rd,IMM,1)
+#define M_SRA(rs1,rs2,rd)              M_SHFT(0x02,0x27,rs1,rs2,rd,REG,0)      /* 32b rd = rs >> rs2 */
+#define M_SRA_IMM(rs1,rs2,rd)  M_SHFT(0x02,0x27,rs1,rs2,rd,IMM,0)
+
+#define M_ISEXT(rs,rd)                         M_SRA_IMM(rs,0,rd)                  /* sign extend 32 bits*/
+
+
+#define M_ADD(rs1,rs2,rd)      M_OP3(0x02,0x00,rd,rs1,rs2,REG)         /* 64b rd = rs1 + rs2 */
+#define M_ADD_IMM(rs1,rs2,rd)   M_OP3(0x02,0x00,rd,rs1,rs2,IMM)
+#define M_SUB(rs1,rs2,rd)       M_OP3(0x02,0x04,rd,rs1,rs2,REG)        /* 64b rd = rs1 - rs2 */
+#define M_SUB_IMM(rs1,rs2,rd)   M_OP3(0x02,0x04,rd,rs1,rs2,IMM)
+#define M_MULX(rs1,rs2,rd)      M_OP3(0x02,0x09,rd,rs1,rs2,REG)        /* 64b rd = rs1 * rs2 */
+#define M_MULX_IMM(rs1,rs2,rd)  M_OP3(0x02,0x09,rd,rs1,rs2,IMM)
+#define M_DIVX(rs1,rs2,rd)      M_OP3(0x02,0x2d,rd,rs1,rs2,REG)        /* 64b rd = rs1 / rs2 */
+
+
+
+/**** compare and conditional ALU operations ***********/
+
+#define M_CMP(rs1,rs2)          M_SUB(rs1,rs2,REG_ZERO)             /* sets xcc and icc   */
+#define M_CMP_IMM(rs1,rs2)      M_SUB_IMM(rs1,rs2,REG_ZERO)
+
+/* move integer register on (64-bit) condition */
+
+#define M_XCMOVEQ(rs,rd)        M_FMT4(0x2,0x2c,rd,rs,0x1,1,1,0,REG)   /* a==b ? rd=rs    */
+#define M_XCMOVNE(rs,rd)        M_FMT4(0x2,0x2c,rd,rs,0x9,1,1,0,REG)   /* a!=b ? rd=rs    */
+#define M_XCMOVLT(rs,rd)        M_FMT4(0x2,0x2c,rd,rs,0x3,1,1,0,REG)   /* a<b  ? rd=rs    */
+#define M_XCMOVGE(rs,rd)        M_FMT4(0x2,0x2c,rd,rs,0xb,1,1,0,REG)   /* a>=b ? rd=rs    */
+#define M_XCMOVLE(rs,rd)        M_FMT4(0x2,0x2c,rd,rs,0x2,1,1,0,REG)   /* a<=b ? rd=rs    */
+#define M_XCMOVGT(rs,rd)        M_FMT4(0x2,0x2c,rd,rs,0xa,1,1,0,REG)   /* a>b  ? rd=rs    */
+
+#define M_XCMOVEQ_IMM(rs,rd)    M_FMT4(0x2,0x2c,rd,rs,0x1,1,1,0,IMM)   /* a==b ? rd=rs    */
+#define M_XCMOVNE_IMM(rs,rd)    M_FMT4(0x2,0x2c,rd,rs,0x9,1,1,0,IMM)   /* a!=b ? rd=rs    */
+#define M_XCMOVLT_IMM(rs,rd)    M_FMT4(0x2,0x2c,rd,rs,0x3,1,1,0,IMM)   /* a<b  ? rd=rs    */
+#define M_XCMOVGE_IMM(rs,rd)    M_FMT4(0x2,0x2c,rd,rs,0xb,1,1,0,IMM)   /* a>=b ? rd=rs    */
+#define M_XCMOVLE_IMM(rs,rd)    M_FMT4(0x2,0x2c,rd,rs,0x2,1,1,0,IMM)   /* a<=b ? rd=rs    */
+#define M_XCMOVGT_IMM(rs,rd)    M_FMT4(0x2,0x2c,rd,rs,0xa,1,1,0,IMM)   /* a>b  ? rd=rs    */
+
+/* move integer register on (fcc0) floating point condition */
+
+#define M_CMOVFGT_IMM(rs,rd)    M_FMT4(0x2,0x2c,rd,rs,0x6,0,0,0,IMM)   /* fa>fb  ? rd=rs  */
+#define M_CMOVFLT_IMM(rs,rd)    M_FMT4(0x2,0x2c,rd,rs,0x4,0,0,0,IMM)   /* fa<fb  ? rd=rs  */
+#define M_CMOVFEQ_IMM(rs,rd)    M_FMT4(0x2,0x2c,rd,rs,0x9,0,0,0,IMM)   /* fa==fb ? rd=rs  */
+
+/* move integer register on (32-bit) condition */
+
+
+
+/* move integer register on register condition */
+
+#define M_CMOVREQ(rs1,rs2,rd) M_OP3C(0x2,0x2f,0x1,rd,rs1,rs2,REG)      /* rs1==0 ? rd=rs2 */
+#define M_CMOVRNE(rs1,rs2,rd) M_OP3C(0x2,0x2f,0x5,rd,rs1,rs2,REG)      /* rs1!=0 ? rd=rs2 */
+#define M_CMOVRLE(rs1,rs2,rd) M_OP3C(0x2,0x2f,0x2,rd,rs1,rs2,REG)      /* rs1<=0 ? rd=rs2 */
+#define M_CMOVRLT(rs1,rs2,rd) M_OP3C(0x2,0x2f,0x3,rd,rs1,rs2,REG)      /* rs1<0  ? rd=rs2 */
+#define M_CMOVRGT(rs1,rs2,rd) M_OP3C(0x2,0x2f,0x6,rd,rs1,rs2,REG)      /* rs1>0  ? rd=rs2 */
+#define M_CMOVRGE(rs1,rs2,rd) M_OP3C(0x2,0x2f,0x7,rd,rs1,rs2,REG)      /* rs1>=0 ? rd=rs2 */
+
+#define M_CMOVREQ_IMM(rs1,rs2,rd) M_OP3C(0x2,0x2f,0x1,rd,rs1,rs2,IMM)  /* rs1==0 ? rd=rs2 */
+#define M_CMOVRNE_IMM(rs1,rs2,rd) M_OP3C(0x2,0x2f,0x5,rd,rs1,rs2,IMM)  /* rs1!=0 ? rd=rs2 */
+#define M_CMOVRLE_IMM(rs1,rs2,rd) M_OP3C(0x2,0x2f,0x2,rd,rs1,rs2,IMM)  /* rs1<=0 ? rd=rs2 */
+#define M_CMOVRLT_IMM(rs1,rs2,rd) M_OP3C(0x2,0x2f,0x3,rd,rs1,rs2,IMM)  /* rs1<0  ? rd=rs2 */
+#define M_CMOVRGT_IMM(rs1,rs2,rd) M_OP3C(0x2,0x2f,0x6,rd,rs1,rs2,IMM)  /* rs1>0  ? rd=rs2 */
+#define M_CMOVRGE_IMM(rs1,rs2,rd) M_OP3C(0x2,0x2f,0x7,rd,rs1,rs2,IMM)  /* rs1>=0 ? rd=rs2 */
+
+
+/**** load/store operations ********/
+
+#define M_SLDU(rd,rs,disp)      M_OP3(0x03,0x02,rd,rs,disp,IMM)        /* 16-bit load, uns*/
+#define M_SLDS(rd,rs,disp)      M_OP3(0x03,0x0a,rd,rs,disp,IMM)        /* 16-bit load, sig*/
+#define M_BLDS(rd,rs,disp)      M_OP3(0x03,0x09,rd,rs,disp,IMM)        /* 8-bit load, sig */
+
+
+#define M_LDX_INTERN(rd,rs,disp) M_OP3(0x03,0x0b,rd,rs,disp,IMM)       /* 64-bit load, sig*/
+#define M_LDX(rd,rs,disp) \
+       do { \
+        s4 lo = (short) (disp); \
+        s4 hi = (short) (((disp) - lo) >> 13); \
+        if (hi == 0) { \
+            M_LDX_INTERN(rd,rs,lo); \
+        } else { \
+            M_SETHI(hi&0x3ffff8,rd); \
+            M_AADD(rs,rd,rd); \
+            M_LDX_INTERN(rd,rd,lo); \
+        } \
+    } while (0)
+
+#define M_ILD_INTERN(rd,rs,disp) M_OP3(0x03,0x08,rd,rs,disp,IMM)       /* 32-bit load, sig */
+#define M_ILD(rd,rs,disp) \
+       do { \
+        s4 lo = (short) (disp); \
+        s4 hi = (short) (((disp) - lo) >> 13); \
+        if (hi == 0) { \
+            M_ILD_INTERN(rd,rs,lo); \
+        } else { \
+            M_SETHI(hi&0x3ffff8,rd); \
+            M_AADD(rs,rd,rd); \
+            M_ILD_INTERN(rd,rd,lo); \
+        } \
+    } while (0)
+
+
+
+#define M_SST(rd,rs,disp)       M_OP3(0x03,0x06,rd,rs,disp,IMM)        /* 16-bit store     */
+#define M_BST(rd,rs,disp)       M_OP3(0x03,0x05,rd,rs,disp,IMM)        /*  8-bit store     */
+
+/* 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_STX_INTERN(rd,rs,disp) M_OP3(0x03,0x0e,rd,rs,disp,IMM)       /* 64-bit store    */
+#define M_STX(rd,rs,disp) \
+       do { \
+        s4 lo = (short) (disp); \
+        s4 hi = (short) (((disp) - lo) >> 13); \
+        if (hi == 0) { \
+            M_STX_INTERN(rd,rs,lo); \
+        } else { \
+            M_SETHI(hi&0x3ffff8,REG_ITMP3); /* sethi has a 22bit imm, only set upper 19 bits */ \
+            M_AADD(rs,REG_ITMP3,REG_ITMP3); \
+            M_STX_INTERN(rd,REG_ITMP3,lo); \
+        } \
+    } while (0)
+
+
+#define M_IST_INTERN(rd,rs,disp) M_OP3(0x03,0x04,rd,rs,disp,IMM)       /* 32-bit store    */
+#define M_IST(rd,rs,disp) \
+    do { \
+        s4 lo = (short) (disp); \
+        s4 hi = (short) (((disp) - lo) >> 13); \
+        if (hi == 0) { \
+            M_IST_INTERN(rd,rs,lo); \
+        } else { \
+            M_SETHI(hi&0x3ffff8,REG_ITMP3); /* sethi has a 22bit imm, only set upper 19 bits */ \
+            M_AADD(rs,REG_ITMP3,REG_ITMP3); \
+            M_IST_INTERN(rd,REG_ITMP3,lo); \
+        } \
+    } while (0)
+
+
+/**** branch operations ********/
+/* XXX prediction and annul bits currently set to defaults, but could be used for optimizations */
+
+/* branch on integer register */
+
+#define M_BEQZ(r,disp)          M_BRAREG(0x0,0x1,r,disp,1,0)          /* br r == 0   */
+#define M_BLEZ(r,disp)          M_BRAREG(0x0,0x2,r,disp,1,0)          /* br r <= 0   */
+#define M_BLTZ(r,disp)          M_BRAREG(0x0,0x3,r,disp,1,0)          /* br r < 0    */
+#define M_BNEZ(r,disp)          M_BRAREG(0x0,0x5,r,disp,1,0)          /* br r != 0   */
+#define M_BGTZ(r,disp)          M_BRAREG(0x0,0x6,r,disp,1,0)          /* br r > 0    */
+#define M_BGEZ(r,disp)          M_BRAREG(0x0,0x7,r,disp,1,0)          /* br r >= 0   */
+
+
+/* branch on (64-bit) integer condition codes */
+
+#define M_XBEQ(disp)            M_BRACC(0x00,0x1,0x1,disp,2,1,0)      /* branch a==b */
+#define M_XBNEQ(disp)           M_BRACC(0x00,0x1,0x9,disp,2,1,0)      /* branch a!=b */
+#define M_XBGT(disp)            M_BRACC(0x00,0x1,0xa,disp,2,1,0)      /* branch a>b  */
+#define M_XBLT(disp)            M_BRACC(0x00,0x1,0x3,disp,2,1,0)      /* branch a<b  */
+#define M_XBGE(disp)            M_BRACC(0x00,0x1,0xb,disp,2,1,0)      /* branch a>=b */
+#define M_XBLE(disp)            M_BRACC(0x00,0x1,0x2,disp,2,1,0)      /* branch a<=b */
+#define M_XBUGE(disp)           M_BRACC(0x00,0x1,0xd,disp,2,1,0)      /* br uns a>=b */
+
+/* branch on (32-bit) integer condition codes */
+
+#define M_BR(disp)              M_BRACC(0x00,0x1,0x8,disp,0,1,0)      /* branch      */
+#define M_BEQ(disp)             M_BRACC(0x00,0x1,0x1,disp,0,1,0)      /* branch a==b */
+#define M_BNEQ(disp)            M_BRACC(0x00,0x1,0x9,disp,0,1,0)      /* branch a!=b */
+#define M_BGT(disp)             M_BRACC(0x00,0x1,0xa,disp,0,1,0)      /* branch a>b  */
+#define M_BLT(disp)             M_BRACC(0x00,0x1,0x3,disp,0,1,0)      /* branch a<b  */
+#define M_BGE(disp)             M_BRACC(0x00,0x1,0xb,disp,0,1,0)      /* branch a>=b */
+#define M_BLE(disp)             M_BRACC(0x00,0x1,0x2,disp,0,1,0)      /* branch a<=b */
+
+
+
+
+
+
+
+#define M_JMP(rd,rs1,rs2)       M_OP3(0x02,0x38,rd, rs1,rs2,REG)  /* jump to rs1+rs2, adr of instr. saved to rd */
+#define M_JMP_IMM(rd,rs1,rs2)   M_OP3(0x02,0x38,rd, rs1,rs2,IMM)
+#define M_RET(rs)                              M_OP3(0x02,0x38,REG_ZERO,rs,REG_ZERO,REG)
+
+#define M_RETURN(rs)            M_OP3(0x02,0x39,0,rs,REG_ZERO,REG) /* like ret, does window restore */
+/**** floating point operations **/
+
+
+#define M_DMOV(rs,rd)           M_FOP3(0x02,0x34,0x02,rd,0,rs)      /* rd = rs */
+#define M_FMOV(rs,rd)           M_FOP3(0x02,0x34,0x01,rd*2,0,rs*2)  /* rd = rs */
+
+#define M_FNEG(rs,rd)                  M_FOP3(0x02,0x34,0x05,rd,0,rs)          /* rd = -rs     */
+#define M_DNEG(rs,rd)                  M_FOP3(0x02,0x34,0x06,rd,0,rs)          /* rd = -rs     */
+
+#define M_FADD(rs1,rs2,rd)      M_FOP3(0x02,0x34,0x41,rd,rs1,rs2)  /* float add    */
+#define M_DADD(rs1,rs2,rd)      M_FOP3(0x02,0x34,0x42,rd,rs1,rs2)  /* double add   */
+#define M_FSUB(rs1,rs2,rd)      M_FOP3(0x02,0x34,0x045,rd,rs1,rs2)     /* float sub    */
+#define M_DSUB(rs1,rs2,rd)      M_FOP3(0x02,0x34,0x046,rd,rs1,rs2) /* double sub   */
+#define M_FMUL(rs1,rs2,rd)      M_FOP3(0x02,0x34,0x049,rd,rs1,rs2) /* float mul    */
+#define M_DMUL(rs1,rs2,rd)      M_FOP3(0x02,0x34,0x04a,rd,rs1,rs2) /* double mul   */
+#define M_FDIV(rs1,rs2,rd)      M_FOP3(0x02,0x34,0x04d,rd,rs1,rs2) /* float div    */
+#define M_DDIV(rs1,rs2,rd)      M_FOP3(0x02,0x34,0x04e,rd,rs1,rs2) /* double div   */
+
+
+/**** compare and conditional FPU operations ***********/
+
+/* rd field 0 ==> fcc target unit is fcc0 */
+#define M_FCMP(rs1,rs2)                    M_FOP3(0x02,0x35,0x051,0,rs1*2,rs2*2) /* set fcc flt  */
+#define M_DCMP(rs1,rs2)                    M_FOP3(0x02,0x35,0x052,0,rs1,rs2)     /* set fcc dbl  */
+
+/* conversion functions */
+
+#define M_CVTIF(rs,rd)          M_FOP3(0x02,0x34,0x0c4,rd*2,0,rs*2)/* int2flt      */
+#define M_CVTID(rs,rd)          M_FOP3(0x02,0x34,0x0c8,rd,0,rs*2)  /* int2dbl      */
+#define M_CVTLF(rs,rd)          M_FOP3(0x02,0x34,0x084,rd*2,0,rs)  /* long2flt     */
+#define M_CVTLD(rs,rd)          M_FOP3(0x02,0x34,0x088,rd,0,rs)    /* long2dbl     */
+
+#define M_CVTFI(rs,rd)          M_FOP3(0x02,0x34,0x0d1,rd*2,0,rs*2)   /* flt2int   */
+#define M_CVTDI(rs,rd)          M_FOP3(0x02,0x34,0x0d2,rd*2,0,rs)     /* dbl2int   */
+#define M_CVTFL(rs,rd)          M_FOP3(0x02,0x34,0x081,rd,0,rs*2)     /* flt2long  */
+#define M_CVTDL(rs,rd)          M_FOP3(0x02,0x34,0x082,rd,0,rs)       /* dbl2long  */
+
+#define M_CVTFD(rs,rd)          M_FOP3(0x02,0x34,0x0c9,rd,0,rs*2)     /* flt2dbl   */
+#define M_CVTDF(rs,rd)          M_FOP3(0x02,0x34,0x0c6,rd*2,0,rs)     /* dbl2float */
+
+
+/* translate logical double register index to float index. (e.g. %d1 -> %f2, %d2 -> %f4, etc.) */
+/* we don't have to pack the 6-bit register number, since we are not using the upper 16 doubles */
+/* floats reside in lower register of a double pair, use same translation as above */
+#define M_DLD_INTERN(rd,rs1,disp) M_OP3(0x03,0x23,rd*2,rs1,disp,IMM)    /* double (64-bit) load */
+#define M_DLD(rd,rs,disp) \
+       do { \
+        s4 lo = (short) (disp); \
+        s4 hi = (short) (((disp) - lo) >> 13); \
+        if (hi == 0) { \
+            M_DLD_INTERN(rd,rs,lo); \
+        } else { \
+            M_SETHI(hi&0x3ffff8,rd); \
+            M_AADD(rs,rd,rd); \
+            M_DLD_INTERN(rd,rd,lo); \
+        } \
+    } while (0)
+/* Note for SETHI: sethi has a 22bit imm, only set upper 19 bits */ 
+
+#define M_FLD_INTERN(rd,rs1,disp) M_OP3(0x03,0x20,rd*2,rs1,disp,IMM)    /* float (32-bit) load */
+#define M_FLD(rd,rs,disp) \
+       do { \
+        s4 lo = (short) (disp); \
+        s4 hi = (short) (((disp) - lo) >> 13); \
+        if (hi == 0) { \
+            M_FLD_INTERN(rd,rs,lo); \
+        } else { \
+            M_SETHI(hi&0x3ffff8,rd); \
+            M_AADD(rs,rd,rd); \
+            M_FLD_INTERN(rd,rd,lo); \
+        } \
+    } while (0)
+
+
+#define M_FST_INTERN(rd,rs,disp) M_OP3(0x03,0x24,rd*2,rs,disp,IMM)    /* float (32-bit) store  */
+#define M_FST(rd,rs,disp) \
+    do { \
+        s4 lo = (short) (disp); \
+        s4 hi = (short) (((disp) - lo) >> 13); \
+        if (hi == 0) { \
+            M_FST_INTERN(rd,rs,lo); \
+        } else { \
+            M_SETHI(hi&0x3ffff8,REG_ITMP3); \
+            M_AADD(rs,REG_ITMP3,REG_ITMP3); \
+            M_FST_INTERN(rd,REG_ITMP3,lo); \
+        } \
+    } while (0)
+    
+
+#define M_DST_INTERN(rd,rs1,disp) M_OP3(0x03,0x27,rd,rs1,disp,IMM)    /* double (64-bit) store */
+#define M_DST(rd,rs,disp) \
+    do { \
+        s4 lo = (short) (disp); \
+        s4 hi = (short) (((disp) - lo) >> 13); \
+        if (hi == 0) { \
+            M_DST_INTERN(rd,rs,lo); \
+        } else { \
+            M_SETHI(hi&0x3ffff8,REG_ITMP3); \
+            M_AADD(rs,REG_ITMP3,REG_ITMP3); \
+            M_DST_INTERN(rd,REG_ITMP3,lo); \
+        } \
+    } while (0)
+    
+    
+    
+/*
+ * Address pseudo instruction
+ */
+
+#define POINTERSHIFT 3 /* x8 */
+
+
+#define M_ALD_INTERN(a,b,disp)  M_LDX_INTERN(a,b,disp)
+#define M_ALD(a,b,disp)         M_LDX(a,b,disp)
+#define M_AST_INTERN(a,b,disp)  M_STX_INTERN(a,b,disp)
+#define M_AST(a,b,disp)         M_STX(a,b,disp)
+#define M_AADD(a,b,c)           M_ADD(a,b,c)
+#define M_AADD_IMM(a,b,c)       M_ADD_IMM(a,b,c)
+#define M_ASUB_IMM(a,b,c)       M_SUB_IMM(a,b,c)
+#define M_ASLL_IMM(a,b,c)       M_SLLX_IMM(a,b,c)
+
+
+
+
+/* var_to_reg_xxx **************************************************************
+
+   This function generates code to fetch data from a pseudo-register
+   into a real register. If the pseudo-register has actually been
+   assigned to a real register, no code will be emitted, since
+   following operations can use this register directly.
+    
+   v: pseudoregister to be fetched from
+   tempregnum: temporary register to be used if v is actually spilled to ram
+
+   return: the register number, where the operand can be found after 
+           fetching (this wil be either tempregnum or the register
+           number allready given to v)
+
+*******************************************************************************/
+
+#define var_to_reg_int(regnr,v,tempnr) \
+    do { \
+        if ((v)->flags & INMEMORY) { \
+            COUNT_SPILLS; \
+            M_LDX(tempnr, REG_SP, (v)->regoff * 8); \
+            regnr = tempnr; \
+        } else { \
+            regnr = (v)->regoff; \
+        } \
+    } while (0)
+                                                                                                                                 
+
+/* gen_resolvebranch ***********************************************************
+ *
+ *    backpatches a branch instruction
+ *    On Sparc all there is to do, is replace the 22bit disp at the end of the 
+ *    instruction.
+ *    THIS APPLIES TO THE (V8) BICC INSTRUCTION ONLY.
+ *
+ *    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) (to) - (so)) >> 2 & 0x1fffff
+
+
+
+                                                                                                                                 
+       
+#endif /* _CODEGEN_H */
diff --git a/src/vm/jit/sparc64/disass.c b/src/vm/jit/sparc64/disass.c
new file mode 100644 (file)
index 0000000..3838e9d
--- /dev/null
@@ -0,0 +1,142 @@
+/* src/vm/jit/i386/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
+            Christian Thalinger
+            Alexander Jordan
+
+   Changes:      
+
+   $Id: disass.c 4357 2006-01-22 23:33:38Z twisti $
+
+*/
+
+
+#include "config.h"
+
+#include <assert.h>
+#include <dis-asm.h>
+#include <stdarg.h>
+
+#include "vm/types.h"
+
+#include "vm/global.h"
+#include "vm/jit/disass.h"
+
+char *regs[] = {
+       "g0",
+       "g1",
+       "g2",
+       "g3",
+       "g4",
+       "g5",
+       "g6",
+       "g7",
+       "o0",
+       "o1",
+       "o2",
+       "o3",
+       "o4",
+       "o5",
+       "o6",
+       "o7",
+       "l0",
+       "l1",
+       "l2",
+       "l3",
+       "l4",
+       "l5",
+       "l6",
+       "l7",
+       "l0",
+       "i1",
+       "i2",
+       "i3",
+       "i4",
+       "i5",
+       "i6",
+       "i7"
+};
+
+/* disassinstr *****************************************************************
+
+   Outputs a disassembler listing of one machine code instruction on
+   'stdout'.
+
+   code: instructions machine code
+
+*******************************************************************************/
+
+u1 *disassinstr(u1 *code)
+{
+       s4 seqlen;
+       s4 i;
+
+       if (!disass_initialized) {
+               INIT_DISASSEMBLE_INFO(info, NULL, disass_printf);
+
+               /* setting the struct members must be done after
+                  INIT_DISASSEMBLE_INFO */
+
+               info.mach             = bfd_mach_sparc_v9;
+               info.read_memory_func = &disass_buffer_read_memory;
+
+               disass_initialized = 1;
+       }
+
+       printf("0x%08x:   ", (s4) code);
+
+       /* disass_len = 0; */
+
+       seqlen = print_insn_sparc((bfd_vma) code, &info);
+
+       for (i = 0; i < seqlen; i++, code++) {
+               printf("%02x ", *code);
+       }
+
+       for (; i < 8; i++) {
+               printf("   ");
+       }
+
+       /* printf("   %s\n", disass_buf); */
+
+       return code;
+}
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
diff --git a/src/vm/jit/sparc64/emit.c b/src/vm/jit/sparc64/emit.c
new file mode 100644 (file)
index 0000000..563a4d4
--- /dev/null
@@ -0,0 +1,219 @@
+/* src/vm/jit/sparc64/emit.c - Sparc 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
+            Alexander Jordan
+
+   Changes: 
+
+   $Id: emitfuncs.c 4398 2006-01-31 23:43:08Z twisti $
+
+*/
+
+#include "vm/types.h"
+
+#include "md-abi.h"
+
+#include "vm/jit/jit.h"
+#include "vm/jit/sparc64/codegen.h"
+#include "vm/jit/sparc64/emit.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            reg;
+
+       /* get required compiler data */
+
+       cd = jd->cd;
+
+       if (src->flags & INMEMORY) {
+               COUNT_SPILLS;
+
+               if (IS_FLT_DBL_TYPE(src->type))
+                       M_LDDF(REG_SP, src->regoff * 8, tempreg);
+               else
+                       M_LDX(REG_SP, src->regoff * 8, tempreg);
+
+               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            reg;
+
+       /* get required compiler data */
+
+       cd = jd->cd;
+
+       if (src->flags & INMEMORY) {
+               COUNT_SPILLS;
+
+               if (IS_FLT_DBL_TYPE(src->type))
+                       M_LDDF(REG_SP, src->regoff * 8, tempreg);
+               else
+                       M_LDX(REG_SP, src->regoff * 8, tempreg);
+
+               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            reg;
+
+       /* get required compiler data */
+
+       cd = jd->cd;
+
+       if (src->flags & INMEMORY) {
+               COUNT_SPILLS;
+
+               if (IS_FLT_DBL_TYPE(src->type))
+                       M_LDDF(REG_SP, src->regoff * 8, tempreg);
+               else
+                       M_LDX(REG_SP, src->regoff * 8, tempreg);
+
+               reg = tempreg;
+       } else
+               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))
+                       M_STDF(d, REG_SP, dst->regoff * 8);
+               else
+                       M_STX(d, REG_SP, dst->regoff * 8);
+       }
+}
+
+
+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;
+
+       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 (IS_FLT_DBL_TYPE(src->type)) {
+                       /* always move doubles for now */
+                       M_DBLMOVE(s1, d);
+               }
+               else
+                       M_INTMOVE(s1, d);
+
+               emit_store(jd, iptr, dst, d);
+       }
+}
+
+
+void emit_iconst(codegendata *cd, s4 d, s4 value)
+{
+       s4 disp;
+
+       if ((value >= -4096) && (value <= 4095)) {
+               M_IOR(REG_ZERO, value, d, IMM);
+       } 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/sparc64/linux/.cvsignore b/src/vm/jit/sparc64/linux/.cvsignore
new file mode 100644 (file)
index 0000000..1f83cf9
--- /dev/null
@@ -0,0 +1,10 @@
+*.a
+*.o
+*.la
+*.lo
+.deps
+.libs
+Makefile
+Makefile.in
+TAGS
+offsets.h
diff --git a/src/vm/jit/sparc64/linux/Makefile.am b/src/vm/jit/sparc64/linux/Makefile.am
new file mode 100644 (file)
index 0000000..bb1941c
--- /dev/null
@@ -0,0 +1,53 @@
+## src/vm/jit/alpha/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 4563 2006-03-06 13:03:05Z twisti $
+
+## 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 =
+
+noinst_LTLIBRARIES = libmd.la
+
+libmd_la_SOURCES = \
+       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/sparc64/linux/md-os.c b/src/vm/jit/sparc64/linux/md-os.c
new file mode 100644 (file)
index 0000000..a3f10a0
--- /dev/null
@@ -0,0 +1,125 @@
+/* src/vm/jit/alpha/linux/md.c - machine dependent Alpha 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 4357 2006-01-22 23:33:38Z twisti $
+
+*/
+
+#include "config.h"
+
+#include <assert.h>
+#include <ucontext.h>
+
+#include "vm/types.h"
+
+#include "vm/jit/sparc64/md-abi.h"
+
+#include "vm/exceptions.h"
+#include "vm/signallocal.h"
+#include "vm/stringlocal.h"
+#include "vm/jit/asmpart.h"
+#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)
+{
+       ucontext_t  *_uc;
+       mcontext_t  *_mc;
+       u4           instr;
+       ptrint       addr;
+       u1          *pv;
+       u1          *sp;
+       u1          *ra;
+       u1          *xpc;
+
+       _uc = (ucontext_t *) _p;
+       _mc = &_uc->uc_mcontext;
+
+       instr = *((s4 *) (_mc->mc_gregs[MC_PC]));
+       /*addr = _mc->sc_regs[(instr >> 16) & 0x1f];*/
+       addr = 0;
+
+       if (addr == 0) {
+               pv  = (u1 *) _mc->mc_gregs[MC_G2];
+               sp  = (u1 *) _mc->mc_fp;
+               ra  = (u1 *) _mc->mc_i7;       /* this is correct for leafs */
+               xpc = (u1 *) _mc->mc_gregs[MC_PC];
+
+               _mc->mc_gregs[MC_G4] =
+                       (ptrint) stacktrace_hardware_nullpointerexception(pv, sp, ra, xpc);
+
+               _mc->mc_gregs[MC_G5] = (ptrint) xpc;
+               _mc->mc_gregs[MC_PC] = (ptrint) asm_handle_exception;
+
+       } else {
+               addr += (long) ((instr << 16) >> 16);
+
+               throw_cacao_exception_exit(string_java_lang_InternalError,
+                                                                  "Segmentation fault: 0x%016lx at 0x%016lx\n",
+                                                                  addr, _mc->mc_gregs[MC_PC]);
+       }
+}
+
+
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+void thread_restartcriticalsection(ucontext_t *_uc)
+{
+       mcontext_t *_mc;
+       void       *critical;
+
+       _mc = &_uc->uc_mcontext;
+
+       critical = thread_checkcritical((void *) _mc->sc_pc);
+
+       if (critical)
+               _mc->sc_pc = (ptrint) critical;
+}
+#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/sparc64/machine-instr.h b/src/vm/jit/sparc64/machine-instr.h
new file mode 100644 (file)
index 0000000..c989a2a
--- /dev/null
@@ -0,0 +1,42 @@
+#ifndef _MACHINE_INSTR_H
+#define _MACHINE_INSTR_H
+/*
+static inline void
+__attribute__ ((unused))
+atomic_add (volatile int *mem, int val)
+{
+    int temp;
+
+  __asm__ __volatile__ (
+    "1:\t"
+    "ldl_l  %1,%3\n\t"
+    "addl   %1,%2,%1\n\t"
+    "stl_c  %1,%0\n\t"
+    "beq    %1,1b\n\t"
+    : "=m"(*mem), "=&r"(temp)
+    : "r"(val), "m"(*mem));
+}
+*/
+
+static inline long
+__attribute__ ((unused))
+compare_and_swap (volatile long *p, long oldval, long newval)
+{
+  long ret;
+
+  __asm__ __volatile__ (
+    "mov %3,%0\n\t"
+    "casx %1,%2,%0\n\t"
+    : "=&r"(ret), "=m"(*p) 
+    : "r"(oldval), "r"(newval), "m"(*p));
+
+  return ret;
+}
+
+#define STORE_ORDER_BARRIER() __asm__ __volatile__ ("wmb" : : : "memory");
+#define MEMORY_BARRIER_BEFORE_ATOMIC() __asm__ __volatile__ ("mb" : : : "memory");
+#define MEMORY_BARRIER_AFTER_ATOMIC() __asm__ __volatile__ ("mb" : : : "memory");
+#define MEMORY_BARRIER() __asm__ __volatile__ ( \
+               "mb" : : : "memory" );
+
+#endif
diff --git a/src/vm/jit/sparc64/md-abi.c b/src/vm/jit/sparc64/md-abi.c
new file mode 100644 (file)
index 0000000..092dc9f
--- /dev/null
@@ -0,0 +1,156 @@
+
+#include "config.h"
+#include "vm/types.h"
+
+#include "vm/jit/sparc64/md-abi.h"
+
+#include "vm/descriptor.h"
+#include "vm/global.h"
+
+
+/* register descripton array **************************************************/
+
+/* callee point-of-view, after SAVE has been called */
+s4 nregdescint[] = {
+       /* zero  itmp1/g1 itmp2/g2 itmp3/g3 temp/g4  temp/g5  sys/g6   sys/g7 */  
+       REG_RES, REG_RES, REG_RES, REG_RES, REG_TMP, REG_TMP, REG_RES, REG_RES,
+       
+       /* o0    o1       o2       o3       o4       o5       sp/o6    o7     */
+       REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_RES, REG_TMP,
+       
+       /* l0    l1       l2       l3       l4       l5       l6       l7     */
+       REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
+       
+       /* i0    i1       i2       i3       i4       pv/i5    fp/i6    ra/i7  */
+       REG_RET, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_RES, REG_RES, REG_RES,
+       REG_END
+       
+       /* XXX i1 - i4: SAV OR ARG ??? */
+};
+
+s4 nregdescfloat[] = {
+       REG_RET, REG_RES, REG_RES, REG_RES, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
+       REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
+       REG_END
+};
+
+
+/* md_param_alloc **************************************************************
+
+   XXX
+
+*******************************************************************************/
+
+void md_param_alloc(methoddesc *md)
+{
+       paramdesc *pd;
+       s4         i;
+       s4         reguse;
+       s4         stacksize;
+
+       /* set default values */
+
+       reguse = 0;
+       stacksize = 0;
+
+       /* get params field of methoddesc */
+
+       pd = md->params;
+
+       for (i = 0; i < md->paramcount; i++, pd++) {
+               switch (md->paramtypes[i].type) {
+               case TYPE_INT:
+               case TYPE_ADR:
+               case TYPE_LNG:
+                       if (i < INT_ARG_CNT) {
+                               pd->inmemory = false;
+                               pd->regoff = reguse;
+                               reguse++;
+                               md->argintreguse = reguse;
+
+                       } else {
+                               pd->inmemory = true;
+                               pd->regoff = stacksize;
+                               stacksize++;
+                       }
+                       break;
+               case TYPE_FLT:
+               case TYPE_DBL:
+                       if (i < FLT_ARG_CNT) {
+                               pd->inmemory = false;
+                               pd->regoff = reguse;
+                               reguse++;
+                               md->argfltreguse = reguse;
+                       } else {
+                               pd->inmemory = true;
+                               pd->regoff = stacksize;
+                               stacksize++;
+                       }
+                       break;
+               }
+       }
+
+       /* fill register and stack usage */
+
+       md->memuse = stacksize;
+}
+
+
+/* md_return_alloc *************************************************************
+
+   Precolor the Java Stackelement containing the Return Value. Since
+   alpha has a dedicated return register (not an reused arg or
+   reserved reg), this is striaghtforward possible, as long, as this
+   stackelement does not have to survive a method invokation
+   (SAVEDVAR)
+
+   --- 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_FRESULT]
+
+*******************************************************************************/
+
+void md_return_alloc(methodinfo *m, registerdata *rd, s4 return_type,
+                                        stackptr stackslot)
+{
+       /* Only precolor the stackslot, if it is not used for parameter precoloring AND */
+       /* it is not a SAVEDVAR <-> has not to survive method invokations */
+
+       if (!m->isleafmethod || (m->parseddesc->paramcount == 0)) {
+
+               if (!(stackslot->flags & SAVEDVAR)) {
+                       stackslot->varkind = ARGVAR;
+                       stackslot->varnum = -1;
+                       stackslot->flags = 0;
+
+                       if (IS_INT_LNG_TYPE(return_type)) {
+                               stackslot->regoff = REG_RESULT_CALLEE;
+                       } else { /* float/double */
+                               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:
+ */
diff --git a/src/vm/jit/sparc64/md-abi.h b/src/vm/jit/sparc64/md-abi.h
new file mode 100644 (file)
index 0000000..b26d1c4
--- /dev/null
@@ -0,0 +1,111 @@
+/* src/vm/jit/sparc64/md-abi.h - defines for Sparc 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: Alexander Jordan
+
+   Changes:
+
+   $Id: md-abi.h 4357 2006-01-22 23:33:38Z twisti $
+
+*/
+
+#ifndef _MD_ABI_H
+#define _MD_ABI_H
+
+/* preallocated registers *****************************************************/
+
+/* integer registers */
+  
+#define REG_RESULT_CALLEE      24   /* to deliver method results                                 */
+#define REG_RESULT_CALLER       8   /* to read method results                    */
+
+#define REG_RA_CALLEE          26   /* callee reads return address here          */
+#define REG_RA_CALLER          15   /* caller puts address of call instr here    */
+
+#define REG_PV_CALLEE                  29   /* procedure vector, as found by callee      */
+#define REG_PV_CALLER          13   /* caller provides PV here */
+
+
+#define REG_METHODPTR    4   /* pointer to the place from where the procedure */
+                             /* vector has been fetched         */
+                             
+                             
+#define REG_ITMP1        1   /* temporary register (scratch)                  */
+#define REG_ITMP2        2   /* temporary register (application)              */
+#define REG_ITMP3        3   /* temporary register (application)              */
+
+#define REG_ITMP2_XPTR   2   /* exception pointer = temporary register 2      */
+#define REG_ITMP3_XPC    3   /* exception pc = temporary register 3           */
+
+#define REG_SP          14   /* stack pointer                                 */
+#define REG_FP          30   /* frame pointer                                 */
+#define REG_ZERO         0   /* always zero                                   */
+
+/* floating point registers */
+/* only using the lower half of the floating registers for now */
+
+
+#define REG_FRESULT      0   /* to deliver floating point method results      */
+
+#define REG_FTMP1        1   /* temporary floating point register             */
+#define REG_FTMP2        2   /* temporary floating point register             */
+#define REG_FTMP3        3   /* temporary floating point register             */
+
+#define REG_IFTMP        1   /* temporary integer and floating point register */
+
+
+#define INT_REG_CNT     32   /* number of integer registers                   */
+#define INT_SAV_CNT     16   /* number of int callee saved registers          */
+#define INT_ARG_CNT      5   /* number of int argument registers (-1 for PV)  */
+#define INT_TMP_CNT      5   /* int temp registers (%g1-%g5)                  */
+#define INT_RES_CNT      6   /* number of reserved integer registers          */
+                             /* pv, zero, %g6, %g7, sp, ra                    */
+
+#define FLT_REG_CNT     16   /* number of float registers                     */
+#define FLT_SAV_CNT      4   /* number of flt callee saved registers          */
+#define FLT_ARG_CNT      4   /* number of flt argument registers              */
+#define FLT_TMP_CNT      4   /* number of flt temp registers                  */
+#define FLT_RES_CNT      3   /* number of reserved float registers            */
+                             /* the one "missing" register is the return reg  */
+
+/* #define TRACE_ARGS_NUM   5 */
+
+#endif /* _MD_ABI_H */
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
diff --git a/src/vm/jit/sparc64/md-asm.h b/src/vm/jit/sparc64/md-asm.h
new file mode 100644 (file)
index 0000000..e488b76
--- /dev/null
@@ -0,0 +1,65 @@
+/* src/vm/jit/sparc64/md-asm.h - assembler defines for Sparc 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
+            Alexander Jordan
+
+   Changes:
+
+   $Id: md-asm.h 4498 2006-02-12 23:43:09Z twisti $
+
+*/
+
+#ifndef _MD_ASM_H
+#define _MD_ASM_H
+
+
+/* register defines
+ * ***********************************************************/
+
+#define zero   %g0
+#define itmp1  %g1
+#define itmp2  %g2
+#define itmp3  %g3
+
+
+#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/sparc64/md.c b/src/vm/jit/sparc64/md.c
new file mode 100644 (file)
index 0000000..e912e7e
--- /dev/null
@@ -0,0 +1,165 @@
+
+#include "config.h"
+
+#include "vm/types.h"
+
+#include "vm/jit/sparc64/md-abi.h"
+
+#include "vm/exceptions.h"
+#include "vm/stringlocal.h"
+#include "vm/jit/asmpart.h"
+#include "vm/jit/stacktrace.h"
+
+
+/* md_init *********************************************************************
+
+   Do some machine dependent initialization.
+
+*******************************************************************************/
+
+void md_init(void)
+{
+       /* do nothing */
+}
+
+
+/* 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)
+{
+       /* where's it gonna be ? */
+
+       return 0;
+}
+
+
+/* md_codegen_findmethod *******************************************************
+
+
+   This reconstructs and returns the PV of a method given a return address
+   pointer. (basically, same was as the generated code following the jump does)
+   
+   Machine code:
+
+   6b5b4000    jsr     (pv)
+   277afffe    ldah    pv,-2(ra)
+   237ba61c    lda     pv,-23012(pv)
+
+*******************************************************************************/
+
+u1 *md_codegen_findmethod(u1 *ra)
+{
+       u1 *pv;
+       u4  mcode;
+       s4  offset;
+
+       pv = ra;
+
+       /* get first instruction word after jump */
+
+       mcode = *((u4 *) ra);
+
+       /* check if we have 2 instructions (ldah, lda) */
+
+       if ((mcode >> 16) == 0x277a) {
+               /* get displacement of first instruction (ldah) */
+
+               offset = (s4) (mcode << 16);
+               pv += offset;
+
+               /* get displacement of second instruction (lda) */
+
+               mcode = *((u4 *) (ra + 1 * 4));
+
+               assert((mcode >> 16) == 0x237b);
+
+               offset = (s2) (mcode & 0x0000ffff);
+               pv += offset;
+
+       } else {
+               /* get displacement of first instruction (lda) */
+
+               assert((mcode >> 16) == 0x237a);
+
+               offset = (s2) (mcode & 0x0000ffff);
+               pv += offset;
+       }
+
+       return pv;
+}
+
+
+/* md_cacheflush ***************************************************************
+
+   Calls the system's function to flush the instruction and data
+   cache.
+
+*******************************************************************************/
+
+void md_cacheflush(u1 *addr, s4 nbytes)
+{
+       /* don't know yet */    
+}
+
+
+/* md_icacheflush **************************************************************
+
+   Calls the system's function to flush the instruction cache.
+
+*******************************************************************************/
+
+void md_icacheflush(u1 *addr, s4 nbytes)
+{
+       /* don't know yet */    
+}
+
+
+/* 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:
+ */