/*
 * $Id: jexc_vm.h,v 1.7 2000/09/29 09:59:56 msato Exp $
 * $RWC_Release: Omni-1.6 $
 * $RWC_Copyright:
 *  Omni Compiler Software Version 1.5-1.6
 *  Copyright (C) 2002 PC Cluster Consortium
 *  
 *  This software is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU Lesser General Public License version
 *  2.1 published by the Free Software Foundation.
 *  
 *  Omni Compiler Software Version 1.0-1.4
 *  Copyright (C) 1999, 2000, 2001.
 *   Tsukuba Research Center, Real World Computing Partnership, Japan.
 *  
 *  Please check the Copyright and License information in the files named
 *  COPYRIGHT and LICENSE under the top  directory of the Omni Compiler
 *  Software release kit.
 *  
 *  
 *  $
 */
#include "omniConfig.h"
#include "jexc_runtime.h"
#include "jexc_sys_class.h"

jexc_any tmp1,tmp2;

#define SWAP_TMP tmp1.i

/* note: on memory, order is low and high */
#define POP2_tmp1 \
sp -= 2; tmp1.HL.high = *((jexc_int *)(sp+1)); tmp1.HL.low = *((jexc_int *)sp);
#define POP2_tmp2 \
sp -= 2; tmp2.HL.high = *((jexc_int *)(sp+1)); tmp2.HL.low = *((jexc_int *)sp);
#define PUSH2_tmp1 \
*((jexc_int *)(sp+1)) = tmp1.HL.high; *((jexc_int *)sp) = tmp1.HL.low; sp += 2;

#define OP_PUSH_INT(n)		*((jexc_int *)(sp++)) = (n)
#define OP_PUSH_STRING(i) 	*sp++ = (jexc_word)(jexc_string_table[(i)])
#define OP_PUSH_WORD(w) 	*sp++ = (w)
#define OP_PUSH_LONG(low,high)  \
*((jexc_int *)(sp)) = (low); *((jexc_int *)(sp+1)) = (high); sp += 2
#define OP_PUSH_FLOAT(f) 	*((jexc_float *)(sp++)) = (f)
#define OP_PUSH_DOUBLE(x)	tmp1.d = x; PUSH2_tmp1

/* 
 *  headers
 */
#define JEXC_BEGIN_INITIALIZE void jexc_class_initialize(){ \
    jexc_class *current_class;
#define JEXC_END_INITIALIZE }

#define CLASS_INIT_BEGIN(name,id,super,i_static,n_static,i_var,n_var,n_method)\
 current_class = jexc_define_class(name,id,super,i_static,n_static,i_var,n_var,n_method);

#define CLASS_METHOD(f,i) current_class->methods[i] = f;

#define CLASS_INTERFACE(m_id,disp) \
jexc_add_interface(current_class,m_id,disp);

#define CLASS_FIELD_INIT_B(disp,x) \
*((jexc_byte *)(current_class->i_static_base+disp)) = x;
#define CLASS_FIELD_INIT_Z(disp,x) \
*((jexc_byte *)(current_class->i_static_base+disp)) = x;
#define CLASS_FIELD_INIT_C(disp,x) \
*((jexc_short *)(current_class->i_static_base+disp)) = x;
#define CLASS_FIELD_INIT_S(disp,x) \
*((jexc_short *)(current_class->i_static_base+disp)) = x;
#define CLASS_FIELD_INIT_I(disp,x) \
*((jexc_int *)(current_class->i_static_base+disp)) = x;
#define CLASS_FIELD_INIT_F(disp,x) \
*((jexc_int *)(current_class->i_static_base+disp)) = x;

#define CLASS_FIELD_INIT_L(disp,id) \
current_class->n_static_base[disp] = (jexc_word)jexc_string_table[id];

/* not yet */
#define CLASS_FIELD_INIT_J(disp,x_l,x_h)
#define CLASS_FIELD_INIT_D(disp,x_l,x_h)

#define CLASS_INIT_END 	/* do nothing */

#define JEXC_DEFINE_MAIN(c,m) \
int main(int argc,char *argv[]) { jexc_run_main(argc,argv,c,m); }

#define DEFINE_METHOD(fname) \
void fname(jexc_word **spp) { \
register jexc_word *fp,*sp; jexc_word *sp0; jexc_word *top_save = Top; \
int pc; int jsr_ret_lab; int have_catch = FALSE;

#define END_METHOD \
ret_exit:  Top = top_save; \
if(have_catch) jexc_catch_p = jexc_catch_p->link; return; }

#define INIT_METHOD(max_stack,n_local,narg) \
fp = *spp; sp = fp+n_local; Top = sp + max_stack;

#define EXCEPTION_TABLE_BEGIN { \
jexc_catch_info catch_info; catch_info.top_save = Top; \
catch_info.link = jexc_catch_p; jexc_catch_p = &catch_info; \
have_catch = TRUE; if(setjmp(catch_info.env) != 0){

#define EXECPTION_DEF(start,end,handlers,id) \
if(jexc_catch_match(pc,start,end,id)){ \
  *sp++ = jexc_throw_object; goto handlers; }

#define EXCEPTION_TABLE_END jexc_throw(NULL); }}

#define CHECK_PC(i)	pc = i

#define RET_TABLE_BEGIN jsr_ret: switch(jsr_ret_lab){ 
#define RET_LABEL(n,l)	case (n): goto l;
#define RET_TABLE_END 	default: jexc_error("ret_label"); }

/*
 *  opcode 
 */
#define OP_nop() /* nothing */

#define OP_invokevirtual(c,i,narg) \
sp -= (narg+1); sp0 = sp; (*((*sp)->class->methods[i]))(&sp0); sp = sp0

#define OP_invokespecial(c,i,narg) \
sp -= (narg+1); sp0 = sp; (*(jexc_class_table[c]->methods[i]))(&sp0); sp = sp0

#define OP_invokestatic(c,i,narg) \
sp -= narg; sp0 = sp; (*(jexc_class_table[c]->methods[i]))(&sp0); sp = sp0

#define OP_return() goto ret_exit;

#define OP_ireturn() fp[0]=sp[-1]; *spp += 1; goto ret_exit;
#define OP_areturn() fp[0]=sp[-1]; *spp += 1; goto ret_exit;
#define OP_freturn() fp[0]=sp[-1]; *spp += 1; goto ret_exit;

#define OP_lreturn() fp[0]=sp[-2]; fp[1]=sp[-1]; *spp += 2; goto ret_exit;
#define OP_dreturn() fp[0]=sp[-2]; fp[1]=sp[-1]; *spp += 2; goto ret_exit;

#define OP_invokeinterface(c,i,narg) \
sp -= narg; sp0 = sp; (*(jexc_class_table[c]->methods[i]))(&sp0); sp = sp0

#define CALL_INTERFACE(id) (*jexc_lookup_interface((*spp)[0],id))(spp);

#define OP_jsr(lab,ret_lab) 	*((jexc_int *)(sp++)) = ret_lab; goto lab;
#define OP_ret(v) 	jsr_ret_lab = *((jexc_int *)(fp+v)); goto jsr_ret;

#define OP_athrow() 	sp--; jexc_throw(*sp)

#define OP_new(i)  *sp++ = jexc_new_object(jexc_class_table[i])

#define OP_newarray(i)	\
*(sp-1) = (jexc_word)jexc_new_iarray(*((jexc_int *)(sp-1)),i)

#define OP_anewarray(i)	\
*(sp-1) = (jexc_word)jexc_new_array(*((jexc_int *)(sp-1)))

#define OP_multianewarray(i,ndim) \
sp -= ((n)-1); sp[-1] = (jexc_word)jexc_new_multiarray(ndim,sp-1)

#define OP_checkcast(i) jexc_checkcast(sp[-1],jexc_class_table[i])
#define OP_instanceof(i) \
*((jexc_int *)(sp-1)) = jexc_instanceof(*(sp-1),jexc_class_table[i])

#define OP_pop()   --sp
#define OP_pop2()  sp -= 2
#define OP_dup()   *sp = *(sp-1); sp++
#define OP_dup2()  sp += 2; sp[-1] = sp[-3]; sp[-2] = sp[-4]
#define OP_dup_x1() *sp = sp[-1]; sp[-1] = sp[-2]; sp[-2] = *sp; sp++
#define OP_dup_x2() *sp = sp[-1]; sp[-1] = sp[-2]; sp[-2] = sp[-3]; sp[-3] = *sp; sp++
#define OP_dup2_x1() \
sp +=2; sp[-1]=sp[-3]; sp[-2]=sp[-4]; sp[-3]=sp[-5]; \
sp[-4]=sp[-1]; sp[-5]=sp[-2];
#define OP_dup2_x2() \
sp +=2; sp[-1]=sp[-4]; sp[-2]=sp[-5]; sp[-3]=sp[-6]; sp[-4]=sp[-7]; \
sp[-5]=sp[-1]; sp[-6]=sp[-2];
#define OP_swap() SWAP_TEP = sp[-1]; sp[-1] = sp[-2]; sp[-2] = SWAP_TMP

/* 
 * pushd constant 
 */
/* bipush,sipush,ldc,ldc_w,ldc2_w */

#define OP_aconst_null() *(sp++) = 0

#define OP_iconst_m1() OP_PUSH_INT(-1)
#define OP_iconst_0() OP_PUSH_INT(0)
#define OP_iconst_1() OP_PUSH_INT(1)
#define OP_iconst_2() OP_PUSH_INT(2)
#define OP_iconst_3() OP_PUSH_INT(3)
#define OP_iconst_4() OP_PUSH_INT(4)
#define OP_iconst_5() OP_PUSH_INT(5)

#define OP_lconst_0() OP_PUSH_LONG(0,0)
#define OP_lconst_1() OP_PUSH_LONG(1,0)
#define OP_fconst_0() OP_PUSH_FLOAT(0.0)
#define OP_fconst_1() OP_PUSH_FLOAT(1.0)
#define OP_fconst_2() OP_PUSH_FLOAT(2.0)
#define OP_dconst_0() OP_PUSH_DOUBLE(0.0)
#define OP_dconst_1() OP_PUSH_DOUBLE(1.0)

/* B: byte
 * C: char
 * D: double
 * F: float
 * I: int
 * J: long
 * S: short
 * Z: boolean
 */

#define STATIC_L(c,i) jexc_class_table[c]->n_static_base[i]
#define STATIC_B(c,i) \
(*((jexc_byte *)(jexc_class_table[c]->i_static_base+(i))))
#define STATIC_S(c,i) \
(*((jexc_short *)(jexc_class_table[c]->i_static_base+(i))))
#define STATIC_I(c,i) \
(*((jexc_int *)(jexc_class_table[c]->i_static_base+(i))))

#define OP_getstatic_L(c,i)   *sp++ = STATIC_L(c,i)
#define OP_getstatic_Z(c,i) 	*((jexc_int *)(sp++)) = STATIC_B(c,i)
#define OP_getstatic_B(c,i)	*((jexc_int *)(sp++)) = STATIC_B(c,i)
#define OP_getstatic_C(c,i) 	*((jexc_int *)(sp++)) = STATIC_S(c,i)
#define OP_getstatic_S(c,i)	*((jexc_int *)(sp++)) = STATIC_S(c,i)
#define OP_getstatic_F(c,i)	*((jexc_int *)(sp++)) = STATIC_I(c,i)
#define OP_getstatic_I(c,i)	*((jexc_int *)(sp++)) = STATIC_I(c,i)
#define OP_getstatic_D(c,i)	OP_getstatic_J(c,i)
#define OP_getstatic_J(c,i) \
tmp1.HL.low=STATIC_I(c,i); tmp1.HL.high=STATIC_I(c,i+4);PUSH2_tmp1

#define OP_putstatic_L(c,i)   	STATIC_L(c,i) = *(--sp)
#define OP_putstatic_Z(c,i) 	STATIC_B(c,i) = *((jexc_int *)(--sp))
#define OP_putstatic_B(c,i)	STATIC_B(c,i) = *((jexc_int *)(--sp))
#define OP_putstatic_C(c,i) 	STATIC_S(c,i) = *((jexc_int *)(--sp))
#define OP_putstatic_S(c,i)	STATIC_S(c,i) = *((jexc_int *)(--sp))
#define OP_putstatic_F(c,i)	STATIC_I(c,i) = *((jexc_int *)(--sp))
#define OP_putstatic_I(c,i)	STATIC_I(c,i) = *((jexc_int *)(--sp))
#define OP_putstatic_D(c,i)  OP_putstatic_J(c,i)
#define OP_putstatic_J(c,i) \
POP2_tmp1; STATIC_I(c,i)=tmp1.HL.low;FIELD_I(c,i+4)=tmp1.HL.high; 

#define FIELD_L(p,i) (p)->n_var_base[i]
#define FIELD_B(p,i) (*((jexc_byte *)((p)->i_var_base+(i))))
#define FIELD_S(p,i) (*((jexc_short *)((p)->i_var_base+(i))))
#define FIELD_I(p,i) (*((jexc_int *)((p)->i_var_base+(i))))

#define OP_getfield_L(c,i)	sp[-1] = FIELD_L(sp[-1],i)
#define OP_getfield_Z(c,i) 	*((jexc_int *)(sp-1)) = FIELD_B(sp[-1],i)
#define OP_getfield_B(c,i)	*((jexc_int *)(sp-1)) = FIELD_B(sp[-1],i)
#define OP_getfield_C(c,i)	*((jexc_int *)(sp-1)) = FIELD_S(sp[-1],i)
#define OP_getfield_S(c,i)	*((jexc_int *)(sp-1)) = FIELD_S(sp[-1],i)
#define OP_getfield_F(c,i)	*((jexc_int *)(sp-1)) = FIELD_I(sp[-1],i)
#define OP_getfield_I(c,i)	*((jexc_int *)(sp-1)) = FIELD_I(sp[-1],i)
#define OP_getfield_D(c,i)	OP_getfield_J(c,i)
#define OP_getfield_J(c,i) \
sp--; tmp1.HL.low=FIELD_I(*sp,i); tmp1.HL.high=FIELD_I(*sp,i+4);PUSH2_tmp1

#define OP_putfield_L(c,i)	sp-=2; FIELD_L(*sp,i) = sp[1]
#define OP_putfield_Z(c,i) 	sp-=2; FIELD_B(*sp,i) = *((jexc_int*)(sp+1))
#define OP_putfield_B(c,i)	sp-=2; FIELD_B(*sp,i) = *((jexc_int*)(sp+1))
#define OP_putfield_C(c,i)	sp-=2; FIELD_S(*sp,i) = *((jexc_int*)(sp+1))
#define OP_putfield_S(c,i)	sp-=2; FIELD_S(*sp,i) = *((jexc_int*)(sp+1))
#define OP_putfield_F(c,i)	sp-=2; FIELD_I(*sp,i) = *((jexc_int*)(sp+1))
#define OP_putfield_I(c,i)	sp-=2; FIELD_I(*sp,i) = *((jexc_int*)(sp+1))
#define OP_putfield_D(c,i)  OP_putfield_J(c,i)
#define OP_putfield_J(c,i) \
POP2_tmp1; sp--; FIELD_I(*sp,i)=tmp1.HL.low;FIELD_I(*sp,i+4)=tmp1.HL.high; 

#define OP_iload_0()  OP_iload(0)
#define OP_iload_1()  OP_iload(1)
#define OP_iload_2()  OP_iload(2)
#define OP_iload_3()  OP_iload(3)
#define OP_iload(x)   *sp++ = fp[x]

#define OP_lload_0()  OP_lload(0)
#define OP_lload_1()  OP_lload(1)
#define OP_lload_2()  OP_lload(2)
#define OP_lload_3()  OP_lload(3)
#define OP_lload(x)   *sp++ = fp[x]; *sp++ = fp[x+1];

#define OP_dload_0()  OP_dload(0)
#define OP_dload_1()  OP_dload(1)
#define OP_dload_2()  OP_dload(2)
#define OP_dload_3()  OP_dload(3)
#define OP_dload(x)   *sp++ = fp[x]; *sp++ = fp[x+1];

#define OP_aload_0()  OP_aload(0)
#define OP_aload_1()  OP_aload(1)
#define OP_aload_2()  OP_aload(2)
#define OP_aload_3()  OP_aload(3)
#define OP_aload(x)	*sp++ = fp[x]

#define OP_istore_0() OP_istore(0)
#define OP_istore_1() OP_istore(1)
#define OP_istore_2() OP_istore(2)
#define OP_istore_3() OP_istore(3)
#define OP_istore(x)  fp[x] = *(--sp)

#define OP_lstore_0() OP_lstore(0)
#define OP_lstore_1() OP_lstore(1)
#define OP_lstore_2() OP_lstore(2)
#define OP_lstore_3() OP_lstore(3)
#define OP_lstore(x)  fp[x+1] = *(--sp); fp[x] = *(--sp)

#define OP_dstore_0() OP_dstore(0)
#define OP_dstore_1() OP_dstore(1)
#define OP_dstore_2() OP_dstore(2)
#define OP_dstore_3() OP_dstore(3)
#define OP_dstore(x)  fp[x+1] = *(--sp); fp[x] = *(--sp)

#define OP_astore_0() OP_astore(0)
#define OP_astore_1() OP_astore(1)
#define OP_astore_2() OP_astore(2)
#define OP_astore_3() OP_astore(3)
#define OP_astore(x)  fp[x] = *(--sp)

#define OP_arraylength() \
*((jexc_int *)(sp-1)) = ((jexc_array *)(*(sp-1)))->length

#define AELEM_A(ap,i) ((jexc_array *)(ap))->elem[i]
#define AELEM_B(ap,i) *(((jexc_byte *)(((jexc_iarray *)(ap))->base))+(i))
#define AELEM_C(ap,i) *(((jexc_char *)(((jexc_iarray *)(ap))->base))+(i))
#define AELEM_F(ap,i) *(((jexc_float *)(((jexc_iarray *)(ap))->base))+(i))
#define AELEM_I(ap,i) *(((jexc_int *)(((jexc_iarray *)(ap))->base))+(i))
#define AELEM_S(ap,i) *(((jexc_short *)(((jexc_iarray *)(ap))->base))+(i))
#define AELEM_L_L(ap,i) *(((jexc_int *)(((jexc_iarray *)(ap))->base))+(i))
#define AELEM_L_H(ap,i) *(((jexc_int *)(((jexc_iarray *)(ap))->base))+(i)+1)

#define OP_aaload() \
sp--; *((jexc_word *)(sp-1)) = AELEM_A(*(sp-1),*((jexc_int *)sp))
#define OP_iaload() \
sp--; *((jexc_int *)(sp-1)) = AELEM_I(*(sp-1),*((jexc_int *)sp))
#define OP_baload() \
sp--; *((jexc_int *)(sp-1)) = AELEM_B(*(sp-1),*((jexc_int *)sp))
#define OP_caload() \
sp--; *((jexc_int *)(sp-1)) = AELEM_C(*(sp-1),*((jexc_int *)sp))
#define OP_saload() \
sp--; *((jexc_int *)(sp-1)) = AELEM_S(*(sp-1),*((jexc_int *)sp))

#define OP_daload() OP_laload()
#define OP_laload() \
tmp1.HL.low = AELEM_L_L(*(sp-2),*((jexc_int *)(sp-1))); \
tmp1.HL.high = AELEM_L_H(*(sp-2),*((jexc_int *)(sp-1))); \
*((jexc_int *)(sp-2)) = tmp1.HL.low; *((jexc_int *)(sp-1)) = tmp1.HL.high;

#define OP_aastore() \
sp -= 3;  AELEM_A(*sp,*((jexc_int *)(sp+1))) = *((jexc_word *)(sp+2))
#define OP_iastore() \
sp -= 3; AELEM_I(*sp,*((jexc_int *)(sp+1))) = *((jexc_int *)(sp+2))
#define OP_bastore() \
sp -= 3; AELEM_B(*sp,*((jexc_int *)(sp+1))) = *((jexc_int *)(sp+2))
#define OP_castore() \
sp -= 3; AELEM_C(*sp,*((jexc_int *)(sp+1))) = *((jexc_int *)(sp+2))
#define OP_sastore() \
sp -= 3; AELEM_S(*sp,*((jexc_int *)(sp+1))) = *((jexc_int *)(sp+2))

#define OP_dastore() OP_lastore()
#define OP_lastore() POP2_tmp1; sp -= 2; \
AELEM_L_L(sp,*((jexc_int *)(sp+1))) = tmp1.HL.low; \
AELEM_L_H(sp,*((jexc_int *)(sp+1))) = tmp1.HL.high; 

#define OP_iinc(x,n) *((jexc_int *)(fp+x)) += (n)

#define OP_goto(L) 	goto L

#define OP_ifeq(L) sp--; if(*((jexc_int *)sp) == 0) goto L
#define OP_ifne(L) sp--; if(*((jexc_int *)sp) != 0) goto L
#define OP_ifge(L) sp--; if(*((jexc_int *)sp) >= 0) goto L
#define OP_ifgt(L) sp--; if(*((jexc_int *)sp) > 0) goto L
#define OP_iflt(L) sp--; if(*((jexc_int *)sp) < 0) goto L
#define OP_ifle(L) sp--; if(*((jexc_int *)sp) <= 0) goto L

#define OP_if_icmpeq(L)\
sp -= 2; if(*((jexc_int *)sp) == *((jexc_int *)(sp+1))) goto L
#define OP_if_icmpne(L)\
sp -= 2; if(*((jexc_int *)sp) != *((jexc_int *)(sp+1))) goto L
#define OP_if_icmplt(L)	\
sp -= 2; if(*((jexc_int *)sp) < *((jexc_int *)(sp+1))) goto L
#define OP_if_icmple(L)\
sp -= 2; if(*((jexc_int *)sp) <= *((jexc_int *)(sp+1))) goto L
#define OP_if_icmpge(L)\
sp -= 2; if(*((jexc_int *)sp) >= *((jexc_int *)(sp+1))) goto L
#define OP_if_icmpgt(L)\
sp -= 2; if(*((jexc_int *)sp) > *((jexc_int *)(sp+1))) goto L

#define OP_if_acmpeq(L) sp -= 2; if(*sp == *(sp+1)) goto L
#define OP_if_acmpne(L) sp -= 2; if(*sp != *(sp+1)) goto L

#define OP_ifnull(L) 	sp--; if(*sp == 0) goto L
#define OP_ifnonnull(L) 	sp--; if(*sp != 0) goto L

#define OP_fcmpg() sp--; \
*((jexc_int *)(sp-1)) = (*((jexc_float *)(sp-1)) > *((jexc_float *)(sp-1))) ? \
-1 : ((*((jexc_float *)(sp-1)) == *((jexc_float *)(sp-1))) ? 0 : 1)
#define OP_fcmpl() OP_fcmpg()

#define OP_lcmp() POP2_tmp2; POP2_tmp1; \
tmp1.i = (tmp1.l < tmp2.l) ? -1 : ((tmp1.l == tmp2.l) ? 0 : 1); \
*((jexc_int *)sp++) = tmp1.i

#define OP_dcmpg() POP2_tmp2; POP2_tmp1; \
tmp1.i = (tmp1.d < tmp2.d) ? -1 : ((tmp1.d == tmp2.d) ? 0 : 1); \
*((jexc_int *)sp++) = tmp1.i
#define OP_dcmpl() dcmpg()

#define OP_SWITCH_BEGIN(def_label) \
switch(*((jexc_int *)(--sp))){  default: goto def_label
#define CASE_GOTO(i,label) case i: goto label
#define OP_SWITCH_END }

#define OP_i2b()   *((jexc_int *)(sp-1)) &= 0xFF
#define OP_i2c()   *((jexc_int *)(sp-1)) &= 0xFFFF
#define OP_i2s()   *((jexc_int *)(sp-1)) &= 0xFFFF

#define OP_i2f()   *((jexc_float *)(sp-1)) = *((jexc_int *)(sp-1))
#define OP_i2l()   tmp1.l = *((jexc_int *)(--sp)); PUSH2_tmp1
#define OP_i2d()   tmp1.d = *((jexc_int *)(--sp)); PUSH2_tmp1

#define OP_l2i()   POP2_tmp1; tmp1.i = tmp1.l; *((jexc_int *)(sp++)) = tmp1.i
#define OP_l2f()   POP2_tmp1; tmp1.f = tmp1.l; *((jexc_float *)(sp++)) = tmp1.f
#define OP_l2d()   POP2_tmp1; tmp1.d = tmp1.l; PUSH2_tmp1

#define OP_f2i()   *((jexc_int *)(sp-1)) = *((jexc_float *)(sp-1))
#define OP_f2l()   tmp1.l = *((jexc_float *)(--sp)); PUSH2_tmp1
#define OP_f2d()   tmp1.d = *((jexc_float *)(--sp)); PUSH2_tmp1

#define OP_d2i()   POP2_tmp1; tmp1.i = tmp1.d; *((jexc_int *)(sp++)) = tmp1.i
#define OP_d2l()   POP2_tmp1; tmp1.l = tmp1.d; PUSH2_tmp1
#define OP_d2f()   POP2_tmp1; tmp1.f = tmp1.d; *((jexc_float *)(sp++)) = tmp1.f

#define OP_iadd()   sp--; *((jexc_int *)(sp-1)) += *((jexc_int *)(sp))
#define OP_isub()   sp--; *((jexc_int *)(sp-1)) -= *((jexc_int *)(sp))
#define OP_imul()   sp--; *((jexc_int *)(sp-1)) *= *((jexc_int *)(sp))
#define OP_idiv()   sp--; *((jexc_int *)(sp-1)) /= *((jexc_int *)(sp))
#define OP_irem()   sp--; *((jexc_int *)(sp-1)) %= *((jexc_int *)(sp))
#define OP_ineg()   *((jexc_int *)(sp-1)) = -*((jexc_int *)(sp-1))

#define OP_fadd()   sp--; *((jexc_float *)(sp-1)) += *((jexc_float *)(sp))
#define OP_fsub()   sp--; *((jexc_float *)(sp-1)) -= *((jexc_float *)(sp))
#define OP_fmul()   sp--; *((jexc_float *)(sp-1)) *= *((jexc_float *)(sp))
#define OP_fdiv()   sp--; *((jexc_float *)(sp-1)) /= *((jexc_float *)(sp))
/* #define OP_frem()  */
#define OP_fneg()   *((jexc_float *)(sp-1)) = -*((jexc_float *)(sp-1))

#define OP_ladd()   POP2_tmp2; POP2_tmp1; tmp1.l += tmp2.l; PUSH2_tmp1
#define OP_lsub()   POP2_tmp2; POP2_tmp1; tmp1.l -= tmp2.l; PUSH2_tmp1
#define OP_lmul()   POP2_tmp2; POP2_tmp1; tmp1.l *= tmp2.l; PUSH2_tmp1
#define OP_ldiv()   POP2_tmp2; POP2_tmp1; tmp1.l /= tmp2.l; PUSH2_tmp1
#define OP_lrem()   POP2_tmp2; POP2_tmp1; tmp1.l %= tmp2.l; PUSH2_tmp1
#define OP_lneg()   POP2_tmp1; tmp1.l = -tmp1.l; PUSH2_tmp1

#define OP_dadd()   POP2_tmp2; POP2_tmp1; tmp1.d += tmp2.d; PUSH2_tmp1
#define OP_dsub()   POP2_tmp2; POP2_tmp1; tmp1.d -= tmp2.d; PUSH2_tmp1
#define OP_dmul()   POP2_tmp2; POP2_tmp1; tmp1.d *= tmp2.d; PUSH2_tmp1
#define OP_ddiv()   POP2_tmp2; POP2_tmp1; tmp1.d /= tmp2.d; PUSH2_tmp1
/* #define OP_drem()    */
#define OP_dneg()   POP2_tmp1; tmp1.d = -tmp1.d; PUSH2_tmp1

#define OP_ior()    sp--; *((jexc_int *)(sp-1)) |= *((jexc_int *)(sp))
#define OP_iand()   sp--; *((jexc_int *)(sp-1)) &= *((jexc_int *)(sp))
#define OP_ixor()   sp--; *((jexc_int *)(sp-1)) ^= *((jexc_int *)(sp))
#define OP_ishl()   sp--; *((jexc_int *)(sp-1)) <<= *((jexc_int *)(sp))
#define OP_ishr()   sp--; *((jexc_int *)(sp-1)) >>= *((jexc_int *)(sp))
#define OP_iushr()  sp--; *((jexc_uint *)(sp-1)) >>= *((jexc_int *)(sp))

#define OP_lor()    POP2_tmp2; POP2_tmp1; tmp1.l |= tmp2.l; PUSH2_tmp1
#define OP_land()   POP2_tmp2; POP2_tmp1; tmp1.l &= tmp2.l; PUSH2_tmp1
#define OP_lxor()   POP2_tmp2; POP2_tmp1; tmp1.l ^= tmp2.l; PUSH2_tmp1
#define OP_lshl()   \
tmp2.i = *((jexc_int *)(--sp)); POP2_tmp1; tmp1.l <<= tmp2.i; PUSH2_tmp1
#define OP_lshr()   \
tmp2.i = *((jexc_int *)(--sp)); POP2_tmp1; tmp1.l >>= tmp2.i; PUSH2_tmp1
#define OP_lushr()  \
tmp2.i = *((jexc_int *)(--sp)); POP2_tmp1; tmp1.ul >>= tmp2.i; PUSH2_tmp1

