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
This commit is contained in:
Aaron Giles 2008-05-22 03:09:01 +00:00
parent bb9fec0f86
commit 98a8e73947
8 changed files with 975 additions and 900 deletions

1
.gitattributes vendored
View File

@ -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

View File

@ -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

View File

@ -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)

File diff suppressed because it is too large Load Diff

View File

@ -1,9 +1,11 @@
static const int adr_a_begin[]={
-1, -1, BEGIN_XS, BEGIN_X, BEGIN_S, BEGIN_M, BEGIN_B, BEGIN_W,
-1, -1, -1, -1, -1, -1, -1, -1,
};
static const int adr_a_count[]={
-1, -1, COUNT_XS, COUNT_X, COUNT_S, COUNT_M, COUNT_B, COUNT_W,
-1, -1, -1, -1, -1, -1, -1, -1,
};
static const int adr_b_begin[]={
@ -26,12 +28,37 @@ static const int adr_af_count[]={
-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 };
static const int reg_left[] ={A,B,C,D, B,C,A,C, I,I,I,I, I,I,I,I};
static const int reg_right[]={B,C,A,C, A,B,C,D, I,I,I,I, I,I,I,I};
static const int add_left[] ={A,B,C,D, I,I,I,I, B,C,A,C, I,I,I,I};
static const int add_right[]={B,C,A,C, I,I,I,I, A,B,C,D, I,I,I,I};
static const int sub_left[] ={A,B,C,D, I,I,I,I, B,C,A,C, A,B,C,D};
static const int sub_right[]={B,C,A,C, I,I,I,I, A,B,C,D, B,C,A,C};
void saturn_invalid3( int op1, int op2, int op3 )
{
logerror( "SATURN#%d invalid opcode %x%x%x at %05x\n",
cpu_getactivecpu(), op1, op2, op3, saturn.pc-3 );
}
void saturn_invalid4( int op1, int op2, int op3, int op4 )
{
logerror( "SATURN#%d invalid opcode %x%x%x%x at %05x\n",
cpu_getactivecpu(), op1, op2, op3, op4, saturn.pc-4 );
}
void saturn_invalid5( int op1, int op2, int op3, int op4, int op5 )
{
logerror( "SATURN#%d invalid opcode %x%x%x%x%x at %05x\n",
cpu_getactivecpu(), op1, op2, op3, op4, op5, saturn.pc-5 );
}
void saturn_invalid6( int op1, int op2, int op3, int op4, int op5, int op6 )
{
logerror( "SATURN#%d invalid opcode %x%x%x%x%x%x at %05x\n",
cpu_getactivecpu(), op1, op2, op3, op4, op5, op6, saturn.pc-6 );
}
INLINE void saturn_instruction_0e(void)
{
@ -68,6 +95,9 @@ INLINE void saturn_instruction_0e(void)
break; //A=A!B xs
}
break;
default:
saturn_invalid3( 0, 0xe, adr );
break;
}
}
@ -84,6 +114,9 @@ static void saturn_instruction_1(void)
case 8: case 9: case 0xa: case 0xb: case 0xc:
saturn_copy(R0+(reg&7), BEGIN_W, COUNT_W, C);
break; // r0=c w
default:
saturn_invalid3( 1, adr, reg );
break;
}
break;
case 1:
@ -94,6 +127,9 @@ static void saturn_instruction_1(void)
case 8: case 9: case 0xa: case 0xb: case 0xc:
saturn_copy(C, BEGIN_W, COUNT_W, R0+(reg&7));
break; // c=r0 w
default:
saturn_invalid3( 1, adr, reg );
break;
}
break;
case 2:
@ -104,6 +140,9 @@ static void saturn_instruction_1(void)
case 8: case 9: case 0xa: case 0xb: case 0xc:
saturn_exchange(C, BEGIN_W, COUNT_W, R0+(reg&7));
break; // cr0ex w
default:
saturn_invalid3( 2, adr, reg );
break;
}
break;
case 3:
@ -159,6 +198,9 @@ static void saturn_instruction_1(void)
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;
default:
saturn_invalid4( 1, 5, oper, adr );
break;
}
break;
case 2: case 3: case 6: case 7:
@ -172,6 +214,9 @@ static void saturn_instruction_1(void)
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;
default:
saturn_invalid4( 1, 5, oper, adr );
break;
}
break;
case 8: saturn_store_nibbles(A, 0, READ_OP()+1, 0); break;
@ -184,21 +229,22 @@ static void saturn_instruction_1(void)
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 9: saturn_load_adr(0,2);break;
case 0xa: saturn_load_adr(0,4);break;
case 0xb: saturn_load_adr(0,5);break;
case 0xc: saturn_sub_adr(1);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;
}
}
static void saturn_instruction_80(void)
{
int op;
switch(READ_OP()) {
case 0: saturn_out_cs();break;
case 1: saturn_out_c();break;
@ -212,12 +258,13 @@ static void saturn_instruction_80(void)
switch(READ_OP()) {
case 0: saturn_interrupt_on();break;
case 1:
switch(READ_OP()) {
switch(op=READ_OP()) {
case 0: saturn_reset_interrupt();break;
default: saturn_invalid5( 8, 0, 8, 1, op ); break;
}
break;
case 2: saturn_load_reg(A);break; //la
case 3: saturn_bus_command_c();break;
case 3: saturn_bus_command_b();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;
@ -244,10 +291,10 @@ static void saturn_instruction_80(void)
static void saturn_instruction_81a(void)
{
int reg, adr;
int reg, adr,op;
switch(adr=READ_OP()) {
case 0:
switch(READ_OP()) {
switch(op=READ_OP()) {
case 0:
switch(reg=READ_OP()) {
case 0: case 1: case 2: case 3: case 4:
@ -256,6 +303,9 @@ static void saturn_instruction_81a(void)
case 8: case 9: case 0xa: case 0xb: case 0xc:
saturn_copy(R0+(reg&7),saturn.p,1,C);
break; //r0=c p
default:
saturn_invalid6( 8, 1, 0xa, adr, op, reg);
break;
}
break;
case 1:
@ -266,6 +316,9 @@ static void saturn_instruction_81a(void)
case 8: case 9: case 0xa: case 0xb: case 0xc:
saturn_copy(C,saturn.p,1,R0+(reg&7));
break; //c=r0 p
default:
saturn_invalid6( 8, 1, 0xa, adr, op, reg);
break;
}
break;
case 2:
@ -276,12 +329,18 @@ static void saturn_instruction_81a(void)
case 8: case 9: case 0xa: case 0xb: case 0xc:
saturn_exchange(C, saturn.p,1,R0+(reg&7));
break; // cr0ex p
default:
saturn_invalid6( 8, 1, 0xa, adr, op, reg);
break;
}
break;
default:
saturn_invalid5( 8, 1, 0xa, adr, op );
break;
}
break;
case 1:
switch(READ_OP()) {
switch(op=READ_OP()) {
case 0:
switch(reg=READ_OP()) {
case 0: case 1: case 2: case 3: case 4:
@ -290,6 +349,9 @@ static void saturn_instruction_81a(void)
case 8: case 9: case 0xa: case 0xb: case 0xc:
saturn_copy(R0+(reg&7),0,saturn.p+1,C);
break; //r0=c wp
default:
saturn_invalid6( 8, 1, 0xa, adr, op, reg);
break;
}
break;
case 1:
@ -300,6 +362,9 @@ static void saturn_instruction_81a(void)
case 8: case 9: case 0xa: case 0xb: case 0xc:
saturn_copy(C,0,saturn.p+1,R0+(reg&7));
break; //c=r0 wp
default:
saturn_invalid6( 8, 1, 0xa, adr, op, reg);
break;
}
break;
case 2:
@ -310,12 +375,18 @@ static void saturn_instruction_81a(void)
case 8: case 9: case 0xa: case 0xb: case 0xc:
saturn_exchange(C, 0, saturn.p+1, R0+(reg&7));
break; // cr0ex wp
default:
saturn_invalid6( 8, 1, 0xa, adr, op, reg);
break;
}
break;
default:
saturn_invalid5( 8, 1, 0xa, adr, op );
break;
}
break;
case 2: case 3: case 4: case 5: case 6: case 7: case 0xf:
switch(READ_OP()) {
switch(op=READ_OP()) {
case 0:
switch(reg=READ_OP()) {
case 0: case 1: case 2: case 3: case 4:
@ -324,6 +395,9 @@ static void saturn_instruction_81a(void)
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
default:
saturn_invalid6( 8, 1, 0xa, adr, op, reg);
break;
}
break;
case 1:
@ -334,6 +408,9 @@ static void saturn_instruction_81a(void)
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
default:
saturn_invalid6( 8, 1, 0xa, adr, op, reg);
break;
}
break;
case 2:
@ -344,10 +421,19 @@ static void saturn_instruction_81a(void)
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
default:
saturn_invalid6( 8, 1, 0xa, adr, op, reg);
break;
}
break;
default:
saturn_invalid5( 8, 1, 0xa, adr, op );
break;
}
break;
default:
saturn_invalid4( 8, 1, 0xa, adr );
break;
}
}
@ -368,17 +454,23 @@ static void saturn_instruction_81(void)
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);
saturn_sub_const(A+(reg&3), saturn.p, 1, READ_OP()+1);
break;
default:
saturn_invalid5( 8, 1, 8, adr, reg );
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);
saturn_add_const(A+reg, 0, 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);
saturn_sub_const(A+(reg&3), 0, saturn.p+1, READ_OP()+1);
break;
default:
saturn_invalid5( 8, 1, 8, adr, reg );
break;
}
break;
@ -388,10 +480,16 @@ static void saturn_instruction_81(void)
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);
saturn_sub_const(A+(reg&3), adr_af_begin[adr], adr_af_count[adr], READ_OP()+1);
break;
default:
saturn_invalid5( 8, 1, 8, adr, reg );
break;
}
break;
default:
saturn_invalid4( 8, 1, 8, adr );
break;
}
break;
case 9:
@ -401,6 +499,9 @@ static void saturn_instruction_81(void)
case 0: case 1: case 2: case 3:
saturn_shift_right(A+reg,saturn.p,1);
break; // asrb p
default:
saturn_invalid5( 8, 1, 9, adr, reg );
break;
}
break;
case 1:
@ -408,28 +509,38 @@ static void saturn_instruction_81(void)
case 0: case 1: case 2: case 3:
saturn_shift_right(A+reg, 0,saturn.p+1);
break; // asrb wp
default:
saturn_invalid5( 8, 1, 9, adr, reg );
break;
}
break;
case 2: /*case 3:*/ case 4: case 5: case 6:/* case 7:*/case 0xf:
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
default:
saturn_invalid5( 8, 1, 9, adr, reg );
break;
}
break;
default:
saturn_invalid4( 8, 1, 9, adr );
break;
}
break;
case 0xa:
saturn_instruction_81a();
break;
case 0xb:
switch(READ_OP()) {
switch(adr=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;
default: saturn_invalid4( 8, 1, reg, adr ); break;
}
break;
case 0xc: case 0xd: case 0xe: case 0xf:
@ -440,7 +551,7 @@ static void saturn_instruction_81(void)
static void saturn_instruction_8(void)
{
int oper;
int oper, adr;
switch(READ_OP()) {
case 0:
@ -489,10 +600,22 @@ static void saturn_instruction_8(void)
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;
case 0xc:
adr=READ_OP_DIS16();
saturn_jump((adr+saturn.pc-4)&0xfffff,1);
break;
case 0xd:
adr=READ_OP_ARG20();
saturn_jump(adr,1);
break;
case 0xe:
adr=READ_OP_DIS16();
saturn_call((adr+saturn.pc)&0xfffff);
break;
case 0xf:
adr=READ_OP_ARG20();
saturn_call(adr);
break;
}
}
@ -533,8 +656,7 @@ static void saturn_instruction_9(void)
break;
}
break;
case 2: case 3: case 4: case 5:
case 6: case 7:
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]);
@ -612,9 +734,8 @@ static void saturn_instruction_a(void)
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);
saturn_add(A+(reg&3), saturn.p, 1, A+(reg&3));
break;
case 0xc: case 0xd: case 0xe: case 0xf:
saturn_decrement(A+(reg&3), saturn.p, 1);
@ -625,13 +746,13 @@ static void saturn_instruction_a(void)
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]);
saturn_add(add_left[reg], 0, 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);
saturn_add(A+(reg&3), 0, saturn.p+1, A+(reg&3));
break;
case 0xc: case 0xd: case 0xe: case 0xf:
saturn_decrement(A+(reg&3), 1, saturn.p+1);
saturn_decrement(A+(reg&3), 0, saturn.p+1);
break;
}
break;
@ -642,7 +763,7 @@ static void saturn_instruction_a(void)
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]);
saturn_add(A+(reg&3), adr_a_begin[adr], adr_a_count[adr], A+(reg&3));
break;
case 0xc: case 0xd: case 0xe: case 0xf:
saturn_decrement(A+(reg&3), adr_a_begin[adr], adr_a_count[adr]);
@ -656,7 +777,7 @@ static void saturn_instruction_a(void)
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
saturn_copy(reg_right[reg&7], saturn.p,1,reg_left[reg&7]);
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]);
@ -670,7 +791,7 @@ static void saturn_instruction_a(void)
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
saturn_copy(reg_right[reg&7], 0, saturn.p+1, reg_left[reg&7]);
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]);
@ -684,12 +805,10 @@ static void saturn_instruction_a(void)
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
saturn_copy(reg_right[reg&7], adr_b_begin[adr], adr_b_count[adr], reg_left[reg&7]);
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]);
saturn_exchange(reg_left[reg&3], adr_b_begin[adr], adr_b_count[adr], reg_right[reg&3]);
break; // abex xs
}
break;
@ -705,12 +824,12 @@ static void saturn_instruction_b(void)
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]));
saturn_sub(sub_left[reg], saturn.p, 1, 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]));
saturn_sub2(sub_left[reg], saturn.p, 1, sub_right[reg]);
break;
}
break;
@ -718,12 +837,12 @@ static void saturn_instruction_b(void)
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]);
saturn_sub(sub_left[reg], 0, 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
saturn_increment(A+(reg&3), 0, 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]);
saturn_sub2(sub_left[reg], 0, saturn.p+1, sub_right[reg]);
break;
}
break;
@ -731,8 +850,7 @@ static void saturn_instruction_b(void)
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]);
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]);
@ -750,9 +868,9 @@ static void saturn_instruction_b(void)
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
saturn_negate(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
saturn_invert(A+(reg&3), saturn.p, 1); break; // A=-A-1 p
}
break;
case 9:
@ -762,9 +880,9 @@ static void saturn_instruction_b(void)
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
saturn_negate(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
saturn_invert(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:
@ -776,10 +894,10 @@ static void saturn_instruction_b(void)
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]);
saturn_negate(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]);
saturn_invert(A+(reg&3), adr_b_begin[adr], adr_b_count[adr]);
break;
}
break;
@ -806,16 +924,10 @@ static void saturn_instruction(void)
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 0xc: saturn_inc_p();break;
case 0xd: saturn_dec_p();break;
case 0xe: saturn_instruction_0e();break;
case 0xf: saturn_return_interrupt();break;
case 0xe:
saturn_instruction_0e();
break;
}
break;
case 1:
@ -824,12 +936,15 @@ static void saturn_instruction(void)
case 2:
saturn_load_p();
break;
case 3: saturn_load_reg(C);break; // lc
case 3:
saturn_load_reg(C);
break; // lc
case 4:
adr=READ_OP_DIS8();
if (adr==0) {
saturn_return(saturn.carry);
} else {
}
else {
saturn_jump((saturn.pc+adr-2)&0xfffff, saturn.carry);
}
break;
@ -837,7 +952,8 @@ static void saturn_instruction(void)
adr=READ_OP_DIS8();
if (adr==0) {
saturn_return(!saturn.carry);
} else {
}
else {
saturn_jump((saturn.pc+adr-2)&0xfffff,!saturn.carry);
}
break;
@ -866,7 +982,7 @@ static void saturn_instruction(void)
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);
saturn_add(A+(reg&3), BEGIN_A, COUNT_A, A+(reg&3));
break;
case 0xc: case 0xd: case 0xe: case 0xf:
saturn_decrement(A+(reg&3), BEGIN_A, COUNT_A);
@ -880,7 +996,7 @@ static void saturn_instruction(void)
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
saturn_copy(reg_right[reg&7], BEGIN_A, COUNT_A, reg_left[reg&7]);
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]);
@ -891,13 +1007,13 @@ static void saturn_instruction(void)
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]));
saturn_sub(sub_left[reg], BEGIN_A, COUNT_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]));
saturn_sub2(sub_left[reg], BEGIN_A, COUNT_A, sub_right[reg]);
break;
}
break;
@ -910,10 +1026,10 @@ static void saturn_instruction(void)
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);
saturn_negate(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);
saturn_invert(A+(reg&3),BEGIN_A, COUNT_A);
break; // A=-A-1 a
}
break;

View File

@ -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.
@ -22,7 +24,7 @@
#include "debugger.h"
#include "saturn.h"
#include "sat.h"
#include "deprecat.h" /* for Machine */
#define R0 0
#define R1 1
@ -33,18 +35,13 @@
#define B 6
#define C 7
#define D 8
#define I 9 // invalid
typedef int SaturnAdr; // 20 bit
typedef UINT8 SaturnNib; // 4 bit
typedef short SaturnX; // 12 bit
typedef INT64 SaturnM; // 48 bit
typedef UINT32 SaturnAdr; // 20 bit, packed
typedef UINT8 SaturnNib; // 4 bit
typedef union {
UINT8 b[8];
UINT16 w[4];
UINT32 d[2];
UINT64 q;
} Saturn64;
// 64 bit, unpacked (one nibble per byte)
typedef SaturnNib Saturn64[16];
#define VERBOSE 0
@ -52,38 +49,34 @@ typedef union {
/****************************************************************************
* The 6502 registers.
* The SATURN registers.
****************************************************************************/
typedef struct
{
SATURN_CONFIG *config;
Saturn64 reg[9]; //r0,r1,r2,r3,r4,a,b,c,d;
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 out; // 12 bit (packed)
UINT8 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;
SaturnNib hst; // hardware status 4 bit
#define XM 1 // external Modules missing
#define SB 2 // Sticky bit
#define SR 4 // Service Request
#define MP 8 // Module Pulled
UINT8 pending_irq; /* nonzero if an IRQ is pending */
UINT8 after_cli; /* pending IRQ and last insn cleared I */
UINT8 nmi_state;
UINT8 irq_state;
UINT8 irq_enable; /* INTON / INTOFF */
UINT8 in_irq; /* already servicing IRQ */
UINT8 pending_irq; /* IRQ is pending */
UINT8 sleeping; /* low-consumption state */
int (*irq_callback)(int irqline); /* IRQ callback */
} Saturn_Regs;
@ -94,6 +87,7 @@ static Saturn_Regs saturn;
/***************************************************************
* include the opcode macros, functions and tables
***************************************************************/
#include "satops.c"
#include "sattable.c"
@ -106,12 +100,39 @@ static Saturn_Regs saturn;
static void saturn_init(int index, int clock, const void *config, int (*irqcallback)(int))
{
saturn.config = (SATURN_CONFIG *) config;
saturn.irq_callback = irqcallback;
state_save_register_item_array("saturn",index,saturn.reg[R0]);
state_save_register_item_array("saturn",index,saturn.reg[R1]);
state_save_register_item_array("saturn",index,saturn.reg[R2]);
state_save_register_item_array("saturn",index,saturn.reg[R3]);
state_save_register_item_array("saturn",index,saturn.reg[R4]);
state_save_register_item_array("saturn",index,saturn.reg[A]);
state_save_register_item_array("saturn",index,saturn.reg[B]);
state_save_register_item_array("saturn",index,saturn.reg[C]);
state_save_register_item_array("saturn",index,saturn.reg[D]);
state_save_register_item_array("saturn",index,saturn.d);
state_save_register_item("saturn",index,saturn.pc);
state_save_register_item("saturn",index,saturn.oldpc);
state_save_register_item_array("saturn",index,saturn.rstk);
state_save_register_item("saturn",index,saturn.out);
state_save_register_item("saturn",index,saturn.carry);
state_save_register_item("saturn",index,saturn.st);
state_save_register_item("saturn",index,saturn.hst);
state_save_register_item("saturn",index,saturn.nmi_state);
state_save_register_item("saturn",index,saturn.irq_state);
state_save_register_item("saturn",index,saturn.irq_enable);
state_save_register_item("saturn",index,saturn.in_irq);
state_save_register_item("saturn",index,saturn.pending_irq);
state_save_register_item("saturn",index,saturn.sleeping);
}
static void saturn_reset(void)
{
saturn.stackpointer=0;
saturn.pc=0;
saturn.sleeping = 0;
saturn.irq_enable = 0;
saturn.in_irq = 0;
change_pc(saturn.pc);
}
@ -134,18 +155,16 @@ static void saturn_set_context (void *src)
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.in_irq = 1; /* reset by software, using RTI */
saturn.pending_irq = 0;
saturn_ICount -= 7;
saturn_push(saturn.pc);
saturn.pc=IRQ_ADDRESS;
LOG(("Saturn#%d takes IRQ ($%04x)\n", cpu_getactivecpu(), saturn.pc));
if (saturn.irq_callback) (*saturn.irq_callback)(SATURN_IRQ_LINE);
change_pc(saturn.pc);
}
static int saturn_execute(int cycles)
@ -160,133 +179,96 @@ static int saturn_execute(int cycles)
CALL_DEBUGGER(saturn.pc);
/* 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 )
if ( saturn.sleeping )
{
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"));
}
/* 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;
}
}

View File

@ -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 */

View File

@ -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", "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" } },
{ { "?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", "BRLT.%-2s A,B,%05x" } },
{ { "?A<B %s,rtn", "RETLT.%-2s A,B" } },
{ { "?B<C %s,%05x", "BRLT.%-2s B,C,%05x" } },
{ { "?B<C %s,rtn", "RETLT.%-2s B,C" } },
{ { "?C<A %s,%05x", "BRLT.%-2s C,A,%05x" } },
{ { "?C<A %s,rtn", "RETLT.%-2s C,A" } },
{ { "?D<C %s,%05x", "BRLT.%-2s D,C,%05x" } },
{ { "?D<C %s,rtn", "RETLT.%-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;