From 98a8e739479b1339c5de45a1b1c9da3b8060ee15 Mon Sep 17 00:00:00 2001 From: Aaron Giles Date: Thu, 22 May 2008 03:09:01 +0000 Subject: [PATCH] From: Antoine Mine [mailto:Antoine.Mine@ens.fr] Subject: saturn CPU patch Dear MAMEDev, The attached patch corrects several bugs in the emulation of the saturn CPU. These corrections are needed to make new HP48 drivers (to be submitted to MESS imminently) work. AFAIK, MESS is the only place where this CPU is used, so, the patch should not cause any regression in MAME. The patch is against 0125u1. Best regards, - Antoine Mine --- .gitattributes | 1 - src/emu/cpu/cpu.mak | 3 +- src/emu/cpu/saturn/sat.h | 22 - src/emu/cpu/saturn/satops.c | 987 ++++++++++++++++------------------ src/emu/cpu/saturn/sattable.c | 264 ++++++--- src/emu/cpu/saturn/saturn.c | 314 ++++++----- src/emu/cpu/saturn/saturn.h | 38 +- src/emu/cpu/saturn/saturnds.c | 246 +++++---- 8 files changed, 975 insertions(+), 900 deletions(-) delete mode 100644 src/emu/cpu/saturn/sat.h diff --git a/.gitattributes b/.gitattributes index 2b6bfafacae..c8ca150983f 100644 --- a/.gitattributes +++ b/.gitattributes @@ -329,7 +329,6 @@ src/emu/cpu/s2650/2650dasm.c svneol=native#text/plain src/emu/cpu/s2650/s2650.c svneol=native#text/plain src/emu/cpu/s2650/s2650.h svneol=native#text/plain src/emu/cpu/s2650/s2650cpu.h svneol=native#text/plain -src/emu/cpu/saturn/sat.h svneol=native#text/plain src/emu/cpu/saturn/satops.c svneol=native#text/plain src/emu/cpu/saturn/sattable.c svneol=native#text/plain src/emu/cpu/saturn/saturn.c svneol=native#text/plain diff --git a/src/emu/cpu/cpu.mak b/src/emu/cpu/cpu.mak index b7b5e1773f4..31e249b6c05 100644 --- a/src/emu/cpu/cpu.mak +++ b/src/emu/cpu/cpu.mak @@ -1328,8 +1328,7 @@ endif $(CPUOBJ)/saturn/saturn.o: $(CPUSRC)/saturn/saturn.c \ $(CPUSRC)/saturn/sattable.c \ $(CPUSRC)/saturn/satops.c \ - $(CPUSRC)/saturn/saturn.h \ - $(CPUSRC)/saturn/sat.h + $(CPUSRC)/saturn/saturn.h diff --git a/src/emu/cpu/saturn/sat.h b/src/emu/cpu/saturn/sat.h deleted file mode 100644 index 8632468dc04..00000000000 --- a/src/emu/cpu/saturn/sat.h +++ /dev/null @@ -1,22 +0,0 @@ -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 index 578e3036994..da75169565f 100644 --- a/src/emu/cpu/saturn/satops.c +++ b/src/emu/cpu/saturn/satops.c @@ -1,61 +1,86 @@ #define IRQ_ADDRESS 0xf +#define saturn_assert(x) \ + do { if (!(x)) logerror("SATURN%d assertion failed: %s at %s:%i, pc=%05x\n", cpu_getactivecpu(), #x, __FILE__, __LINE__, saturn.pc); } while (0) + INLINE int READ_OP(void) { + UINT8 data; saturn_ICount-=3; - return cpu_readop(saturn.pc++); + data=cpu_readop(saturn.pc); + saturn_assert(data<0x10); + saturn.pc=(saturn.pc+1)&0xfffff; + return data; } INLINE int READ_OP_ARG(void) { + UINT8 data; saturn_ICount-=3; - return cpu_readop_arg(saturn.pc++); + data=cpu_readop_arg(saturn.pc); + saturn_assert(data<0x10); + saturn.pc=(saturn.pc+1)&0xfffff; + return data; } INLINE int READ_OP_ARG8(void) { - return READ_OP_ARG()|(READ_OP_ARG()<<4); + int n0=READ_OP_ARG(); + int n1=READ_OP_ARG(); + return n0|(n1<<4); } INLINE INT8 READ_OP_DIS8(void) { - return READ_OP_ARG()|(READ_OP_ARG()<<4); + return (INT8)READ_OP_ARG8(); } INLINE int READ_OP_ARG12(void) { - return READ_OP_ARG()|(READ_OP_ARG()<<4)|(READ_OP_ARG()<<8); + int n0=READ_OP_ARG(); + int n1=READ_OP_ARG(); + int n2=READ_OP_ARG(); + return n0|(n1<<4)|(n2<<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; + int temp=READ_OP_ARG12(); + if (temp&0x800) temp-=0x1000; + return temp; } INLINE int READ_OP_ARG16(void) { - return READ_OP_ARG()|(READ_OP_ARG()<<4)|(READ_OP_ARG()<<8)|(READ_OP_ARG()<<12); + int n0=READ_OP_ARG(); + int n1=READ_OP_ARG(); + int n2=READ_OP_ARG(); + int n3=READ_OP_ARG(); + return n0|(n1<<4)|(n2<<8)|(n3<<12); } INLINE INT16 READ_OP_DIS16(void) { - return READ_OP_ARG()|(READ_OP_ARG()<<4)|(READ_OP_ARG()<<8)|(READ_OP_ARG()<<12); + return (INT16)READ_OP_ARG16(); } 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); + int n0=READ_OP_ARG(); + int n1=READ_OP_ARG(); + int n2=READ_OP_ARG(); + int n3=READ_OP_ARG(); + int n4=READ_OP_ARG(); + return n0|(n1<<4)|(n2<<8)|(n3<<12)|(n4<<16); } INLINE int READ_NIBBLE(SaturnAdr adr) { - int data; + UINT8 data; saturn_ICount-=3; - data = program_read_byte(adr); - if (saturn.config&&saturn.config->crc) saturn.config->crc(adr, data); + data=program_read_byte(adr&0xfffff); + saturn_assert(data<0x10); + if (saturn.config&&saturn.config->crc) saturn.config->crc(Machine, adr&0xfffff, data); return data; } @@ -71,34 +96,21 @@ INLINE int READ_12(SaturnAdr adr) 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); + 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); + 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); + saturn_ICount-=3; + saturn_assert(nib<0x10); + program_write_byte(adr&0xfffff,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 @@ -114,46 +126,55 @@ INLINE void WRITE_NIBBLE(SaturnAdr adr, SaturnNib nib) #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) +INLINE int S64_READ_X(int r) +{ + return saturn.reg[r][0]|(saturn.reg[r][1]<<4)|(saturn.reg[r][2]<<8); +} -#define S64_READ_XS(r) S64_READ_NIBBLE(r,2) -#define S64_WRITE_XS(r,v) S64_WRITE_NIBBLE(r,2,v) +INLINE int S64_READ_WORD(int r) +{ + return saturn.reg[r][0]|(saturn.reg[r][1]<<4)|(saturn.reg[r][2]<<8)|(saturn.reg[r][3]<<12); +} -#define S64_READ_S(r) S64_READ_NIBBLE(r,15) -#define S64_WRITE_S(r,v) S64_WRITE_NIBBLE(r,15,v) +INLINE int S64_READ_A(int r) +{ + return saturn.reg[r][0]|(saturn.reg[r][1]<<4)|(saturn.reg[r][2]<<8)|(saturn.reg[r][3]<<12)|(saturn.reg[r][4]<<16); +} -#define S64_READ_P(r) S64_READ_NIBBLE(r,saturn.p) -#define S64_WRITE_P(r,v) S64_WRITE_NIBBLE(r,saturn.p,v) +INLINE void S64_WRITE_X(int r, int v) +{ + saturn.reg[r][0]=v&0xf; + saturn.reg[r][1]=(v>>4)&0xf; + saturn.reg[r][2]=(v>>8)&0xf; +} -#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)) +INLINE void S64_WRITE_WORD(int r, int v) +{ + saturn.reg[r][0]=v&0xf; + saturn.reg[r][1]=(v>>4)&0xf; + saturn.reg[r][2]=(v>>8)&0xf; + saturn.reg[r][3]=(v>>12)&0xf; +} + +INLINE void S64_WRITE_A(int r, int v) +{ + saturn.reg[r][0]=v&0xf; + saturn.reg[r][1]=(v>>4)&0xf; + saturn.reg[r][2]=(v>>8)&0xf; + saturn.reg[r][3]=(v>>12)&0xf; + saturn.reg[r][4]=(v>>16)&0xf; +} -// 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; } @@ -161,79 +182,107 @@ 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) { - + LOG(( "SATURN#%d at %05x: INTON\n", cpu_getactivecpu(), saturn.pc-4 )); + saturn.irq_enable=1; + if (saturn.irq_state) + { + LOG(( "SATURN#%d set_irq_line(ASSERT)\n", cpu_getactivecpu())); + saturn.pending_irq=1; + } } INLINE void saturn_interrupt_off(void) { - + LOG(( "SATURN#%d at %05x: INTOFF\n", cpu_getactivecpu(), saturn.pc-4 )); + saturn.irq_enable=0; } INLINE void saturn_reset_interrupt(void) { - + LOG(( "SATURN#%d at %05x: RSI\n", cpu_getactivecpu(), saturn.pc-5 )); + if (saturn.config&&saturn.config->rsi) saturn.config->rsi(Machine); } INLINE void saturn_mem_reset(void) { - if (saturn.config->reset) saturn.config->reset(); + if (saturn.config&&saturn.config->reset) saturn.config->reset(Machine); } INLINE void saturn_mem_config(void) { - if (saturn.config->config) saturn.config->config(S64_READ_A(C)); + if (saturn.config&&saturn.config->config) saturn.config->config(Machine, S64_READ_A(C)); } INLINE void saturn_mem_unconfig(void) { - if (saturn.config->unconfig) saturn.config->unconfig(S64_READ_A(C)); + if (saturn.config&&saturn.config->unconfig) saturn.config->unconfig(Machine, S64_READ_A(C)); } -INLINE int saturn_mem_id(void) +int monitor_id; + +INLINE void saturn_mem_id(void) { - if (saturn.config->id) return saturn.config->id(); - return 0; + int id=0; + if (saturn.config&&saturn.config->id) id=saturn.config->id(Machine); + S64_WRITE_A(C,id); + monitor_id = id; } INLINE void saturn_shutdown(void) { + saturn.sleeping=1; + saturn.irq_enable=1; + LOG(( "SATURN#%d at %05x: SHUTDN\n", cpu_getactivecpu(), saturn.pc-3 )); } INLINE void saturn_bus_command_b(void) { + logerror( "SATURN#%d at %05x: BUSCB opcode not handled\n", cpu_getactivecpu(), saturn.pc-4 ); } INLINE void saturn_bus_command_c(void) { + logerror( "SATURN#%d at %05x: BUSCC opcode not handled\n", cpu_getactivecpu(), saturn.pc-3 ); } INLINE void saturn_bus_command_d(void) { + logerror( "SATURN#%d at %05x: BUSCD opcode not handled\n", cpu_getactivecpu(), saturn.pc-4 ); } INLINE void saturn_serial_request(void) { + logerror( "SATURN#%d at %05x: SREQ? opcode not handled\n", cpu_getactivecpu(), saturn.pc-3 ); } INLINE void saturn_out_c(void) { - if (saturn.config&&saturn.config->out) saturn.config->out(S64_READ_X(C)); + saturn.out=S64_READ_X(C); + if (saturn.config&&saturn.config->out) saturn.config->out(Machine, saturn.out); } INLINE void saturn_out_cs(void) { - if (saturn.config&&saturn.config->out) - saturn.config->out(S64_READ_NIBBLE(C,0)|(saturn.out&0xff0)); + saturn.out=(saturn.out&0xff0)|saturn.reg[C][0]; + if (saturn.config&&saturn.config->out) saturn.config->out(Machine, saturn.out); } +int monitor_in; + INLINE void saturn_in(int reg) { - if (saturn.config&&saturn.config->in) S64_WORD(reg,0)=saturn.config->in(); + int in = 0; + saturn_assert(reg>=0 && reg<9); + if (!(saturn.pc&1)) + logerror( "SATURN#%d at %05x: reg=IN opcode at odd addresse\n", + cpu_getactivecpu(), saturn.pc-3 ); + if (saturn.config&&saturn.config->in) in = saturn.config->in(Machine); + S64_WRITE_WORD(reg,in); + monitor_in = in; } INLINE void saturn_sethex(void) { saturn.decimal=0; } @@ -242,142 +291,69 @@ INLINE void saturn_setdec(void) { saturn.decimal=1; } /* st related */ INLINE void saturn_clear_st(void) { - saturn.st=0; + saturn.st&=0xf000; } INLINE void saturn_st_to_c(void) { - S64_WRITE_X(C, saturn.st&0xfff); + S64_WRITE_X(C,saturn.st); } INLINE void saturn_c_to_st(void) { - saturn.st=(saturn.st&~0xfff)|S64_READ_X(C); + saturn.st=(saturn.st&0xf000)|(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); + int t=saturn.st; + saturn.st=(t&0xf000)|(S64_READ_X(C)); + S64_WRITE_X(C,t); } +INLINE void saturn_jump_after_test(void) +{ + int 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_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; - } + saturn.st &= ~(1<<(READ_OP_ARG())); } 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; - } + saturn.st |= (1<<(READ_OP_ARG())); } 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); - } + saturn.carry=!((saturn.st>>(READ_OP_ARG()))&1); + saturn_jump_after_test(); } 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); - } + saturn.carry=(saturn.st>>(READ_OP_ARG()))&1; + saturn_jump_after_test(); } INLINE void saturn_hst_clear_bits(void) { - saturn.hst&=~READ_OP_ARG(); + saturn.hst&=~(READ_OP_ARG()); } INLINE void saturn_hst_bits_cleared(void) { - saturn.carry=!(saturn.hst&READ_OP_ARG()); + saturn.carry=!(saturn.hst&(READ_OP_ARG())); + saturn_jump_after_test(); } /* p related */ @@ -385,31 +361,31 @@ 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); + saturn.p=saturn.reg[C][nr]; + saturn.reg[C][nr]=t; } INLINE void saturn_p_to_c(void) { int nr=READ_OP_ARG(); - S64_WRITE_NIBBLE(C,nr,saturn.p); + saturn.reg[C][nr]=saturn.p; } INLINE void saturn_c_to_p(void) { int nr=READ_OP_ARG(); - saturn.p=S64_READ_NIBBLE(C,nr); + saturn.p=saturn.reg[C][nr]; } INLINE void saturn_dec_p(void) { saturn.carry=saturn.p==0; - saturn.p=saturn.p-1; + saturn.p=(saturn.p-1)&0xf; } INLINE void saturn_inc_p(void) { - saturn.p=saturn.p+1; + saturn.p=(saturn.p+1)&0xf; saturn.carry=saturn.p==0; } @@ -420,39 +396,19 @@ INLINE void saturn_load_p(void) 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); - } + saturn.carry=saturn.p==(READ_OP_ARG()); + saturn_jump_after_test(); } 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); - } + saturn.carry=saturn.p!=(READ_OP_ARG()); + saturn_jump_after_test(); } INLINE void saturn_ca_p_1(void) { - int a=S64_READ_A(C)+1+saturn.p; + int a=(S64_READ_A(C))+1+saturn.p; saturn.carry=a>=0x100000; S64_WRITE_A(C,a&0xfffff); } @@ -461,13 +417,15 @@ INLINE void saturn_load_reg(int reg) { int count=READ_OP_ARG(); int pos=saturn.p; + saturn_assert(reg>=0 && reg<9); for (; count>=0; count--, pos=(pos+1)&0xf ) { - S64_WRITE_NIBBLE( reg, pos, READ_OP_ARG()); + saturn.reg[reg][pos]=READ_OP_ARG(); } } INLINE void saturn_jump(int adr, int jump) { + saturn_assert(adr>=0 && adr<0x100000); if (jump) { saturn.pc=adr; saturn_ICount-=10; @@ -477,6 +435,7 @@ INLINE void saturn_jump(int adr, int jump) INLINE void saturn_call(int adr) { + saturn_assert(adr>=0 && adr<0x100000); saturn_push(saturn.pc); saturn.pc=adr; // saturn_ICount-=10; @@ -510,6 +469,8 @@ INLINE void saturn_return_carry_clear(void) INLINE void saturn_return_interrupt(void) { + LOG(( "SATURN#%d at %05x: RTI\n", cpu_getactivecpu(), saturn.pc-2 )); + saturn.in_irq=0; /* set to 1 when an IRQ is taken */ saturn.pc=saturn_pop(); // saturn_ICount-=10; change_pc(saturn.pc); @@ -535,254 +496,172 @@ INLINE void saturn_push_c(void) INLINE void saturn_indirect_jump(int reg) { + saturn_assert(reg>=0 && reg<9); 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; + int i, t; + saturn_assert(reg>=0 && reg<9); + saturn_assert(begin>=0 && count>=0 && begin+count<=16); + saturn.carry=1; for (i=0; i=0 && reg<9); + saturn_assert(right>=0 && right<9); + saturn_assert(begin>=0 && count>=0 && begin+count<=16); + saturn.carry=1; for (i=0; i=0 && reg<9); + saturn_assert(begin>=0 && count>=0 && begin+count<=16); + saturn.carry=0; for (i=0; i=0 && reg<9); + saturn_assert(right>=0 && right<9); + saturn_assert(begin>=0 && count>=0 && begin+count<=16); + saturn.carry=0; for (i=0; i=0; i--) { - t=S64_READ_NIBBLE(reg, (begin+i)&0xf ); - t2=S64_READ_NIBBLE(right, (begin+i)&0xf ); - if (t<=t2) break; + int i, t,t2; + saturn_assert(reg>=0 && reg<9); + saturn_assert(right>=0 && right<9); + saturn_assert(begin>=0 && count>=0 && begin+count<=16); + saturn.carry=0; + for (i=count-1; i>=0; i--) { + t=saturn.reg[reg][begin+i]; + t2=saturn.reg[right][begin+i]; + if (t>t2) { saturn.carry=1; break; } + if (t=0; i--) { - t=S64_READ_NIBBLE(reg, (begin+i)&0xf ); - t2=S64_READ_NIBBLE(right, (begin+i)&0xf ); - if (t=0 && reg<9); + saturn_assert(right>=0 && right<9); + saturn_assert(begin>=0 && count>=0 && begin+count<=16); + saturn.carry=1; + for (i=count-1; i>=0; i--) { + t=saturn.reg[reg][begin+i]; + t2=saturn.reg[right][begin+i]; + if (tt2) 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); - } + saturn_jump_after_test(); } 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; + int i, t,t2; + saturn_assert(reg>=0 && reg<9); + saturn_assert(right>=0 && right<9); + saturn_assert(begin>=0 && count>=0 && begin+count<=16); + saturn.carry=1; + for (i=count-1; i>=0; i--) { + t=saturn.reg[reg][begin+i]; + t2=saturn.reg[right][begin+i]; + if (t>t2) { saturn.carry=0; break; } + if (t=0; i--) { - t=S64_READ_NIBBLE(reg, (begin+i)&0xf ); - t2=S64_READ_NIBBLE(right, (begin+i)&0xf ); - if (t>=t2) break; + int i, t,t2; + saturn_assert(reg>=0 && reg<9); + saturn_assert(right>=0 && right<9); + saturn_assert(begin>=0 && count>=0 && begin+count<=16); + saturn.carry=0; + for (i=count-1; i>=0; i--) { + t=saturn.reg[reg][begin+i]; + t2=saturn.reg[right][begin+i]; + if (tt2) 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); - } + saturn_jump_after_test(); } 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); - } + int op=READ_OP_ARG(); + saturn_assert(reg>=0 && reg<9); + saturn.carry=!((saturn.reg[reg][op>>2]>>(op&3))&1); + saturn_jump_after_test(); } 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); - } + int op=READ_OP_ARG(); + saturn_assert(reg>=0 && reg<9); + saturn.carry=(saturn.reg[reg][op>>2]>>(op&3))&1; + saturn_jump_after_test(); } INLINE void saturn_load_pc(int reg) { + saturn_assert(reg>=0 && reg<9); saturn.pc=S64_READ_A(reg); change_pc(saturn.pc); } INLINE void saturn_store_pc(int reg) { + saturn_assert(reg>=0 && reg<9); S64_WRITE_A(reg,saturn.pc); } INLINE void saturn_exchange_pc(int reg) { int temp=saturn.pc; + saturn_assert(reg>=0 && reg<9); saturn.pc=S64_READ_A(reg); change_pc(saturn.pc); S64_WRITE_A(reg, temp); @@ -793,6 +672,8 @@ INLINE void saturn_exchange_pc(int reg) *************************************************************************************/ INLINE void saturn_load_adr(int reg, int nibbles) { + saturn_assert(reg>=0 && reg<2); + saturn_assert(nibbles==2 || nibbles==4 || nibbles==5); switch (nibbles) { case 5: saturn.d[reg]=READ_OP_ARG20(); @@ -809,6 +690,7 @@ INLINE void saturn_load_adr(int reg, int nibbles) INLINE void saturn_add_adr(int reg) { int t=saturn.d[reg]+READ_OP_ARG()+1; + saturn_assert(reg>=0 && reg<2); saturn.d[reg]=t&0xfffff; saturn.carry=t>=0x100000; } @@ -816,33 +698,44 @@ INLINE void saturn_add_adr(int reg) INLINE void saturn_sub_adr(int reg) { int t=saturn.d[reg]-READ_OP_ARG()-1; + saturn_assert(reg>=0 && reg<2); saturn.d[reg]=t&0xfffff; saturn.carry=t<0; } INLINE void saturn_adr_to_reg(int adr, int reg) { + saturn_assert(reg>=0 && reg<9); + saturn_assert(adr>=0 && adr<2); S64_WRITE_A(reg,saturn.d[adr]); } INLINE void saturn_reg_to_adr(int reg, int adr) { + saturn_assert(reg>=0 && reg<9); + saturn_assert(adr>=0 && adr<2); 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); + saturn_assert(reg>=0 && reg<9); + saturn_assert(adr>=0 && adr<2); + S64_WRITE_WORD(reg,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); + saturn_assert(reg>=0 && reg<9); + saturn_assert(adr>=0 && adr<2); + saturn.d[adr]=(saturn.d[adr]&0xf0000)|S64_READ_WORD(reg); } INLINE void saturn_exchange_adr_reg(int adr, int reg) { int temp=saturn.d[adr]; + saturn_assert(reg>=0 && reg<9); + saturn_assert(adr>=0 && adr<2); saturn.d[adr]=S64_READ_A(reg); S64_WRITE_A(reg,temp); } @@ -850,15 +743,20 @@ INLINE void saturn_exchange_adr_reg(int adr, int reg) 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); + saturn_assert(reg>=0 && reg<9); + saturn_assert(adr>=0 && adr<2); + saturn.d[adr]=(saturn.d[adr]&0xf0000)|S64_READ_WORD(reg); + S64_WRITE_WORD(reg,temp); } INLINE void saturn_load_nibbles(int reg, int begin, int count, int adr) { int i; + saturn_assert(reg>=0 && reg<9); + saturn_assert(adr>=0 && adr<2); + saturn_assert(begin>=0 && count>=0 && begin+count<=16); for (i=0; i=0 && reg<9); + saturn_assert(adr>=0 && adr<2); + saturn_assert(begin>=0 && count>=0 && begin+count<=16); for (i=0; i=0 && reg<9); + saturn.reg[reg][arg>>2]&=~(1<<(arg&3)); } 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; - } + int arg=READ_OP_ARG(); + saturn_assert(reg>=0 && reg<9); + saturn.reg[reg][arg>>2]|=1<<(arg&3); } /**************************************************************************** @@ -922,8 +793,10 @@ INLINE void saturn_set_bit(int reg) INLINE void saturn_clear(int reg, int begin, int count) { int i; + saturn_assert(reg>=0 && reg<9); + saturn_assert(begin>=0 && count>=0 && begin+count<=16); for (i=0; i=0 && left<9); + saturn_assert(right>=0 && right<9); + saturn_assert(begin>=0 && count>=0 && begin+count<=16); for (i=0; i=0 && dest<9); + saturn_assert(src>=0 && src<9); + saturn_assert(begin>=0 && count>=0 && begin+count<=16); for (i=0; i=0 && reg<9); + saturn_assert(right>=0 && right<9); + saturn_assert(begin>=0 && count>=0 && begin+count<=16); + saturn.carry=0; for (i=0; i0x10) { - t=S64_READ_NIBBLE(reg, (begin+i)&0xf)+1; - } else { - t=S64_READ_NIBBLE(reg, (begin+i)&0xf); + t=saturn.reg[reg][begin+i]; + t+=saturn.reg[right][begin+i]; + t+=saturn.carry; + if (t>=base) { + saturn.carry=1; + t-=base; } - t+=S64_READ_NIBBLE(right, (begin+i)&0xf ); - S64_WRITE_NIBBLE(reg, (begin+i)&0xf , t&0x0f); + else saturn.carry=0; + saturn_assert(t>=0); saturn_assert(t=0 && reg<9); + saturn_assert(begin>=0 && count>=0 && begin+count<=16); + saturn_assert(count>1 || !saturn.decimal); /* SATURN bug */ for (i=0; i>4)+1; - S64_WRITE_NIBBLE(reg, (begin+i)&0xf, t&0x0f); + t=saturn.reg[reg][begin+i]; + t+=(right&0xf); + right>>=4; + if (t>=base) { + right++; + t-=base; + } + saturn_assert(t>=0); saturn_assert(t=0x10; + saturn.carry=right>0; } /**************************************************************************** @@ -993,32 +888,48 @@ INLINE void saturn_add_const(int reg, int begin, int count, SaturnNib right) ****************************************************************************/ INLINE void saturn_sub(int reg, int begin, int count, int right) { - int i, t=0; + int i, t; + int base=saturn.decimal?10:16; + saturn_assert(reg>=0 && reg<9); + saturn_assert(right>=0 && right<9); + saturn_assert(begin>=0 && count>=0 && begin+count<=16); + saturn.carry=0; for (i=0; i0x10) { - t=S64_READ_NIBBLE(reg, (begin+i)&0xf)-1; - } else { - t=S64_READ_NIBBLE(reg, (begin+i)&0xf ); + t=saturn.reg[reg][begin+i]; + t-=saturn.reg[right][begin+i]; + t-=saturn.carry; + if (t<0) { + saturn.carry=1; + t+=base; } - t-=S64_READ_NIBBLE(right, (begin+i)&0xf ); - S64_WRITE_NIBBLE(reg, (begin+i)&0xf, t&0x0f); + else saturn.carry=0; + saturn_assert(t>=0); saturn_assert(t=0 && reg<9); + saturn_assert(begin>=0 && count>=0 && begin+count<=16); + saturn_assert(count>1 || !saturn.decimal); /* SATURN bug */ for (i=0; i>4)+1; - S64_WRITE_NIBBLE(reg, (begin+i)&0xf, t&0x0f); + t=saturn.reg[reg][begin+i]; + t-=(right&0xf); + right>>=4; + if (t<0) { + right++; + t+=base; + } + saturn_assert(t>=0); saturn_assert(t=0) break; + if (!right) break; } - saturn.carry=t<0; + saturn.carry=right>0; } /**************************************************************************** @@ -1026,15 +937,25 @@ INLINE void saturn_sub_const(int reg, int begin, int count, int right) ****************************************************************************/ INLINE void saturn_sub2(int reg, int begin, int count, int right) { - int i, t=0; + int i, t; + int base=saturn.decimal?10:16; + saturn_assert(reg>=0 && reg<9); + saturn_assert(right>=0 && right<9); + saturn_assert(begin>=0 && count>=0 && begin+count<=16); + saturn.carry=0; for (i=0; i=0); saturn_assert(t=0) break; } - saturn.carry=t<0; } /**************************************************************************** @@ -1043,13 +964,17 @@ INLINE void saturn_sub2(int reg, int begin, int count, int right) INLINE void saturn_increment(int reg, int begin, int count) { int i, t=0; + int base=saturn.decimal?10:16; + saturn_assert(reg>=0 && reg<9); + saturn_assert(begin>=0 && count>=0 && begin+count<=16); for (i=0; i=base) saturn.reg[reg][begin+i]=t-base; + else { saturn.reg[reg][begin+i]=t; break; } } + saturn.carry=t>=base; } /**************************************************************************** @@ -1058,14 +983,17 @@ INLINE void saturn_increment(int reg, int begin, int count) INLINE void saturn_decrement(int reg, int begin, int count) { int i, t=0; + int base=saturn.decimal?10:16; + saturn_assert(reg>=0 && reg<9); + saturn_assert(begin>=0 && count>=0 && begin+count<=16); for (i=0; i=0 && reg<9); + saturn_assert(begin>=0 && count>=0 && begin+count<=16); + saturn.carry=0; for (i=0; i=0 && reg<9); + saturn_assert(begin>=0 && count>=0 && begin+count<=16); + c=1; + saturn.carry=0; for (i=0; imax) n-=max+1; + else c=0; + saturn_assert(n>=0); saturn_assert(n<=max); + saturn.reg[reg][begin+i]=n&0xf; saturn_ICount-=2; } } @@ -1106,9 +1041,11 @@ INLINE void saturn_negate(int reg, int begin, int count) INLINE void saturn_or(int dest, int begin, int count, int src) { int i; + saturn_assert(dest>=0 && dest<9); + saturn_assert(src>=0 && src<9); + saturn_assert(begin>=0 && count>=0 && begin+count<=16); for (i=0; i=0 && dest<9); + saturn_assert(src>=0 && src<9); + saturn_assert(begin>=0 && count>=0 && begin+count<=16); for (i=0; i1; i--) { - S64_WRITE_NIBBLE(reg, (begin+i)&0xf, S64_READ_NIBBLE(reg,(begin+i-1)&0xf) ); + saturn_assert(reg>=0 && reg<9); + saturn_assert(begin>=0 && count>=0 && begin+count<=16); + if (saturn.reg[reg][begin+count-1]) saturn.hst|=SB; + for (i=count-1; i>=1; i--) { + saturn.reg[reg][begin+i]=saturn.reg[reg][begin+i-1]; saturn_ICount-=2; } - S64_WRITE_NIBBLE(reg, begin, 0); + saturn.reg[reg][begin]=0; saturn_ICount-=2; } @@ -1146,64 +1088,65 @@ INLINE void saturn_shift_nibble_left(int reg, int begin, int count) INLINE void saturn_shift_nibble_right(int reg, int begin, int count) { int i; + saturn_assert(reg>=0 && reg<9); + saturn_assert(begin>=0 && count>=0 && begin+count<=16); + if (saturn.reg[reg][begin]) saturn.hst|=SB; for (i=1; i=0 && reg<9); + for (i=15; i>=1; i--) { + saturn.reg[reg][i]=saturn.reg[reg][i-1]; + saturn_ICount-=2; + } + saturn.reg[reg][0]=x; saturn_ICount-=2; } /**************************************************************************** - rotate nibble left opers + rotate nibbles right 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; + int i, x=saturn.reg[reg][0]; + saturn_assert(reg>=0 && reg<9); + for (i=1; i<16; i++) { + saturn.reg[reg][i-1]=saturn.reg[reg][i]; + saturn_ICount-=2; + } + saturn.reg[reg][15]=x; + if (x) saturn.hst|=SB; + saturn_ICount-=2; } + /**************************************************************************** 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; + saturn_assert(reg>=0 && reg<9); + saturn_assert(begin>=0 && count>=0 && begin+count<=16); + for (i=count-1; i>=0; i--) { + t=saturn.reg[reg][begin+i]; + t|=(c<<4); c=t&1; - S64_WRITE_NIBBLE(reg, (begin+i-1)&0xf, t>>1); + saturn.reg[reg][begin+i]=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; i0", 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")); - } + /* advance time when sleeping */ + saturn_ICount -= 100; } else - if( saturn.pending_irq ) - saturn_take_irq(); + { + /* takes irq */ + if ( saturn.pending_irq && (!saturn.in_irq) ) + saturn_take_irq(); + + /* execute one instruction */ + saturn_instruction(); + } } while (saturn_ICount > 0); return cycles - saturn_ICount; } -#ifdef UNUSED_FUNCTION -void saturn_set_nmi_line(int state) + +static void saturn_set_nmi_line(int state) { - if (saturn.nmi_state == state) return; + if ( state == saturn.nmi_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())); + if ( state != CLEAR_LINE ) + { + LOG(( "SATURN#%d set_nmi_line(ASSERT)\n", cpu_getactivecpu())); saturn.pending_irq = 1; } } -void saturn_set_irq_callback(int (*callback)(int)) +static void saturn_set_irq_line(int state) { - saturn.irq_callback = callback; -} -#endif - -#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); + if ( state == saturn.irq_state ) return; + saturn.irq_state = state; + if ( state != CLEAR_LINE && saturn.irq_enable ) + { + LOG(( "SATURN#%d set_irq_line(ASSERT)\n", cpu_getactivecpu())); + saturn.pending_irq = 1; + } } -static void saturn_state_load(void *file) +static void saturn_set_wakeup_line(int state) { - 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); + if (saturn.sleeping && state==1) + { + LOG(( "SATURN#%d set_wakeup_line(ASSERT)\n", cpu_getactivecpu())); + if (saturn.irq_callback) (*saturn.irq_callback)(SATURN_WAKEUP_LINE); + saturn.sleeping = 0; + } } -#endif + + /************************************************************************** * Generic set_info **************************************************************************/ +static void IntReg64(Saturn64 r, INT64 d) +{ + int i; + for (i=0; i<16; i++) + r[i] = (d >> (4*i)) & 0xf; +} + + 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_INPUT_STATE + SATURN_NMI_LINE: saturn_set_nmi_line(info->i); break; + case CPUINFO_INT_INPUT_STATE + SATURN_IRQ_LINE: saturn_set_irq_line(info->i); break; + case CPUINFO_INT_INPUT_STATE + SATURN_WAKEUP_LINE: saturn_set_wakeup_line(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_A: IntReg64(saturn.reg[A], info->i); break; + case CPUINFO_INT_REGISTER + SATURN_B: IntReg64(saturn.reg[B], info->i); break; + case CPUINFO_INT_REGISTER + SATURN_C: IntReg64(saturn.reg[C], info->i); break; + case CPUINFO_INT_REGISTER + SATURN_D: IntReg64(saturn.reg[D], info->i); break; + case CPUINFO_INT_REGISTER + SATURN_R0: IntReg64(saturn.reg[R0], info->i); break; + case CPUINFO_INT_REGISTER + SATURN_R1: IntReg64(saturn.reg[R1], info->i); break; + case CPUINFO_INT_REGISTER + SATURN_R2: IntReg64(saturn.reg[R2], info->i); break; + case CPUINFO_INT_REGISTER + SATURN_R3: IntReg64(saturn.reg[R3], info->i); break; + case CPUINFO_INT_REGISTER + SATURN_R4: IntReg64(saturn.reg[R4], info->i); break; 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; @@ -299,6 +281,7 @@ static void saturn_set_info(UINT32 state, cpuinfo *info) 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; + case CPUINFO_INT_REGISTER + SATURN_SLEEPING: saturn.sleeping = info->i; } } @@ -306,6 +289,18 @@ static void saturn_set_info(UINT32 state, cpuinfo *info) * Generic get_info **************************************************************************/ +#define Reg64Data(s) s[15],s[14],s[13],s[12],s[11],s[10],s[9],s[8],s[7],s[6],s[5],s[4],s[3],s[2],s[1],s[0] +#define Reg64Format "%x %x%x%x%x%x%x%x %x%x%x %x%x%x%x%x" + +static INT64 Reg64Int(Saturn64 r) +{ + INT64 x = 0; + int i; + for (i=0; i<16; i++) + x |= (INT64) r[i] << (4*i); + return x; +} + void saturn_get_info(UINT32 state, cpuinfo *info) { switch (state) @@ -332,29 +327,27 @@ void saturn_get_info(UINT32 state, cpuinfo *info) 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_INPUT_STATE + SATURN_NMI_LINE: info->i = saturn.nmi_state; break; + case CPUINFO_INT_INPUT_STATE + SATURN_IRQ_LINE: 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_A: info->i = Reg64Int(saturn.reg[A]); break; + case CPUINFO_INT_REGISTER + SATURN_B: info->i = Reg64Int(saturn.reg[B]); break; + case CPUINFO_INT_REGISTER + SATURN_C: info->i = Reg64Int(saturn.reg[C]); break; + case CPUINFO_INT_REGISTER + SATURN_D: info->i = Reg64Int(saturn.reg[D]); break; + case CPUINFO_INT_REGISTER + SATURN_R0: info->i = Reg64Int(saturn.reg[R0]); break; + case CPUINFO_INT_REGISTER + SATURN_R1: info->i = Reg64Int(saturn.reg[R1]); break; + case CPUINFO_INT_REGISTER + SATURN_R2: info->i = Reg64Int(saturn.reg[R2]); break; + case CPUINFO_INT_REGISTER + SATURN_R3: info->i = Reg64Int(saturn.reg[R3]); break; + case CPUINFO_INT_REGISTER + SATURN_R4: info->i = Reg64Int(saturn.reg[R4]); break; + 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; @@ -367,6 +360,7 @@ void saturn_get_info(UINT32 state, cpuinfo *info) 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; + case CPUINFO_INT_REGISTER + SATURN_SLEEPING: info->i = saturn.sleeping; /* --- the following bits of info are returned as pointers to data or functions --- */ case CPUINFO_PTR_SET_INFO: info->setinfo = saturn_set_info; break; @@ -391,17 +385,16 @@ void saturn_get_info(UINT32 state, cpuinfo *info) 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_A: sprintf(info->s = cpuintrf_temp_str(), "A: " Reg64Format, Reg64Data(saturn.reg[A]));break; + case CPUINFO_STR_REGISTER + SATURN_B: sprintf(info->s = cpuintrf_temp_str(), "B: " Reg64Format, Reg64Data(saturn.reg[B]));break; + case CPUINFO_STR_REGISTER + SATURN_C: sprintf(info->s = cpuintrf_temp_str(), "C: " Reg64Format, Reg64Data(saturn.reg[C]));break; + case CPUINFO_STR_REGISTER + SATURN_D: sprintf(info->s = cpuintrf_temp_str(), "D: " Reg64Format, Reg64Data(saturn.reg[D]));break; + case CPUINFO_STR_REGISTER + SATURN_R0: sprintf(info->s = cpuintrf_temp_str(), "R0: " Reg64Format, Reg64Data(saturn.reg[R0]));break; + case CPUINFO_STR_REGISTER + SATURN_R1: sprintf(info->s = cpuintrf_temp_str(), "R1: " Reg64Format, Reg64Data(saturn.reg[R1]));break; + case CPUINFO_STR_REGISTER + SATURN_R2: sprintf(info->s = cpuintrf_temp_str(), "R2: " Reg64Format, Reg64Data(saturn.reg[R2]));break; + case CPUINFO_STR_REGISTER + SATURN_R3: sprintf(info->s = cpuintrf_temp_str(), "R3: " Reg64Format, Reg64Data(saturn.reg[R3]));break; + case CPUINFO_STR_REGISTER + SATURN_R4: sprintf(info->s = cpuintrf_temp_str(), "R4: " Reg64Format, Reg64Data(saturn.reg[R4]));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; @@ -414,7 +407,8 @@ void saturn_get_info(UINT32 state, cpuinfo *info) 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; + case CPUINFO_STR_REGISTER + SATURN_IRQ_STATE: sprintf(info->s = cpuintrf_temp_str(), "IRQ:%c%c%c%i", saturn.in_irq?'S':'.', saturn.irq_enable?'e':'.', saturn.pending_irq?'p':'.', saturn.irq_state); break; + case CPUINFO_STR_FLAGS: sprintf(info->s = cpuintrf_temp_str(), "%c%c", saturn.decimal?'D':'.', saturn.carry ? 'C':'.'); break; + case CPUINFO_STR_REGISTER + SATURN_SLEEPING: sprintf(info->s = cpuintrf_temp_str(), "sleep:%c", saturn.sleeping?'S':'.'); break; } } diff --git a/src/emu/cpu/saturn/saturn.h b/src/emu/cpu/saturn/saturn.h index 6bf164a1533..e302f5b7a66 100644 --- a/src/emu/cpu/saturn/saturn.h +++ b/src/emu/cpu/saturn/saturn.h @@ -6,6 +6,8 @@ * * Copyright Peter Trauner, all rights reserved. * + * Modified by Antoine Mine' + * * - 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. @@ -49,15 +51,37 @@ HP38G 09/??/95 1LT8 Yorke 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); + void (*out)(running_machine*,int); + int (*in)(running_machine*); + void (*reset)(running_machine*); + void (*config)(running_machine*,int v); + void (*unconfig)(running_machine*,int v); + int (*id)(running_machine*); + void (*crc)(running_machine*,int addr, int data); + void (*rsi)(running_machine*); } SATURN_CONFIG; +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_OUT, + SATURN_CARRY, + SATURN_ST, + SATURN_HST, + + SATURN_IRQ_STATE, + SATURN_SLEEPING, +}; + +#define SATURN_IRQ_LINE 0 +#define SATURN_NMI_LINE 1 +#define SATURN_WAKEUP_LINE 2 + #ifdef ENABLE_DEBUGGER unsigned saturn_dasm(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram); #endif /* ENABLE_DEBUGGER */ diff --git a/src/emu/cpu/saturn/saturnds.c b/src/emu/cpu/saturn/saturnds.c index dc92b7b7e29..a4cd921429f 100644 --- a/src/emu/cpu/saturn/saturnds.c +++ b/src/emu/cpu/saturn/saturnds.c @@ -1,11 +1,13 @@ /***************************************************************************** * - * saturn.c + * saturnds.c * portable saturn emulator interface * (hp calculators) * * Copyright Peter Trauner, all rights reserved. * + * Modified by Antoine Mine' + * * - 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. @@ -24,7 +26,8 @@ #include "debugger.h" #include "saturn.h" -#include "sat.h" + +#define SATURN_HP_MNEMONICS #if defined SATURN_HP_MNEMONICS // class/hp mnemonics @@ -51,7 +54,7 @@ static const char *const adr_af[]= { P, WP, XS, X, S, M, B, W, 0, 0, 0, 0, 0, 0, 0, A }; static const char *const adr_a[]= -{ P, WP, XS, X, S, M, B, W }; + { 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' }; @@ -80,8 +83,12 @@ typedef enum { CcopyP, PcopyC, sreq, CswapP, inton, AloadImm, buscb, - clearAbit, setAbit, Abitclear, Abitset, - clearCbit, setCbit, Cbitclear, Cbitset, + clearAbit, setAbit, + branchAbitclear, returnAbitclear, + branchAbitset, returnAbitset, + clearCbit, setCbit, + branchCbitclear, returnCbitclear, + branchCbitset, returnCbitset, PCloadA, buscd, PCloadC, intoff, rsi, jumpA, jumpC, PCcopyA, PCcopyC, AcopyPC, CcopyPC, @@ -132,7 +139,7 @@ typedef enum { branchDnotgreaterC, returnDnotgreaterC, SetHexMode, SetDecMode, - PopC, PushC, + PushC, PopC, D0loadImm2, D0loadImm4, D0loadImm5, D1loadImm2, D1loadImm4, D1loadImm5, @@ -232,11 +239,15 @@ static const struct { { { "Abit=0 %x", "CLRB %x,A" } }, { { "Abit=1 %x", "SETB %x,A" } }, { { "?Abit=0 %x,%05x", "BRBC %x,A,%05x" } }, + { { "?Abit=0 %x,rtn", "RETBC %x,A" } }, { { "?Abit=1 %x,%05x", "BRBS %x,A,%05x" } }, + { { "?Abit=1 %x,rtn", "RETBS %x,A" } }, { { "Cbit=0 %x", "CLRB %x,C" } }, { { "Cbit=1 %x", "SETB %x,C" } }, { { "?Cbit=0 %x,%05x", "BRBC %x,C,%05x" } }, + { { "?Cbit=0 %x,rtn", "RETBC %x,C" } }, { { "?Cbit=1 %x,%05x", "BRBS %x,C,%05x" } }, + { { "?Cbit=1 %x,rtn", "RETBS %x,C" } }, { { "PC=(A)", "JUMP.A @A" } }, { { "!buscd", "!BUSCD" } }, { { "PC=(C)", "JUMP.A @C" } }, @@ -252,83 +263,83 @@ static const struct { { { "HST=0 %x", "CLRHST %x" } }, { { "?HST=0 %x,%05x", "BRBCHST %x,%05x" } }, - { { "?HST=0 %x", "RETBCHST %x" } }, + { { "?HST=0 %x,rtn", "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=0 %x,rtn", "RETBC ST,%x" } }, { { "?ST=1 %x,%05x", "BRBS ST,%x,%05x" } }, - { { "?ST=1 %x", "RETBS ST,%x" } }, + { { "?ST=1 %x,rtn", "RETBS ST,%x" } }, { { "?P# %x,%05x", "BRNE P,%x,%05x" } }, - { { "?P# %x", "RETNE P,%x" } }, + { { "?P# %x,rtn", "RETNE P,%x" } }, { { "?P= %x,%05x", "BREQ P,%x,%05x" } }, - { { "?P= %x", "RETEQ P,%x" } }, + { { "?P= %x,rtn", "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 %s,%05x", "BREQ.%-2s A,B,%05x" } }, + { { "?A=B %s,rtn", "RETEQ.%-2s A,B" } }, + { { "?B=C %s,%05x", "BREQ.%-2s B,C,%05x" } }, + { { "?B=C %s,rtn", "RETEQ.%-2s B,C" } }, + { { "?A=C %s,%05x", "BREQ.%-2s A,C,%05x" } }, + { { "?A=C %s,rtn", "RETEQ.%-2s A,C" } }, + { { "?C=D %s,%05x", "BREQ.%-2s C,D,%05x" } }, + { { "?C=D %s,rtn", "RETEQ.%-2s C,D" } }, + { { "?A#B %s,%05x", "BRNE.%-2s A,B,%05x" } }, + { { "?A#B %s,rtn", "RETNE.%-2s A,B" } }, + { { "?B#C %s,%05x", "BRNE.%-2s B,C,%05x" } }, + { { "?B#C %s,rtn", "RETNE.%-2s B,C" } }, + { { "?A#C %s,%05x", "BRNE.%-2s A,C,%05x" } }, + { { "?A#C %s,rtn", "RETNE.%-2s A,C" } }, + { { "?C#D %s,%05x", "BRNE.%-2s C,D,%05x" } }, + { { "?C#D %s,rtn", "RETNE.%-2s C,D" } }, + { { "?A=0 %s,%05x", "BRZ.%-2s A,%05x" } }, + { { "?A=0 %s,rtn", "RETZ.%-2s A" } }, + { { "?B=0 %s,%05x", "BRZ.%-2s B,%05x" } }, + { { "?B=0 %s,rtn", "RETZ.%-2s B" } }, + { { "?C=0 %s,%05x", "BRZ.%-2s C,%05x" } }, + { { "?C=0 %s,rtn", "RETZ.%-2s C" } }, + { { "?D=0 %s,%05x", "BRZ.%-2s D,%05x" } }, + { { "?D=0 %s,rtn", "RETZ.%-2s D" } }, + { { "?A#0 %s,%05x", "BRNZ.%-2s A,%05x" } }, + { { "?A#0 %s,rtn", "RETNZ.%-2s A" } }, + { { "?B#0 %s,%05x", "BRNZ.%-2s B,%05x" } }, + { { "?B#0 %s,rtn", "RETNZ.%-2s B" } }, + { { "?C#0 %s,%05x", "BRNZ.%-2s C,%05x" } }, + { { "?C#0 %s,rtn", "RETNZ.%-2s C" } }, + { { "?D#0 %s,%05x", "BRNZ.%-2s D,%05x" } }, + { { "?D#0 %s,rtn", "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", "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" } }, + { { "?A>B %s,%05x", "BRGT.%-2s A,B,%05x" } }, + { { "?A>B %s,rtn", "RETGT.%-2s A,B" } }, + { { "?B>C %s,%05x", "BRGT.%-2s B,C,%05x" } }, + { { "?B>C %s,rtn", "RETGT.%-2s B,C" } }, + { { "?C>A %s,%05x", "BRGT.%-2s C,A,%05x" } }, + { { "?C>A %s,rtn", "RETGT.%-2s C,A" } }, + { { "?D>C %s,%05x", "BRGT.%-2s D,C,%05x" } }, + { { "?D>C %s,rtn", "RETGT.%-2s D,C" } }, + { { "?A=B %s,%05x", "BRGE.%-2s A,B,%05x" } }, + { { "?A>=B %s,rtn", "RETGE.%-2s A,B" } }, + { { "?B>=C %s,%05x", "BRGE.%-2s B,C,%05x" } }, + { { "?B>=C %s,rtn", "RETGE.%-2s B,C" } }, + { { "?C>=A %s,%05x", "BRGE.%-2s C,A,%05x" } }, + { { "?C>=A %s,rtn", "RETGE.%-2s C,A" } }, + { { "?D>=C %s,%05x", "BRGE.%-2s D,C,%05x" } }, + { { "?D>=C %s,rtn", "RETGE.%-2s D,C" } }, + { { "?A<=B %s,%05x", "BRLE.%-2s A,B,%05x" } }, + { { "?A<=B %s,rtn", "RETLE.%-2s A,B" } }, + { { "?B<=C %s,%05x", "BRLE.%-2s B,C,%05x" } }, + { { "?B<=C %s,rtn", "RETLE.%-2s B,C" } }, + { { "?C<=A %s,%05x", "BRLE.%-2s C,A,%05x" } }, + { { "?C<=A %s,rtn", "RETLE.%-2s C,A" } }, + { { "?D<=C %s,%05x", "BRLE.%-2s D,C,%05x" } }, + { { "?D<=C %s,rtn", "RETLE.%-2s D,C" } }, { { "sethex", "SETHEX" } }, { { "setdec", "SETDEC" } }, @@ -456,19 +467,19 @@ static const struct { { { "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" } }, + { { "Asrb %s", "SRB.%-2s A" } }, + { { "Bsrb %s", "SRB.%-2s B" } }, + { { "Csrb %s", "SRB.%-2s C" } }, + { { "Dsrb %s", "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" } }, + { { "Asrc %s", "RRN.%-2s A" } }, + { { "Bsrc %s", "RRN.%-2s B" } }, + { { "Csrc %s", "RRN.%-2s C" } }, + { { "Dsrc %s", "RRN.%-2s D" } }, { { "A=A+B %s", "ADD.%-2s B,A" } }, { { "B=B+C %s", "ADD.%-2s C,B" } }, @@ -566,7 +577,8 @@ typedef struct { 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 + FieldP, FieldWP, FieldXS, FieldX, FieldS, FieldM, FieldB, FieldW, FieldA, + AdrImmCount } adr; MNEMONICS mnemonic; } OPCODE; @@ -613,8 +625,8 @@ static const OPCODE opcodes[][0x10]= { { Complete, AdrNone, ReturnClearCarry }, { Complete, AdrNone, SetHexMode }, { Complete, AdrNone, SetDecMode }, - { Complete, AdrNone, PopC }, { Complete, AdrNone, PushC }, + { Complete, AdrNone, PopC }, { Complete, AdrNone, clearST }, { Complete, AdrNone, CcopyST }, { Complete, AdrNone, STcopyC }, @@ -817,12 +829,12 @@ static const OPCODE opcodes[][0x10]= { { Complete, AdrNone, buscb }, { Complete, Imm, clearAbit }, { Complete, Imm, setAbit }, - { Complete, ImmBranch, Abitclear }, - { Complete, ImmBranch, Abitset }, + { Complete, TestBranchRet, branchAbitclear }, + { Complete, TestBranchRet, branchAbitset }, { Complete, Imm, clearCbit }, { Complete, Imm, setCbit }, - { Complete, ImmBranch, Cbitclear }, - { Complete, ImmBranch, Cbitset }, + { Complete, TestBranchRet, branchCbitclear }, + { Complete, TestBranchRet, branchCbitset }, { Complete, AdrNone, PCloadA }, { Complete, AdrNone, buscd }, { Complete, AdrNone, PCloadC }, @@ -833,12 +845,12 @@ static const OPCODE opcodes[][0x10]= { }, { //81 { Complete, FieldW, AshiftleftCarry }, { Complete, FieldW, BshiftleftCarry }, - { Complete, FieldW, DshiftleftCarry }, + { Complete, FieldW, CshiftleftCarry }, { Complete, FieldW, DshiftleftCarry }, { Complete, FieldW, AshiftrightCarry }, - { Complete, FieldW, AshiftrightCarry }, - { Complete, FieldW, AshiftrightCarry }, - { Complete, FieldW, AshiftrightCarry }, + { Complete, FieldW, BshiftrightCarry }, + { Complete, FieldW, CshiftrightCarry }, + { Complete, FieldW, DshiftrightCarry }, { Opcode818 }, { Opcode819 }, { Opcode81A }, @@ -865,15 +877,22 @@ static const OPCODE opcodes[][0x10]= { { 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 + { Complete, AdrImmCount, AaddImm }, + { Complete, AdrImmCount, BaddImm }, + { Complete, AdrImmCount, CaddImm }, + { Complete, AdrImmCount, DaddImm }, + { Illegal }, + { Illegal }, + { Illegal }, + { Illegal }, + { Complete, AdrImmCount, AsubImm }, + { Complete, AdrImmCount, BsubImm }, + { Complete, AdrImmCount, CsubImm }, + { Complete, AdrImmCount, DsubImm }, + { Illegal }, + { Illegal }, + { Illegal }, + { Illegal }, }, { //819 { Opcode819a, AdrAF }, { Opcode819a, AdrAF }, @@ -1269,7 +1288,7 @@ unsigned saturn_dasm(char *dst, offs_t pc, const UINT8 *oprom, const UINT8 *opra while (cont) { - op = oprom[pos++]; + op = oprom[pos++] & 0xf; level+=op; switch (level->sel) { case Illegal: @@ -1311,6 +1330,9 @@ unsigned saturn_dasm(char *dst, offs_t pc, const UINT8 *oprom, const UINT8 *opra case ImmCount: sprintf(dst, mnemonics[level->mnemonic].name[set], oprom[pos++]+1); break; + case AdrImmCount: + sprintf(dst, mnemonics[level->mnemonic].name[set], field_2_string(adr), 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); @@ -1336,29 +1358,29 @@ unsigned saturn_dasm(char *dst, offs_t pc, const UINT8 *oprom, const UINT8 *opra sprintf(dst, mnemonics[level->mnemonic].name[set], v); break; case ImmCload: - c=i=oprom[pos++]; + c=i=oprom[pos++] & 0xf; number[i+1]=0; - for (;i>=0; i--) number[i]=number_2_hex[oprom[pos++]]; + for (;i>=0; i--) number[i]=number_2_hex[oprom[pos++] & 0xf]; sprintf(dst, mnemonics[level->mnemonic].name[set], c+1, number); break; case Dis3: SATURN_PEEKOP_DIS12(v); - c=(pc+pos-3+v)%0xfffff; + 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; + c=(pc+pos+v)&0xfffff; sprintf(dst, mnemonics[level->mnemonic].name[set], c ); break; case Dis4: SATURN_PEEKOP_DIS16(v); - c=(pc+pos-4+v)%0xfffff; + 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; + c=(pc+pos+v)&0xfffff; sprintf(dst, mnemonics[level->mnemonic].name[set], c ); break; case Abs: @@ -1436,13 +1458,13 @@ unsigned saturn_dasm(char *dst, offs_t pc, const UINT8 *oprom, const UINT8 *opra sprintf(dst, mnemonics[level->mnemonic].name[set], W ); break; case AdrA: - sprintf(dst, mnemonics[level->mnemonic].name[set], adr_a[oprom[pos++]] ); + sprintf(dst, mnemonics[level->mnemonic].name[set], adr_a[oprom[pos++] & 0x7] ); break; case AdrAF: - sprintf(dst, mnemonics[level->mnemonic].name[set], adr_af[oprom[pos++]] ); + sprintf(dst, mnemonics[level->mnemonic].name[set], adr_af[oprom[pos++] & 0xf] ); break; case AdrB: - sprintf(dst, mnemonics[level->mnemonic].name[set], adr_b[oprom[pos++]&0x7] ); + sprintf(dst, mnemonics[level->mnemonic].name[set], adr_b[oprom[pos++] & 0x7] ); break; } break;