/*
** Starscream 680x0 emulation library
** Copyright 1997, 1998, 1999 Neill Corlett
**
** Refer to STARDOC.TXT for terms of use, API reference, and directions on
** how to compile.
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <ctype.h>
#include <stdint.h>
#include "starcpu.h"
#include "cpudebug.h"

void (*cpudebug_get)(char*, int);
void (*cpudebug_put)(const char*);

static void cpudebug_gets(char *s, int n) {
	if(cpudebug_get) cpudebug_get(s, n);
	else fgets(s, n, stdin);
}

static void cpudebug_putc(char c) {
	static char buffer[100];
	static unsigned l = 0;
	buffer[l++] = c;
	if((c == '\n') || (l == (sizeof(buffer) - 1))) {
		buffer[l] = 0;
		if(cpudebug_put) cpudebug_put(buffer);
		else fputs(buffer, stdout);
		l = 0;
	}
}

static void cpudebug_printf(const char *fmt, ...) {
	static char buffer[400];
	char *s = buffer;
	va_list ap;
	va_start(ap, fmt);
	vsprintf(s, fmt, ap);
	va_end(ap);
	while(*s) cpudebug_putc(*s++);
}

#define byte uint8_t
#define word uit16_t
#define dword uint32_t

#define int08 int8_t
#define int16 int16_t
#define int32 int32_t

int cpudebug_disabled(void){return 0;}

#define ea eacalc[inst&0x3F]()

/******************************
** SNAGS / EA CONSIDERATIONS **
*******************************

- ADDX is encoded the same way as ADD->ea
- SUBX is encoded the same way as SUB->ea
- ABCD is encoded the same way as AND->ea
- EXG is encoded the same way as AND->ea
- SBCD is encoded the same way as OR->ea
- EOR is encoded the same way as CMPM
- ASR is encoded the same way as LSR
  (so are LSL and ASL, but they do the same thing)
- Bcc does NOT support 32-bit offsets on the 68000.
  (this is a reminder, don't bother implementing 32-bit offsets!)
- Look on p. 3-19 for how to calculate branch conditions (GE, LT, GT, etc.)
- Bit operations are 32-bit for registers, 8-bit for memory locations.
- MOVEM->memory is encoded the same way as EXT
  If the EA is just a register, then it's EXT, otherwise it's MOVEM.
- MOVEP done the same way as the bit operations
- Scc done the same way as DBcc.
  Assume it's Scc, unless the EA is a direct An mode (then it's a DBcc).
- SWAP done the same way as PEA
- TAS done the same way as ILLEGAL

- LINK, NOP, RTR, RTS, TRAP, TRAPV, UNLK are encoded the same way.

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

#define hex08 "%02X"
#define hex16 "%04X"
#define hex32 "%08X"
#define hexlong "%06X"

#define isregister ((inst&0x0030)==0x0000)
#define isaddressr ((inst&0x0038)==0x0008)

static char eabuffer[20],sdebug[80];
static dword debugpc,hexaddr;
static int isize;
static word inst;

static word fetch(void){
	debugpc+=2;
	isize+=2;
	return(s68000fetch(debugpc-2)&0xFFFF);
}

static dword fetchl(void){
	dword t;
	t=(s68000fetch(debugpc)&0xFFFF);
	t<<=16;
	t|=(s68000fetch(debugpc+2)&0xFFFF);
	debugpc+=4;
	isize+=4;
	return t;
}

static int08 opsize[1024]={
1,2,4,0,0,0,0,0,1,2,4,0,0,0,0,0,1,2,4,0,0,0,0,0,1,2,4,0,0,0,0,0,
0,0,0,0,0,0,0,0,1,2,4,0,0,0,0,0,1,2,4,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
1,2,4,2,0,0,2,4,1,2,4,1,0,0,2,4,1,2,4,1,0,0,2,4,1,2,4,2,0,0,2,4,
1,4,2,4,0,0,2,4,1,2,4,1,0,0,2,4,0,0,2,4,0,0,2,4,0,2,0,0,0,0,2,4,
1,2,4,0,1,2,4,0,1,2,4,0,1,2,4,0,1,2,4,0,1,2,4,0,1,2,4,0,1,2,4,0,
1,2,4,0,1,2,4,0,1,2,4,0,1,2,4,0,1,2,4,0,1,2,4,0,1,2,4,0,1,2,4,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
4,4,4,4,0,0,0,0,4,4,4,4,0,0,0,0,4,4,4,4,0,0,0,0,4,4,4,4,0,0,0,0,
4,4,4,4,0,0,0,0,4,4,4,4,0,0,0,0,4,4,4,4,0,0,0,0,4,4,4,4,0,0,0,0,
1,2,4,2,1,2,4,2,1,2,4,2,1,2,4,2,1,2,4,2,1,2,4,2,1,2,4,2,1,2,4,2,
1,2,4,2,1,2,4,2,1,2,4,2,1,2,4,2,1,2,4,2,1,2,4,2,1,2,4,2,1,2,4,2,
1,2,4,2,1,2,4,4,1,2,4,2,1,2,4,4,1,2,4,2,1,2,4,4,1,2,4,2,1,2,4,4,
1,2,4,2,1,2,4,4,1,2,4,2,1,2,4,4,1,2,4,2,1,2,4,4,1,2,4,2,1,2,4,4,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,2,4,2,1,2,4,4,1,2,4,2,1,2,4,4,1,2,4,2,1,2,4,4,1,2,4,2,1,2,4,4,
1,2,4,2,1,2,4,4,1,2,4,2,1,2,4,4,1,2,4,2,1,2,4,4,1,2,4,2,1,2,4,4,
1,2,4,2,1,2,4,2,1,2,4,2,1,2,4,2,1,2,4,2,1,2,4,2,1,2,4,2,1,2,4,2,
1,2,4,2,1,2,4,2,1,2,4,2,1,2,4,2,1,2,4,2,1,2,4,2,1,2,4,2,1,2,4,2,
1,2,4,2,1,2,4,4,1,2,4,2,1,2,4,4,1,2,4,2,1,2,4,4,1,2,4,2,1,2,4,4,
1,2,4,2,1,2,4,4,1,2,4,2,1,2,4,4,1,2,4,2,1,2,4,4,1,2,4,2,1,2,4,4,
1,2,4,2,1,2,4,2,1,2,4,2,1,2,4,2,1,2,4,2,1,2,4,2,1,2,4,2,1,2,4,2,
1,2,4,0,1,2,4,0,1,2,4,0,1,2,4,0,1,2,4,0,1,2,4,0,1,2,4,0,1,2,4,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

/******************** EA GENERATION ********************/

/* These are the functions to generate effective addresses.
   Here is the syntax:

   eacalc[mode]();

   mode   is the EA mode << 3 + register number

   The function sets addr so you can use m68read and m68write.

   These routines screw around with the PC, and might call fetch() a couple
   times to get extension words.  Place the eacalc() calls strategically to
   get the extension words in the right order.
*/

/* These are the jump tables for EA calculation.
   drd     = data reg direct                         Dn
   ard     = address reg direct                      An
   ari     = address reg indirect                   (An)
   ari_inc = address reg indirect, postincrement    (An)+
   ari_dec = address reg indirect, predecrement    -(An)
   ari_dis = address reg indirect, displacement     (d16,An)
   ari_ind = address reg indirect, index            (d8,An,Xn)
   pci_dis = prog. counter indirect, displacement   (d16,PC)
   pci_ind = prog. counter indirect, index          (d8,PC,Xn)
*/

#define eacalc_drd(n,r) static void n(void){sprintf(eabuffer,"d%d",r);}
#define eacalc_ard(n,r) static void n(void){sprintf(eabuffer,"a%d",r);}
#define eacalc_ari(n,r) static void n(void){sprintf(eabuffer,"(a%d)",r);}
#define eacalc_ari_inc(n,r) static void n(void){sprintf(eabuffer,"(a%d)+",r);}
#define eacalc_ari_dec(n,r) static void n(void){sprintf(eabuffer,"-(a%d)",r);}
#define eacalc_ari_dis(n,r) static void n(void){\
	int16 briefext=fetch();\
	sprintf(eabuffer,"%c$" hex16 "(a%d)",(briefext<0)?'-':'+',(briefext<0)?-briefext:briefext,r);\
}
#define eacalc_ari_ind(n,r) static void n(void){\
	int16 briefext=fetch();\
	if(briefext<0)sprintf(eabuffer,"-$" hex08 "(a%d,%c%d.%c)",\
		(int08)-briefext,r,\
		briefext&0x8000?'a':'d',(briefext>>12)&7,\
		briefext&0x800?'l':'w');\
	else sprintf(eabuffer,"+$" hex08 "(a%d,%c%d.%c)",\
		(int08)briefext,r,\
		briefext&0x8000?'a':'d',(briefext>>12)&7,\
		briefext&0x800?'l':'w');\
}
eacalc_drd(ea_0_0,0)
eacalc_drd(ea_0_1,1)
eacalc_drd(ea_0_2,2)
eacalc_drd(ea_0_3,3)
eacalc_drd(ea_0_4,4)
eacalc_drd(ea_0_5,5)
eacalc_drd(ea_0_6,6)
eacalc_drd(ea_0_7,7)
eacalc_ard(ea_1_0,0)
eacalc_ard(ea_1_1,1)
eacalc_ard(ea_1_2,2)
eacalc_ard(ea_1_3,3)
eacalc_ard(ea_1_4,4)
eacalc_ard(ea_1_5,5)
eacalc_ard(ea_1_6,6)
eacalc_ard(ea_1_7,7)
eacalc_ari(ea_2_0,0)
eacalc_ari(ea_2_1,1)
eacalc_ari(ea_2_2,2)
eacalc_ari(ea_2_3,3)
eacalc_ari(ea_2_4,4)
eacalc_ari(ea_2_5,5)
eacalc_ari(ea_2_6,6)
eacalc_ari(ea_2_7,7)
eacalc_ari_inc(ea_3_0,0)
eacalc_ari_inc(ea_3_1,1)
eacalc_ari_inc(ea_3_2,2)
eacalc_ari_inc(ea_3_3,3)
eacalc_ari_inc(ea_3_4,4)
eacalc_ari_inc(ea_3_5,5)
eacalc_ari_inc(ea_3_6,6)
eacalc_ari_inc(ea_3_7,7)
eacalc_ari_dec(ea_4_0,0)
eacalc_ari_dec(ea_4_1,1)
eacalc_ari_dec(ea_4_2,2)
eacalc_ari_dec(ea_4_3,3)
eacalc_ari_dec(ea_4_4,4)
eacalc_ari_dec(ea_4_5,5)
eacalc_ari_dec(ea_4_6,6)
eacalc_ari_dec(ea_4_7,7)
eacalc_ari_dis(ea_5_0,0)
eacalc_ari_dis(ea_5_1,1)
eacalc_ari_dis(ea_5_2,2)
eacalc_ari_dis(ea_5_3,3)
eacalc_ari_dis(ea_5_4,4)
eacalc_ari_dis(ea_5_5,5)
eacalc_ari_dis(ea_5_6,6)
eacalc_ari_dis(ea_5_7,7)
eacalc_ari_ind(ea_6_0,0)
eacalc_ari_ind(ea_6_1,1)
eacalc_ari_ind(ea_6_2,2)
eacalc_ari_ind(ea_6_3,3)
eacalc_ari_ind(ea_6_4,4)
eacalc_ari_ind(ea_6_5,5)
eacalc_ari_ind(ea_6_6,6)
eacalc_ari_ind(ea_6_7,7)

/* These are the "special" addressing modes:
   abshort    absolute short address
   abslong    absolute long address
   immdata    immediate data
*/

static void eacalcspecial_abshort(void){
	word briefext;
	briefext=fetch();
	sprintf(eabuffer,"($" hex16 ")",briefext);
}

static void eacalcspecial_abslong(void){
	dword briefext;
	briefext=fetch();
	briefext<<=16;
	briefext|=fetch();
	sprintf(eabuffer,"($"hexlong")",briefext);
}

static void eacalcspecial_immdata(void){
	dword briefext;
	switch(opsize[inst>>6]){
		case 1:
			briefext=fetch()&0xFF;
			sprintf(eabuffer,"#$" hex08,briefext);
			break;
		case 2:
			briefext=fetch();
			sprintf(eabuffer,"#$" hex16,briefext);
			break;
		default:
			briefext=fetch();
			briefext<<=16;
			briefext|=fetch();
			sprintf(eabuffer,"#$" hex32,briefext);
			break;
	}
}

static void eacalcspecial_pci_dis(void){
	dword dpc = debugpc;
	word briefext = fetch();
	sprintf(eabuffer,"$" hexlong "(pc)",((int16)(briefext))+dpc);
}

static void eacalcspecial_pci_ind(void){
	dword dpc = debugpc;
	word briefext = fetch();
	sprintf(eabuffer,"$" hexlong "(pc,%c%d)",
		((int08)(briefext))+dpc,
		briefext&0x8000?'a':'d',(briefext>>12)&7);
}

static void eacalcspecial_unknown(void){
	sprintf(eabuffer,"*** UNKNOWN EA MODE ***");
}

static void (*(eacalc[64]))(void)={
ea_0_0,ea_0_1,ea_0_2,ea_0_3,ea_0_4,ea_0_5,ea_0_6,ea_0_7,
ea_1_0,ea_1_1,ea_1_2,ea_1_3,ea_1_4,ea_1_5,ea_1_6,ea_1_7,
ea_2_0,ea_2_1,ea_2_2,ea_2_3,ea_2_4,ea_2_5,ea_2_6,ea_2_7,
ea_3_0,ea_3_1,ea_3_2,ea_3_3,ea_3_4,ea_3_5,ea_3_6,ea_3_7,
ea_4_0,ea_4_1,ea_4_2,ea_4_3,ea_4_4,ea_4_5,ea_4_6,ea_4_7,
ea_5_0,ea_5_1,ea_5_2,ea_5_3,ea_5_4,ea_5_5,ea_5_6,ea_5_7,
ea_6_0,ea_6_1,ea_6_2,ea_6_3,ea_6_4,ea_6_5,ea_6_6,ea_6_7,
eacalcspecial_abshort,eacalcspecial_abslong,eacalcspecial_pci_dis,eacalcspecial_pci_ind,
eacalcspecial_immdata,eacalcspecial_unknown,eacalcspecial_unknown,eacalcspecial_unknown};

static void m68unsupported(void){
	sprintf(sdebug,"*** NOT RECOGNIZED ***");
}

static void m68_unrecog_x(void){
	sprintf(sdebug,"unrecognized");
}

/******************** BIT TEST-AND-____ ********************/

static void m68_bitopdn_x(void){
	int16 d16;
	if((inst&0x38)==0x08){
		d16=fetch();
		sprintf(eabuffer,"%c$" hex16 "(a%d)",(d16<0)?'-':'+',(d16<0)?-d16:d16,inst&7);
		if(!(inst&0x80)){
			sprintf(sdebug,"movep%s %s,d%d",
				((inst&0x40)==0x40)?".l":"  ",
				eabuffer,inst>>9
			);
		}else{
			sprintf(sdebug,"movep%s d%d,%s",
				((inst&0x40)==0x40)?".l":"  ",
				inst>>9,eabuffer
			);
		}
	}else{
		ea;
		switch((inst>>6)&3){
		case 0:sprintf(sdebug,"btst    d%d,%s",inst>>9,eabuffer);break;
		case 1:sprintf(sdebug,"bchg    d%d,%s",inst>>9,eabuffer);break;
		case 2:sprintf(sdebug,"bclr    d%d,%s",inst>>9,eabuffer);break;
		case 3:sprintf(sdebug,"bset    d%d,%s",inst>>9,eabuffer);break;
		default:break;
		}
	}
}

#define bittest_st(name,dump) static void name(void){\
	byte shiftby=(fetch()&0xFF);\
	ea;sprintf(sdebug,"%s    #$"hex08",%s",dump,shiftby,eabuffer);\
}

bittest_st(m68_btst_st_x,"btst")
bittest_st(m68_bclr_st_x,"bclr")
bittest_st(m68_bset_st_x,"bset")
bittest_st(m68_bchg_st_x,"bchg")

/******************** Bcc ********************/

#define conditional_branch(name,dump) static void name(void){\
	int16 disp;\
	int32 currentpc=debugpc;\
	disp=(int08)(inst&0xFF);\
	if(!disp)disp=fetch();\
	sprintf(sdebug,"%s     ($"hexlong")",dump,currentpc+disp);\
}

conditional_branch(m68_bra_____x,"bra")
conditional_branch(m68_bhi_____x,"bhi")
conditional_branch(m68_bls_____x,"bls")
conditional_branch(m68_bcc_____x,"bcc")
conditional_branch(m68_bcs_____x,"bcs")
conditional_branch(m68_bne_____x,"bne")
conditional_branch(m68_beq_____x,"beq")
conditional_branch(m68_bvc_____x,"bvc")
conditional_branch(m68_bvs_____x,"bvs")
conditional_branch(m68_bpl_____x,"bpl")
conditional_branch(m68_bmi_____x,"bmi")
conditional_branch(m68_bge_____x,"bge")
conditional_branch(m68_blt_____x,"blt")
conditional_branch(m68_bgt_____x,"bgt")
conditional_branch(m68_ble_____x,"ble")

/******************** Scc, DBcc ********************/

#define scc_dbcc(name,dump1,dump2)\
static void name(void){\
	ea;if(isaddressr){\
		int16 disp;\
		disp=fetch();\
		sprintf(sdebug,"%s    d%d,($"hexlong")",dump2,inst&7,debugpc+disp-2);\
	}else sprintf(sdebug,"%s     %s",dump1,eabuffer);\
}

scc_dbcc(m68_st______x,"st ","dbt ")
scc_dbcc(m68_sf______x,"sf ","dbra")
scc_dbcc(m68_shi_____x,"shi","dbhi")
scc_dbcc(m68_sls_____x,"sls","dbls")
scc_dbcc(m68_scc_____x,"scc","dbcc")
scc_dbcc(m68_scs_____x,"scs","dbcs")
scc_dbcc(m68_sne_____x,"sne","dbne")
scc_dbcc(m68_seq_____x,"seq","dbeq")
scc_dbcc(m68_svc_____x,"svc","dbvc")
scc_dbcc(m68_svs_____x,"svs","dbvs")
scc_dbcc(m68_spl_____x,"spl","dbpl")
scc_dbcc(m68_smi_____x,"smi","dbmi")
scc_dbcc(m68_sge_____x,"sge","dbge")
scc_dbcc(m68_slt_____x,"slt","dblt")
scc_dbcc(m68_sgt_____x,"sgt","dbgt")
scc_dbcc(m68_sle_____x,"sle","dble")

/******************** JMP ********************/

static void m68_jmp_____x(void){ea;sprintf(sdebug,"jmp     %s",eabuffer);}

/******************** JSR/BSR ********************/

static void m68_jsr_____x(void){ea;sprintf(sdebug,"jsr     %s",eabuffer);}

static void m68_bsr_____x(void){
	int16 disp;
	int32 currentpc=debugpc;
	disp=(int08)(inst&0xFF);
	if(!disp)disp=fetch();
	sprintf(sdebug,"%s     ($"hexlong")","bsr",disp+currentpc);
}

/******************** TAS ********************/

/* Test-and-set / illegal */
static void m68_tas_____b(void){
	if(inst==0x4AFC){
		sprintf(sdebug,"illegal");
	}else{
		ea;
		sprintf(sdebug,"tas     %s",eabuffer);
	}
}

/******************** LEA ********************/

static void m68_lea___n_l(void){
	ea;sprintf(sdebug,"lea     %s,a%d",eabuffer,(inst>>9)&7);
}

/******************** PEA ********************/

static void m68_pea_____l(void){
	ea;if(isregister){/* SWAP Dn */
		sprintf(sdebug,"swap    d%d",inst&7);
	}else{
		sprintf(sdebug,"pea     %s",eabuffer);
	}
}

/******************** CLR, NEG, NEGX, NOT, TST ********************/

#define negate_ea(name,dump) static void name(void){\
	ea;sprintf(sdebug,"%s  %s",dump,eabuffer);\
}

negate_ea(m68_neg_____b,"neg.b ")
negate_ea(m68_neg_____w,"neg   ")
negate_ea(m68_neg_____l,"neg.l ")
negate_ea(m68_negx____b,"negx.b")
negate_ea(m68_negx____w,"negx  ")
negate_ea(m68_negx____l,"negx.l")
negate_ea(m68_not_____b,"not.b ")
negate_ea(m68_not_____w,"not   ")
negate_ea(m68_not_____l,"not.l ")
negate_ea(m68_clr_____b,"clr.b ")
negate_ea(m68_clr_____w,"clr   ")
negate_ea(m68_clr_____l,"clr.l ")
negate_ea(m68_tst_____b,"tst.b ")
negate_ea(m68_tst_____w,"tst   ")
negate_ea(m68_tst_____l,"tst.l ")

/********************      SOURCE: IMMEDIATE DATA
********************* DESTINATION: EFFECTIVE ADDRESS
********************/

#define im_to_ea(name,type,hextype,fetchtype,dump,r) static void name(void){\
	type src=(type)fetchtype();\
	if((inst&0x3F)==0x3C){\
	sprintf(sdebug,"%s   #$"hextype",%s",dump,src,r);\
	}else{\
	ea;sprintf(sdebug,"%s   #$"hextype",%s",dump,src,eabuffer);\
	}\
}

im_to_ea(m68_ori_____b,byte ,hex08,fetch ,"or.b ","ccr")
im_to_ea(m68_ori_____w,word ,hex16,fetch ,"or   ","sr" )
im_to_ea(m68_ori_____l,dword,hex32,fetchl,"or.l ",""   )
im_to_ea(m68_andi____b,byte ,hex08,fetch ,"and.b","ccr")
im_to_ea(m68_andi____w,word ,hex16,fetch ,"and  ","sr" )
im_to_ea(m68_andi____l,dword,hex32,fetchl,"and.l",""   )
im_to_ea(m68_eori____b,byte ,hex08,fetch ,"eor.b","ccr")
im_to_ea(m68_eori____w,word ,hex16,fetch ,"eor  ","sr" )
im_to_ea(m68_eori____l,dword,hex32,fetchl,"eor.l",""   )
im_to_ea(m68_addi____b,byte ,hex08,fetch ,"add.b",""   )
im_to_ea(m68_addi____w,word ,hex16,fetch ,"add  ",""   )
im_to_ea(m68_addi____l,dword,hex32,fetchl,"add.l",""   )
im_to_ea(m68_subi____b,byte ,hex08,fetch ,"sub.b",""   )
im_to_ea(m68_subi____w,word ,hex16,fetch ,"sub  ",""   )
im_to_ea(m68_subi____l,dword,hex32,fetchl,"sub.l",""   )
im_to_ea(m68_cmpi____b,byte ,hex08,fetch ,"cmp.b",""   )
im_to_ea(m68_cmpi____w,word ,hex16,fetch ,"cmp  ",""   )
im_to_ea(m68_cmpi____l,dword,hex32,fetchl,"cmp.l",""   )

/********************      SOURCE: EFFECTIVE ADDRESS
********************* DESTINATION: DATA REGISTER
********************/

#define ea_to_dn(name,dump) static void name(void){\
	ea;sprintf(sdebug,"%s   %s,d%d",dump,eabuffer,(inst>>9)&7);\
}

ea_to_dn(m68_or__d_n_b,"or.b ")
ea_to_dn(m68_or__d_n_w,"or   ")
ea_to_dn(m68_or__d_n_l,"or.l ")
ea_to_dn(m68_and_d_n_b,"and.b")
ea_to_dn(m68_and_d_n_w,"and  ")
ea_to_dn(m68_and_d_n_l,"and.l")
ea_to_dn(m68_add_d_n_b,"add.b")
ea_to_dn(m68_add_d_n_w,"add  ")
ea_to_dn(m68_add_d_n_l,"add.l")
ea_to_dn(m68_sub_d_n_b,"sub.b")
ea_to_dn(m68_sub_d_n_w,"sub  ")
ea_to_dn(m68_sub_d_n_l,"sub.l")
ea_to_dn(m68_cmp_d_n_b,"cmp.b")
ea_to_dn(m68_cmp_d_n_w,"cmp  ")
ea_to_dn(m68_cmp_d_n_l,"cmp.l")

/********************      SOURCE: EFFECTIVE ADDRESS
********************* DESTINATION: ADDRESS REGISTER
********************/

#define ea_to_an(name,dump) static void name(void){\
	ea;sprintf(sdebug,"%s   %s,a%d",dump,eabuffer,((inst>>9)&7));\
}

ea_to_an(m68_adda__n_w,"add  ")
ea_to_an(m68_adda__n_l,"add.l")
ea_to_an(m68_suba__n_w,"sub  ")
ea_to_an(m68_suba__n_l,"sub.l")
ea_to_an(m68_cmpa__n_w,"cmp  ")
ea_to_an(m68_cmpa__n_l,"cmp.l")

/******************** SUPPORT ROUTINE:  ADDX AND SUBX
********************/

#define support_addsubx(name,dump)\
static void name(void){\
	word nregx=(inst>>9)&7,nregy=inst&7;\
	if(inst&0x0008)sprintf(sdebug,"%s  -(a%d),-(a%d)",dump,nregy,nregx);\
	else sprintf(sdebug,"%s  d%d,d%d",dump,nregy,nregx);\
}

support_addsubx(m68support_addx_b,"addx.b")
support_addsubx(m68support_addx_w,"addx  ")
support_addsubx(m68support_addx_l,"addx.l")
support_addsubx(m68support_subx_b,"subx.b")
support_addsubx(m68support_subx_w,"subx  ")
support_addsubx(m68support_subx_l,"subx.l")

#define support_bcd(name,dump)\
static void name(void){\
	word nregx=(inst>>9)&7,nregy=inst&7;\
	if(inst&0x0008)sprintf(sdebug,"%s    -(a%d),-(a%d)",dump,nregy,nregx);\
	else sprintf(sdebug,"%s  d%d,d%d",dump,nregy,nregx);\
}

support_bcd(m68support_abcd,"abcd")
support_bcd(m68support_sbcd,"sbcd")

/******************** SUPPORT ROUTINE:  CMPM
********************/

#define support_cmpm(name,dump) static void name(void){\
	sprintf(sdebug,"%s   (a%d)+,(a%d)+",dump,inst&7,(inst>>9)&7);\
}

support_cmpm(m68support_cmpm_b,"cmp.b")
support_cmpm(m68support_cmpm_w,"cmp  ")
support_cmpm(m68support_cmpm_l,"cmp.l")

/******************** SUPPORT ROUTINE:  EXG
********************/

static void m68support_exg_same(void){
	dword rx;
	rx=(inst&8)|((inst>>9)&7);
	sprintf(sdebug,"exg     %c%d,%c%d",
		rx&8?'a':'d',rx&7,inst&8?'a':'d',inst&7);
}

static void m68support_exg_diff(void){
	sprintf(sdebug,"exg     d%d,a%d",(inst>>9)&7,inst&7);
}

/********************      SOURCE: DATA REGISTER
********************* DESTINATION: EFFECTIVE ADDRESS
*********************
********************* calls a support routine if EA is a register
********************/

#define dn_to_ea(name,dump,s_cond,s_routine)\
static void name(void){\
	ea;if(s_cond)s_routine();\
	else sprintf(sdebug,"%s   d%d,%s",dump,(inst>>9)&7,eabuffer);\
}

dn_to_ea(m68_add_e_n_b,"add.b",isregister,m68support_addx_b)
dn_to_ea(m68_add_e_n_w,"add  ",isregister,m68support_addx_w)
dn_to_ea(m68_add_e_n_l,"add.l",isregister,m68support_addx_l)
dn_to_ea(m68_sub_e_n_b,"sub.b",isregister,m68support_subx_b)
dn_to_ea(m68_sub_e_n_w,"sub  ",isregister,m68support_subx_w)
dn_to_ea(m68_sub_e_n_l,"sub.l",isregister,m68support_subx_l)
dn_to_ea(m68_eor_e_n_b,"eor.b",isaddressr,m68support_cmpm_b)
dn_to_ea(m68_eor_e_n_w,"eor  ",isaddressr,m68support_cmpm_w)
dn_to_ea(m68_eor_e_n_l,"eor.l",isaddressr,m68support_cmpm_l)
dn_to_ea(m68_or__e_n_b,"or.b ",isregister,m68support_sbcd)
dn_to_ea(m68_or__e_n_w,"or   ",isregister,m68unsupported)
dn_to_ea(m68_or__e_n_l,"or.l ",isregister,m68unsupported)
dn_to_ea(m68_and_e_n_b,"and.b",isregister,m68support_abcd)
dn_to_ea(m68_and_e_n_w,"and  ",isregister,m68support_exg_same)
dn_to_ea(m68_and_e_n_l,"and.l",isaddressr,m68support_exg_diff)

/********************      SOURCE: QUICK DATA
********************* DESTINATION: EFFECTIVE ADDRESS
********************/

#define qn_to_ea(name,dump1) static void name(void){\
	ea;sprintf(sdebug,"%s   #%d,%s",dump1,(((inst>>9)&7)==0)?8:(inst>>9)&7,eabuffer);\
}

qn_to_ea(m68_addq__n_b,"add.b")
qn_to_ea(m68_addq__n_w,"add  ")
qn_to_ea(m68_addq__n_l,"add.l")
qn_to_ea(m68_subq__n_b,"sub.b")
qn_to_ea(m68_subq__n_w,"sub  ")
qn_to_ea(m68_subq__n_l,"sub.l")

/********************      SOURCE: QUICK DATA
********************* DESTINATION: DATA REGISTER
********************/
/* MOVEQ is the only instruction that uses this form */

static void m68_moveq_n_l(void){
	sprintf(sdebug,"moveq   #$"hex08",d%d",inst&0xFF,(inst>>9)&7);
}

/********************      SOURCE: EFFECTIVE ADDRESS
********************* DESTINATION: EFFECTIVE ADDRESS
********************/
/* MOVE is the only instruction that uses this form */

#define ea_to_ea(name,dump) static void name(void){\
	char tmpbuf[40];\
	ea;strcpy(tmpbuf,eabuffer);\
	eacalc[((((inst>>3)&(7<<3)))|((inst>>9)&7))]();\
	sprintf(sdebug,"%s  %s,%s",dump,tmpbuf,eabuffer);\
}

ea_to_ea(m68_move____b,"move.b")
ea_to_ea(m68_move____w,"move  ")
ea_to_ea(m68_move____l,"move.l")

/******************** MOVEM, EXT
********************/

static void getreglistf(word mask,char*rl){
	if(mask&0x0001){*(rl++)='d';*(rl++)='0';*(rl++)='/';}
	if(mask&0x0002){*(rl++)='d';*(rl++)='1';*(rl++)='/';}
	if(mask&0x0004){*(rl++)='d';*(rl++)='2';*(rl++)='/';}
	if(mask&0x0008){*(rl++)='d';*(rl++)='3';*(rl++)='/';}
	if(mask&0x0010){*(rl++)='d';*(rl++)='4';*(rl++)='/';}
	if(mask&0x0020){*(rl++)='d';*(rl++)='5';*(rl++)='/';}
	if(mask&0x0040){*(rl++)='d';*(rl++)='6';*(rl++)='/';}
	if(mask&0x0080){*(rl++)='d';*(rl++)='7';*(rl++)='/';}
	if(mask&0x0100){*(rl++)='a';*(rl++)='0';*(rl++)='/';}
	if(mask&0x0200){*(rl++)='a';*(rl++)='1';*(rl++)='/';}
	if(mask&0x0400){*(rl++)='a';*(rl++)='2';*(rl++)='/';}
	if(mask&0x0800){*(rl++)='a';*(rl++)='3';*(rl++)='/';}
	if(mask&0x1000){*(rl++)='a';*(rl++)='4';*(rl++)='/';}
	if(mask&0x2000){*(rl++)='a';*(rl++)='5';*(rl++)='/';}
	if(mask&0x4000){*(rl++)='a';*(rl++)='6';*(rl++)='/';}
	if(mask&0x8000){*(rl++)='a';*(rl++)='7';*(rl++)='/';}
	*(--rl)=0;
}

static void getreglistb(word mask,char*rl){
	if(mask&0x0001){*(rl++)='a';*(rl++)='7';*(rl++)='/';}
	if(mask&0x0002){*(rl++)='a';*(rl++)='6';*(rl++)='/';}
	if(mask&0x0004){*(rl++)='a';*(rl++)='5';*(rl++)='/';}
	if(mask&0x0008){*(rl++)='a';*(rl++)='4';*(rl++)='/';}
	if(mask&0x0010){*(rl++)='a';*(rl++)='3';*(rl++)='/';}
	if(mask&0x0020){*(rl++)='a';*(rl++)='2';*(rl++)='/';}
	if(mask&0x0040){*(rl++)='a';*(rl++)='1';*(rl++)='/';}
	if(mask&0x0080){*(rl++)='a';*(rl++)='0';*(rl++)='/';}
	if(mask&0x0100){*(rl++)='d';*(rl++)='7';*(rl++)='/';}
	if(mask&0x0200){*(rl++)='d';*(rl++)='6';*(rl++)='/';}
	if(mask&0x0400){*(rl++)='d';*(rl++)='5';*(rl++)='/';}
	if(mask&0x0800){*(rl++)='d';*(rl++)='4';*(rl++)='/';}
	if(mask&0x1000){*(rl++)='d';*(rl++)='3';*(rl++)='/';}
	if(mask&0x2000){*(rl++)='d';*(rl++)='2';*(rl++)='/';}
	if(mask&0x4000){*(rl++)='d';*(rl++)='1';*(rl++)='/';}
	if(mask&0x8000){*(rl++)='d';*(rl++)='0';*(rl++)='/';}
	*(--rl)=0;
}

#define movem_mem(name,dumpm,dumpx)\
static void name(void){\
	word regmask;\
	char reglist[50];\
	if((inst&0x38)==0x0000){ /* ext */\
		sprintf(sdebug,dumpx"d%d",inst&7);\
	}else if((inst&0x38)==0x0020){ /* predecrement addressing mode */\
		regmask=fetch();\
		getreglistb(regmask,reglist);\
		sprintf(sdebug,dumpm"%s,-(a%d)",reglist,inst&7);\
	}else{\
		regmask=fetch();\
		ea;getreglistf(regmask,reglist);\
		sprintf(sdebug,dumpm "%s,%s",reglist,eabuffer);\
	}\
}

movem_mem(m68_movem___w,"movem   ","ext     ")
movem_mem(m68_movem___l,"movem.l ","ext.l   ")

#define movem_reg(name,dump) static void name(void){\
	word regmask;\
	char reglist[50];\
	regmask=fetch();\
	ea;getreglistf(regmask,reglist);\
	sprintf(sdebug,dump "%s,%s",eabuffer,reglist);\
}

movem_reg(m68_movem_r_w,"movem   ")
movem_reg(m68_movem_r_l,"movem.l ")

/******************** INSTRUCTIONS THAT INVOLVE SR/CCR ********************/

static void m68_move2sr_w(void){ea;sprintf(sdebug,"move    %s,sr",eabuffer);}
static void m68_movefsr_w(void){ea;sprintf(sdebug,"move    sr,%s",eabuffer);}
static void m68_move2cc_w(void){ea;sprintf(sdebug,"move.b  %s,ccr",eabuffer);}
static void m68_movefcc_w(void){ea;sprintf(sdebug,"move.b  ccr,%s",eabuffer);}

static void m68_rts_____x(void){sprintf(sdebug,"rts");}

/******************** SHIFTS AND ROTATES ********************/

#define regshift(name,sizedump) \
static void name(void){\
	char tmpbuf[10];\
	if((inst&0x20)==0)sprintf(tmpbuf,"#$"hex08",d%d",(((inst>>9)&7)==0)?8:(inst>>9)&7,inst&7);\
	else sprintf(tmpbuf,"d%d,d%d",(inst>>9)&7,inst&7);\
	switch(inst&0x18){\
		case 0x00:sprintf(sdebug,"as%s   %s",sizedump,tmpbuf);break;\
		case 0x08:sprintf(sdebug,"ls%s   %s",sizedump,tmpbuf);break;\
		case 0x10:sprintf(sdebug,"rox%s  %s",sizedump,tmpbuf);break;\
		case 0x18:sprintf(sdebug,"ro%s   %s",sizedump,tmpbuf);break;\
	}\
}

regshift(m68_shl_r_n_b,"l.b")
regshift(m68_shl_r_n_w,"l  ")
regshift(m68_shl_r_n_l,"l.l")
regshift(m68_shr_r_n_b,"r.b")
regshift(m68_shr_r_n_w,"r  ")
regshift(m68_shr_r_n_l,"r.l")

/******************** NOP ********************/

static void m68_nop_____x(void){sprintf(sdebug,"nop");}

/******************** LINK / UNLINK ********************/

static void m68_link_an_w(void){
	int16 briefext=fetch();
	sprintf(sdebug,"link    a%d,%c#$"hex16,inst&7,briefext<0?'-':'+',
		briefext<0?-briefext:briefext
	);
}

static void m68_unlk_an_x(void){
	sprintf(sdebug,"unlk    a%d",inst&7);
}

static void m68_stop____x(void){sprintf(sdebug,"stop    #$%04X",fetch());}
static void m68_rte_____x(void){sprintf(sdebug,"rte");}
static void m68_rtr_____x(void){sprintf(sdebug,"rtr");}
static void m68_reset___x(void){sprintf(sdebug,"reset");}
static void m68_rtd_____x(void){
	int16 briefext=fetch();
	sprintf(sdebug,"rtd     %c#$"hex16,briefext<0?'-':'+',
		briefext<0?-briefext:briefext);
}
static void m68_divu__n_w(void){ea;sprintf(sdebug,"divu    %s,d%d",eabuffer,(inst>>9)&7);}
static void m68_divs__n_w(void){ea;sprintf(sdebug,"divs    %s,d%d",eabuffer,(inst>>9)&7);}
static void m68_mulu__n_w(void){ea;sprintf(sdebug,"mulu    %s,d%d",eabuffer,(inst>>9)&7);}
static void m68_muls__n_w(void){ea;sprintf(sdebug,"muls    %s,d%d",eabuffer,(inst>>9)&7);}

static void m68_asr_m___w(void){ea;sprintf(sdebug,"asr     %s",eabuffer);}
static void m68_asl_m___w(void){ea;sprintf(sdebug,"asl     %s",eabuffer);}
static void m68_lsr_m___w(void){ea;sprintf(sdebug,"lsr     %s",eabuffer);}
static void m68_lsl_m___w(void){ea;sprintf(sdebug,"lsl     %s",eabuffer);}
static void m68_roxr_m__w(void){ea;sprintf(sdebug,"roxr    %s",eabuffer);}
static void m68_roxl_m__w(void){ea;sprintf(sdebug,"roxl    %s",eabuffer);}
static void m68_ror_m___w(void){ea;sprintf(sdebug,"ror     %s",eabuffer);}
static void m68_rol_m___w(void){ea;sprintf(sdebug,"rol     %s",eabuffer);}

static void m68_nbcd____b(void){ea;sprintf(sdebug,"nbcd.b  %s",eabuffer);}
static void m68_chk___n_w(void){ea;sprintf(sdebug,"chk     %s,d%d",eabuffer,(inst>>9)&7);}

static void m68_trap_nn_x(void){sprintf(sdebug,"trap    #%d",inst&0xF);}
static void m68_move_2u_l(void){sprintf(sdebug,"move.l  a%d,usp",inst&7);}
static void m68_move_fu_l(void){sprintf(sdebug,"move.l  usp,a%d",inst&7);}

static void m68_trapv___x(void){sprintf(sdebug,"trapv");}

static char*specialregister(unsigned short int code){
	switch(code&0xFFF){
	case 0x000:return("sfc");
	case 0x001:return("dfc");
	case 0x800:return("usp");
	case 0x801:return("vbr");
	}
	return("???");
}

static void m68_movec_r_x(void){
	unsigned short int f=fetch();
	sprintf(sdebug,"movec   %s,%c%d",
		specialregister(f),
		(f&0x8000)?'a':'d',(f>>12)&7
	);
}

static void m68_movec_c_x(void){
	unsigned short int f=fetch();
	sprintf(sdebug,"movec   %c%d,%s",
		(f&0x8000)?'a':'d',(f>>12)&7,
		specialregister(f)
	);
}

/******************** SPECIAL INSTRUCTION TABLE ********************/

/* This table is used for 0100111001xxxxxx instructions (4E4x-4E7x) */
static void(*(debugspecialmap[64]))(void)={
/* 0000xx */ m68_trap_nn_x,m68_trap_nn_x,m68_trap_nn_x,m68_trap_nn_x,
/* 0001xx */ m68_trap_nn_x,m68_trap_nn_x,m68_trap_nn_x,m68_trap_nn_x,
/* 0010xx */ m68_trap_nn_x,m68_trap_nn_x,m68_trap_nn_x,m68_trap_nn_x,
/* 0011xx */ m68_trap_nn_x,m68_trap_nn_x,m68_trap_nn_x,m68_trap_nn_x,
/* 0100xx */ m68_link_an_w,m68_link_an_w,m68_link_an_w,m68_link_an_w,
/* 0101xx */ m68_link_an_w,m68_link_an_w,m68_link_an_w,m68_link_an_w,
/* 0110xx */ m68_unlk_an_x,m68_unlk_an_x,m68_unlk_an_x,m68_unlk_an_x,
/* 0111xx */ m68_unlk_an_x,m68_unlk_an_x,m68_unlk_an_x,m68_unlk_an_x,
/* 1000xx */ m68_move_2u_l,m68_move_2u_l,m68_move_2u_l,m68_move_2u_l,
/* 1001xx */ m68_move_2u_l,m68_move_2u_l,m68_move_2u_l,m68_move_2u_l,
/* 1010xx */ m68_move_fu_l,m68_move_fu_l,m68_move_fu_l,m68_move_fu_l,
/* 1011xx */ m68_move_fu_l,m68_move_fu_l,m68_move_fu_l,m68_move_fu_l,
/* 1100xx */ m68_reset___x,m68_nop_____x,m68_stop____x,m68_rte_____x,
/* 1101xx */ m68_rtd_____x,m68_rts_____x,m68_trapv___x,m68_rtr_____x,
/* 1110xx */ m68_unrecog_x,m68_unrecog_x,m68_movec_r_x,m68_movec_c_x,
/* 1111xx */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x};

static void m68_special_x(void){
	debugspecialmap[inst&0x3F]();
}

/******************** INSTRUCTION TABLE ********************/

/* The big 1024-element jump table that handles all possible opcodes
   is in the following header file.
   Use this syntax to execute an instruction:

   cpumap[i>>6]();

   ("i" is the instruction word)
*/

static void(*(debugmap[1024]))(void)={
/* 00000000ss */ m68_ori_____b,m68_ori_____w,m68_ori_____l,m68_unrecog_x,
/* 00000001ss */ m68_bitopdn_x,m68_bitopdn_x,m68_bitopdn_x,m68_bitopdn_x,
/* 00000010ss */ m68_andi____b,m68_andi____w,m68_andi____l,m68_unrecog_x,
/* 00000011ss */ m68_bitopdn_x,m68_bitopdn_x,m68_bitopdn_x,m68_bitopdn_x,
/* 00000100ss */ m68_subi____b,m68_subi____w,m68_subi____l,m68_unrecog_x,
/* 00000101ss */ m68_bitopdn_x,m68_bitopdn_x,m68_bitopdn_x,m68_bitopdn_x,
/* 00000110ss */ m68_addi____b,m68_addi____w,m68_addi____l,m68_unrecog_x,
/* 00000111ss */ m68_bitopdn_x,m68_bitopdn_x,m68_bitopdn_x,m68_bitopdn_x,
/* 00001000ss */ m68_btst_st_x,m68_bchg_st_x,m68_bclr_st_x,m68_bset_st_x,
/* 00001001ss */ m68_bitopdn_x,m68_bitopdn_x,m68_bitopdn_x,m68_bitopdn_x,
/* 00001010ss */ m68_eori____b,m68_eori____w,m68_eori____l,m68_unrecog_x,
/* 00001011ss */ m68_bitopdn_x,m68_bitopdn_x,m68_bitopdn_x,m68_bitopdn_x,
/* 00001100ss */ m68_cmpi____b,m68_cmpi____w,m68_cmpi____l,m68_unrecog_x,
/* 00001101ss */ m68_bitopdn_x,m68_bitopdn_x,m68_bitopdn_x,m68_bitopdn_x,
/* 00001110ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,
/* 00001111ss */ m68_bitopdn_x,m68_bitopdn_x,m68_bitopdn_x,m68_bitopdn_x,
/* 00010000ss */ m68_move____b,m68_move____b,m68_move____b,m68_move____b,
/* 00010001ss */ m68_move____b,m68_move____b,m68_move____b,m68_move____b,
/* 00010010ss */ m68_move____b,m68_move____b,m68_move____b,m68_move____b,
/* 00010011ss */ m68_move____b,m68_move____b,m68_move____b,m68_move____b,
/* 00010100ss */ m68_move____b,m68_move____b,m68_move____b,m68_move____b,
/* 00010101ss */ m68_move____b,m68_move____b,m68_move____b,m68_move____b,
/* 00010110ss */ m68_move____b,m68_move____b,m68_move____b,m68_move____b,
/* 00010111ss */ m68_move____b,m68_move____b,m68_move____b,m68_move____b,
/* 00011000ss */ m68_move____b,m68_move____b,m68_move____b,m68_move____b,
/* 00011001ss */ m68_move____b,m68_move____b,m68_move____b,m68_move____b,
/* 00011010ss */ m68_move____b,m68_move____b,m68_move____b,m68_move____b,
/* 00011011ss */ m68_move____b,m68_move____b,m68_move____b,m68_move____b,
/* 00011100ss */ m68_move____b,m68_move____b,m68_move____b,m68_move____b,
/* 00011101ss */ m68_move____b,m68_move____b,m68_move____b,m68_move____b,
/* 00011110ss */ m68_move____b,m68_move____b,m68_move____b,m68_move____b,
/* 00011111ss */ m68_move____b,m68_move____b,m68_move____b,m68_move____b,
/* 00100000ss */ m68_move____l,m68_move____l,m68_move____l,m68_move____l,
/* 00100001ss */ m68_move____l,m68_move____l,m68_move____l,m68_move____l,
/* 00100010ss */ m68_move____l,m68_move____l,m68_move____l,m68_move____l,
/* 00100011ss */ m68_move____l,m68_move____l,m68_move____l,m68_move____l,
/* 00100100ss */ m68_move____l,m68_move____l,m68_move____l,m68_move____l,
/* 00100101ss */ m68_move____l,m68_move____l,m68_move____l,m68_move____l,
/* 00100110ss */ m68_move____l,m68_move____l,m68_move____l,m68_move____l,
/* 00100111ss */ m68_move____l,m68_move____l,m68_move____l,m68_move____l,
/* 00101000ss */ m68_move____l,m68_move____l,m68_move____l,m68_move____l,
/* 00101001ss */ m68_move____l,m68_move____l,m68_move____l,m68_move____l,
/* 00101010ss */ m68_move____l,m68_move____l,m68_move____l,m68_move____l,
/* 00101011ss */ m68_move____l,m68_move____l,m68_move____l,m68_move____l,
/* 00101100ss */ m68_move____l,m68_move____l,m68_move____l,m68_move____l,
/* 00101101ss */ m68_move____l,m68_move____l,m68_move____l,m68_move____l,
/* 00101110ss */ m68_move____l,m68_move____l,m68_move____l,m68_move____l,
/* 00101111ss */ m68_move____l,m68_move____l,m68_move____l,m68_move____l,
/* 00110000ss */ m68_move____w,m68_move____w,m68_move____w,m68_move____w,
/* 00110001ss */ m68_move____w,m68_move____w,m68_move____w,m68_move____w,
/* 00110010ss */ m68_move____w,m68_move____w,m68_move____w,m68_move____w,
/* 00110011ss */ m68_move____w,m68_move____w,m68_move____w,m68_move____w,
/* 00110100ss */ m68_move____w,m68_move____w,m68_move____w,m68_move____w,
/* 00110101ss */ m68_move____w,m68_move____w,m68_move____w,m68_move____w,
/* 00110110ss */ m68_move____w,m68_move____w,m68_move____w,m68_move____w,
/* 00110111ss */ m68_move____w,m68_move____w,m68_move____w,m68_move____w,
/* 00111000ss */ m68_move____w,m68_move____w,m68_move____w,m68_move____w,
/* 00111001ss */ m68_move____w,m68_move____w,m68_move____w,m68_move____w,
/* 00111010ss */ m68_move____w,m68_move____w,m68_move____w,m68_move____w,
/* 00111011ss */ m68_move____w,m68_move____w,m68_move____w,m68_move____w,
/* 00111100ss */ m68_move____w,m68_move____w,m68_move____w,m68_move____w,
/* 00111101ss */ m68_move____w,m68_move____w,m68_move____w,m68_move____w,
/* 00111110ss */ m68_move____w,m68_move____w,m68_move____w,m68_move____w,
/* 00111111ss */ m68_move____w,m68_move____w,m68_move____w,m68_move____w,
/* 01000000ss */ m68_negx____b,m68_negx____w,m68_negx____l,m68_movefsr_w,
/* 01000001ss */ m68_unrecog_x,m68_unrecog_x,m68_chk___n_w,m68_lea___n_l,
/* 01000010ss */ m68_clr_____b,m68_clr_____w,m68_clr_____l,m68_movefcc_w,
/* 01000011ss */ m68_unrecog_x,m68_unrecog_x,m68_chk___n_w,m68_lea___n_l,
/* 01000100ss */ m68_neg_____b,m68_neg_____w,m68_neg_____l,m68_move2cc_w,
/* 01000101ss */ m68_unrecog_x,m68_unrecog_x,m68_chk___n_w,m68_lea___n_l,
/* 01000110ss */ m68_not_____b,m68_not_____w,m68_not_____l,m68_move2sr_w,
/* 01000111ss */ m68_unrecog_x,m68_unrecog_x,m68_chk___n_w,m68_lea___n_l,
/* 01001000ss */ m68_nbcd____b,m68_pea_____l,m68_movem___w,m68_movem___l,
/* 01001001ss */ m68_unrecog_x,m68_unrecog_x,m68_chk___n_w,m68_lea___n_l,
/* 01001010ss */ m68_tst_____b,m68_tst_____w,m68_tst_____l,m68_tas_____b,
/* 01001011ss */ m68_unrecog_x,m68_unrecog_x,m68_chk___n_w,m68_lea___n_l,
/* 01001100ss */ m68_unrecog_x,m68_unrecog_x,m68_movem_r_w,m68_movem_r_l,
/* 01001101ss */ m68_unrecog_x,m68_unrecog_x,m68_chk___n_w,m68_lea___n_l,
/* 01001110ss */ m68_unrecog_x,m68_special_x,m68_jsr_____x,m68_jmp_____x,
/* 01001111ss */ m68_unrecog_x,m68_unrecog_x,m68_chk___n_w,m68_lea___n_l,
/* 01010000ss */ m68_addq__n_b,m68_addq__n_w,m68_addq__n_l,m68_st______x,
/* 01010001ss */ m68_subq__n_b,m68_subq__n_w,m68_subq__n_l,m68_sf______x,
/* 01010010ss */ m68_addq__n_b,m68_addq__n_w,m68_addq__n_l,m68_shi_____x,
/* 01010011ss */ m68_subq__n_b,m68_subq__n_w,m68_subq__n_l,m68_sls_____x,
/* 01010100ss */ m68_addq__n_b,m68_addq__n_w,m68_addq__n_l,m68_scc_____x,
/* 01010101ss */ m68_subq__n_b,m68_subq__n_w,m68_subq__n_l,m68_scs_____x,
/* 01010110ss */ m68_addq__n_b,m68_addq__n_w,m68_addq__n_l,m68_sne_____x,
/* 01010111ss */ m68_subq__n_b,m68_subq__n_w,m68_subq__n_l,m68_seq_____x,
/* 01011000ss */ m68_addq__n_b,m68_addq__n_w,m68_addq__n_l,m68_svc_____x,
/* 01011001ss */ m68_subq__n_b,m68_subq__n_w,m68_subq__n_l,m68_svs_____x,
/* 01011010ss */ m68_addq__n_b,m68_addq__n_w,m68_addq__n_l,m68_spl_____x,
/* 01011011ss */ m68_subq__n_b,m68_subq__n_w,m68_subq__n_l,m68_smi_____x,
/* 01011100ss */ m68_addq__n_b,m68_addq__n_w,m68_addq__n_l,m68_sge_____x,
/* 01011101ss */ m68_subq__n_b,m68_subq__n_w,m68_subq__n_l,m68_slt_____x,
/* 01011110ss */ m68_addq__n_b,m68_addq__n_w,m68_addq__n_l,m68_sgt_____x,
/* 01011111ss */ m68_subq__n_b,m68_subq__n_w,m68_subq__n_l,m68_sle_____x,
/* 01100000ss */ m68_bra_____x,m68_bra_____x,m68_bra_____x,m68_bra_____x,
/* 01100001ss */ m68_bsr_____x,m68_bsr_____x,m68_bsr_____x,m68_bsr_____x,
/* 01100010ss */ m68_bhi_____x,m68_bhi_____x,m68_bhi_____x,m68_bhi_____x,
/* 01100011ss */ m68_bls_____x,m68_bls_____x,m68_bls_____x,m68_bls_____x,
/* 01100100ss */ m68_bcc_____x,m68_bcc_____x,m68_bcc_____x,m68_bcc_____x,
/* 01100101ss */ m68_bcs_____x,m68_bcs_____x,m68_bcs_____x,m68_bcs_____x,
/* 01100110ss */ m68_bne_____x,m68_bne_____x,m68_bne_____x,m68_bne_____x,
/* 01100111ss */ m68_beq_____x,m68_beq_____x,m68_beq_____x,m68_beq_____x,
/* 01101000ss */ m68_bvc_____x,m68_bvc_____x,m68_bvc_____x,m68_bvc_____x,
/* 01101001ss */ m68_bvs_____x,m68_bvs_____x,m68_bvs_____x,m68_bvs_____x,
/* 01101010ss */ m68_bpl_____x,m68_bpl_____x,m68_bpl_____x,m68_bpl_____x,
/* 01101011ss */ m68_bmi_____x,m68_bmi_____x,m68_bmi_____x,m68_bmi_____x,
/* 01101100ss */ m68_bge_____x,m68_bge_____x,m68_bge_____x,m68_bge_____x,
/* 01101101ss */ m68_blt_____x,m68_blt_____x,m68_blt_____x,m68_blt_____x,
/* 01101110ss */ m68_bgt_____x,m68_bgt_____x,m68_bgt_____x,m68_bgt_____x,
/* 01101111ss */ m68_ble_____x,m68_ble_____x,m68_ble_____x,m68_ble_____x,
/* 01110000ss */ m68_moveq_n_l,m68_moveq_n_l,m68_moveq_n_l,m68_moveq_n_l,
/* 01110001ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,
/* 01110010ss */ m68_moveq_n_l,m68_moveq_n_l,m68_moveq_n_l,m68_moveq_n_l,
/* 01110011ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,
/* 01110100ss */ m68_moveq_n_l,m68_moveq_n_l,m68_moveq_n_l,m68_moveq_n_l,
/* 01110101ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,
/* 01110110ss */ m68_moveq_n_l,m68_moveq_n_l,m68_moveq_n_l,m68_moveq_n_l,
/* 01110111ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,
/* 01111000ss */ m68_moveq_n_l,m68_moveq_n_l,m68_moveq_n_l,m68_moveq_n_l,
/* 01111001ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,
/* 01111010ss */ m68_moveq_n_l,m68_moveq_n_l,m68_moveq_n_l,m68_moveq_n_l,
/* 01111011ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,
/* 01111100ss */ m68_moveq_n_l,m68_moveq_n_l,m68_moveq_n_l,m68_moveq_n_l,
/* 01111101ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,
/* 01111110ss */ m68_moveq_n_l,m68_moveq_n_l,m68_moveq_n_l,m68_moveq_n_l,
/* 01111111ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,
/* 10000000ss */ m68_or__d_n_b,m68_or__d_n_w,m68_or__d_n_l,m68_divu__n_w,
/* 10000001ss */ m68_or__e_n_b,m68_or__e_n_w,m68_or__e_n_l,m68_divs__n_w,
/* 10000010ss */ m68_or__d_n_b,m68_or__d_n_w,m68_or__d_n_l,m68_divu__n_w,
/* 10000011ss */ m68_or__e_n_b,m68_or__e_n_w,m68_or__e_n_l,m68_divs__n_w,
/* 10000100ss */ m68_or__d_n_b,m68_or__d_n_w,m68_or__d_n_l,m68_divu__n_w,
/* 10000101ss */ m68_or__e_n_b,m68_or__e_n_w,m68_or__e_n_l,m68_divs__n_w,
/* 10000110ss */ m68_or__d_n_b,m68_or__d_n_w,m68_or__d_n_l,m68_divu__n_w,
/* 10000111ss */ m68_or__e_n_b,m68_or__e_n_w,m68_or__e_n_l,m68_divs__n_w,
/* 10001000ss */ m68_or__d_n_b,m68_or__d_n_w,m68_or__d_n_l,m68_divu__n_w,
/* 10001001ss */ m68_or__e_n_b,m68_or__e_n_w,m68_or__e_n_l,m68_divs__n_w,
/* 10001010ss */ m68_or__d_n_b,m68_or__d_n_w,m68_or__d_n_l,m68_divu__n_w,
/* 10001011ss */ m68_or__e_n_b,m68_or__e_n_w,m68_or__e_n_l,m68_divs__n_w,
/* 10001100ss */ m68_or__d_n_b,m68_or__d_n_w,m68_or__d_n_l,m68_divu__n_w,
/* 10001101ss */ m68_or__e_n_b,m68_or__e_n_w,m68_or__e_n_l,m68_divs__n_w,
/* 10001110ss */ m68_or__d_n_b,m68_or__d_n_w,m68_or__d_n_l,m68_divu__n_w,
/* 10001111ss */ m68_or__e_n_b,m68_or__e_n_w,m68_or__e_n_l,m68_divs__n_w,
/* 10010000ss */ m68_sub_d_n_b,m68_sub_d_n_w,m68_sub_d_n_l,m68_suba__n_w,
/* 10010001ss */ m68_sub_e_n_b,m68_sub_e_n_w,m68_sub_e_n_l,m68_suba__n_l,
/* 10010010ss */ m68_sub_d_n_b,m68_sub_d_n_w,m68_sub_d_n_l,m68_suba__n_w,
/* 10010011ss */ m68_sub_e_n_b,m68_sub_e_n_w,m68_sub_e_n_l,m68_suba__n_l,
/* 10010100ss */ m68_sub_d_n_b,m68_sub_d_n_w,m68_sub_d_n_l,m68_suba__n_w,
/* 10010101ss */ m68_sub_e_n_b,m68_sub_e_n_w,m68_sub_e_n_l,m68_suba__n_l,
/* 10010110ss */ m68_sub_d_n_b,m68_sub_d_n_w,m68_sub_d_n_l,m68_suba__n_w,
/* 10010111ss */ m68_sub_e_n_b,m68_sub_e_n_w,m68_sub_e_n_l,m68_suba__n_l,
/* 10011000ss */ m68_sub_d_n_b,m68_sub_d_n_w,m68_sub_d_n_l,m68_suba__n_w,
/* 10011001ss */ m68_sub_e_n_b,m68_sub_e_n_w,m68_sub_e_n_l,m68_suba__n_l,
/* 10011010ss */ m68_sub_d_n_b,m68_sub_d_n_w,m68_sub_d_n_l,m68_suba__n_w,
/* 10011011ss */ m68_sub_e_n_b,m68_sub_e_n_w,m68_sub_e_n_l,m68_suba__n_l,
/* 10011100ss */ m68_sub_d_n_b,m68_sub_d_n_w,m68_sub_d_n_l,m68_suba__n_w,
/* 10011101ss */ m68_sub_e_n_b,m68_sub_e_n_w,m68_sub_e_n_l,m68_suba__n_l,
/* 10011110ss */ m68_sub_d_n_b,m68_sub_d_n_w,m68_sub_d_n_l,m68_suba__n_w,
/* 10011111ss */ m68_sub_e_n_b,m68_sub_e_n_w,m68_sub_e_n_l,m68_suba__n_l,
/* 10100000ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,
/* 10100001ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,
/* 10100010ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,
/* 10100011ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,
/* 10100100ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,
/* 10100101ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,
/* 10100110ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,
/* 10100111ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,
/* 10101000ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,
/* 10101001ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,
/* 10101010ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,
/* 10101011ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,
/* 10101100ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,
/* 10101101ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,
/* 10101110ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,
/* 10101111ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,
/* 10110000ss */ m68_cmp_d_n_b,m68_cmp_d_n_w,m68_cmp_d_n_l,m68_cmpa__n_w,
/* 10110001ss */ m68_eor_e_n_b,m68_eor_e_n_w,m68_eor_e_n_l,m68_cmpa__n_l,
/* 10110010ss */ m68_cmp_d_n_b,m68_cmp_d_n_w,m68_cmp_d_n_l,m68_cmpa__n_w,
/* 10110011ss */ m68_eor_e_n_b,m68_eor_e_n_w,m68_eor_e_n_l,m68_cmpa__n_l,
/* 10110100ss */ m68_cmp_d_n_b,m68_cmp_d_n_w,m68_cmp_d_n_l,m68_cmpa__n_w,
/* 10110101ss */ m68_eor_e_n_b,m68_eor_e_n_w,m68_eor_e_n_l,m68_cmpa__n_l,
/* 10110110ss */ m68_cmp_d_n_b,m68_cmp_d_n_w,m68_cmp_d_n_l,m68_cmpa__n_w,
/* 10110111ss */ m68_eor_e_n_b,m68_eor_e_n_w,m68_eor_e_n_l,m68_cmpa__n_l,
/* 10111000ss */ m68_cmp_d_n_b,m68_cmp_d_n_w,m68_cmp_d_n_l,m68_cmpa__n_w,
/* 10111001ss */ m68_eor_e_n_b,m68_eor_e_n_w,m68_eor_e_n_l,m68_cmpa__n_l,
/* 10111010ss */ m68_cmp_d_n_b,m68_cmp_d_n_w,m68_cmp_d_n_l,m68_cmpa__n_w,
/* 10111011ss */ m68_eor_e_n_b,m68_eor_e_n_w,m68_eor_e_n_l,m68_cmpa__n_l,
/* 10111100ss */ m68_cmp_d_n_b,m68_cmp_d_n_w,m68_cmp_d_n_l,m68_cmpa__n_w,
/* 10111101ss */ m68_eor_e_n_b,m68_eor_e_n_w,m68_eor_e_n_l,m68_cmpa__n_l,
/* 10111110ss */ m68_cmp_d_n_b,m68_cmp_d_n_w,m68_cmp_d_n_l,m68_cmpa__n_w,
/* 10111111ss */ m68_eor_e_n_b,m68_eor_e_n_w,m68_eor_e_n_l,m68_cmpa__n_l,
/* 11000000ss */ m68_and_d_n_b,m68_and_d_n_w,m68_and_d_n_l,m68_mulu__n_w,
/* 11000001ss */ m68_and_e_n_b,m68_and_e_n_w,m68_and_e_n_l,m68_muls__n_w,
/* 11000010ss */ m68_and_d_n_b,m68_and_d_n_w,m68_and_d_n_l,m68_mulu__n_w,
/* 11000011ss */ m68_and_e_n_b,m68_and_e_n_w,m68_and_e_n_l,m68_muls__n_w,
/* 11000100ss */ m68_and_d_n_b,m68_and_d_n_w,m68_and_d_n_l,m68_mulu__n_w,
/* 11000101ss */ m68_and_e_n_b,m68_and_e_n_w,m68_and_e_n_l,m68_muls__n_w,
/* 11000110ss */ m68_and_d_n_b,m68_and_d_n_w,m68_and_d_n_l,m68_mulu__n_w,
/* 11000111ss */ m68_and_e_n_b,m68_and_e_n_w,m68_and_e_n_l,m68_muls__n_w,
/* 11001000ss */ m68_and_d_n_b,m68_and_d_n_w,m68_and_d_n_l,m68_mulu__n_w,
/* 11001001ss */ m68_and_e_n_b,m68_and_e_n_w,m68_and_e_n_l,m68_muls__n_w,
/* 11001010ss */ m68_and_d_n_b,m68_and_d_n_w,m68_and_d_n_l,m68_mulu__n_w,
/* 11001011ss */ m68_and_e_n_b,m68_and_e_n_w,m68_and_e_n_l,m68_muls__n_w,
/* 11001100ss */ m68_and_d_n_b,m68_and_d_n_w,m68_and_d_n_l,m68_mulu__n_w,
/* 11001101ss */ m68_and_e_n_b,m68_and_e_n_w,m68_and_e_n_l,m68_muls__n_w,
/* 11001110ss */ m68_and_d_n_b,m68_and_d_n_w,m68_and_d_n_l,m68_mulu__n_w,
/* 11001111ss */ m68_and_e_n_b,m68_and_e_n_w,m68_and_e_n_l,m68_muls__n_w,
/* 11010000ss */ m68_add_d_n_b,m68_add_d_n_w,m68_add_d_n_l,m68_adda__n_w,
/* 11010001ss */ m68_add_e_n_b,m68_add_e_n_w,m68_add_e_n_l,m68_adda__n_l,
/* 11010010ss */ m68_add_d_n_b,m68_add_d_n_w,m68_add_d_n_l,m68_adda__n_w,
/* 11010011ss */ m68_add_e_n_b,m68_add_e_n_w,m68_add_e_n_l,m68_adda__n_l,
/* 11010100ss */ m68_add_d_n_b,m68_add_d_n_w,m68_add_d_n_l,m68_adda__n_w,
/* 11010101ss */ m68_add_e_n_b,m68_add_e_n_w,m68_add_e_n_l,m68_adda__n_l,
/* 11010110ss */ m68_add_d_n_b,m68_add_d_n_w,m68_add_d_n_l,m68_adda__n_w,
/* 11010111ss */ m68_add_e_n_b,m68_add_e_n_w,m68_add_e_n_l,m68_adda__n_l,
/* 11011000ss */ m68_add_d_n_b,m68_add_d_n_w,m68_add_d_n_l,m68_adda__n_w,
/* 11011001ss */ m68_add_e_n_b,m68_add_e_n_w,m68_add_e_n_l,m68_adda__n_l,
/* 11011010ss */ m68_add_d_n_b,m68_add_d_n_w,m68_add_d_n_l,m68_adda__n_w,
/* 11011011ss */ m68_add_e_n_b,m68_add_e_n_w,m68_add_e_n_l,m68_adda__n_l,
/* 11011100ss */ m68_add_d_n_b,m68_add_d_n_w,m68_add_d_n_l,m68_adda__n_w,
/* 11011101ss */ m68_add_e_n_b,m68_add_e_n_w,m68_add_e_n_l,m68_adda__n_l,
/* 11011110ss */ m68_add_d_n_b,m68_add_d_n_w,m68_add_d_n_l,m68_adda__n_w,
/* 11011111ss */ m68_add_e_n_b,m68_add_e_n_w,m68_add_e_n_l,m68_adda__n_l,
/* 11100000ss */ m68_shr_r_n_b,m68_shr_r_n_w,m68_shr_r_n_l,m68_asr_m___w,
/* 11100001ss */ m68_shl_r_n_b,m68_shl_r_n_w,m68_shl_r_n_l,m68_asl_m___w,
/* 11100010ss */ m68_shr_r_n_b,m68_shr_r_n_w,m68_shr_r_n_l,m68_lsr_m___w,
/* 11100011ss */ m68_shl_r_n_b,m68_shl_r_n_w,m68_shl_r_n_l,m68_lsl_m___w,
/* 11100100ss */ m68_shr_r_n_b,m68_shr_r_n_w,m68_shr_r_n_l,m68_roxr_m__w,
/* 11100101ss */ m68_shl_r_n_b,m68_shl_r_n_w,m68_shl_r_n_l,m68_roxl_m__w,
/* 11100110ss */ m68_shr_r_n_b,m68_shr_r_n_w,m68_shr_r_n_l,m68_ror_m___w,
/* 11100111ss */ m68_shl_r_n_b,m68_shl_r_n_w,m68_shl_r_n_l,m68_rol_m___w,
/* 11101000ss */ m68_shr_r_n_b,m68_shr_r_n_w,m68_shr_r_n_l,m68_unrecog_x,
/* 11101001ss */ m68_shl_r_n_b,m68_shl_r_n_w,m68_shl_r_n_l,m68_unrecog_x,
/* 11101010ss */ m68_shr_r_n_b,m68_shr_r_n_w,m68_shr_r_n_l,m68_unrecog_x,
/* 11101011ss */ m68_shl_r_n_b,m68_shl_r_n_w,m68_shl_r_n_l,m68_unrecog_x,
/* 11101100ss */ m68_shr_r_n_b,m68_shr_r_n_w,m68_shr_r_n_l,m68_unrecog_x,
/* 11101101ss */ m68_shl_r_n_b,m68_shl_r_n_w,m68_shl_r_n_l,m68_unrecog_x,
/* 11101110ss */ m68_shr_r_n_b,m68_shr_r_n_w,m68_shr_r_n_l,m68_unrecog_x,
/* 11101111ss */ m68_shl_r_n_b,m68_shl_r_n_w,m68_shl_r_n_l,m68_unrecog_x,
/* 11110000ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,
/* 11110001ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,
/* 11110010ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,
/* 11110011ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,
/* 11110100ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,
/* 11110101ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,
/* 11110110ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,
/* 11110111ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,
/* 11111000ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,
/* 11111001ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,
/* 11111010ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,
/* 11111011ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,
/* 11111100ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,
/* 11111101ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,
/* 11111110ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,
/* 11111111ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x};

static void cpudebug_disassemble(int n) {
	while(n--) {
		dword addr = debugpc;
		cpudebug_printf("%08X: ", addr);
		isize = 0;
		inst = fetch();
		debugmap[inst >> 6]();
		while(addr < debugpc) {
			cpudebug_printf("%04X ", s68000fetch(addr) & 0xFFFF);
			addr += 2;
		}
		while(isize < 10) {
			cpudebug_printf("     ");
			isize += 2;
		}
		cpudebug_printf("%s\n", sdebug);
	}
}

static void cpudebug_hexdump(void) {
	byte c, tmpchar[16];
	dword tmpaddr;
	int i, j, k;
	tmpaddr = hexaddr & 0xFFFFFFF0;
	for(i = 0; i < 8; i++) {
		cpudebug_printf("%08X: %c", tmpaddr,
			(hexaddr == tmpaddr) ? '>' : ' '
		);
		for(j = 0; j < 16; j += 2) {
			k = s68000fetch(tmpaddr) & 0xFFFF;
			tmpchar[j    ] = k >> 8;
			tmpchar[j + 1] = k & 0xFF;
			tmpaddr += 2;
			cpudebug_printf("%02X%02X%c",
				tmpchar[j], tmpchar[j + 1],
				(( hexaddr            == tmpaddr   )&&(j!=14))?'>':
				(((hexaddr&0xFFFFFFFE)==(tmpaddr-2))?'<':' ')
			);
		}
		cpudebug_printf("  ");
		for(j = 0; j < 16; j++) {
			c = tmpchar[j];
			if((c<32)||(c>126))c='.';
			cpudebug_printf("%c", c);
		}
		cpudebug_printf("\n");
	}
	hexaddr += 0x80;
}

static void cpudebug_registerdump(void) {
	int i;
	cpudebug_printf(
		"d0=%08X   d4=%08X   a0=%08X   a4=%08X   %c%c%c%c%c\n",
		s68000context.dreg[0],s68000context.dreg[4],
		s68000context.areg[0],s68000context.areg[4],
		(s68000context.sr >> 4) & 1 ? 'X' : '-',
		(s68000context.sr >> 3) & 1 ? 'N' : '-',
		(s68000context.sr >> 2) & 1 ? 'Z' : '-',
		(s68000context.sr >> 1) & 1 ? 'V' : '-',
		(s68000context.sr     ) & 1 ? 'C' : '-'
	);
	cpudebug_printf(
		"d1=%08X   d5=%08X   a1=%08X   a5=%08X   intmask=%d\n",
		s68000context.dreg[1], s68000context.dreg[5],
		s68000context.areg[1], s68000context.areg[5],
		(s68000context.sr >> 8) & 7
	);
	cpudebug_printf(
		"d2=%08X   d6=%08X   a2=%08X   a6=%08X   ",
		s68000context.dreg[2], s68000context.dreg[6],
		s68000context.areg[2], s68000context.areg[6]
	);
	for(i = 1; i <= 7; i++) {
		if(s68000context.interrupts[0] & (1 << i)) {
			cpudebug_printf("%02X", s68000context.interrupts[i]);
		} else {
			cpudebug_printf("--");
		}
	}
	cpudebug_printf(
		"\nd3=%08X   d7=%08X   a3=%08X   a7=%08X   %csp=%08X\n",
		s68000context.dreg[3], s68000context.dreg[7],
		s68000context.areg[3], s68000context.areg[7],
		((s68000context.sr)&0x2000)?'u':'s', s68000context.asp
	);
	debugpc = s68000context.pc;
	cpudebug_disassemble(1);
	debugpc = s68000context.pc;
}

int cpudebug_interactive(
	int cpun,
	void (*put)(const char*),
	void (*get)(char*, int),
	void (*execstep)(void),
	void (*dump)(void)
) {
	char inputstr[80];
	char *cmd, *args, *argsend;
	dword tmppc;
	hexaddr = 0;
	cpudebug_put = put;
	cpudebug_get = get;
	for(;;) {
		s68000flushInterrupts();
		cpudebug_printf("cpu%d-", cpun);
		cpudebug_gets(inputstr, sizeof(inputstr));
		cmd = inputstr;
		while((tolower(*cmd) < 'a') && (tolower(*cmd) > 'z')) {
			if(!(*cmd)) break;
			cmd++;
		}
		if(!(*cmd)) continue;
		*cmd = tolower(*cmd);
		args = cmd + 1;
		while((*args) && ((*args) < 32)) args++;
		switch(*cmd) {
		case '?':
			cpudebug_printf(
"b [address]           Run continuously, break at PC=[address]\n"
"d [address]           Dump memory, starting at [address]\n"
"h                     Hardware dump\n"
"i [number]            Generate hardware interrupt [number]\n"
"j [address]           Jump directly to [address]\n"
"q                     Quit\n"
"r                     Show register dump and next instruction\n"
"s [n]                 Switch to CPU [n]\n"
"t [hex number]        Trace through [hex number] instructions\n"
"u [address]           Unassemble code, starting at [address]\n"
			);
			break;
		case 'b':
			if(*args) {
				tmppc = strtoul(args, &argsend, 16);
				if(argsend != args) {
					while(s68000context.pc != tmppc)
					if(execstep) execstep();
					else s68000exec(1);
					cpudebug_registerdump();
				} else {
					cpudebug_printf("Invalid address\n");
				}
			} else {
				cpudebug_printf("Need an address\n");
			}
			break;
		case 'u':
			if(*args) {
				tmppc = strtoul(args, &argsend, 16);
				if(argsend != args) debugpc = tmppc;
			}
			cpudebug_disassemble(16);
			break;
		case 'd':
			if(*args) {
				tmppc = strtoul(args,&argsend,16);
				if(argsend != args) hexaddr = tmppc;
			}
			cpudebug_hexdump();
			break;
		case 'h':
			if(dump) dump();
			break;
		case 'j':
			if(*args) {
				tmppc = strtoul(args, &argsend, 16);
				if(argsend != args) {
					s68000context.pc = tmppc;
					cpudebug_printf("PC set to %08X\n",
						s68000context.pc
					);
					debugpc = s68000context.pc;
					cpudebug_disassemble(1);
					debugpc = s68000context.pc;
				} else {
					cpudebug_printf("Invalid address\n");
				}
			} else {
				cpudebug_printf("Need an address\n");
			}
			break;
		case 'i':
			if(*args) {
				tmppc = strtoul(args, &argsend, 10);
				if(argsend != args) {
					cpudebug_printf("Interrupt %d generated\n", tmppc);
					s68000interrupt(tmppc, -1);
					s68000flushInterrupts();
					cpudebug_registerdump();
					debugpc = s68000context.pc;
				} else {
					cpudebug_printf("Invalid interrupt number\n");
				}
			} else {
				cpudebug_printf("Need an interrupt number\n");
			}
			break;
		case 't':
			tmppc = 1;
			if(*args) {
				tmppc = strtoul(args, &argsend, 16);
				if(argsend == args) tmppc = 1;
			}
			if(tmppc > 0) {
				while(tmppc--) {
					if(execstep) execstep();
					else s68000exec(1);
				}
				cpudebug_registerdump();
			}
			break;
		case 'r':
			cpudebug_registerdump();
			break;
		case 'q':
			return -1;
		case 's':
			if(*args) {
				tmppc = strtoul(args, &argsend, 10);
				if(tmppc > 0) return tmppc;
				else cpudebug_printf("Invalid CPU number\n");
			} else return 0;
			break;
		default:
/*			cpudebug_printf("Unknown command\n");*/
			break;
		}
	}
	return -1;
}
