/*
 * kaffe.def
 * Kaffe instruction definitions.
 * Used by intrp, JIT and JIT3 engines.
 *
 * Copyright (c) 1996, 1997, 1999, 2000
 *	Transvirtual Technologies, Inc.  All rights reserved.
 *
 * See the file "license.terms" for information on usage and redistribution 
 * of this file. 
 */

/* 
 * This file has been modified by JJC, for its use as part of his debugger, bdbj.
 * Modifications are delimited by START JJC, END JJC blocks and single lines
 * modified are marked by simply JJC.
 *
 * Last modified August 2002.
 */

#define trace_jcode(x)	DBG(MOREJIT, dprintf ("@%d:\t", pc); dprintf x;)

define_insn(NOP)
{
        /*
         * No operation.
         */
	trace_jcode (("nop\n"));
}

define_insn(ACONST_NULL)
{
	/*
	 * ... -> ..., 0
	 */
	trace_jcode (("aconst 0\n"));

	push(1);
	move_ref_const(stack(0), 0);
	markisobj; /* JJC */
}

define_insn(ICONST_M1)
define_insn_alias(ICONST_0)
define_insn_alias(ICONST_1)
define_insn_alias(ICONST_2)
define_insn_alias(ICONST_3)
define_insn_alias(ICONST_4)
define_insn_alias(ICONST_5)
{
	/*
	 * ... -> ..., [-1 .. 5]
	 */
	trace_jcode (("iconst %d\n", getopcode() - ICONST_0));	

	push(1);
	move_int_const(stack(0), getopcode() - ICONST_0);

	marknotobj_int; /* JJC */
}

define_insn(LCONST_0)
define_insn_alias(LCONST_1)
{
	/*
	 * ... -> ..., 0, [0 .. 1]
	 */
	trace_jcode (("lconst %d\n", getopcode() - LCONST_0));	

	push(2);
	move_long_const(stack_long(0), getopcode() - LCONST_0);
	marknotobj2_long; /* JJC */
}

define_insn(FCONST_0)
define_insn_alias(FCONST_1)
define_insn_alias(FCONST_2)
{
	/*
	 * ... -> ..., [0.0 .. 2.0]
	 */
	trace_jcode (("fconst %f\n", (double)(jfloat)(getopcode() - FCONST_0)));	

	push(1);
	move_float_const(stack(0), (jfloat)(getopcode() - FCONST_0));
	marknotobj_float; /* JJC */
}

define_insn(DCONST_0)
define_insn_alias(DCONST_1)
{
	/*
	 * ... -> ..., [0.0 .. 1.0]
	 */
	trace_jcode (("dconst %f\n", (double)(jdouble)(getopcode() - DCONST_0)));	

	push(2);
	move_double_const(stack_double(0), (jdouble)(getopcode() - DCONST_0));
	marknotobj2_double; /* JJC */
}

define_insn(BIPUSH)
{
	/*
	 * ... -> ..., val
	 */
	check_pc (0);

	low = (int8)getpc(0);
	trace_jcode (("bipush %d\n", low));

	push(1);
	move_int_const(stack(0), low);
	marknotobj_int; /* JJC */
}

define_insn(SIPUSH)
{
	/*
	 * ... -> ..., val
	 */
	check_pcidx (0);

	low = (int16)((getpc(0) << 8) | getpc(1));
	trace_jcode (("sipush %d\n", low));

	push(1);
	move_int_const(stack(0), low);
	marknotobj_int; /* JJC */
}

define_insn(LDC1)
{
	/*
	 * ... -> ..., const
	 */
	check_pc (0);

	idx = (uint8)getpc(0);
	trace_jcode (("ldc1 %d\n", idx));

	push(1);
	low = CLASS_CONST_TAG(current_class(), idx);
	switch (low) {
	case CONSTANT_String:
		{
			errorInfo ei;
			void *s;

			s = resolveString(current_class(), idx, &ei);
			if (s == 0) {
				compile_time_error(ei);
			}
			move_string_const(stack(0), s);
			markisobj; /* JJC/ */
		}
		break;
	case CONSTANT_ResolvedString:
		move_string_const(stack(0), (void*)CLASS_CONST_DATA(current_class(),idx));
		markisobj; /* JJC */
		break;
	case CONSTANT_Float:
		move_float_const(stack(0), *(float*)&CLASS_CONST_DATA(current_class(),idx));
		marknotobj_float; /* JJC */
		break;
	case CONSTANT_Integer:
		move_int_const(stack(0), CLASS_CONST_DATA(current_class(),idx));
		marknotobj_int; /* JJC */ 
		break;
	default:
		ABORT();
	}
}

define_insn(LDC2)
{
	/*
	 * ... -> ..., const
	 */
	check_pcidx (0);

	idx = (uint16)((getpc(0) << 8) | getpc(1));
	trace_jcode (("ldc2 %d\n", idx));

	push(1);
	low = CLASS_CONST_TAG(current_class(), idx);
	switch (low) {
	case CONSTANT_String:
		{
			errorInfo ei;
			void *s;

			s = resolveString(current_class(), idx, &ei);
			if (s == 0) {
				compile_time_error(ei);
			}
			move_string_const(stack(0), s);
			markisobj; /* JJC */
		}
		break;
	case CONSTANT_ResolvedString:
		move_string_const(stack(0), (void*)CLASS_CONST_DATA(current_class(),idx));
		markisobj; /* JJC */
		break;
	case CONSTANT_Float:
		move_float_const(stack(0), *(jfloat*)&CLASS_CONST_DATA(current_class(),idx));
		marknotobj_float; /* JJC */
		break;
	case CONSTANT_Integer:
		move_int_const(stack(0), CLASS_CONST_DATA(current_class(),idx));
		marknotobj_int; /* JJC */
		break;
	default:
		ABORT();
	}
}

define_insn(LDC2W)
{
	/*
	 * ... -> ..., long const
	 */
	check_pcidx (0);

	idx = (uint16)((getpc(0) << 8) | getpc(1));
	trace_jcode (("ldc2w %d\n", idx));

	push(2);
	switch (CLASS_CONST_TAG(current_class(), idx)) {
	case CONSTANT_Long:
		tmpl.j = CLASS_CONST_LONG (current_class(), idx);
		move_long_const(stack_long(0), tmpl.j);
		marknotobj2_long; /* JJC */
		break;
	case CONSTANT_Double:
		tmpl.j = CLASS_CONST_DOUBLE (current_class(), idx);
		move_double_const(stack_double(0), tmpl.d);
		marknotobj2_double; /* JJC */
		break;
	default:
		ABORT();
	}
}

define_insn(ILOAD)
{
	/*
	 * ..., -> ..., local variable
	 */
	check_pc (0);
	idx = (uint8)getpc(0);
	trace_jcode (("iload %d\n", idx));

	check_local_int(idx);

	push(1);
	move_int(stack(0), local(idx));
	marknotobj_int; /* JJC */
}

define_insn(LLOAD)
{
	/*
	 * ..., -> ..., long local variable
	 */
	check_pc (0);
	idx = (uint8)getpc(0);
	trace_jcode (("lload %d\n", idx));

	check_local_long(idx+1);

	push(2);
	move_long(stack_long(0), local_long(idx));
	marknotobj2_long; /* JJC */
}

define_insn(FLOAD)
{
	/*
	 * ..., -> ..., local variable
	 */
	check_pc (0);
	idx = (uint8)getpc(0);
	trace_jcode (("fload %d\n", idx));

	check_local_float(idx);

	push(1);
	move_float(stack(0), local_float(idx));
	marknotobj_float; /* JJC */
}

define_insn(DLOAD)
{
	/*
	 * ..., -> ..., double local variable
	 */
	check_pc (0);
	idx = (uint8)getpc(0);
	trace_jcode (("dload %d\n", idx));

	check_local_double(idx+1);

	push(2);
	move_double(stack_double(0), local_double(idx));
	marknotobj2_double; /* JJC */
}

define_insn(ALOAD)
{
	/*
	 * ..., -> ..., local variable
	 */
	check_pc (0);
	idx = (uint8)getpc(0);
	trace_jcode (("aload %d\n", idx));

	check_local_ref(idx);
	push(1);
	move_ref(stack(0), local(idx));
	/* START JJC */
	if( valid_log )
	  if( opsobjs )
	    *opsobjs = lvtobjs[ idx ];
	/* END JJC */
}

define_insn(ILOAD_0)
define_insn_alias(ILOAD_1)
define_insn_alias(ILOAD_2)
define_insn_alias(ILOAD_3)
{
	/*
	 * ..., -> ..., local variable
	 */
	trace_jcode (("iload %d\n", getopcode() - ILOAD_0));

	check_local_int(getopcode() - ILOAD_0);

	push(1);
	move_int(stack(0), local(getopcode() - ILOAD_0));
	marknotobj_int; /* JJC */
}

define_insn(LLOAD_0)
define_insn_alias(LLOAD_1)
define_insn_alias(LLOAD_2)
define_insn_alias(LLOAD_3)
{
	/*
	 * ..., -> ..., local variable
	 */
	trace_jcode (("lload %d\n", getopcode() - LLOAD_0));

	check_local_long((getopcode() - LLOAD_0)+1);

	push(2);
	move_long(stack_long(0), local_long(getopcode() - LLOAD_0));
	marknotobj2_long; /* JJC */
}

define_insn(FLOAD_0)
define_insn_alias(FLOAD_1)
define_insn_alias(FLOAD_2)
define_insn_alias(FLOAD_3)
{
	/*
	 * ..., -> ..., local variable
	 */
	trace_jcode (("fload %d\n", getopcode() - FLOAD_0));

	check_local_float(getopcode() - FLOAD_0);

	push(1);
	move_float(stack(0), local_float(getopcode() - FLOAD_0));
	marknotobj_float; /* JJC */
}

define_insn(DLOAD_0)
define_insn_alias(DLOAD_1)
define_insn_alias(DLOAD_2)
define_insn_alias(DLOAD_3)
{
	/*
	 * ..., -> ..., local variable
	 */
	trace_jcode (("dload %d\n", getopcode() - DLOAD_0));

	check_local_double((getopcode() - DLOAD_0)+1);

	push(2);
	move_double(stack_double(0), local_double(getopcode() - DLOAD_0));
	marknotobj2_double; /* JJC */
}

define_insn(ALOAD_0)
define_insn_alias(ALOAD_1)
define_insn_alias(ALOAD_2)
define_insn_alias(ALOAD_3)
{
	/*
	 * ..., -> ..., local variable
	 */
	trace_jcode (("aload %d\n", getopcode() - ALOAD_0));

	check_local_ref(getopcode() - ALOAD_0);

	push(1);
	move_ref(stack(0), local(getopcode() - ALOAD_0));
	/* START JJC */
	if( valid_log )
	  if( opsobjs )
	    *opsobjs = lvtobjs[ getopcode() - ALOAD_0 ];
	/* END JJC */
}

define_insn(IALOAD)
{
	/*
	 * ..., array ref, index -> ..., value
	 */
	trace_jcode (("iaload\n"));

	check_stack_int(0);
	check_stack_intarray(1);

	check_null (IALOAD, rstack(1), 34);

	/* Check we are within the array bounds */
	check_array_index(rstack(1), rstack(0));

	load_offset_scaled_int(stack(1), rstack(1), rstack(0), object_array_offset);
	pop(1);
	marknotobj_int; /* JJC */
}

define_insn(LALOAD)
{
	/*
	 * ..., array ref, index -> ..., long value
	 */
	trace_jcode (("laload\n"));

	check_stack_int(0);
	check_stack_longarray(1);

	check_null (LALOAD, stack(1), 34);

	/* Check we are within the array bounds */
	check_array_index(rstack(1), rstack(0));

	load_offset_scaled_long(stack_long(0), stack(1), stack(0), object_array_offset);
	marknotobj2_long; /* JJC */
}

define_insn(FALOAD)
{
	/*
	 * ..., array ref, index -> ..., float value
	 */
	trace_jcode (("faload\n"));

	check_stack_int(0);
	check_stack_floatarray(1);

	check_null (FALOAD, stack(1), 34);

	/* Check we are within the array bounds */
	check_array_index(rstack(1), rstack(0));

	load_offset_scaled_float(stack_float(1), stack(1), stack(0), object_array_offset);

	pop(1);
	marknotobj_float; /* JJC */
}

define_insn(DALOAD)
{
	/*
	 * ..., array ref, index -> ..., double value
	 */
	trace_jcode (("daload\n"));

	check_stack_int(0);
	check_stack_doublearray(1);

	check_null (DALOAD, stack(1), 34);

	/* Check we are within the array bounds */
	check_array_index(rstack(1), rstack(0));

	load_offset_scaled_double(stack_double(0), stack(1), stack(0), object_array_offset);
	marknotobj2_double; /* JJC */
}

define_insn(AALOAD)
{
	/*
	 * ..., array ref, index -> ..., ref value
	 */
	trace_jcode (("aaload\n"));

	check_stack_int(0);
	check_stack_refarray(1);

	check_null(AALOAD, rstack(1), 34);

	/* Check we are within the array bounds */
	check_array_index(rstack(1), rstack(0));

	/* START JJC */
	if( valid_log )
	  oldopsobjs = ( strncmp( CLASS_ELEMENT_TYPE(OBJECT_CLASS((Hjava_lang_Object*)(stack(1)[0].v.taddr)))->name->data, "Lkaffe/util/Ptr;", 16 ) == 0 ) ? NOTSUREOBJ : ISOBJ;
	/* END JJC */
	
	load_offset_scaled_ref(stack(1), rstack(1), rstack(0), object_array_offset);
	pop(1);

	/* START JJC */
	if( valid_log ) {
	  if( oldopsobjs == 0 )
	    *opsobjs = oldopsobjs;
	}
	/* END JJC */

}

define_insn(BALOAD)
{
	/*
	 * ..., array ref, index -> ..., byte value
	 */
	trace_jcode (("baload\n"));

	check_stack_int(0);
	check_stack_bytearray(1);

	check_null(BALOAD, rstack(1), 34);

	/* Check we are within the array bounds */
	check_array_index(rstack(1), rstack(0));

	load_offset_scaled_byte(stack(1), rstack(1), rstack(0), object_array_offset);
	pop(1);
	marknotobj_int; /* JJC */
}

define_insn(CALOAD)
{
	/*
	 * ..., array ref, index -> ..., char value
	 */
	trace_jcode (("caload\n"));

	check_stack_int(0);
	check_stack_chararray(1);

	check_null(CALOAD, rstack(1), 34);

	/* Check we are within the array bounds */
	check_array_index(rstack(1), rstack(0));

	load_offset_scaled_char(stack(1), rstack(1), rstack(0), object_array_offset);
	pop(1);
	marknotobj_int; /* JJC */
}

define_insn(SALOAD)
{
	/*
	 * ..., array ref, index -> ..., short value
	 */
	trace_jcode (("saload\n"));

	check_stack_int(0);
	check_stack_shortarray(1);

	check_null(SALOAD, rstack(1), 34);

	/* Check we are within the array bounds */
	check_array_index(rstack(1), rstack(0));

	load_offset_scaled_short(stack(1), rstack(1), rstack(0), object_array_offset);
	pop(1);
	marknotobj_int; /* JJC */
}

define_insn(ISTORE)
{
	/*
	 * ..., var -> ...
	 */
	check_pc (0);
	idx = (uint8)getpc(0);
	trace_jcode (("istore %d\n", idx));

	check_stack_int(0);

	if( valid_log ) wcbuffs( local( idx )[ 0 ], opsobjs ? lvtobjs[ idx ] : 0, debug, thr ); /* JJC */
	move_int(local(idx), stack(0));
	if( opsobjs ) lvtobjs[ idx ] = NOTOBJ_INT; /* JJC */
	pop(1);
}

define_insn(LSTORE)
{
	/*
	 * ..., long var -> ...
	 */
	check_pc (0);
	idx = (uint8)getpc(0);
	trace_jcode (("lstore %d\n", idx));

	check_stack_long(0);

	/* move_long(local_long(idx), stack_long(0)); */
	swap_long( local_long( idx ), stack_long( 0 ) ); /* JJC */
	/* START JJC */
	if( opsobjs ) {
	  *( opsobjs - 1 ) = lvtobjs[ idx ];
	  *opsobjs = lvtobjs[ idx + 1 ];
	  /*  *( opsobjs - 1 ) = *opsobjs = lvtobjs[ idx ]; */
	  lvtobjs[ idx ] = NOTOBJ_LONG;
	  lvtobjs[ idx + 1 ] = NOTOBJ_SKIP;
	}
	/* END JJC */
	if( valid_log ) savestack( 2 );                  /* JJC */
	
	pop(2);

}

define_insn(FSTORE)
{
	/*
	 * ..., var -> ...
	 */
	check_pc (0);
	idx = (uint8)getpc(0);
	trace_jcode (("fstore %d\n", idx));

	check_stack_float(0);

	if( valid_log ) wcbuffs( local( idx )[ 0 ], opsobjs ? lvtobjs[ idx ] : 0, debug, thr ); /* JJC */
	move_float(local_float(idx), stack(0)); 
	if( opsobjs ) lvtobjs[ idx ] = NOTOBJ_FLOAT; /* JJC */
	pop(1);
}

define_insn(DSTORE)
{
	/*
	 * ..., var -> ...
	 */
	check_pc (0);
	idx = (uint8)getpc(0);
	trace_jcode (("dstore %d\n", idx));

	check_stack_double(0);

	/* move_double(local_double(idx), stack_double(0)); */
	swap_long( local_double( idx ), stack_double( 0 ) ); /* JJC */
	/* START JJC */
	if( opsobjs ) {
	  *( opsobjs - 1 ) = lvtobjs[ idx ]; 
	  *opsobjs = lvtobjs[ idx + 1 ];
	  lvtobjs[ idx ] = NOTOBJ_DOUBLE;
	  lvtobjs[ idx + 1 ] = NOTOBJ_SKIP;
	}
	/* END JJC */
	if( valid_log ) savestack( 2 );                      /* JJC */
	
	pop(2);
}

define_insn(ASTORE)
{
	/*
	 * ..., var -> ...
	 */
	check_pc (0);
	idx = (uint8)getpc(0);
	trace_jcode (("astore %d\n", idx));

	check_stack_ref(0);

	/* move_ref(local(idx), stack(0)); */
	
	/* START JJC */
	swap_any( local( idx ), stack( 0 ) );    
	if( opsobjs ) {
	  oldopsobjs = *opsobjs;
	  *opsobjs = lvtobjs[ idx ];
	  if( local( idx )[ 0 ].v.tint <= 0xFFFF )	
	    lvtobjs[ idx ] = 0; /* almost certainly a return address */
	  else
	    lvtobjs[ idx ] = oldopsobjs;
	}
	if( valid_log ) savestack( 1 );       
	/* END JJC */
	
	pop(1);
}

define_insn(ISTORE_0)
define_insn_alias(ISTORE_1)
define_insn_alias(ISTORE_2)
define_insn_alias(ISTORE_3)
{
	/*
	 * ..., val -> ...
	 */
	trace_jcode (("istore %d\n", getopcode() - ISTORE_0));

	check_stack_int(0);
	if( valid_log ) wcbuffs( local( getopcode() - ISTORE_0 )[ 0 ], opsobjs ?      /* JJC */
				 lvtobjs[ getopcode() - ISTORE_0 ] : 0, debug, thr ); /* JJC */
	move_int(local(getopcode() - ISTORE_0), stack(0));
	if( opsobjs ) lvtobjs[ getopcode() - ISTORE_0 ] = NOTOBJ_INT; /* JJC */	
	pop(1);
}

define_insn(LSTORE_0)
define_insn_alias(LSTORE_1)
define_insn_alias(LSTORE_2)
define_insn_alias(LSTORE_3)
{
	/*
	 * ..., long val -> ...
	 */
	trace_jcode (("lstore %d\n", getopcode() - LSTORE_0));

	check_stack_long(0);

	/* move_long(local_long(getopcode() - LSTORE_0), stack_long(0)); removed by JJC */
	swap_long(local_long(getopcode() - LSTORE_0), stack_long(0)); /* JJC */
	/* START JJC */
	if( opsobjs ) {
	  *( opsobjs - 1 ) = lvtobjs[ getopcode() - LSTORE_0 ]; 
	  *opsobjs = lvtobjs[ getopcode() - LSTORE_0 + 1 ];
	  
	  lvtobjs[ getopcode() - LSTORE_0 ] = NOTOBJ_LONG;
	  lvtobjs[ getopcode() - LSTORE_0 + 1 ] = NOTOBJ_SKIP;
	}
	/* END JJC */
	
	if( valid_log ) savestack( 2 ); /* JJC */
	
	pop(2);
}

define_insn(FSTORE_0)
define_insn_alias(FSTORE_1)
define_insn_alias(FSTORE_2)
define_insn_alias(FSTORE_3)
{
	/*
	 * ..., val -> ...
	 */
	trace_jcode (("fstore %d\n", getopcode() - FSTORE_0));

	check_stack_float(0);

	/* move_float(local_float(getopcode() - FSTORE_0), stack(0)); removed by JJC */
	swap_any(local_float(getopcode() - FSTORE_0), stack(0)); /* JJC */
	/* START JJC */
	if( opsobjs ) {
	  *opsobjs = lvtobjs[ getopcode() - FSTORE_0 ];
	  lvtobjs[ getopcode() - FSTORE_0 ] = NOTOBJ_FLOAT;
	}
	/* END JJC */
	if( valid_log ) savestack( 1 ); /* JJC */
	pop(1);      
}

define_insn(DSTORE_0)
define_insn_alias(DSTORE_1)
define_insn_alias(DSTORE_2)
define_insn_alias(DSTORE_3)
{
	/*
	 * ..., double val -> ...
	 */
	trace_jcode (("dstore %d\n", getopcode() - DSTORE_0));

	check_stack_double(0);

	/* move_double(local_double(getopcode() - DSTORE_0), stack_double(0)); removed by JJC */
	swap_long(local_double(getopcode() - DSTORE_0), stack_double(0)); /* JJC */
	/* START JJC */
	if( opsobjs ) {
	  *( opsobjs - 1 ) = lvtobjs[ getopcode() - DSTORE_0 ];
	  *opsobjs = lvtobjs[ getopcode() - DSTORE_0 + 1 ];
	  lvtobjs[ getopcode() - DSTORE_0 ] = NOTOBJ_DOUBLE;
	  lvtobjs[ getopcode() - DSTORE_0 + 1] = NOTOBJ_SKIP;
	}
	/* END JJC */
	if( valid_log ) savestack( 2 ); /* JJC */
	
	pop(2);
}

define_insn(ASTORE_0)
define_insn_alias(ASTORE_1)
define_insn_alias(ASTORE_2)
define_insn_alias(ASTORE_3)
{
	/*
	 * ..., val -> ...
	 */
	trace_jcode (("astore %d\n", getopcode() - ASTORE_0));

	check_stack_ref(0);

	/*move_ref(local(getopcode() - ASTORE_0), stack(0));*/
	
	/* START JJC */
	swap_any(local(getopcode() - ASTORE_0), stack(0)); /* JJC */
	if( opsobjs ) {
	  oldopsobjs = *opsobjs;
	  *opsobjs = lvtobjs[ getopcode() - ASTORE_0 ];
	  if( local(getopcode() - ASTORE_0)[ 0 ].v.tint <= 0xFFFF )
	    lvtobjs[ getopcode() - ASTORE_0 ] = 0; /* almost certainly a return address */
	  else
	    lvtobjs[ getopcode() - ASTORE_0 ] = oldopsobjs;
	}
	if( valid_log ) savestack( 1 ); 
	/* END JJC */
	
	pop(1);
}

define_insn(IASTORE)
{
	/*
	 * ..., array ref, index, val -> ...
	 */
	trace_jcode (("iastore\n"));

	check_stack_int(0);
	check_stack_int(1);
	check_stack_intarray(2);

	check_null(IASTORE, rstack(2), 34);

	/* Check we are within the array bounds */
	check_array_index(rstack(2), rstack(1));

	load_offset_scaled_int( tmp, stack( 2 ), stack( 1 ), object_array_offset ); /* JJC */
	store_offset_scaled_int(rstack(2), rstack(1), object_array_offset, rstack(0));
	move_int( stack( 0 ), tmp ); /* JJC */
	if( valid_log ) savestack( 3 );            /* JJC */

	pop(3);
}

define_insn(LASTORE)
{
	/*
	 * ..., array ref, index, long val -> ...
	 */
	trace_jcode (("lastore\n"));

	check_stack_int(0);
	check_stack_int(1);
	check_stack_longarray(2);

	check_null(LASTORE, stack(3), 34);

	/* Check we are within the array bounds */
	check_array_index(rstack(3), rstack(2));
	
	load_offset_scaled_long( tmp, stack( 3 ), stack( 2 ), object_array_offset ); /* JJC */
	store_offset_scaled_long(stack(3), stack(2), object_array_offset, stack_long(0));
	move_long( stack_long( 0 ), tmp ); /* JJC */
	if( valid_log ) savestack( 4 ); /* JJC */

	pop(4);
}

define_insn(FASTORE)
{
	/*
	 * ..., array ref, index, float val -> ...
	 */
	trace_jcode (("fastore\n"));

	check_stack_int(0);
	check_stack_int(1);
	check_stack_floatarray(2);

	check_null(FASTORE, stack(2), 34);

	/* Check we are within the array bounds */
	check_array_index(rstack(2), rstack(1));

	load_offset_scaled_float( tmp, stack( 2 ), stack( 1 ), object_array_offset ); /* JJC */
	store_offset_scaled_float(stack(2), stack(1), object_array_offset, stack(0));
	move_float( stack( 0 ), tmp ); /* JJC */
	if( valid_log ) savestack( 3 ); /* JJC */ 	
	
	pop(3);
}

define_insn(DASTORE)
{
	/*
	 * ..., array ref, index, double val -> ...
	 */
	trace_jcode (("dastore\n"));

	check_stack_int(0);
	check_stack_int(1);
	check_stack_doublearray(2);

	check_null(DASTORE, stack(3), 34);

	/* Check we are within the array bounds */
	check_array_index(rstack(3), rstack(2));

	load_offset_scaled_double( tmp, stack( 3 ), stack( 2 ), object_array_offset ); /* JJC */
	store_offset_scaled_double(stack(3), stack(2), object_array_offset, stack_double(0));
	move_double( stack_long( 0 ), tmp ); /* JJC */
	if( valid_log ) savestack( 4 ); /* JJC */

	pop(4);
}

define_insn(AASTORE)
{
	/*
	 * ..., array ref, index, val -> ...
	 */
	trace_jcode (("aastore\n"));

	check_stack_int(0);
	check_stack_int(1);
	check_stack_refarray(2);

	check_null(AASTORE, rstack(2), 34);

	/* Check we are within the array bounds */
	check_array_index(rstack(2), rstack(1));

	check_array_store(rstack(2), rstack(0));

	SOFT_ADDREFERENCE(rstack(2), rstack(0));


	load_offset_scaled_ref( tmp, stack( 2 ), stack( 1 ), object_array_offset ); /* JJC */
	store_offset_scaled_ref(rstack(2), rstack(1), object_array_offset, rstack(0));

	move_ref( stack( 0 ), tmp ); /* JJC */
	/* START JJC */
	if( valid_log ) {
	  if( strncmp( CLASS_ELEMENT_TYPE(OBJECT_CLASS((Hjava_lang_Object*)(stack(2)[0].v.taddr)))->name->data, "Lkaffe/util/Ptr;", 16 ) == 0 ) {
	    markunknown;
	  }
	  savestack( 3 ); 
	}
	/* END JJC */
	pop(3);
}

define_insn(BASTORE)
{
	/*
	 * ..., array ref, index, byte value  -> ...
	 */
	trace_jcode (("bastore\n"));

	check_stack_int(0);
	check_stack_int(1);
	check_stack_bytearray(2);

	check_null(BASTORE, rstack(2), 34);

	/* Check we are within the array bounds */
	check_array_index(rstack(2), rstack(1));

	load_offset_scaled_byte( tmp, stack( 2 ), stack( 1 ), object_array_offset ); /* JJC */
	store_offset_scaled_byte(rstack(2), rstack(1), object_array_offset, rstack(0));
	move_int( stack( 0 ), tmp ); /* JJC */
	if( valid_log ) savestack( 3 ); /* JJC */

	pop(3);
}

define_insn(CASTORE)
{
	/*
	 * ..., array ref, index, char value  -> ...
	 */
	trace_jcode (("castore\n"));

	check_stack_int(0);
	check_stack_int(1);
	check_stack_chararray(2);

	check_null(CASTORE, rstack(2), 34);

	/* Check we are within the array bounds */
	check_array_index(rstack(2), rstack(1));

	load_offset_scaled_char( tmp, stack( 2 ), stack( 1 ), object_array_offset ); /* JJC */
	
	store_offset_scaled_char(rstack(2), rstack(1), object_array_offset, rstack(0));
	
	move_int( stack( 0 ), tmp ); /* JJC */
	if( valid_log ) savestack( 3 ); /* JJC */
	pop(3);
}

define_insn(SASTORE)
{
	/*
	 * ..., array ref, index, short value  -> ...
	 */
	trace_jcode (("sastore\n"));

	check_stack_int(0);
	check_stack_int(1);
	check_stack_shortarray(2);

	check_null(SASTORE, rstack(2), 34);

	/* Check we are within the array bounds */
	check_array_index(rstack(2), rstack(1));

	load_offset_scaled_short( tmp, stack( 2 ), stack( 1 ), object_array_offset ); /* JJC */
	store_offset_scaled_short(rstack(2), rstack(1), object_array_offset, rstack(0));
	move_int( stack( 0 ), tmp ); /* JJC */
	if( valid_log ) savestack( 3 ); /* JJC */

	pop(3);
}

define_insn(POP)
{
    	/*
	 * ..., slot -> ...
	 */
	trace_jcode (("pop\n"));

	pop(1);
}

define_insn(POP2)
{
    	/*
	 * ..., slot, slot -> ...
	 */
	trace_jcode (("pop2\n"));

	pop(2);
}

define_insn(DUP)
{
	trace_jcode (("dup\n"));

	push(1);
	move_any(stack(0), stack(1));
	if( opsobjs ) *opsobjs = *( opsobjs - 1); /* JJC */
}

define_insn(DUP_X1)
{
	trace_jcode (("dup_x1\n"));

	push(1);
	move_any(stack(0), stack(1));
	move_any(stack(1), stack(2));
	move_any(stack(2), stack(0));
	/* START JJC */
	if( opsobjs ) {
	  *opsobjs = *( opsobjs - 1 );
	  *( opsobjs - 1 ) = *( opsobjs - 2 );
	  *( opsobjs - 2 ) = *opsobjs;
	}
	/* END JJC */

}

define_insn(DUP_X2)
{
	trace_jcode (("dup_x2\n"));

	push(1);
	move_any(stack(0), stack(1));
	move_any(stack(1), stack(2));
	move_any(stack(2), stack(3));
	move_any(stack(3), stack(0));
	/* START JJC */
	if( opsobjs ) {
	  *opsobjs = *( opsobjs - 1 );
	  *( opsobjs - 1 ) = *( opsobjs - 2 );
	  *( opsobjs - 2 ) = *( opsobjs - 3 );
	  *( opsobjs - 3 ) = *opsobjs;
	}
	/* END JJC */
}

define_insn(DUP2)
{
	trace_jcode (("dup2\n"));

	push(2);
	move_any(stack(0), stack(2));
	move_any(stack(1), stack(3));
	/* START JJC */
	if( opsobjs ) {
	  *opsobjs = *( opsobjs - 2 );
	  *( opsobjs - 1 ) = *( opsobjs - 3 );
	}
	/* END JJC */
}

define_insn(DUP2_X1)
{
	trace_jcode (("dup2_x1\n"));

	push(2);
	move_any(stack(0), stack(2));
	move_any(stack(1), stack(3));
	move_any(stack(2), stack(4));
	move_any(stack(3), stack(0));
	move_any(stack(4), stack(1));
	/* START JJC */
	if( opsobjs ) {
	  *opsobjs = *( opsobjs - 2 );
	  *( opsobjs - 1 ) = *( opsobjs - 3 );
	  *( opsobjs - 2 ) = *( opsobjs - 4 );
	  *( opsobjs - 3 ) = *opsobjs;
	  *( opsobjs - 4 ) = *( opsobjs - 1 );
	}
	/* END JJC */
}

define_insn(DUP2_X2)
{
	trace_jcode (("dup2_x2\n"));

	push(2);
	move_any(stack(0), stack(2));
	move_any(stack(1), stack(3));
	move_any(stack(2), stack(4));
	move_any(stack(3), stack(5));
	move_any(stack(4), stack(0));
	move_any(stack(5), stack(1));

	/* START JJC */
	if( opsobjs ) {
	  *opsobjs = *( opsobjs - 2 );
	  *( opsobjs - 1 ) = *( opsobjs - 3 );
	  *( opsobjs - 2 ) = *( opsobjs - 4 );
	  *( opsobjs - 3 ) = *( opsobjs - 5 );
	  *( opsobjs - 4 ) = *opsobjs;
	  *( opsobjs - 5 ) = *( opsobjs - 1 );
	}
	/* END JJC */
}

define_insn(SWAP)
{
        /*
         * ..., val1, val2 -> ..., val2, val1
         */
	trace_jcode (("swap\n"));

	swap_any(stack(0), stack(1));
	/* START JJC */
	if( opsobjs ) {
	  int8 t = *opsobjs;
	  *opsobjs = *( opsobjs - 1 );
	  *( opsobjs - 1 ) = t;
	}
	/* END JJC */

}

define_insn(IADD)
{
        /*
         * ..., val1, val2 -> ..., val1+val2
         */
	trace_jcode (("iadd\n"));

	check_stack_int(0);
	check_stack_int(1);

	add_int(stack(1), rstack(1), rstack(0));
	pop(1);
}

define_insn(LADD)
{
        /*
         * ..., long val1, long val2 -> ..., long val1+val2
         */
	trace_jcode (("ladd\n"));

	check_stack_long(0);
	check_stack_long(2);

	slot_nowriteback2(stack_long(0));
	slot_nowriteback2(stack_long(2));

	add_long(stack_long(2), rstack_long(2), rstack_long(0));
	pop(2);
}

define_insn(FADD)
{
        /*
         * ..., val1, val2 -> ..., val1+val2
         */
	trace_jcode (("fadd\n"));

	check_stack_float(0);
	check_stack_float(1);

	add_float(stack_float(1), rstack_float(1), rstack_float(0));
	pop(1);
}

define_insn(DADD)
{
        /*
         * ..., double val1, long val2 -> ..., double val1+val2
         */
	trace_jcode (("dadd\n"));

	check_stack_double(0);
	check_stack_double(2);

	add_double(stack_double(2), rstack_double(2), rstack_double(0));
	pop(2);
}

define_insn(ISUB)
{
        /*
         * ..., val1, val2 -> ..., val1-val2
         */
	trace_jcode (("isub\n"));

	check_stack_int(0);
	check_stack_int(1);

	sub_int(stack(1), rstack(1), rstack(0));
	pop(1);
}

define_insn(LSUB)
{
        /*
         * ..., long val1, long val2 -> ..., long val1-val2
         */
	trace_jcode (("lsub\n"));

	check_stack_long(0);
	check_stack_long(2);

	slot_nowriteback2(stack_long(0));
	slot_nowriteback2(stack_long(2));

	sub_long(stack_long(2), rstack_long(2), rstack_long(0));
	pop(2);
}

define_insn(FSUB)
{
        /*
         * ..., val1, val2 -> ..., val1-val2
         */
	trace_jcode (("fsub\n"));

	check_stack_float(0);
	check_stack_float(1);

	sub_float(stack_float(1), rstack_float(1), rstack_float(0));
	pop(1);
}

define_insn(DSUB)
{
        /*
         * ..., double val1, long val2 -> ..., double val1-val2
         */
	trace_jcode (("dsub\n"));

	check_stack_double(0);
	check_stack_double(2);

	sub_double(stack_double(2), rstack_double(2), rstack_double(0));
	pop(2);
}

define_insn(IMUL)
{
        /*
         * ..., val1, val2 -> ..., val1*val2
         */
	trace_jcode (("imul\n"));

	check_stack_int(0);
	check_stack_int(1);

	mul_int(stack(1), rstack(1), rstack(0));
	pop(1);
}

define_insn(LMUL)
{
        /*
         * ..., long val1, long val2 -> ..., long val1*val2
         */
	trace_jcode (("lmul\n"));

	check_stack_long(0);
	check_stack_long(2);

	slot_nowriteback2(stack_long(0));
	slot_nowriteback2(stack_long(2));

	mul_long(stack_long(2), rstack_long(2), rstack_long(0));
	pop(2);
}

define_insn(FMUL)
{
        /*
         * ..., val1, val2 -> ..., val1*val2
         */
	trace_jcode (("fmul\n"));

	check_stack_float(0);
	check_stack_float(1);

	mul_float(stack_float(1), rstack_float(1), rstack_float(0));
	pop(1);
}

define_insn(DMUL)
{
        /*
         * ..., double val1, long val2 -> ..., double val1*val2
         */
	trace_jcode (("dmul\n"));

	check_stack_double(0);
	check_stack_double(2);

	mul_double(stack_double(2), rstack_double(2), rstack_double(0));
	pop(2);
}

define_insn(IDIV)
{
        /*
         * ..., val1, val2 -> ..., val1/val2
         */
	trace_jcode (("idiv\n"));

	check_stack_int(0);
	check_stack_int(1);

	check_div(IDIV, rstack(0), 1);

	div_int(stack(1), rstack(1), rstack(0));
	pop(1);
}

define_insn(LDIV)
{
        /*
         * ..., long val1, long val2 -> ..., long val1/val2
         */
	trace_jcode (("ldiv\n"));

	check_stack_long(0);
	check_stack_long(2);

	slot_nowriteback2(stack_long(0));
	slot_nowriteback2(stack_long(2));

	check_div_long(LDIV, rstack_long(0), 1);

	div_long(stack_long(2), rstack_long(2), rstack_long(0));
	pop(2);
}

define_insn(FDIV)
{
        /*
         * ..., val1, val2 -> ..., val1/val2
         */
	trace_jcode (("fdiv\n"));

	check_stack_float(0);
	check_stack_float(1);

	div_float(stack_float(1), rstack_float(1), rstack_float(0));
	pop(1);
}

define_insn(DDIV)
{
        /*
         * ..., val1, val2 -> ..., val1/val2
         */
	trace_jcode (("ddiv\n"));

	check_stack_double(0);
	check_stack_double(2);

	div_double(stack_double(2), rstack_double(2), rstack_double(0));
	pop(2);
}

define_insn(IREM)
{
        /*
         * ..., val1, val2 -> ..., val1%val2
         */
	trace_jcode (("irem\n"));

	check_stack_int(0);
	check_stack_int(1);

	check_div(IREM, rstack(0), 1);

	rem_int(stack(1), rstack(1), rstack(0));
	pop(1);
}

define_insn(LREM)
{
        /*
         * ..., long val1, long val2 -> ..., long val1%val2
         */
	trace_jcode (("lrem\n"));

	check_stack_long(0);
	check_stack_long(2);

	slot_nowriteback2(stack_long(0));
	slot_nowriteback2(stack_long(2));

	check_div_long(LREM, rstack_long(0), 1);

	rem_long(stack_long(2), rstack_long(2), rstack_long(0));
	pop(2);
}

define_insn(FREM)
{
        /*
         * ..., val1, val2 -> ..., val1%val2
         */
	trace_jcode (("frem\n"));

	check_stack_float(0);
	check_stack_float(1);

	rem_float(stack_float(1), rstack_float(1), rstack_float(0));
	pop(1);
}

define_insn(DREM)
{
        /*
         * ..., val1, val2 -> ..., val1%val2
         */
	trace_jcode (("drem\n"));

	check_stack_double(0);
	check_stack_double(2);

	rem_double(stack_double(2), rstack_double(2), rstack_double(0));
	pop(2);
}

define_insn(INEG)
{
	trace_jcode (("ineg\n"));

	check_stack_int(0);

	neg_int(stack(0), rstack(0));
}

define_insn(LNEG)
{
	trace_jcode (("lneg\n"));

	check_stack_long(0);

	slot_nowriteback2(stack_long(0));

	neg_long(stack_long(0), rstack_long(0));
}

define_insn(FNEG)
{
	trace_jcode (("fneg\n"));

	check_stack_float(0);

	neg_float(stack_float(0), rstack_float(0));
}

define_insn(DNEG)
{
	trace_jcode (("dneg\n"));

	check_stack_double(0);

	neg_double(stack_double(0), rstack_double(0));
}

define_insn(ISHL)
{
	/*
	 * ..., val1, val2 -> ... val1 << val2
	 */
	trace_jcode (("ishl\n"));

	check_stack_int(0);
	check_stack_int(1);

	lshl_int(stack(1), rstack(1), rstack(0));
	pop(1);
}

define_insn(LSHL)
{
	/*
	 * ..., long val1, val2 -> ... long val1 << val2
	 */
	trace_jcode (("lshl\n"));

	check_stack_int(0);
	check_stack_long(1);

	slot_nowriteback(stack(0));
	slot_nowriteback2(stack_long(1));

	lshl_long(stack_long(1), stack_long(1), stack(0));
	pop(1);
}

define_insn(ISHR)
{
	/*
	 * ..., val1, val2 -> ... val1 >> val2
	 */
	trace_jcode (("ishr\n"));

	check_stack_int(0);
	check_stack_int(1);

	ashr_int(stack(1), rstack(1), rstack(0));
	pop(1);
}

define_insn(LSHR)
{
	/*
	 * ..., long val1, val2 -> ... long val1 >> val2
	 */
	trace_jcode (("lshr\n"));

	check_stack_int(0);
	check_stack_long(1);

	slot_nowriteback(stack(0));
	slot_nowriteback2(stack_long(1));

	ashr_long(stack_long(1), stack_long(1), stack(0));
	pop(1);
}

define_insn(IUSHR)
{
	/*
	 * ..., val1, val2 -> ... val1 >> val2
	 */
	trace_jcode (("iushr\n"));

	check_stack_int(0);
	check_stack_int(1);

	lshr_int(stack(1), rstack(1), rstack(0));
	pop(1);
}

define_insn(LUSHR)
{
	/*
	 * ..., long val1, val2 -> ... long val1 >> val2
	 */
	trace_jcode (("lushr\n"));

	check_stack_int(0);
	check_stack_long(1);

	slot_nowriteback(stack(0));
	slot_nowriteback2(stack_long(1));

	lshr_long(stack_long(1), stack_long(1), stack(0));
	pop(1);
}

define_insn(IAND)
{
        /*
         * ..., val1, val2 -> ..., val1 & val2
         */
	trace_jcode (("iand\n"));

	check_stack_int(0);
	check_stack_int(1);

	and_int(stack(1), rstack(1), rstack(0));
	pop(1);
}

define_insn(LAND)
{
        /*
         * ..., long val1, long val2 -> ..., long val1 & val2
         */
	trace_jcode (("land\n"));

	check_stack_long(0);
	check_stack_long(2);

	slot_nowriteback2(stack_long(0));
	slot_nowriteback2(stack_long(2));

	and_long(stack_long(2), rstack_long(2), rstack_long(0));
	pop(2);
}

define_insn(IOR)
{
        /*
         * ..., val1, val2 -> ..., val1 | val2
         */
	trace_jcode (("ior\n"));

	check_stack_int(0);
	check_stack_int(1);

	or_int(stack(1), rstack(1), rstack(0));
	pop(1);
}

define_insn(LOR)
{
        /*
         * ..., long val1, long val2 -> ..., long val1 | val2
         */
	trace_jcode (("lor\n"));

	check_stack_long(0);
	check_stack_long(2);

	slot_nowriteback2(stack_long(0));
	slot_nowriteback2(stack_long(2));

	or_long(stack_long(2), rstack_long(2), rstack_long(0));
	pop(2);
}

define_insn(IXOR)
{
        /*
         * ..., val1, val2 -> ..., val1 ^ val2
         */
	trace_jcode (("ixor\n"));

	check_stack_int(0);
	check_stack_int(1);

	xor_int(stack(1), rstack(1), rstack(0));
	pop(1);
}

define_insn(LXOR)
{
        /*
         * ..., long val1, long val2 -> ..., long val1 ^ val2
         */
	trace_jcode (("lxor\n"));

	check_stack_long(0);
	check_stack_long(2);

	slot_nowriteback2(stack_long(0));
	slot_nowriteback2(stack_long(2));

	xor_long(stack_long(2), rstack_long(2), rstack_long(0));
	pop(2);
}

define_insn(IINC)
{
	check_pc (0);
	check_pc (1);
	idx = (uint8)getpc(0);
	low = (int8)getpc(1);
	trace_jcode (("iinc %d %d\n", idx, low));

	check_local_int(idx);

	add_int_const(local(idx), local(idx), low);
}

define_insn(I2L)
{
	trace_jcode (("i2l\n"));

	check_stack_int(0);

	push(1);
	cvt_int_long(stack_long(0), stack(1));
}

define_insn(I2F)
{
	trace_jcode (("i2f\n"));

	check_stack_int(0);

	cvt_int_float(stack(0), stack(0));
}

define_insn(I2D)
{
	trace_jcode (("i2d\n"));

	check_stack_int(0);

	push(1);
	cvt_int_double(stack_double(0), stack(1));
}

define_insn(L2I)
{
	trace_jcode (("l2i\n"));

	check_stack_long(0);

	cvt_long_int(stack(1), stack_long(0));
	pop(1);
}

define_insn(L2F)
{
	trace_jcode (("l2f\n"));

	check_stack_long(0);

	cvt_long_float(stack(1), stack_long(0));
	pop(1);
}

define_insn(L2D)
{
	trace_jcode (("l2d\n"));

	check_stack_long(0);

	cvt_long_double(stack_double(0), stack_long(0));
}

define_insn(F2I)
{
	trace_jcode (("f2i\n"));

	check_stack_float(0);

	cvt_float_int(stack(0), stack(0));
}

define_insn(F2L)
{
	trace_jcode (("f2l\n"));

	check_stack_float(0);

	push(1);
	cvt_float_long(stack_long(0), stack(1));
}

define_insn(F2D)
{
	trace_jcode (("f2d\n"));

	check_stack_float(0);

	push(1);
	cvt_float_double(stack_double(0), stack(1));
}

define_insn(D2I)
{
	trace_jcode (("d2i\n"));

	check_stack_double(0);

	cvt_double_int(stack(1), stack_double(0));
	pop(1);
}

define_insn(D2L)
{
	trace_jcode (("d2l\n"));

	check_stack_double(0);

	cvt_double_long(stack_long(0), stack_double(0));
}

define_insn(D2F)
{
	trace_jcode (("d2f\n"));

	check_stack_double(0);

	cvt_double_float(stack(1), stack_double(0));
	pop(1);
}

define_insn(INT2BYTE)
{
	trace_jcode (("int2byte\n"));

	check_stack_int(0);

	cvt_int_byte(stack(0), rstack(0));
}

define_insn(INT2CHAR)
{
	trace_jcode (("int2char\n"));

	check_stack_int(0);

	cvt_int_char(stack(0), rstack(0));
}

define_insn(INT2SHORT)
{
	trace_jcode (("int2short\n"));

	check_stack_int(0);

	cvt_int_short(stack(0), rstack(0));
}

define_insn(LCMP)
{
	/*
	 * ..., long val1, long val2 -> ..., result
	 */
	trace_jcode (("lcmp\n"));

	check_stack_long(0);
	check_stack_long(2);

	slot_nowriteback2(stack_long(0));
	slot_nowriteback2(stack_long(2));

	lcmp(stack(3), rstack_long(0), rstack_long(2));
	pop(3);
}

define_insn(FCMPL)
{
	/*
	 * ..., float val1, float val2 -> ..., result
	 */
	trace_jcode (("fcmpl\n"));

	check_stack_float(0);
	check_stack_float(1);

	cmpl_float(stack(1), stack(1), stack(0));
	pop(1);
}

define_insn(FCMPG)
{
	/*
	 * ..., float val1, float val2 -> ..., result
	 */
	trace_jcode (("fcmpg\n"));

	check_stack_float(0);
	check_stack_float(1);

	cmpg_float(stack(1), stack(1), stack(0));
	pop(1);
}

define_insn(DCMPL)
{
	/*
	 * ..., double val1, double val2 -> ..., result
	 */
	trace_jcode (("dcmpl\n"));

	check_stack_double(0);
	check_stack_double(2);

	cmpl_double(stack(3), stack_double(2), stack_double(0));
	pop(3);
}

define_insn(DCMPG)
{
	/*
	 * ..., double val1, double val2 -> ..., result
	 */
	trace_jcode (("dcmpg\n"));

	check_stack_double(0);
	check_stack_double(2);

	cmpg_double(stack(3), stack_double(2), stack_double(0));
	pop(3);
}

define_insn(IFEQ)
{
	check_pcidx (0);
	check_stack_int(0);

	idx = (int16)((getpc(0) << 8) | getpc(1));
	trace_jcode (("ifeq %d\n", pc + idx));

	slot_nowriteback(stack(0));
	begin_sync();

	cbranch_int_const_eq(rstack(0), 0, reference_code_label(pc+idx));
	pop(1);

	end_sync();
}

define_insn(IFNE)
{
	check_pcidx (0);
	check_stack_int(0);

	idx = (int16)((getpc(0) << 8) | getpc(1));
	trace_jcode (("ifne %d\n", pc + idx));

	slot_nowriteback(stack(0));
	begin_sync();

	cbranch_int_const_ne(rstack(0), 0, reference_code_label(pc+idx));
	pop(1);

	end_sync();
}

define_insn(IFLT)
{
	check_pcidx (0);
	check_stack_int(0);

	idx = (int16)((getpc(0) << 8) | getpc(1));
	trace_jcode (("iflt %d\n", pc + idx));

	slot_nowriteback(stack(0));
	begin_sync();

	cbranch_int_const_lt(rstack(0), 0, reference_code_label(pc+idx));
	pop(1);

	end_sync();
}

define_insn(IFGE)
{
	check_pcidx (0);
	check_stack_int(0);

	idx = (int16)((getpc(0) << 8) | getpc(1));
	trace_jcode (("ifge %d\n", pc + idx));

	slot_nowriteback(stack(0));
	begin_sync();

	cbranch_int_const_ge(rstack(0), 0, reference_code_label(pc+idx));
	pop(1);

	end_sync();
}

define_insn(IFGT)
{
	check_pcidx (0);
	check_stack_int(0);

	idx = (int16)((getpc(0) << 8) | getpc(1));
	trace_jcode (("ifgt %d\n", pc + idx));

	slot_nowriteback(stack(0));
	begin_sync();

	cbranch_int_const_gt(rstack(0), 0, reference_code_label(pc+idx));
	pop(1);

	end_sync();
}

define_insn(IFLE)
{
	check_pcidx (0);
	check_stack_int(0);

	idx = (int16)((getpc(0) << 8) | getpc(1));
	trace_jcode (("ifle %d\n", pc + idx));

	slot_nowriteback(stack(0));
	begin_sync();

	cbranch_int_const_le(rstack(0), 0, reference_code_label(pc+idx));
	pop(1);

	end_sync();
}

define_insn(IF_ICMPEQ)
{
	check_pcidx (0);
	check_stack_int(0);
	check_stack_int(1);

	idx = (int16)((getpc(0) << 8) | getpc(1));
	trace_jcode (("if_icmpeq %d\n", pc + idx));

	slot_nowriteback(stack(0));
	slot_nowriteback(stack(1));
	begin_sync();

	cbranch_int_eq(rstack(1), rstack(0), reference_code_label(pc+idx));
	pop(2);

	end_sync();
}

define_insn(IF_ICMPNE)
{
	check_pcidx (0);
	check_stack_int(0);
	check_stack_int(1);

	idx = (int16)((getpc(0) << 8) | getpc(1));
	trace_jcode (("if_icmpne %d\n", pc + idx));

	slot_nowriteback(stack(0));
	slot_nowriteback(stack(1));
	begin_sync();

	cbranch_int_ne(rstack(1), rstack(0), reference_code_label(pc+idx));
	pop(2);

	end_sync();
}

define_insn(IF_ICMPLT)
{
	check_pcidx (0);
	check_stack_int(0);
	check_stack_int(1);

	idx = (int16)((getpc(0) << 8) | getpc(1));
	trace_jcode (("if_icmplt %d\n", pc + idx));

	slot_nowriteback(stack(0));
	slot_nowriteback(stack(1));
	begin_sync();

	cbranch_int_lt(rstack(1), rstack(0), reference_code_label(pc+idx));
	pop(2);

	end_sync();
}

define_insn(IF_ICMPGE)
{
	check_pcidx (0);
	check_stack_int(0);
	check_stack_int(1);

	idx = (int16)((getpc(0) << 8) | getpc(1));
	trace_jcode (("if_icmpge %d\n", pc + idx));

	slot_nowriteback(stack(0));
	slot_nowriteback(stack(1));
	begin_sync();

	cbranch_int_ge(rstack(1), rstack(0), reference_code_label(pc+idx));
	pop(2);

	end_sync();
}

define_insn(IF_ICMPGT)
{
	check_pcidx (0);
	check_stack_int(0);
	check_stack_int(1);

	idx = (int16)((getpc(0) << 8) | getpc(1));
	trace_jcode (("if_icmpgt %d\n", pc + idx));

	slot_nowriteback(stack(0));
	slot_nowriteback(stack(1));
	begin_sync();

	cbranch_int_gt(rstack(1), rstack(0), reference_code_label(pc+idx));
	pop(2);

	end_sync();
}

define_insn(IF_ICMPLE)
{
	check_pcidx (0);
	check_stack_int(0);
	check_stack_int(1);

	idx = (int16)((getpc(0) << 8) | getpc(1));
	trace_jcode (("if_icmple %d\n", pc + idx));

	slot_nowriteback(stack(0));
	slot_nowriteback(stack(1));
	begin_sync();

	cbranch_int_le(rstack(1), rstack(0), reference_code_label(pc+idx));
	pop(2);

	end_sync();
}

define_insn(IF_ACMPEQ)
{
	check_pcidx (0);
	check_stack_ref(0);
	check_stack_ref(1);

	idx = (int16)((getpc(0) << 8) | getpc(1));
	trace_jcode (("if_acmpeq %d\n", pc + idx));

	slot_nowriteback(stack(0));
	slot_nowriteback(stack(1));
	begin_sync();

	cbranch_ref_eq(rstack(1), rstack(0), reference_code_label(pc+idx));
	pop(2);

	end_sync();
}

define_insn(IF_ACMPNE)
{
	check_pcidx (0);
	check_stack_ref(0);
	check_stack_ref(1);

	idx = (int16)((getpc(0) << 8) | getpc(1));
	trace_jcode (("if_acmpne %d\n", pc + idx));

	slot_nowriteback(stack(0));
	slot_nowriteback(stack(1));
	begin_sync();

	cbranch_ref_ne(rstack(1), rstack(0), reference_code_label(pc+idx));
	pop(2);

	end_sync();
}

define_insn(GOTO)
{
	check_pcidx (0);

	idx = (int16)((getpc(0) << 8) | getpc(1));
	trace_jcode (("goto %d\n", pc + idx));

	begin_sync();
	branch_a(reference_code_label(pc+idx));
	end_sync();
}

define_insn(JSR)
{
	/*
	 * ... -> ..., ret-addr
	 */
	check_pcidx (0);

	idx = (int16)((getpc(0) << 8) | getpc(1));
	trace_jcode (("jsr %d\n", pc + idx));

	push(1);
	move_label_const(stack(0), reference_code_label(npc));
	marknotobj_int; /* JJC */ 

	begin_sync();
	branch_a(reference_code_label(pc+idx));
	end_sync();
}

define_insn(RET)
{
	check_pc (0);

	idx = (uint8)getpc(0);
	trace_jcode (("ret %d\n", idx));

	check_local_ref(idx);

	begin_sync();
	branch_indirect(stored_code_label(local(idx)));
	end_sync();
}

define_insn(TABLESWITCH)
{
	/*
	 * ..., index -> ...
	 */
	check_stack_int(0);

	npc = (pc + 1 + 3) & -4;
	low = (int32)((getcode(npc+4) << 24) | (getcode(npc+5) << 16) |
				(getcode(npc+6) << 8) | getcode(npc+7));
	high = (int32)((getcode(npc+8) << 24) | (getcode(npc+9) << 16) |
				(getcode(npc+10) << 8) | getcode(npc+11));
	npc = npc + 12;

	trace_jcode (("tableswitch %d %d\n", low, high));

	end_sub_block();
	cbranch_int_const_lt(stack(0), low, reference_label(TABLESWITCH, 8));
	cbranch_int_const_le(stack(0), high, reference_label(TABLESWITCH, 7));

	start_sub_block();
	set_label(TABLESWITCH, 8);
	move_int_const(stack(0), low-3); /* Position at default entry */
	end_sub_block();

	start_sub_block();
	set_label(TABLESWITCH, 7);
	if (low != 0) {
		start_sub_block();
		sub_int_const(stack(0), stack(0), low);
		end_sub_block();
	}
	lshl_int_const(stack(0), stack(0), switchtable_shift);
	slot_alloctmp(tmp2);
	move_label_const(tmp2, reference_table_label(9));
	add_ref(stack(0), tmp2, stack(0));
	slot_freetmp(tmp2);
	load_code_ref(stack(0), stack(0));
	end_sub_block();
	branch_indirect(table_code_label(stack(0)));
	pop(1);

#if defined(TRANSLATOR)
	{
		build_code_ref(&getcode(npc-12), pc);	/* Default entry */
		build_code_ref(&getcode(npc-12), pc);	/* Dummy */
		build_code_ref(&getcode(npc-12), pc);	/* Dummy */
		set_label(TABLESWITCH, 9);
		for (idx = 0; idx < high-low+1; idx++) {
			build_code_ref(&getcode(npc + (idx << switchtable_shift)), pc);
		}
	}
#endif
	adjustpc((4 - (pc % 4)) + 12 + (high - low + 1) * 4);
}

define_insn(LOOKUPSWITCH)
{
	/*
	 * ..., key -> ...
	 */
	check_stack_int(0);

	npc = (pc + 1 + 3) & -4;
	idx = (int32)((getcode(npc+4) << 24) | (getcode(npc+5) << 16) |
				(getcode(npc+6) << 8) | getcode(npc+7));

	trace_jcode (("lookupswitch %d\n", idx));

	slot_alloctmp(mtable);
	slot_alloctmp(tmp);

	move_label_const(tmp, reference_table_label(7));
	if (idx != 0) {
		slot_alloctmp(tmp2);
		move_ref(tmp2, tmp);
		add_ref_const(tmp, tmp, idx * switchpair_size);

		end_sub_block();
		set_label(LOOKUPSWITCH, 5);
		start_sub_block();
		load_key(mtable, tmp);
		end_sub_block();
		cbranch_int_eq(mtable, stack(0), reference_label(LOOKUPSWITCH, 6));

		start_sub_block();
		add_ref_const(tmp, tmp, -switchpair_size);
		end_sub_block();
		cbranch_ref_ne(tmp, tmp2, reference_label(LOOKUPSWITCH, 5));
		slot_freetmp(tmp2);

		start_sub_block();
		add_ref_const(tmp, tmp, -switchpair_addr);
		end_sub_block();

		set_label(LOOKUPSWITCH, 6);
		start_sub_block();
		add_ref_const(tmp, tmp, switchpair_addr);
	}
	load_code_ref(tmp, tmp);
	end_sub_block();
	branch_indirect(table_code_label(tmp));
	pop(1);

	slot_freetmp(mtable);
	slot_freetmp(tmp);

#if defined(TRANSLATOR)
	{
		set_label(LOOKUPSWITCH, 7);
		build_code_ref(&getcode(npc), pc);
		build_key(&getcode(npc)); /* Dummy key */
		for (low = 1; low <= idx; low++) {
			build_key(&getcode(npc + (low * switchpair_size)));
			build_code_ref(&getcode(npc + (low * switchpair_size) + switchpair_addr), pc);
		}
	}
#endif
	adjustpc((4 - (pc % 4)) + (idx + 1) * 8);
}

define_insn(IRETURN)
{
	trace_jcode (("ireturn\n"));

	if( valid_log ) {         /* JJC */
	  savewholestack;   /* JJC */
	  savelocals;       /* JJC */
	}    /* JJC */

	check_stack_int(0);

	monitor_exit();
	returnarg_int(rstack(0));
	ret();
}

define_insn(LRETURN)
{
	trace_jcode (("lreturn\n"));
	if( valid_log ) {         /* JJC */
	  savewholestack;   /* JJC */
	  savelocals;       /* JJC */
	}                         /* JJC */

	check_stack_long(0);

	monitor_exit();
	returnarg_long(rstack_long(0));
	ret();
}

define_insn(FRETURN)
{
	trace_jcode (("freturn\n"));

	if( valid_log ) {         /* JJC */
	  savewholestack;   /* JJC */
	  savelocals;       /* JJC */
	}                         /* JJC */
	
	check_stack_float(0);

	monitor_exit();
	returnarg_float(rstack_float(0));
	ret();
}

define_insn(DRETURN)
{
	trace_jcode (("dreturn\n"));

	if( valid_log ) {         /* JJC */
	  savewholestack;   /* JJC */
	  savelocals;       /* JJC */
	}                         /* JJC */

	check_stack_double(0);

	monitor_exit();
	returnarg_double(rstack_double(0));
	ret();
}

define_insn(ARETURN)
{
	trace_jcode (("areturn\n"));

	if( valid_log ) {         /* JJC */
	  savewholestack;   /* JJC */
	  savelocals;       /* JJC */
	}                         /* JJC */

	check_stack_ref(0);

	monitor_exit();
	returnarg_ref(rstack_ref(0));
	ret();
}

define_insn(RETURN)
{
	trace_jcode (("return\n"));

	if( valid_log ) {         /* JJC */
	  savewholestack;   /* JJC */
	  savelocals;       /* JJC */
	}                         /* JJC */

	monitor_exit();
	ret();
}

/*
 * This macro initialises the static data associated with a class.
 */
#define	INIT_STATIC_CLASS(c) \
	if (c != 0 && c->state != CSTATE_COMPLETE) { \
		softcall_initialise_class(c); \
	}

define_insn(GETSTATIC)
{
	/*
	 * ... -> ..., value
	 */
	check_pcidx (0);

	idx = (uint16)((getpc(0) << 8) | getpc(1));

	trace_jcode (("getstatic %d\n", idx));

	get_static_field_info(idx);
	INIT_STATIC_CLASS(field_class());

	if (field_field() == 0) {
		softcall_nosuchfield(field_classname(), field_name());
		switch (field_sig()->data[0]) {
		case 'J':
		case 'D':
			push(2);
			break;
		default:
			push(1);
			break;
		}
	}
	/* Use the proper load to increase the chances of the translator
	   getting data in the right type of register.  */
	else if (!FIELD_ISPRIM(field_field())) {
		push(1);
		/* START JJC */
		if( valid_log ) {
		  if( strncmp( finfo.signature->data, "Lkaffe/util/Ptr;", 16 ) == 0 ) {
		    markunknown;
		  }
		  else
		    markisobj;
		}
		/* END JJC */
		load_addr_ref(stack(0), FIELD_ADDRESS(field_field()));
	}
	else switch (CLASS_PRIM_SIG(FIELD_TYPE(field_field()))) {
	case 'I':
		push(1);
		load_addr_int(stack(0), FIELD_ADDRESS(field_field()));
		marknotobj_int; /* JJC */
		break;
	case 'S':
		push(1);
		load_addr_short(stack(0), FIELD_ADDRESS(field_field()));
		marknotobj_int; /* JJC */
		break;
	case 'B':
	case 'Z':
		push(1);
		load_addr_byte(stack(0), FIELD_ADDRESS(field_field()));
		marknotobj_int; /* JJC */
		break;
	case 'C':
		push(1);
		load_addr_char(stack(0), FIELD_ADDRESS(field_field()));
		marknotobj_int; /* JJC */
		break;
	case 'F':
		push(1);
		load_addr_float(stack(0), FIELD_ADDRESS(field_field()));
		marknotobj_float; /* JJC */
		break;
	case 'J':
		push(2);
		load_addr_long(stack_long(0), FIELD_ADDRESS(field_field()));
		break;
	case 'D':
		push(2);
		load_addr_double(stack_double(0), FIELD_ADDRESS(field_field()));
		marknotobj2_double; /* JJC */
		break;
	default:
		ABORT();
	}
}

define_insn(PUTSTATIC)
{
	/*
	 * ..., value  -> ...
	 */
	check_pcidx (0);

	idx = (uint16)((getpc(0) << 8) | getpc(1));
	trace_jcode (("putstatic %d\n", idx));

	get_static_field_info(idx);
	INIT_STATIC_CLASS(field_class());

	if (field_field() == 0) {
		softcall_nosuchfield(field_classname(), field_name());
		switch (field_sig()->data[0]) {
		case 'J':
		case 'D':
			pop(2);
			break;
		default:
			pop(1);
			break;
		}
	}
	else if (!FIELD_ISPRIM(field_field())) {
		SOFT_ADDREFERENCE_STATIC(field_statics(), stack(0));
		load_addr_ref( tmp, FIELD_ADDRESS( finfo.field ) ); /* JJC */
		store_addr_ref(FIELD_ADDRESS(field_field()), stack(0));
		move_ref( stack( 0 ), tmp ); /* JJC */
		/* START JJC */
		if( valid_log ) {
		  if( strncmp( finfo.signature->data, "Lkaffe/util/Ptr;", 16 ) == 0 ) {
		    markunknown;
		  }
		  if( valid_log ) savestack( 1 );
		}
		/* END JJC */
		pop(1);
	}
	else switch (CLASS_PRIM_SIG(FIELD_TYPE(field_field()))) {
	case 'I':
	  load_addr_int( tmp, FIELD_ADDRESS( finfo.field ) ); /* JJC */
	  store_addr_int(FIELD_ADDRESS(field_field()), stack(0));
	  move_int( stack( 0 ), tmp ); /* JJC */
	  if( valid_log ) savestack( 1 ); /* JJC */
	  pop(1);
	  break;
	case 'S':
	  load_addr_short( tmp, FIELD_ADDRESS( finfo.field ) ); /* JJC */
	  store_addr_short(FIELD_ADDRESS(field_field()), stack(0));
	  move_int( stack( 0 ), tmp ); /* JJC */
	  if( valid_log ) savestack( 1 ); /* JJC */
	  pop(1);
	  break;
	case 'B':
	case 'Z':
	  load_addr_byte( tmp, FIELD_ADDRESS( finfo.field ) ); /* JJC */
	  store_addr_byte(FIELD_ADDRESS(field_field()), stack(0));
	  move_int( stack( 0 ), tmp ); /* JJC */
	  if( valid_log ) savestack( 1 ); /* JJC */
	  pop(1);
	  break;
	case 'C':
	  load_addr_char( tmp, FIELD_ADDRESS( finfo.field ) ); /* JJC */
	  store_addr_char(FIELD_ADDRESS(field_field()), stack(0));
	  move_int( stack( 0 ), tmp ); /* JJC */
	  if( valid_log ) savestack( 1 ); /* JJC */
	  pop(1);
	  break;
	case 'F':
	  load_addr_float( tmp, FIELD_ADDRESS( finfo.field ) ); /* JJC */
	  store_addr_float(FIELD_ADDRESS(field_field()), stack(0));
	  move_float( stack( 0 ), tmp ); /* JJC */
	  if( valid_log ) savestack( 1 ); /* JJC */	  
	  pop(1);
	  break;
	case 'J':
	  load_addr_long( tmp, FIELD_ADDRESS( finfo.field ) ); /* JJC */
	  store_addr_long(FIELD_ADDRESS(field_field()), stack_long(0));
	  move_long( stack_long( 0 ), tmp ); /* JJC */
	  if( valid_log ) savestack( 2 ); /* JJC */
	  pop(2);
	  break;
	case 'D':
	  load_addr_double( tmp, FIELD_ADDRESS( finfo.field ) ); /* JJC */
	  store_addr_double(FIELD_ADDRESS(field_field()), stack_double(0));
	  move_double( stack_long( 0 ), tmp ); /* JJC */
	  if( valid_log ) savestack( 2 ); /* JJC */
	  pop(2);
	  break;
	default:
	  ABORT();
	}
}

define_insn(GETFIELD)
{
	/*
	 * ..., obj-ref -> ..., value
	 */
        if( valid_log ) /* JJC */
	  savestack( 1 ); /* JJC */

	check_pcidx (0);
	check_stack_ref(0);

	check_null(GETFIELD, stack(0), 34);

	idx = (uint16)((getpc(0) << 8) | getpc(1));
	trace_jcode (("getfield %d\n", idx));

	get_field_info(idx);

	/* If field not found we put an exception down */
	if (field_field() == 0) {
		softcall_nosuchfield(field_classname(), field_name());
		switch (field_sig()->data[0]) {
		case 'J':
		case 'D':
			pop(1);
			break;
		default:
			break;
		}
	}
	/* Use the proper load to increase the chances of the translator
	   getting data in the right type of register.  */
	else if (!FIELD_ISPRIM(field_field())) {
		load_offset_ref(stack(0), rstack(0), FIELD_BOFFSET(field_field()));
		if( valid_log ) wcbuffi( 0, debug ); /* JJC */
		/* START JJC */
		if( valid_log ) {
		  if( strncmp( finfo.signature->data, "Lkaffe/util/Ptr;", 16 ) == 0 ) {
		    markunknown;
		  }
		  else
		    markisobj;
		}
		/* END JJC */
	}
	else switch (CLASS_PRIM_SIG(FIELD_TYPE(field_field()))) {
	case 'I':
		load_offset_int(stack(0), rstack(0), FIELD_BOFFSET(field_field()));
		marknotobj_int; /* JJC */
		if( valid_log ) wcbuffi( 0, debug ); /* JJC */
		break;
	case 'S':
		load_offset_short(stack(0), rstack(0), FIELD_BOFFSET(field_field()));
		marknotobj_int; /* JJC */
		if( valid_log ) wcbuffi( 0, debug ); /* JJC */
		break;
	case 'B':
	case 'Z':
	        load_offset_byte(stack(0), rstack(0), FIELD_BOFFSET(field_field()));
		marknotobj_int; /* JJC */
		if( valid_log ) wcbuffi( 0, debug ); /* JJC */
		break;
	case 'C':
         	load_offset_char(stack(0), rstack(0), FIELD_BOFFSET(field_field()));
		marknotobj_int; /* JJC */
		if( valid_log ) wcbuffi( 0, debug ); /* JJC */
		break;
	case 'F':
		load_offset_float(stack(0), stack(0), FIELD_BOFFSET(field_field()));
		marknotobj_float; /* JJC */
		if( valid_log ) wcbuffi( 0, debug ); /* JJC */
		break;
	case 'J':
      		load_offset_long(stack_long(-1), stack(0), FIELD_BOFFSET(field_field()));
		push(1);
		marknotobj2_long; /* JJC */
		if( valid_log ) wcbuffi( 1, debug ); /* JJC */
		break;
	case 'D':
		load_offset_double(stack_double(-1), stack(0), FIELD_BOFFSET(field_field()));
		push(1);
		marknotobj2_double; /* JJC */
		if( valid_log ) wcbuffi( 1, debug ); /* JJC */
		break;

	default:
		ABORT();
	}
}

define_insn(PUTFIELD)
{
	/*
	 * ..., obj-ref, value  -> ...
	 */
	check_pcidx (0);

	idx = (uint16)((getpc(0) << 8) | getpc(1));
	trace_jcode (("putfield %d\n", idx));

	get_field_info(idx);

	if (field_field() == 0) {
		softcall_nosuchfield(field_classname(), field_name());
		switch (field_sig()->data[0]) {
		case 'J':
		case 'D':
			pop(3);
			break;
		default:
			pop(2);
			break;
		}
	}
	/* Use the proper store to increase the chances of the translator
	   having the data in the right type of register already.  */
	else if (!FIELD_ISPRIM(field_field())) {
		check_stack_ref(1);
		check_null(PUTFIELD, rstack(1), 35);
		SOFT_ADDREFERENCE(rstack(1), rstack(0));
		load_offset_ref( tmp, stack( 1 ), FIELD_BOFFSET( finfo.field ) ); /* JJC */ 
		store_offset_ref(rstack(1), FIELD_BOFFSET(field_field()), rstack(0));
		move_ref( stack( 0 ), tmp ); /* JJC */
		/* START JJC */
		if( valid_log ) {
		  if( strncmp( finfo.signature->data, "Lkaffe/util/Ptr;", 16 ) == 0 ) {
		    markunknown;
		  }
		  savestack( 2 );
		}
		/* END JJC */
		pop(2);
	}
	else switch (CLASS_PRIM_SIG(FIELD_TYPE(field_field()))) {
	case 'I':
		check_stack_ref(1);
		check_null(PUTFIELD, stack(1), 36);
		load_offset_int( tmp, stack( 1 ), FIELD_BOFFSET( finfo.field ) ); /* JJC */
		store_offset_int(stack(1), FIELD_BOFFSET(field_field()), stack(0));
		move_int( stack( 0 ), tmp ); /* JJC */
		if( valid_log ) savestack( 2 ); /* JJC */
		pop(2);
		break;
	case 'S':
		check_stack_ref(1);
		check_null(PUTFIELD, stack(1), 37);
		load_offset_short( tmp, stack( 1 ), FIELD_BOFFSET( finfo.field ) ); /* JJC */
		store_offset_short(stack(1), FIELD_BOFFSET(field_field()), stack(0));
		move_int( stack( 0 ), tmp ); /* JJC */
		if( valid_log ) savestack( 2 ); /* JJC */
		pop(2);
		break;
	case 'B':
	case 'Z':
		check_stack_ref(1);
		check_null(PUTFIELD, stack(1), 37);
		load_offset_byte( tmp, stack( 1 ), FIELD_BOFFSET( finfo.field ) ); /* JJC */
		store_offset_byte(stack(1), FIELD_BOFFSET(field_field()), stack(0));
		move_int( stack( 0 ), tmp ); /* JJC */
		if( valid_log ) savestack( 2 ); /* JJC */
		pop(2);
		break;
	case 'C':
		check_stack_ref(1);
		check_null(PUTFIELD, stack(1), 37);
		load_offset_char( tmp, stack( 1 ), FIELD_BOFFSET( finfo.field ) ); /* JJC */
		store_offset_char(stack(1), FIELD_BOFFSET(field_field()), stack(0));
		move_int( stack( 0 ), tmp ); /* JJC */
		if( valid_log ) savestack( 2 ); /* JJC */
		pop(2);
		break;
	case 'F':
		check_stack_ref(1);
		check_null(PUTFIELD, stack(1), 37);
		load_offset_float( tmp, stack( 1 ), FIELD_BOFFSET( finfo.field ) ); /* JJC */
		store_offset_float(stack(1), FIELD_BOFFSET(field_field()), stack(0));
		move_float( stack( 0 ), tmp ); /* JJC */
		if( valid_log ) savestack( 2 ); /* JJC */
		pop(2);
		break;
	case 'J':
		check_stack_ref(2);
		check_null(PUTFIELD, stack(2), 38);
		load_offset_long( tmp, stack( 2 ), FIELD_BOFFSET( finfo.field ) );/* JJC */
		store_offset_long(stack(2), FIELD_BOFFSET(field_field()), stack_long(0));
		move_long( stack_long( 0 ), tmp ); /* JJC */
		if( valid_log ) savestack( 3 ); /* JJC */
		pop(3);
		break;
	case 'D':
		check_stack_ref(2);
		check_null(PUTFIELD, stack(2), 39);
		load_offset_double( tmp, stack( 2 ), FIELD_BOFFSET( finfo.field ) ); /* JJC */
		store_offset_double(stack(2), FIELD_BOFFSET(field_field()), stack_double(0));
		move_double( stack_long( 0 ), tmp ); /* JJC */
		if( valid_log ) savestack( 3 ); /* JJC */
		pop(3);
		break;
	default:
		ABORT();
	}
}

/* START JJC */

#define METHOD_RETURN_TYPE() ( ( method_method()->parsed_sig->signature->data ) + ( method_method()->parsed_sig->ret_and_args[ 0 ] ) )

/* END JJC */

#define	METHOD_RETURN_VALUE()									\
do {												\
	/* Store the return type (if necessary) */						\
	switch (low) {										\
	case 'V':										\
		break;										\
        /* START JJC */										\
        case 'L': push(1);									\
                  return_ref(stack(0));								\
                  if( valid_log ) {								\
		    if( strncmp( METHOD_RETURN_TYPE(), "Lkaffe/util/Ptr;", 16 ) == 0 ) {	\
		      markunknown;								\
		    }										\
		    else									\
		      markisobj;								\
		  }										\
		  break;									\
        /* END JJC */										\
	case '[':										\
		push(1);									\
		return_ref(stack(0));								\
		markisobj; /* JJC */								\
		break;										\
	case 'I':										\
	case 'Z':										\
	case 'S':										\
	case 'B':										\
	case 'C':										\
		push(1);									\
		return_int(stack(0));								\
        marknotobj_int; /* JJC */								\
		break;										\
	case 'F':										\
		push(1);									\
		return_float(stack(0));								\
        marknotobj_float; /* JJC */								\
		break;										\
	case 'J':										\
		push(2);									\
		return_long(stack_long(0));							\
        marknotobj2_long; /* JJC */								\
		break;										\
	case 'D':										\
		push(2);									\
		return_double(stack_double(0));							\
        marknotobj2_double; /* JJC */								\
		break;										\
	default:										\
		ABORT();									\
	}											\
} while (0)

#define PASSON ( reverse_method == T_RETRY_OVER_FIRST ? T_RETRY_OVER : reverse_method == T_FWDS_INTO && running_over ? T_FWDS_OVER : reverse_method )

define_insn(INVOKEVIRTUAL)
{
	/*
	 * ..., obj, ..args.., -> ...
	 */

        int8 beg = F_END; /* JJC */
	if( valid_log ) (debug->last_method) = meth; /* JJC */

	check_pcidx (0);

	idx = (uint16)((getpc(0) << 8) | getpc(1));
	trace_jcode (("invokevirtual %d\n", idx));

	get_method_info_noerror(idx);

	if( valid_log ) savestackandn( method_nargs( ) + 1 ); /* JJC */

	/* If class doesn't exist, call 'NoSuchClassError' */
	if (method_class() == 0) {
		softcall_nosuchclass(method_classname());
		low = method_returntype();
		pop(method_nargs() + 1);
		METHOD_RETURN_VALUE();
	}
	/* If method doesn't exist, call 'NoSuchMethodError' */
	else if (method_method() == 0) {
		softcall_nosuchmethod(method_class(), method_name(), method_sig());
		low = method_returntype();
		pop(method_nargs() + 1);
		METHOD_RETURN_VALUE();
	}
	else {
        	void *ptf; /* JJC */
		int is_virtual = method_method()->idx >= 0;
		if (is_virtual) {
			slot_alloctmp(tmp);
		}
#ifdef TRANSLATOR
		else {
			tmp = 0;	/* for compiler warning */
		}
#endif

		idx = method_nargs();
		ptf = (stack(idx))[0].v.taddr; /* JJC */

		check_null(INVOKEVIRTUAL, stack(idx), 34);

		check_stack_ref(idx);

		if (is_virtual) {
			/* Find dispatch table in object */
			load_offset_ref(tmp, stack(idx), method_dtable_offset);

			/* Check method table for cached entry */
			load_offset_ref(tmp, tmp,
				DTABLE_METHODOFFSET + 
				method_idx() * DTABLE_METHODSIZE);
		} else {
			/* Explicitly check that object is non-null.
			 * Implicitly done in the dispatch table lookup. */
			explicit_check_null(INVOKEVIRTUAL, stack(idx), 35);
		}

		/* Push arguments & object */
		build_call_frame(method_sig(), stack(idx), idx);
		idx++;

		if (is_virtual) {
			slot_nowriteback(tmp);
		}
		pop(idx);
		begin_func_sync();

		/* Call it */
		low = method_returntype();
		if (is_virtual) {
                        softcall_initialise_class(method_class()); 
			beg = virtualMachine((methods*)(tmp)[0].v.taddr, sp+1, retval, tid, PASSON, thr ); /* JJC */
    		        /* call(tmp) */;
			slot_freetmp(tmp);
		} else {
		  softcall_initialise_class(method_class()); 
		  beg = virtualMachine(method_method(), sp+1, retval, tid, PASSON, thr ); /* JJC */
		  /* call_indirect_method(method_method()); */
		}

		/* START JJC */
		if( reverse_method == T_RETRY ) {
		  reverse_method = T_FWDS_INTO;
		  valid_log = 1;
		} else if( reverse_method == T_RETRY_OVER || reverse_method == T_RETRY_OVER_FIRST ) {
		  valid_log = 1;
		}
		/* END JJC */
		
		/* START JJC (mark end of function) */
		if( valid_log && ( beg == F_END ) ) {
		  slots s;
		  s.v.taddr = ptf;
		  wcbuffs( s, 1, debug, thr );			
		  wcbuffpc( pc + METHOD_OFFSET, debug );
		}
		/* END JJC */

		/* Pop args */
		popargs();

		end_func_sync();
		METHOD_RETURN_VALUE();
		/* START JJC (if exited from start reverse to last line) */
		if( beg == F_BEG ) {
		  ret = reverseVirtualMachine( meth, lcl, &sp, &npc, retval, mjbuf, tid,
					       debug, callback, meth->fullSourceFile, &opsobjs, lvtobjs,
					       reverse_method == T_RETRY_OVER ? R_OVER : R_INTO, 
					       &cl, &seen_new_line, code, thr, false );
		  if( ret == F_BEG ) {
		    D_FL( fprintf( stderr, "------RUN VIRTUAL MACHINE: exit: ret == F_BEG\n" ) );
		    return F_BEG;
		  }
		  else if( ret == F_CATCH ) {
		    D_FL( fprintf( stderr, "------RUN VIRTUAL MACHINE: exit: ret == F_CATCH\n" ) );
		    return F_RETRY; /* not entirely sure about this */ 
		  }
		}
		assert( reverse_method != T_RETRY_OVER );
		if( reverse_method == T_RETRY_OVER || reverse_method == T_RETRY_OVER_FIRST )
		  reverse_method = T_FWDS_INTO;
		/* END JJC */
		
	} 
}

define_insn(INVOKESPECIAL)
{
	/*
	 * ..., obj, ..args.., -> ...
	 */
        int8 beg = F_END; /* JJC */
        if( valid_log ) (debug->last_method) = meth; /* JJC */

	check_pcidx (0);

	idx = (uint16)((getpc(0) << 8) | getpc(1));
	trace_jcode (("invokespecial %d\n", idx));

	get_special_method_info_noerror(idx);

	if( valid_log ) {                         /* JJC */
	  savestackandn( method_nargs( ) + 1 );  /* JJC */
	}  /* JJC */

	/* If class doesn't exist, call 'NoSuchClassError' */
	if (method_class() == 0) {
		softcall_nosuchclass(method_classname());
		low = method_returntype();
		pop(method_nargs() + 1);
		METHOD_RETURN_VALUE();
	}
	/* If method doesn't exist, call 'NoSuchMethodError' */
	else if (method_method() == 0) {
		softcall_nosuchmethod(method_class(), method_name(), method_sig());
		low = method_returntype();
		pop(method_nargs() + 1);
		METHOD_RETURN_VALUE();
	}
	else {  void* ptf; /* JJC */
		idx = method_nargs();
		ptf = ( stack( idx ) )[0].v.taddr; /* JJC */

		explicit_check_null(INVOKESPECIAL, stack(idx), 34);

		check_stack_ref(idx);

		/* Push arguments & object */
		build_call_frame(method_sig(), stack(idx), idx);
		idx++;

		pop(idx);
		begin_func_sync();

		/* Call it */
		low = method_returntype();

		/* call_indirect_method(method_method()); */
		softcall_initialise_class(method_class()); /* JJC */
		beg = virtualMachine(method_method(), sp+1, retval, tid, PASSON, thr ); /* JJC */

		/* START JJC */
		if( reverse_method == T_RETRY ) {
		  reverse_method = T_FWDS_INTO;
		  valid_log = 1;
		} else if( reverse_method == T_RETRY_OVER || reverse_method == T_RETRY_OVER_FIRST ) {
		  valid_log = 1;
		}
		/* END JJC */
		
		/* START JJC (mark end of function) */
		if( valid_log && ( beg == F_END ) ) {
		  slots s;
		  s.v.taddr = ptf;
		  wcbuffs( s, 1, debug, thr );
		  wcbuffpc( pc + METHOD_OFFSET, debug ); 
		}
		/* END JJC */
		
		/* Pop args */
		popargs();

		end_func_sync();
		METHOD_RETURN_VALUE();

		/* START JJC (if exited from start reverse to last line) */
		if( beg == F_BEG ) {
		  ret = reverseVirtualMachine( meth, lcl, &sp, &npc, retval, mjbuf, tid,
					       debug, callback, meth->fullSourceFile, &opsobjs, lvtobjs,
					       reverse_method == T_RETRY_OVER ? R_OVER : R_INTO, 
					       &cl, &seen_new_line, code, thr, false );
		  if( ret == F_BEG ) {
		    D_FL( fprintf( stderr, "------RUN VIRTUAL MACHINE: exit: ret == F_BEG\n" ) );
		    return F_BEG;
		  }
		  else if( ret == F_CATCH ) {
		    D_FL( fprintf( stderr, "------RUN VIRTUAL MACHINE: exit: ret == F_CATCH\n" ) );
		    return F_RETRY;  /* not sure! */
		  }
		}
		assert( reverse_method != T_RETRY_OVER );
		if( reverse_method == T_RETRY_OVER || reverse_method == T_RETRY_OVER_FIRST )
		  reverse_method = T_FWDS_INTO;
		
		/* END JJC */
	}
}

define_insn(INVOKESTATIC)
{
	/*
	 * ..., ..args.., -> ...
	 */
  int8 beg = F_END; /* JJC */
  if( valid_log ) (debug->last_method) = meth; /* JJC */
  
  check_pcidx (0);
  
  idx = (uint16)((getpc(0) << 8) | getpc(1));
  trace_jcode (("invokestatic %d\n", idx));
  
  get_method_info_noerror(idx);
  
  if( valid_log ) {                         /* JJC */
    savestackandn( method_nargs( ) );      /* JJC */
  }                                         /* JJC */
  
  
  
  /* If class doesn't exist, call 'NoSuchClassError' */
  if (method_class() == 0) {
    softcall_nosuchclass(method_classname());
    low = method_returntype();
    pop(method_nargs());
    METHOD_RETURN_VALUE();
  }
  /* If method doesn't exist, call 'NoSuchMethodError' */
  else if (method_method() == 0) {
    softcall_nosuchmethod(method_class(), method_name(), method_sig());
    low = method_returntype();
    pop(method_nargs());
    METHOD_RETURN_VALUE();
  }
  else {
    idx = method_nargs();
    
    /* Push arguments */
    build_call_frame(method_sig(), 0, idx);
    
    pop(idx);
    begin_func_sync();
    
    /* Call it */
    low = method_returntype();
    
    softcall_initialise_class(method_class()); /* JJC */
    beg = virtualMachine(method_method(), sp+1, retval, tid, PASSON, thr); /* JJC */
    
    /* call_indirect_method(method_method()); removed by JJC */
    
    /* START JJC */
    if( reverse_method == T_RETRY ) {
      reverse_method = T_FWDS_INTO;
      valid_log = 1;
    } else if( reverse_method == T_RETRY_OVER || reverse_method == T_RETRY_OVER_FIRST ) {
      valid_log = 1;
    }
    /* END JJC */
    
    if( valid_log && ( beg == F_END ) ) wcbuffpc( pc + METHOD_OFFSET, debug ); /* JJC */
    
    /* Pop args */
    popargs();
    
    end_func_sync();
    METHOD_RETURN_VALUE();
    
    /* START JJC (if exited from start reverse to last line) */
    if( beg == F_BEG ) {
      ret = reverseVirtualMachine( meth, lcl, &sp, &npc, retval, mjbuf, tid,
				   debug, callback, meth->fullSourceFile, &opsobjs, lvtobjs,
				   reverse_method == T_RETRY_OVER ? R_OVER : R_INTO, 
				   &cl, &seen_new_line, code, thr, false );
      if( ret == F_BEG ) {
	D_FL( fprintf( stderr, "------RUN VIRTUAL MACHINE: exit: ret == F_BEG\n" ) );
	return F_BEG;
      }
      else if( ret == F_CATCH ) {
	D_FL( fprintf( stderr, "------RUN VIRTUAL MACHINE: exit: ret == F_CATCH\n" ) );
	return F_RETRY; /* not sure */
      }
    }
    assert( reverse_method != T_RETRY_OVER );
    if( reverse_method == T_RETRY_OVER || reverse_method == T_RETRY_OVER_FIRST )
      reverse_method = T_FWDS_INTO; 
    /* END JJC */
    
  }
}

define_insn(INVOKEINTERFACE)
{
	/*
	 * ..., obj, ..args.., -> ...
	 */
        int8 beg = F_END; /* JJC */
	if( valid_log ) (debug->last_method) = meth; /* JJC */

	check_pcidx (0);
	check_pc (2);

	idx = (uint16)((getpc(0) << 8) | getpc(1));
	trace_jcode (("invokeinterface %d\n", idx));

	get_interface_method_info_noerror(idx);

	if( valid_log ) {                         /* JJC */
	  savestackandn( (uint8)getpc( 2 ) );    /* JJC */
	}                                         /* JJC */

	/* If class doesn't exist, call 'NoSuchClassError' */
	if (method_class() == 0) {
		softcall_nosuchclass(method_classname());
		low = method_returntype();
		pop((uint8)getpc(2));
		METHOD_RETURN_VALUE();
	}
	/* If method doesn't exist, call 'NoSuchMethodError' */
	else if (method_method() == 0) {
		softcall_nosuchmethod(method_class(), method_name(), method_sig());
		low = method_returntype();
		pop((uint8)getpc(2));
		METHOD_RETURN_VALUE();
	}
	else {
	        void *ptf; /* JJC */
		idx = (uint8)getpc(2) - 1;
		ptf = ( stack( idx ) )[0].v.taddr; /* JJC */

		check_null(INVOKEINTERFACE, stack(idx), 34);

		check_stack_ref(idx);

		slot_alloctmp(tmp);
		softcall_lookupinterfacemethod(tmp, method_method(), stack(idx));

		/* Push arguments & object */
		build_call_frame(method_sig(), stack(idx), idx);
		idx++;

		slot_nowriteback(tmp);
		pop(idx);
		begin_func_sync();

		/* Call it */
		low = method_returntype();
		
		softcall_initialise_class(method_class()); /* JJC */
		beg = virtualMachine((methods*)(tmp)[0].v.taddr, sp+1, retval, tid, PASSON, thr); /* JJC */
		/* START JJC */
		if( reverse_method == T_RETRY ) {
		  reverse_method = T_FWDS_INTO;
		  valid_log = 1;
		} else if( reverse_method == T_RETRY_OVER || reverse_method == T_RETRY_OVER_FIRST ) {
		  valid_log = 1;
		}
		/* END JJC */
		
		/* START JJC (mark end of function) */
		if( valid_log && ( beg == F_END ) ) {
		  slots s;
		  s.v.taddr = ptf;
		  wcbuffs( s, 1, debug, thr );
		  wcbuffpc( pc + METHOD_OFFSET, debug );
		}
		/* END JJC */

		/* call(tmp); removed by JJC */
		slot_freetmp(tmp);

		/* Pop args */
		popargs();

		end_func_sync();
		METHOD_RETURN_VALUE();

		/* START JJC (if exited from start reverse to last line) */
		if( beg == F_BEG ) {
		  ret = reverseVirtualMachine( meth, lcl, &sp, &npc, retval, mjbuf, tid,
					       debug, callback, meth->fullSourceFile, &opsobjs, lvtobjs,
					       reverse_method == T_RETRY_OVER ? R_OVER : R_INTO, 
					       &cl, &seen_new_line, code, thr, false );
		  if( ret == F_BEG ) {
		    D_FL( fprintf( stderr, "------RUN VIRTUAL MACHINE: exit: ret == F_BEG\n" ) );
		    return F_BEG;
		  }
		  else if( ret == F_CATCH ) {
		    D_FL( fprintf( stderr, "------RUN VIRTUAL MACHINE: exit: ret == F_CATCH\n" ) );
		    return F_RETRY; 
		  }
		}
		assert( reverse_method != T_RETRY_OVER );
		if( reverse_method == T_RETRY_OVER || reverse_method == T_RETRY_OVER_FIRST )
		  reverse_method = T_FWDS_INTO;
		/* END JJC */

	}
}

define_insn(NEW)
{
	/*
	 * ... ->  ..., object ref
	 */
	check_pcidx (0);

	idx = (uint16)((getpc(0) << 8) | getpc(1));
	trace_jcode (("new %d\n", idx));

	get_class_info_noerror(idx);
	push(1);
	markisobj; /* JJC */
	if (class_object() == 0) {
		softcall_nosuchclass(class_name(idx));
	}
	else {
		softcall_new(stack(0), class_object());
	}
}

define_insn(NEWARRAY)
{
	/*
	 * ... size ->  ..., object ref
	 */
	check_pc (0);
	check_stack_int(0);

	low = (uint8)getpc(0);
	trace_jcode (("newarray %d\n", low));

	softcall_newarray(stack(0), stack(0), low);
	markisobj; /* JJC */
}

define_insn(ANEWARRAY)
{
	/*
	 * ... size ->  ..., object ref
	 */
	check_pcidx (0);
	check_stack_int(0);

	idx = (uint16)((getpc(0) << 8) | getpc(1));
	trace_jcode (("anewarray %d\n", idx));

	get_class_info_noerror(idx);
	if (class_object() == 0) {
		softcall_nosuchclass(class_name(idx));
	}
	else {
		softcall_anewarray(stack(0), stack(0), class_object());
	}
	markisobj; /* JJC */
}

define_insn(ARRAYLENGTH)
{
	/*
	 * ..., obj -> ..., length
	 */
	trace_jcode (("arraylength\n"));

	check_null(ARRAYLENGTH, rstack(0), 34);

	check_stack_array(0);

	load_offset_int(stack(0), rstack(0), object_array_length);
	marknotobj_int; /* JJC */
}

define_insn(ATHROW)
{
	/*
	 * ..., obj -> undefined
	 */
	trace_jcode (("athrow\n"));

	check_null(ATHROW, rstack(0), 34);

	check_stack_ref(0);

	softcall_athrow(rstack(0));
}

define_insn(CHECKCAST)
{
	/*
	 * ..., obj -> ..., obj
	 */
	check_pcidx (0);
	check_stack_ref(0);

	idx = (uint16)((getpc(0) << 8) | getpc(1));
	trace_jcode (("checkcast %d\n", idx));

	get_class_info_noerror(idx);
	if (class_object() == 0) {
		softcall_nosuchclass(class_name(idx));
	}
	else {
		softcall_checkcast(stack(0), rstack(0), class_object());
	}
}

define_insn(INSTANCEOF)
{
	/*
	 * ..., obj -> ..., result
	 */
	check_pcidx (0);
	check_stack_ref(0);

	idx = (uint16)((getpc(0) << 8) | getpc(1));
	trace_jcode (("instanceof %d\n", idx));

	get_class_info_noerror(idx);
	if (class_object() == 0) {
		softcall_nosuchclass(class_name(idx));
	}
	else {
		softcall_instanceof(stack(0), rstack(0), class_object());
	}
	marknotobj_int; /* JJC */
}

define_insn(MONITORENTER)
{
	/*
	 * ... obj -> ...
	 */
	trace_jcode (("monitorenter\n"));

	check_null(MONITORENTER, rstack(0), 34);

	check_stack_ref(0);
	begin_func_sync();

	softcall_monitorenter(rstack(0));
	pop(1);

	end_func_sync();
}

define_insn(MONITOREXIT)
{
	/*
	 * ... obj -> ...
	 */
	trace_jcode (("monitorexit\n"));

	check_null(MONITOREXIT, rstack(0), 34);

	check_stack_ref(0);
	begin_func_sync();

	softcall_monitorexit(rstack(0));
	pop(1);

	end_func_sync();
}

define_insn(WIDE)
{
	/* Move PC to widened instruction */
	pc = npc;
	npc = pc + insnLen[getopcode()] + 1;

	switch(getopcode()) {
	default:
		ABORT();

	define_wide_insn(ILOAD)
	{
		/*
		 * ..., -> ..., local variable
		 */
		check_pcidx (0);
		idx = (uint16)((getpc(0) << 8) | getpc(1));
		trace_jcode (("wide iload %d\n", idx));

		check_local_int(idx);
 
		push(1);
		move_int(stack(0), local(idx));
		marknotobj_int; /* JJC */
	}
	define_wide_insn(FLOAD)
	{
		/*
		 * ..., -> ..., local variable
		 */
		check_pcidx (0);
		idx = (uint16)((getpc(0) << 8) | getpc(1));
		trace_jcode (("wide fload %d\n", idx));

		check_local_float(idx);
 
		push(1);
		move_float(stack(0), local_float(idx));
		marknotobj_float; /* JJC */
	}
	define_wide_insn(ALOAD)
	{
		/*
		 * ..., -> ..., local variable
		 */
		check_pcidx (0);
		idx = (uint16)((getpc(0) << 8) | getpc(1));
		trace_jcode (("wide aload %d\n", idx));
                
		check_local_ref(idx);  
 
		push(1);
		move_ref(stack(0), local(idx));
		/* START JJC */
		if( valid_log )
		  if( opsobjs )
		    *opsobjs = lvtobjs[ idx ];
		/* END JJC */
	}
	define_wide_insn(LLOAD)
	{
		/*      
		 * ..., -> ..., long local variable
		 */
		check_pcidx (0);
		idx = (uint16)((getpc(0) << 8) | getpc(1));
		trace_jcode (("wide lload %d\n", idx));
                
		check_local_long(idx+1);

		push(2);
		move_long(stack_long(0), local_long(idx));
		marknotobj2_long; /* JJC */
	}
	define_wide_insn(DLOAD)
	{
		/*      
		 * ..., -> ..., double local variable
		 */
		check_pcidx (0);
		idx = (uint16)((getpc(0) << 8) | getpc(1));
		trace_jcode (("wide dload %d\n", idx));
                
		check_local_double(idx+1);

		push(2);
		move_double(stack_double(0), local_double(idx));
		marknotobj2_double; /* JJC */
	}
	define_wide_insn(ISTORE)
	{
		/*      
		 * ..., var -> ...
		 */
		check_pcidx (0);
		idx = (uint16)((getpc(0) << 8) | getpc(1));
		trace_jcode (("wide istore %d\n", idx));

		check_stack_int(0);
         	swap_any( local( idx ), stack( 0 ) ); /* JJC */
		/* START JJC */
		if( opsobjs ) {
		  *opsobjs = lvtobjs[ idx ];
		  lvtobjs[ idx ] = NOTOBJ_INT;
		}
		/* END JJC */
		if( valid_log ) savestack( 1 ); /* JJC */

		pop(1); 
	}
	define_wide_insn(FSTORE)
	{
		/*      
		 * ..., var -> ...
		 */
		check_pcidx (0);
		idx = (uint16)((getpc(0) << 8) | getpc(1));
		trace_jcode (("wide fstore %d\n", idx));
 
		check_stack_float(0);
         
		/*move_float(local_float(idx), stack(0));*/
		swap_any( local_float( idx ), stack( 0 ) ); /* JJC */
		/* START JJC */
		if( opsobjs ) {
		  *opsobjs = lvtobjs[ idx ];
		  lvtobjs[ idx ] = NOTOBJ_FLOAT;
		}
		/* END JJC */
		if( valid_log ) savestack( 1 ); /* JJC */

		pop(1); 
	}
	define_wide_insn(ASTORE)
	{
		/*
		 * ..., var -> ...
		 */
		check_pcidx (0);
		idx = (uint16)((getpc(0) << 8) | getpc(1));
		trace_jcode (("wide astore %d\n", idx));

		check_stack_ref(0);

		/*move_ref(local(idx), stack(0));*/
		
		/* START JJC */
		swap_any( local( idx ), stack( 0 ) ); 
		if( opsobjs ) {
		  oldopsobjs = *opsobjs;
		  *opsobjs = lvtobjs[ idx ];
		  lvtobjs[ idx ] = oldopsobjs;
		}
		if( valid_log ) savestack( 1 ); 
		/* END JJC */
		
		pop(1);
	}
	define_wide_insn(LSTORE)
	{
		/*      
		 * ..., long var -> ...
		 */
		check_pcidx (0);
		idx = (uint16)((getpc(0) << 8) | getpc(1));
		trace_jcode (("wide lstore %d\n", idx));

		check_stack_long(0);
 
		/*move_long(local_long(idx), stack_long(0));*/
		swap_long( local_long( idx ), stack_long( 0 ) ); /* JJC */
		/* START JJC */
		if( opsobjs ) {
		  *( opsobjs - 1 ) = lvtobjs[ idx ];
		  *opsobjs = lvtobjs[ idx + 1 ];
		  lvtobjs[ idx ] = NOTOBJ_LONG;
		  lvtobjs[ idx + 1 ] = NOTOBJ_SKIP;
		}
		/* END JJC */
		if( valid_log ) savestack( 2 ); /* JJC */		
		pop(2);
	}
	define_wide_insn(DSTORE)
	{
		/*      
		 * ..., var -> ...
		 */
		check_pcidx (0);
		idx = (uint16)((getpc(0) << 8) | getpc(1));
		trace_jcode (("wide dstore %d\n", idx));

		check_stack_double(0);

		/*move_double(local_double(idx), stack_double(0));*/
		swap_long( local_double( idx ), stack_double( 0 ) ); /* JJC */
		/* START JJC */
		if( opsobjs ) {
		  *( opsobjs - 1 ) = lvtobjs[ idx ];
		  *opsobjs = lvtobjs[ idx + 1 ];
		  lvtobjs[ idx ] = NOTOBJ_DOUBLE;
		  lvtobjs[ idx + 1 ] = NOTOBJ_SKIP;
		}
		/* END JJC */
		if( valid_log ) savestack( 2 ); /* JJC */
		
		pop(2);
	}
	define_wide_insn(IINC)
	{
		check_pcidx (0);
		check_pcidx (2);
		idx = (uint16)((getpc(0) << 8) | getpc(1));
		low = (int16)((getpc(2) << 8) | getpc(3));
		trace_jcode (("wide iinc %d %d\n", idx, low));

		check_local_int(idx);

		add_int_const(local(idx), local(idx), low);

		npc += 1;	/* Extra one */
	}
	}
}

define_insn(MULTIANEWARRAY)
{
	/*
	 * ... size1, size2, ... sizen ->  ..., object ref
	 */
	check_pcidx (0);
	check_pc (2);

	idx = (uint16)((getpc(0) << 8) | getpc(1));
	low = (uint8)getpc(2);

	if( valid_log ) savestackandn( low ); /* JJC */

	trace_jcode (("multinewarray %d %d\n", idx, low));

	for (high = 0; high < low; high++) {
		check_stack_int(high);
	}

	get_class_info(idx);

	/* NB: softcall does the necessary stack adjustments */
	softcall_multianewarray(stack(low-1), low, stack(0), class_object());
	markisobj; /* JJC */
}

define_insn(IFNULL)
{
	check_pcidx (0);
	check_stack_ref(0);

	idx = (int16)((getpc(0) << 8) | getpc(1));
	trace_jcode (("ifnull %d\n", pc + idx));

	slot_nowriteback(stack(0));
	begin_sync();

	cbranch_ref_const_eq(rstack(0), 0, reference_code_label(pc+idx));
	pop(1);

	end_sync();
}

define_insn(IFNONNULL)
{
	check_pcidx (0);
	check_stack_ref(0);

	idx = (int16)((getpc(0) << 8) | getpc(1));
	trace_jcode (("ifnonnull %d\n", pc + idx));

	slot_nowriteback(stack(0));

	begin_sync();

	cbranch_ref_const_ne(rstack(0), 0, reference_code_label(pc+idx));
	pop(1);

	end_sync();
}

define_insn(GOTO_W)
{
	check_pcwidx (0);

	idx = (int32)((getpc(0) << 24) | (getpc(1) << 16) |
				(getpc(2) << 8) | getpc(3));

	trace_jcode (("goto_w %d\n", pc + idx));

	begin_sync();
	branch_a(reference_code_label(pc+idx));
	end_sync();
}

define_insn(JSR_W)
{
	/*
	 * ... -> ..., ret-addr
	 */
	check_pcwidx (0);

	idx = (int32)((getpc(0) << 24) | (getpc(1) << 16) |
				(getpc(2) << 8) | getpc(3));

	trace_jcode (("jsr_w %d\n", pc + idx));

	push(1);
	move_label_const(stack(0), reference_code_label(npc));
	begin_sync();
	branch_a(reference_code_label(pc+idx));
	end_sync();
}

define_insn(BREAKPOINT)
{
	trace_jcode (("breakpoint\n"));

	softcall_breakpoint();
}
