diff options
author | 2007-12-17 15:19:59 +0000 | |
---|---|---|
committer | 2007-12-17 15:19:59 +0000 | |
commit | 7b77f1218624ea26dbb2efd85a19f795f5d4e02e (patch) | |
tree | 19209304095572b4fd61c2a2d6a5aa75c4e471ad /src/emu/cpu/saturn | |
parent | 3da7f476068b3ffef713218ba2fc1bd5030f2c38 (diff) |
Initial checkin of MAME 0.121.mame0121
Diffstat (limited to 'src/emu/cpu/saturn')
-rw-r--r-- | src/emu/cpu/saturn/sat.h | 22 | ||||
-rw-r--r-- | src/emu/cpu/saturn/satops.c | 1209 | ||||
-rw-r--r-- | src/emu/cpu/saturn/sattable.c | 921 | ||||
-rw-r--r-- | src/emu/cpu/saturn/saturn.c | 422 | ||||
-rw-r--r-- | src/emu/cpu/saturn/saturn.h | 68 | ||||
-rw-r--r-- | src/emu/cpu/saturn/saturnds.c | 1454 |
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; +} |