/*
 * machine.c
 * Extremely simplified Java virtual machine interpreter.
 *
 *  Many things omitted, including:
 *   - synchronization for threads
 *   - exception handling
 *   - wide arguments
 *   - multiple types of data
 *
 * Derived from kaffe by Tim Wilkinson
 * Copyright (c) 1996 T. J. Wilkinson & Associates, London, UK.
 */

typedef unsigned char bytecode;
#define NOP 0
#define ACONST_NULL 1
...

const uint8 insnLen[256] = {
	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
        ...}


void
virtualMachine(methods* meth, int* args, int* retval)
{
	/* If these can be kept in registers then things will go much
	 * better.
	 */
	register bytecode* code;  /* code array */
	register int* lcl;      /* operand stack */
	register int* sp;       /* operand stack pointer */
	register uintp pc = 0;    /* current code pointer */
	register uintp npc = 0;   /* next code pointer * /

	/* Allocate stack space and locals. */
	lcl = alloca(sizeof(int) * (meth->localsz + meth->stacksz));

	/* Determine number of arguments */
	nargs = meth->...;

	/* Copy in the arguments */
	sp = lcl;
	args = &args[nargs-1];
	for (i = 0; i < nargs; i++) {
		*(sp++) = *(nargs--);
	}

	sp = &lcl[meth->localsz + meth->stacksz];

	code = (bytecode*)meth->c.bcode.code;


	/* Execute the code */
	for (;;) {
		pc = npc;
		npc = pc + insnLen[code[pc]];
		switch(code[pc]) {

		NOP: 
		  break;

		ACONST_NULL:
		  *(--sp) = 0;
		  break;

                ...

		BIPUSH:
		  *(--sp) = (int8)code[pc+1];
		  break;

		...

  	        ILOAD:
		  idx = (uint8)code[pc+1];
		  *(--sp) = *(lcl+idx)
		  break;

		...

	        ISTORE:
		  idx = (uint8)code[pc+1];
		  *(lcl+idx) = *(sp++)
		  break;
		  
	        ...

  	        DUP_X1:
		  sp--;
		  *sp = *(sp+1);
		  *(sp+1) = *(sp+2);
		  *(sp+2) = *sp;
		  break;
		  
		...

	        IADD:
		  *(++sp) = *sp + *(sp+1)
		  break;

		...


      	        IINC:
		  idx = (uint8)code[pc+1];
		  *(lcl+idx) = *(lcl+idx) + (int8)code[pc+2];
		  break;

		...

  	        IFEQ:
		  idx = (int16)((code[pc+1] << 8) | code[pc+2]);
		  if (*sp++ = 0) npc = pc+idx;
		  break;
		 
                ...
		
	        GETFIELD:
		  idx = (uint16)((pc[1] << 8) | pc[2]);
                  offset = get_field_offset(idx);  /* some magic */
		  *sp = *(*sp+offset);
		  break;

		...

	        INVOKESTATIC:
		  idx = (uint16)((pc[1] << 8) | pc[2]);
		  method = get_method_info(idx); /* magic */
		  nargs = method->...;
		  virtualMachine(method, sp, retval);
		  sp += (nargs -1);
		  *sp = *retval;
		  break;
		  
	        IRETURN:
		  *retval = *sp;
		  goto end;

		...
		}
	}
	end:
}
