Logo Search packages:      
Sourcecode: cacao-source version File versions  Download package

codegen.c

/* src/vm/jit/intrp/codegen.c - code generator for Interpreter

   Copyright (C) 1996-2005, 2006, 2007, 2008
   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO

   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.

*/


#include "config.h"

#include <assert.h>
#include <stdio.h>

#if defined(WITH_FFI)
# include <ffi.h>
#elif defined(WITH_FFCALL)
# include <avcall.h>
#else
# error neither WITH_FFI nor WITH_FFCALL defined
#endif

#include "vm/types.h"

#include "arch.h"

#include "vm/jit/intrp/codegen.h"
#include "vm/jit/intrp/intrp.h"

#include "mm/memory.h"

#include "native/native.h"

#include "vm/builtin.h"
#include "vm/exceptions.h"
#include "vm/global.h"
#include "vm/stringlocal.h"
#include "vm/vm.h"

#include "vm/jit/asmpart.h"
#include "vm/jit/codegen-common.h"
#include "vm/jit/dseg.h"
#include "vm/jit/jit.h"
#include "vm/jit/parse.h"
#include "vm/jit/patcher.h"
#include "vm/jit/stack.h"
#include "vm/jit/stacktrace.h"

#include "vmcore/class.h"
#include "vmcore/options.h"


#define gen_branch(_inst) { \
  gen_##_inst(cd, 0); \
  codegen_addreference(cd, BLOCK_OF(iptr->dst.insindex)); \
}

#define index2offset(_i) (-(_i) * SIZEOF_VOID_P)

/* functions used by cacao-gen.i */

void genarg_v(codegendata *cd1, Cell v)
{
      Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
      *((Cell *) *mcodepp) = v;
      (*mcodepp)++;
}

void genarg_i(codegendata *cd1, s4 i)
{
      Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
      *((Cell *) *mcodepp) = i;
      (*mcodepp)++;
}

void genarg_b(codegendata *cd1, s4 i)
{
  genarg_i(cd1, i);
}

void genarg_f(codegendata *cd1, float f)
{
      s4 fi;

      vm_f2Cell(f,fi);
      genarg_i(cd1, fi);
}

void genarg_l(codegendata *cd1, s8 l)
{
      Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
      vm_l2twoCell(l, ((Cell *) *mcodepp)[1], ((Cell *) *mcodepp)[0]);
      (*mcodepp) +=2;
}

void genarg_aRef(codegendata *cd1, java_objectheader *a)
{
      Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
      *((java_objectheader **) *mcodepp) = a;
      (*mcodepp)++;
}

void genarg_aArray(codegendata *cd1, java_arrayheader *a)
{
      Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
      *((java_arrayheader **) *mcodepp) = a;
      (*mcodepp)++;
}

void genarg_aaTarget(codegendata *cd1, Inst **a)
{
      Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
      *((Inst ***) *mcodepp) = a;
      (*mcodepp)++;
}

void genarg_aClass(codegendata *cd1, classinfo *a)
{
      Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
      *((classinfo **) *mcodepp) = a;
      (*mcodepp)++;
}

void genarg_acr(codegendata *cd1, constant_classref *a)
{
      Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
      *((constant_classref **) *mcodepp) = a;
      (*mcodepp)++;
}

void genarg_addr(codegendata *cd1, u1 *a)
{
      Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
      *((u1 **) *mcodepp) = a;
      (*mcodepp)++;
}

void genarg_af(codegendata *cd1, functionptr a)
{
      Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
      *((functionptr *) *mcodepp) = a;
      (*mcodepp)++;
}

void genarg_afi(codegendata *cd1, fieldinfo *a)
{
      Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
      *((fieldinfo **) *mcodepp) = a;
      (*mcodepp)++;
}

void genarg_am(codegendata *cd1, methodinfo *a)
{
      Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
      *((methodinfo **) *mcodepp) = a;
      (*mcodepp)++;
}

void genarg_acell(codegendata *cd1, Cell *a)
{
      Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
      *((Cell **) *mcodepp) = a;
      (*mcodepp)++;
}

void genarg_ainst(codegendata *cd1, Inst *a)
{
      Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
      *((Inst **) *mcodepp) = a;
      (*mcodepp)++;
}

void genarg_auf(codegendata *cd1, unresolved_field *a)
{
      Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
      *((unresolved_field **) *mcodepp) = a;
      (*mcodepp)++;
}

void genarg_aum(codegendata *cd1, unresolved_method *a)
{
      Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
      *((unresolved_method **) *mcodepp) = a;
      (*mcodepp)++;
}

void genarg_avftbl(codegendata *cd1, vftbl_t *a)
{
      Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
      *((vftbl_t **) *mcodepp) = a;
      (*mcodepp)++;
}


/* include the interpreter generation functions *******************************/

/* Do not use "java-gen.i", it does not work with builddir. */
#include <java-gen.i>


typedef void (*genfunctionptr) (codegendata *);

typedef struct builtin_gen builtin_gen;

00221 struct builtin_gen {
      functionptr builtin;
      genfunctionptr gen;
};

struct builtin_gen builtin_gen_table[] = {
    {BUILTIN_new,                     gen_NEW,             }, 
    {BUILTIN_newarray,                gen_NEWARRAY,        },
    {BUILTIN_newarray_boolean,        gen_NEWARRAY_BOOLEAN,},
    {BUILTIN_newarray_byte,           gen_NEWARRAY_BYTE,   },
    {BUILTIN_newarray_char,           gen_NEWARRAY_CHAR,   },
    {BUILTIN_newarray_short,          gen_NEWARRAY_SHORT,  },    
    {BUILTIN_newarray_int,            gen_NEWARRAY_INT,    },
    {BUILTIN_newarray_long,           gen_NEWARRAY_LONG,   },
    {BUILTIN_newarray_float,          gen_NEWARRAY_FLOAT,  },    
    {BUILTIN_newarray_double,         gen_NEWARRAY_DOUBLE, },
    {BUILTIN_arrayinstanceof,         gen_ARRAYINSTANCEOF, },

#if defined(ENABLE_THREADS)
    {LOCK_monitor_enter,              gen_MONITORENTER,    },
    {LOCK_monitor_exit,               gen_MONITOREXIT,     },
#endif

#if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L)
    {BUILTIN_f2l,                     gen_F2L,             },
#endif

#if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L)
    {BUILTIN_d2l,                           gen_D2L,                 },
#endif

#if !(SUPPORT_FLOAT && SUPPORT_F2I)
    {BUILTIN_f2i,                           gen_F2I,                 },
#endif

#if !(SUPPORT_DOUBLE && SUPPORT_D2I)
    {BUILTIN_d2i,                           gen_D2I,                 },
#endif

#if !SUPPORT_DIVISION
    {BUILTIN_idiv,                                gen_IDIV,                },
    {BUILTIN_irem,                                gen_IREM,                },
#endif

#if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
    {BUILTIN_ldiv,                                gen_LDIV,                },
    {BUILTIN_lrem,                                gen_LREM,                },
#endif

    {BUILTIN_frem,                                gen_FREM,                },
    {BUILTIN_drem,                                gen_DREM,            },
};


/* codegen *********************************************************************

   Generates machine code.

*******************************************************************************/

#define I(value)   iptr[0].sx.val.i = (value); break;

bool intrp_codegen(jitdata *jd)
{
      methodinfo         *m;
      codegendata        *cd;
      registerdata       *rd;
      s4                  i, len, s1, s2, d;
      basicblock         *bptr;
      instruction        *iptr;
      u2                  currentline;
      methodinfo         *lm;             /* local methodinfo for ICMD_INVOKE*  */
      unresolved_method  *um;
      builtintable_entry *bte;
      methoddesc         *md;
      fieldinfo          *fi;
      unresolved_field   *uf;
      s4                  fieldtype;

      /* get required compiler data */

      m  = jd->m;
      cd = jd->cd;
      rd = jd->rd;

      /* prevent compiler warnings */

      d = 0;
      currentline = 0;
      lm = NULL;
      bte = NULL;

      /* determine stackframe size (in units of ptrint slots) */

      cd->stackframesize = m->maxlocals;

#if defined(ENABLE_THREADS)
      if (checksync && code_is_synchronized(code))
            cd->stackframesize += 1;
#endif

      /* create method header */

      (void) dseg_add_unique_address(cd, jd->code);
      (void) dseg_add_unique_s4(cd, cd->stackframesize * SIZEOF_VOID_P);

      code->synchronizedoffset = rd->memuse * 8;

      /* REMOVEME: We still need it for exception handling in assembler. */

      if (code_is_leafmethod(code))
            (void) dseg_add_unique_s4(cd, 1);
      else
            (void) dseg_add_unique_s4(cd, 0);

      (void) dseg_add_unique_s4(cd, 0);
      (void) dseg_add_unique_s4(cd, 0);

      dseg_addlinenumbertablesize(cd);

#if 0 
      /* initialize mcode variables */
      
      cd->mcodeptr = cd->mcodebase;
      cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
#endif

      gen_BBSTART;

#if defined(ENABLE_THREADS)
      if (checksync && code_is_synchronized(code)) {
            if (m->flags & ACC_STATIC) {
                  gen_ACONST(cd, (java_objectheader *) m->clazz);
            }
            else {
                  gen_ALOAD(cd, 0);
                  gen_DUP(cd);
                  gen_ASTORE(cd, index2offset(m->maxlocals));
            }
            
            gen_MONITORENTER(cd);
      }                 
#endif

      if (opt_verbosecall)
            gen_TRACECALL(cd, m);

      gen_BBEND;

      /* walk through all basic blocks */

      for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {

            bptr->mpc = (s4) (cd->mcodeptr - cd->mcodebase);

            if (bptr->flags != BBDELETED) {

            /* walk through all instructions */
            
            len = bptr->icount;

            gen_BBSTART;

            for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
                  if (iptr->line != currentline) {
                        dseg_addlinenumber(cd, iptr->line);
                        currentline = iptr->line;
                  }

            MCODECHECK(64);       /* an instruction usually needs < 64 words      */

switch_again:
            switch (iptr->opc) {

            case ICMD_INLINE_START:
            case ICMD_INLINE_END:
                  break;

            case ICMD_NOP:        /* ...  ==> ...                                 */
                  break;

            case ICMD_CHECKNULL:  /* ..., objectref  ==> ..., objectref           */

                  gen_CHECKNULL(cd);
                  break;

            /* constant operations ************************************************/

            case ICMD_ICONST:     /* ...  ==> ..., constant                       */
                                  /* op1 = 0, val.i = constant                    */

                  /* optimize ICONST (2^x) .. IREM --> IREMPOW2 (const) */

                  if (len >= 2 && iptr[1].opc == ICMD_IREM) {
                        switch (iptr[0].sx.val.i) {
      case 0x00000001: case 0x00000002: case 0x00000004: case 0x00000008:
      case 0x00000010: case 0x00000020: case 0x00000040: case 0x00000080:
      case 0x00000100: case 0x00000200: case 0x00000400: case 0x00000800:
      case 0x00001000: case 0x00002000: case 0x00004000: case 0x00008000:
      case 0x00010000: case 0x00020000: case 0x00040000: case 0x00080000:
      case 0x00100000: case 0x00200000: case 0x00400000: case 0x00800000:
      case 0x01000000: case 0x02000000: case 0x04000000: case 0x08000000:
      case 0x10000000: case 0x20000000: case 0x40000000: case 0x80000000:
                              iptr[0].opc = ICMD_IREMPOW2;
                              iptr[0].sx.val.i--;
                              iptr[1].opc = ICMD_NOP;
                              goto switch_again;
                        }
                  }

                  /* optimize ICONST (2^x) .. IDIV --> IDIVPOW2 (const) */

                  if (len >= 2 && iptr[1].opc == ICMD_IDIV) {
                        switch (iptr[0].sx.val.i) {
                             case 0x00000002: I( 1) case 0x00000004: I( 2) case 0x00000008: I( 3)
      case 0x00000010: I( 4) case 0x00000020: I( 5) case 0x00000040: I( 6) case 0x00000080: I( 7)
      case 0x00000100: I( 8) case 0x00000200: I( 9) case 0x00000400: I(10) case 0x00000800: I(11)
      case 0x00001000: I(12) case 0x00002000: I(13) case 0x00004000: I(14) case 0x00008000: I(15)
      case 0x00010000: I(16) case 0x00020000: I(17) case 0x00040000: I(18) case 0x00080000: I(19)
      case 0x00100000: I(20) case 0x00200000: I(21) case 0x00400000: I(22) case 0x00800000: I(23)
      case 0x01000000: I(24) case 0x02000000: I(25) case 0x04000000: I(26) case 0x08000000: I(27)
      case 0x10000000: I(28) case 0x20000000: I(29) case 0x40000000: I(30) case 0x80000000: I(31)
      default: goto dont_opt_IDIVPOW2;
                        }
                        iptr[0].opc = ICMD_IDIVPOW2;
                        iptr[1].opc = ICMD_NOP;
                        goto switch_again;
                  }
dont_opt_IDIVPOW2:

                  /* optimize ICONST .. IF_ICMPxx --> IFxx (const) */

                  if (len >= 2) {
                        switch (iptr[1].opc) {
                              case ICMD_IF_ICMPEQ: iptr[0].opc = ICMD_IFEQ; break;
                              case ICMD_IF_ICMPNE: iptr[0].opc = ICMD_IFNE; break;
                              case ICMD_IF_ICMPLT: iptr[0].opc = ICMD_IFLT; break;
                              case ICMD_IF_ICMPLE: iptr[0].opc = ICMD_IFLE; break;
                              case ICMD_IF_ICMPGT: iptr[0].opc = ICMD_IFGT; break;
                              case ICMD_IF_ICMPGE: iptr[0].opc = ICMD_IFGE; break;
                              default:        goto dont_opt_IFxx;
                        }
                        iptr[0].dst.insindex = iptr[1].dst.insindex;
                        iptr[1].opc = ICMD_NOP;
                        goto switch_again;
                  }
dont_opt_IFxx:

                  gen_ICONST(cd, iptr->sx.val.i);
                  break;

            case ICMD_LCONST:     /* ...  ==> ..., constant                       */
                                  /* op1 = 0, val.l = constant                    */

                  /* optimize LCONST (2^x) .. LREM --> LREMPOW2 (const) */

                  if (len >= 2 && iptr[1].opc == ICMD_LREM) {
                        switch (iptr[0].sx.val.l) {
      case 0x00000001: case 0x00000002: case 0x00000004: case 0x00000008:
      case 0x00000010: case 0x00000020: case 0x00000040: case 0x00000080:
      case 0x00000100: case 0x00000200: case 0x00000400: case 0x00000800:
      case 0x00001000: case 0x00002000: case 0x00004000: case 0x00008000:
      case 0x00010000: case 0x00020000: case 0x00040000: case 0x00080000:
      case 0x00100000: case 0x00200000: case 0x00400000: case 0x00800000:
      case 0x01000000: case 0x02000000: case 0x04000000: case 0x08000000:
      case 0x10000000: case 0x20000000: case 0x40000000: case 0x80000000:
                              iptr[0].opc = ICMD_LREMPOW2;
                              iptr[0].sx.val.l--;
                              iptr[1].opc = ICMD_NOP;
                              goto switch_again;
                        }
                  }

                  /* optimize LCONST (2^x) .. LDIV --> LDIVPOW2 (const) */

                  if (len >= 2 && iptr[1].opc == ICMD_LDIV) {
                        switch (iptr[0].sx.val.l) {
                             case 0x00000002: I( 1) case 0x00000004: I( 2) case 0x00000008: I( 3)
      case 0x00000010: I( 4) case 0x00000020: I( 5) case 0x00000040: I( 6) case 0x00000080: I( 7)
      case 0x00000100: I( 8) case 0x00000200: I( 9) case 0x00000400: I(10) case 0x00000800: I(11)
      case 0x00001000: I(12) case 0x00002000: I(13) case 0x00004000: I(14) case 0x00008000: I(15)
      case 0x00010000: I(16) case 0x00020000: I(17) case 0x00040000: I(18) case 0x00080000: I(19)
      case 0x00100000: I(20) case 0x00200000: I(21) case 0x00400000: I(22) case 0x00800000: I(23)
      case 0x01000000: I(24) case 0x02000000: I(25) case 0x04000000: I(26) case 0x08000000: I(27)
      case 0x10000000: I(28) case 0x20000000: I(29) case 0x40000000: I(30) case 0x80000000: I(31)
      default: goto dont_opt_LDIVPOW2;
                        }
                        iptr[0].opc = ICMD_LDIVPOW2;
                        iptr[1].opc = ICMD_NOP;
                        goto switch_again;
                  }
dont_opt_LDIVPOW2:

                  /* optimize LCONST .. LCMP .. IFxx (0) --> IF_Lxx */

                  if (len >= 3 && iptr[1].opc == ICMD_LCMP && iptr[2].sx.val.i == 0) {
                        switch (iptr[2].opc) {
                              case ICMD_IFEQ: iptr[0].opc = ICMD_IF_LEQ; break;
                              case ICMD_IFNE: iptr[0].opc = ICMD_IF_LNE; break;
                              case ICMD_IFLT: iptr[0].opc = ICMD_IF_LLT; break;
                              case ICMD_IFLE: iptr[0].opc = ICMD_IF_LLE; break;
                              case ICMD_IFGT: iptr[0].opc = ICMD_IF_LGT; break;
                              case ICMD_IFGE: iptr[0].opc = ICMD_IF_LGE; break;
                              default:        goto dont_opt_IF_Lxx;
                        }
                        iptr[0].dst.insindex = iptr[2].dst.insindex;
                        iptr[1].opc = ICMD_NOP;
                        iptr[2].opc = ICMD_NOP;
                        goto switch_again;
                  }
dont_opt_IF_Lxx:

                  gen_LCONST(cd, iptr->sx.val.l);
                  break;

            case ICMD_FCONST:     /* ...  ==> ..., constant                       */
                                  /* op1 = 0, val.f = constant                    */
                  {
                        ptrint fi;

                        vm_f2Cell(iptr->sx.val.f, fi);
                        gen_ICONST(cd, fi);
                  }
                  break;
                  
            case ICMD_DCONST:     /* ...  ==> ..., constant                       */
                                  /* op1 = 0, val.d = constant                    */

                  gen_LCONST(cd, *(s8 *)&(iptr->sx.val.d));
                  break;

            case ICMD_ACONST:     /* ...  ==> ..., constant                       */
                                  /* op1 = 0, val.a = constant                    */

                  if (INSTRUCTION_IS_UNRESOLVED(iptr))
                        gen_PATCHER_ACONST(cd, NULL, iptr->sx.val.c.ref);
                  else
                        gen_ACONST(cd, iptr->sx.val.anyptr);
                  break;


            /* load/store operations **********************************************/

            case ICMD_ILOAD:      /* ...  ==> ..., content of local variable      */
                                  /* op1 = local variable                         */

                  gen_ILOAD(cd, index2offset(iptr->s1.varindex));
                  break;

            case ICMD_LLOAD:      /* ...  ==> ..., content of local variable      */
                                  /* op1 = local variable                         */

                  gen_LLOAD(cd, index2offset(iptr->s1.varindex));
                  break;

            case ICMD_ALOAD:      /* ...  ==> ..., content of local variable      */
                                  /* op1 = local variable                         */

                  gen_ALOAD(cd, index2offset(iptr->s1.varindex));
                  break;

            case ICMD_FLOAD:      /* ...  ==> ..., content of local variable      */
                                  /* op1 = local variable                         */

                  gen_ILOAD(cd, index2offset(iptr->s1.varindex));
                  break;

            case ICMD_DLOAD:      /* ...  ==> ..., content of local variable      */
                                  /* op1 = local variable                         */

                  gen_LLOAD(cd, index2offset(iptr->s1.varindex));
                  break;


            case ICMD_ISTORE:     /* ..., value  ==> ...                          */
                                  /* op1 = local variable                         */

                  gen_ISTORE(cd, index2offset(iptr->dst.varindex));
                  break;

            case ICMD_LSTORE:     /* ..., value  ==> ...                          */
                                  /* op1 = local variable                         */

                  gen_LSTORE(cd, index2offset(iptr->dst.varindex));
                  break;

            case ICMD_ASTORE:     /* ..., value  ==> ...                          */
                                  /* op1 = local variable                         */

                  gen_ASTORE(cd, index2offset(iptr->dst.varindex));
                  break;


            case ICMD_FSTORE:     /* ..., value  ==> ...                          */
                                  /* op1 = local variable                         */

                  gen_ISTORE(cd, index2offset(iptr->dst.varindex));
                  break;

            case ICMD_DSTORE:     /* ..., value  ==> ...                          */
                                  /* op1 = local variable                         */

                  gen_LSTORE(cd, index2offset(iptr->dst.varindex));
                  break;


            /* pop/dup/swap operations ********************************************/

            case ICMD_POP:        /* ..., value  ==> ...                          */

                  gen_POP(cd);
                  break;

            case ICMD_POP2:       /* ..., value, value  ==> ...                   */

                  gen_POP2(cd);
                  break;

            case ICMD_DUP:        /* ..., a ==> ..., a, a                         */

                  gen_DUP(cd);
                  break;

            case ICMD_DUP_X1:     /* ..., a, b ==> ..., b, a, b                   */

                  gen_DUP_X1(cd);
                  break;

            case ICMD_DUP_X2:     /* ..., a, b, c ==> ..., c, a, b, c             */

                  gen_DUP_X2(cd);
                  break;

            case ICMD_DUP2:       /* ..., a, b ==> ..., a, b, a, b                */

                  gen_DUP2(cd);
                  break;

            case ICMD_DUP2_X1:    /* ..., a, b, c ==> ..., b, c, a, b, c          */

                  gen_DUP2_X1(cd);
                  break;

            case ICMD_DUP2_X2:    /* ..., a, b, c, d ==> ..., c, d, a, b, c, d    */

                  gen_DUP2_X2(cd);
                  break;

            case ICMD_SWAP:       /* ..., a, b ==> ..., b, a                      */

                  gen_SWAP(cd);
                  break;


            /* integer operations *************************************************/

            case ICMD_INEG:       /* ..., value  ==> ..., - value                 */

                  gen_INEG(cd);
                  break;

            case ICMD_LNEG:       /* ..., value  ==> ..., - value                 */

                  gen_LNEG(cd);
                  break;

            case ICMD_I2L:        /* ..., value  ==> ..., value                   */

                  gen_I2L(cd);
                  break;

            case ICMD_L2I:        /* ..., value  ==> ..., value                   */

                  gen_L2I(cd);
                  break;

            case ICMD_INT2BYTE:   /* ..., value  ==> ..., value                   */

                  gen_INT2BYTE(cd);
                  break;

            case ICMD_INT2CHAR:   /* ..., value  ==> ..., value                   */

                  gen_INT2CHAR(cd);
                  break;

            case ICMD_INT2SHORT:  /* ..., value  ==> ..., value                   */

                  gen_INT2SHORT(cd);
                  break;


            case ICMD_IADD:       /* ..., val1, val2  ==> ..., val1 + val2        */

                  gen_IADD(cd);
                  break;

            case ICMD_LADD:       /* ..., val1, val2  ==> ..., val1 + val2        */

                  gen_LADD(cd);
                  break;

            case ICMD_ISUB:       /* ..., val1, val2  ==> ..., val1 - val2        */

                  gen_ISUB(cd);
                  break;

            case ICMD_LSUB:       /* ..., val1, val2  ==> ..., val1 - val2        */

                  gen_LSUB(cd);
                  break;

            case ICMD_IMUL:       /* ..., val1, val2  ==> ..., val1 * val2        */

                  gen_IMUL(cd);
                  break;

            case ICMD_LMUL:       /* ..., val1, val2  ==> ..., val1 * val2        */

                  gen_LMUL(cd);
                  break;

            case ICMD_IDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */

                  gen_IDIV(cd);
                  break;

            case ICMD_IREM:       /* ..., val1, val2  ==> ..., val1 % val2        */

                  gen_IREM(cd);
                  break;

            case ICMD_LDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */

                  gen_LDIV(cd);
                  break;

            case ICMD_LREM:       /* ..., val1, val2  ==> ..., val1 % val2        */

                  gen_LREM(cd);
                  break;

            case ICMD_IDIVPOW2:   /* ..., value  ==> ..., value << constant       */
                                  /* val.i = constant                             */
                                  
                  gen_IDIVPOW2(cd, iptr->sx.val.i);
                  break;

            case ICMD_IREMPOW2:   /* ..., value  ==> ..., value % constant        */
                                  /* val.i = constant                             */

                  gen_IREMPOW2(cd, iptr->sx.val.i);
                  break;

            case ICMD_LDIVPOW2:   /* ..., value  ==> ..., value << constant       */
                                  /* val.i = constant                             */
                                  
                  gen_LDIVPOW2(cd, iptr->sx.val.i);
                  break;

            case ICMD_LREMPOW2:   /* ..., value  ==> ..., value % constant        */
                                  /* val.l = constant                             */

                  gen_LREMPOW2(cd, iptr->sx.val.i);
                  break;

            case ICMD_ISHL:       /* ..., val1, val2  ==> ..., val1 << val2       */

                  gen_ISHL(cd);
                  break;

            case ICMD_ISHR:       /* ..., val1, val2  ==> ..., val1 >> val2       */

                  gen_ISHR(cd);
                  break;

            case ICMD_IUSHR:      /* ..., val1, val2  ==> ..., val1 >>> val2      */

                  gen_IUSHR(cd);
                  break;

            case ICMD_LSHL:       /* ..., val1, val2  ==> ..., val1 << val2       */

                  gen_LSHL(cd);
                  break;

            case ICMD_LSHR:       /* ..., val1, val2  ==> ..., val1 >> val2       */

                  gen_LSHR(cd);
                  break;

            case ICMD_LUSHR:      /* ..., val1, val2  ==> ..., val1 >>> val2      */

                  gen_LUSHR(cd);
                  break;

            case ICMD_IAND:       /* ..., val1, val2  ==> ..., val1 & val2        */

                  gen_IAND(cd);
                  break;

            case ICMD_LAND:       /* ..., val1, val2  ==> ..., val1 & val2        */

                  gen_LAND(cd);
                  break;

            case ICMD_IOR:        /* ..., val1, val2  ==> ..., val1 | val2        */

                  gen_IOR(cd);
                  break;

            case ICMD_LOR:        /* ..., val1, val2  ==> ..., val1 | val2        */

                  gen_LOR(cd);
                  break;

            case ICMD_IXOR:       /* ..., val1, val2  ==> ..., val1 ^ val2        */

                  gen_IXOR(cd);
                  break;

            case ICMD_LXOR:       /* ..., val1, val2  ==> ..., val1 ^ val2        */

                  gen_LXOR(cd);
                  break;


            case ICMD_LCMP:       /* ..., val1, val2  ==> ..., val1 cmp val2      */

                  /* optimize LCMP .. IFxx (0) --> IF_LCMPxx */

                  if (len >= 2 && iptr[1].sx.val.i == 0) {
                        switch (iptr[1].opc) {
                              case ICMD_IFEQ: iptr[0].opc = ICMD_IF_LCMPEQ; break;
                              case ICMD_IFNE: iptr[0].opc = ICMD_IF_LCMPNE; break;
                              case ICMD_IFLT: iptr[0].opc = ICMD_IF_LCMPLT; break;
                              case ICMD_IFLE: iptr[0].opc = ICMD_IF_LCMPLE; break;
                              case ICMD_IFGT: iptr[0].opc = ICMD_IF_LCMPGT; break;
                              case ICMD_IFGE: iptr[0].opc = ICMD_IF_LCMPGE; break;
                              default:        goto dont_opt_IF_LCMPxx;
                        }
                        iptr[0].dst.insindex = iptr[1].dst.insindex;
                        iptr[1].opc = ICMD_NOP;
                        goto switch_again;
                  }
dont_opt_IF_LCMPxx:

                  gen_LCMP(cd);
                  break;


            case ICMD_IINC:       /* ..., value  ==> ..., value + constant        */
                                  /* op1 = variable, val.i = constant             */

                  gen_IINC(cd, index2offset(iptr->s1.varindex), iptr->sx.val.i);
                  break;


            /* floating operations ************************************************/

            case ICMD_FNEG:       /* ..., value  ==> ..., - value                 */

                  gen_FNEG(cd);
                  break;

            case ICMD_DNEG:       /* ..., value  ==> ..., - value                 */

                  gen_DNEG(cd);
                  break;

            case ICMD_FADD:       /* ..., val1, val2  ==> ..., val1 + val2        */

                  gen_FADD(cd);
                  break;

            case ICMD_DADD:       /* ..., val1, val2  ==> ..., val1 + val2        */

                  gen_DADD(cd);
                  break;

            case ICMD_FSUB:       /* ..., val1, val2  ==> ..., val1 - val2        */

                  gen_FSUB(cd);
                  break;

            case ICMD_DSUB:       /* ..., val1, val2  ==> ..., val1 - val2        */

                  gen_DSUB(cd);
                  break;

            case ICMD_FMUL:       /* ..., val1, val2  ==> ..., val1 * val2        */

                  gen_FMUL(cd);
                  break;

            case ICMD_DMUL:       /* ..., val1, val2  ==> ..., val1 *** val2      */

                  gen_DMUL(cd);
                  break;

            case ICMD_FDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */

                  gen_FDIV(cd);
                  break;

            case ICMD_DDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */

                  gen_DDIV(cd);
                  break;
            
            case ICMD_FREM:       /* ..., val1, val2  ==> ..., val1 % val2        */

                  gen_FREM(cd);
                  break;

            case ICMD_DREM:       /* ..., val1, val2  ==> ..., val1 % val2        */

                  gen_DREM(cd);
                  break;
            
            case ICMD_I2F:       /* ..., value  ==> ..., (float) value            */

                  gen_I2F(cd);
                  break;

            case ICMD_L2F:       /* ..., value  ==> ..., (float) value            */

                  gen_L2F(cd);
                  break;

            case ICMD_I2D:       /* ..., value  ==> ..., (double) value           */

                  gen_I2D(cd);
                  break;
                  
            case ICMD_L2D:       /* ..., value  ==> ..., (double) value           */

                  gen_L2D(cd);
                  break;
                  
            case ICMD_F2I:       /* ..., value  ==> ..., (int) value              */

                  gen_F2I(cd);
                  break;
            
            case ICMD_D2I:       /* ..., value  ==> ..., (int) value              */

                  gen_D2I(cd);
                  break;
            
            case ICMD_F2L:       /* ..., value  ==> ..., (long) value             */

                  gen_F2L(cd);
                  break;

            case ICMD_D2L:       /* ..., value  ==> ..., (long) value             */

                  gen_D2L(cd);
                  break;

            case ICMD_F2D:       /* ..., value  ==> ..., (double) value           */

                  gen_F2D(cd);
                  break;
                              
            case ICMD_D2F:       /* ..., value  ==> ..., (float) value            */

                  gen_D2F(cd);
                  break;
            
            case ICMD_FCMPL:      /* ..., val1, val2  ==> ..., val1 fcmpl val2    */

                  gen_FCMPL(cd);
                  break;
                  
            case ICMD_DCMPL:      /* ..., val1, val2  ==> ..., val1 fcmpl val2    */

                  gen_DCMPL(cd);
                  break;
                  
            case ICMD_FCMPG:      /* ..., val1, val2  ==> ..., val1 fcmpg val2    */

                  gen_FCMPG(cd);
                  break;

            case ICMD_DCMPG:      /* ..., val1, val2  ==> ..., val1 fcmpg val2    */

                  gen_DCMPG(cd);
                  break;


            /* memory operations **************************************************/

            case ICMD_ARRAYLENGTH: /* ..., arrayref  ==> ..., length              */

                  gen_ARRAYLENGTH(cd);
                  break;

            case ICMD_BALOAD:     /* ..., arrayref, index  ==> ..., value         */

                  gen_BALOAD(cd);
                  break;

            case ICMD_CALOAD:     /* ..., arrayref, index  ==> ..., value         */

                  gen_CALOAD(cd);
                  break;                  

            case ICMD_SALOAD:     /* ..., arrayref, index  ==> ..., value         */

                  gen_SALOAD(cd);
                  break;

            case ICMD_IALOAD:     /* ..., arrayref, index  ==> ..., value         */

                  gen_IALOAD(cd);
                  break;

            case ICMD_FALOAD:     /* ..., arrayref, index  ==> ..., value         */

                  gen_FALOAD(cd);
                  break;

            case ICMD_LALOAD:     /* ..., arrayref, index  ==> ..., value         */
            case ICMD_DALOAD:     /* ..., arrayref, index  ==> ..., value         */

                  gen_LALOAD(cd);
                  break;

            case ICMD_AALOAD:     /* ..., arrayref, index  ==> ..., value         */

                  gen_AALOAD(cd);
                  break;


            case ICMD_BASTORE:    /* ..., arrayref, index, value  ==> ...         */

                  gen_BASTORE(cd);
                  break;

            case ICMD_CASTORE:    /* ..., arrayref, index, value  ==> ...         */
            case ICMD_SASTORE:    /* ..., arrayref, index, value  ==> ...         */

                  gen_CASTORE(cd);
                  break;

            case ICMD_IASTORE:    /* ..., arrayref, index, value  ==> ...         */

                  gen_IASTORE(cd);
                  break;

            case ICMD_FASTORE:    /* ..., arrayref, index, value  ==> ...         */

                  gen_FASTORE(cd);
                  break;

            case ICMD_LASTORE:    /* ..., arrayref, index, value  ==> ...         */
            case ICMD_DASTORE:    /* ..., arrayref, index, value  ==> ...         */

                  gen_LASTORE(cd);
                  break;

            case ICMD_AASTORE:    /* ..., arrayref, index, value  ==> ...         */

                  gen_AASTORE(cd);
                  break;


            case ICMD_GETSTATIC:  /* ...  ==> ..., value                          */
                                  /* op1 = type, val.a = field address            */

                  if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
                        fi        = NULL;
                        uf        = iptr->sx.s23.s3.uf;
                        fieldtype = uf->fieldref->parseddesc.fd->type;
                  }
                  else {
                        fi        = iptr->sx.s23.s3.fmiref->p.field;
                        uf        = NULL;
                        fieldtype = fi->type;
                  }

                  switch (fieldtype) {
                  case TYPE_INT:
                        if (fi == NULL)
                              gen_PATCHER_GETSTATIC_INT(cd, 0, uf);
                        else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
                              gen_PATCHER_GETSTATIC_CLINIT_INT(cd, 0, fi);
                        else
                              gen_GETSTATIC_INT(cd, (u1 *) &(fi->value.i), fi);
                        break;
                  case TYPE_FLT:
                        if (fi == NULL)
                              gen_PATCHER_GETSTATIC_FLOAT(cd, 0, uf);
                        else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
                              gen_PATCHER_GETSTATIC_CLINIT_FLOAT(cd, 0, fi);
                        else
                              gen_GETSTATIC_FLOAT(cd, (u1 *) &(fi->value.i), fi);
                        break;
                  case TYPE_LNG:
                  case TYPE_DBL:
                        if (fi == NULL)
                              gen_PATCHER_GETSTATIC_LONG(cd, 0, uf);
                        else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
                              gen_PATCHER_GETSTATIC_CLINIT_LONG(cd, 0, fi);
                        else
                              gen_GETSTATIC_LONG(cd, (u1 *) &(fi->value.l), fi);
                        break;
                  case TYPE_ADR:
                        if (fi == NULL)
                              gen_PATCHER_GETSTATIC_CELL(cd, 0, uf);
                        else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
                              gen_PATCHER_GETSTATIC_CLINIT_CELL(cd, 0, fi);
                        else
                              gen_GETSTATIC_CELL(cd, (u1 *) &(fi->value.a), fi);
                        break;
                  }
                  break;

            case ICMD_PUTSTATIC:  /* ..., value  ==> ...                          */
                                  /* op1 = type, val.a = field address            */

                  if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
                        fi        = NULL;
                        uf        = iptr->sx.s23.s3.uf;
                        fieldtype = uf->fieldref->parseddesc.fd->type;
                  }
                  else {
                        fi        = iptr->sx.s23.s3.fmiref->p.field;
                        uf        = NULL;
                        fieldtype = fi->type;
                  }

                  switch (fieldtype) {
                  case TYPE_INT:
                        if (fi == NULL)
                              gen_PATCHER_PUTSTATIC_INT(cd, 0, uf);
                        else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
                              gen_PATCHER_PUTSTATIC_CLINIT_INT(cd, 0, fi);
                        else
                              gen_PUTSTATIC_INT(cd, (u1 *) &(fi->value.i), fi);
                        break;
                  case TYPE_FLT:
                        if (fi == NULL)
                              gen_PATCHER_PUTSTATIC_FLOAT(cd, 0, uf);
                        else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
                              gen_PATCHER_PUTSTATIC_CLINIT_FLOAT(cd, 0, fi);
                        else
                              gen_PUTSTATIC_FLOAT(cd, (u1 *) &(fi->value.i), fi);
                        break;
                  case TYPE_LNG:
                  case TYPE_DBL:
                        if (fi == NULL)
                              gen_PATCHER_PUTSTATIC_LONG(cd, 0, uf);
                        else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
                              gen_PATCHER_PUTSTATIC_CLINIT_LONG(cd, 0, fi);
                        else
                              gen_PUTSTATIC_LONG(cd, (u1 *) &(fi->value.l), fi);
                        break;
                  case TYPE_ADR:
                        if (fi == NULL)
                              gen_PATCHER_PUTSTATIC_CELL(cd, 0, uf);
                        else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
                              gen_PATCHER_PUTSTATIC_CLINIT_CELL(cd, 0, fi);
                        else
                              gen_PUTSTATIC_CELL(cd, (u1 *) &(fi->value.a), fi);
                        break;
                  }
                  break;


            case ICMD_GETFIELD:   /* ...  ==> ..., value                          */
                                  /* op1 = type, val.a = field address            */

                  if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
                        fi        = NULL;
                        uf        = iptr->sx.s23.s3.uf;
                        fieldtype = uf->fieldref->parseddesc.fd->type;
                  }
                  else {
                        fi        = iptr->sx.s23.s3.fmiref->p.field;
                        uf        = NULL;
                        fieldtype = fi->type;
                  }

                  switch (fieldtype) {
                  case TYPE_INT:
                        if (fi == NULL)
                              gen_PATCHER_GETFIELD_INT(cd, 0, uf);
                        else
                              gen_GETFIELD_INT(cd, fi->offset, fi);
                        break;
                  case TYPE_FLT:
                        if (fi == NULL)
                              gen_PATCHER_GETFIELD_FLOAT(cd, 0, uf);
                        else
                              gen_GETFIELD_FLOAT(cd, fi->offset, fi);
                        break;
                  case TYPE_LNG:
                  case TYPE_DBL:
                        if (fi == NULL)
                              gen_PATCHER_GETFIELD_LONG(cd, 0, uf);
                        else
                              gen_GETFIELD_LONG(cd, fi->offset, fi);
                        break;
                  case TYPE_ADR:
                        if (fi == NULL)
                              gen_PATCHER_GETFIELD_CELL(cd, 0, uf);
                        else
                              gen_GETFIELD_CELL(cd, fi->offset, fi);
                        break;
                  }
                  break;

            case ICMD_PUTFIELD:   /* ..., objectref, value  ==> ...               */
                                  /* op1 = type, val.a = field address            */

                  if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
                        fi        = NULL;
                        uf        = iptr->sx.s23.s3.uf;
                        fieldtype = uf->fieldref->parseddesc.fd->type;
                  }
                  else {
                        fi        = iptr->sx.s23.s3.fmiref->p.field;
                        uf        = NULL;
                        fieldtype = fi->type;
                  }

                  switch (fieldtype) {
                  case TYPE_INT:
                        if (fi == NULL)
                              gen_PATCHER_PUTFIELD_INT(cd, 0, uf);
                        else
                              gen_PUTFIELD_INT(cd, fi->offset, fi);
                        break;
                  case TYPE_FLT:
                        if (fi == NULL)
                              gen_PATCHER_PUTFIELD_FLOAT(cd, 0, uf);
                        else
                              gen_PUTFIELD_FLOAT(cd, fi->offset, fi);
                        break;
                  case TYPE_LNG:
                  case TYPE_DBL:
                        if (fi == NULL)
                              gen_PATCHER_PUTFIELD_LONG(cd, 0, uf);
                        else
                              gen_PUTFIELD_LONG(cd, fi->offset, fi);
                        break;
                  case TYPE_ADR:
                        if (fi == NULL)
                              gen_PATCHER_PUTFIELD_CELL(cd, 0, uf);
                        else
                              gen_PUTFIELD_CELL(cd, fi->offset, fi);
                        break;
                  }
                  break;


            /* branch operations **************************************************/

            case ICMD_ATHROW:       /* ..., objectref ==> ... (, objectref)       */

                  gen_ATHROW(cd);
                  break;

            case ICMD_GOTO:         /* ... ==> ...                                */
                                    /* op1 = target JavaVM pc                     */
                  gen_branch(GOTO);
                  break;

            case ICMD_JSR:          /* ... ==> ...                                */
                                    /* op1 = target JavaVM pc                     */

                  gen_JSR(cd, NULL);
                  codegen_addreference(cd, BLOCK_OF(iptr->sx.s23.s3.jsrtarget.insindex));
                  break;

            case ICMD_RET:          /* ... ==> ...                                */
                                    /* op1 = local variable                       */

                  gen_RET(cd, index2offset(iptr->s1.varindex));
                  break;

            case ICMD_IFNULL:       /* ..., value ==> ...                         */
                                    /* op1 = target JavaVM pc                     */

                  gen_branch(IFNULL);
                  break;

            case ICMD_IFNONNULL:    /* ..., value ==> ...                         */
                                    /* op1 = target JavaVM pc                     */

                  gen_branch(IFNONNULL);
                  break;

            case ICMD_IFEQ:         /* ..., value ==> ...                         */
                                    /* op1 = target JavaVM pc, val.i = constant   */

                  if (iptr->sx.val.i == 0) {
                        gen_branch(IFEQ);
                  } else {
                        gen_ICONST(cd, iptr->sx.val.i);
                        gen_branch(IF_ICMPEQ);
                  }
                  break;

            case ICMD_IFLT:         /* ..., value ==> ...                         */
                                    /* op1 = target JavaVM pc, val.i = constant   */

                  if (iptr->sx.val.i == 0) {
                        gen_branch(IFLT);
                  } else {
                        gen_ICONST(cd, iptr->sx.val.i);
                        gen_branch(IF_ICMPLT);
                  }
                  break;

            case ICMD_IFLE:         /* ..., value ==> ...                         */
                                    /* op1 = target JavaVM pc, val.i = constant   */

                  if (iptr->sx.val.i == 0) {
                        gen_branch(IFLE);
                  } else {
                        gen_ICONST(cd, iptr->sx.val.i);
                        gen_branch(IF_ICMPLE);
                  }
                  break;

            case ICMD_IFNE:         /* ..., value ==> ...                         */
                                    /* op1 = target JavaVM pc, val.i = constant   */

                  if (iptr->sx.val.i == 0) {
                        gen_branch(IFNE);
                  } else {
                        gen_ICONST(cd, iptr->sx.val.i);
                        gen_branch(IF_ICMPNE);
                  }
                  break;

            case ICMD_IFGT:         /* ..., value ==> ...                         */
                                    /* op1 = target JavaVM pc, val.i = constant   */

                  if (iptr->sx.val.i == 0) {
                        gen_branch(IFGT);
                  } else {
                        gen_ICONST(cd, iptr->sx.val.i);
                        gen_branch(IF_ICMPGT);
                  }
                  break;

            case ICMD_IFGE:         /* ..., value ==> ...                         */
                                    /* op1 = target JavaVM pc, val.i = constant   */

                  if (iptr->sx.val.i == 0) {
                        gen_branch(IFGE);
                  } else {
                        gen_ICONST(cd, iptr->sx.val.i);
                        gen_branch(IF_ICMPGE);
                  }
                  break;


            case ICMD_IF_LEQ:       /* ..., value ==> ...                         */
                                    /* op1 = target JavaVM pc, val.l = constant   */

                  gen_LCONST(cd, iptr->sx.val.l);
                  gen_branch(IF_LCMPEQ);
                  break;

            case ICMD_IF_LLT:       /* ..., value ==> ...                         */
                                    /* op1 = target JavaVM pc, val.l = constant   */

                  gen_LCONST(cd, iptr->sx.val.l);
                  gen_branch(IF_LCMPLT);
                  break;

            case ICMD_IF_LLE:       /* ..., value ==> ...                         */
                                    /* op1 = target JavaVM pc, val.l = constant   */

                  gen_LCONST(cd, iptr->sx.val.l);
                  gen_branch(IF_LCMPLE);
                  break;

            case ICMD_IF_LNE:       /* ..., value ==> ...                         */
                                    /* op1 = target JavaVM pc, val.l = constant   */

                  gen_LCONST(cd, iptr->sx.val.l);
                  gen_branch(IF_LCMPNE);
                  break;

            case ICMD_IF_LGT:       /* ..., value ==> ...                         */
                                    /* op1 = target JavaVM pc, val.l = constant   */

                  gen_LCONST(cd, iptr->sx.val.l);
                  gen_branch(IF_LCMPGT);
                  break;

            case ICMD_IF_LGE:       /* ..., value ==> ...                         */
                                    /* op1 = target JavaVM pc, val.l = constant   */

                  gen_LCONST(cd, iptr->sx.val.l);
                  gen_branch(IF_LCMPGE);
                  break;

            case ICMD_IF_LCMPEQ:    /* ..., value, value ==> ...                  */
                                    /* op1 = target JavaVM pc                     */

                  gen_branch(IF_LCMPEQ);
                  break;

            case ICMD_IF_LCMPNE:    /* ..., value, value ==> ...                  */
                                    /* op1 = target JavaVM pc                     */

                  gen_branch(IF_LCMPNE);
                  break;

            case ICMD_IF_LCMPLT:    /* ..., value, value ==> ...                  */
                                    /* op1 = target JavaVM pc                     */

                  gen_branch(IF_LCMPLT);
                  break;

            case ICMD_IF_LCMPGT:    /* ..., value, value ==> ...                  */
                                    /* op1 = target JavaVM pc                     */

                  gen_branch(IF_LCMPGT);
                  break;

            case ICMD_IF_LCMPLE:    /* ..., value, value ==> ...                  */
                                    /* op1 = target JavaVM pc                     */

                  gen_branch(IF_LCMPLE);
                  break;

            case ICMD_IF_LCMPGE:    /* ..., value, value ==> ...                  */
                                    /* op1 = target JavaVM pc                     */

                  gen_branch(IF_LCMPGE);
                  break;


            case ICMD_IF_ICMPEQ:    /* ..., value, value ==> ...                  */
                                    /* op1 = target JavaVM pc                     */

                  gen_branch(IF_ICMPEQ);
                  break;

            case ICMD_IF_ACMPEQ:    /* ..., value, value ==> ...                  */
                                    /* op1 = target JavaVM pc                     */

                  gen_branch(IF_ACMPEQ);
                  break;

            case ICMD_IF_ICMPNE:    /* ..., value, value ==> ...                  */
                                    /* op1 = target JavaVM pc                     */

                  gen_branch(IF_ICMPNE);
                  break;

            case ICMD_IF_ACMPNE:    /* ..., value, value ==> ...                  */
                                    /* op1 = target JavaVM pc                     */

                  gen_branch(IF_ACMPNE);
                  break;

            case ICMD_IF_ICMPLT:    /* ..., value, value ==> ...                  */
                                    /* op1 = target JavaVM pc                     */

                  gen_branch(IF_ICMPLT);
                  break;

            case ICMD_IF_ICMPGT:    /* ..., value, value ==> ...                  */
                                    /* op1 = target JavaVM pc                     */

                  gen_branch(IF_ICMPGT);
                  break;

            case ICMD_IF_ICMPLE:    /* ..., value, value ==> ...                  */
                                    /* op1 = target JavaVM pc                     */

                  gen_branch(IF_ICMPLE);
                  break;

            case ICMD_IF_ICMPGE:    /* ..., value, value ==> ...                  */
                                    /* op1 = target JavaVM pc                     */

                  gen_branch(IF_ICMPGE);
                  break;


            case ICMD_ARETURN:      /* ..., retvalue ==> ...                      */
            case ICMD_IRETURN:      /* ..., retvalue ==> ...                      */
            case ICMD_FRETURN:      /* ..., retvalue ==> ...                      */

#if defined(ENABLE_THREADS)
                  if (checksync && code_is_synchronized(code)) {
                        if (m->flags & ACC_STATIC) {
                              gen_ACONST(cd, (java_objectheader *) m->clazz);
                        } else {
                              gen_ALOAD(cd, index2offset(m->maxlocals));
                        }
                        gen_MONITOREXIT(cd);
                  }
#endif
                  if (opt_verbosecall)
                        gen_TRACERETURN(cd, m);

                  gen_IRETURN(cd, index2offset(cd->stackframesize));
                  break;

            case ICMD_LRETURN:      /* ..., retvalue ==> ...                      */
            case ICMD_DRETURN:      /* ..., retvalue ==> ...                      */

#if defined(ENABLE_THREADS)
                  if (checksync && code_is_synchronized(code)) {
                        if (m->flags & ACC_STATIC) {
                              gen_ACONST(cd, (java_objectheader *) m->clazz);
                        } else {
                              gen_ALOAD(cd, index2offset(m->maxlocals));
                        }
                        gen_MONITOREXIT(cd);
                  }
#endif
                  if (opt_verbosecall)
                        gen_TRACELRETURN(cd, m);

                  gen_LRETURN(cd, index2offset(cd->stackframesize));
                  break;

            case ICMD_RETURN:       /* ...  ==> ...                               */

#if defined(ENABLE_THREADS)
                  if (checksync && code_is_synchronized(code)) {
                        if (m->flags & ACC_STATIC) {
                              gen_ACONST(cd, (java_objectheader *) m->clazz);
                        } else {
                              gen_ALOAD(cd, index2offset(m->maxlocals));
                        }
                        gen_MONITOREXIT(cd);
                  }
#endif
                  if (opt_verbosecall)
                        gen_TRACERETURN(cd, m);

                  gen_RETURN(cd, index2offset(cd->stackframesize));
                  break;


            case ICMD_TABLESWITCH:  /* ..., index ==> ...                         */
                  {
                  s4 i, l;
                  branch_target_t *table;

                  table = iptr->dst.table;

                  l = iptr->sx.s23.s2.tablelow;
                  i = iptr->sx.s23.s3.tablehigh;
                  
                  i = i - l + 1;

                  /* arguments: low, range, datasegment address, table
                   offset in datasegment, default target */

                  gen_TABLESWITCH(cd, l, i, NULL, 0, NULL);

                  /* actually -3 cells offset */

                  cd->mcodeptr = (u1 *) cd->mcodeptr - 2 * sizeof(Inst);
                  dseg_adddata(cd);
                  cd->mcodeptr = (u1 *) cd->mcodeptr + 2 * sizeof(Inst);

                  codegen_addreference(cd, BLOCK_OF(table[0].insindex));

                  /* build jump table top down and use address of lowest entry */

                  table += i;

                  while (--i >= 0) {
                        dseg_add_target(cd, BLOCK_OF(table->insindex)); 
                        --table;
                  }
                  }

                  /* length of dataseg after last dseg_add_target is used by load */
                  ((ptrint *)(cd->mcodeptr))[-2] = (ptrint) -(cd->dseglen);
                  break;


            case ICMD_LOOKUPSWITCH: /* ..., key ==> ...                           */
                  {
                  s4 i;
                  lookup_target_t *lookup;

                  lookup = iptr->dst.lookup;

                  i = iptr->sx.s23.s2.lookupcount;
                  
                  /* arguments: count, datasegment address, table offset in         */
                  /* datasegment, default target                                    */
                  gen_LOOKUPSWITCH(cd, i, NULL, 0, NULL);

                  /* actually -3 cells offset */

                  cd->mcodeptr = (u1 *) cd->mcodeptr - 2 * sizeof(Inst);
                  dseg_adddata(cd);
                  cd->mcodeptr = (u1 *) cd->mcodeptr + 2 * sizeof(Inst);

                  /* build jump table top down and use address of lowest entry */

                  while (--i >= 0) {
                        dseg_add_target(cd, BLOCK_OF(lookup->target.insindex)); 
                        dseg_add_unique_address(cd, lookup->value);
                        lookup++;
                  }

                  codegen_addreference(cd, BLOCK_OF(iptr->sx.s23.s3.lookupdefault.insindex));
                  }

                  /* length of dataseg after last dseg_add_target is used by load */
                  ((ptrint *)(cd->mcodeptr))[-2] = (ptrint) -(cd->dseglen);
                  break;


            case ICMD_BUILTIN:      /* ..., arg1, arg2, arg3 ==> ...              */
                                    /* op1 = arg count val.a = builtintable entry */
                  bte = iptr->sx.s23.s3.bte;

                  for (i = 0; i < sizeof(builtin_gen_table)/sizeof(builtin_gen); i++) {
                        builtin_gen *bg = &builtin_gen_table[i];
                        if (bg->builtin == bte->fp) {
                              (bg->gen)(cd);
                              goto gen_builtin_end;
                        }
                  }

                  vm_abort(0);

            gen_builtin_end:
                  break;

            case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ...            */
                                    /* op1 = arg count, val.a = method pointer    */

                  if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
                        um = iptr->sx.s23.s3.um;
                        md = um->methodref->parseddesc.md;
                        gen_PATCHER_INVOKESTATIC(cd, 0, md->paramslots, um);
                  }
                  else {
                        lm = iptr->sx.s23.s3.fmiref->p.method;
                        md = lm->parseddesc;
                        gen_INVOKESTATIC(cd, (Inst **) lm->stubroutine, md->paramslots, lm);
                  }
                  break;

            case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */

                  if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
                        um = iptr->sx.s23.s3.um;
                        md = um->methodref->parseddesc.md;
                        gen_PATCHER_INVOKESPECIAL(cd, 0, md->paramslots, um);
                  }
                  else {
                        lm = iptr->sx.s23.s3.fmiref->p.method;
                        md = lm->parseddesc;
                        gen_INVOKESPECIAL(cd, (Inst **) lm->stubroutine, md->paramslots, lm);
                  }
                  break;

            case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer    */

                  if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
                        um = iptr->sx.s23.s3.um;
                        md = um->methodref->parseddesc.md;
                        gen_PATCHER_INVOKEVIRTUAL(cd, 0, md->paramslots, um);
                  }
                  else {
                        lm = iptr->sx.s23.s3.fmiref->p.method;
                        md = lm->parseddesc;

                        s1 = OFFSET(vftbl_t, table[0]) +
                              sizeof(methodptr) * lm->vftblindex;

                        gen_INVOKEVIRTUAL(cd, s1, md->paramslots, lm);
                  }
                  break;

            case ICMD_INVOKEINTERFACE:/* op1 = arg count, val.a = method pointer  */

                  if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
                        um = iptr->sx.s23.s3.um;
                        md = um->methodref->parseddesc.md;
                        gen_PATCHER_INVOKEINTERFACE(cd, 0, 0, md->paramslots, um);
                  }
                  else {
                        lm = iptr->sx.s23.s3.fmiref->p.method;
                        md = lm->parseddesc;

                        s1 = OFFSET(vftbl_t, interfacetable[0]) -
                              sizeof(methodptr*) * lm->clazz->index;

                        s2 = sizeof(methodptr) * (lm - lm->clazz->methods);

                        gen_INVOKEINTERFACE(cd, s1, s2, md->paramslots, lm);
                  }
                  break;


            case ICMD_CHECKCAST:  /* ..., objectref ==> ..., objectref            */
                                  /* op1:   0 == array, 1 == class                */
                                  /* val.a: (classinfo *) superclass              */

                  if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
                        if (INSTRUCTION_IS_UNRESOLVED(iptr))
                              gen_PATCHER_CHECKCAST(cd, NULL, iptr->sx.s23.s3.c.ref);
                        else
                              gen_CHECKCAST(cd, iptr->sx.s23.s3.c.cls, NULL);
                  }
                  else {
                        if (INSTRUCTION_IS_UNRESOLVED(iptr))
                              gen_PATCHER_ARRAYCHECKCAST(cd, NULL, iptr->sx.s23.s3.c.ref);
                        else
                              gen_ARRAYCHECKCAST(cd, iptr->sx.s23.s3.c.cls, NULL);
                  }
                  break;

            case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult            */
                                  /* op1:   0 == array, 1 == class                */
                                  /* val.a: (classinfo *) superclass              */

                  if (INSTRUCTION_IS_UNRESOLVED(iptr))
                        gen_PATCHER_INSTANCEOF(cd, NULL, iptr->sx.s23.s3.c.ref);
                  else
                        gen_INSTANCEOF(cd, iptr->sx.s23.s3.c.cls, iptr->sx.s23.s3.c.ref);
                  break;

            case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref  */
                                  /* op1 = dimension, val.a = class               */

                  if (INSTRUCTION_IS_UNRESOLVED(iptr))
                        gen_PATCHER_MULTIANEWARRAY(cd, NULL, iptr->s1.argcount, iptr->sx.s23.s3.c.ref);
                  else
                        gen_MULTIANEWARRAY(cd, iptr->sx.s23.s3.c.cls, iptr->s1.argcount, NULL);
                  break;

            default:
                  exceptions_throw_internalerror("Unknown ICMD %d during code generation",
                                                               iptr->opc);
                  return false;
      } /* switch */
            
      } /* for instruction */

      gen_BBEND;

      } /* if (bptr->flags != BBDELETED) */
      } /* for basic block */

      dseg_createlinenumbertable(cd);

      codegen_finish(jd);

#ifdef VM_PROFILING
      vm_block_insert(jd->code->mcode + jd->code->mcodelength);
#endif

      /* branch resolving (walk through all basic blocks) */

      for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
            branchref *brefs;

            for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
                  gen_resolveanybranch(((u1*) jd->code->entrypoint) + brefs->branchpos,
                                       ((u1 *)jd->code->entrypoint) + bptr->mpc);
            }
      }

      /* everything's ok */

      return true;
}


/* createcompilerstub **********************************************************

   Creates a stub routine which calls the compiler.

   A stub consists of:

   +-------------+
   | codeinfo *  |
   +-------------+ <-- stub
   | codeptr     |
   +-------------+
   | framesize   |  (in ptrint units, does not include return address)
   +-------------+
   | TRANSLATE   |
   +-------------+
   | methodinfo  |
   +-------------+

   codeptr points either to TRANSLATE or to the translated threaded code

   all methods are called indirectly through methodptr

*******************************************************************************/

#define COMPILERSTUB_DATASIZE    2
#define COMPILERSTUB_CODESIZE    4

#define COMPILERSTUB_SIZE        COMPILERSTUB_DATASIZE + COMPILERSTUB_CODESIZE


u1 *intrp_createcompilerstub(methodinfo *m)
{
      Inst        *s;
      Inst        *d;
      codegendata *cd;
      s4           stackframesize;
      int32_t      dumpmarker;

      s = CNEW(Inst, COMPILERSTUB_SIZE);

      /* set data pointer and code pointer */

      d = s;
      s = s + COMPILERSTUB_DATASIZE;

      /* The codeinfo pointer is actually a pointer to the
         methodinfo. This fakes a codeinfo structure. */

      d[0] = (Inst *) m;
      d[1] = (Inst *) &d[0];                                    /* fake code->m */

      /* mark start of dump memory area */

      DMARKER;
      
      cd = DNEW(codegendata);
    cd->mcodeptr = (u1 *) s;
      cd->lastinstwithoutdispatch = ~0;
      cd->superstarts = NULL;

      genarg_ainst(cd, s + 2);

      if (m->flags & ACC_NATIVE) {
            stackframesize = m->parseddesc->paramslots;
      } 
      else {
            stackframesize = m->maxlocals;

#if defined(ENABLE_THREADS)
            if (checksync && code_is_synchronized(code))
                  stackframesize += 1;
#endif
      }

      genarg_i(cd, stackframesize);

      gen_BBSTART;
      gen_TRANSLATE(cd, m);
      gen_BBEND;
      
#ifdef VM_PROFILING
      vm_block_insert(cd->mcodeptr);
#endif

#if defined(ENABLE_STATISTICS)
      if (opt_stat)
            count_cstub_len += COMPILERSTUB_SIZE;
#endif

      /* release dump area */

      DRELEASE;
      
      return (u1 *) s;
}


#if defined(WITH_FFI)
static ffi_type *cacaotype2ffitype(s4 cacaotype)
{
      switch (cacaotype) {
      case TYPE_INT:
#if SIZEOF_VOID_P == 8
            return &ffi_type_sint64;
#else
            return &ffi_type_sint32;
#endif
      case TYPE_LNG:
            return &ffi_type_sint64;
      case TYPE_FLT:
            return &ffi_type_float;
      case TYPE_DBL:
            return &ffi_type_double;
      case TYPE_ADR:
            return &ffi_type_pointer;
      case TYPE_VOID:
            return &ffi_type_void;
      default:
            assert(false);
      }
}
#endif


/* native stub:
+---------+
|NATIVECALL|
+---------+
|methodinf|
+---------+
|function |
+---------+
|cif      |
+---------+
*/

#if defined(WITH_FFI)
static ffi_cif *createnativecif(methodinfo *m, methoddesc *nmd)
{
      methoddesc  *md = m->parseddesc; 
      ffi_cif     *pcif = NEW(ffi_cif);
      ffi_type   **types = MNEW(ffi_type *, nmd->paramcount);
      ffi_type   **ptypes = types;
      s4           i;

      /* pass env pointer */

      *ptypes++ = &ffi_type_pointer;

      /* for static methods, pass class pointer */

      if (m->flags & ACC_STATIC)
            *ptypes++ = &ffi_type_pointer;

      /* pass parameter to native function */

      for (i = 0; i < md->paramcount; i++)
            *ptypes++ = cacaotype2ffitype(md->paramtypes[i].type);

      assert(ptypes - types == nmd->paramcount);

    if (ffi_prep_cif(pcif, FFI_DEFAULT_ABI, nmd->paramcount, cacaotype2ffitype(md->returntype.type), types) != FFI_OK)
            assert(0);

      return pcif;
}
#endif


u1 *intrp_createnativestub(functionptr f, jitdata *jd, methoddesc *nmd)
{
      methodinfo   *m;
      codeinfo     *code;
      codegendata  *cd;
      registerdata *rd;
#if defined(WITH_FFI)
      ffi_cif *cif;
#else
      u1      *cif;
#endif
      s4            stackframesize;

      /* get required compiler data */

      m    = jd->m;
      code = jd->code;
      cd   = jd->cd;
      rd   = jd->rd;

      /* determine stackframe size (in units of ptrint) */

      stackframesize = nmd->paramslots;

      /* create method header */

      (void) dseg_add_unique_address(cd, code);              /* CodeinfoPointer */
      (void) dseg_add_unique_s4(cd, stackframesize * SIZEOF_VOID_P); /*FrameSize*/
      (void) dseg_add_unique_s4(cd, 0);                       /* IsSync         */
      (void) dseg_add_unique_s4(cd, 0);                       /* IsLeaf         */
      (void) dseg_add_unique_s4(cd, 0);                       /* IntSave        */
      (void) dseg_add_unique_s4(cd, 0);                       /* FltSave        */
      dseg_addlinenumbertablesize(cd);
      (void) dseg_add_unique_s4(cd, 0);                       /* ExTableSize    */

#if defined(WITH_FFI)
      /* prepare ffi cif structure */

      cif = createnativecif(m, nmd);
#else
      cif = NULL;
#endif

      gen_BBSTART;

      if (opt_verbosecall)
            gen_TRACECALL(cd, m);

      if (f == NULL) {
            gen_PATCHER_NATIVECALL(cd, m, f, (u1 *)cif);
      } else {
            if (opt_verbosecall)
                  gen_TRACENATIVECALL(cd, m, f, (u1 *)cif);
            else
                  gen_NATIVECALL(cd, m, f, (u1 *)cif);
      }

      gen_BBEND;

      codegen_finish(jd);

#ifdef VM_PROFILING
      vm_block_insert(jd->code->mcode + jd->code->mcodelength);
#endif

      return jd->code->entrypoint;
}


/* call jni function */
Cell *nativecall(functionptr f, methodinfo *m, Cell *sp, Inst *ra, Cell *fp, u1 *addrcif)
{
#if defined(WITH_FFCALL)
      av_alist alist;
      methoddesc *md;
      Cell *p;
      Cell *endsp;
      s4 i;

      struct {
            stackframeinfo sfi;
            localref_table lrt;
      } s;

      md = m->parseddesc;

      switch (md->returntype.type) {
      case TYPE_INT:
            endsp = sp - 1 + md->paramslots;
            av_start_long(alist, f, endsp);
            break;
      case TYPE_LNG:
            endsp = sp - 2 + md->paramslots;
            av_start_longlong(alist, f, endsp);
            break;
      case TYPE_FLT:
            endsp = sp - 1 + md->paramslots;
            av_start_float(alist, f, endsp);
            break;
      case TYPE_DBL:
            endsp = sp - 2 + md->paramslots;
            av_start_double(alist, f, endsp);
            break;
      case TYPE_ADR:
            endsp = sp - 1 + md->paramslots;
            av_start_ptr(alist, f, void *, endsp);
            break;
      case TYPE_VOID:
            endsp = sp + md->paramslots;
            av_start_void(alist, f);
            break;
      default:
            assert(false);
      }

      av_ptr(alist, _Jv_JNIEnv *, _Jv_env);

      if (m->flags & ACC_STATIC)
            av_ptr(alist, classinfo *, m->clazz);

      for (i = 0, p = sp + md->paramslots; i < md->paramcount; i++) {
            switch (md->paramtypes[i].type) {
            case TYPE_INT:
                  p -= 1;
                  av_long(alist, *p);
                  break;
            case TYPE_LNG:
                  p -= 2;
                  av_longlong(alist, *(s8 *)p);
                  break;
            case TYPE_FLT:
                  p -= 1;
                  av_float(alist, *((float *) p));
                  break;
            case TYPE_DBL:
                  p -= 2;
                  av_double(alist, *(double *) p);
                  break;
            case TYPE_ADR:
                  p -= 1;
                  av_ptr(alist, void *, *(void **) p);
                  break;
            default:
                  assert(false);
            }
      }

      global_sp = sp;

      /* create stackframe info structure */

      codegen_start_native_call(((u1 *) &s) + sizeof(s), m->code->entrypoint,
                                            (u1 *) fp, (u1 *) ra);

      av_call(alist);

      *exceptionptr = codegen_finish_native_call(((u1 *) &s) + sizeof(s));

      CLEAR_global_sp;

      return endsp;
#elif defined(WITH_FFI)
      methoddesc  *md = m->parseddesc; 
      ffi_cif     *pcif;
      void        *values[md->paramcount + 2];
      void       **pvalues = values;
      Cell        *p;
      Cell        *endsp;
      s4           i;
      _Jv_JNIEnv  *penv;

      struct {
            stackframeinfo sfi;
            localref_table lrt;
      } s;

      pcif = (ffi_cif *) addrcif;

      /* pass env pointer */

      penv = (_Jv_JNIEnv *) _Jv_env;
      *pvalues++ = &penv;

      /* for static methods, pass class pointer */

      if (m->flags & ACC_STATIC)
            *pvalues++ = &m->clazz;

      /* pass parameter to native function */

      for (i = 0, p = sp + md->paramslots; i < md->paramcount; i++) {
            if (IS_2_WORD_TYPE(md->paramtypes[i].type))
                  p -= 2;
            else
                  p--;

            *pvalues++ = p;
      }

      /* calculate position of return value */

      if (md->returntype.type == TYPE_VOID)
            endsp = sp + md->paramslots;
      else
            endsp = sp - (IS_2_WORD_TYPE(md->returntype.type) ? 2 : 1) + md->paramslots;

      global_sp = sp;

      /* create stackframe info structure */

      codegen_start_native_call(((u1 *) &s) + sizeof(s), m->code->entrypoint,
                                            (u1 *) fp, (u1 *) ra);

      ffi_call(pcif, FFI_FN(f), endsp, values);

      *exceptionptr = codegen_finish_native_call(((u1 *) &s) + sizeof(s));

      CLEAR_global_sp;

      return endsp;
#endif
}


u1 *createcalljavafunction(methodinfo *m)
{
      methodinfo         *tmpm;
      u1                 *entrypoint;
      jitdata            *jd;
      codegendata        *cd;
      registerdata       *rd;
      methoddesc         *md;
      int32_t             dumpmarker;

      /* mark dump memory */

      DMARKER;

      /* allocate memory */

      jd = DNEW(jitdata);

      tmpm = DNEW(methodinfo);
      cd = DNEW(codegendata);
      rd = DNEW(registerdata);

      jd->m = tmpm;
      jd->flags = 0;
      jd->cd = cd;
      jd->rd = rd;

      /* Allocate codeinfo memory from the heap as we need to keep them. */

      jd->code = code_codeinfo_new(tmpm); /* XXX check allocation */

      /* setup code generation stuff */

      MSET(tmpm, 0, u1, sizeof(methodinfo));

      codegen_setup(jd);

      md = m->parseddesc;

      /* create method header */

      (void) dseg_add_unique_address(cd, NULL);              /* CodeinfoPointer */
      (void) dseg_add_unique_s4(cd, md->paramslots * SIZEOF_VOID_P);/* FrameSize*/
      (void) dseg_add_unique_s4(cd, 0);                       /* IsSync         */
      (void) dseg_add_unique_s4(cd, 0);                       /* IsLeaf         */
      (void) dseg_add_unique_s4(cd, 0);                       /* IntSave        */
      (void) dseg_add_unique_s4(cd, 0);                       /* FltSave        */
      dseg_addlinenumbertablesize(cd);
      (void) dseg_add_unique_s4(cd, 0);                       /* ExTableSize    */


      /* generate code */
      
      gen_BBSTART;
      gen_INVOKESTATIC(cd, (Inst **)m->stubroutine, md->paramslots, 0);
      gen_END(cd);

      gen_BBEND;

      codegen_finish(jd);

#ifdef VM_PROFILING
      vm_block_insert(jd->code->mcode + jd->code->mcodelength);
#endif
      entrypoint = jd->code->entrypoint;

      /* release memory */

      DRELEASE;

      return entrypoint;
}


/*
 * 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:
 */

Generated by  Doxygen 1.6.0   Back to index