#define _PROCESS_2
#include "includes.h"
#include "threads.h"		/** See threads.h for trap handler **/
#include "minisl.h"



/*********************** THE STACKS ****************************/

/** (!) Beware: context switching must also save these **/
msl_instr_t *	msl_pc ;	/* program counter */
CELLt *	msl_ld ;	/* dynamic link */
CELLt *	msl_sp ;	/* stack pointer */
CELLt *	msl_rp ;	/* return stack pointer */
CELLt *	msl_spbot ;	/* limits of the stack */
CELLt *	msl_sptop ;
CELLt *	msl_rpbot ;	/* limits of the return stack */
CELLt *	msl_rptop ;

msl_instr_t *	msl_err_pc ;

#define pop()			(*(sp++))
#define push(v)			({ ulong C=(ulong)v ; (--sp)[0]=C ;})
#define rpop()			(*(rp++))
#define rpush(v)		({ ulong C=(ulong)v ; (--rp)[0]=C ;})
#define	get_next_instr()	(*(++pc))
#define	next_instr()		get_next_instr()
#define immediate()		((ulong)get_next_instr())

/*
In case of alignment problem:

#define immediate()		\
	({ \
	  char * p = (char*) pc ; \
	  pc += INSTR_PER_CELL ; \
	  READ_LONG(p) ; \
	})
*/


#define top			(sp[0])
#define next			(sp[1])
#define	pc			msl_pc
#define	sp			msl_sp
#define	rp			msl_rp
#define ld			msl_ld
#define	spbot			msl_spbot
#define	sptop			msl_sptop
#define	rpbot			msl_rpbot
#define	rptop			msl_rptop

#define	pcell(p)		(*(CELLt*)p)
#define	pchar(p)		(*(Char*)p)

#define msl_abort(msg)	({___(0,msg " at line %d\n",__LINE__);\
			  msl_err_pc=pc;pc=NULL;sp=NULL;return;})



#define check_sp_up(n)		((sp+n)<=spbot?0:\
				    msl_abort("stack underflow"))
#define check_sp_down(n)	((sp-n)>=sptop?0:\
				    msl_abort("stack overflow"))
#define check_rp_up(n)		((rp+n)<=spbot?0:\
				    msl_abort("return stack underflow"))
#define check_rp_down(n)	((rp-n)>=sptop?0:\
				    msl_abort("return stack overflow"))
#define check_pc(n)		(n)
#define check_r_Caddr(n)	(n)
#define check_w_Caddr(n)	(n)
#define check_r_caddr(n)	(n)
#define check_w_caddr(n)	(n)


#define INSTR_PER_CELL	1
#define CHAR_PER_CELL	4
#define MSL_TRUE	(-1)
#define MSL_FALSE	0
#define MSL_FLAG(x)	((x)?MSL_TRUE:MSL_FALSE)


/* VERY dangerous ! */
#define TRAP_Handler(trap)	( * ((msl_instr_t)(trap)) )


/******************** Token -> threaded code translation *******************/

msl_instr_tbl_t		msl_instruction_table [NUM_OF_MSL_INSTR] = {
#include "minisl.co1"
};


/**************************** Actual code **********************************/

CELLt minisl (msl_instr_t* _pc,
	     CELLt * _sp,CELLt * _spbot,CELLt * _sptop,
	     CELLt * _rp,CELLt * _rpbot,CELLt * _rptop) {
  ___(450,"MiniSL called !\n") ;
  pc = _pc ;
  sp = _sp ;
  spbot = _spbot ;
  sptop = _sptop ;
  rp = _rp ;
  rpbot = _rpbot ;
  rptop = _rptop ;

  while (pc) {
    ___(400,"MiniSL sp=[%08lX], pc=[%08lX]\n",sp,pc) ;
    ___(400,"Instruction: %08lX\n",*pc) ;
    (*pc)() ;
  }
  if (sp)	return pop () ;
  else		{ pc=msl_err_pc ; return (CELLt)(uInt)0x82FEEB1E ;};
}

void _output_stack (FILE* file) {
  CELLt * lsp=spbot ;
  _t_fprintf(file,"\npc=[%08lX]\tsp=[%08lX]\tspbot=[%08lX]\tsptop=[%08lX]\n",
	     pc,sp,spbot,sptop) ;
  while (--lsp>=sp) _t_fprintf(file,"	[%08lX]	%ld\n",*lsp,*lsp) ;
}

char * get_msl_opcode(msl_instr_t tok) {
  int i ;
  for (i=0;i<NUM_OF_MSL_INSTR;i++) {
    if (tok==msl_instruction_table[i].code)
      return msl_instruction_table[i].C_name ;
  }
  return "" ;
}

#include "minisl.co2"

void __CodeDump__ (FILE* file,msl_instr_t*dpc) {
  
  _t_fprintf(file,"\nDumping code at [%08lX]\n",dpc);
  while (*(dpc)!=msl_End_Of_Dump) {
    _t_fprintf(file,"[%08lX]:\t0x%08lX\t%-10s\n",
	       dpc,*dpc,get_msl_opcode(*dpc)) ;
    dpc++ ;
  }
}

