summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/cpu/saturn
diff options
context:
space:
mode:
author Aaron Giles <aaron@aarongiles.com>2007-12-17 15:19:59 +0000
committer Aaron Giles <aaron@aarongiles.com>2007-12-17 15:19:59 +0000
commit7b77f1218624ea26dbb2efd85a19f795f5d4e02e (patch)
tree19209304095572b4fd61c2a2d6a5aa75c4e471ad /src/emu/cpu/saturn
parent3da7f476068b3ffef713218ba2fc1bd5030f2c38 (diff)
Initial checkin of MAME 0.121.mame0121
Diffstat (limited to 'src/emu/cpu/saturn')
-rw-r--r--src/emu/cpu/saturn/sat.h22
-rw-r--r--src/emu/cpu/saturn/satops.c1209
-rw-r--r--src/emu/cpu/saturn/sattable.c921
-rw-r--r--src/emu/cpu/saturn/saturn.c422
-rw-r--r--src/emu/cpu/saturn/saturn.h68
-rw-r--r--src/emu/cpu/saturn/saturnds.c1454
6 files changed, 4096 insertions, 0 deletions
diff --git a/src/emu/cpu/saturn/sat.h b/src/emu/cpu/saturn/sat.h
new file mode 100644
index 00000000000..8632468dc04
--- /dev/null
+++ b/src/emu/cpu/saturn/sat.h
@@ -0,0 +1,22 @@
+enum {
+ SATURN_A=1, SATURN_B, SATURN_C, SATURN_D,
+ SATURN_R0, SATURN_R1, SATURN_R2, SATURN_R3, SATURN_R4,
+ SATURN_RSTK0, SATURN_RSTK1, SATURN_RSTK2, SATURN_RSTK3,
+ SATURN_RSTK4, SATURN_RSTK5, SATURN_RSTK6, SATURN_RSTK7,
+ SATURN_PC, SATURN_D0, SATURN_D1,
+
+ SATURN_P,
+ SATURN_IN,
+ SATURN_OUT,
+ SATURN_CARRY,
+ SATURN_ST,
+ SATURN_HST,
+
+ SATURN_EA,
+ SATURN_NMI_STATE,
+ SATURN_IRQ_STATE
+};
+
+#define PEEK_OP(pc) cpu_readop(pc)
+#define PEEK_NIBBLE(adr) cpu_readmem_20(adr)
+
diff --git a/src/emu/cpu/saturn/satops.c b/src/emu/cpu/saturn/satops.c
new file mode 100644
index 00000000000..578e3036994
--- /dev/null
+++ b/src/emu/cpu/saturn/satops.c
@@ -0,0 +1,1209 @@
+#define IRQ_ADDRESS 0xf
+
+INLINE int READ_OP(void)
+{
+ saturn_ICount-=3;
+ return cpu_readop(saturn.pc++);
+}
+
+INLINE int READ_OP_ARG(void)
+{
+ saturn_ICount-=3;
+ return cpu_readop_arg(saturn.pc++);
+}
+
+INLINE int READ_OP_ARG8(void)
+{
+ return READ_OP_ARG()|(READ_OP_ARG()<<4);
+}
+
+INLINE INT8 READ_OP_DIS8(void)
+{
+ return READ_OP_ARG()|(READ_OP_ARG()<<4);
+}
+
+INLINE int READ_OP_ARG12(void)
+{
+ return READ_OP_ARG()|(READ_OP_ARG()<<4)|(READ_OP_ARG()<<8);
+}
+
+INLINE int READ_OP_DIS12(void)
+{
+ int temp=READ_OP_ARG()|(READ_OP_ARG()<<4)|(READ_OP_ARG()<<8);
+ if (temp&0x800) return -0x1000+temp;
+ else return temp;
+}
+
+INLINE int READ_OP_ARG16(void)
+{
+ return READ_OP_ARG()|(READ_OP_ARG()<<4)|(READ_OP_ARG()<<8)|(READ_OP_ARG()<<12);
+}
+
+INLINE INT16 READ_OP_DIS16(void)
+{
+ return READ_OP_ARG()|(READ_OP_ARG()<<4)|(READ_OP_ARG()<<8)|(READ_OP_ARG()<<12);
+}
+
+INLINE int READ_OP_ARG20(void)
+{
+ return READ_OP_ARG()|(READ_OP_ARG()<<4)|(READ_OP_ARG()<<8)
+ |(READ_OP_ARG()<<12)|(READ_OP_ARG()<<16);
+}
+
+INLINE int READ_NIBBLE(SaturnAdr adr)
+{
+ int data;
+ saturn_ICount-=3;
+ data = program_read_byte(adr);
+ if (saturn.config&&saturn.config->crc) saturn.config->crc(adr, data);
+ return data;
+}
+
+INLINE int READ_8(SaturnAdr adr)
+{
+ return READ_NIBBLE(adr)|(READ_NIBBLE(adr+1)<<4);
+}
+
+INLINE int READ_12(SaturnAdr adr)
+{
+ return READ_NIBBLE(adr)|(READ_NIBBLE(adr+1)<<4)|(READ_NIBBLE(adr+2)<<8);
+}
+
+INLINE int READ_16(SaturnAdr adr)
+{
+ return READ_NIBBLE(adr)|(READ_NIBBLE(adr+1)<<4)
+ |(READ_NIBBLE(adr+2)<<8)|(READ_NIBBLE(adr+3)<<12);
+}
+
+INLINE int READ_20(SaturnAdr adr)
+{
+ return READ_NIBBLE(adr)|(READ_NIBBLE(adr+1)<<4)
+ |(READ_NIBBLE(adr+2)<<8)|(READ_NIBBLE(adr+3)<<12)|(READ_NIBBLE(adr+4)<<16);
+}
+
+INLINE void WRITE_NIBBLE(SaturnAdr adr, SaturnNib nib)
+{
+ saturn_ICount -= 3;
+ program_write_byte(adr, nib);
+}
+
+#ifdef LSB_FIRST
+#define S64_BYTE(r, x) saturn.reg[r].b[x]
+#define S64_WORD(r, x) saturn.reg[r].w[x]
+#define S64_DOUBLE(r, x) saturn.reg[r].d[x]
+#else
+#define S64_BYTE(r, x) saturn.reg[r].b[7-x]
+#define S64_WORD(r, x) saturn.reg[r].w[3-x]
+#define S64_DOUBLE(r, x) saturn.reg[r].d[1-x]
+#endif
+
+#define S64_QUAD(r) saturn.reg[r].q
+
+#define BEGIN_B 0
+#define COUNT_B 2
+#define BEGIN_X 0
+#define COUNT_X 3
+#define BEGIN_XS 2
+#define COUNT_XS 1
+#define BEGIN_A 0
+#define COUNT_A 5
+#define BEGIN_M 3
+#define COUNT_M 12
+#define BEGIN_S 15
+#define COUNT_S 1
+#define BEGIN_W 0
+#define COUNT_W 16
+
+#define S64_READ_NIBBLE(r, x) (((x)&1) ? (S64_BYTE(r, ((x)>>1))>>4) : (S64_BYTE(r, ((x)>>1))&0xf) )
+#define S64_WRITE_NIBBLE(r, x, v) \
+ (S64_BYTE(r, ((x)>>1)) = ((x)&1) \
+ ?(S64_BYTE(r, ((x)>>1))&0xf)|((v)<<4) \
+ :(S64_BYTE(r, ((x)>>1))&0xf0)|(v) )
+
+#define S64_READ_B(r) S64_BYTE(r,0)
+#define S64_WRITE_B(r,v) (S64_BYTE(r,0)=v)
+
+#define S64_READ_XS(r) S64_READ_NIBBLE(r,2)
+#define S64_WRITE_XS(r,v) S64_WRITE_NIBBLE(r,2,v)
+
+#define S64_READ_S(r) S64_READ_NIBBLE(r,15)
+#define S64_WRITE_S(r,v) S64_WRITE_NIBBLE(r,15,v)
+
+#define S64_READ_P(r) S64_READ_NIBBLE(r,saturn.p)
+#define S64_WRITE_P(r,v) S64_WRITE_NIBBLE(r,saturn.p,v)
+
+#define S64_READ_X(r) (S64_WORD(r,0)&0xfff)
+#define S64_WRITE_X(r,v) (S64_WORD(r,0)=(S64_WORD(r,0)&~0xfff)|(v))
+
+// for address reg operations
+#define S64_READ_WORD(r,nr) S64_WORD(r,nr)
+#define S64_WRITE_WORD(r,nr,v) (S64_WORD(r,nr)=v)
+
+#define S64_READ_A(r) (S64_DOUBLE(r,0)&0xfffff)
+#define S64_WRITE_A(r,v) (S64_DOUBLE(r,0)=(S64_DOUBLE(r,0)&~0xfffff)|(v))
+
+#define S64_READ_M(r) ((S64_QUAD(r)>>12)&0xffffffffffffULL)
+#define S64_WRITE_M(r,v) (S64_QUAD(r)=(S64_QUAD(r)&~0xffffffffffff000ULL)|((v)<<12))
+
+#define S64_READ_W(r) S64_QUAD(r)
+#define S64_WRITE_W(r,v) (S64_QUAD(r)=(v))
+
+INLINE SaturnAdr saturn_pop(void)
+{
+ SaturnAdr temp=saturn.rstk[0];
+ memmove(saturn.rstk, saturn.rstk+1, sizeof(saturn.rstk)-sizeof(saturn.rstk[0]));
+ saturn.rstk[7]=0;
+ saturn.stackpointer--;
+ return temp;
+}
+
+INLINE void saturn_push(SaturnAdr adr)
+{
+ memmove(saturn.rstk+1, saturn.rstk, sizeof(saturn.rstk)-sizeof(saturn.rstk[0]));
+ saturn.rstk[0]=adr;
+ saturn.stackpointer++;
+}
+
+INLINE void saturn_interrupt_on(void)
+{
+
+}
+
+INLINE void saturn_interrupt_off(void)
+{
+
+}
+
+INLINE void saturn_reset_interrupt(void)
+{
+
+}
+
+INLINE void saturn_mem_reset(void)
+{
+ if (saturn.config->reset) saturn.config->reset();
+}
+
+INLINE void saturn_mem_config(void)
+{
+ if (saturn.config->config) saturn.config->config(S64_READ_A(C));
+}
+
+INLINE void saturn_mem_unconfig(void)
+{
+ if (saturn.config->unconfig) saturn.config->unconfig(S64_READ_A(C));
+}
+
+INLINE int saturn_mem_id(void)
+{
+ if (saturn.config->id) return saturn.config->id();
+ return 0;
+}
+
+INLINE void saturn_shutdown(void)
+{
+}
+
+INLINE void saturn_bus_command_b(void)
+{
+}
+
+INLINE void saturn_bus_command_c(void)
+{
+}
+
+INLINE void saturn_bus_command_d(void)
+{
+}
+
+INLINE void saturn_serial_request(void)
+{
+}
+
+INLINE void saturn_out_c(void)
+{
+ if (saturn.config&&saturn.config->out) saturn.config->out(S64_READ_X(C));
+}
+
+INLINE void saturn_out_cs(void)
+{
+ if (saturn.config&&saturn.config->out)
+ saturn.config->out(S64_READ_NIBBLE(C,0)|(saturn.out&0xff0));
+}
+
+INLINE void saturn_in(int reg)
+{
+ if (saturn.config&&saturn.config->in) S64_WORD(reg,0)=saturn.config->in();
+}
+
+INLINE void saturn_sethex(void) { saturn.decimal=0; }
+INLINE void saturn_setdec(void) { saturn.decimal=1; }
+
+/* st related */
+INLINE void saturn_clear_st(void)
+{
+ saturn.st=0;
+}
+
+INLINE void saturn_st_to_c(void)
+{
+ S64_WRITE_X(C, saturn.st&0xfff);
+}
+
+INLINE void saturn_c_to_st(void)
+{
+ saturn.st=(saturn.st&~0xfff)|S64_READ_X(C);
+}
+
+INLINE void saturn_exchange_c_st(void)
+{
+ int t=saturn.st&0xfff;
+ saturn.st=(saturn.st&~0xfff)|S64_READ_X(C);
+ S64_WRITE_X(C, t);
+}
+
+INLINE void saturn_st_clear_bit(void)
+{
+ switch(READ_OP_ARG()) {
+ case 0: saturn.st&=~1;break;
+ case 1: saturn.st&=~2;break;
+ case 2: saturn.st&=~4;break;
+ case 3: saturn.st&=~8;break;
+ case 4: saturn.st&=~0x10;break;
+ case 5: saturn.st&=~0x20;break;
+ case 6: saturn.st&=~0x40;break;
+ case 7: saturn.st&=~0x80;break;
+ case 8: saturn.st&=~0x100;break;
+ case 9: saturn.st&=~0x200;break;
+ case 0xa: saturn.st&=~0x400;break;
+ case 0xb: saturn.st&=~0x800;break;
+ case 0xc: saturn.st&=~0x1000;break;
+ case 0xd: saturn.st&=~0x2000;break;
+ case 0xe: saturn.st&=~0x4000;break;
+ case 0xf: saturn.st&=~0x8000;break;
+ }
+}
+
+INLINE void saturn_st_set_bit(void)
+{
+ switch(READ_OP_ARG()) {
+ case 0: saturn.st|=1;break;
+ case 1: saturn.st|=2;break;
+ case 2: saturn.st|=4;break;
+ case 3: saturn.st|=8;break;
+ case 4: saturn.st|=0x10;break;
+ case 5: saturn.st|=0x20;break;
+ case 6: saturn.st|=0x40;break;
+ case 7: saturn.st|=0x80;break;
+ case 8: saturn.st|=0x100;break;
+ case 9: saturn.st|=0x200;break;
+ case 0xa: saturn.st|=0x400;break;
+ case 0xb: saturn.st|=0x800;break;
+ case 0xc: saturn.st|=0x1000;break;
+ case 0xd: saturn.st|=0x2000;break;
+ case 0xe: saturn.st|=0x4000;break;
+ case 0xf: saturn.st|=0x8000;break;
+ }
+}
+
+INLINE void saturn_st_jump_bit_clear(void)
+{
+ int adr;
+ switch(READ_OP_ARG()) {
+ case 0: saturn.carry=!saturn.st&1;break;
+ case 1: saturn.carry=!saturn.st&2;break;
+ case 2: saturn.carry=!saturn.st&4;break;
+ case 3: saturn.carry=!saturn.st&8;break;
+ case 4: saturn.carry=!saturn.st&0x10;break;
+ case 5: saturn.carry=!saturn.st&0x20;break;
+ case 6: saturn.carry=!saturn.st&0x40;break;
+ case 7: saturn.carry=!saturn.st&0x80;break;
+ case 8: saturn.carry=!saturn.st&0x100;break;
+ case 9: saturn.carry=!saturn.st&0x200;break;
+ case 0xa: saturn.carry=!saturn.st&0x400;break;
+ case 0xb: saturn.carry=!saturn.st&0x800;break;
+ case 0xc: saturn.carry=!saturn.st&0x1000;break;
+ case 0xd: saturn.carry=!saturn.st&0x2000;break;
+ case 0xe: saturn.carry=!saturn.st&0x4000;break;
+ case 0xf: saturn.carry=!saturn.st&0x8000;break;
+ }
+ adr=READ_OP_DIS8();
+ if (saturn.carry) {
+ if (adr==0) {
+ saturn.pc=saturn_pop();
+ } else {
+ saturn.pc=(saturn.pc+adr-2)&0xfffff;
+ }
+ change_pc(saturn.pc);
+ }
+}
+
+INLINE void saturn_st_jump_bit_set(void)
+{
+ int adr;
+ switch(READ_OP_ARG()) {
+ case 0: saturn.carry=saturn.st&1;break;
+ case 1: saturn.carry=saturn.st&2;break;
+ case 2: saturn.carry=saturn.st&4;break;
+ case 3: saturn.carry=saturn.st&8;break;
+ case 4: saturn.carry=saturn.st&0x10;break;
+ case 5: saturn.carry=saturn.st&0x20;break;
+ case 6: saturn.carry=saturn.st&0x40;break;
+ case 7: saturn.carry=saturn.st&0x80;break;
+ case 8: saturn.carry=saturn.st&0x100;break;
+ case 9: saturn.carry=saturn.st&0x200;break;
+ case 0xa: saturn.carry=saturn.st&0x400;break;
+ case 0xb: saturn.carry=saturn.st&0x800;break;
+ case 0xc: saturn.carry=saturn.st&0x1000;break;
+ case 0xd: saturn.carry=saturn.st&0x2000;break;
+ case 0xe: saturn.carry=saturn.st&0x4000;break;
+ case 0xf: saturn.carry=saturn.st&0x8000;break;
+ }
+ adr=READ_OP_DIS8();
+ if (saturn.carry) {
+ if (adr==0) {
+ saturn.pc=saturn_pop();
+ } else {
+ saturn.pc=(saturn.pc+adr-2)&0xfffff;
+ }
+ change_pc(saturn.pc);
+ }
+}
+
+INLINE void saturn_hst_clear_bits(void)
+{
+ saturn.hst&=~READ_OP_ARG();
+}
+
+INLINE void saturn_hst_bits_cleared(void)
+{
+ saturn.carry=!(saturn.hst&READ_OP_ARG());
+}
+
+/* p related */
+INLINE void saturn_exchange_p(void)
+{
+ int nr=READ_OP_ARG();
+ int t=saturn.p;
+ saturn.p=S64_READ_NIBBLE(C,nr);
+ S64_WRITE_NIBBLE(C,nr,t);
+}
+
+INLINE void saturn_p_to_c(void)
+{
+ int nr=READ_OP_ARG();
+ S64_WRITE_NIBBLE(C,nr,saturn.p);
+}
+
+INLINE void saturn_c_to_p(void)
+{
+ int nr=READ_OP_ARG();
+ saturn.p=S64_READ_NIBBLE(C,nr);
+}
+
+INLINE void saturn_dec_p(void)
+{
+ saturn.carry=saturn.p==0;
+ saturn.p=saturn.p-1;
+}
+
+INLINE void saturn_inc_p(void)
+{
+ saturn.p=saturn.p+1;
+ saturn.carry=saturn.p==0;
+}
+
+INLINE void saturn_load_p(void)
+{
+ saturn.p=READ_OP_ARG();
+}
+
+INLINE void saturn_p_equals(void)
+{
+ int nr=READ_OP_ARG();
+ int adr;
+ saturn.carry=saturn.p==nr;
+ adr=READ_OP_DIS8();
+ if (saturn.carry) {
+ if (adr==0) {
+ saturn.pc=saturn_pop();
+ } else {
+ saturn.pc=(saturn.pc+adr-2)&0xfffff;
+ }
+ change_pc(saturn.pc);
+ }
+}
+
+INLINE void saturn_p_not_equals(void)
+{
+ int nr=READ_OP_ARG();
+ int adr;
+ saturn.carry=saturn.p!=nr;
+ adr=READ_OP_DIS8();
+ if (saturn.carry) {
+ if (adr==0) {
+ saturn.pc=saturn_pop();
+ } else {
+ saturn.pc=(saturn.pc+adr-2)&0xfffff;
+ }
+ change_pc(saturn.pc);
+ }
+}
+
+INLINE void saturn_ca_p_1(void)
+{
+ int a=S64_READ_A(C)+1+saturn.p;
+ saturn.carry=a>=0x100000;
+ S64_WRITE_A(C,a&0xfffff);
+}
+
+INLINE void saturn_load_reg(int reg)
+{
+ int count=READ_OP_ARG();
+ int pos=saturn.p;
+ for (; count>=0; count--, pos=(pos+1)&0xf ) {
+ S64_WRITE_NIBBLE( reg, pos, READ_OP_ARG());
+ }
+}
+
+INLINE void saturn_jump(int adr, int jump)
+{
+ if (jump) {
+ saturn.pc=adr;
+ saturn_ICount-=10;
+ change_pc(saturn.pc);
+ }
+}
+
+INLINE void saturn_call(int adr)
+{
+ saturn_push(saturn.pc);
+ saturn.pc=adr;
+// saturn_ICount-=10;
+ change_pc(saturn.pc);
+}
+
+INLINE void saturn_return(int yes)
+{
+ if (yes) {
+ saturn.pc=saturn_pop();
+// saturn_ICount-=10;
+ change_pc(saturn.pc);
+ }
+}
+
+INLINE void saturn_return_carry_set(void)
+{
+ saturn.pc=saturn_pop();
+// saturn_ICount-=10;
+ change_pc(saturn.pc);
+ saturn.carry=1;
+}
+
+INLINE void saturn_return_carry_clear(void)
+{
+ saturn.pc=saturn_pop();
+// saturn_ICount-=10;
+ change_pc(saturn.pc);
+ saturn.carry=0;
+}
+
+INLINE void saturn_return_interrupt(void)
+{
+ saturn.pc=saturn_pop();
+// saturn_ICount-=10;
+ change_pc(saturn.pc);
+}
+
+INLINE void saturn_return_xm_set(void)
+{
+ saturn.pc=saturn_pop();
+ saturn.hst|=XM;
+// saturn_ICount-=10;
+ change_pc(saturn.pc);
+}
+
+INLINE void saturn_pop_c(void)
+{
+ S64_WRITE_A(C,saturn_pop());
+}
+
+INLINE void saturn_push_c(void)
+{
+ saturn_push(S64_READ_A(C));
+}
+
+INLINE void saturn_indirect_jump(int reg)
+{
+ saturn.pc=READ_20(S64_READ_A(reg));
+ change_pc(saturn.pc);
+}
+
+INLINE void saturn_equals_zero(int reg, int begin, int count)
+{
+ int i, t,adr;
+ for (i=0; i<count; i++) {
+ t=S64_READ_NIBBLE(reg, (begin+i)&0xf );
+ if (t!=0) break;
+ saturn_ICount-=2;
+ }
+ saturn.carry=i==count;
+ adr=READ_OP_DIS8();
+ if (saturn.carry) {
+ if (adr==0) {
+ saturn.pc=saturn_pop();
+ } else {
+ saturn.pc=(saturn.pc+adr-2)&0xfffff;
+ }
+ change_pc(saturn.pc);
+ }
+}
+
+INLINE void saturn_equals(int reg, int begin, int count, int right)
+{
+ int i, t,t2,adr;
+ for (i=0; i<count; i++) {
+ t=S64_READ_NIBBLE(reg, (begin+i)&0xf );
+ t2=S64_READ_NIBBLE(right, (begin+i)&0xf );
+ if (t!=t2) break;
+ saturn_ICount-=2;
+ }
+ saturn.carry=i==count;
+ adr=READ_OP_DIS8();
+ if (saturn.carry) {
+ if (adr==0) {
+ saturn.pc=saturn_pop();
+ } else {
+ saturn.pc=(saturn.pc+adr-2)&0xfffff;
+ }
+ change_pc(saturn.pc);
+ }
+}
+
+INLINE void saturn_not_equals_zero(int reg, int begin, int count)
+{
+ int i, t,adr;
+ for (i=0; i<count; i++) {
+ t=S64_READ_NIBBLE(reg, (begin+i)&0xf );
+ if (t==0) break;
+ saturn_ICount-=2;
+ }
+ saturn.carry=i==count;
+ adr=READ_OP_DIS8();
+ if (saturn.carry) {
+ if (adr==0) {
+ saturn.pc=saturn_pop();
+ } else {
+ saturn.pc=(saturn.pc+adr-2)&0xfffff;
+ }
+ change_pc(saturn.pc);
+ }
+}
+
+INLINE void saturn_not_equals(int reg, int begin, int count, int right)
+{
+ int i, t,t2,adr;
+ for (i=0; i<count; i++) {
+ t=S64_READ_NIBBLE(reg, (begin+i)&0xf );
+ t2=S64_READ_NIBBLE(right, (begin+i)&0xf );
+ if (t==t2) break;
+ saturn_ICount-=2;
+ }
+ saturn.carry=i==count;
+ adr=READ_OP_DIS8();
+ if (saturn.carry) {
+ if (adr==0) {
+ saturn.pc=saturn_pop();
+ } else {
+ saturn.pc=(saturn.pc+adr-2)&0xfffff;
+ }
+ change_pc(saturn.pc);
+ }
+}
+
+INLINE void saturn_greater(int reg, int begin, int count, int right)
+{
+ int i, t,t2,adr;
+ for (i=count; i>=0; i--) {
+ t=S64_READ_NIBBLE(reg, (begin+i)&0xf );
+ t2=S64_READ_NIBBLE(right, (begin+i)&0xf );
+ if (t<=t2) break;
+ saturn_ICount-=2;
+ }
+ saturn.carry=i<0;
+ adr=READ_OP_DIS8();
+ if (saturn.carry) {
+ if (adr==0) {
+ saturn.pc=saturn_pop();
+ } else {
+ saturn.pc=(saturn.pc+adr-2)&0xfffff;
+ }
+ change_pc(saturn.pc);
+ }
+}
+
+INLINE void saturn_greater_equals(int reg, int begin, int count, int right)
+{
+ int i, t,t2,adr;
+ for (i=count; i>=0; i--) {
+ t=S64_READ_NIBBLE(reg, (begin+i)&0xf );
+ t2=S64_READ_NIBBLE(right, (begin+i)&0xf );
+ if (t<t2) break;
+ saturn_ICount-=2;
+ }
+ saturn.carry=i<0;
+ adr=READ_OP_DIS8();
+ if (saturn.carry) {
+ if (adr==0) {
+ saturn.pc=saturn_pop();
+ } else {
+ saturn.pc=(saturn.pc+adr-2)&0xfffff;
+ }
+ change_pc(saturn.pc);
+ }
+}
+
+INLINE void saturn_smaller_equals(int reg, int begin, int count, int right)
+{
+ int i, t,t2,adr;
+ for (i=count; i>=0; i--) {
+ t=S64_READ_NIBBLE(reg, (begin+i)&0xf );
+ t2=S64_READ_NIBBLE(right, (begin+i)&0xf );
+ if (t>t2) break;
+ saturn_ICount-=2;
+ }
+ saturn.carry=i<0;
+ adr=READ_OP_DIS8();
+ if (saturn.carry) {
+ if (adr==0) {
+ saturn.pc=saturn_pop();
+ } else {
+ saturn.pc=(saturn.pc+adr-2)&0xfffff;
+ }
+ change_pc(saturn.pc);
+ }
+}
+
+INLINE void saturn_smaller(int reg, int begin, int count, int right)
+{
+ int i, t,t2,adr;
+ for (i=count; i>=0; i--) {
+ t=S64_READ_NIBBLE(reg, (begin+i)&0xf );
+ t2=S64_READ_NIBBLE(right, (begin+i)&0xf );
+ if (t>=t2) break;
+ saturn_ICount-=2;
+ }
+ saturn.carry=i<0;
+ adr=READ_OP_DIS8();
+ if (saturn.carry) {
+ if (adr==0) {
+ saturn.pc=saturn_pop();
+ } else {
+ saturn.pc=(saturn.pc+adr-2)&0xfffff;
+ }
+ change_pc(saturn.pc);
+ }
+}
+
+INLINE void saturn_jump_bit_clear(int reg)
+{
+ int adr;
+ switch(READ_OP_ARG()) {
+ case 0: saturn.carry=!(S64_BYTE( reg, 0)&1);break;
+ case 1: saturn.carry=!(S64_BYTE( reg, 0)&2);break;
+ case 2: saturn.carry=!(S64_BYTE( reg, 0)&4);break;
+ case 3: saturn.carry=!(S64_BYTE( reg, 0)&8);break;
+ case 4: saturn.carry=!(S64_BYTE( reg, 0)&0x10);break;
+ case 5: saturn.carry=!(S64_BYTE( reg, 0)&0x20);break;
+ case 6: saturn.carry=!(S64_BYTE( reg, 0)&0x40);break;
+ case 7: saturn.carry=!(S64_BYTE( reg, 0)&0x80);break;
+ case 8: saturn.carry=!(S64_BYTE( reg, 1)&1);break;
+ case 9: saturn.carry=!(S64_BYTE( reg, 1)&2);break;
+ case 0xa: saturn.carry=!(S64_BYTE( reg, 1)&4);break;
+ case 0xb: saturn.carry=!(S64_BYTE( reg, 1)&8);break;
+ case 0xc: saturn.carry=!(S64_BYTE( reg, 1)&0x10);break;
+ case 0xd: saturn.carry=!(S64_BYTE( reg, 1)&0x20);break;
+ case 0xe: saturn.carry=!(S64_BYTE( reg, 1)&0x40);break;
+ case 0xf: saturn.carry=!(S64_BYTE( reg, 1)&0x80);break;
+ }
+ adr=READ_OP_DIS8();
+ if (saturn.carry) {
+ if (adr==0) {
+ saturn.pc=saturn_pop();
+ } else {
+ saturn.pc=(saturn.pc+adr-2)&0xfffff;
+ }
+ change_pc(saturn.pc);
+ }
+}
+
+INLINE void saturn_jump_bit_set(int reg)
+{
+ int adr;
+ switch(READ_OP_ARG()) {
+ case 0: saturn.carry=S64_BYTE( reg, 0)&1;break;
+ case 1: saturn.carry=S64_BYTE( reg, 0)&2;break;
+ case 2: saturn.carry=S64_BYTE( reg, 0)&4;break;
+ case 3: saturn.carry=S64_BYTE( reg, 0)&8;break;
+ case 4: saturn.carry=S64_BYTE( reg, 0)&0x10;break;
+ case 5: saturn.carry=S64_BYTE( reg, 0)&0x20;break;
+ case 6: saturn.carry=S64_BYTE( reg, 0)&0x40;break;
+ case 7: saturn.carry=S64_BYTE( reg, 0)&0x80;break;
+ case 8: saturn.carry=S64_BYTE( reg, 1)&1;break;
+ case 9: saturn.carry=S64_BYTE( reg, 1)&2;break;
+ case 0xa: saturn.carry=S64_BYTE( reg, 1)&4;break;
+ case 0xb: saturn.carry=S64_BYTE( reg, 1)&8;break;
+ case 0xc: saturn.carry=S64_BYTE( reg, 1)&0x10;break;
+ case 0xd: saturn.carry=S64_BYTE( reg, 1)&0x20;break;
+ case 0xe: saturn.carry=S64_BYTE( reg, 1)&0x40;break;
+ case 0xf: saturn.carry=S64_BYTE( reg, 1)&0x80;break;
+ }
+ adr=READ_OP_DIS8();
+ if (saturn.carry) {
+ if (adr==0) {
+ saturn.pc=saturn_pop();
+ } else {
+ saturn.pc=(saturn.pc+adr-2)&0xfffff;
+ }
+ change_pc(saturn.pc);
+ }
+}
+
+INLINE void saturn_load_pc(int reg)
+{
+ saturn.pc=S64_READ_A(reg);
+ change_pc(saturn.pc);
+}
+
+INLINE void saturn_store_pc(int reg)
+{
+ S64_WRITE_A(reg,saturn.pc);
+}
+
+INLINE void saturn_exchange_pc(int reg)
+{
+ int temp=saturn.pc;
+ saturn.pc=S64_READ_A(reg);
+ change_pc(saturn.pc);
+ S64_WRITE_A(reg, temp);
+}
+
+/*************************************************************************************
+ address register related
+*************************************************************************************/
+INLINE void saturn_load_adr(int reg, int nibbles)
+{
+ switch (nibbles) {
+ case 5:
+ saturn.d[reg]=READ_OP_ARG20();
+ break;
+ case 4:
+ saturn.d[reg]=(saturn.d[reg]&0xf0000)|READ_OP_ARG16();
+ break;
+ case 2:
+ saturn.d[reg]=(saturn.d[reg]&0xfff00)|READ_OP_ARG8();
+ break;
+ }
+}
+
+INLINE void saturn_add_adr(int reg)
+{
+ int t=saturn.d[reg]+READ_OP_ARG()+1;
+ saturn.d[reg]=t&0xfffff;
+ saturn.carry=t>=0x100000;
+}
+
+INLINE void saturn_sub_adr(int reg)
+{
+ int t=saturn.d[reg]-READ_OP_ARG()-1;
+ saturn.d[reg]=t&0xfffff;
+ saturn.carry=t<0;
+}
+
+INLINE void saturn_adr_to_reg(int adr, int reg)
+{
+ S64_WRITE_A(reg,saturn.d[adr]);
+}
+
+INLINE void saturn_reg_to_adr(int reg, int adr)
+{
+ saturn.d[adr]=S64_READ_A(reg);
+}
+
+INLINE void saturn_adr_to_reg_word(int adr, int reg)
+{
+ S64_WRITE_WORD(reg,0,saturn.d[adr]&0xffff);
+}
+
+INLINE void saturn_reg_to_adr_word(int reg, int adr)
+{
+ saturn.d[adr]=(saturn.d[adr]&0xf0000)|S64_READ_WORD(reg,0);
+}
+
+INLINE void saturn_exchange_adr_reg(int adr, int reg)
+{
+ int temp=saturn.d[adr];
+ saturn.d[adr]=S64_READ_A(reg);
+ S64_WRITE_A(reg,temp);
+}
+
+INLINE void saturn_exchange_adr_reg_word(int adr, int reg)
+{
+ int temp=saturn.d[adr]&0xffff;
+ saturn.d[adr]=(saturn.d[adr]&0xf0000)|S64_READ_WORD(reg,0);
+ S64_WRITE_WORD(reg,0,temp);
+}
+
+INLINE void saturn_load_nibbles(int reg, int begin, int count, int adr)
+{
+ int i;
+ for (i=0; i<count; i++) {
+ S64_WRITE_NIBBLE(reg,(begin+i)&0xf,READ_NIBBLE(saturn.d[adr]+i) );
+ saturn_ICount-=2;
+ }
+}
+
+INLINE void saturn_store_nibbles(int reg, int begin, int count, int adr)
+{
+ int i;
+ for (i=0; i<count; i++) {
+ WRITE_NIBBLE(saturn.d[adr]+i,S64_READ_NIBBLE(reg,(begin+i)&0xf) );
+ saturn_ICount-=2;
+ }
+}
+
+INLINE void saturn_clear_bit(int reg)
+{
+ switch(READ_OP_ARG()) {
+ case 0: S64_BYTE( reg, 0)&=~1;break;
+ case 1: S64_BYTE( reg, 0)&=~2;break;
+ case 2: S64_BYTE( reg, 0)&=~4;break;
+ case 3: S64_BYTE( reg, 0)&=~8;break;
+ case 4: S64_BYTE( reg, 0)&=~0x10;break;
+ case 5: S64_BYTE( reg, 0)&=~0x20;break;
+ case 6: S64_BYTE( reg, 0)&=~0x40;break;
+ case 7: S64_BYTE( reg, 0)&=~0x80;break;
+ case 8: S64_BYTE( reg, 1)&=~1;break;
+ case 9: S64_BYTE( reg, 1)&=~2;break;
+ case 0xa: S64_BYTE( reg, 1)&=~4;break;
+ case 0xb: S64_BYTE( reg, 1)&=~8;break;
+ case 0xc: S64_BYTE( reg, 1)&=~0x10;break;
+ case 0xd: S64_BYTE( reg, 1)&=~0x20;break;
+ case 0xe: S64_BYTE( reg, 1)&=~0x40;break;
+ case 0xf: S64_BYTE( reg, 1)&=~0x80;break;
+ }
+}
+
+INLINE void saturn_set_bit(int reg)
+{
+ switch(READ_OP_ARG()) {
+ case 0: S64_BYTE( reg, 0)|=1;break;
+ case 1: S64_BYTE( reg, 0)|=2;break;
+ case 2: S64_BYTE( reg, 0)|=4;break;
+ case 3: S64_BYTE( reg, 0)|=8;break;
+ case 4: S64_BYTE( reg, 0)|=0x10;break;
+ case 5: S64_BYTE( reg, 0)|=0x20;break;
+ case 6: S64_BYTE( reg, 0)|=0x40;break;
+ case 7: S64_BYTE( reg, 0)|=0x80;break;
+ case 8: S64_BYTE( reg, 1)|=1;break;
+ case 9: S64_BYTE( reg, 1)|=2;break;
+ case 0xa: S64_BYTE( reg, 1)|=4;break;
+ case 0xb: S64_BYTE( reg, 1)|=8;break;
+ case 0xc: S64_BYTE( reg, 1)|=0x10;break;
+ case 0xd: S64_BYTE( reg, 1)|=0x20;break;
+ case 0xe: S64_BYTE( reg, 1)|=0x40;break;
+ case 0xf: S64_BYTE( reg, 1)|=0x80;break;
+ }
+}
+
+/****************************************************************************
+ clear opers
+ ****************************************************************************/
+INLINE void saturn_clear(int reg, int begin, int count)
+{
+ int i;
+ for (i=0; i<count; i++) {
+ S64_WRITE_NIBBLE(reg, (begin+i)&0xf, 0);
+ saturn_ICount-=2;
+ }
+}
+
+/****************************************************************************
+ exchange opers
+ ****************************************************************************/
+INLINE void saturn_exchange(int left, int begin, int count, int right)
+{
+ int i;
+ SaturnNib temp;
+ for (i=0; i<count; i++) {
+ temp=S64_READ_NIBBLE(left,(begin+i)&0xf);
+ S64_WRITE_NIBBLE(left, (begin+i)&0xf, S64_READ_NIBBLE(right,(begin+i)&0xf));
+ S64_WRITE_NIBBLE(right, (begin+i)&0xf, temp);
+ saturn_ICount-=2;
+ }
+}
+
+/****************************************************************************
+ copy opers
+ ****************************************************************************/
+INLINE void saturn_copy(int dest, int begin, int count, int src)
+{
+ int i;
+ for (i=0; i<count; i++) {
+ S64_WRITE_NIBBLE(dest, (begin+i)&0xf, S64_READ_NIBBLE(src, (begin+i)&0xf));
+ saturn_ICount-=2;
+ }
+}
+
+/****************************************************************************
+ add opers
+ ****************************************************************************/
+INLINE void saturn_add(int reg, int begin, int count, int right)
+{
+ int i, t=0;
+ for (i=0; i<count; i++) {
+ if (t>0x10) {
+ t=S64_READ_NIBBLE(reg, (begin+i)&0xf)+1;
+ } else {
+ t=S64_READ_NIBBLE(reg, (begin+i)&0xf);
+ }
+ t+=S64_READ_NIBBLE(right, (begin+i)&0xf );
+ S64_WRITE_NIBBLE(reg, (begin+i)&0xf , t&0x0f);
+ saturn_ICount-=2;
+ }
+ saturn.carry=t==0x10;
+}
+
+INLINE void saturn_add_const(int reg, int begin, int count, SaturnNib right)
+{
+ int i, t=0;
+ for (i=0; i<count; i++) {
+ t=S64_READ_NIBBLE(reg, (begin+i)&0xf);
+ t+=right;
+ right=(right>>4)+1;
+ S64_WRITE_NIBBLE(reg, (begin+i)&0xf, t&0x0f);
+ saturn_ICount-=2;
+ if (t<0x10) break;
+ }
+ saturn.carry=t>=0x10;
+}
+
+/****************************************************************************
+ sub opers
+ ****************************************************************************/
+INLINE void saturn_sub(int reg, int begin, int count, int right)
+{
+ int i, t=0;
+ for (i=0; i<count; i++) {
+ if (t>0x10) {
+ t=S64_READ_NIBBLE(reg, (begin+i)&0xf)-1;
+ } else {
+ t=S64_READ_NIBBLE(reg, (begin+i)&0xf );
+ }
+ t-=S64_READ_NIBBLE(right, (begin+i)&0xf );
+ S64_WRITE_NIBBLE(reg, (begin+i)&0xf, t&0x0f);
+ saturn_ICount-=2;
+ }
+ saturn.carry=t<0;
+}
+
+INLINE void saturn_sub_const(int reg, int begin, int count, int right)
+{
+ int i, t=0;
+ for (i=0; i<count; i++) {
+ t=S64_READ_NIBBLE(reg, (begin+i)&0xf );
+ t-=right;
+ right=(right>>4)+1;
+ S64_WRITE_NIBBLE(reg, (begin+i)&0xf, t&0x0f);
+ saturn_ICount-=2;
+ if (t>=0) break;
+ }
+ saturn.carry=t<0;
+}
+
+/****************************************************************************
+ sub2 opers (a=b-a)
+ ****************************************************************************/
+INLINE void saturn_sub2(int reg, int begin, int count, int right)
+{
+ int i, t=0;
+ for (i=0; i<count; i++) {
+ t=S64_READ_NIBBLE(reg, (begin+i)&0xf );
+ t=S64_READ_NIBBLE(right, i)-t;
+ S64_WRITE_NIBBLE(reg, (begin+i)&0xf, t&0x0f);
+ saturn_ICount-=2;
+ if (t>=0) break;
+ }
+ saturn.carry=t<0;
+}
+
+/****************************************************************************
+ increment opers
+ ****************************************************************************/
+INLINE void saturn_increment(int reg, int begin, int count)
+{
+ int i, t=0;
+ for (i=0; i<count; i++) {
+ t=S64_READ_NIBBLE(reg, (begin+i)&0xf );
+ t++;
+ S64_WRITE_NIBBLE(reg, (begin+i)&0xf, t&0x0f);
+ saturn_ICount-=2;
+ if (t!=0x10) break;
+ }
+}
+
+/****************************************************************************
+ decrement opers
+ ****************************************************************************/
+INLINE void saturn_decrement(int reg, int begin, int count)
+{
+ int i, t=0;
+ for (i=0; i<count; i++) {
+ t=S64_READ_NIBBLE(reg, (begin+i)&0xf );
+ t=(t-1)&0xf;
+ S64_WRITE_NIBBLE(reg, (begin+i)&0xf, t);
+ saturn_ICount-=2;
+ if (t!=0) break;
+ }
+ saturn.carry=t==0;
+}
+
+/****************************************************************************
+ invert (1 complement) opers
+ ****************************************************************************/
+INLINE void saturn_invert(int reg, int begin, int count)
+{
+ int i;
+ SaturnNib n;
+ saturn.carry=1;
+ for (i=0; i<count; i++) {
+ S64_WRITE_NIBBLE(reg, (begin+i)&0xf, (n=S64_READ_NIBBLE(reg,(begin+i)&0xf)) ^ 0xf);
+ saturn.carry=saturn.carry && (n==0);
+ saturn_ICount-=2;
+ }
+}
+
+/****************************************************************************
+ negate (2 complement) opers
+ ****************************************************************************/
+INLINE void saturn_negate(int reg, int begin, int count)
+{
+ int i;
+ SaturnNib n;
+ saturn.carry=1;
+ for (i=0; i<count; i++) {
+ n=S64_READ_NIBBLE(reg, (begin+i)&0xf );
+ saturn.carry=saturn.carry && (n==0);
+ n=((n ^ 0xf)+1)&0xf;
+ S64_WRITE_NIBBLE(reg, (begin+i)&0xf, n);
+ saturn_ICount-=2;
+ }
+}
+
+/****************************************************************************
+ or opers
+ ****************************************************************************/
+INLINE void saturn_or(int dest, int begin, int count, int src)
+{
+ int i;
+ for (i=0; i<count; i++) {
+ S64_WRITE_NIBBLE(dest, (begin+i)&0xf,
+ S64_READ_NIBBLE(dest,(begin+i)&0xf)|S64_READ_NIBBLE(src,(begin+i)&0xf));
+ saturn_ICount-=2;
+ }
+}
+
+/****************************************************************************
+ and opers
+ ****************************************************************************/
+INLINE void saturn_and(int dest, int begin, int count, int src)
+{
+ int i;
+ for (i=0; i<count; i++) {
+ S64_WRITE_NIBBLE(dest, (begin+i)&0xf,
+ S64_READ_NIBBLE(dest,(begin+i)&0xf)&S64_READ_NIBBLE(src,(begin+i)&0xf));
+ saturn_ICount-=2;
+ }
+}
+
+/****************************************************************************
+ shift nibbles left opers
+ ****************************************************************************/
+INLINE void saturn_shift_nibble_left(int reg, int begin, int count)
+{
+ int i;
+ for (i=count; i>1; i--) {
+ S64_WRITE_NIBBLE(reg, (begin+i)&0xf, S64_READ_NIBBLE(reg,(begin+i-1)&0xf) );
+ saturn_ICount-=2;
+ }
+ S64_WRITE_NIBBLE(reg, begin, 0);
+ saturn_ICount-=2;
+}
+
+/****************************************************************************
+ shift nibbles right opers
+ ****************************************************************************/
+INLINE void saturn_shift_nibble_right(int reg, int begin, int count)
+{
+ int i;
+ for (i=1; i<count; i++) {
+ S64_WRITE_NIBBLE(reg, (begin+i-1)&0xf, S64_READ_NIBBLE(reg,(begin+i)&0xf) );
+ saturn_ICount-=2;
+ }
+ S64_WRITE_NIBBLE(reg, (begin+i-1)&0xf, 0);
+ saturn_ICount-=2;
+}
+
+/****************************************************************************
+ rotate nibble left opers
+ ****************************************************************************/
+INLINE void saturn_rotate_nibble_left_w(int reg)
+{
+ SaturnNib a=S64_READ_NIBBLE(reg, 15);
+ S64_WRITE_W(reg, S64_READ_W(reg)<<4);
+ S64_WRITE_NIBBLE(reg,0,a);
+ saturn_ICount-=32;
+}
+
+INLINE void saturn_rotate_nibble_right_w(int reg)
+{
+ SaturnNib a=S64_READ_NIBBLE(reg,0);
+ if (a) saturn.hst|=SB;
+ S64_WRITE_W(reg, S64_READ_W(reg)>>4);
+ S64_WRITE_NIBBLE(reg,15,a);
+ saturn_ICount-=32;
+}
+
+/****************************************************************************
+ shift right opers
+ ****************************************************************************/
+INLINE void saturn_shift_right(int reg, int begin, int count)
+{
+ int i, t, c=0;
+ for (i=count; i>=count; i--) {
+ t=S64_READ_NIBBLE(reg, (begin+i)&0xf );
+ if (c) t|=0x10;
+ c=t&1;
+ S64_WRITE_NIBBLE(reg, (begin+i-1)&0xf, t>>1);
+ saturn_ICount-=2;
+ }
+ if (c) saturn.hst|=SB;
+ saturn_ICount-=2;
+}
+
+
+/****************************************************************************
+ shift left opers, sets carry!
+ ****************************************************************************/
+INLINE void saturn_shift_left(int reg, int begin, int count)
+{
+ SaturnNib t;
+ int i;
+ saturn.carry=0;
+ for (i=0; i<count; i++) {
+ t=S64_READ_NIBBLE(reg,(begin+i)&0xf);
+ S64_WRITE_NIBBLE(reg, (begin+i)&0xf, ((t<<1)&0xf)|saturn.carry);
+ saturn.carry=t&8?1:0;
+ saturn_ICount-=2;
+ }
+}
diff --git a/src/emu/cpu/saturn/sattable.c b/src/emu/cpu/saturn/sattable.c
new file mode 100644
index 00000000000..3eb06fd986d
--- /dev/null
+++ b/src/emu/cpu/saturn/sattable.c
@@ -0,0 +1,921 @@
+static const int adr_a_begin[]={
+-1, -1, BEGIN_XS, BEGIN_X, BEGIN_S, BEGIN_M, BEGIN_B, BEGIN_W,
+};
+
+static const int adr_a_count[]={
+-1, -1, COUNT_XS, COUNT_X, COUNT_S, COUNT_M, COUNT_B, COUNT_W,
+};
+
+static const int adr_b_begin[]={
+-1, -1, -1, -1, -1, -1, -1, -1,
+-1, -1, BEGIN_XS, BEGIN_X, BEGIN_S, BEGIN_M, BEGIN_B, BEGIN_W,
+};
+
+static const int adr_b_count[]={
+-1, -1, -1, -1, -1, -1, -1, -1,
+-1, -1, COUNT_XS, COUNT_X, COUNT_S, COUNT_M, COUNT_B, COUNT_W,
+};
+
+static const int adr_af_begin[]={
+-1, -1, BEGIN_XS, BEGIN_X, BEGIN_S, BEGIN_M, BEGIN_B, BEGIN_W,
+-1, -1, -1, -1, -1, -1, -1, BEGIN_A
+};
+
+static const int adr_af_count[]={
+-1, -1, COUNT_XS, COUNT_X, COUNT_S, COUNT_M, COUNT_B, COUNT_W,
+-1, -1, -1, -1, -1, -1, -1, COUNT_A
+};
+
+static const int reg_left[]={A,B,C,D,B,C,A,C};
+static const int reg_right[]={B,C,A,C,A,B,C,D};
+static const int add_left[]={ A,B,C,D, 0,0,0,0, B,C,A,C };
+static const int add_right[]={ B,C,A,C, 0,0,0,0, A,B,C,D };
+static const int sub_left[]={A,B,C,D, 0,0,0,0, B,C,A,C, A,B,C,D};
+static const int sub_right[]={B,C,A,C, 0,0,0,0, A,B,C,D, A,B,C,D };
+
+INLINE void saturn_instruction_0e(void)
+{
+ int reg, adr;
+
+ switch(adr=READ_OP()) {
+ case 0:
+ switch(reg=READ_OP()){
+ case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
+ saturn_and(reg_left[reg], saturn.p, 1, reg_right[reg]);
+ break; //A=A&B p
+ case 8: case 9: case 0xa: case 0xb: case 0xc: case 0xd: case 0xe: case 0xf:
+ saturn_or(reg_left[reg&7], saturn.p, 1, reg_right[reg&7]);
+ break; //A=A!B p
+ }
+ break;
+ case 1:
+ switch(reg=READ_OP()){
+ case 0: case 1: case 2: case 3:case 4: case 5: case 6: case 7:
+ saturn_and(reg_left[reg], 0, saturn.p+1, reg_right[reg]);
+ break; //A=A&B wp
+ case 8: case 9: case 0xa: case 0xb: case 0xc: case 0xd: case 0xe: case 0xf:
+ saturn_or(reg_left[reg&7], 0, saturn.p+1, reg_right[reg&7]);
+ break; //A=A!B wp
+ }
+ break;
+ case 2: case 3: case 4: case 5: case 6: case 7: case 0xf:
+ switch(reg=READ_OP()){
+ case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
+ saturn_and(reg_left[reg], adr_af_begin[adr], adr_af_count[adr], reg_right[reg]);
+ break; //A=A&B xs
+ case 8: case 9: case 0xa: case 0xb: case 0xc: case 0xd: case 0xe: case 0xf:
+ saturn_or(reg_left[reg&7], adr_af_begin[adr], adr_af_count[adr], reg_right[reg&7]);
+ break; //A=A!B xs
+ }
+ break;
+ }
+}
+
+static void saturn_instruction_1(void)
+{
+ int reg, adr, oper;
+
+ switch (adr=READ_OP()) {
+ case 0:
+ switch (reg=READ_OP()) {
+ case 0: case 1: case 2: case 3: case 4:
+ saturn_copy(R0+reg, BEGIN_W, COUNT_W, A);
+ break; // r0=a w
+ case 8: case 9: case 0xa: case 0xb: case 0xc:
+ saturn_copy(R0+(reg&7), BEGIN_W, COUNT_W, C);
+ break; // r0=c w
+ }
+ break;
+ case 1:
+ switch (reg=READ_OP()) {
+ case 0: case 1: case 2: case 3: case 4:
+ saturn_copy(A, BEGIN_W, COUNT_W, R0+reg);
+ break; // a=r0 w
+ case 8: case 9: case 0xa: case 0xb: case 0xc:
+ saturn_copy(C, BEGIN_W, COUNT_W, R0+(reg&7));
+ break; // c=r0 w
+ }
+ break;
+ case 2:
+ switch (reg=READ_OP()) {
+ case 0: case 1: case 2: case 3: case 4:
+ saturn_exchange(A, BEGIN_W, COUNT_W, R0+reg);
+ break; // ar0ex w
+ case 8: case 9: case 0xa: case 0xb: case 0xc:
+ saturn_exchange(C, BEGIN_W, COUNT_W, R0+(reg&7));
+ break; // cr0ex w
+ }
+ break;
+ case 3:
+ switch (READ_OP()) {
+ case 0: saturn_reg_to_adr(A,0);break;
+ case 1: saturn_reg_to_adr(A,1);break;
+ case 2: saturn_exchange_adr_reg(0,A);break;
+ case 3: saturn_exchange_adr_reg(1,A);break;
+ case 4: saturn_reg_to_adr(C,0);break;
+ case 5: saturn_reg_to_adr(C,1);break;
+ case 6: saturn_exchange_adr_reg(0,C);break;
+ case 7: saturn_exchange_adr_reg(1,C);break;
+ case 8: saturn_reg_to_adr_word(A,0);break;
+ case 9: saturn_reg_to_adr_word(A,1);break;
+ case 0xa: saturn_exchange_adr_reg_word(0,A);break;
+ case 0xb: saturn_exchange_adr_reg_word(1,A);break;
+ case 0xc: saturn_reg_to_adr_word(C,0);break;
+ case 0xd: saturn_reg_to_adr_word(C,1);break;
+ case 0xe: saturn_exchange_adr_reg_word(0,C);break;
+ case 0xf: saturn_exchange_adr_reg_word(1,C);break;
+ }
+ break;
+ case 4:
+ switch (READ_OP()) {
+ case 0: saturn_store_nibbles(A, BEGIN_A, COUNT_A, 0); break;
+ case 1: saturn_store_nibbles(A, BEGIN_A, COUNT_A, 1); break;
+ case 2: saturn_load_nibbles(A, BEGIN_A, COUNT_A, 0); break;
+ case 3: saturn_load_nibbles(A, BEGIN_A, COUNT_A, 1); break;
+ case 4: saturn_store_nibbles(C, BEGIN_A, COUNT_A, 0); break;
+ case 5: saturn_store_nibbles(C, BEGIN_A, COUNT_A, 1); break;
+ case 6: saturn_load_nibbles(C, BEGIN_A, COUNT_A, 0); break;
+ case 7: saturn_load_nibbles(C, BEGIN_A, COUNT_A, 1); break;
+ case 8: saturn_store_nibbles(A, BEGIN_B, COUNT_B, 0); break;
+ case 9: saturn_store_nibbles(A, BEGIN_B, COUNT_B, 1); break;
+ case 0xa: saturn_load_nibbles(A, BEGIN_B, COUNT_B, 0); break;
+ case 0xb: saturn_load_nibbles(A, BEGIN_B, COUNT_B, 1); break;
+ case 0xc: saturn_store_nibbles(C, BEGIN_B, COUNT_B, 0); break;
+ case 0xd: saturn_store_nibbles(C, BEGIN_B, COUNT_B, 1); break;
+ case 0xe: saturn_load_nibbles(C, BEGIN_B, COUNT_B, 0); break;
+ case 0xf: saturn_load_nibbles(C, BEGIN_B, COUNT_B, 1); break;
+ }
+ break;
+ case 5:
+ switch (oper=READ_OP()) {
+ case 0: case 1: case 4: case 5:
+ switch (adr=READ_OP()) {
+ case 0:
+ saturn_store_nibbles(oper&4?C:A,saturn.p,1,oper&1);
+ break;
+ case 1:
+ saturn_store_nibbles(oper&4?C:A,0,saturn.p+1,oper&1);
+ break;
+ case 2: case 3: case 4: case 5: case 6: case 7:
+ saturn_store_nibbles(oper&4?C:A,adr_a_begin[adr],adr_a_count[adr],oper&1);
+ break;
+ }
+ break;
+ case 2: case 3: case 6: case 7:
+ switch (adr=READ_OP()) {
+ case 0:
+ saturn_load_nibbles(oper&4?C:A,saturn.p,1,oper&1);
+ break;
+ case 1:
+ saturn_load_nibbles(oper&4?C:A,0,saturn.p+1,oper&1);
+ break;
+ case 2: case 3: case 4: case 5: case 6: case 7:
+ saturn_load_nibbles(oper&4?C:A,adr_a_begin[adr],adr_a_count[adr],oper&1);
+ break;
+ }
+ break;
+ case 8: saturn_store_nibbles(A, 0, READ_OP()+1, 0); break;
+ case 9: saturn_store_nibbles(A, 0, READ_OP()+1, 1); break;
+ case 0xa: saturn_load_nibbles(A, 0, READ_OP()+1, 0); break;
+ case 0xb: saturn_load_nibbles(A, 0, READ_OP()+1, 1); break;
+ case 0xc: saturn_store_nibbles(C, 0, READ_OP()+1, 0); break;
+ case 0xd: saturn_store_nibbles(C, 0, READ_OP()+1, 1); break;
+ case 0xe: saturn_load_nibbles(C, 0, READ_OP()+1, 0); break;
+ case 0xf: saturn_load_nibbles(C, 0, READ_OP()+1, 1); break;
+ }
+ break;
+ case 9: saturn_load_adr(0,2);break;
+ case 0xa: saturn_load_adr(0,4);break;
+ case 0xb: saturn_load_adr(0,5);break;
+ case 0xd: saturn_load_adr(1,2);break;
+ case 0xe: saturn_load_adr(1,4);break;
+ case 0xf: saturn_load_adr(1,5);break;
+ case 6: saturn_add_adr(0);break;
+ case 7: saturn_add_adr(1);break;
+ case 8: saturn_sub_adr(0);break;
+ case 0xc: saturn_sub_adr(1);break;
+ }
+}
+
+static void saturn_instruction_80(void)
+{
+ switch(READ_OP()) {
+ case 0: saturn_out_cs();break;
+ case 1: saturn_out_c();break;
+ case 2: saturn_in(A);break;
+ case 3: saturn_in(C);break;
+ case 4: saturn_mem_unconfig();break;
+ case 5: saturn_mem_config();break;
+ case 6: saturn_mem_id();break;
+ case 7: saturn_shutdown();break;
+ case 8:
+ switch(READ_OP()) {
+ case 0: saturn_interrupt_on();break;
+ case 1:
+ switch(READ_OP()) {
+ case 0: saturn_reset_interrupt();break;
+ }
+ break;
+ case 2: saturn_load_reg(A);break; //la
+ case 3: saturn_bus_command_c();break;
+ case 4: saturn_clear_bit(A);break; // abit=0
+ case 5: saturn_set_bit(A);break; // abit=1
+ case 6: saturn_jump_bit_clear(A);break;
+ case 7: saturn_jump_bit_set(A);break;
+ case 8: saturn_clear_bit(C);break; // cbit=0
+ case 9: saturn_set_bit(C);break; // cbit=1
+ case 0xa: saturn_jump_bit_clear(C);break;
+ case 0xb: saturn_jump_bit_set(C);break;
+ case 0xc: saturn_indirect_jump(A);break;
+ case 0xd: saturn_bus_command_d();break;
+ case 0xe: saturn_indirect_jump(C);break;
+ case 0xf: saturn_interrupt_off();break;
+ }
+ break;
+ case 9: saturn_ca_p_1();break;//C+P+1
+ case 0xa: saturn_mem_reset();break;
+ case 0xb: saturn_bus_command_b();break;
+ case 0xc: saturn_p_to_c();break;
+ case 0xd: saturn_c_to_p();break;
+ case 0xe: saturn_serial_request();break;
+ case 0xf: saturn_exchange_p();break;
+ }
+}
+
+static void saturn_instruction_81a(void)
+{
+ int reg, adr;
+ switch(adr=READ_OP()) {
+ case 0:
+ switch(READ_OP()) {
+ case 0:
+ switch(reg=READ_OP()) {
+ case 0: case 1: case 2: case 3: case 4:
+ saturn_copy(R0+reg,saturn.p,1,A);
+ break; //r0=a p
+ case 8: case 9: case 0xa: case 0xb: case 0xc:
+ saturn_copy(R0+(reg&7),saturn.p,1,C);
+ break; //r0=c p
+ }
+ break;
+ case 1:
+ switch(reg=READ_OP()) {
+ case 0: case 1: case 2: case 3: case 4:
+ saturn_copy(A,saturn.p,1,R0+reg);
+ break; //a=r0 p
+ case 8: case 9: case 0xa: case 0xb: case 0xc:
+ saturn_copy(C,saturn.p,1,R0+(reg&7));
+ break; //c=r0 p
+ }
+ break;
+ case 2:
+ switch (reg=READ_OP()) {
+ case 0: case 1: case 2: case 3: case 4:
+ saturn_exchange(A, saturn.p,1,R0+reg);
+ break; // ar0ex p
+ case 8: case 9: case 0xa: case 0xb: case 0xc:
+ saturn_exchange(C, saturn.p,1,R0+(reg&7));
+ break; // cr0ex p
+ }
+ break;
+ }
+ break;
+ case 1:
+ switch(READ_OP()) {
+ case 0:
+ switch(reg=READ_OP()) {
+ case 0: case 1: case 2: case 3: case 4:
+ saturn_copy(R0+reg,0,saturn.p+1,A);
+ break; //r0=a wp
+ case 8: case 9: case 0xa: case 0xb: case 0xc:
+ saturn_copy(R0+(reg&7),0,saturn.p+1,C);
+ break; //r0=c wp
+ }
+ break;
+ case 1:
+ switch(reg=READ_OP()) {
+ case 0: case 1: case 2: case 3: case 4:
+ saturn_copy(A,0,saturn.p+1,R0+reg);
+ break; //a=r0 wp
+ case 8: case 9: case 0xa: case 0xb: case 0xc:
+ saturn_copy(C,0,saturn.p+1,R0+(reg&7));
+ break; //c=r0 wp
+ }
+ break;
+ case 2:
+ switch (reg=READ_OP()) {
+ case 0: case 1: case 2: case 3: case 4:
+ saturn_exchange(A, 0, saturn.p+1, R0+reg);
+ break; // ar0ex wp
+ case 8: case 9: case 0xa: case 0xb: case 0xc:
+ saturn_exchange(C, 0, saturn.p+1, R0+(reg&7));
+ break; // cr0ex wp
+ }
+ break;
+ }
+ break;
+ case 2: case 3: case 4: case 5: case 6: case 7: case 0xf:
+ switch(READ_OP()) {
+ case 0:
+ switch(reg=READ_OP()) {
+ case 0: case 1: case 2: case 3: case 4:
+ saturn_copy(R0+reg,adr_af_begin[adr],adr_af_count[adr],A);
+ break; //r0=a xs
+ case 8: case 9: case 0xa: case 0xb: case 0xc:
+ saturn_copy(R0+(reg&7),adr_af_begin[adr], adr_af_count[adr],C);
+ break; //r0=c xs
+ }
+ break;
+ case 1:
+ switch(reg=READ_OP()) {
+ case 0: case 1: case 2: case 3: case 4:
+ saturn_copy(A,adr_af_begin[adr],adr_af_count[adr],R0+reg);
+ break; //a=r0 xs
+ case 8: case 9: case 0xa: case 0xb: case 0xc:
+ saturn_copy(C,adr_af_begin[adr],adr_af_count[adr],R0+(reg&7));
+ break; //c=r0 xs
+ }
+ break;
+ case 2:
+ switch (reg=READ_OP()) {
+ case 0: case 1: case 2: case 3: case 4:
+ saturn_exchange(A, adr_af_begin[adr], adr_af_count[adr], R0+reg);
+ break; // ar0ex xs
+ case 8: case 9: case 0xa: case 0xb: case 0xc:
+ saturn_exchange(C, adr_af_begin[adr], adr_af_count[adr], R0+(reg&7));
+ break; // cr0ex xs
+ }
+ break;
+ }
+ break;
+ }
+}
+
+static void saturn_instruction_81(void)
+{
+ int reg, adr;
+
+ switch(reg=READ_OP()) {
+ case 0: case 1: case 2: case 3:
+ saturn_rotate_nibble_left_w(A+reg); break; // aslc w
+ case 4: case 5: case 6: case 7:
+ saturn_rotate_nibble_right_w(A+(reg&3)); break; // asrc w
+ case 8:
+ switch(adr=READ_OP()) {
+ case 0:
+ switch (reg=READ_OP()) {
+ case 0: case 1: case 2: case 3:
+ saturn_add_const(A+reg, saturn.p, 1, READ_OP()+1);
+ break;
+ case 8: case 9: case 0xa: case 0xb:
+ saturn_sub_const(A+reg, saturn.p, 1, READ_OP()+1);
+ break;
+ }
+ break;
+ case 1:
+ switch (reg=READ_OP()) {
+ case 0: case 1: case 2: case 3:
+ saturn_add_const(A+reg, 1, saturn.p+1, READ_OP()+1);
+ break;
+ case 8: case 9: case 0xa: case 0xb:
+ saturn_sub_const(A+reg, 1, saturn.p+1, READ_OP()+1);
+ break;
+ }
+ break;
+ case 2: case 3: case 4: case 5: case 6: case 7: case 0xf:
+ switch (reg=READ_OP()) {
+ case 0: case 1: case 2: case 3:
+ saturn_add_const(A+reg, adr_af_begin[adr], adr_af_count[adr], READ_OP()+1);
+ break;
+ case 8: case 9: case 0xa: case 0xb:
+ saturn_sub_const(A+reg, adr_af_begin[adr], adr_af_count[adr], READ_OP()+1);
+ break;
+ }
+ break;
+ }
+ break;
+ case 9:
+ switch(adr=READ_OP()) {
+ case 0:
+ switch(reg=READ_OP()){
+ case 0: case 1: case 2: case 3:
+ saturn_shift_right(A+reg,saturn.p,1);
+ break; // asrb p
+ }
+ break;
+ case 1:
+ switch(reg=READ_OP()){
+ case 0: case 1: case 2: case 3:
+ saturn_shift_right(A+reg, 0,saturn.p+1);
+ break; // asrb wp
+ }
+ break;
+ case 2: /*case 3:*/ case 4: case 5: case 6:/* case 7:*/case 0xf:
+ switch(reg=READ_OP()){
+ case 0: case 1: case 2: case 3:
+ saturn_shift_right(A+reg, adr_af_begin[adr], adr_af_count[adr]);
+ break; // asrb xs
+ }
+ break;
+ }
+ break;
+ case 0xa:
+ saturn_instruction_81a();
+ break;
+ case 0xb:
+ switch(READ_OP()) {
+ case 2: saturn_load_pc(A);break;
+ case 3: saturn_load_pc(C);break;
+ case 4: saturn_store_pc(A);break;
+ case 5: saturn_store_pc(C);break;
+ case 6: saturn_exchange_pc(A);break;
+ case 7: saturn_exchange_pc(C);break;
+ }
+ break;
+ case 0xc: case 0xd: case 0xe: case 0xf:
+ saturn_shift_right(A+(reg&3), BEGIN_W, COUNT_W);
+ break; // asrb w
+ }
+}
+
+static void saturn_instruction_8(void)
+{
+ int oper;
+
+ switch(READ_OP()) {
+ case 0:
+ saturn_instruction_80();
+ break;
+ case 1:
+ saturn_instruction_81();
+ break;
+ case 2: saturn_hst_clear_bits();break;
+ case 3: saturn_hst_bits_cleared();break;
+ case 4: saturn_st_clear_bit();break;
+ case 5: saturn_st_set_bit();break;
+ case 6: saturn_st_jump_bit_clear();break;
+ case 7: saturn_st_jump_bit_set();break;
+ case 8: saturn_p_not_equals(); break;
+ case 9: saturn_p_equals(); break;
+ case 0xa:
+ switch(oper=READ_OP()) {
+ case 0: case 1: case 2: case 3:
+ saturn_equals(reg_left[oper&3] , BEGIN_A, COUNT_A, reg_right[oper&3]);
+ break;
+ case 4: case 5: case 6: case 7:
+ saturn_not_equals(reg_left[oper&3] , BEGIN_A, COUNT_A, reg_right[oper&3]);
+ break;
+ case 8: case 9: case 0xa: case 0xb:
+ saturn_equals_zero(A+(oper&3), BEGIN_A, COUNT_A);
+ break;
+ case 0xc: case 0xd: case 0xe: case 0xf:
+ saturn_not_equals_zero(A+(oper&3), BEGIN_A, COUNT_A);
+ break;
+ }
+ break;
+ case 0xb:
+ switch(oper=READ_OP()) {
+ case 0: case 1: case 2: case 3:
+ saturn_greater(reg_left[oper&3] , BEGIN_A, COUNT_A, reg_right[oper&3]);
+ break;
+ case 4: case 5: case 6: case 7:
+ saturn_smaller(reg_left[oper&3] , BEGIN_A, COUNT_A, reg_right[oper&3]);
+ break;
+ case 8: case 9: case 0xa: case 0xb:
+ saturn_greater_equals(reg_left[oper&3], BEGIN_A, COUNT_A, reg_right[oper&3]);
+ break;
+ case 0xc: case 0xd: case 0xe: case 0xf:
+ saturn_smaller_equals(reg_left[oper&3], BEGIN_A, COUNT_A, reg_right[oper&3]);
+ break;
+ }
+ break;
+ case 0xc: saturn_jump((READ_OP_DIS16()+saturn.pc-4)&0xfffff,1);break;
+ case 0xd: saturn_jump(READ_OP_ARG20(),1);break;
+ case 0xe: saturn_call((READ_OP_DIS16()+saturn.pc)&0xfffff);break;
+ case 0xf: saturn_call(READ_OP_ARG20());break;
+ }
+}
+
+static void saturn_instruction_9(void)
+{
+ int adr, oper;
+
+ switch(adr=READ_OP()) {
+ case 0:
+ switch(oper=READ_OP()) {
+ case 0: case 1: case 2: case 3:
+ saturn_equals(reg_left[oper&3] , saturn.p, 1, reg_right[oper&3]);
+ break;
+ case 4: case 5: case 6: case 7:
+ saturn_not_equals(reg_left[oper&3] ,saturn.p, 1, reg_right[oper&3]);
+ break;
+ case 8: case 9: case 0xa: case 0xb:
+ saturn_equals_zero(A+(oper&3), saturn.p, 1);
+ break;
+ case 0xc: case 0xd: case 0xe: case 0xf:
+ saturn_not_equals_zero(A+(oper&3), saturn.p, 1);
+ break;
+ }
+ break;
+ case 1:
+ switch(oper=READ_OP()) {
+ case 0: case 1: case 2: case 3:
+ saturn_equals(reg_left[oper&3] , 0, saturn.p+1, reg_right[oper&3]);
+ break;
+ case 4: case 5: case 6: case 7:
+ saturn_not_equals(reg_left[oper&3] , 0, saturn.p+1, reg_right[oper&3]);
+ break;
+ case 8: case 9: case 0xa: case 0xb:
+ saturn_equals_zero(A+(oper&3), 0, saturn.p+1);
+ break;
+ case 0xc: case 0xd: case 0xe: case 0xf:
+ saturn_not_equals_zero(A+(oper&3), 0, saturn.p+1);
+ break;
+ }
+ break;
+ case 2: case 3: case 4: case 5:
+ case 6: case 7:
+ switch(oper=READ_OP()) {
+ case 0: case 1: case 2: case 3:
+ saturn_equals(reg_left[oper&3] ,adr_a_begin[adr], adr_a_count[adr], reg_right[oper&3]);
+ break;
+ case 4: case 5: case 6: case 7:
+ saturn_not_equals(reg_left[oper&3] ,adr_a_begin[adr], adr_a_count[adr], reg_right[oper&3]);
+ break;
+ case 8: case 9: case 0xa: case 0xb:
+ saturn_equals_zero(A+(oper&3),adr_a_begin[adr], adr_a_count[adr]);
+ break;
+ case 0xc: case 0xd: case 0xe: case 0xf:
+ saturn_not_equals_zero(A+(oper&3) ,adr_a_begin[adr], adr_a_count[adr]);
+ break;
+ }
+ break;
+ case 8:
+ switch(oper=READ_OP()) {
+ case 0: case 1: case 2: case 3:
+ saturn_greater(reg_left[oper&3] ,saturn.p, 1, reg_right[oper&3]);
+ break;
+ case 4: case 5: case 6: case 7:
+ saturn_smaller(reg_left[oper&3] ,saturn.p, 1, reg_right[oper&3]);
+ break;
+ case 8: case 9: case 0xa: case 0xb:
+ saturn_greater_equals(reg_left[oper&3] ,saturn.p, 1, reg_right[oper&3]);
+ break;
+ case 0xc: case 0xd: case 0xe: case 0xf:
+ saturn_smaller_equals(reg_left[oper&3] ,saturn.p, 1, reg_right[oper&3]);
+ break;
+ }
+ break;
+ case 9:
+ switch(oper=READ_OP()) {
+ case 0: case 1: case 2: case 3:
+ saturn_greater(reg_left[oper&3] , 0, saturn.p+1, reg_right[oper&3]);
+ break;
+ case 4: case 5: case 6: case 7:
+ saturn_smaller(reg_left[oper&3] , 0, saturn.p+1, reg_right[oper&3]);
+ break;
+ case 8: case 9: case 0xa: case 0xb:
+ saturn_greater_equals(reg_left[oper&3], 0, saturn.p+1, reg_right[oper&3]);
+ break;
+ case 0xc: case 0xd: case 0xe: case 0xf:
+ saturn_smaller_equals(reg_left[oper&3], 0, saturn.p+1, reg_right[oper&3]);
+ break;
+ }
+ break;
+ case 0xa: case 0xb: case 0xc: case 0xd: case 0xe: case 0xf:
+ switch(oper=READ_OP()) {
+ case 0: case 1: case 2: case 3:
+ saturn_greater(reg_left[oper&3] ,adr_b_begin[adr], adr_b_count[adr], reg_right[oper&3]);
+ break;
+ case 4: case 5: case 6: case 7:
+ saturn_smaller(reg_left[oper&3] ,adr_b_begin[adr], adr_b_count[adr], reg_right[oper&3]);
+ break;
+ case 8: case 9: case 0xa: case 0xb:
+ saturn_greater_equals(reg_left[oper&3] ,adr_b_begin[adr], adr_b_count[adr], reg_right[oper&3]);
+ break;
+ case 0xc: case 0xd: case 0xe: case 0xf:
+ saturn_smaller_equals(reg_left[oper&3] ,adr_b_begin[adr], adr_b_count[adr], reg_right[oper&3]);
+ break;
+ }
+ break;
+ }
+}
+
+static void saturn_instruction_a(void)
+{
+ int reg, adr;
+
+ switch(adr=READ_OP()) {
+ case 0:
+ switch (reg=READ_OP()) {
+ case 0: case 1: case 2: case 3:
+ case 8: case 9: case 0xa: case 0xb:
+ saturn_add(add_left[reg], saturn.p, 1, add_right[reg]);
+ break;
+ break;
+ case 4: case 5: case 6: case 7:
+ saturn_shift_left(A+(reg&3), saturn.p, 1);
+ break;
+ case 0xc: case 0xd: case 0xe: case 0xf:
+ saturn_decrement(A+(reg&3), saturn.p, 1);
+ break;
+ }
+ break;
+ case 1:
+ switch (reg=READ_OP()) {
+ case 0: case 1: case 2: case 3:
+ case 8: case 9: case 0xa: case 0xb:
+ saturn_add(add_left[reg], 1, saturn.p+1, add_right[reg]);
+ break;
+ case 4: case 5: case 6: case 7:
+ saturn_shift_left(A+(reg&3), 1, saturn.p+1);
+ break;
+ case 0xc: case 0xd: case 0xe: case 0xf:
+ saturn_decrement(A+(reg&3), 1, saturn.p+1);
+ break;
+ }
+ break;
+ case 2: case 3: case 4: case 5: case 6: case 7:
+ switch (reg=READ_OP()) {
+ case 0: case 1: case 2: case 3:
+ case 8: case 9: case 0xa: case 0xb:
+ saturn_add(add_left[reg], adr_a_begin[adr], adr_a_count[adr], add_right[reg]);
+ break;
+ case 4: case 5: case 6: case 7:
+ saturn_shift_left(A+(reg&3), adr_a_begin[adr], adr_a_count[adr]);
+ break;
+ case 0xc: case 0xd: case 0xe: case 0xf:
+ saturn_decrement(A+(reg&3), adr_a_begin[adr], adr_a_count[adr]);
+ break;
+ }
+ break;
+ case 8:
+ switch(reg=READ_OP()) {
+ case 0: case 1: case 2: case 3:
+ saturn_clear(A+reg, saturn.p,1);
+ break; // a=0 p
+ case 4: case 5: case 6: case 7:
+ case 8: case 9: case 0xa: case 0xb:
+ saturn_copy(reg_right[reg&7], saturn.p,1,reg_left[reg&7]); //!correct
+ break; // a=b p
+ case 0xc: case 0xd: case 0xe: case 0xf:
+ saturn_exchange(reg_left[reg&3], saturn.p,1,reg_right[reg&3]);
+ break; // abex p
+ }
+ break;
+ case 9:
+ switch(reg=READ_OP()) {
+ case 0: case 1: case 2: case 3:
+ saturn_clear(A+reg,0,saturn.p+1);
+ break; // a=0 wp
+ case 4: case 5: case 6: case 7:
+ case 8: case 9: case 0xa: case 0xb:
+ saturn_copy(reg_right[reg&7], 0, saturn.p+1, reg_left[reg&7]); //!correct
+ break; // a=b wp
+ case 0xc: case 0xd: case 0xe: case 0xf:
+ saturn_exchange(reg_left[reg&3], 0, saturn.p+1, reg_right[reg&3]);
+ break; // abex wp
+ }
+ break;
+ case 0xa: case 0xb: case 0xc: case 0xd: case 0xe: case 0xf:
+ switch(reg=READ_OP()) {
+ case 0: case 1: case 2: case 3:
+ saturn_clear(A+reg, adr_b_begin[adr], adr_b_count[adr]);
+ break; // a=0 xs
+ case 4: case 5: case 6: case 7:
+ case 8: case 9: case 0xa: case 0xb:
+ saturn_copy(reg_right[reg&7], adr_b_begin[adr], adr_b_count[adr],
+ reg_left[reg&7]); //correct
+ break; // a=b xs
+ case 0xc: case 0xd: case 0xe: case 0xf:
+ saturn_exchange(reg_left[reg&3], adr_b_begin[adr], adr_b_count[adr],
+ reg_right[reg&3]);
+ break; // abex xs
+ }
+ break;
+ }
+}
+
+static void saturn_instruction_b(void)
+{
+ int adr, reg;
+
+ switch(adr=READ_OP()) {
+ case 0:
+ switch(reg=READ_OP()) {
+ case 0: case 1: case 2: case 3:
+ case 8: case 9: case 0xa: case 0xb:
+ saturn_sub(sub_left[reg], saturn.p, 1, S64_READ_P(sub_right[reg]));
+ break;
+ case 4: case 5: case 6: case 7:
+ saturn_increment(A+(reg&3), saturn.p, 1); break; // a=a+1 p
+ case 0xc: case 0xd: case 0xe: case 0xf:
+ saturn_sub2(sub_left[reg], saturn.p, 1, S64_READ_P(sub_right[reg]));
+ break;
+ }
+ break;
+ case 1:
+ switch(reg=READ_OP()) {
+ case 0: case 1: case 2: case 3:
+ case 8: case 9: case 0xa: case 0xb:
+ saturn_sub(sub_left[reg], 1, saturn.p+1, sub_right[reg]);
+ break;
+ case 4: case 5: case 6: case 7:
+ saturn_increment(A+(reg&3), 1, saturn.p+1); break; // a=a+1 wp
+ case 0xc: case 0xd: case 0xe: case 0xf:
+ saturn_sub2(sub_left[reg], 1, saturn.p+1, sub_right[reg]);
+ break;
+ }
+ break;
+ case 2: case 3: case 4: case 5: case 6: case 7:
+ switch(reg=READ_OP()) {
+ case 0: case 1: case 2: case 3:
+ case 8: case 9: case 0xa: case 0xb:
+ saturn_sub(sub_left[reg], adr_a_begin[adr], adr_a_count[adr],
+ sub_right[reg]);
+ break;
+ case 4: case 5: case 6: case 7:
+ saturn_increment(A+(reg&3), adr_a_begin[adr], adr_a_count[adr]);
+ break; // a=a+1 xs
+ case 0xc: case 0xd: case 0xe: case 0xf:
+ saturn_sub2(sub_left[reg], adr_a_begin[adr], adr_a_count[adr],
+ sub_right[reg]);
+ break;
+ }
+ break;
+ case 8:
+ switch(reg=READ_OP()) {
+ case 0: case 1: case 2: case 3:
+ saturn_shift_nibble_left(A+reg, saturn.p, 1); break; // asl p
+ case 4: case 5: case 6: case 7:
+ saturn_shift_nibble_right(A+(reg&3), saturn.p, 1); break; // asr p
+ case 8: case 9: case 0xa: case 0xb:
+ saturn_invert(A+(reg&3), saturn.p, 1); break; // A=-A p
+ case 0xc: case 0xd: case 0xe: case 0xf:
+ saturn_negate(A+(reg&3), saturn.p, 1); break; // A=-A-1 p
+ }
+ break;
+ case 9:
+ switch(reg=READ_OP()) {
+ case 0: case 1: case 2: case 3:
+ saturn_shift_nibble_left(A+reg,0,saturn.p+1); break; // asl wp
+ case 4: case 5: case 6: case 7:
+ saturn_shift_nibble_right(A+(reg&3),0,saturn.p+1); break; // asr wp
+ case 8: case 9: case 0xa: case 0xb:
+ saturn_invert(A+(reg&3),0,saturn.p+1); break; // A=-A wp
+ case 0xc: case 0xd: case 0xe: case 0xf:
+ saturn_negate(A+(reg&3),0,saturn.p+1); break; // A=-A-1 wp
+ }
+ break;
+ case 0xa: case 0xb: case 0xc: case 0xd: case 0xe: case 0xf:
+ switch(reg=READ_OP()) {
+ case 0: case 1: case 2: case 3:
+ saturn_shift_nibble_left(A+reg,adr_b_begin[adr], adr_b_count[adr]);
+ break;
+ case 4: case 5: case 6: case 7:
+ saturn_shift_nibble_right(A+(reg&3), adr_b_begin[adr], adr_b_count[adr]);
+ break;
+ case 8: case 9: case 0xa: case 0xb:
+ saturn_invert(A+(reg&3), adr_b_begin[adr], adr_b_count[adr]);
+ break;
+ case 0xc: case 0xd: case 0xe: case 0xf:
+ saturn_negate(A+(reg&3), adr_b_begin[adr], adr_b_count[adr]);
+ break;
+ }
+ break;
+ }
+}
+
+
+static void saturn_instruction(void)
+{
+ int reg, adr;
+
+ switch(READ_OP()) {
+ case 0:
+ switch(READ_OP()) {
+ case 0: saturn_return_xm_set();break;
+ case 1: saturn_return(1);break;
+ case 2: saturn_return_carry_set();break;
+ case 3: saturn_return_carry_clear();break;
+ case 4: saturn_sethex();break;
+ case 5: saturn_setdec();break;
+ case 6: saturn_push_c();break;
+ case 7: saturn_pop_c();break;
+ case 8: saturn_clear_st();break;
+ case 9: saturn_st_to_c();break;
+ case 0xa: saturn_c_to_st();break;
+ case 0xb: saturn_exchange_c_st();break;
+ case 0xc:
+ saturn_inc_p();
+ break;
+ case 0xd:
+ saturn_dec_p();
+ break;
+ case 0xf: saturn_return_interrupt();break;
+ case 0xe:
+ saturn_instruction_0e();
+ break;
+ }
+ break;
+ case 1:
+ saturn_instruction_1();
+ break;
+ case 2:
+ saturn_load_p();
+ break;
+ case 3: saturn_load_reg(C);break; // lc
+ case 4:
+ adr=READ_OP_DIS8();
+ if (adr==0) {
+ saturn_return(saturn.carry);
+ } else {
+ saturn_jump((saturn.pc+adr-2)&0xfffff, saturn.carry);
+ }
+ break;
+ case 5:
+ adr=READ_OP_DIS8();
+ if (adr==0) {
+ saturn_return(!saturn.carry);
+ } else {
+ saturn_jump((saturn.pc+adr-2)&0xfffff,!saturn.carry);
+ }
+ break;
+ case 6:
+ adr=READ_OP_DIS12();
+ saturn_jump((saturn.pc+adr-3)&0xfffff,1); break;
+ case 7:
+ adr=READ_OP_DIS12();
+ saturn_call((adr+saturn.pc)&0xfffff); break;
+ case 8:
+ saturn_instruction_8();
+ break;
+ case 9:
+ saturn_instruction_9();
+ break;
+ case 0xa:
+ saturn_instruction_a();
+ break;
+ case 0xb:
+ saturn_instruction_b();
+ break;
+ case 0xc:
+ switch (reg=READ_OP()) {
+ case 0: case 1: case 2: case 3:
+ case 8: case 9: case 0xa: case 0xb:
+ saturn_add(add_left[reg], BEGIN_A, COUNT_A, add_right[reg]);
+ break;
+ case 4: case 5: case 6: case 7:
+ saturn_shift_left(A+(reg&3), BEGIN_A, COUNT_A);
+ break;
+ case 0xc: case 0xd: case 0xe: case 0xf:
+ saturn_decrement(A+(reg&3), BEGIN_A, COUNT_A);
+ break;
+ }
+ break;
+ case 0xd:
+ switch(reg=READ_OP()) {
+ case 0: case 1: case 2: case 3:
+ saturn_clear(A+reg, BEGIN_A, COUNT_A);
+ break; // a=0 a
+ case 4: case 5: case 6: case 7:
+ case 8: case 9: case 0xa: case 0xb:
+ saturn_copy(reg_right[reg&7], BEGIN_A, COUNT_A, reg_left[reg&7]); //correct
+ break; // a=b a
+ case 0xc: case 0xd: case 0xe: case 0xf:
+ saturn_exchange(reg_left[reg&3], BEGIN_A, COUNT_A, reg_right[reg&3]);
+ break; // abex a
+ }
+ break;
+ case 0xe:
+ switch(reg=READ_OP()) {
+ case 0: case 1: case 2: case 3:
+ case 8: case 9: case 0xa: case 0xb:
+ saturn_sub(sub_left[reg], BEGIN_A, COUNT_A, S64_READ_A(sub_right[reg]));
+ break;
+ case 4: case 5: case 6: case 7:
+ saturn_increment(A+(reg&3), BEGIN_A, COUNT_A);
+ break; // a=a+1 a
+ case 0xc: case 0xd: case 0xe: case 0xf:
+ saturn_sub2(sub_left[reg], BEGIN_A, COUNT_A, S64_READ_A(sub_right[reg]));
+ break;
+ }
+ break;
+ case 0xf:
+ switch(reg=READ_OP()) {
+ case 0: case 1: case 2: case 3:
+ saturn_shift_nibble_left(A+reg,BEGIN_A, COUNT_A);
+ break; // asl a
+ case 4: case 5: case 6: case 7:
+ saturn_shift_nibble_right(A+(reg&3),BEGIN_A, COUNT_A);
+ break; // asr a
+ case 8: case 9: case 0xa: case 0xb:
+ saturn_invert(A+(reg&3),BEGIN_A, COUNT_A);
+ break; // A=-A a
+ case 0xc: case 0xd: case 0xe: case 0xf:
+ saturn_negate(A+(reg&3),BEGIN_A, COUNT_A);
+ break; // A=-A-1 a
+ }
+ break;
+ }
+}
diff --git a/src/emu/cpu/saturn/saturn.c b/src/emu/cpu/saturn/saturn.c
new file mode 100644
index 00000000000..e18ec06dc9b
--- /dev/null
+++ b/src/emu/cpu/saturn/saturn.c
@@ -0,0 +1,422 @@
+/*****************************************************************************
+ *
+ * saturn.c
+ * portable saturn emulator interface
+ * (hp calculators)
+ *
+ * Copyright (c) 2000 Peter Trauner, all rights reserved.
+ *
+ * - This source code is released as freeware for non-commercial purposes.
+ * - You are free to use and redistribute this code in modified or
+ * unmodified form, provided you list me in the credits.
+ * - If you modify this source code, you must add a notice to each modified
+ * source file that it has been changed. If you're a nice person, you
+ * will clearly mark each change too. :)
+ * - If you wish to use this for commercial purposes, please contact me at
+ * peter.trauner@jk.uni-linz.ac.at
+ * - The author of this copywritten work reserves the right to change the
+ * terms of its usage and license at any time, including retroactively
+ * - This entire notice must remain in the source code.
+ *
+ *****************************************************************************/
+#include "cpuintrf.h"
+#include "debugger.h"
+
+#include "saturn.h"
+#include "sat.h"
+
+#define R0 0
+#define R1 1
+#define R2 2
+#define R3 3
+#define R4 4
+#define A 5
+#define B 6
+#define C 7
+#define D 8
+
+typedef int SaturnAdr; // 20 bit
+typedef UINT8 SaturnNib; // 4 bit
+typedef short SaturnX; // 12 bit
+typedef INT64 SaturnM; // 48 bit
+
+typedef union {
+ UINT8 b[8];
+ UINT16 w[4];
+ UINT32 d[2];
+ UINT64 q;
+} Saturn64;
+
+#define VERBOSE 0
+
+#if VERBOSE
+#define LOG(x) logerror x
+#else
+#define LOG(x)
+#endif
+
+
+/****************************************************************************
+ * The 6502 registers.
+ ****************************************************************************/
+typedef struct
+{
+ SATURN_CONFIG *config;
+ Saturn64 reg[9]; //r0,r1,r2,r3,r4,a,b,c,d;
+
+ SaturnAdr d[2], pc, oldpc, rstk[8]; // 20 bit addresses
+
+ int stackpointer; // this is only for debugger stepover support!
+
+ SaturnNib p; // 4 bit pointer
+
+ UINT16 in;
+ int out; // 12
+ int carry, decimal;
+ UINT16 st; // status 16 bit
+#define XM 1
+#define SR 2
+#define SB 4
+#define MP 8
+ int hst; // hardware status 4 bit
+ /* XM external Modules missing
+ SR Service Request
+ SB Sticky bit
+ MP Module Pulled */
+
+ int irq_state;
+
+ UINT8 pending_irq; /* nonzero if an IRQ is pending */
+ UINT8 after_cli; /* pending IRQ and last insn cleared I */
+ UINT8 nmi_state;
+ int (*irq_callback)(int irqline); /* IRQ callback */
+} Saturn_Regs;
+
+static int saturn_ICount = 0;
+
+static Saturn_Regs saturn;
+
+/***************************************************************
+ * include the opcode macros, functions and tables
+ ***************************************************************/
+#include "satops.c"
+#include "sattable.c"
+
+/*****************************************************************************
+ *
+ * Saturn CPU interface functions
+ *
+ *****************************************************************************/
+
+static void saturn_init(int index, int clock, const void *config, int (*irqcallback)(int))
+{
+ saturn.config = (SATURN_CONFIG *) config;
+}
+
+static void saturn_reset(void)
+{
+ saturn.stackpointer=0;
+ saturn.pc=0;
+ change_pc(saturn.pc);
+}
+
+static void saturn_get_context (void *dst)
+{
+ if( dst )
+ *(Saturn_Regs*)dst = saturn;
+}
+
+static void saturn_set_context (void *src)
+{
+ if( src )
+ {
+ saturn = *(Saturn_Regs*)src;
+ change_pc(saturn.pc);
+ }
+}
+
+
+
+INLINE void saturn_take_irq(void)
+{
+ {
+ saturn_ICount -= 7;
+
+ saturn_push(saturn.pc);
+ saturn.pc=IRQ_ADDRESS;
+
+ LOG(("Saturn#%d takes IRQ ($%04x)\n", cpu_getactivecpu(), saturn.pc));
+ /* call back the cpuintrf to let it clear the line */
+ if (saturn.irq_callback) (*saturn.irq_callback)(0);
+ change_pc(saturn.pc);
+ }
+ saturn.pending_irq = 0;
+}
+
+int saturn_execute(int cycles)
+{
+ saturn_ICount = cycles;
+
+ change_pc(saturn.pc);
+
+ do
+ {
+ saturn.oldpc = saturn.pc;
+
+ CALL_MAME_DEBUG;
+
+ /* if an irq is pending, take it now */
+ if( saturn.pending_irq )
+ saturn_take_irq();
+
+ saturn_instruction();
+
+ /* check if the I flag was just reset (interrupts enabled) */
+ if( saturn.after_cli )
+ {
+ LOG(("M6502#%d after_cli was >0", cpu_getactivecpu()));
+ saturn.after_cli = 0;
+ if (saturn.irq_state != CLEAR_LINE)
+ {
+ LOG((": irq line is asserted: set pending IRQ\n"));
+ saturn.pending_irq = 1;
+ }
+ else
+ {
+ LOG((": irq line is clear\n"));
+ }
+ }
+ else
+ if( saturn.pending_irq )
+ saturn_take_irq();
+
+ } while (saturn_ICount > 0);
+
+ return cycles - saturn_ICount;
+}
+
+void saturn_set_nmi_line(int state)
+{
+ if (saturn.nmi_state == state) return;
+ saturn.nmi_state = state;
+ if( state != CLEAR_LINE )
+ {
+ LOG(( "M6502#%d set_nmi_line(ASSERT)\n", cpu_getactivecpu()));
+ saturn_ICount -= 7;
+ saturn_push(saturn.pc);
+ saturn.pc=IRQ_ADDRESS;
+
+ LOG(("M6502#%d takes NMI ($%04x)\n", cpu_getactivecpu(), PC));
+ change_pc(saturn.pc);
+ }
+}
+
+void saturn_set_irq_line(int irqline, int state)
+{
+ saturn.irq_state = state;
+ if( state != CLEAR_LINE )
+ {
+ LOG(( "M6502#%d set_irq_line(ASSERT)\n", cpu_getactivecpu()));
+ saturn.pending_irq = 1;
+ }
+}
+
+void saturn_set_irq_callback(int (*callback)(int))
+{
+ saturn.irq_callback = callback;
+}
+
+#if 0
+static void saturn_state_save(void *file)
+{
+ int cpu = cpu_getactivecpu();
+ state_save_UINT16(file,"m6502",cpu,"PC",&m6502.pc.w.l,2);
+ state_save_UINT16(file,"m6502",cpu,"SP",&m6502.sp.w.l,2);
+ state_save_UINT8(file,"m6502",cpu,"P",&m6502.p,1);
+ state_save_UINT8(file,"m6502",cpu,"A",&m6502.a,1);
+ state_save_UINT8(file,"m6502",cpu,"X",&m6502.x,1);
+ state_save_UINT8(file,"m6502",cpu,"Y",&m6502.y,1);
+ state_save_UINT8(file,"m6502",cpu,"PENDING",&m6502.pending_irq,1);
+ state_save_UINT8(file,"m6502",cpu,"AFTER_CLI",&m6502.after_cli,1);
+ state_save_UINT8(file,"m6502",cpu,"NMI_STATE",&m6502.nmi_state,1);
+ state_save_UINT8(file,"m6502",cpu,"IRQ_STATE",&m6502.irq_state,1);
+ state_save_UINT8(file,"m6502",cpu,"SO_STATE",&m6502.so_state,1);
+}
+
+static void saturn_state_load(void *file)
+{
+ int cpu = cpu_getactivecpu();
+ state_load_UINT16(file,"m6502",cpu,"PC",&m6502.pc.w.l,2);
+ state_load_UINT16(file,"m6502",cpu,"SP",&m6502.sp.w.l,2);
+ state_load_UINT8(file,"m6502",cpu,"P",&m6502.p,1);
+ state_load_UINT8(file,"m6502",cpu,"A",&m6502.a,1);
+ state_load_UINT8(file,"m6502",cpu,"X",&m6502.x,1);
+ state_load_UINT8(file,"m6502",cpu,"Y",&m6502.y,1);
+ state_load_UINT8(file,"m6502",cpu,"PENDING",&m6502.pending_irq,1);
+ state_load_UINT8(file,"m6502",cpu,"AFTER_CLI",&m6502.after_cli,1);
+ state_load_UINT8(file,"m6502",cpu,"NMI_STATE",&m6502.nmi_state,1);
+ state_load_UINT8(file,"m6502",cpu,"IRQ_STATE",&m6502.irq_state,1);
+ state_load_UINT8(file,"m6502",cpu,"SO_STATE",&m6502.so_state,1);
+}
+#endif
+
+/**************************************************************************
+ * Generic set_info
+ **************************************************************************/
+
+static void saturn_set_info(UINT32 state, cpuinfo *info)
+{
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_STATE + SATURN_NMI_STATE: saturn.nmi_state = info->i; break;
+ case CPUINFO_INT_INPUT_STATE + SATURN_IRQ_STATE: saturn.irq_state = info->i; break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + SATURN_PC: saturn.pc = info->i; change_pc(saturn.pc); break;
+ case CPUINFO_INT_SP: saturn.stackpointer = info->i; break;
+ case CPUINFO_INT_REGISTER + SATURN_D0: saturn.d[0] = info->i; break;
+ case CPUINFO_INT_REGISTER + SATURN_D1: saturn.d[1] = info->i; break;
+#if 0
+ case CPUINFO_INT_REGISTER + SATURN_A: saturn.reg[A] = info->i; break;
+ case CPUINFO_INT_REGISTER + SATURN_B: saturn.reg[B] = info->i; break;
+ case CPUINFO_INT_REGISTER + SATURN_C: saturn.reg[C] = info->i; break;
+ case CPUINFO_INT_REGISTER + SATURN_D: saturn.reg[D] = info->i; break;
+ case CPUINFO_INT_REGISTER + SATURN_R0: saturn.reg[R0] = info->i; break;
+ case CPUINFO_INT_REGISTER + SATURN_R1: saturn.reg[R1] = info->i; break;
+ case CPUINFO_INT_REGISTER + SATURN_R2: saturn.reg[R2] = info->i; break;
+ case CPUINFO_INT_REGISTER + SATURN_R3: saturn.reg[R3] = info->i; break;
+ case CPUINFO_INT_REGISTER + SATURN_R4: saturn.reg[R4] = info->i; break;
+#endif
+ case CPUINFO_INT_REGISTER + SATURN_P: saturn.p = info->i; break;
+ case CPUINFO_INT_REGISTER + SATURN_IN: saturn.in = info->i; break;
+ case CPUINFO_INT_REGISTER + SATURN_OUT: saturn.out = info->i; break;
+ case CPUINFO_INT_REGISTER + SATURN_CARRY: saturn.carry = info->i; break;
+ case CPUINFO_INT_REGISTER + SATURN_ST: saturn.st = info->i; break;
+ case CPUINFO_INT_REGISTER + SATURN_HST: saturn.hst = info->i; break;
+ case CPUINFO_INT_REGISTER + SATURN_RSTK0: saturn.rstk[0] = info->i; break;
+ case CPUINFO_INT_REGISTER + SATURN_RSTK1: saturn.rstk[1] = info->i; break;
+ case CPUINFO_INT_REGISTER + SATURN_RSTK2: saturn.rstk[2] = info->i; break;
+ case CPUINFO_INT_REGISTER + SATURN_RSTK3: saturn.rstk[3] = info->i; break;
+ case CPUINFO_INT_REGISTER + SATURN_RSTK4: saturn.rstk[4] = info->i; break;
+ case CPUINFO_INT_REGISTER + SATURN_RSTK5: saturn.rstk[5] = info->i; break;
+ case CPUINFO_INT_REGISTER + SATURN_RSTK6: saturn.rstk[6] = info->i; break;
+ case CPUINFO_INT_REGISTER + SATURN_RSTK7: saturn.rstk[7] = info->i; break;
+ }
+}
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+void saturn_get_info(UINT32 state, cpuinfo *info)
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(saturn); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 1; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break;
+ case CPUINFO_INT_ENDIANNESS: info->i = CPU_IS_LE; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 1; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 20; /* 20 nibbles max */ break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 2; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 21; break;
+
+ case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 8; break;
+ case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 20; break;
+ case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_PROGRAM: info->i = 0; break;
+ case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 0; break;
+ case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 0; break;
+ case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_DATA: info->i = 0; break;
+ case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO: info->i = 0; break;
+ case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_IO: info->i = 0; break;
+ case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_IO: info->i = 0; break;
+
+ case CPUINFO_INT_INPUT_STATE + SATURN_NMI_STATE: info->i = saturn.nmi_state; break;
+ case CPUINFO_INT_INPUT_STATE + SATURN_IRQ_STATE: info->i = saturn.irq_state; break;
+
+ case CPUINFO_INT_PREVIOUSPC: info->i = saturn.oldpc; break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + SATURN_PC: info->i = saturn.pc; break;
+ case CPUINFO_INT_SP: info->i = saturn.stackpointer; break;
+ case CPUINFO_INT_REGISTER + SATURN_D0: info->i = saturn.d[0]; break;
+ case CPUINFO_INT_REGISTER + SATURN_D1: info->i = saturn.d[1]; break;
+#if 0
+ case CPUINFO_INT_REGISTER + SATURN_A: info->i = saturn.reg[A]; break;
+ case CPUINFO_INT_REGISTER + SATURN_B: info->i = saturn.reg[B]; break;
+ case CPUINFO_INT_REGISTER + SATURN_C: info->i = saturn.reg[C]; break;
+ case CPUINFO_INT_REGISTER + SATURN_D: info->i = saturn.reg[D]; break;
+ case CPUINFO_INT_REGISTER + SATURN_R0: info->i = saturn.reg[R0]; break;
+ case CPUINFO_INT_REGISTER + SATURN_R1: info->i = saturn.reg[R1]; break;
+ case CPUINFO_INT_REGISTER + SATURN_R2: info->i = saturn.reg[R2]; break;
+ case CPUINFO_INT_REGISTER + SATURN_R3: info->i = saturn.reg[R3]; break;
+ case CPUINFO_INT_REGISTER + SATURN_R4: info->i = saturn.reg[R4]; break;
+#endif
+ case CPUINFO_INT_REGISTER + SATURN_P: info->i = saturn.p; break;
+ case CPUINFO_INT_REGISTER + SATURN_IN: info->i = saturn.in; break;
+ case CPUINFO_INT_REGISTER + SATURN_OUT: info->i = saturn.out; break;
+ case CPUINFO_INT_REGISTER + SATURN_CARRY: info->i = saturn.carry; break;
+ case CPUINFO_INT_REGISTER + SATURN_ST: info->i = saturn.st; break;
+ case CPUINFO_INT_REGISTER + SATURN_HST: info->i = saturn.hst; break;
+ case CPUINFO_INT_REGISTER + SATURN_RSTK0: info->i = saturn.rstk[0]; break;
+ case CPUINFO_INT_REGISTER + SATURN_RSTK1: info->i = saturn.rstk[1]; break;
+ case CPUINFO_INT_REGISTER + SATURN_RSTK2: info->i = saturn.rstk[2]; break;
+ case CPUINFO_INT_REGISTER + SATURN_RSTK3: info->i = saturn.rstk[3]; break;
+ case CPUINFO_INT_REGISTER + SATURN_RSTK4: info->i = saturn.rstk[4]; break;
+ case CPUINFO_INT_REGISTER + SATURN_RSTK5: info->i = saturn.rstk[5]; break;
+ case CPUINFO_INT_REGISTER + SATURN_RSTK6: info->i = saturn.rstk[6]; break;
+ case CPUINFO_INT_REGISTER + SATURN_RSTK7: info->i = saturn.rstk[7]; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_PTR_SET_INFO: info->setinfo = saturn_set_info; break;
+ case CPUINFO_PTR_GET_CONTEXT: info->getcontext = saturn_get_context; break;
+ case CPUINFO_PTR_SET_CONTEXT: info->setcontext = saturn_set_context; break;
+ case CPUINFO_PTR_INIT: info->init = saturn_init; break;
+ case CPUINFO_PTR_RESET: info->reset = saturn_reset; break;
+ case CPUINFO_PTR_EXECUTE: info->execute = saturn_execute; break;
+ case CPUINFO_PTR_BURN: info->burn = NULL; break;
+#ifdef MAME_DEBUG
+ case CPUINFO_PTR_DISASSEMBLE: info->disassemble = saturn_dasm; break;
+#endif /* MAME_DEBUG */
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &saturn_ICount; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case CPUINFO_STR_NAME: strcpy(info->s = cpuintrf_temp_str(), "Saturn"); break;
+ case CPUINFO_STR_CORE_FAMILY: strcpy(info->s = cpuintrf_temp_str(), "Saturn"); break;
+ case CPUINFO_STR_CORE_VERSION: strcpy(info->s = cpuintrf_temp_str(), "1.0alpha"); break;
+ case CPUINFO_STR_CORE_FILE: strcpy(info->s = cpuintrf_temp_str(), __FILE__); break;
+ case CPUINFO_STR_CORE_CREDITS: strcpy(info->s = cpuintrf_temp_str(), "Copyright (c) 2000 Peter Trauner, all rights reserved."); break;
+
+ case CPUINFO_STR_REGISTER + SATURN_PC: sprintf(info->s = cpuintrf_temp_str(), "PC: %.5x", saturn.pc);break;
+ case CPUINFO_STR_REGISTER + SATURN_D0: sprintf(info->s = cpuintrf_temp_str(), "D0: %.5x", saturn.d[0]);break;
+ case CPUINFO_STR_REGISTER + SATURN_D1: sprintf(info->s = cpuintrf_temp_str(), "D1: %.5x", saturn.d[1]);break;
+ case CPUINFO_STR_REGISTER + SATURN_A: sprintf(info->s = cpuintrf_temp_str(), "A: %.8x %.8x", saturn.reg[A].d[1], saturn.reg[A].d[0]);break;
+ case CPUINFO_STR_REGISTER + SATURN_B: sprintf(info->s = cpuintrf_temp_str(), "B: %.8x %.8x", saturn.reg[B].d[1], saturn.reg[B].d[0]);break;
+ case CPUINFO_STR_REGISTER + SATURN_C: sprintf(info->s = cpuintrf_temp_str(), "C: %.8x %.8x", saturn.reg[C].d[1], saturn.reg[C].d[0]);break;
+ case CPUINFO_STR_REGISTER + SATURN_D: sprintf(info->s = cpuintrf_temp_str(), "D: %.8x %.8x", saturn.reg[D].d[1], saturn.reg[D].d[0]);break;
+ case CPUINFO_STR_REGISTER + SATURN_R0: sprintf(info->s = cpuintrf_temp_str(), "R0:%.8x %.8x", saturn.reg[R0].d[1], saturn.reg[R0].d[0]);break;
+ case CPUINFO_STR_REGISTER + SATURN_R1: sprintf(info->s = cpuintrf_temp_str(), "R1:%.8x %.8x", saturn.reg[R1].d[1], saturn.reg[R1].d[0]);break;
+ case CPUINFO_STR_REGISTER + SATURN_R2: sprintf(info->s = cpuintrf_temp_str(), "R2:%.8x %.8x", saturn.reg[R2].d[1], saturn.reg[R2].d[0]);break;
+ case CPUINFO_STR_REGISTER + SATURN_R3: sprintf(info->s = cpuintrf_temp_str(), "R3:%.8x %.8x", saturn.reg[R3].d[1], saturn.reg[R3].d[0]);break;
+ case CPUINFO_STR_REGISTER + SATURN_R4: sprintf(info->s = cpuintrf_temp_str(), "R4:%.8x %.8x", saturn.reg[R4].d[1], saturn.reg[R4].d[0]);break;
+ case CPUINFO_STR_REGISTER + SATURN_P: sprintf(info->s = cpuintrf_temp_str(), "P:%x", saturn.p);break;
+ case CPUINFO_STR_REGISTER + SATURN_IN: sprintf(info->s = cpuintrf_temp_str(), "IN:%.4x", saturn.in);break;
+ case CPUINFO_STR_REGISTER + SATURN_OUT: sprintf(info->s = cpuintrf_temp_str(), "OUT:%.3x", saturn.out);break;
+ case CPUINFO_STR_REGISTER + SATURN_CARRY: sprintf(info->s = cpuintrf_temp_str(), "Carry: %d", saturn.carry);break;
+ case CPUINFO_STR_REGISTER + SATURN_ST: sprintf(info->s = cpuintrf_temp_str(), "ST:%.4x", saturn.st);break;
+ case CPUINFO_STR_REGISTER + SATURN_HST: sprintf(info->s = cpuintrf_temp_str(), "HST:%x", saturn.hst);break;
+ case CPUINFO_STR_REGISTER + SATURN_RSTK0: sprintf(info->s = cpuintrf_temp_str(), "RSTK0:%.5x", saturn.rstk[0]);break;
+ case CPUINFO_STR_REGISTER + SATURN_RSTK1: sprintf(info->s = cpuintrf_temp_str(), "RSTK1:%.5x", saturn.rstk[1]);break;
+ case CPUINFO_STR_REGISTER + SATURN_RSTK2: sprintf(info->s = cpuintrf_temp_str(), "RSTK2:%.5x", saturn.rstk[2]);break;
+ case CPUINFO_STR_REGISTER + SATURN_RSTK3: sprintf(info->s = cpuintrf_temp_str(), "RSTK3:%.5x", saturn.rstk[3]);break;
+ case CPUINFO_STR_REGISTER + SATURN_RSTK4: sprintf(info->s = cpuintrf_temp_str(), "RSTK4:%.5x", saturn.rstk[4]);break;
+ case CPUINFO_STR_REGISTER + SATURN_RSTK5: sprintf(info->s = cpuintrf_temp_str(), "RSTK5:%.5x", saturn.rstk[5]);break;
+ case CPUINFO_STR_REGISTER + SATURN_RSTK6: sprintf(info->s = cpuintrf_temp_str(), "RSTK6:%.5x", saturn.rstk[6]);break;
+ case CPUINFO_STR_REGISTER + SATURN_RSTK7: sprintf(info->s = cpuintrf_temp_str(), "RSTK7:%.5x", saturn.rstk[7]);break;
+ case CPUINFO_STR_REGISTER + SATURN_IRQ_STATE: sprintf(info->s = cpuintrf_temp_str(), "IRQ:%.4x", saturn.pending_irq);break;
+ case CPUINFO_STR_FLAGS: sprintf(info->s = cpuintrf_temp_str(), "%c%c", saturn.decimal?'D':'.', saturn.carry ? 'C':'.'); break;
+ }
+}
diff --git a/src/emu/cpu/saturn/saturn.h b/src/emu/cpu/saturn/saturn.h
new file mode 100644
index 00000000000..85e66a68536
--- /dev/null
+++ b/src/emu/cpu/saturn/saturn.h
@@ -0,0 +1,68 @@
+/*****************************************************************************
+ *
+ * saturn.h
+ * portable saturn emulator interface
+ * (hp calculators)
+ *
+ * Copyright (c) 2000 Peter Trauner, all rights reserved.
+ *
+ * - This source code is released as freeware for non-commercial purposes.
+ * - You are free to use and redistribute this code in modified or
+ * unmodified form, provided you list me in the credits.
+ * - If you modify this source code, you must add a notice to each modified
+ * source file that it has been changed. If you're a nice person, you
+ * will clearly mark each change too. :)
+ * - If you wish to use this for commercial purposes, please contact me at
+ * peter.trauner@jk.uni-linz.ac.at
+ * - The author of this copywritten work reserves the right to change the
+ * terms of its usage and license at any time, including retroactively
+ * - This entire notice must remain in the source code.
+ *
+ *****************************************************************************/
+/*
+Calculator Release Date Chip Version Analog/Digital IC
+HP71B (early) 02/01/84 1LF2 -
+HP71B (later) ??/??/?? 1LK7 -
+HP18C 06/01/86 1LK7 -
+HP28C 01/05/87 1LK7 -
+HP17B 01/04/88 1LT8 Lewis
+HP19B 01/04/88 1LT8 Lewis
+HP27S 01/04/88 1LT8 Lewis
+HP28S 01/04/88 1LT8 Lewis
+HP48SX 03/16/91 1LT8 Clarke
+HP48S 04/02/91 1LT8 Clarke
+HP48GX 06/01/93 1LT8 Yorke
+HP48G 06/01/93 1LT8 Yorke
+HP38G 09/??/95 1LT8 Yorke
+*/
+/* 4 bit processor
+ 20 address lines */
+
+#ifndef _SATURN_H
+#define _SATURN_H
+
+#include "cpuintrf.h"
+
+#define SATURN_INT_NONE 0
+#define SATURN_INT_IRQ 1
+#define SATURN_INT_NMI 2
+
+typedef struct
+{
+ void (*out)(int);
+ int (*in)(void);
+ void (*reset)(void);
+ void (*config)(int v);
+ void (*unconfig)(int v);
+ int (*id)(void);
+ void (*crc)(int addr, int data);
+} SATURN_CONFIG;
+
+#ifdef MAME_DEBUG
+unsigned saturn_dasm(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram);
+#endif /* MAME_DEBUG */
+
+void saturn_get_info(UINT32 state, cpuinfo *info);
+
+#endif
+
diff --git a/src/emu/cpu/saturn/saturnds.c b/src/emu/cpu/saturn/saturnds.c
new file mode 100644
index 00000000000..cf6005ffa62
--- /dev/null
+++ b/src/emu/cpu/saturn/saturnds.c
@@ -0,0 +1,1454 @@
+/*****************************************************************************
+ *
+ * saturn.c
+ * portable saturn emulator interface
+ * (hp calculators)
+ *
+ * Copyright (c) 2000 Peter Trauner, all rights reserved.
+ *
+ * - This source code is released as freeware for non-commercial purposes.
+ * - You are free to use and redistribute this code in modified or
+ * unmodified form, provided you list me in the credits.
+ * - If you modify this source code, you must add a notice to each modified
+ * source file that it has been changed. If you're a nice person, you
+ * will clearly mark each change too. :)
+ * - If you wish to use this for commercial purposes, please contact me at
+ * peter.trauner@jk.uni-linz.ac.at
+ * - The author of this copywritten work reserves the right to change the
+ * terms of its usage and license at any time, including retroactively
+ * - This entire notice must remain in the source code.
+ *
+ *****************************************************************************/
+
+#include "cpuintrf.h"
+#include "debugger.h"
+
+#include "saturn.h"
+#include "sat.h"
+
+#if defined SATURN_HP_MNEMONICS
+// class/hp mnemonics
+static int set=0;
+#else
+// readable/normal mnemonics
+static int set=1;
+#endif
+
+#define P "P"
+#define WP "WP"
+#define XS "XS"
+#define X "X"
+#define S "S"
+#define M "M"
+#define B "B"
+#define W "W"
+#define A "A"
+
+static const char *adr_b[]=
+{ P, WP, XS, X, S, M, B, W };
+
+static const char *adr_af[]=
+{ P, WP, XS, X, S, M, B, W, 0, 0, 0, 0, 0, 0, 0, A };
+
+static const char *adr_a[]=
+{ P, WP, XS, X, S, M, B, W };
+
+static const char number_2_hex[]=
+{ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
+
+#define SATURN_PEEKOP_DIS8(v) v = (INT8)( oprom[pos] | ( oprom[pos+1] << 4 ) ); pos+= 2;
+
+#define SATURN_PEEKOP_DIS12(v) v = oprom[pos] | ( oprom[pos+1] << 4 ) | ( oprom[pos+2] << 8 ); \
+ pos += 3; \
+ if ( v & 0x0800 ) v = -0x1000 + v;
+
+#define SATURN_PEEKOP_DIS16(v) v = (INT16)( oprom[pos] | ( oprom[pos+1] << 4 ) | ( oprom[pos+2] << 8 ) | ( oprom[pos+3] << 12 ) ); pos += 4;
+
+#define SATURN_PEEKOP_ADR(v) v = oprom[pos] | ( oprom[pos+1] << 4 ) | ( oprom[pos+2] << 8 ) | ( oprom[pos+3] << 12 ) | ( oprom[pos+4] << 16 ); pos += 5;
+
+
+// don't split branch and return, source relies on this ordering
+typedef enum {
+ Return, ReturnSetXM, ReturnSetCarry, ReturnClearCarry, ReturnFromInterrupt,
+ jump3,jump4,jump,
+ call3,call4,call,
+ branchCarrySet, returnCarrySet,
+ branchCarryClear, returnCarryClear,
+
+ outCS, outC, inA, inC,
+ unconfig, config, Cid, shutdown, cp1, reset, buscc,
+ CcopyP, PcopyC, sreq, CswapP,
+
+ inton, AloadImm, buscb,
+ clearAbit, setAbit, Abitclear, Abitset,
+ clearCbit, setCbit, Cbitclear, Cbitset,
+ PCloadA, buscd, PCloadC, intoff, rsi,
+
+ jumpA, jumpC, PCcopyA, PCcopyC, AcopyPC, CcopyPC,
+
+ clearHST,
+ branchHSTclear, returnHSTclear,
+
+ clearBitST, setBitST,
+ branchSTclear, returnSTclear,
+ branchSTset, returnSTset,
+
+
+ branchPdiffers, returnPdiffers,
+ branchPequals, returnPequals,
+
+ branchAequalsB, returnAequalsB,
+ branchBequalsC, returnBequalsC,
+ branchAequalsC, returnAequalsC,
+ branchCequalsD, returnCequalsD,
+ branchAdiffersB, returnAdiffersB,
+ branchBdiffersC, returnBdiffersC,
+ branchAdiffersC, returnAdiffersC,
+ branchCdiffersD, returnCdiffersD,
+ branchAzero, returnAzero,
+ branchBzero, returnBzero,
+ branchCzero, returnCzero,
+ branchDzero, returnDzero,
+ branchAnotzero, returnAnotzero,
+ branchBnotzero, returnBnotzero,
+ branchCnotzero, returnCnotzero,
+ branchDnotzero, returnDnotzero,
+
+ branchAgreaterB, returnAgreaterB,
+ branchBgreaterC, returnBgreaterC,
+ branchCgreaterA, returnCgreaterA,
+ branchDgreaterC, returnDgreaterC,
+ branchAlowerB, returnAlowerB,
+ branchBlowerC, returnBlowerC,
+ branchClowerA, returnClowerA,
+ branchDlowerC, returnDlowerC,
+ branchAnotlowerB, returnAnotlowerB,
+ branchBnotlowerC, returnBnotlowerC,
+ branchCnotlowerA, returnCnotlowerA,
+ branchDnotlowerC, returnDnotlowerC,
+ branchAnotgreaterB, returnAnotgreaterB,
+ branchBnotgreaterC, returnBnotgreaterC,
+ branchCnotgreaterA, returnCnotgreaterA,
+ branchDnotgreaterC, returnDnotgreaterC,
+
+ SetHexMode, SetDecMode,
+ PopC, PushC,
+
+ D0loadImm2, D0loadImm4, D0loadImm5,
+ D1loadImm2, D1loadImm4, D1loadImm5,
+ PloadImm, CloadImm,
+
+ clearST,
+ CcopyST, STcopyC,
+ swapCST,
+
+ incP, decP,
+
+ R0copyA, R1copyA, R2copyA, R3copyA, R4copyA,
+ R0copyC, R1copyC, R2copyC, R3copyC, R4copyC,
+
+ AcopyR0, AcopyR1, AcopyR2, AcopyR3, AcopyR4,
+ CcopyR0, CcopyR1, CcopyR2, CcopyR3, CcopyR4,
+
+ D0copyA, D1copyA, D0copyC, D1copyC,
+ D0copyAShort, D1copyAShort, D0copyCShort, D1copyCShort, // other class mnemonic
+
+ SwapAR0, SwapAR1, SwapAR2, SwapAR3, SwapAR4,
+ SwapCR0, SwapCR1, SwapCR2, SwapCR3, SwapCR4,
+
+ SwapAD0, SwapAD1, SwapCD0, SwapCD1,
+ SwapAD0Short, SwapAD1Short, SwapCD0Short, SwapCD1Short, // other class mnemonic
+
+ D0storeA, D1storeA, D0storeC, D1storeC,
+ AloadD0, AloadD1, CloadD0, CloadD1,
+
+ D0addImm, D1addImm, D0subImm, D1subImm,
+ AaddImm, BaddImm, CaddImm, DaddImm,
+ AsubImm, BsubImm, CsubImm, DsubImm,
+
+ AandB, BandC, CandA, DandC, BandA, CandB, AandC, CandD,
+ AorB, BorC, CorA, DorC, BorA, CorB, AorC, CorD,
+
+ Ashiftrightbit, Bshiftrightbit, Cshiftrightbit, Dshiftrightbit,
+
+ AshiftleftCarry, BshiftleftCarry, CshiftleftCarry, DshiftleftCarry,
+ AshiftrightCarry, BshiftrightCarry, CshiftrightCarry, DshiftrightCarry,
+
+ AaddB, BaddC, CaddA, DaddC, AaddA, BaddB, CaddC, DaddD,
+ BaddA, CaddB, AaddC, CaddD, decA, decB, decC, decD,
+
+ AsubB, BsubC, CsubA, DsubC, incA, incB, incC, incD,
+ BsubA, CsubB, AsubC, CsubD, AsubnB, BsubnC, CsubnA, DsubnC,
+
+ clearA, clearB, clearC, clearD,
+ AcopyB, BcopyC, CcopyA, DcopyC, BcopyA, CcopyB, AcopyC, CcopyD,
+ AswapB, BswapC, CswapA, DswapC,
+
+ Ashiftleft, Bshiftleft, Cshiftleft, Dshiftleft,
+ Ashiftright, Bshiftright, Cshiftright, Dshiftright,
+ negateA, negateB, negateC, negateD,
+ notA, notB, notC, notD
+
+} MNEMONICS;
+
+static struct {
+ const char *name[2];
+} mnemonics[]={
+ { { "rtn", "RET" } },
+ { { "rtnsXM", "RETSETXM" } },
+ { { "rtnsC", "RETSETC" } },
+ { { "rtncC", "RETCLRC" } },
+ { { "rti", "RETI" } },
+ { { "goto %05x", "JUMP.3 %05x" } },
+ { { "goto %05x", "JUMP.4 %05x" } },
+ { { "goto %05x", "JUMP %05x" } },
+ { { "gosub %05x", "CALL.3 %05x" } },
+ { { "gosub %05x", "CALL.4 %05x" } },
+ { { "gosub %05x", "CALL %05x" } },
+ { { "goC %05x", "BRCS %05x" } },
+ { { "rtnC", "RETCS" } },
+ { { "gonC %05x", "BRCC %05x" } },
+ { { "rtnnC", "RETCC" } },
+
+ { { "OUT=CS", "OUT.S C" } },
+ { { "OUT=C", "OUT.X C" } },
+ { { "A=IN", "IN.4 A" } },
+ { { "C=IN", "IN.4 C" } },
+ { { "uncnfg", "UNCNFG" } },
+ { { "config", "CONFIG" } },
+ { { "C=id", "MOVE.A ID,C" } },
+ { { "!shutdn", "!SHUTDN" } },
+ { { "C+P+1", "ADD.A P+1,C" } },
+ { { "reset", "RESET" } },
+ { { "!buscc", "!BUSCC" } },
+ { { "C=P %x", "MOVE.1 P,C,%x" } },
+ { { "P=C %x", "MOVE.1 C,%x,P" } },
+ { { "!sreq?", "!SREQ" } },
+ { { "CPex %x", "SWAP.1 P,C,%x" } },
+
+ { { "!inton", "!INTON" } },
+ { { "LA %-2x %s", "MOVE.P%-2x %s,A" } },
+ { { "!buscb", "!BUSCB" } },
+ { { "Abit=0 %x", "CLRB %x,A" } },
+ { { "Abit=1 %x", "SETB %x,A" } },
+ { { "?Abit=0 %x,%05x", "BRBC %x,A,%05x" } },
+ { { "?Abit=1 %x,%05x", "BRBS %x,A,%05x" } },
+ { { "Cbit=0 %x", "CLRB %x,C" } },
+ { { "Cbit=1 %x", "SETB %x,C" } },
+ { { "?Cbit=0 %x,%05x", "BRBC %x,C,%05x" } },
+ { { "?Cbit=1 %x,%05x", "BRBS %x,C,%05x" } },
+ { { "PC=(A)", "JUMP.A @A" } },
+ { { "!buscd", "!BUSCD" } },
+ { { "PC=(C)", "JUMP.A @C" } },
+ { { "!intoff", "!INTOFF" } },
+ { { "!rsi", "!RSI" } },
+
+ { { "PC=A", "JUMP.A A" } },
+ { { "PC=C", "JUMP.A C" } },
+ { { "A=PC", "MOVE.A PC,A" } },
+ { { "C=PC", "MOVE.A PC,C" } },
+ { { "APCex", "SWAP.A A,PC" } },
+ { { "CPCex", "SWAP.A C,PC" } },
+
+ { { "HST=0 %x", "CLRHST %x" } },
+ { { "?HST=0 %x,%05x", "BRBCHST %x,%05x" } },
+ { { "?HST=0 %x", "RETBCHST %x" } },
+ { { "ST=0 %x", "CLRB %x,ST" } },
+ { { "ST=1 %x", "SETB %x,ST" } },
+ { { "?ST=0 %x,%05x", "BRBC ST,%x,%05x" } },
+ { { "?ST=0 %x", "RETBC ST,%x" } },
+ { { "?ST=1 %x,%05x", "BRBS ST,%x,%05x" } },
+ { { "?ST=1 %x", "RETBS ST,%x" } },
+ { { "?P# %x,%05x", "BRNE P,%x,%05x" } },
+ { { "?P# %x", "RETNE P,%x" } },
+ { { "?P= %x,%05x", "BREQ P,%x,%05x" } },
+ { { "?P= %x", "RETEQ P,%x" } },
+
+ { { "?A=B %x,%05x", "BREQ.%-2s A,B,%05x" } },
+ { { "?A=B %x", "RETEQ.%-2s A,B" } },
+ { { "?B=C %x,%05x", "BREQ.%-2s B,C,%05x" } },
+ { { "?B=C %x", "RETEQ.%-2s B,C" } },
+ { { "?A=C %x,%05x", "BREQ.%-2s A,C,%05x" } },
+ { { "?A=C %x", "RETEQ.%-2s A,C" } },
+ { { "?C=D %x,%05x", "BREQ.%-2s C,D,%05x" } },
+ { { "?C=D %x", "RETEQ.%-2s C,D" } },
+ { { "?A#B %x,%05x", "BRNE.%-2s A,B,%05x" } },
+ { { "?A#B %x", "RETNE.%-2s A,B" } },
+ { { "?B#C %x,%05x", "BRNE.%-2s B,C,%05x" } },
+ { { "?B#C %x", "RETNE.%-2s B,C" } },
+ { { "?A#C %x,%05x", "BRNE.%-2s A,C,%05x" } },
+ { { "?A#C %x", "RETNE.%-2s A,C" } },
+ { { "?C#D %x,%05x", "BRNE.%-2s C,D,%05x" } },
+ { { "?C#D %x", "RETNE.%-2s C,D" } },
+ { { "?A=0 %x,%05x", "BRZ.%-2s A,%05x" } },
+ { { "?A=0 %x", "RETZ.%-2s A" } },
+ { { "?B=0 %x,%05x", "BRZ.%-2s B,%05x" } },
+ { { "?B=0 %x", "RETZ.%-2s B" } },
+ { { "?C=0 %x,%05x", "BRZ.%-2s C,%05x" } },
+ { { "?C=0 %x", "RETZ.%-2s C" } },
+ { { "?D=0 %x,%05x", "BRZ.%-2s D,%05x" } },
+ { { "?D=0 %x", "RETZ.%-2s D" } },
+ { { "?A#0 %x,%05x", "BRNZ.%-2s A,%05x" } },
+ { { "?A#0 %x", "RETNZ.%-2s A" } },
+ { { "?B#0 %x,%05x", "BRNZ.%-2s B,%05x" } },
+ { { "?B#0 %x", "RETNZ.%-2s B" } },
+ { { "?C#0 %x,%05x", "BRNZ.%-2s C,%05x" } },
+ { { "?C#0 %x", "RETNZ.%-2s C" } },
+ { { "?D#0 %x,%05x", "BRNZ.%-2s D,%05x" } },
+ { { "?D#0 %x", "RETNZ.%-2s D" } },
+
+ { { "?A>B %x,%05x", "BRGT.%-2s A,B,%05x" } },
+ { { "?A>B %x", "RETGT.%-2s A,B" } },
+ { { "?B>C %x,%05x", "BRGT.%-2s B,C,%05x" } },
+ { { "?B>C %x", "RETGT.%-2s B,C" } },
+ { { "?C>A %x,%05x", "BRGT.%-2s C,A,%05x" } },
+ { { "?C>A %x", "RETGT.%-2s C,A" } },
+ { { "?D>C %x,%05x", "BRGT.%-2s D,C,%05x" } },
+ { { "?D>C %x", "RETGT.%-2s D,C" } },
+ { { "?A<B %x,%05x", "BRLT.%-2s A,B,%05x" } },
+ { { "?A<B %x", "RETLT.%-2s A,B" } },
+ { { "?B<C %x,%05x", "BRLT.%-2s B,C,%05x" } },
+ { { "?B<C %x", "RETLT.%-2s B,C" } },
+ { { "?C<A %x,%05x", "BRLT.%-2s C,A,%05x" } },
+ { { "?C<A %x", "RETLT.%-2s C,A" } },
+ { { "?D<C %x,%05x", "BRLT.%-2s D,C,%05x" } },
+ { { "?D<C %x", "RETLT.%-2s D,C" } },
+ { { "?A>=B %x,%05x", "BRGE.%-2s A,B,%05x" } },
+ { { "?A>=B %x", "RETGE.%-2s A,B" } },
+ { { "?B>=C %x,%05x", "BRGE.%-2s B,C,%05x" } },
+ { { "?B>=C %x", "RETGE.%-2s B,C" } },
+ { { "?C>=A %x,%05x", "BRGE.%-2s C,A,%05x" } },
+ { { "?C>=A %x", "RETGE.%-2s C,A" } },
+ { { "?D>=C %x,%05x", "BRGE.%-2s D,C,%05x" } },
+ { { "?D>=C %x", "RETGE.%-2s D,C" } },
+ { { "?A<=B %x,%05x", "BRLE.%-2s A,B,%05x" } },
+ { { "?A<=B %x", "RETLE.%-2s A,B" } },
+ { { "?B<=C %x,%05x", "BRLE.%-2s B,C,%05x" } },
+ { { "?B<=C %x", "RETLE.%-2s B,C" } },
+ { { "?C<=A %x,%05x", "BRLE.%-2s C,A,%05x" } },
+ { { "?C<=A %x", "RETLE.%-2s C,A" } },
+ { { "?D<=C %x,%05x", "BRLE.%-2s D,C,%05x" } },
+ { { "?D<=C %x", "RETLE.%-2s D,C" } },
+
+ { { "sethex", "SETHEX" } },
+ { { "setdec", "SETDEC" } },
+ { { "RSTK=C", "PUSH.A C" } },
+ { { "C=RSTK", "POP.A C" } },
+
+ // load immediate
+ { { "D0= %02x", "MOVE.2 %02x,D0" } },
+ { { "D0= %04x", "MOVE.4 %04x,D0" } },
+ { { "D0= %05x", "MOVE.5 %05x,D0" } },
+
+ { { "D1= %02x", "MOVE.2 %02x,D1" } },
+ { { "D1= %04x", "MOVE.4 %04x,D1" } },
+ { { "D1= %05x", "MOVE.5 %05x,D1" } },
+
+ { { "P= %x", "MOVE %x,P" } },
+ { { "lC %-2x %s", "MOVE.P%-2x %s,C" } },
+
+ { { "clrST", "CLR.X ST" } },
+ { { "C=ST", "MOVE.X ST,C" } },
+ { { "ST=C", "MOVE.X C,ST" } },
+ { { "CSTex", "SWAP.X C,ST" } },
+
+ { { "P=P+1", "INC P" } },
+ { { "P=P-1", "DEC P" } },
+
+ // copy
+ { { "R0=A %s", "MOVE.%-2s A,R0" } },
+ { { "R1=A %s", "MOVE.%-2s A,R1" } },
+ { { "R2=A %s", "MOVE.%-2s A,R2" } },
+ { { "R3=A %s", "MOVE.%-2s A,R3" } },
+ { { "R4=A %s", "MOVE.%-2s A,R4" } },
+
+ { { "R0=C %s", "MOVE.%-2s C,R0" } },
+ { { "R1=C %s", "MOVE.%-2s C,R1" } },
+ { { "R2=C %s", "MOVE.%-2s C,R2" } },
+ { { "R3=C %s", "MOVE.%-2s C,R3" } },
+ { { "R4=C %s", "MOVE.%-2s C,R4" } },
+
+ { { "A=R0 %s", "MOVE.%-2s R0,A" } },
+ { { "A=R1 %s", "MOVE.%-2s R1,A" } },
+ { { "A=R2 %s", "MOVE.%-2s R2,A" } },
+ { { "A=R3 %s", "MOVE.%-2s R3,A" } },
+ { { "A=R4 %s", "MOVE.%-2s R4,A" } },
+
+ { { "C=R0 %s", "MOVE.%-2s R0,C" } },
+ { { "C=R1 %s", "MOVE.%-2s R1,C" } },
+ { { "C=R2 %s", "MOVE.%-2s R2,C" } },
+ { { "C=R3 %s", "MOVE.%-2s R3,C" } },
+ { { "C=R4 %s", "MOVE.%-2s R4,C" } },
+
+ { { "D0=A", "MOVE.A A,D0" } },
+ { { "D1=A", "MOVE.A A,D1" } },
+ { { "D0=C", "MOVE.A C,D0" } },
+ { { "D1=C", "MOVE.A C,D1" } },
+ { { "D0=As", "MOVE.S A,D0" } },
+ { { "D1=As", "MOVE.S A,D1" } },
+ { { "D0=Cs", "MOVE.S C,D0" } },
+ { { "D1=Cs", "MOVE.S C,D1" } },
+
+ // swap operations
+ { { "AR0ex %s", "SWAP.%-2s A,R0" } },
+ { { "AR1ex %s", "SWAP.%-2s A,R1" } },
+ { { "AR2ex %s", "SWAP.%-2s A,R2" } },
+ { { "AR3ex %s", "SWAP.%-2s A,R3" } },
+ { { "AR4ex %s", "SWAP.%-2s A,R4" } },
+
+ { { "CR0ex %s", "SWAP.%-2s C,R0" } },
+ { { "CR1ex %s", "SWAP.%-2s C,R1" } },
+ { { "CR2ex %s", "SWAP.%-2s C,R2" } },
+ { { "CR3ex %s", "SWAP.%-2s C,R3" } },
+ { { "CR4ex %s", "SWAP.%-2s C,R4" } },
+
+ { { "AD0ex", "SWAP.A A,D0" } },
+ { { "AD1ex", "SWAP.A A,D1" } },
+ { { "CD0ex", "SWAP.A C,D0" } },
+ { { "CD1ex", "SWAP.A C,D1" } },
+ { { "AD0xs", "SWAP.S A,D0" } },
+ { { "AD1xs", "SWAP.S A,D1" } },
+ { { "CD0xs", "SWAP.S C,D0" } },
+ { { "CD1xs", "SWAP.S C,D1" } },
+
+ // store
+ { { "Dat0=A %s", "MOVE.%-2s A,@D0" } },
+ { { "Dat1=A %s", "MOVE.%-2s A,@D0" } },
+ { { "Dat0=C %s", "MOVE.%-2s C,@D0" } },
+ { { "Dat1=C %s", "MOVE.%-2s C,@D0" } },
+
+ // load
+ { { "A=Dat0 %s", "MOVE.%-2s @D0,A" } },
+ { { "A=Dat1 %s", "MOVE.%-2s @D0,A" } },
+ { { "C=Dat0 %s", "MOVE.%-2s @D0,C" } },
+ { { "C=Dat1 %s", "MOVE.%-2s @D0,C" } },
+
+ // add/sub immediate
+ { { "D0=D0+ %x", "ADD.A %x,D0" } },
+ { { "D1=D1+ %x", "ADD.A %x,D1" } },
+ { { "D0=D0- %x", "SUB.A %x,D0" } },
+ { { "D1=D1- %x", "SUB.A %x,D1" } },
+
+ { { "A=A+ %s,%x", "ADD.%-2s %x,A" } },
+ { { "B=B+ %s,%x", "ADD.%-2s %x,B" } },
+ { { "C=C+ %s,%x", "ADD.%-2s %x,C" } },
+ { { "D=D+ %s,%x", "ADD.%-2s %x,D" } },
+ { { "A=A- %s,%x", "SUB.%-2s %x,A" } },
+ { { "B=B- %s,%x", "SUB.%-2s %x,B" } },
+ { { "C=C- %s,%x", "SUB.%-2s %x,C" } },
+ { { "D=D- %s,%x", "SUB.%-2s %x,D" } },
+
+ { { "A=A&B %s", "AND.%-2s B,A" } },
+ { { "B=B&C %s", "AND.%-2s C,B" } },
+ { { "C=C&A %s", "AND.%-2s A,C" } },
+ { { "D=D&C %s", "AND.%-2s C,D" } },
+ { { "B=B&A %s", "AND.%-2s A,B" } },
+ { { "C=C&B %s", "AND.%-2s B,C" } },
+ { { "A=A&C %s", "AND.%-2s C,A" } },
+ { { "C=C&D %s", "AND.%-2s D,C" } },
+
+ { { "A=A!B %s", "OR.%-2s B,A" } },
+ { { "B=B!C %s", "OR.%-2s C,B" } },
+ { { "C=C!A %s", "OR.%-2s A,C" } },
+ { { "D=D!C %s", "OR.%-2s C,D" } },
+ { { "B=B!A %s", "OR.%-2s A,B" } },
+ { { "C=C!B %s", "OR.%-2s B,C" } },
+ { { "A=A!C %s", "OR.%-2s C,A" } },
+ { { "C=C!D %s", "OR.%-2s D,C" } },
+
+ { { "Asrb %x", "SRB.%-2s A" } },
+ { { "Bsrb %x", "SRB.%-2s B" } },
+ { { "Csrb %x", "SRB.%-2s C" } },
+ { { "Dsrb %x", "SRB.%-2s D" } },
+
+ { { "Aslc %s", "RLN.%-2s A" } },
+ { { "Bslc %s", "RLN.%-2s B" } },
+ { { "Cslc %s", "RLN.%-2s C" } },
+ { { "Dslc %s", "RLN.%-2s D" } },
+ { { "Aslc %s", "RRN.%-2s A" } },
+ { { "Bslc %s", "RRN.%-2s B" } },
+ { { "Cslc %s", "RRN.%-2s C" } },
+ { { "Dslc %s", "RRN.%-2s D" } },
+
+ { { "A=A+B %s", "ADD.%-2s B,A" } },
+ { { "B=B+C %s", "ADD.%-2s C,B" } },
+ { { "C=C+A %s", "ADD.%-2s A,C" } },
+ { { "D=D+C %s", "ADD.%-2s C,D" } },
+ { { "A=A+A %s", "ADD.%-2s A,A" } },
+ { { "B=B+B %s", "ADD.%-2s B,B" } },
+ { { "C=C+C %s", "ADD.%-2s C,C" } },
+ { { "D=D+C %s", "ADD.%-2s D,D" } },
+ { { "B=B+A %s", "ADD.%-2s A,B" } },
+ { { "C=C+B %s", "ADD.%-2s B,C" } },
+ { { "A=A+C %s", "ADD.%-2s C,A" } },
+ { { "C=C+D %s", "ADD.%-2s D,C" } },
+ { { "A=A-1 %s", "DEC.%-2s A" } },
+ { { "B=B-1 %s", "DEC.%-2s B" } },
+ { { "C=C-1 %s", "DEC.%-2s C" } },
+ { { "D=D-1 %s", "DEC.%-2s D" } },
+
+ { { "A=A-B %s", "ADD.%-2s B,A" } },
+ { { "B=B-C %s", "ADD.%-2s C,B" } },
+ { { "C=C-A %s", "ADD.%-2s A,C" } },
+ { { "D=D-C %s", "ADD.%-2s C,D" } },
+ { { "A=A+1 %s", "INC.%-2s A" } },
+ { { "B=B+1 %s", "INC.%-2s B" } },
+ { { "C=C+1 %s", "INC.%-2s C" } },
+ { { "D=D+1 %s", "INC.%-2s D" } },
+ { { "B=B-A %s", "SUB.%-2s A,B" } },
+ { { "C=C-B %s", "SUB.%-2s B,C" } },
+ { { "A=A-C %s", "SUB.%-2s C,A" } },
+ { { "C=C-D %s", "SUB.%-2s D,C" } },
+ { { "A=B-A %s", "SUBN.%-2s B,A" } },
+ { { "B=C-B %s", "SUBN.%-2s C,B" } },
+ { { "C=A-C %s", "SUBN.%-2s A,C" } },
+ { { "D=C-D %s", "SUBN.%-2s C,D" } },
+
+ { { "A=0 %s", "CLR.%-2s A" } },
+ { { "B=0 %s", "CLR.%-2s B" } },
+ { { "C=0 %s", "CLR.%-2s C" } },
+ { { "D=0 %s", "CLR.%-2s D" } },
+ { { "A=B %s", "MOVE.%-2s B,A" } },
+ { { "B=C %s", "MOVE.%-2s C,B" } },
+ { { "C=A %s", "MOVE.%-2s A,C" } },
+ { { "D=C %s", "MOVE.%-2s C,D" } },
+ { { "B=A %s", "MOVE.%-2s A,B" } },
+ { { "C=B %s", "MOVE.%-2s B,C" } },
+ { { "A=C %s", "MOVE.%-2s C,A" } },
+ { { "C=D %s", "MOVE.%-2s D,C" } },
+ { { "ABex %s", "SWAP.%-2s A,B" } },
+ { { "BCex %s", "SWAP.%-2s B,C" } },
+ { { "ACex %s", "SWAP.%-2s A,C" } },
+ { { "CDex %s", "SWAP.%-2s C,D" } },
+
+ { { "Asl %s", "SLN.%-2s A" } },
+ { { "Bsl %s", "SLN.%-2s B" } },
+ { { "Csl %s", "SLN.%-2s C" } },
+ { { "Dsl %s", "SLN.%-2s D" } },
+ { { "Asr %s", "SRN.%-2s A" } },
+ { { "Bsr %s", "SRN.%-2s B" } },
+ { { "Csr %s", "SRN.%-2s C" } },
+ { { "Dsr %s", "SRN.%-2s D" } },
+ { { "A=-A %s", "NEG.%-2s A" } },
+ { { "B=-B %s", "NEG.%-2s B" } },
+ { { "C=-C %s", "NEG.%-2s C" } },
+ { { "D=-D %s", "NEG.%-2s D" } },
+ { { "A=-A-1 %s", "NOT.%-2s A" } },
+ { { "B=-B-1 %s", "NOT.%-2s B" } },
+ { { "C=-C-1 %s", "NOT.%-2s C" } },
+ { { "D=-D-1 %s", "NOT.%-2s D" } }
+
+};
+
+typedef struct {
+ enum {
+ Complete=-1,
+ Illegal,
+ Opcode0, Opcode0E, Opcode0Ea,
+ Opcode1, Opcode10, Opcode11, Opcode12, Opcode13, Opcode14, Opcode15,
+ Opcode8, Opcode80, Opcode808, Opcode8081,
+ Opcode81, Opcode818, Opcode818a, Opcode819, Opcode819a,
+ Opcode81A, Opcode81Aa, Opcode81Aa0,Opcode81Aa1, Opcode81Aa2, Opcode81B,
+ Opcode8A, Opcode8B,
+ Opcode9, Opcode9a, Opcode9b,
+ OpcodeA, OpcodeAa, OpcodeAb,
+ OpcodeB, OpcodeBa, OpcodeBb,
+ OpcodeC,
+ OpcodeD,
+ OpcodeE,
+ OpcodeF
+ } sel;
+ enum {
+ AdrNone,
+ AdrAF, AdrA, AdrB, AdrCount,
+ BranchReturn, TestBranchRet, ImmBranch,
+ ABranchReturn, // address field A
+ xBranchReturn, // address field specified in previous opcode entry
+ Imm, ImmCount, ImmCload, Imm2, Imm4, Imm5,
+ Dis3, Dis3Call, Dis4, Dis4Call, Abs,
+ FieldP, FieldWP, FieldXS, FieldX, FieldS, FieldM, FieldB, FieldW, FieldA
+ } adr;
+ MNEMONICS mnemonic;
+} OPCODE;
+
+static const char *field_2_string(int adr_enum)
+{
+ switch (adr_enum) {
+ case FieldP: return P;
+ case FieldWP: return WP;
+ case FieldXS: return XS;
+ case FieldX: return X;
+ case FieldS: return S;
+ case FieldM: return M;
+ case FieldB: return B;
+ case FieldW: return W;
+ case FieldA: return A;
+ }
+ return 0;
+}
+
+static OPCODE opcodes[][0x10]= {
+ {
+ // first digit
+ { Opcode0 },
+ { Opcode1 },
+ { Complete, Imm, PloadImm },
+ { Complete, ImmCload, CloadImm },
+ { Complete, BranchReturn, branchCarrySet},
+ { Complete, BranchReturn, branchCarryClear },
+ { Complete, Dis3, jump3 },
+ { Complete, Dis3Call, call3 },
+ { Opcode8 },
+ { Opcode9 },
+ { OpcodeA },
+ { OpcodeB },
+ { OpcodeC },
+ { OpcodeD },
+ { OpcodeE },
+ { OpcodeF }
+ }, { // 0
+ { Complete, AdrNone, ReturnSetXM },
+ { Complete, AdrNone, Return },
+ { Complete, AdrNone, ReturnSetCarry },
+ { Complete, AdrNone, ReturnClearCarry },
+ { Complete, AdrNone, SetHexMode },
+ { Complete, AdrNone, SetDecMode },
+ { Complete, AdrNone, PopC },
+ { Complete, AdrNone, PushC },
+ { Complete, AdrNone, clearST },
+ { Complete, AdrNone, CcopyST },
+ { Complete, AdrNone, STcopyC },
+ { Complete, AdrNone, swapCST },
+ { Complete, AdrNone, incP },
+ { Complete, AdrNone, decP },
+ { Opcode0E },
+ { Complete, AdrNone, ReturnFromInterrupt }
+ }, { //0E
+ { Opcode0Ea, AdrAF },
+ { Opcode0Ea, AdrAF },
+ { Opcode0Ea, AdrAF },
+ { Opcode0Ea, AdrAF },
+ { Opcode0Ea, AdrAF },
+ { Opcode0Ea, AdrAF },
+ { Opcode0Ea, AdrAF },
+ { Opcode0Ea, AdrAF },
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ { Opcode0Ea, AdrAF }
+ }, { //0Ea
+ { Complete, AdrNone, AandB },
+ { Complete, AdrNone, BandC },
+ { Complete, AdrNone, CandA },
+ { Complete, AdrNone, DandC },
+ { Complete, AdrNone, BandA },
+ { Complete, AdrNone, CandB },
+ { Complete, AdrNone, AandC },
+ { Complete, AdrNone, CandD },
+ { Complete, AdrNone, AorB },
+ { Complete, AdrNone, BorC },
+ { Complete, AdrNone, CorA },
+ { Complete, AdrNone, DorC },
+ { Complete, AdrNone, BorA },
+ { Complete, AdrNone, CorB },
+ { Complete, AdrNone, AorC },
+ { Complete, AdrNone, CorD }
+ }, { //1
+ { Opcode10 },
+ { Opcode11 },
+ { Opcode12 },
+ { Opcode13 },
+ { Opcode14 },
+ { Opcode15 },
+ { Complete, ImmCount, D0addImm },
+ { Complete, ImmCount, D1addImm },
+ { Complete, ImmCount, D0subImm },
+ { Complete, Imm2, D0loadImm2 },
+ { Complete, Imm4, D0loadImm4 },
+ { Complete, Imm5, D0loadImm5 },
+ { Complete, ImmCount, D1subImm },
+ { Complete, Imm2, D1loadImm2 },
+ { Complete, Imm4, D1loadImm4 },
+ { Complete, Imm5, D1loadImm5 }
+ }, { //10
+ { Complete, FieldW, R0copyA },
+ { Complete, FieldW, R1copyA },
+ { Complete, FieldW, R2copyA },
+ { Complete, FieldW, R3copyA },
+ { Complete, FieldW, R4copyA },
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ { Complete, FieldW, R0copyC },
+ { Complete, FieldW, R1copyC },
+ { Complete, FieldW, R2copyC },
+ { Complete, FieldW, R3copyC },
+ { Complete, FieldW, R4copyC },
+ { Illegal },
+ { Illegal },
+ { Illegal }
+ }, { //11
+ { Complete, FieldW, AcopyR0 },
+ { Complete, FieldW, AcopyR1 },
+ { Complete, FieldW, AcopyR2 },
+ { Complete, FieldW, AcopyR3 },
+ { Complete, FieldW, AcopyR4 },
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ { Complete, FieldW, CcopyR0 },
+ { Complete, FieldW, CcopyR1 },
+ { Complete, FieldW, CcopyR2 },
+ { Complete, FieldW, CcopyR3 },
+ { Complete, FieldW, CcopyR4 },
+ { Illegal },
+ { Illegal },
+ { Illegal }
+ }, { //12
+ { Complete, FieldW, SwapAR0 },
+ { Complete, FieldW, SwapAR1 },
+ { Complete, FieldW, SwapAR2 },
+ { Complete, FieldW, SwapAR3 },
+ { Complete, FieldW, SwapAR4 },
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ { Complete, FieldW, SwapCR0 },
+ { Complete, FieldW, SwapCR1 },
+ { Complete, FieldW, SwapCR2 },
+ { Complete, FieldW, SwapCR3 },
+ { Complete, FieldW, SwapCR4 },
+ { Illegal },
+ { Illegal },
+ { Illegal }
+ }, { //13
+ { Complete, FieldA, D0copyA },
+ { Complete, FieldA, D1copyA },
+ { Complete, FieldA, SwapAD0 },
+ { Complete, FieldA, SwapAD1 },
+ { Complete, FieldA, D0copyC },
+ { Complete, FieldA, D1copyC },
+ { Complete, FieldA, SwapCD0 },
+ { Complete, FieldA, SwapCD1 },
+ { Complete, FieldS, D0copyAShort },
+ { Complete, FieldS, D1copyAShort },
+ { Complete, FieldS, SwapAD0Short },
+ { Complete, FieldS, SwapAD1Short },
+ { Complete, FieldS, D0copyCShort },
+ { Complete, FieldS, D1copyCShort },
+ { Complete, FieldS, SwapCD0Short },
+ { Complete, FieldS, SwapCD1Short }
+ }, { //14
+ { Complete, FieldA, D0storeA },
+ { Complete, FieldA, D1storeA },
+ { Complete, FieldA, AloadD0 },
+ { Complete, FieldA, AloadD1 },
+ { Complete, FieldA, D0storeC },
+ { Complete, FieldA, D1storeC },
+ { Complete, FieldA, CloadD0 },
+ { Complete, FieldA, CloadD1 },
+ { Complete, FieldB, D0storeA },
+ { Complete, FieldB, D1storeA },
+ { Complete, FieldB, AloadD0 },
+ { Complete, FieldB, AloadD1 },
+ { Complete, FieldB, D0storeC },
+ { Complete, FieldB, D1storeC },
+ { Complete, FieldB, CloadD0 },
+ { Complete, FieldB, CloadD1 }
+ }, { //15
+ { Complete, AdrA, D0storeA },
+ { Complete, AdrA, D1storeA },
+ { Complete, AdrA, AloadD0 },
+ { Complete, AdrA, AloadD1 },
+ { Complete, AdrA, D0storeC },
+ { Complete, AdrA, D1storeC },
+ { Complete, AdrA, CloadD0 },
+ { Complete, AdrA, CloadD1 },
+ { Complete, AdrCount, D0storeA },
+ { Complete, AdrCount, D1storeA },
+ { Complete, AdrCount, AloadD0 },
+ { Complete, AdrCount, AloadD1 },
+ { Complete, AdrCount, D0storeC },
+ { Complete, AdrCount, D1storeC },
+ { Complete, AdrCount, CloadD0 },
+ { Complete, AdrCount, CloadD1 },
+ }, { //8
+ { Opcode80 },
+ { Opcode81 },
+ { Complete, Imm, clearHST },
+ { Complete, TestBranchRet, branchHSTclear },
+ { Complete, Imm, clearBitST },
+ { Complete, Imm, setBitST },
+ { Complete, TestBranchRet, branchSTclear },
+ { Complete, TestBranchRet, branchSTset },
+ { Complete, TestBranchRet, branchPdiffers},
+ { Complete, TestBranchRet, branchPequals},
+ { Opcode8A },
+ { Opcode8B },
+ { Complete, Dis4, jump4 },
+ { Complete, Abs, jump },
+ { Complete, Dis4Call, call4 },
+ { Complete, Abs, call }
+ }, { //80
+ { Complete, AdrNone, outCS },
+ { Complete, AdrNone, outC },
+ { Complete, AdrNone, inA },
+ { Complete, AdrNone, inC },
+ { Complete, AdrNone, unconfig },
+ { Complete, AdrNone, config },
+ { Complete, AdrNone, Cid },
+ { Complete, AdrNone, shutdown },
+ { Opcode808 },
+ { Complete, AdrNone, cp1 },
+ { Complete, AdrNone, reset },
+ { Complete, AdrNone, buscc },
+ { Complete, Imm, CcopyP },
+ { Complete, Imm, PcopyC },
+ { Complete, AdrNone, sreq },
+ { Complete, Imm, CswapP }
+ }, { //808
+ { Complete, AdrNone, inton },
+ { Opcode8081 },
+ { Complete, ImmCload, AloadImm },
+ { Complete, AdrNone, buscb },
+ { Complete, Imm, clearAbit },
+ { Complete, Imm, setAbit },
+ { Complete, ImmBranch, Abitclear },
+ { Complete, ImmBranch, Abitset },
+ { Complete, Imm, clearCbit },
+ { Complete, Imm, setCbit },
+ { Complete, ImmBranch, Cbitclear },
+ { Complete, ImmBranch, Cbitset },
+ { Complete, AdrNone, PCloadA },
+ { Complete, AdrNone, buscd },
+ { Complete, AdrNone, PCloadC },
+ { Complete, AdrNone, intoff }
+ }, { //8081
+ { Complete, AdrNone, rsi },
+ //! rest illegal
+ }, { //81
+ { Complete, FieldW, AshiftleftCarry },
+ { Complete, FieldW, BshiftleftCarry },
+ { Complete, FieldW, DshiftleftCarry },
+ { Complete, FieldW, DshiftleftCarry },
+ { Complete, FieldW, AshiftrightCarry },
+ { Complete, FieldW, AshiftrightCarry },
+ { Complete, FieldW, AshiftrightCarry },
+ { Complete, FieldW, AshiftrightCarry },
+ { Opcode818 },
+ { Opcode819 },
+ { Opcode81A },
+ { Opcode81B },
+ { Complete, FieldW, Ashiftrightbit },
+ { Complete, FieldW, Bshiftrightbit },
+ { Complete, FieldW, Cshiftrightbit },
+ { Complete, FieldW, Dshiftrightbit }
+ }, { //818
+ { Opcode818a, AdrAF },
+ { Opcode818a, AdrAF },
+ { Opcode818a, AdrAF },
+ { Opcode818a, AdrAF },
+ { Opcode818a, AdrAF },
+ { Opcode818a, AdrAF },
+ { Opcode818a, AdrAF },
+ { Opcode818a, AdrAF },
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ { Opcode818a, AdrAF },
+ }, { //818a
+ { Complete, AdrNone, AaddImm },
+ { Complete, AdrNone, BaddImm },
+ { Complete, AdrNone, CaddImm },
+ { Complete, AdrNone, DaddImm },
+ { Complete, AdrNone, AsubImm },
+ { Complete, AdrNone, BsubImm },
+ { Complete, AdrNone, CsubImm },
+ { Complete, AdrNone, DsubImm }
+ //! rest illegal
+ }, { //819
+ { Opcode819a, AdrAF },
+ { Opcode819a, AdrAF },
+ { Opcode819a, AdrAF },
+ { Opcode819a, AdrAF },
+ { Opcode819a, AdrAF },
+ { Opcode819a, AdrAF },
+ { Opcode819a, AdrAF },
+ { Opcode819a, AdrAF }, //?
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ { Opcode819a, AdrAF },
+ }, { //819a }
+ { Complete, AdrNone, Ashiftright },
+ { Complete, AdrNone, Bshiftright },
+ { Complete, AdrNone, Cshiftright },
+ { Complete, AdrNone, Dshiftright },
+ //! rest illegal
+ }, { //81A
+ { Opcode81Aa, AdrAF },
+ { Opcode81Aa, AdrAF },
+ { Opcode81Aa, AdrAF },
+ { Opcode81Aa, AdrAF },
+ { Opcode81Aa, AdrAF },
+ { Opcode81Aa, AdrAF },
+ { Opcode81Aa, AdrAF },
+ { Opcode81Aa, AdrAF },
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ { Opcode81Aa, AdrAF },
+ }, { //81Aa
+ { Opcode81Aa0 },
+ { Opcode81Aa1 },
+ { Opcode81Aa2 },
+ //! rest illegal
+ }, { //81Aa0
+ { Complete, AdrNone, R0copyA },
+ { Complete, AdrNone, R1copyA },
+ { Complete, AdrNone, R2copyA },
+ { Complete, AdrNone, R3copyA },
+ { Complete, AdrNone, R4copyA },
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ { Complete, AdrNone, R0copyC },
+ { Complete, AdrNone, R1copyC },
+ { Complete, AdrNone, R2copyC },
+ { Complete, AdrNone, R3copyC },
+ { Complete, AdrNone, R4copyC },
+ { Illegal },
+ { Illegal },
+ { Illegal }
+ }, { //81Aa1
+ { Complete, AdrNone, AcopyR0 },
+ { Complete, AdrNone, AcopyR1 },
+ { Complete, AdrNone, AcopyR2 },
+ { Complete, AdrNone, AcopyR3 },
+ { Complete, AdrNone, AcopyR4 },
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ { Complete, AdrNone, CcopyR0 },
+ { Complete, AdrNone, CcopyR1 },
+ { Complete, AdrNone, CcopyR2 },
+ { Complete, AdrNone, CcopyR3 },
+ { Complete, AdrNone, CcopyR4 },
+ { Illegal },
+ { Illegal },
+ { Illegal }
+ }, { //81Aa2
+ { Complete, AdrNone, SwapAR0 },
+ { Complete, AdrNone, SwapAR1 },
+ { Complete, AdrNone, SwapAR2 },
+ { Complete, AdrNone, SwapAR3 },
+ { Complete, AdrNone, SwapAR4 },
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ { Complete, AdrNone, SwapCR0 },
+ { Complete, AdrNone, SwapCR1 },
+ { Complete, AdrNone, SwapCR2 },
+ { Complete, AdrNone, SwapCR3 },
+ { Complete, AdrNone, SwapCR4 },
+ { Illegal },
+ { Illegal },
+ { Illegal }
+ }, { //81B
+ { Illegal },
+ { Illegal },
+ { Complete, AdrNone, jumpA },
+ { Complete, AdrNone, jumpC },
+ { Complete, AdrNone, PCcopyA },
+ { Complete, AdrNone, PCcopyC },
+ { Complete, AdrNone, AcopyPC },
+ { Complete, AdrNone, CcopyPC },
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ { Illegal }
+ }, { //8A
+ { Complete, ABranchReturn, branchAequalsB },
+ { Complete, ABranchReturn, branchBequalsC },
+ { Complete, ABranchReturn, branchAequalsC },
+ { Complete, ABranchReturn, branchCequalsD },
+ { Complete, ABranchReturn, branchAdiffersB },
+ { Complete, ABranchReturn, branchBdiffersC },
+ { Complete, ABranchReturn, branchAdiffersC },
+ { Complete, ABranchReturn, branchCdiffersD },
+ { Complete, ABranchReturn, branchAzero },
+ { Complete, ABranchReturn, branchBzero },
+ { Complete, ABranchReturn, branchCzero },
+ { Complete, ABranchReturn, branchDzero },
+ { Complete, ABranchReturn, branchAnotzero },
+ { Complete, ABranchReturn, branchBnotzero },
+ { Complete, ABranchReturn, branchCnotzero },
+ { Complete, ABranchReturn, branchDnotzero }
+ }, { //8B
+ { Complete, ABranchReturn, branchAgreaterB },
+ { Complete, ABranchReturn, branchBgreaterC },
+ { Complete, ABranchReturn, branchCgreaterA },
+ { Complete, ABranchReturn, branchDgreaterC },
+ { Complete, ABranchReturn, branchAlowerB },
+ { Complete, ABranchReturn, branchBlowerC },
+ { Complete, ABranchReturn, branchClowerA },
+ { Complete, ABranchReturn, branchDlowerC },
+ { Complete, ABranchReturn, branchAnotlowerB },
+ { Complete, ABranchReturn, branchBnotlowerC },
+ { Complete, ABranchReturn, branchCnotlowerA },
+ { Complete, ABranchReturn, branchDnotlowerC },
+ { Complete, ABranchReturn, branchAnotgreaterB },
+ { Complete, ABranchReturn, branchBnotgreaterC },
+ { Complete, ABranchReturn, branchCnotgreaterA },
+ { Complete, ABranchReturn, branchDnotgreaterC }
+ }, { //9
+ { Opcode9a, AdrA },
+ { Opcode9a, AdrA },
+ { Opcode9a, AdrA },
+ { Opcode9a, AdrA },
+ { Opcode9a, AdrA },
+ { Opcode9a, AdrA },
+ { Opcode9a, AdrA },
+ { Opcode9a, AdrA },
+ { Opcode9b, AdrB },
+ { Opcode9b, AdrB },
+ { Opcode9b, AdrB },
+ { Opcode9b, AdrB },
+ { Opcode9b, AdrB },
+ { Opcode9b, AdrB },
+ { Opcode9b, AdrB },
+ { Opcode9b, AdrB },
+ }, { //9a
+ { Complete, xBranchReturn, branchAequalsB },
+ { Complete, xBranchReturn, branchBequalsC },
+ { Complete, xBranchReturn, branchAequalsC },
+ { Complete, xBranchReturn, branchCequalsD },
+ { Complete, xBranchReturn, branchAdiffersB },
+ { Complete, xBranchReturn, branchBdiffersC },
+ { Complete, xBranchReturn, branchAdiffersC },
+ { Complete, xBranchReturn, branchCdiffersD },
+ { Complete, xBranchReturn, branchAzero },
+ { Complete, xBranchReturn, branchBzero },
+ { Complete, xBranchReturn, branchCzero },
+ { Complete, xBranchReturn, branchDzero },
+ { Complete, xBranchReturn, branchAnotzero },
+ { Complete, xBranchReturn, branchBnotzero },
+ { Complete, xBranchReturn, branchCnotzero },
+ { Complete, xBranchReturn, branchDnotzero }
+ }, { //9b
+ { Complete, xBranchReturn, branchAgreaterB },
+ { Complete, xBranchReturn, branchBgreaterC },
+ { Complete, xBranchReturn, branchCgreaterA },
+ { Complete, xBranchReturn, branchDgreaterC },
+ { Complete, xBranchReturn, branchAlowerB },
+ { Complete, xBranchReturn, branchBlowerC },
+ { Complete, xBranchReturn, branchClowerA },
+ { Complete, xBranchReturn, branchDlowerC },
+ { Complete, xBranchReturn, branchAnotlowerB },
+ { Complete, xBranchReturn, branchBnotlowerC },
+ { Complete, xBranchReturn, branchCnotlowerA },
+ { Complete, xBranchReturn, branchDnotlowerC },
+ { Complete, xBranchReturn, branchAnotgreaterB },
+ { Complete, xBranchReturn, branchBnotgreaterC },
+ { Complete, xBranchReturn, branchCnotgreaterA },
+ { Complete, xBranchReturn, branchDnotgreaterC }
+ }, { //A
+ { OpcodeAa, AdrA },
+ { OpcodeAa, AdrA },
+ { OpcodeAa, AdrA },
+ { OpcodeAa, AdrA },
+ { OpcodeAa, AdrA },
+ { OpcodeAa, AdrA },
+ { OpcodeAa, AdrA },
+ { OpcodeAa, AdrA },
+ { OpcodeAb, AdrB },
+ { OpcodeAb, AdrB },
+ { OpcodeAb, AdrB },
+ { OpcodeAb, AdrB },
+ { OpcodeAb, AdrB },
+ { OpcodeAb, AdrB },
+ { OpcodeAb, AdrB },
+ { OpcodeAb, AdrB },
+ }, { //Aa
+ { Complete, AdrNone, AaddB },
+ { Complete, AdrNone, BaddC },
+ { Complete, AdrNone, CaddA },
+ { Complete, AdrNone, DaddC },
+ { Complete, AdrNone, AaddA },
+ { Complete, AdrNone, BaddB },
+ { Complete, AdrNone, CaddC },
+ { Complete, AdrNone, DaddD },
+ { Complete, AdrNone, BaddA },
+ { Complete, AdrNone, CaddB },
+ { Complete, AdrNone, AaddC },
+ { Complete, AdrNone, CaddD },
+ { Complete, AdrNone, decA },
+ { Complete, AdrNone, decB },
+ { Complete, AdrNone, decC },
+ { Complete, AdrNone, decD },
+ }, { //Ab
+ { Complete, AdrNone, clearA },
+ { Complete, AdrNone, clearB },
+ { Complete, AdrNone, clearC },
+ { Complete, AdrNone, clearD },
+ { Complete, AdrNone, AcopyB },
+ { Complete, AdrNone, BcopyC },
+ { Complete, AdrNone, CcopyA },
+ { Complete, AdrNone, DcopyC },
+ { Complete, AdrNone, BcopyA },
+ { Complete, AdrNone, CcopyB },
+ { Complete, AdrNone, AcopyC },
+ { Complete, AdrNone, CcopyD },
+ { Complete, AdrNone, AswapB },
+ { Complete, AdrNone, BswapC },
+ { Complete, AdrNone, CswapA },
+ { Complete, AdrNone, DswapC }
+ }, { //B
+ { OpcodeBa, AdrA },
+ { OpcodeBa, AdrA },
+ { OpcodeBa, AdrA },
+ { OpcodeBa, AdrA },
+ { OpcodeBa, AdrA },
+ { OpcodeBa, AdrA },
+ { OpcodeBa, AdrA },
+ { OpcodeBa, AdrA },
+ { OpcodeBb, AdrB },
+ { OpcodeBb, AdrB },
+ { OpcodeBb, AdrB },
+ { OpcodeBb, AdrB },
+ { OpcodeBb, AdrB },
+ { OpcodeBb, AdrB },
+ { OpcodeBb, AdrB },
+ { OpcodeBb, AdrB },
+ }, { //Ba
+ { Complete, AdrNone, AsubB },
+ { Complete, AdrNone, BsubC },
+ { Complete, AdrNone, CsubA },
+ { Complete, AdrNone, DsubC },
+ { Complete, AdrNone, incA },
+ { Complete, AdrNone, incB },
+ { Complete, AdrNone, incC },
+ { Complete, AdrNone, incD },
+ { Complete, AdrNone, BsubA },
+ { Complete, AdrNone, CsubB },
+ { Complete, AdrNone, AsubC },
+ { Complete, AdrNone, CsubD },
+ { Complete, AdrNone, AsubnB },
+ { Complete, AdrNone, BsubnC },
+ { Complete, AdrNone, CsubnA },
+ { Complete, AdrNone, DsubnC },
+ }, { //Bb
+ { Complete, AdrNone, Ashiftleft },
+ { Complete, AdrNone, Bshiftleft },
+ { Complete, AdrNone, Cshiftleft },
+ { Complete, AdrNone, Dshiftleft },
+ { Complete, AdrNone, Ashiftright },
+ { Complete, AdrNone, Bshiftright },
+ { Complete, AdrNone, Cshiftright },
+ { Complete, AdrNone, Dshiftright },
+ { Complete, AdrNone, negateA },
+ { Complete, AdrNone, negateB },
+ { Complete, AdrNone, negateC },
+ { Complete, AdrNone, negateD },
+ { Complete, AdrNone, notA },
+ { Complete, AdrNone, notB },
+ { Complete, AdrNone, notC },
+ { Complete, AdrNone, notD }
+ }, { //C
+ { Complete, FieldA, AaddB },
+ { Complete, FieldA, BaddC },
+ { Complete, FieldA, CaddA },
+ { Complete, FieldA, DaddC },
+ { Complete, FieldA, AaddA },
+ { Complete, FieldA, BaddB },
+ { Complete, FieldA, CaddC },
+ { Complete, FieldA, DaddD },
+ { Complete, FieldA, BaddA },
+ { Complete, FieldA, CaddB },
+ { Complete, FieldA, AaddC },
+ { Complete, FieldA, CaddD },
+ { Complete, FieldA, decA },
+ { Complete, FieldA, decB },
+ { Complete, FieldA, decC },
+ { Complete, FieldA, decD }
+ }, { //D
+ { Complete, FieldA, clearA },
+ { Complete, FieldA, clearB },
+ { Complete, FieldA, clearC },
+ { Complete, FieldA, clearD },
+ { Complete, FieldA, AcopyB },
+ { Complete, FieldA, BcopyC },
+ { Complete, FieldA, CcopyA },
+ { Complete, FieldA, DcopyC },
+ { Complete, FieldA, BcopyA },
+ { Complete, FieldA, CcopyB },
+ { Complete, FieldA, AcopyC },
+ { Complete, FieldA, CcopyD },
+ { Complete, FieldA, AswapB },
+ { Complete, FieldA, BswapC },
+ { Complete, FieldA, CswapA },
+ { Complete, FieldA, DswapC }
+ }, { //E
+ { Complete, FieldA, AsubB },
+ { Complete, FieldA, BsubC },
+ { Complete, FieldA, CsubA },
+ { Complete, FieldA, DsubC },
+ { Complete, FieldA, incA },
+ { Complete, FieldA, incB },
+ { Complete, FieldA, incC },
+ { Complete, FieldA, incD },
+ { Complete, FieldA, BsubA },
+ { Complete, FieldA, CsubB },
+ { Complete, FieldA, AsubC },
+ { Complete, FieldA, CsubD },
+ { Complete, FieldA, AsubnB },
+ { Complete, FieldA, BsubnC },
+ { Complete, FieldA, CsubnA },
+ { Complete, FieldA, DsubnC }
+ }, { //F
+ { Complete, FieldA, Ashiftleft },
+ { Complete, FieldA, Bshiftleft },
+ { Complete, FieldA, Cshiftleft },
+ { Complete, FieldA, Dshiftleft },
+ { Complete, FieldA, Ashiftright },
+ { Complete, FieldA, Bshiftright },
+ { Complete, FieldA, Cshiftright },
+ { Complete, FieldA, Dshiftright },
+ { Complete, FieldA, negateA },
+ { Complete, FieldA, negateB },
+ { Complete, FieldA, negateC },
+ { Complete, FieldA, negateD },
+ { Complete, FieldA, notA },
+ { Complete, FieldA, notB },
+ { Complete, FieldA, notC },
+ { Complete, FieldA, notD }
+ }
+};
+
+static const int field_adr_af[]=
+{ FieldP, FieldWP, FieldXS, FieldX, FieldS, FieldM, FieldB, FieldW, 0, 0, 0, 0, 0, 0, 0, FieldA };
+
+static const int field_adr_a[]=
+{ FieldP, FieldWP, FieldXS, FieldX, FieldS, FieldM, FieldB, FieldW};
+
+static const int field_adr_b[]=
+{ FieldP, FieldWP, FieldXS, FieldX, FieldS, FieldM, FieldB, FieldW };
+
+unsigned saturn_dasm(char *dst, offs_t pc, const UINT8 *oprom, const UINT8 *opram)
+{
+ int adr=0;
+
+ int cont=1; // operation still not complete disassembled
+ char bin[10]; int binsize=0; // protocollizing fetched nibbles
+ char number[17];
+ OPCODE *level=opcodes[0]; //pointer to current digit
+ int op; // currently fetched nibble
+ int pos = 0;
+
+ int i,c,v;
+
+ while (cont)
+ {
+ op = oprom[pos++];
+ level+=op;
+ switch (level->sel) {
+ case Illegal:
+ cont=0;
+ bin[binsize++]=number_2_hex[op];
+ bin[binsize]=0;
+ sprintf(dst, "???%s",bin);
+ break;
+ default:
+ bin[binsize++]=number_2_hex[op];
+ switch (level->adr) {
+ case AdrNone: break;
+ case AdrA:
+ adr=field_adr_a[op];
+ break;
+ case AdrAF:
+ adr=field_adr_af[op];
+ break;
+ case AdrB:
+ adr=field_adr_b[op&7];
+ break;
+ default:
+ cont = 0;
+ bin[binsize++]=number_2_hex[op];
+ bin[binsize]=0;
+ sprintf(dst, "???%s",bin);
+ break;
+ }
+ break;
+ case Complete:
+ cont=0;
+ switch (level->adr==AdrNone?adr:level->adr) {
+ case AdrNone:
+ strcpy(dst, mnemonics[level->mnemonic].name[set]);
+ break;
+ case Imm:
+ sprintf(dst, mnemonics[level->mnemonic].name[set], oprom[pos++]);
+ break;
+ case ImmCount:
+ sprintf(dst, mnemonics[level->mnemonic].name[set], oprom[pos++]+1);
+ break;
+ case AdrCount: // mnemonics have string %s for address field
+ snprintf(number,sizeof(number),"%x",oprom[pos++]+1);
+ sprintf(dst, mnemonics[level->mnemonic].name[set], number);
+ break;
+ case Imm2:
+ v=oprom[pos++];
+ v|=oprom[pos++]<<4;
+ sprintf(dst, mnemonics[level->mnemonic].name[set], v);
+ break;
+ case Imm4:
+ v=oprom[pos++];
+ v|=oprom[pos++]<<4;
+ v|=oprom[pos++]<<8;
+ v|=oprom[pos++]<<12;
+ sprintf(dst, mnemonics[level->mnemonic].name[set], v);
+ break;
+ case Imm5:
+ v=oprom[pos++];
+ v|=oprom[pos++]<<4;
+ v|=oprom[pos++]<<8;
+ v|=oprom[pos++]<<12;
+ v|=oprom[pos++]<<16;
+ sprintf(dst, mnemonics[level->mnemonic].name[set], v);
+ break;
+ case ImmCload:
+ c=i=oprom[pos++];
+ number[i+1]=0;
+ for (;i>=0; i--) number[i]=number_2_hex[oprom[pos++]];
+ sprintf(dst, mnemonics[level->mnemonic].name[set], c+1, number);
+ break;
+ case Dis3:
+ SATURN_PEEKOP_DIS12(v);
+ c=(pc+pos-3+v)%0xfffff;
+ sprintf(dst, mnemonics[level->mnemonic].name[set], c );
+ break;
+ case Dis3Call:
+ SATURN_PEEKOP_DIS12(v);
+ c=(pc+pos-3+v)%0xfffff;
+ sprintf(dst, mnemonics[level->mnemonic].name[set], c );
+ break;
+ case Dis4:
+ SATURN_PEEKOP_DIS16(v);
+ c=(pc+pos-4+v)%0xfffff;
+ sprintf(dst, mnemonics[level->mnemonic].name[set], c );
+ break;
+ case Dis4Call:
+ SATURN_PEEKOP_DIS16(v);
+ c=(pc+pos-4+v)%0xfffff;
+ sprintf(dst, mnemonics[level->mnemonic].name[set], c );
+ break;
+ case Abs:
+ SATURN_PEEKOP_ADR(v);
+ sprintf(dst, mnemonics[level->mnemonic].name[set], v );
+ break;
+ case BranchReturn:
+ SATURN_PEEKOP_DIS8(v);
+ if (v==0) {
+ strcpy(dst, mnemonics[level->mnemonic+1].name[set]);
+ } else {
+ c=(pc+pos-2+v)&0xfffff;
+ sprintf(dst, mnemonics[level->mnemonic].name[set], c);
+ }
+ break;
+ case ABranchReturn:
+ SATURN_PEEKOP_DIS8(v);
+ if (v==0) {
+ sprintf(dst, mnemonics[level->mnemonic+1].name[set], A);
+ } else {
+ c=(pc+pos-2+v)&0xfffff;
+ sprintf(dst, mnemonics[level->mnemonic].name[set], A, c);
+ }
+ break;
+ case xBranchReturn:
+ SATURN_PEEKOP_DIS8(v);
+ if (v==0) {
+ sprintf(dst, mnemonics[level->mnemonic+1].name[set], field_2_string(adr));
+ } else {
+ c=(pc+pos-2+v)&0xfffff;
+ sprintf(dst, mnemonics[level->mnemonic].name[set], field_2_string(adr), c);
+ }
+ break;
+ case TestBranchRet:
+ i=oprom[pos++];
+ SATURN_PEEKOP_DIS8(v);
+ if (v==0) {
+ sprintf(dst, mnemonics[level->mnemonic+1].name[set], i);
+ } else {
+ c=(pc+pos-2+v)&0xfffff;
+ sprintf(dst, mnemonics[level->mnemonic].name[set], i, c);
+ }
+ break;
+ case ImmBranch:
+ i=oprom[pos++];
+ SATURN_PEEKOP_DIS8(v);
+ c=(pc+pos-2+v)&0xfffff;
+ sprintf(dst, mnemonics[level->mnemonic].name[set], i, c);
+ break;
+ case FieldP:
+ sprintf(dst, mnemonics[level->mnemonic].name[set], P );
+ break;
+ case FieldWP:
+ sprintf(dst, mnemonics[level->mnemonic].name[set], WP );
+ break;
+ case FieldXS:
+ sprintf(dst, mnemonics[level->mnemonic].name[set], XS );
+ break;
+ case FieldX:
+ sprintf(dst, mnemonics[level->mnemonic].name[set], X );
+ break;
+ case FieldS:
+ sprintf(dst, mnemonics[level->mnemonic].name[set], S );
+ break;
+ case FieldM:
+ sprintf(dst, mnemonics[level->mnemonic].name[set], M );
+ break;
+ case FieldB:
+ sprintf(dst, mnemonics[level->mnemonic].name[set], B );
+ break;
+ case FieldA:
+ sprintf(dst, mnemonics[level->mnemonic].name[set], A );
+ break;
+ case FieldW:
+ sprintf(dst, mnemonics[level->mnemonic].name[set], W );
+ break;
+ case AdrA:
+ sprintf(dst, mnemonics[level->mnemonic].name[set], adr_a[oprom[pos++]] );
+ break;
+ case AdrAF:
+ sprintf(dst, mnemonics[level->mnemonic].name[set], adr_af[oprom[pos++]] );
+ break;
+ case AdrB:
+ sprintf(dst, mnemonics[level->mnemonic].name[set], adr_b[oprom[pos++]&0x7] );
+ break;
+ }
+ break;
+ }
+ level = opcodes[level->sel];
+ }
+
+ return pos;
+}