diff --git a/src/emu_emulate.c b/src/emu_emulate.c index 9a75225..8bb1aeb 100644 --- a/src/emu_emulate.c +++ b/src/emu_emulate.c @@ -552,1812 +552,13 @@ void load_addr( word_20* dat, long addr, int n ) } } -static inline bool _step_instruction_group_80( void ) -{ - int t, op3, op4, op5, op6; - unsigned char* REG; - long addr; - op3 = read_nibble( saturn.PC + 2 ); - switch ( op3 ) { - case 0: /* OUT=CS */ - saturn.PC += 3; - copy_register( saturn.OUT, saturn.C, OUTS_FIELD ); - /* check_out_register(); */ - return false; - case 1: /* OUT=C */ - saturn.PC += 3; - copy_register( saturn.OUT, saturn.C, OUT_FIELD ); - /* check_out_register(); */ - return false; - case 2: /* A=IN */ - saturn.PC += 3; - do_in(); - copy_register( saturn.A, saturn.IN, IN_FIELD ); - return false; - case 3: /* C=IN */ - saturn.PC += 3; - do_in(); - copy_register( saturn.C, saturn.IN, IN_FIELD ); - return false; - case 4: /* UNCNFG */ - saturn.PC += 3; - do_unconfigure(); - return false; - case 5: /* CONFIG */ - saturn.PC += 3; - do_configure(); - return false; - case 6: /* C=ID */ - saturn.PC += 3; - return get_identification(); - case 7: /* SHUTDN */ - saturn.PC += 3; - do_shutdown(); - return false; - case 8: - op4 = read_nibble( saturn.PC + 3 ); - switch ( op4 ) { - case 0: /* INTON */ - saturn.PC += 4; - do_inton(); - return false; - case 1: /* RSI... */ - op5 = read_nibble( saturn.PC + 4 ); - saturn.PC += 5; - do_reset_interrupt_system(); - return false; - case 2: /* LA... */ - op5 = read_nibble( saturn.PC + 4 ); - load_constant( saturn.A, op5 + 1, saturn.PC + 5 ); - saturn.PC += 6 + op5; - return false; - case 3: /* BUSCB */ - saturn.PC += 4; - return false; - case 4: /* ABIT=0 */ - op5 = read_nibble( saturn.PC + 4 ); - saturn.PC += 5; - clear_register_bit( saturn.A, op5 ); - return false; - case 5: /* ABIT=1 */ - op5 = read_nibble( saturn.PC + 4 ); - saturn.PC += 5; - set_register_bit( saturn.A, op5 ); - return false; - case 8: /* CBIT=0 */ - op5 = read_nibble( saturn.PC + 4 ); - saturn.PC += 5; - clear_register_bit( saturn.C, op5 ); - return false; - case 9: /* CBIT=1 */ - op5 = read_nibble( saturn.PC + 4 ); - saturn.PC += 5; - set_register_bit( saturn.C, op5 ); - return false; - case 6: /* ?ABIT=0 */ - case 7: /* ?ABIT=1 */ - case 0xa: /* ?CBIT=0 */ - case 0xb: /* ?CBIT=1 */ - op5 = read_nibble( saturn.PC + 4 ); - if ( op4 < 8 ) - REG = saturn.A; - else - REG = saturn.C; - if ( op4 == 6 || op4 == 0xa ) - t = 0; - else - t = 1; - saturn.CARRY = ( get_register_bit( REG, op5 ) == t ) ? 1 : 0; - if ( saturn.CARRY ) { - saturn.PC += 5; - op6 = read_nibbles( saturn.PC, 2 ); - if ( op6 ) { - if ( op6 & 0x80 ) - op6 |= jumpmasks[ 2 ]; - saturn.PC = ( saturn.PC + op6 ) & 0xfffff; - } else - saturn.PC = pop_return_addr(); - } else - saturn.PC += 7; - return false; - case 0xc: /* PC=(A) */ - addr = dat_to_addr( saturn.A ); - saturn.PC = read_nibbles( addr, 5 ); - return false; - case 0xd: /* BUSCD */ - saturn.PC += 4; - return false; - case 0xe: /* PC=(C) */ - addr = dat_to_addr( saturn.C ); - saturn.PC = read_nibbles( addr, 5 ); - return false; - case 0xf: /* INTOFF */ - saturn.PC += 4; - do_intoff(); - return false; - default: - return true; - } - case 9: /* C+P+1 */ - saturn.PC += 3; - add_p_plus_one( saturn.C ); - return false; - case 0xa: /* RESET */ - saturn.PC += 3; - do_reset(); - return false; - case 0xb: /* BUSCC */ - saturn.PC += 3; - return false; - case 0xc: /* C=P n */ - op4 = read_nibble( saturn.PC + 3 ); - saturn.PC += 4; - set_register_nibble( saturn.C, op4, saturn.P ); - return false; - case 0xd: /* P=C n */ - op4 = read_nibble( saturn.PC + 3 ); - saturn.PC += 4; - saturn.P = get_register_nibble( saturn.C, op4 ); - return false; - case 0xe: /* SREQ? */ - saturn.PC += 3; - saturn.C[ 0 ] = 0; - saturn.SR = 0; - return false; - case 0xf: /* CPEX n */ - op4 = read_nibble( saturn.PC + 3 ); - saturn.PC += 4; - t = get_register_nibble( saturn.C, op4 ); - set_register_nibble( saturn.C, op4, saturn.P ); - saturn.P = t; - return false; - default: - return true; - } -} - -static inline bool _step_instruction_group_1( void ) -{ - int op, op2, op3, op4; - - op2 = read_nibble( saturn.PC + 1 ); - switch ( op2 ) { - case 0: - op3 = read_nibble( saturn.PC + 2 ); - switch ( op3 ) { - case 0: /* saturn.R0=A */ - saturn.PC += 3; - copy_register( saturn.R0, saturn.A, W_FIELD ); - return false; - case 1: /* saturn.R1=A */ - case 5: - saturn.PC += 3; - copy_register( saturn.R1, saturn.A, W_FIELD ); - return false; - case 2: /* saturn.R2=A */ - case 6: - saturn.PC += 3; - copy_register( saturn.R2, saturn.A, W_FIELD ); - return false; - case 3: /* saturn.R3=A */ - case 7: - saturn.PC += 3; - copy_register( saturn.R3, saturn.A, W_FIELD ); - return false; - case 4: /* saturn.R4=A */ - saturn.PC += 3; - copy_register( saturn.R4, saturn.A, W_FIELD ); - return false; - case 8: /* saturn.R0=C */ - saturn.PC += 3; - copy_register( saturn.R0, saturn.C, W_FIELD ); - return false; - case 9: /* saturn.R1=C */ - case 0xd: - saturn.PC += 3; - copy_register( saturn.R1, saturn.C, W_FIELD ); - return false; - case 0xa: /* saturn.R2=C */ - case 0xe: - saturn.PC += 3; - copy_register( saturn.R2, saturn.C, W_FIELD ); - return false; - case 0xb: /* saturn.R3=C */ - case 0xf: - saturn.PC += 3; - copy_register( saturn.R3, saturn.C, W_FIELD ); - return false; - case 0xc: /* saturn.R4=C */ - saturn.PC += 3; - copy_register( saturn.R4, saturn.C, W_FIELD ); - return false; - default: - return true; - } - case 1: - op3 = read_nibble( saturn.PC + 2 ); - switch ( op3 ) { - case 0: /* A=R0 */ - saturn.PC += 3; - copy_register( saturn.A, saturn.R0, W_FIELD ); - return false; - case 1: /* A=R1 */ - case 5: - saturn.PC += 3; - copy_register( saturn.A, saturn.R1, W_FIELD ); - return false; - case 2: /* A=R2 */ - case 6: - saturn.PC += 3; - copy_register( saturn.A, saturn.R2, W_FIELD ); - return false; - case 3: /* A=R3 */ - case 7: - saturn.PC += 3; - copy_register( saturn.A, saturn.R3, W_FIELD ); - return false; - case 4: /* A=R4 */ - saturn.PC += 3; - copy_register( saturn.A, saturn.R4, W_FIELD ); - return false; - case 8: /* C=R0 */ - saturn.PC += 3; - copy_register( saturn.C, saturn.R0, W_FIELD ); - return false; - case 9: /* C=R1 */ - case 0xd: - saturn.PC += 3; - copy_register( saturn.C, saturn.R1, W_FIELD ); - return false; - case 0xa: /* C=R2 */ - case 0xe: - saturn.PC += 3; - copy_register( saturn.C, saturn.R2, W_FIELD ); - return false; - case 0xb: /* C=R3 */ - case 0xf: - saturn.PC += 3; - copy_register( saturn.C, saturn.R3, W_FIELD ); - return false; - case 0xc: /* C=R4 */ - saturn.PC += 3; - copy_register( saturn.C, saturn.R4, W_FIELD ); - return false; - default: - return true; - } - case 2: - op3 = read_nibble( saturn.PC + 2 ); - switch ( op3 ) { - case 0: /* AR0EX */ - saturn.PC += 3; - exchange_register( saturn.A, saturn.R0, W_FIELD ); - return false; - case 1: /* AR1EX */ - case 5: - saturn.PC += 3; - exchange_register( saturn.A, saturn.R1, W_FIELD ); - return false; - case 2: /* AR2EX */ - case 6: - saturn.PC += 3; - exchange_register( saturn.A, saturn.R2, W_FIELD ); - return false; - case 3: /* AR3EX */ - case 7: - saturn.PC += 3; - exchange_register( saturn.A, saturn.R3, W_FIELD ); - return false; - case 4: /* AR4EX */ - saturn.PC += 3; - exchange_register( saturn.A, saturn.R4, W_FIELD ); - return false; - case 8: /* CR0EX */ - saturn.PC += 3; - exchange_register( saturn.C, saturn.R0, W_FIELD ); - return false; - case 9: /* CR1EX */ - case 0xd: - saturn.PC += 3; - exchange_register( saturn.C, saturn.R1, W_FIELD ); - return false; - case 0xa: /* CR2EX */ - case 0xe: - saturn.PC += 3; - exchange_register( saturn.C, saturn.R2, W_FIELD ); - return false; - case 0xb: /* CR3EX */ - case 0xf: - saturn.PC += 3; - exchange_register( saturn.C, saturn.R3, W_FIELD ); - return false; - case 0xc: /* CR4EX */ - saturn.PC += 3; - exchange_register( saturn.C, saturn.R4, W_FIELD ); - return false; - default: - return true; - } - case 3: - op3 = read_nibble( saturn.PC + 2 ); - switch ( op3 ) { - case 0: /* D0=A */ - saturn.PC += 3; - register_to_address( saturn.A, &saturn.D0, 0 ); - return false; - case 1: /* D1=A */ - saturn.PC += 3; - register_to_address( saturn.A, &saturn.D1, 0 ); - return false; - case 2: /* AD0EX */ - saturn.PC += 3; - exchange_reg( saturn.A, &saturn.D0, A_FIELD ); - return false; - case 3: /* AD1EX */ - saturn.PC += 3; - exchange_reg( saturn.A, &saturn.D1, A_FIELD ); - return false; - case 4: /* D0=C */ - saturn.PC += 3; - register_to_address( saturn.C, &saturn.D0, 0 ); - return false; - case 5: /* D1=C */ - saturn.PC += 3; - register_to_address( saturn.C, &saturn.D1, 0 ); - return false; - case 6: /* CD0EX */ - saturn.PC += 3; - exchange_reg( saturn.C, &saturn.D0, A_FIELD ); - return false; - case 7: /* CD1EX */ - saturn.PC += 3; - exchange_reg( saturn.C, &saturn.D1, A_FIELD ); - return false; - case 8: /* D0=AS */ - saturn.PC += 3; - register_to_address( saturn.A, &saturn.D0, 1 ); - return false; - case 9: /* saturn.D1=AS */ - saturn.PC += 3; - register_to_address( saturn.A, &saturn.D1, 1 ); - return false; - case 0xa: /* AD0XS */ - saturn.PC += 3; - exchange_reg( saturn.A, &saturn.D0, IN_FIELD ); - return false; - case 0xb: /* AD1XS */ - saturn.PC += 3; - exchange_reg( saturn.A, &saturn.D1, IN_FIELD ); - return false; - case 0xc: /* D0=CS */ - saturn.PC += 3; - register_to_address( saturn.C, &saturn.D0, 1 ); - return false; - case 0xd: /* D1=CS */ - saturn.PC += 3; - register_to_address( saturn.C, &saturn.D1, 1 ); - return false; - case 0xe: /* CD0XS */ - saturn.PC += 3; - exchange_reg( saturn.C, &saturn.D0, IN_FIELD ); - return false; - case 0xf: /* CD1XS */ - saturn.PC += 3; - exchange_reg( saturn.C, &saturn.D1, IN_FIELD ); - return false; - default: - return true; - } - case 4: - op3 = read_nibble( saturn.PC + 2 ); - op = op3 < 8 ? 0xf : 6; - switch ( op3 & 7 ) { - case 0: /* DAT0=A */ - saturn.PC += 3; - store( saturn.D0, saturn.A, op ); - return false; - case 1: /* DAT1=A */ - saturn.PC += 3; - store( saturn.D1, saturn.A, op ); - return false; - case 2: /* A=DAT0 */ - saturn.PC += 3; - recall( saturn.A, saturn.D0, op ); - return false; - case 3: /* A=DAT1 */ - saturn.PC += 3; - recall( saturn.A, saturn.D1, op ); - return false; - case 4: /* DAT0=C */ - saturn.PC += 3; - store( saturn.D0, saturn.C, op ); - return false; - case 5: /* DAT1=C */ - saturn.PC += 3; - store( saturn.D1, saturn.C, op ); - return false; - case 6: /* C=DAT0 */ - saturn.PC += 3; - recall( saturn.C, saturn.D0, op ); - return false; - case 7: /* C=DAT1 */ - saturn.PC += 3; - recall( saturn.C, saturn.D1, op ); - return false; - default: - return true; - } - case 5: - op3 = read_nibble( saturn.PC + 2 ); - op4 = read_nibble( saturn.PC + 3 ); - if ( op3 >= 8 ) { - switch ( op3 & 7 ) { - case 0: /* DAT0=A */ - saturn.PC += 4; - store_n( saturn.D0, saturn.A, op4 + 1 ); - return false; - case 1: /* DAT1=A */ - saturn.PC += 4; - store_n( saturn.D1, saturn.A, op4 + 1 ); - return false; - case 2: /* A=DAT0 */ - saturn.PC += 4; - recall_n( saturn.A, saturn.D0, op4 + 1 ); - return false; - case 3: /* A=DAT1 */ - saturn.PC += 4; - recall_n( saturn.A, saturn.D1, op4 + 1 ); - return false; - case 4: /* DAT0=C */ - saturn.PC += 4; - store_n( saturn.D0, saturn.C, op4 + 1 ); - return false; - case 5: /* DAT1=C */ - saturn.PC += 4; - store_n( saturn.D1, saturn.C, op4 + 1 ); - return false; - case 6: /* C=DAT0 */ - saturn.PC += 4; - recall_n( saturn.C, saturn.D0, op4 + 1 ); - return false; - case 7: /* C=DAT1 */ - saturn.PC += 4; - recall_n( saturn.C, saturn.D1, op4 + 1 ); - return false; - default: - return true; - } - } else { - switch ( op3 ) { - case 0: /* DAT0=A */ - saturn.PC += 4; - store( saturn.D0, saturn.A, op4 ); - return false; - case 1: /* DAT1=A */ - saturn.PC += 4; - store( saturn.D1, saturn.A, op4 ); - return false; - case 2: /* A=DAT0 */ - saturn.PC += 4; - recall( saturn.A, saturn.D0, op4 ); - return false; - case 3: /* A=DAT1 */ - saturn.PC += 4; - recall( saturn.A, saturn.D1, op4 ); - return false; - case 4: /* DAT0=C */ - saturn.PC += 4; - store( saturn.D0, saturn.C, op4 ); - return false; - case 5: /* DAT1=C */ - saturn.PC += 4; - store( saturn.D1, saturn.C, op4 ); - return false; - case 6: /* C=DAT0 */ - saturn.PC += 4; - recall( saturn.C, saturn.D0, op4 ); - return false; - case 7: /* C=DAT1 */ - saturn.PC += 4; - recall( saturn.C, saturn.D1, op4 ); - return false; - default: - return true; - } - } - case 6: - op3 = read_nibble( saturn.PC + 2 ); - saturn.PC += 3; - add_address( &saturn.D0, op3 + 1 ); - return false; - case 7: - op3 = read_nibble( saturn.PC + 2 ); - saturn.PC += 3; - add_address( &saturn.D1, op3 + 1 ); - return false; - case 8: - op3 = read_nibble( saturn.PC + 2 ); - saturn.PC += 3; - add_address( &saturn.D0, -( op3 + 1 ) ); - return false; - case 9: - load_addr( &saturn.D0, saturn.PC + 2, 2 ); - saturn.PC += 4; - return false; - case 0xa: - load_addr( &saturn.D0, saturn.PC + 2, 4 ); - saturn.PC += 6; - return false; - case 0xb: - load_addr( &saturn.D0, saturn.PC + 2, 5 ); - saturn.PC += 7; - return false; - case 0xc: - op3 = read_nibble( saturn.PC + 2 ); - saturn.PC += 3; - add_address( &saturn.D1, -( op3 + 1 ) ); - return false; - case 0xd: - load_addr( &saturn.D1, saturn.PC + 2, 2 ); - saturn.PC += 4; - return false; - case 0xe: - load_addr( &saturn.D1, saturn.PC + 2, 4 ); - saturn.PC += 6; - return false; - case 0xf: - load_addr( &saturn.D1, saturn.PC + 2, 5 ); - saturn.PC += 7; - return false; - default: - return true; - } -} - -static inline bool _step_instruction_group_8_thru_f( int op1 ) -{ - int op2, op3, op4, op5, op6; - - op2 = read_nibble( saturn.PC + 1 ); - switch ( op1 ) { - case 8: - switch ( op2 ) { - case 0: - return _step_instruction_group_80(); - case 1: - op3 = read_nibble( saturn.PC + 2 ); - switch ( op3 ) { - case 0: /* ASLC */ - saturn.PC += 3; - shift_left_circ_register( saturn.A, W_FIELD ); - return false; - case 1: /* BSLC */ - saturn.PC += 3; - shift_left_circ_register( saturn.B, W_FIELD ); - return false; - case 2: /* CSLC */ - saturn.PC += 3; - shift_left_circ_register( saturn.C, W_FIELD ); - return false; - case 3: /* DSLC */ - saturn.PC += 3; - shift_left_circ_register( saturn.D, W_FIELD ); - return false; - case 4: /* ASRC */ - saturn.PC += 3; - shift_right_circ_register( saturn.A, W_FIELD ); - return false; - case 5: /* BSRC */ - saturn.PC += 3; - shift_right_circ_register( saturn.B, W_FIELD ); - return false; - case 6: /* CSRC */ - saturn.PC += 3; - shift_right_circ_register( saturn.C, W_FIELD ); - return false; - case 7: /* DSRC */ - saturn.PC += 3; - shift_right_circ_register( saturn.D, W_FIELD ); - return false; - case 8: /* R = R +/- CON */ - op4 = read_nibble( saturn.PC + 3 ); - op5 = read_nibble( saturn.PC + 4 ); - op6 = read_nibble( saturn.PC + 5 ); - if ( op5 < 8 ) { /* PLUS */ - switch ( op5 & 3 ) { - case 0: /* A=A+CON */ - saturn.PC += 6; - add_register_constant( saturn.A, op4, op6 + 1 ); - return false; - case 1: /* B=B+CON */ - saturn.PC += 6; - add_register_constant( saturn.B, op4, op6 + 1 ); - return false; - case 2: /* C=C+CON */ - saturn.PC += 6; - add_register_constant( saturn.C, op4, op6 + 1 ); - return false; - case 3: /* D=D+CON */ - saturn.PC += 6; - add_register_constant( saturn.D, op4, op6 + 1 ); - return false; - default: - return true; - } - } else { /* MINUS */ - switch ( op5 & 3 ) { - case 0: /* A=A-CON */ - saturn.PC += 6; - sub_register_constant( saturn.A, op4, op6 + 1 ); - return false; - case 1: /* B=B-CON */ - saturn.PC += 6; - sub_register_constant( saturn.B, op4, op6 + 1 ); - return false; - case 2: /* C=C-CON */ - saturn.PC += 6; - sub_register_constant( saturn.C, op4, op6 + 1 ); - return false; - case 3: /* D=D-CON */ - saturn.PC += 6; - sub_register_constant( saturn.D, op4, op6 + 1 ); - return false; - default: - return true; - } - } - case 9: /* R SRB FIELD */ - op4 = read_nibble( saturn.PC + 3 ); - op5 = read_nibble( saturn.PC + 4 ); - switch ( op5 & 3 ) { - case 0: - saturn.PC += 5; - shift_right_bit_register( saturn.A, op4 ); - return false; - case 1: - saturn.PC += 5; - shift_right_bit_register( saturn.B, op4 ); - return false; - case 2: - saturn.PC += 5; - shift_right_bit_register( saturn.C, op4 ); - return false; - case 3: - saturn.PC += 5; - shift_right_bit_register( saturn.D, op4 ); - return false; - default: - return true; - } - case 0xa: /* R = R FIELD, etc. */ - op4 = read_nibble( saturn.PC + 3 ); - op5 = read_nibble( saturn.PC + 4 ); - op6 = read_nibble( saturn.PC + 5 ); - switch ( op5 ) { - case 0: - switch ( op6 ) { - case 0: /* saturn.R0=A */ - saturn.PC += 6; - copy_register( saturn.R0, saturn.A, op4 ); - return false; - case 1: /* saturn.R1=A */ - case 5: - saturn.PC += 6; - copy_register( saturn.R1, saturn.A, op4 ); - return false; - case 2: /* saturn.R2=A */ - case 6: - saturn.PC += 6; - copy_register( saturn.R2, saturn.A, op4 ); - return false; - case 3: /* saturn.R3=A */ - case 7: - saturn.PC += 6; - copy_register( saturn.R3, saturn.A, op4 ); - return false; - case 4: /* saturn.R4=A */ - saturn.PC += 6; - copy_register( saturn.R4, saturn.A, op4 ); - return false; - case 8: /* saturn.R0=C */ - saturn.PC += 6; - copy_register( saturn.R0, saturn.C, op4 ); - return false; - case 9: /* saturn.R1=C */ - case 0xd: - saturn.PC += 6; - copy_register( saturn.R1, saturn.C, op4 ); - return false; - case 0xa: /* saturn.R2=C */ - case 0xe: - saturn.PC += 6; - copy_register( saturn.R2, saturn.C, op4 ); - return false; - case 0xb: /* saturn.R3=C */ - case 0xf: - saturn.PC += 6; - copy_register( saturn.R3, saturn.C, op4 ); - return false; - case 0xc: /* saturn.R4=C */ - saturn.PC += 6; - copy_register( saturn.R4, saturn.C, op4 ); - return false; - default: - return true; - } - case 1: - switch ( op6 ) { - case 0: /* A=R0 */ - saturn.PC += 6; - copy_register( saturn.A, saturn.R0, op4 ); - return false; - case 1: /* A=R1 */ - case 5: - saturn.PC += 6; - copy_register( saturn.A, saturn.R1, op4 ); - return false; - case 2: /* A=R2 */ - case 6: - saturn.PC += 6; - copy_register( saturn.A, saturn.R2, op4 ); - return false; - case 3: /* A=R3 */ - case 7: - saturn.PC += 6; - copy_register( saturn.A, saturn.R3, op4 ); - return false; - case 4: /* A=R4 */ - saturn.PC += 6; - copy_register( saturn.A, saturn.R4, op4 ); - return false; - case 8: /* C=R0 */ - saturn.PC += 6; - copy_register( saturn.C, saturn.R0, op4 ); - return false; - case 9: /* C=R1 */ - case 0xd: - saturn.PC += 6; - copy_register( saturn.C, saturn.R1, op4 ); - return false; - case 0xa: /* C=R2 */ - case 0xe: - saturn.PC += 6; - copy_register( saturn.C, saturn.R2, op4 ); - return false; - case 0xb: /* C=R3 */ - case 0xf: - saturn.PC += 6; - copy_register( saturn.C, saturn.R3, op4 ); - return false; - case 0xc: /* C=R4 */ - saturn.PC += 6; - copy_register( saturn.C, saturn.R4, op4 ); - return false; - default: - return true; - } - case 2: - switch ( op6 ) { - case 0: /* AR0EX */ - saturn.PC += 6; - exchange_register( saturn.A, saturn.R0, op4 ); - return false; - case 1: /* AR1EX */ - case 5: - saturn.PC += 6; - exchange_register( saturn.A, saturn.R1, op4 ); - return false; - case 2: /* AR2EX */ - case 6: - saturn.PC += 6; - exchange_register( saturn.A, saturn.R2, op4 ); - return false; - case 3: /* AR3EX */ - case 7: - saturn.PC += 6; - exchange_register( saturn.A, saturn.R3, op4 ); - return false; - case 4: /* AR4EX */ - saturn.PC += 6; - exchange_register( saturn.A, saturn.R4, op4 ); - return false; - case 8: /* CR0EX */ - saturn.PC += 6; - exchange_register( saturn.C, saturn.R0, op4 ); - return false; - case 9: /* CR1EX */ - case 0xd: - saturn.PC += 6; - exchange_register( saturn.C, saturn.R1, op4 ); - return false; - case 0xa: /* CR2EX */ - case 0xe: - saturn.PC += 6; - exchange_register( saturn.C, saturn.R2, op4 ); - return false; - case 0xb: /* CR3EX */ - case 0xf: - saturn.PC += 6; - exchange_register( saturn.C, saturn.R3, op4 ); - return false; - case 0xc: /* CR4EX */ - saturn.PC += 6; - exchange_register( saturn.C, saturn.R4, op4 ); - return false; - default: - return true; - } - default: - return true; - } - case 0xb: - op4 = read_nibble( saturn.PC + 3 ); - switch ( op4 ) { - case 2: /* PC=A */ - saturn.PC = dat_to_addr( saturn.A ); - return false; - case 3: /* PC=C */ - saturn.PC = dat_to_addr( saturn.C ); - return false; - case 4: /* A=PC */ - saturn.PC += 4; - addr_to_dat( saturn.PC, saturn.A ); - return false; - case 5: /* C=PC */ - saturn.PC += 4; - addr_to_dat( saturn.PC, saturn.C ); - return false; - case 6: /* APCEX */ - saturn.PC += 4; - addr_to_dat( saturn.PC, saturn.A ); - saturn.PC = dat_to_addr( saturn.A ); - return false; - case 7: /* CPCEX */ - saturn.PC += 4; - addr_to_dat( saturn.PC, saturn.C ); - saturn.PC = dat_to_addr( saturn.C ); - return false; - default: - return true; - } - case 0xc: /* ASRB */ - saturn.PC += 3; - shift_right_bit_register( saturn.A, W_FIELD ); - return false; - case 0xd: /* BSRB */ - saturn.PC += 3; - shift_right_bit_register( saturn.B, W_FIELD ); - return false; - case 0xe: /* CSRB */ - saturn.PC += 3; - shift_right_bit_register( saturn.C, W_FIELD ); - return false; - case 0xf: /* DSRB */ - saturn.PC += 3; - shift_right_bit_register( saturn.D, W_FIELD ); - return false; - default: - return true; - } - case 2: - op3 = read_nibble( saturn.PC + 2 ); - saturn.PC += 3; - clear_hardware_stat( op3 ); - return false; - case 3: - op3 = read_nibble( saturn.PC + 2 ); - saturn.CARRY = is_zero_hardware_stat( op3 ); - if ( saturn.CARRY ) { - saturn.PC += 3; - op4 = read_nibbles( saturn.PC, 2 ); - if ( op4 ) { - if ( op4 & 0x80 ) - op4 |= jumpmasks[ 2 ]; - saturn.PC = ( saturn.PC + op4 ) & 0xfffff; - } else - saturn.PC = pop_return_addr(); - } else - saturn.PC += 5; - return false; - case 4: - case 5: - op3 = read_nibble( saturn.PC + 2 ); - if ( op2 == 4 ) { - saturn.PC += 3; - clear_program_stat( op3 ); - } else { - saturn.PC += 3; - set_program_stat( op3 ); - } - return false; - case 6: - case 7: - op3 = read_nibble( saturn.PC + 2 ); - if ( op2 == 6 ) - saturn.CARRY = ( get_program_stat( op3 ) == 0 ) ? 1 : 0; - else - saturn.CARRY = ( get_program_stat( op3 ) != 0 ) ? 1 : 0; - if ( saturn.CARRY ) { - saturn.PC += 3; - op4 = read_nibbles( saturn.PC, 2 ); - if ( op4 ) { - if ( op4 & 0x80 ) - op4 |= jumpmasks[ 2 ]; - saturn.PC = ( saturn.PC + op4 ) & 0xfffff; - } else - saturn.PC = pop_return_addr(); - } else - saturn.PC += 5; - return false; - case 8: - case 9: - op3 = read_nibble( saturn.PC + 2 ); - if ( op2 == 8 ) - saturn.CARRY = ( saturn.P != op3 ) ? 1 : 0; - else - saturn.CARRY = ( saturn.P == op3 ) ? 1 : 0; - if ( saturn.CARRY ) { - saturn.PC += 3; - op4 = read_nibbles( saturn.PC, 2 ); - if ( op4 ) { - if ( op4 & 0x80 ) - op4 |= jumpmasks[ 2 ]; - saturn.PC = ( saturn.PC + op4 ) & 0xfffff; - } else - saturn.PC = pop_return_addr(); - } else - saturn.PC += 5; - return false; - case 0xa: - op3 = read_nibble( saturn.PC + 2 ); - switch ( op3 ) { - case 0: /* ?A=B */ - saturn.CARRY = is_equal_register( saturn.A, saturn.B, A_FIELD ); - break; - case 1: /* ?B=C */ - saturn.CARRY = is_equal_register( saturn.B, saturn.C, A_FIELD ); - break; - case 2: /* ?A=C */ - saturn.CARRY = is_equal_register( saturn.A, saturn.C, A_FIELD ); - break; - case 3: /* ?C=D */ - saturn.CARRY = is_equal_register( saturn.C, saturn.D, A_FIELD ); - break; - case 4: /* ?A#B */ - saturn.CARRY = is_not_equal_register( saturn.A, saturn.B, A_FIELD ); - break; - case 5: /* ?B#C */ - saturn.CARRY = is_not_equal_register( saturn.B, saturn.C, A_FIELD ); - break; - case 6: /* ?A#C */ - saturn.CARRY = is_not_equal_register( saturn.A, saturn.C, A_FIELD ); - break; - case 7: /* ?C#D */ - saturn.CARRY = is_not_equal_register( saturn.C, saturn.D, A_FIELD ); - break; - case 8: /* ?A=0 */ - saturn.CARRY = is_zero_register( saturn.A, A_FIELD ); - break; - case 9: /* ?B=0 */ - saturn.CARRY = is_zero_register( saturn.B, A_FIELD ); - break; - case 0xa: /* ?C=0 */ - saturn.CARRY = is_zero_register( saturn.C, A_FIELD ); - break; - case 0xb: /* ?D=0 */ - saturn.CARRY = is_zero_register( saturn.D, A_FIELD ); - break; - case 0xc: /* ?A#0 */ - saturn.CARRY = is_not_zero_register( saturn.A, A_FIELD ); - break; - case 0xd: /* ?B#0 */ - saturn.CARRY = is_not_zero_register( saturn.B, A_FIELD ); - break; - case 0xe: /* ?C#0 */ - saturn.CARRY = is_not_zero_register( saturn.C, A_FIELD ); - break; - case 0xf: /* ?D#0 */ - saturn.CARRY = is_not_zero_register( saturn.D, A_FIELD ); - break; - default: - return true; - } - if ( saturn.CARRY ) { - saturn.PC += 3; - op4 = read_nibbles( saturn.PC, 2 ); - if ( op4 ) { - if ( op4 & 0x80 ) - op4 |= jumpmasks[ 2 ]; - saturn.PC = ( saturn.PC + op4 ) & 0xfffff; - } else - saturn.PC = pop_return_addr(); - } else - saturn.PC += 5; - return false; - case 0xb: - op3 = read_nibble( saturn.PC + 2 ); - switch ( op3 ) { - case 0: /* ?A>B */ - saturn.CARRY = is_greater_register( saturn.A, saturn.B, A_FIELD ); - break; - case 1: /* ?B>C */ - saturn.CARRY = is_greater_register( saturn.B, saturn.C, A_FIELD ); - break; - case 2: /* ?C>A */ - saturn.CARRY = is_greater_register( saturn.C, saturn.A, A_FIELD ); - break; - case 3: /* ?D>C */ - saturn.CARRY = is_greater_register( saturn.D, saturn.C, A_FIELD ); - break; - case 4: /* ?A=B */ - saturn.CARRY = is_greater_or_equal_register( saturn.A, saturn.B, A_FIELD ); - break; - case 9: /* ?B>=C */ - saturn.CARRY = is_greater_or_equal_register( saturn.B, saturn.C, A_FIELD ); - break; - case 0xa: /* ?C>=A */ - saturn.CARRY = is_greater_or_equal_register( saturn.C, saturn.A, A_FIELD ); - break; - case 0xb: /* ?D>=C */ - saturn.CARRY = is_greater_or_equal_register( saturn.D, saturn.C, A_FIELD ); - break; - case 0xc: /* ?A<=B */ - saturn.CARRY = is_less_or_equal_register( saturn.A, saturn.B, A_FIELD ); - break; - case 0xd: /* ?B<=C */ - saturn.CARRY = is_less_or_equal_register( saturn.B, saturn.C, A_FIELD ); - break; - case 0xe: /* ?C<=A */ - saturn.CARRY = is_less_or_equal_register( saturn.C, saturn.A, A_FIELD ); - break; - case 0xf: /* ?D<=C */ - saturn.CARRY = is_less_or_equal_register( saturn.D, saturn.C, A_FIELD ); - break; - default: - return true; - } - if ( saturn.CARRY ) { - saturn.PC += 3; - op4 = read_nibbles( saturn.PC, 2 ); - if ( op4 ) { - if ( op4 & 0x80 ) - op4 |= jumpmasks[ 2 ]; - saturn.PC = ( saturn.PC + op4 ) & 0xfffff; - } else - saturn.PC = pop_return_addr(); - } else - saturn.PC += 5; - return false; - case 0xc: - op3 = read_nibbles( saturn.PC + 2, 4 ); - if ( op3 & 0x8000 ) - op3 |= jumpmasks[ 4 ]; - saturn.PC = ( saturn.PC + op3 + 2 ) & 0xfffff; - return false; - case 0xd: - op3 = read_nibbles( saturn.PC + 2, 5 ); - saturn.PC = op3; - return false; - case 0xe: - op3 = read_nibbles( saturn.PC + 2, 4 ); - if ( op3 & 0x8000 ) - op3 |= jumpmasks[ 4 ]; - push_return_addr( saturn.PC + 6 ); - saturn.PC = ( saturn.PC + op3 + 6 ) & 0xfffff; - return false; - case 0xf: - op3 = read_nibbles( saturn.PC + 2, 5 ); - push_return_addr( saturn.PC + 7 ); - saturn.PC = op3; - return false; - default: - return true; - } - case 9: - op3 = read_nibble( saturn.PC + 2 ); - if ( op2 < 8 ) { - switch ( op3 ) { - case 0: /* ?A=B */ - saturn.CARRY = is_equal_register( saturn.A, saturn.B, op2 ); - break; - case 1: /* ?B=C */ - saturn.CARRY = is_equal_register( saturn.B, saturn.C, op2 ); - break; - case 2: /* ?A=C */ - saturn.CARRY = is_equal_register( saturn.A, saturn.C, op2 ); - break; - case 3: /* ?C=D */ - saturn.CARRY = is_equal_register( saturn.C, saturn.D, op2 ); - break; - case 4: /* ?A#B */ - saturn.CARRY = is_not_equal_register( saturn.A, saturn.B, op2 ); - break; - case 5: /* ?B#C */ - saturn.CARRY = is_not_equal_register( saturn.B, saturn.C, op2 ); - break; - case 6: /* ?A#C */ - saturn.CARRY = is_not_equal_register( saturn.A, saturn.C, op2 ); - break; - case 7: /* ?C#D */ - saturn.CARRY = is_not_equal_register( saturn.C, saturn.D, op2 ); - break; - case 8: /* ?A=0 */ - saturn.CARRY = is_zero_register( saturn.A, op2 ); - break; - case 9: /* ?B=0 */ - saturn.CARRY = is_zero_register( saturn.B, op2 ); - break; - case 0xa: /* ?C=0 */ - saturn.CARRY = is_zero_register( saturn.C, op2 ); - break; - case 0xb: /* ?D=0 */ - saturn.CARRY = is_zero_register( saturn.D, op2 ); - break; - case 0xc: /* ?A#0 */ - saturn.CARRY = is_not_zero_register( saturn.A, op2 ); - break; - case 0xd: /* ?B#0 */ - saturn.CARRY = is_not_zero_register( saturn.B, op2 ); - break; - case 0xe: /* ?C#0 */ - saturn.CARRY = is_not_zero_register( saturn.C, op2 ); - break; - case 0xf: /* ?D#0 */ - saturn.CARRY = is_not_zero_register( saturn.D, op2 ); - break; - default: - return true; - } - } else { - op2 &= 7; - switch ( op3 ) { - case 0: /* ?A>B */ - saturn.CARRY = is_greater_register( saturn.A, saturn.B, op2 ); - break; - case 1: /* ?B>C */ - saturn.CARRY = is_greater_register( saturn.B, saturn.C, op2 ); - break; - case 2: /* ?C>A */ - saturn.CARRY = is_greater_register( saturn.C, saturn.A, op2 ); - break; - case 3: /* ?D>C */ - saturn.CARRY = is_greater_register( saturn.D, saturn.C, op2 ); - break; - case 4: /* ?A=B */ - saturn.CARRY = is_greater_or_equal_register( saturn.A, saturn.B, op2 ); - break; - case 9: /* ?B>=C */ - saturn.CARRY = is_greater_or_equal_register( saturn.B, saturn.C, op2 ); - break; - case 0xa: /* ?C>=A */ - saturn.CARRY = is_greater_or_equal_register( saturn.C, saturn.A, op2 ); - break; - case 0xb: /* ?D>=C */ - saturn.CARRY = is_greater_or_equal_register( saturn.D, saturn.C, op2 ); - break; - case 0xc: /* ?A<=B */ - saturn.CARRY = is_less_or_equal_register( saturn.A, saturn.B, op2 ); - break; - case 0xd: /* ?B<=C */ - saturn.CARRY = is_less_or_equal_register( saturn.B, saturn.C, op2 ); - break; - case 0xe: /* ?C<=A */ - saturn.CARRY = is_less_or_equal_register( saturn.C, saturn.A, op2 ); - break; - case 0xf: /* ?D<=C */ - saturn.CARRY = is_less_or_equal_register( saturn.D, saturn.C, op2 ); - break; - default: - return true; - } - } - if ( saturn.CARRY ) { - saturn.PC += 3; - op4 = read_nibbles( saturn.PC, 2 ); - if ( op4 ) { - if ( op4 & 0x80 ) - op4 |= jumpmasks[ 2 ]; - saturn.PC = ( saturn.PC + op4 ) & 0xfffff; - } else { - saturn.PC = pop_return_addr(); - } - } else { - saturn.PC += 5; - } - return false; - case 0xa: - op3 = read_nibble( saturn.PC + 2 ); - if ( op2 < 8 ) { - switch ( op3 ) { - case 0: /* A=A+B */ - saturn.PC += 3; - add_register( saturn.A, saturn.A, saturn.B, op2 ); - return false; - case 1: /* B=B+C */ - saturn.PC += 3; - add_register( saturn.B, saturn.B, saturn.C, op2 ); - return false; - case 2: /* C=C+A */ - saturn.PC += 3; - add_register( saturn.C, saturn.C, saturn.A, op2 ); - return false; - case 3: /* D=D+C */ - saturn.PC += 3; - add_register( saturn.D, saturn.D, saturn.C, op2 ); - return false; - case 4: /* A=A+A */ - saturn.PC += 3; - add_register( saturn.A, saturn.A, saturn.A, op2 ); - return false; - case 5: /* B=B+B */ - saturn.PC += 3; - add_register( saturn.B, saturn.B, saturn.B, op2 ); - return false; - case 6: /* C=C+C */ - saturn.PC += 3; - add_register( saturn.C, saturn.C, saturn.C, op2 ); - return false; - case 7: /* D=D+D */ - saturn.PC += 3; - add_register( saturn.D, saturn.D, saturn.D, op2 ); - return false; - case 8: /* B=B+A */ - saturn.PC += 3; - add_register( saturn.B, saturn.B, saturn.A, op2 ); - return false; - case 9: /* C=C+B */ - saturn.PC += 3; - add_register( saturn.C, saturn.C, saturn.B, op2 ); - return false; - case 0xa: /* A=A+C */ - saturn.PC += 3; - add_register( saturn.A, saturn.A, saturn.C, op2 ); - return false; - case 0xb: /* C=C+D */ - saturn.PC += 3; - add_register( saturn.C, saturn.C, saturn.D, op2 ); - return false; - case 0xc: /* A=A-1 */ - saturn.PC += 3; - dec_register( saturn.A, op2 ); - return false; - case 0xd: /* B=B-1 */ - saturn.PC += 3; - dec_register( saturn.B, op2 ); - return false; - case 0xe: /* C=C-1 */ - saturn.PC += 3; - dec_register( saturn.C, op2 ); - return false; - case 0xf: /* D=D-1 */ - saturn.PC += 3; - dec_register( saturn.D, op2 ); - return false; - default: - return true; - } - } else { - op2 &= 7; - switch ( op3 ) { - case 0: /* A=0 */ - saturn.PC += 3; - zero_register( saturn.A, op2 ); - return false; - case 1: /* B=0 */ - saturn.PC += 3; - zero_register( saturn.B, op2 ); - return false; - case 2: /* C=0 */ - saturn.PC += 3; - zero_register( saturn.C, op2 ); - return false; - case 3: /* D=0 */ - saturn.PC += 3; - zero_register( saturn.D, op2 ); - return false; - case 4: /* A=B */ - saturn.PC += 3; - copy_register( saturn.A, saturn.B, op2 ); - return false; - case 5: /* B=C */ - saturn.PC += 3; - copy_register( saturn.B, saturn.C, op2 ); - return false; - case 6: /* C=A */ - saturn.PC += 3; - copy_register( saturn.C, saturn.A, op2 ); - return false; - case 7: /* D=C */ - saturn.PC += 3; - copy_register( saturn.D, saturn.C, op2 ); - return false; - case 8: /* B=A */ - saturn.PC += 3; - copy_register( saturn.B, saturn.A, op2 ); - return false; - case 9: /* C=B */ - saturn.PC += 3; - copy_register( saturn.C, saturn.B, op2 ); - return false; - case 0xa: /* A=C */ - saturn.PC += 3; - copy_register( saturn.A, saturn.C, op2 ); - return false; - case 0xb: /* C=D */ - saturn.PC += 3; - copy_register( saturn.C, saturn.D, op2 ); - return false; - case 0xc: /* ABEX */ - saturn.PC += 3; - exchange_register( saturn.A, saturn.B, op2 ); - return false; - case 0xd: /* BCEX */ - saturn.PC += 3; - exchange_register( saturn.B, saturn.C, op2 ); - return false; - case 0xe: /* ACEX */ - saturn.PC += 3; - exchange_register( saturn.A, saturn.C, op2 ); - return false; - case 0xf: /* CDEX */ - saturn.PC += 3; - exchange_register( saturn.C, saturn.D, op2 ); - return false; - default: - return true; - } - } - case 0xb: - op3 = read_nibble( saturn.PC + 2 ); - if ( op2 < 8 ) { - switch ( op3 ) { - case 0: /* A=A-B */ - saturn.PC += 3; - sub_register( saturn.A, saturn.A, saturn.B, op2 ); - return false; - case 1: /* B=B-C */ - saturn.PC += 3; - sub_register( saturn.B, saturn.B, saturn.C, op2 ); - return false; - case 2: /* C=C-A */ - saturn.PC += 3; - sub_register( saturn.C, saturn.C, saturn.A, op2 ); - return false; - case 3: /* D=D-C */ - saturn.PC += 3; - sub_register( saturn.D, saturn.D, saturn.C, op2 ); - return false; - case 4: /* A=A+1 */ - saturn.PC += 3; - inc_register( saturn.A, op2 ); - return false; - case 5: /* B=B+1 */ - saturn.PC += 3; - inc_register( saturn.B, op2 ); - return false; - case 6: /* C=C+1 */ - saturn.PC += 3; - inc_register( saturn.C, op2 ); - return false; - case 7: /* D=D+1 */ - saturn.PC += 3; - inc_register( saturn.D, op2 ); - return false; - case 8: /* B=B-A */ - saturn.PC += 3; - sub_register( saturn.B, saturn.B, saturn.A, op2 ); - return false; - case 9: /* C=C-B */ - saturn.PC += 3; - sub_register( saturn.C, saturn.C, saturn.B, op2 ); - return false; - case 0xa: /* A=A-C */ - saturn.PC += 3; - sub_register( saturn.A, saturn.A, saturn.C, op2 ); - return false; - case 0xb: /* C=C-D */ - saturn.PC += 3; - sub_register( saturn.C, saturn.C, saturn.D, op2 ); - return false; - case 0xc: /* A=B-A */ - saturn.PC += 3; - sub_register( saturn.A, saturn.B, saturn.A, op2 ); - return false; - case 0xd: /* B=C-B */ - saturn.PC += 3; - sub_register( saturn.B, saturn.C, saturn.B, op2 ); - return false; - case 0xe: /* C=A-C */ - saturn.PC += 3; - sub_register( saturn.C, saturn.A, saturn.C, op2 ); - return false; - case 0xf: /* D=C-D */ - saturn.PC += 3; - sub_register( saturn.D, saturn.C, saturn.D, op2 ); - return false; - default: - return true; - } - } else { - op2 &= 7; - switch ( op3 ) { - case 0: /* ASL */ - saturn.PC += 3; - shift_left_register( saturn.A, op2 ); - return false; - case 1: /* BSL */ - saturn.PC += 3; - shift_left_register( saturn.B, op2 ); - return false; - case 2: /* CSL */ - saturn.PC += 3; - shift_left_register( saturn.C, op2 ); - return false; - case 3: /* DSL */ - saturn.PC += 3; - shift_left_register( saturn.D, op2 ); - return false; - case 4: /* ASR */ - saturn.PC += 3; - shift_right_register( saturn.A, op2 ); - return false; - case 5: /* BSR */ - saturn.PC += 3; - shift_right_register( saturn.B, op2 ); - return false; - case 6: /* CSR */ - saturn.PC += 3; - shift_right_register( saturn.C, op2 ); - return false; - case 7: /* DSR */ - saturn.PC += 3; - shift_right_register( saturn.D, op2 ); - return false; - case 8: /* A=-A */ - saturn.PC += 3; - complement_2_register( saturn.A, op2 ); - return false; - case 9: /* B=-B */ - saturn.PC += 3; - complement_2_register( saturn.B, op2 ); - return false; - case 0xa: /* C=-C */ - saturn.PC += 3; - complement_2_register( saturn.C, op2 ); - return false; - case 0xb: /* D=-D */ - saturn.PC += 3; - complement_2_register( saturn.D, op2 ); - return false; - case 0xc: /* A=-A-1 */ - saturn.PC += 3; - complement_1_register( saturn.A, op2 ); - return false; - case 0xd: /* B=-B-1 */ - saturn.PC += 3; - complement_1_register( saturn.B, op2 ); - return false; - case 0xe: /* C=-C-1 */ - saturn.PC += 3; - complement_1_register( saturn.C, op2 ); - return false; - case 0xf: /* D=-D-1 */ - saturn.PC += 3; - complement_1_register( saturn.D, op2 ); - return false; - default: - return true; - } - } - case 0xc: - switch ( op2 ) { - case 0: /* A=A+B */ - saturn.PC += 2; - add_register( saturn.A, saturn.A, saturn.B, A_FIELD ); - return false; - case 1: /* B=B+C */ - saturn.PC += 2; - add_register( saturn.B, saturn.B, saturn.C, A_FIELD ); - return false; - case 2: /* C=C+A */ - saturn.PC += 2; - add_register( saturn.C, saturn.C, saturn.A, A_FIELD ); - return false; - case 3: /* D=D+C */ - saturn.PC += 2; - add_register( saturn.D, saturn.D, saturn.C, A_FIELD ); - return false; - case 4: /* A=A+A */ - saturn.PC += 2; - add_register( saturn.A, saturn.A, saturn.A, A_FIELD ); - return false; - case 5: /* B=B+B */ - saturn.PC += 2; - add_register( saturn.B, saturn.B, saturn.B, A_FIELD ); - return false; - case 6: /* C=C+C */ - saturn.PC += 2; - add_register( saturn.C, saturn.C, saturn.C, A_FIELD ); - return false; - case 7: /* D=D+D */ - saturn.PC += 2; - add_register( saturn.D, saturn.D, saturn.D, A_FIELD ); - return false; - case 8: /* B=B+A */ - saturn.PC += 2; - add_register( saturn.B, saturn.B, saturn.A, A_FIELD ); - return false; - case 9: /* C=C+B */ - saturn.PC += 2; - add_register( saturn.C, saturn.C, saturn.B, A_FIELD ); - return false; - case 0xa: /* A=A+C */ - saturn.PC += 2; - add_register( saturn.A, saturn.A, saturn.C, A_FIELD ); - return false; - case 0xb: /* C=C+D */ - saturn.PC += 2; - add_register( saturn.C, saturn.C, saturn.D, A_FIELD ); - return false; - case 0xc: /* A=A-1 */ - saturn.PC += 2; - dec_register( saturn.A, A_FIELD ); - return false; - case 0xd: /* B=B-1 */ - saturn.PC += 2; - dec_register( saturn.B, A_FIELD ); - return false; - case 0xe: /* C=C-1 */ - saturn.PC += 2; - dec_register( saturn.C, A_FIELD ); - return false; - case 0xf: /* D=D-1 */ - saturn.PC += 2; - dec_register( saturn.D, A_FIELD ); - return false; - default: - return true; - } - case 0xd: - switch ( op2 ) { - case 0: /* A=0 */ - saturn.PC += 2; - zero_register( saturn.A, A_FIELD ); - return false; - case 1: /* B=0 */ - saturn.PC += 2; - zero_register( saturn.B, A_FIELD ); - return false; - case 2: /* C=0 */ - saturn.PC += 2; - zero_register( saturn.C, A_FIELD ); - return false; - case 3: /* D=0 */ - saturn.PC += 2; - zero_register( saturn.D, A_FIELD ); - return false; - case 4: /* A=B */ - saturn.PC += 2; - copy_register( saturn.A, saturn.B, A_FIELD ); - return false; - case 5: /* B=C */ - saturn.PC += 2; - copy_register( saturn.B, saturn.C, A_FIELD ); - return false; - case 6: /* C=A */ - saturn.PC += 2; - copy_register( saturn.C, saturn.A, A_FIELD ); - return false; - case 7: /* D=C */ - saturn.PC += 2; - copy_register( saturn.D, saturn.C, A_FIELD ); - return false; - case 8: /* B=A */ - saturn.PC += 2; - copy_register( saturn.B, saturn.A, A_FIELD ); - return false; - case 9: /* C=B */ - saturn.PC += 2; - copy_register( saturn.C, saturn.B, A_FIELD ); - return false; - case 0xa: /* A=C */ - saturn.PC += 2; - copy_register( saturn.A, saturn.C, A_FIELD ); - return false; - case 0xb: /* C=D */ - saturn.PC += 2; - copy_register( saturn.C, saturn.D, A_FIELD ); - return false; - case 0xc: /* ABEX */ - saturn.PC += 2; - exchange_register( saturn.A, saturn.B, A_FIELD ); - return false; - case 0xd: /* BCEX */ - saturn.PC += 2; - exchange_register( saturn.B, saturn.C, A_FIELD ); - return false; - case 0xe: /* ACEX */ - saturn.PC += 2; - exchange_register( saturn.A, saturn.C, A_FIELD ); - return false; - case 0xf: /* CDEX */ - saturn.PC += 2; - exchange_register( saturn.C, saturn.D, A_FIELD ); - return false; - default: - return true; - } - case 0xe: - switch ( op2 ) { - case 0: /* A=A-B */ - saturn.PC += 2; - sub_register( saturn.A, saturn.A, saturn.B, A_FIELD ); - return false; - case 1: /* B=B-C */ - saturn.PC += 2; - sub_register( saturn.B, saturn.B, saturn.C, A_FIELD ); - return false; - case 2: /* C=C-A */ - saturn.PC += 2; - sub_register( saturn.C, saturn.C, saturn.A, A_FIELD ); - return false; - case 3: /* D=D-C */ - saturn.PC += 2; - sub_register( saturn.D, saturn.D, saturn.C, A_FIELD ); - return false; - case 4: /* A=A+1 */ - saturn.PC += 2; - inc_register( saturn.A, A_FIELD ); - return false; - case 5: /* B=B+1 */ - saturn.PC += 2; - inc_register( saturn.B, A_FIELD ); - return false; - case 6: /* C=C+1 */ - saturn.PC += 2; - inc_register( saturn.C, A_FIELD ); - return false; - case 7: /* D=D+1 */ - saturn.PC += 2; - inc_register( saturn.D, A_FIELD ); - return false; - case 8: /* B=B-A */ - saturn.PC += 2; - sub_register( saturn.B, saturn.B, saturn.A, A_FIELD ); - return false; - case 9: /* C=C-B */ - saturn.PC += 2; - sub_register( saturn.C, saturn.C, saturn.B, A_FIELD ); - return false; - case 0xa: /* A=A-C */ - saturn.PC += 2; - sub_register( saturn.A, saturn.A, saturn.C, A_FIELD ); - return false; - case 0xb: /* C=C-D */ - saturn.PC += 2; - sub_register( saturn.C, saturn.C, saturn.D, A_FIELD ); - return false; - case 0xc: /* A=B-A */ - saturn.PC += 2; - sub_register( saturn.A, saturn.B, saturn.A, A_FIELD ); - return false; - case 0xd: /* B=C-B */ - saturn.PC += 2; - sub_register( saturn.B, saturn.C, saturn.B, A_FIELD ); - return false; - case 0xe: /* C=A-C */ - saturn.PC += 2; - sub_register( saturn.C, saturn.A, saturn.C, A_FIELD ); - return false; - case 0xf: /* D=C-D */ - saturn.PC += 2; - sub_register( saturn.D, saturn.C, saturn.D, A_FIELD ); - return false; - default: - return true; - } - case 0xf: - switch ( op2 ) { - case 0: /* ASL */ - saturn.PC += 2; - shift_left_register( saturn.A, A_FIELD ); - return false; - case 1: /* BSL */ - saturn.PC += 2; - shift_left_register( saturn.B, A_FIELD ); - return false; - case 2: /* CSL */ - saturn.PC += 2; - shift_left_register( saturn.C, A_FIELD ); - return false; - case 3: /* DSL */ - saturn.PC += 2; - shift_left_register( saturn.D, A_FIELD ); - return false; - case 4: /* ASR */ - saturn.PC += 2; - shift_right_register( saturn.A, A_FIELD ); - return false; - case 5: /* BSR */ - saturn.PC += 2; - shift_right_register( saturn.B, A_FIELD ); - return false; - case 6: /* CSR */ - saturn.PC += 2; - shift_right_register( saturn.C, A_FIELD ); - return false; - case 7: /* DSR */ - saturn.PC += 2; - shift_right_register( saturn.D, A_FIELD ); - return false; - case 8: /* A=-A */ - saturn.PC += 2; - complement_2_register( saturn.A, A_FIELD ); - return false; - case 9: /* B=-B */ - saturn.PC += 2; - complement_2_register( saturn.B, A_FIELD ); - return false; - case 0xa: /* C=-C */ - saturn.PC += 2; - complement_2_register( saturn.C, A_FIELD ); - return false; - case 0xb: /* D=-D */ - saturn.PC += 2; - complement_2_register( saturn.D, A_FIELD ); - return false; - case 0xc: /* A=-A-1 */ - saturn.PC += 2; - complement_1_register( saturn.A, A_FIELD ); - return false; - case 0xd: /* B=-B-1 */ - saturn.PC += 2; - complement_1_register( saturn.B, A_FIELD ); - return false; - case 0xe: /* C=-C-1 */ - saturn.PC += 2; - complement_1_register( saturn.C, A_FIELD ); - return false; - case 0xf: /* D=-D-1 */ - saturn.PC += 2; - complement_1_register( saturn.D, A_FIELD ); - return false; - default: - return true; - } - default: - return true; - } -} - void step_instruction( void ) { - int op0, op1, op2, op3; + int op0, op1, op2, op3, op4, op5, op6; bool stop = false; + int t, opX; + unsigned char* REG; + long addr; op0 = read_nibble( saturn.PC ); switch ( op0 ) { @@ -2513,7 +714,404 @@ void step_instruction( void ) } break; case 1: - stop = _step_instruction_group_1(); + op2 = read_nibble( saturn.PC + 1 ); + switch ( op2 ) { + case 0: + op3 = read_nibble( saturn.PC + 2 ); + switch ( op3 ) { + case 0: /* saturn.R0=A */ + saturn.PC += 3; + copy_register( saturn.R0, saturn.A, W_FIELD ); + break; + case 1: /* saturn.R1=A */ + case 5: + saturn.PC += 3; + copy_register( saturn.R1, saturn.A, W_FIELD ); + break; + case 2: /* saturn.R2=A */ + case 6: + saturn.PC += 3; + copy_register( saturn.R2, saturn.A, W_FIELD ); + break; + case 3: /* saturn.R3=A */ + case 7: + saturn.PC += 3; + copy_register( saturn.R3, saturn.A, W_FIELD ); + break; + case 4: /* saturn.R4=A */ + saturn.PC += 3; + copy_register( saturn.R4, saturn.A, W_FIELD ); + break; + case 8: /* saturn.R0=C */ + saturn.PC += 3; + copy_register( saturn.R0, saturn.C, W_FIELD ); + break; + case 9: /* saturn.R1=C */ + case 0xd: + saturn.PC += 3; + copy_register( saturn.R1, saturn.C, W_FIELD ); + break; + case 0xa: /* saturn.R2=C */ + case 0xe: + saturn.PC += 3; + copy_register( saturn.R2, saturn.C, W_FIELD ); + break; + case 0xb: /* saturn.R3=C */ + case 0xf: + saturn.PC += 3; + copy_register( saturn.R3, saturn.C, W_FIELD ); + break; + case 0xc: /* saturn.R4=C */ + saturn.PC += 3; + copy_register( saturn.R4, saturn.C, W_FIELD ); + break; + default: + stop = true; + } + break; + case 1: + op3 = read_nibble( saturn.PC + 2 ); + switch ( op3 ) { + case 0: /* A=R0 */ + saturn.PC += 3; + copy_register( saturn.A, saturn.R0, W_FIELD ); + break; + case 1: /* A=R1 */ + case 5: + saturn.PC += 3; + copy_register( saturn.A, saturn.R1, W_FIELD ); + break; + case 2: /* A=R2 */ + case 6: + saturn.PC += 3; + copy_register( saturn.A, saturn.R2, W_FIELD ); + break; + case 3: /* A=R3 */ + case 7: + saturn.PC += 3; + copy_register( saturn.A, saturn.R3, W_FIELD ); + break; + case 4: /* A=R4 */ + saturn.PC += 3; + copy_register( saturn.A, saturn.R4, W_FIELD ); + break; + case 8: /* C=R0 */ + saturn.PC += 3; + copy_register( saturn.C, saturn.R0, W_FIELD ); + break; + case 9: /* C=R1 */ + case 0xd: + saturn.PC += 3; + copy_register( saturn.C, saturn.R1, W_FIELD ); + break; + case 0xa: /* C=R2 */ + case 0xe: + saturn.PC += 3; + copy_register( saturn.C, saturn.R2, W_FIELD ); + break; + case 0xb: /* C=R3 */ + case 0xf: + saturn.PC += 3; + copy_register( saturn.C, saturn.R3, W_FIELD ); + break; + case 0xc: /* C=R4 */ + saturn.PC += 3; + copy_register( saturn.C, saturn.R4, W_FIELD ); + break; + default: + stop = true; + } + break; + case 2: + op3 = read_nibble( saturn.PC + 2 ); + switch ( op3 ) { + case 0: /* AR0EX */ + saturn.PC += 3; + exchange_register( saturn.A, saturn.R0, W_FIELD ); + break; + case 1: /* AR1EX */ + case 5: + saturn.PC += 3; + exchange_register( saturn.A, saturn.R1, W_FIELD ); + break; + case 2: /* AR2EX */ + case 6: + saturn.PC += 3; + exchange_register( saturn.A, saturn.R2, W_FIELD ); + break; + case 3: /* AR3EX */ + case 7: + saturn.PC += 3; + exchange_register( saturn.A, saturn.R3, W_FIELD ); + break; + case 4: /* AR4EX */ + saturn.PC += 3; + exchange_register( saturn.A, saturn.R4, W_FIELD ); + break; + case 8: /* CR0EX */ + saturn.PC += 3; + exchange_register( saturn.C, saturn.R0, W_FIELD ); + break; + case 9: /* CR1EX */ + case 0xd: + saturn.PC += 3; + exchange_register( saturn.C, saturn.R1, W_FIELD ); + break; + case 0xa: /* CR2EX */ + case 0xe: + saturn.PC += 3; + exchange_register( saturn.C, saturn.R2, W_FIELD ); + break; + case 0xb: /* CR3EX */ + case 0xf: + saturn.PC += 3; + exchange_register( saturn.C, saturn.R3, W_FIELD ); + break; + case 0xc: /* CR4EX */ + saturn.PC += 3; + exchange_register( saturn.C, saturn.R4, W_FIELD ); + break; + default: + stop = true; + } + break; + case 3: + op3 = read_nibble( saturn.PC + 2 ); + switch ( op3 ) { + case 0: /* D0=A */ + saturn.PC += 3; + register_to_address( saturn.A, &saturn.D0, 0 ); + break; + case 1: /* D1=A */ + saturn.PC += 3; + register_to_address( saturn.A, &saturn.D1, 0 ); + break; + case 2: /* AD0EX */ + saturn.PC += 3; + exchange_reg( saturn.A, &saturn.D0, A_FIELD ); + break; + case 3: /* AD1EX */ + saturn.PC += 3; + exchange_reg( saturn.A, &saturn.D1, A_FIELD ); + break; + case 4: /* D0=C */ + saturn.PC += 3; + register_to_address( saturn.C, &saturn.D0, 0 ); + break; + case 5: /* D1=C */ + saturn.PC += 3; + register_to_address( saturn.C, &saturn.D1, 0 ); + break; + case 6: /* CD0EX */ + saturn.PC += 3; + exchange_reg( saturn.C, &saturn.D0, A_FIELD ); + break; + case 7: /* CD1EX */ + saturn.PC += 3; + exchange_reg( saturn.C, &saturn.D1, A_FIELD ); + break; + case 8: /* D0=AS */ + saturn.PC += 3; + register_to_address( saturn.A, &saturn.D0, 1 ); + break; + case 9: /* saturn.D1=AS */ + saturn.PC += 3; + register_to_address( saturn.A, &saturn.D1, 1 ); + break; + case 0xa: /* AD0XS */ + saturn.PC += 3; + exchange_reg( saturn.A, &saturn.D0, IN_FIELD ); + break; + case 0xb: /* AD1XS */ + saturn.PC += 3; + exchange_reg( saturn.A, &saturn.D1, IN_FIELD ); + break; + case 0xc: /* D0=CS */ + saturn.PC += 3; + register_to_address( saturn.C, &saturn.D0, 1 ); + break; + case 0xd: /* D1=CS */ + saturn.PC += 3; + register_to_address( saturn.C, &saturn.D1, 1 ); + break; + case 0xe: /* CD0XS */ + saturn.PC += 3; + exchange_reg( saturn.C, &saturn.D0, IN_FIELD ); + break; + case 0xf: /* CD1XS */ + saturn.PC += 3; + exchange_reg( saturn.C, &saturn.D1, IN_FIELD ); + break; + default: + stop = true; + } + break; + case 4: + op3 = read_nibble( saturn.PC + 2 ); + opX = op3 < 8 ? 0xf : 6; + switch ( op3 & 7 ) { + case 0: /* DAT0=A */ + saturn.PC += 3; + store( saturn.D0, saturn.A, opX ); + break; + case 1: /* DAT1=A */ + saturn.PC += 3; + store( saturn.D1, saturn.A, opX ); + break; + case 2: /* A=DAT0 */ + saturn.PC += 3; + recall( saturn.A, saturn.D0, opX ); + break; + case 3: /* A=DAT1 */ + saturn.PC += 3; + recall( saturn.A, saturn.D1, opX ); + break; + case 4: /* DAT0=C */ + saturn.PC += 3; + store( saturn.D0, saturn.C, opX ); + break; + case 5: /* DAT1=C */ + saturn.PC += 3; + store( saturn.D1, saturn.C, opX ); + break; + case 6: /* C=DAT0 */ + saturn.PC += 3; + recall( saturn.C, saturn.D0, opX ); + break; + case 7: /* C=DAT1 */ + saturn.PC += 3; + recall( saturn.C, saturn.D1, opX ); + break; + default: + stop = true; + } + break; + case 5: + op3 = read_nibble( saturn.PC + 2 ); + op4 = read_nibble( saturn.PC + 3 ); + if ( op3 >= 8 ) { + switch ( op3 & 7 ) { + case 0: /* DAT0=A */ + saturn.PC += 4; + store_n( saturn.D0, saturn.A, op4 + 1 ); + break; + case 1: /* DAT1=A */ + saturn.PC += 4; + store_n( saturn.D1, saturn.A, op4 + 1 ); + break; + case 2: /* A=DAT0 */ + saturn.PC += 4; + recall_n( saturn.A, saturn.D0, op4 + 1 ); + break; + case 3: /* A=DAT1 */ + saturn.PC += 4; + recall_n( saturn.A, saturn.D1, op4 + 1 ); + break; + case 4: /* DAT0=C */ + saturn.PC += 4; + store_n( saturn.D0, saturn.C, op4 + 1 ); + break; + case 5: /* DAT1=C */ + saturn.PC += 4; + store_n( saturn.D1, saturn.C, op4 + 1 ); + break; + case 6: /* C=DAT0 */ + saturn.PC += 4; + recall_n( saturn.C, saturn.D0, op4 + 1 ); + break; + case 7: /* C=DAT1 */ + saturn.PC += 4; + recall_n( saturn.C, saturn.D1, op4 + 1 ); + break; + default: + stop = true; + } + } else { + switch ( op3 ) { + case 0: /* DAT0=A */ + saturn.PC += 4; + store( saturn.D0, saturn.A, op4 ); + break; + case 1: /* DAT1=A */ + saturn.PC += 4; + store( saturn.D1, saturn.A, op4 ); + break; + case 2: /* A=DAT0 */ + saturn.PC += 4; + recall( saturn.A, saturn.D0, op4 ); + break; + case 3: /* A=DAT1 */ + saturn.PC += 4; + recall( saturn.A, saturn.D1, op4 ); + break; + case 4: /* DAT0=C */ + saturn.PC += 4; + store( saturn.D0, saturn.C, op4 ); + break; + case 5: /* DAT1=C */ + saturn.PC += 4; + store( saturn.D1, saturn.C, op4 ); + break; + case 6: /* C=DAT0 */ + saturn.PC += 4; + recall( saturn.C, saturn.D0, op4 ); + break; + case 7: /* C=DAT1 */ + saturn.PC += 4; + recall( saturn.C, saturn.D1, op4 ); + break; + default: + stop = true; + } + } + break; + case 6: + op3 = read_nibble( saturn.PC + 2 ); + saturn.PC += 3; + add_address( &saturn.D0, op3 + 1 ); + break; + case 7: + op3 = read_nibble( saturn.PC + 2 ); + saturn.PC += 3; + add_address( &saturn.D1, op3 + 1 ); + break; + case 8: + op3 = read_nibble( saturn.PC + 2 ); + saturn.PC += 3; + add_address( &saturn.D0, -( op3 + 1 ) ); + break; + case 9: + load_addr( &saturn.D0, saturn.PC + 2, 2 ); + saturn.PC += 4; + break; + case 0xa: + load_addr( &saturn.D0, saturn.PC + 2, 4 ); + saturn.PC += 6; + break; + case 0xb: + load_addr( &saturn.D0, saturn.PC + 2, 5 ); + saturn.PC += 7; + break; + case 0xc: + op3 = read_nibble( saturn.PC + 2 ); + saturn.PC += 3; + add_address( &saturn.D1, -( op3 + 1 ) ); + break; + case 0xd: + load_addr( &saturn.D1, saturn.PC + 2, 2 ); + saturn.PC += 4; + break; + case 0xe: + load_addr( &saturn.D1, saturn.PC + 2, 4 ); + saturn.PC += 6; + break; + case 0xf: + load_addr( &saturn.D1, saturn.PC + 2, 5 ); + saturn.PC += 7; + break; + default: + stop = true; + } break; case 2: op2 = read_nibble( saturn.PC + 1 ); @@ -2534,7 +1132,6 @@ void step_instruction( void ) if ( op2 ) { if ( op2 & 0x80 ) op2 |= jumpmasks[ 2 ]; - saturn.PC = ( saturn.PC + op2 + 1 ) & 0xfffff; } else saturn.PC = pop_return_addr(); @@ -2580,9 +1177,1418 @@ void step_instruction( void ) push_return_addr( saturn.PC + 4 ); saturn.PC = ( op2 + saturn.PC + 4 ) & 0xfffff; break; - default: - stop = _step_instruction_group_8_thru_f( op0 ); + case 8: + op1 = read_nibble( saturn.PC + 1 ); + switch ( op1 ) { + case 0: + /* stop = _step_instruction_group_80(); */ + op3 = read_nibble( saturn.PC + 2 ); + switch ( op3 ) { + case 0: /* OUT=CS */ + saturn.PC += 3; + copy_register( saturn.OUT, saturn.C, OUTS_FIELD ); + break; + case 1: /* OUT=C */ + saturn.PC += 3; + copy_register( saturn.OUT, saturn.C, OUT_FIELD ); + break; + case 2: /* A=IN */ + saturn.PC += 3; + do_in(); + copy_register( saturn.A, saturn.IN, IN_FIELD ); + break; + case 3: /* C=IN */ + saturn.PC += 3; + do_in(); + copy_register( saturn.C, saturn.IN, IN_FIELD ); + break; + case 4: /* UNCNFG */ + saturn.PC += 3; + do_unconfigure(); + break; + case 5: /* CONFIG */ + saturn.PC += 3; + do_configure(); + break; + case 6: /* C=ID */ + saturn.PC += 3; + stop = get_identification(); + break; + case 7: /* SHUTDN */ + saturn.PC += 3; + do_shutdown(); + break; + case 8: + op4 = read_nibble( saturn.PC + 3 ); + switch ( op4 ) { + case 0: /* INTON */ + saturn.PC += 4; + do_inton(); + break; + case 1: /* RSI... */ + op5 = read_nibble( saturn.PC + 4 ); + saturn.PC += 5; + do_reset_interrupt_system(); + break; + case 2: /* LA... */ + op5 = read_nibble( saturn.PC + 4 ); + load_constant( saturn.A, op5 + 1, saturn.PC + 5 ); + saturn.PC += 6 + op5; + break; + case 3: /* BUSCB */ + saturn.PC += 4; + break; + case 4: /* ABIT=0 */ + op5 = read_nibble( saturn.PC + 4 ); + saturn.PC += 5; + clear_register_bit( saturn.A, op5 ); + break; + case 5: /* ABIT=1 */ + op5 = read_nibble( saturn.PC + 4 ); + saturn.PC += 5; + set_register_bit( saturn.A, op5 ); + break; + case 8: /* CBIT=0 */ + op5 = read_nibble( saturn.PC + 4 ); + saturn.PC += 5; + clear_register_bit( saturn.C, op5 ); + break; + case 9: /* CBIT=1 */ + op5 = read_nibble( saturn.PC + 4 ); + saturn.PC += 5; + set_register_bit( saturn.C, op5 ); + break; + case 6: /* ?ABIT=0 */ + case 7: /* ?ABIT=1 */ + case 0xa: /* ?CBIT=0 */ + case 0xb: /* ?CBIT=1 */ + op5 = read_nibble( saturn.PC + 4 ); + if ( op4 < 8 ) + REG = saturn.A; + else + REG = saturn.C; + if ( op4 == 6 || op4 == 0xa ) + t = 0; + else + t = 1; + saturn.CARRY = ( get_register_bit( REG, op5 ) == t ) ? 1 : 0; + if ( saturn.CARRY ) { + saturn.PC += 5; + op6 = read_nibbles( saturn.PC, 2 ); + if ( op6 ) { + if ( op6 & 0x80 ) + op6 |= jumpmasks[ 2 ]; + saturn.PC = ( saturn.PC + op6 ) & 0xfffff; + } else + saturn.PC = pop_return_addr(); + } else + saturn.PC += 7; + break; + case 0xc: /* PC=(A) */ + addr = dat_to_addr( saturn.A ); + saturn.PC = read_nibbles( addr, 5 ); + break; + case 0xd: /* BUSCD */ + saturn.PC += 4; + break; + case 0xe: /* PC=(C) */ + addr = dat_to_addr( saturn.C ); + saturn.PC = read_nibbles( addr, 5 ); + break; + case 0xf: /* INTOFF */ + saturn.PC += 4; + do_intoff(); + break; + default: + stop = true; + } + break; + case 9: /* C+P+1 */ + saturn.PC += 3; + add_p_plus_one( saturn.C ); + break; + case 0xa: /* RESET */ + saturn.PC += 3; + do_reset(); + break; + case 0xb: /* BUSCC */ + saturn.PC += 3; + break; + case 0xc: /* C=P n */ + op4 = read_nibble( saturn.PC + 3 ); + saturn.PC += 4; + set_register_nibble( saturn.C, op4, saturn.P ); + break; + case 0xd: /* P=C n */ + op4 = read_nibble( saturn.PC + 3 ); + saturn.PC += 4; + saturn.P = get_register_nibble( saturn.C, op4 ); + break; + case 0xe: /* SREQ? */ + saturn.PC += 3; + saturn.C[ 0 ] = 0; + saturn.SR = 0; + break; + case 0xf: /* CPEX n */ + op4 = read_nibble( saturn.PC + 3 ); + saturn.PC += 4; + t = get_register_nibble( saturn.C, op4 ); + set_register_nibble( saturn.C, op4, saturn.P ); + saturn.P = t; + break; + default: + stop = true; + } + break; + case 1: + op2 = read_nibble( saturn.PC + 2 ); + switch ( op2 ) { + case 0: /* ASLC */ + saturn.PC += 3; + shift_left_circ_register( saturn.A, W_FIELD ); + break; + case 1: /* BSLC */ + saturn.PC += 3; + shift_left_circ_register( saturn.B, W_FIELD ); + break; + case 2: /* CSLC */ + saturn.PC += 3; + shift_left_circ_register( saturn.C, W_FIELD ); + break; + case 3: /* DSLC */ + saturn.PC += 3; + shift_left_circ_register( saturn.D, W_FIELD ); + break; + case 4: /* ASRC */ + saturn.PC += 3; + shift_right_circ_register( saturn.A, W_FIELD ); + break; + case 5: /* BSRC */ + saturn.PC += 3; + shift_right_circ_register( saturn.B, W_FIELD ); + break; + case 6: /* CSRC */ + saturn.PC += 3; + shift_right_circ_register( saturn.C, W_FIELD ); + break; + case 7: /* DSRC */ + saturn.PC += 3; + shift_right_circ_register( saturn.D, W_FIELD ); + break; + case 8: /* R = R +/- CON */ + op3 = read_nibble( saturn.PC + 3 ); + op4 = read_nibble( saturn.PC + 4 ); + op5 = read_nibble( saturn.PC + 5 ); + if ( op4 < 8 ) { /* PLUS */ + switch ( op4 & 3 ) { + case 0: /* A=A+CON */ + saturn.PC += 6; + add_register_constant( saturn.A, op3, op5 + 1 ); + break; + case 1: /* B=B+CON */ + saturn.PC += 6; + add_register_constant( saturn.B, op3, op5 + 1 ); + break; + case 2: /* C=C+CON */ + saturn.PC += 6; + add_register_constant( saturn.C, op3, op5 + 1 ); + break; + case 3: /* D=D+CON */ + saturn.PC += 6; + add_register_constant( saturn.D, op3, op5 + 1 ); + break; + default: + stop = true; + } + } else { /* MINUS */ + switch ( op4 & 3 ) { + case 0: /* A=A-CON */ + saturn.PC += 6; + sub_register_constant( saturn.A, op3, op5 + 1 ); + break; + case 1: /* B=B-CON */ + saturn.PC += 6; + sub_register_constant( saturn.B, op3, op5 + 1 ); + break; + case 2: /* C=C-CON */ + saturn.PC += 6; + sub_register_constant( saturn.C, op3, op5 + 1 ); + break; + case 3: /* D=D-CON */ + saturn.PC += 6; + sub_register_constant( saturn.D, op3, op5 + 1 ); + break; + default: + stop = true; + } + } + break; + case 9: /* R SRB FIELD */ + op3 = read_nibble( saturn.PC + 3 ); + op4 = read_nibble( saturn.PC + 4 ); + switch ( op4 & 3 ) { + case 0: + saturn.PC += 5; + shift_right_bit_register( saturn.A, op3 ); + break; + case 1: + saturn.PC += 5; + shift_right_bit_register( saturn.B, op3 ); + break; + case 2: + saturn.PC += 5; + shift_right_bit_register( saturn.C, op3 ); + break; + case 3: + saturn.PC += 5; + shift_right_bit_register( saturn.D, op3 ); + break; + default: + stop = true; + } + break; + case 0xa: /* R = R FIELD, etc. */ + op3 = read_nibble( saturn.PC + 3 ); + op4 = read_nibble( saturn.PC + 4 ); + op5 = read_nibble( saturn.PC + 5 ); + switch ( op4 ) { + case 0: + switch ( op5 ) { + case 0: /* saturn.R0=A */ + saturn.PC += 6; + copy_register( saturn.R0, saturn.A, op3 ); + break; + case 1: /* saturn.R1=A */ + case 5: + saturn.PC += 6; + copy_register( saturn.R1, saturn.A, op3 ); + break; + case 2: /* saturn.R2=A */ + case 6: + saturn.PC += 6; + copy_register( saturn.R2, saturn.A, op3 ); + break; + case 3: /* saturn.R3=A */ + case 7: + saturn.PC += 6; + copy_register( saturn.R3, saturn.A, op3 ); + break; + case 4: /* saturn.R4=A */ + saturn.PC += 6; + copy_register( saturn.R4, saturn.A, op3 ); + break; + case 8: /* saturn.R0=C */ + saturn.PC += 6; + copy_register( saturn.R0, saturn.C, op3 ); + break; + case 9: /* saturn.R1=C */ + case 0xd: + saturn.PC += 6; + copy_register( saturn.R1, saturn.C, op3 ); + break; + case 0xa: /* saturn.R2=C */ + case 0xe: + saturn.PC += 6; + copy_register( saturn.R2, saturn.C, op3 ); + break; + case 0xb: /* saturn.R3=C */ + case 0xf: + saturn.PC += 6; + copy_register( saturn.R3, saturn.C, op3 ); + break; + case 0xc: /* saturn.R4=C */ + saturn.PC += 6; + copy_register( saturn.R4, saturn.C, op3 ); + break; + default: + stop = true; + } + break; + case 1: + switch ( op5 ) { + case 0: /* A=R0 */ + saturn.PC += 6; + copy_register( saturn.A, saturn.R0, op3 ); + break; + case 1: /* A=R1 */ + case 5: + saturn.PC += 6; + copy_register( saturn.A, saturn.R1, op3 ); + break; + case 2: /* A=R2 */ + case 6: + saturn.PC += 6; + copy_register( saturn.A, saturn.R2, op3 ); + break; + case 3: /* A=R3 */ + case 7: + saturn.PC += 6; + copy_register( saturn.A, saturn.R3, op3 ); + break; + case 4: /* A=R4 */ + saturn.PC += 6; + copy_register( saturn.A, saturn.R4, op3 ); + break; + case 8: /* C=R0 */ + saturn.PC += 6; + copy_register( saturn.C, saturn.R0, op3 ); + break; + case 9: /* C=R1 */ + case 0xd: + saturn.PC += 6; + copy_register( saturn.C, saturn.R1, op3 ); + break; + case 0xa: /* C=R2 */ + case 0xe: + saturn.PC += 6; + copy_register( saturn.C, saturn.R2, op3 ); + break; + case 0xb: /* C=R3 */ + case 0xf: + saturn.PC += 6; + copy_register( saturn.C, saturn.R3, op3 ); + break; + case 0xc: /* C=R4 */ + saturn.PC += 6; + copy_register( saturn.C, saturn.R4, op3 ); + break; + default: + stop = true; + } + break; + case 2: + switch ( op5 ) { + case 0: /* AR0EX */ + saturn.PC += 6; + exchange_register( saturn.A, saturn.R0, op3 ); + break; + case 1: /* AR1EX */ + case 5: + saturn.PC += 6; + exchange_register( saturn.A, saturn.R1, op3 ); + break; + case 2: /* AR2EX */ + case 6: + saturn.PC += 6; + exchange_register( saturn.A, saturn.R2, op3 ); + break; + case 3: /* AR3EX */ + case 7: + saturn.PC += 6; + exchange_register( saturn.A, saturn.R3, op3 ); + break; + case 4: /* AR4EX */ + saturn.PC += 6; + exchange_register( saturn.A, saturn.R4, op3 ); + break; + case 8: /* CR0EX */ + saturn.PC += 6; + exchange_register( saturn.C, saturn.R0, op3 ); + break; + case 9: /* CR1EX */ + case 0xd: + saturn.PC += 6; + exchange_register( saturn.C, saturn.R1, op3 ); + break; + case 0xa: /* CR2EX */ + case 0xe: + saturn.PC += 6; + exchange_register( saturn.C, saturn.R2, op3 ); + break; + case 0xb: /* CR3EX */ + case 0xf: + saturn.PC += 6; + exchange_register( saturn.C, saturn.R3, op3 ); + break; + case 0xc: /* CR4EX */ + saturn.PC += 6; + exchange_register( saturn.C, saturn.R4, op3 ); + break; + default: + stop = true; + } + break; + default: + stop = true; + } + break; + case 0xb: + op3 = read_nibble( saturn.PC + 3 ); + switch ( op3 ) { + case 2: /* PC=A */ + saturn.PC = dat_to_addr( saturn.A ); + break; + case 3: /* PC=C */ + saturn.PC = dat_to_addr( saturn.C ); + break; + case 4: /* A=PC */ + saturn.PC += 4; + addr_to_dat( saturn.PC, saturn.A ); + break; + case 5: /* C=PC */ + saturn.PC += 4; + addr_to_dat( saturn.PC, saturn.C ); + break; + case 6: /* APCEX */ + saturn.PC += 4; + addr_to_dat( saturn.PC, saturn.A ); + saturn.PC = dat_to_addr( saturn.A ); + break; + case 7: /* CPCEX */ + saturn.PC += 4; + addr_to_dat( saturn.PC, saturn.C ); + saturn.PC = dat_to_addr( saturn.C ); + break; + default: + stop = true; + } + break; + case 0xc: /* ASRB */ + saturn.PC += 3; + shift_right_bit_register( saturn.A, W_FIELD ); + break; + case 0xd: /* BSRB */ + saturn.PC += 3; + shift_right_bit_register( saturn.B, W_FIELD ); + break; + case 0xe: /* CSRB */ + saturn.PC += 3; + shift_right_bit_register( saturn.C, W_FIELD ); + break; + case 0xf: /* DSRB */ + saturn.PC += 3; + shift_right_bit_register( saturn.D, W_FIELD ); + break; + default: + stop = true; + } + break; + case 2: + op2 = read_nibble( saturn.PC + 2 ); + saturn.PC += 3; + clear_hardware_stat( op2 ); + break; + case 3: + op2 = read_nibble( saturn.PC + 2 ); + saturn.CARRY = is_zero_hardware_stat( op2 ); + if ( saturn.CARRY ) { + saturn.PC += 3; + op3 = read_nibbles( saturn.PC, 2 ); + if ( op3 ) { + if ( op3 & 0x80 ) + op3 |= jumpmasks[ 2 ]; + saturn.PC = ( saturn.PC + op3 ) & 0xfffff; + } else + saturn.PC = pop_return_addr(); + } else + saturn.PC += 5; + break; + case 4: + case 5: + op2 = read_nibble( saturn.PC + 2 ); + if ( op1 == 4 ) { + saturn.PC += 3; + clear_program_stat( op2 ); + } else { + saturn.PC += 3; + set_program_stat( op2 ); + } + break; + case 6: + case 7: + op2 = read_nibble( saturn.PC + 2 ); + if ( op1 == 6 ) + saturn.CARRY = ( get_program_stat( op2 ) == 0 ) ? 1 : 0; + else + saturn.CARRY = ( get_program_stat( op2 ) != 0 ) ? 1 : 0; + if ( saturn.CARRY ) { + saturn.PC += 3; + op3 = read_nibbles( saturn.PC, 2 ); + if ( op3 ) { + if ( op3 & 0x80 ) + op3 |= jumpmasks[ 2 ]; + saturn.PC = ( saturn.PC + op3 ) & 0xfffff; + } else + saturn.PC = pop_return_addr(); + } else + saturn.PC += 5; + break; + case 8: + case 9: + op2 = read_nibble( saturn.PC + 2 ); + if ( op1 == 8 ) + saturn.CARRY = ( saturn.P != op2 ) ? 1 : 0; + else + saturn.CARRY = ( saturn.P == op2 ) ? 1 : 0; + if ( saturn.CARRY ) { + saturn.PC += 3; + op3 = read_nibbles( saturn.PC, 2 ); + if ( op3 ) { + if ( op3 & 0x80 ) + op3 |= jumpmasks[ 2 ]; + saturn.PC = ( saturn.PC + op3 ) & 0xfffff; + } else + saturn.PC = pop_return_addr(); + } else + saturn.PC += 5; + break; + case 0xa: + op2 = read_nibble( saturn.PC + 2 ); + switch ( op2 ) { + case 0: /* ?A=B */ + saturn.CARRY = is_equal_register( saturn.A, saturn.B, A_FIELD ); + break; + case 1: /* ?B=C */ + saturn.CARRY = is_equal_register( saturn.B, saturn.C, A_FIELD ); + break; + case 2: /* ?A=C */ + saturn.CARRY = is_equal_register( saturn.A, saturn.C, A_FIELD ); + break; + case 3: /* ?C=D */ + saturn.CARRY = is_equal_register( saturn.C, saturn.D, A_FIELD ); + break; + case 4: /* ?A#B */ + saturn.CARRY = is_not_equal_register( saturn.A, saturn.B, A_FIELD ); + break; + case 5: /* ?B#C */ + saturn.CARRY = is_not_equal_register( saturn.B, saturn.C, A_FIELD ); + break; + case 6: /* ?A#C */ + saturn.CARRY = is_not_equal_register( saturn.A, saturn.C, A_FIELD ); + break; + case 7: /* ?C#D */ + saturn.CARRY = is_not_equal_register( saturn.C, saturn.D, A_FIELD ); + break; + case 8: /* ?A=0 */ + saturn.CARRY = is_zero_register( saturn.A, A_FIELD ); + break; + case 9: /* ?B=0 */ + saturn.CARRY = is_zero_register( saturn.B, A_FIELD ); + break; + case 0xa: /* ?C=0 */ + saturn.CARRY = is_zero_register( saturn.C, A_FIELD ); + break; + case 0xb: /* ?D=0 */ + saturn.CARRY = is_zero_register( saturn.D, A_FIELD ); + break; + case 0xc: /* ?A#0 */ + saturn.CARRY = is_not_zero_register( saturn.A, A_FIELD ); + break; + case 0xd: /* ?B#0 */ + saturn.CARRY = is_not_zero_register( saturn.B, A_FIELD ); + break; + case 0xe: /* ?C#0 */ + saturn.CARRY = is_not_zero_register( saturn.C, A_FIELD ); + break; + case 0xf: /* ?D#0 */ + saturn.CARRY = is_not_zero_register( saturn.D, A_FIELD ); + break; + default: + stop = true; + } + if ( saturn.CARRY ) { + saturn.PC += 3; + op3 = read_nibbles( saturn.PC, 2 ); + if ( op3 ) { + if ( op3 & 0x80 ) + op3 |= jumpmasks[ 2 ]; + saturn.PC = ( saturn.PC + op3 ) & 0xfffff; + } else + saturn.PC = pop_return_addr(); + } else + saturn.PC += 5; + break; + case 0xb: + op2 = read_nibble( saturn.PC + 2 ); + switch ( op2 ) { + case 0: /* ?A>B */ + saturn.CARRY = is_greater_register( saturn.A, saturn.B, A_FIELD ); + break; + case 1: /* ?B>C */ + saturn.CARRY = is_greater_register( saturn.B, saturn.C, A_FIELD ); + break; + case 2: /* ?C>A */ + saturn.CARRY = is_greater_register( saturn.C, saturn.A, A_FIELD ); + break; + case 3: /* ?D>C */ + saturn.CARRY = is_greater_register( saturn.D, saturn.C, A_FIELD ); + break; + case 4: /* ?A=B */ + saturn.CARRY = is_greater_or_equal_register( saturn.A, saturn.B, A_FIELD ); + break; + case 9: /* ?B>=C */ + saturn.CARRY = is_greater_or_equal_register( saturn.B, saturn.C, A_FIELD ); + break; + case 0xa: /* ?C>=A */ + saturn.CARRY = is_greater_or_equal_register( saturn.C, saturn.A, A_FIELD ); + break; + case 0xb: /* ?D>=C */ + saturn.CARRY = is_greater_or_equal_register( saturn.D, saturn.C, A_FIELD ); + break; + case 0xc: /* ?A<=B */ + saturn.CARRY = is_less_or_equal_register( saturn.A, saturn.B, A_FIELD ); + break; + case 0xd: /* ?B<=C */ + saturn.CARRY = is_less_or_equal_register( saturn.B, saturn.C, A_FIELD ); + break; + case 0xe: /* ?C<=A */ + saturn.CARRY = is_less_or_equal_register( saturn.C, saturn.A, A_FIELD ); + break; + case 0xf: /* ?D<=C */ + saturn.CARRY = is_less_or_equal_register( saturn.D, saturn.C, A_FIELD ); + break; + default: + stop = true; + } + if ( saturn.CARRY ) { + saturn.PC += 3; + op3 = read_nibbles( saturn.PC, 2 ); + if ( op3 ) { + if ( op3 & 0x80 ) + op3 |= jumpmasks[ 2 ]; + saturn.PC = ( saturn.PC + op3 ) & 0xfffff; + } else + saturn.PC = pop_return_addr(); + } else + saturn.PC += 5; + break; + case 0xc: + op2 = read_nibbles( saturn.PC + 2, 4 ); + if ( op2 & 0x8000 ) + op2 |= jumpmasks[ 4 ]; + saturn.PC = ( saturn.PC + op2 + 2 ) & 0xfffff; + break; + case 0xd: + op2 = read_nibbles( saturn.PC + 2, 5 ); + saturn.PC = op2; + break; + case 0xe: + op2 = read_nibbles( saturn.PC + 2, 4 ); + if ( op2 & 0x8000 ) + op2 |= jumpmasks[ 4 ]; + push_return_addr( saturn.PC + 6 ); + saturn.PC = ( saturn.PC + op2 + 6 ) & 0xfffff; + break; + case 0xf: + op2 = read_nibbles( saturn.PC + 2, 5 ); + push_return_addr( saturn.PC + 7 ); + saturn.PC = op2; + break; + default: + stop = true; + } break; + case 9: + op1 = read_nibble( saturn.PC + 1 ); + op2 = read_nibble( saturn.PC + 2 ); + if ( op1 < 8 ) { + switch ( op2 ) { + case 0: /* ?A=B */ + saturn.CARRY = is_equal_register( saturn.A, saturn.B, op1 ); + break; + case 1: /* ?B=C */ + saturn.CARRY = is_equal_register( saturn.B, saturn.C, op1 ); + break; + case 2: /* ?A=C */ + saturn.CARRY = is_equal_register( saturn.A, saturn.C, op1 ); + break; + case 3: /* ?C=D */ + saturn.CARRY = is_equal_register( saturn.C, saturn.D, op1 ); + break; + case 4: /* ?A#B */ + saturn.CARRY = is_not_equal_register( saturn.A, saturn.B, op1 ); + break; + case 5: /* ?B#C */ + saturn.CARRY = is_not_equal_register( saturn.B, saturn.C, op1 ); + break; + case 6: /* ?A#C */ + saturn.CARRY = is_not_equal_register( saturn.A, saturn.C, op1 ); + break; + case 7: /* ?C#D */ + saturn.CARRY = is_not_equal_register( saturn.C, saturn.D, op1 ); + break; + case 8: /* ?A=0 */ + saturn.CARRY = is_zero_register( saturn.A, op1 ); + break; + case 9: /* ?B=0 */ + saturn.CARRY = is_zero_register( saturn.B, op1 ); + break; + case 0xa: /* ?C=0 */ + saturn.CARRY = is_zero_register( saturn.C, op1 ); + break; + case 0xb: /* ?D=0 */ + saturn.CARRY = is_zero_register( saturn.D, op1 ); + break; + case 0xc: /* ?A#0 */ + saturn.CARRY = is_not_zero_register( saturn.A, op1 ); + break; + case 0xd: /* ?B#0 */ + saturn.CARRY = is_not_zero_register( saturn.B, op1 ); + break; + case 0xe: /* ?C#0 */ + saturn.CARRY = is_not_zero_register( saturn.C, op1 ); + break; + case 0xf: /* ?D#0 */ + saturn.CARRY = is_not_zero_register( saturn.D, op1 ); + break; + default: + stop = true; + } + } else { + op1 &= 7; + switch ( op2 ) { + case 0: /* ?A>B */ + saturn.CARRY = is_greater_register( saturn.A, saturn.B, op1 ); + break; + case 1: /* ?B>C */ + saturn.CARRY = is_greater_register( saturn.B, saturn.C, op1 ); + break; + case 2: /* ?C>A */ + saturn.CARRY = is_greater_register( saturn.C, saturn.A, op1 ); + break; + case 3: /* ?D>C */ + saturn.CARRY = is_greater_register( saturn.D, saturn.C, op1 ); + break; + case 4: /* ?A=B */ + saturn.CARRY = is_greater_or_equal_register( saturn.A, saturn.B, op1 ); + break; + case 9: /* ?B>=C */ + saturn.CARRY = is_greater_or_equal_register( saturn.B, saturn.C, op1 ); + break; + case 0xa: /* ?C>=A */ + saturn.CARRY = is_greater_or_equal_register( saturn.C, saturn.A, op1 ); + break; + case 0xb: /* ?D>=C */ + saturn.CARRY = is_greater_or_equal_register( saturn.D, saturn.C, op1 ); + break; + case 0xc: /* ?A<=B */ + saturn.CARRY = is_less_or_equal_register( saturn.A, saturn.B, op1 ); + break; + case 0xd: /* ?B<=C */ + saturn.CARRY = is_less_or_equal_register( saturn.B, saturn.C, op1 ); + break; + case 0xe: /* ?C<=A */ + saturn.CARRY = is_less_or_equal_register( saturn.C, saturn.A, op1 ); + break; + case 0xf: /* ?D<=C */ + saturn.CARRY = is_less_or_equal_register( saturn.D, saturn.C, op1 ); + break; + default: + stop = true; + } + } + if ( saturn.CARRY ) { + saturn.PC += 3; + op3 = read_nibbles( saturn.PC, 2 ); + if ( op3 ) { + if ( op3 & 0x80 ) + op3 |= jumpmasks[ 2 ]; + saturn.PC = ( saturn.PC + op3 ) & 0xfffff; + } else { + saturn.PC = pop_return_addr(); + } + } else { + saturn.PC += 5; + } + break; + case 0xa: + op1 = read_nibble( saturn.PC + 1 ); + op2 = read_nibble( saturn.PC + 2 ); + if ( op1 < 8 ) { + switch ( op2 ) { + case 0: /* A=A+B */ + saturn.PC += 3; + add_register( saturn.A, saturn.A, saturn.B, op1 ); + break; + case 1: /* B=B+C */ + saturn.PC += 3; + add_register( saturn.B, saturn.B, saturn.C, op1 ); + break; + case 2: /* C=C+A */ + saturn.PC += 3; + add_register( saturn.C, saturn.C, saturn.A, op1 ); + break; + case 3: /* D=D+C */ + saturn.PC += 3; + add_register( saturn.D, saturn.D, saturn.C, op1 ); + break; + case 4: /* A=A+A */ + saturn.PC += 3; + add_register( saturn.A, saturn.A, saturn.A, op1 ); + break; + case 5: /* B=B+B */ + saturn.PC += 3; + add_register( saturn.B, saturn.B, saturn.B, op1 ); + break; + case 6: /* C=C+C */ + saturn.PC += 3; + add_register( saturn.C, saturn.C, saturn.C, op1 ); + break; + case 7: /* D=D+D */ + saturn.PC += 3; + add_register( saturn.D, saturn.D, saturn.D, op1 ); + break; + case 8: /* B=B+A */ + saturn.PC += 3; + add_register( saturn.B, saturn.B, saturn.A, op1 ); + break; + case 9: /* C=C+B */ + saturn.PC += 3; + add_register( saturn.C, saturn.C, saturn.B, op1 ); + break; + case 0xa: /* A=A+C */ + saturn.PC += 3; + add_register( saturn.A, saturn.A, saturn.C, op1 ); + break; + case 0xb: /* C=C+D */ + saturn.PC += 3; + add_register( saturn.C, saturn.C, saturn.D, op1 ); + break; + case 0xc: /* A=A-1 */ + saturn.PC += 3; + dec_register( saturn.A, op1 ); + break; + case 0xd: /* B=B-1 */ + saturn.PC += 3; + dec_register( saturn.B, op1 ); + break; + case 0xe: /* C=C-1 */ + saturn.PC += 3; + dec_register( saturn.C, op1 ); + break; + case 0xf: /* D=D-1 */ + saturn.PC += 3; + dec_register( saturn.D, op1 ); + break; + default: + stop = true; + } + } else { + op1 &= 7; + switch ( op2 ) { + case 0: /* A=0 */ + saturn.PC += 3; + zero_register( saturn.A, op1 ); + break; + case 1: /* B=0 */ + saturn.PC += 3; + zero_register( saturn.B, op1 ); + break; + case 2: /* C=0 */ + saturn.PC += 3; + zero_register( saturn.C, op1 ); + break; + case 3: /* D=0 */ + saturn.PC += 3; + zero_register( saturn.D, op1 ); + break; + case 4: /* A=B */ + saturn.PC += 3; + copy_register( saturn.A, saturn.B, op1 ); + break; + case 5: /* B=C */ + saturn.PC += 3; + copy_register( saturn.B, saturn.C, op1 ); + break; + case 6: /* C=A */ + saturn.PC += 3; + copy_register( saturn.C, saturn.A, op1 ); + break; + case 7: /* D=C */ + saturn.PC += 3; + copy_register( saturn.D, saturn.C, op1 ); + break; + case 8: /* B=A */ + saturn.PC += 3; + copy_register( saturn.B, saturn.A, op1 ); + break; + case 9: /* C=B */ + saturn.PC += 3; + copy_register( saturn.C, saturn.B, op1 ); + break; + case 0xa: /* A=C */ + saturn.PC += 3; + copy_register( saturn.A, saturn.C, op1 ); + break; + case 0xb: /* C=D */ + saturn.PC += 3; + copy_register( saturn.C, saturn.D, op1 ); + break; + case 0xc: /* ABEX */ + saturn.PC += 3; + exchange_register( saturn.A, saturn.B, op1 ); + break; + case 0xd: /* BCEX */ + saturn.PC += 3; + exchange_register( saturn.B, saturn.C, op1 ); + break; + case 0xe: /* ACEX */ + saturn.PC += 3; + exchange_register( saturn.A, saturn.C, op1 ); + break; + case 0xf: /* CDEX */ + saturn.PC += 3; + exchange_register( saturn.C, saturn.D, op1 ); + break; + default: + stop = true; + } + } + break; + case 0xb: + op1 = read_nibble( saturn.PC + 1 ); + op2 = read_nibble( saturn.PC + 2 ); + if ( op1 < 8 ) { + switch ( op2 ) { + case 0: /* A=A-B */ + saturn.PC += 3; + sub_register( saturn.A, saturn.A, saturn.B, op1 ); + break; + case 1: /* B=B-C */ + saturn.PC += 3; + sub_register( saturn.B, saturn.B, saturn.C, op1 ); + break; + case 2: /* C=C-A */ + saturn.PC += 3; + sub_register( saturn.C, saturn.C, saturn.A, op1 ); + break; + case 3: /* D=D-C */ + saturn.PC += 3; + sub_register( saturn.D, saturn.D, saturn.C, op1 ); + break; + case 4: /* A=A+1 */ + saturn.PC += 3; + inc_register( saturn.A, op1 ); + break; + case 5: /* B=B+1 */ + saturn.PC += 3; + inc_register( saturn.B, op1 ); + break; + case 6: /* C=C+1 */ + saturn.PC += 3; + inc_register( saturn.C, op1 ); + break; + case 7: /* D=D+1 */ + saturn.PC += 3; + inc_register( saturn.D, op1 ); + break; + case 8: /* B=B-A */ + saturn.PC += 3; + sub_register( saturn.B, saturn.B, saturn.A, op1 ); + break; + case 9: /* C=C-B */ + saturn.PC += 3; + sub_register( saturn.C, saturn.C, saturn.B, op1 ); + break; + case 0xa: /* A=A-C */ + saturn.PC += 3; + sub_register( saturn.A, saturn.A, saturn.C, op1 ); + break; + case 0xb: /* C=C-D */ + saturn.PC += 3; + sub_register( saturn.C, saturn.C, saturn.D, op1 ); + break; + case 0xc: /* A=B-A */ + saturn.PC += 3; + sub_register( saturn.A, saturn.B, saturn.A, op1 ); + break; + case 0xd: /* B=C-B */ + saturn.PC += 3; + sub_register( saturn.B, saturn.C, saturn.B, op1 ); + break; + case 0xe: /* C=A-C */ + saturn.PC += 3; + sub_register( saturn.C, saturn.A, saturn.C, op1 ); + break; + case 0xf: /* D=C-D */ + saturn.PC += 3; + sub_register( saturn.D, saturn.C, saturn.D, op1 ); + break; + default: + stop = true; + } + } else { + op1 &= 7; + switch ( op2 ) { + case 0: /* ASL */ + saturn.PC += 3; + shift_left_register( saturn.A, op1 ); + break; + case 1: /* BSL */ + saturn.PC += 3; + shift_left_register( saturn.B, op1 ); + break; + case 2: /* CSL */ + saturn.PC += 3; + shift_left_register( saturn.C, op1 ); + break; + case 3: /* DSL */ + saturn.PC += 3; + shift_left_register( saturn.D, op1 ); + break; + case 4: /* ASR */ + saturn.PC += 3; + shift_right_register( saturn.A, op1 ); + break; + case 5: /* BSR */ + saturn.PC += 3; + shift_right_register( saturn.B, op1 ); + break; + case 6: /* CSR */ + saturn.PC += 3; + shift_right_register( saturn.C, op1 ); + break; + case 7: /* DSR */ + saturn.PC += 3; + shift_right_register( saturn.D, op1 ); + break; + case 8: /* A=-A */ + saturn.PC += 3; + complement_2_register( saturn.A, op1 ); + break; + case 9: /* B=-B */ + saturn.PC += 3; + complement_2_register( saturn.B, op1 ); + break; + case 0xa: /* C=-C */ + saturn.PC += 3; + complement_2_register( saturn.C, op1 ); + break; + case 0xb: /* D=-D */ + saturn.PC += 3; + complement_2_register( saturn.D, op1 ); + break; + case 0xc: /* A=-A-1 */ + saturn.PC += 3; + complement_1_register( saturn.A, op1 ); + break; + case 0xd: /* B=-B-1 */ + saturn.PC += 3; + complement_1_register( saturn.B, op1 ); + break; + case 0xe: /* C=-C-1 */ + saturn.PC += 3; + complement_1_register( saturn.C, op1 ); + break; + case 0xf: /* D=-D-1 */ + saturn.PC += 3; + complement_1_register( saturn.D, op1 ); + break; + default: + stop = true; + } + } + break; + case 0xc: + op1 = read_nibble( saturn.PC + 1 ); + switch ( op1 ) { + case 0: /* A=A+B */ + saturn.PC += 2; + add_register( saturn.A, saturn.A, saturn.B, A_FIELD ); + break; + case 1: /* B=B+C */ + saturn.PC += 2; + add_register( saturn.B, saturn.B, saturn.C, A_FIELD ); + break; + case 2: /* C=C+A */ + saturn.PC += 2; + add_register( saturn.C, saturn.C, saturn.A, A_FIELD ); + break; + case 3: /* D=D+C */ + saturn.PC += 2; + add_register( saturn.D, saturn.D, saturn.C, A_FIELD ); + break; + case 4: /* A=A+A */ + saturn.PC += 2; + add_register( saturn.A, saturn.A, saturn.A, A_FIELD ); + break; + case 5: /* B=B+B */ + saturn.PC += 2; + add_register( saturn.B, saturn.B, saturn.B, A_FIELD ); + break; + case 6: /* C=C+C */ + saturn.PC += 2; + add_register( saturn.C, saturn.C, saturn.C, A_FIELD ); + break; + case 7: /* D=D+D */ + saturn.PC += 2; + add_register( saturn.D, saturn.D, saturn.D, A_FIELD ); + break; + case 8: /* B=B+A */ + saturn.PC += 2; + add_register( saturn.B, saturn.B, saturn.A, A_FIELD ); + break; + case 9: /* C=C+B */ + saturn.PC += 2; + add_register( saturn.C, saturn.C, saturn.B, A_FIELD ); + break; + case 0xa: /* A=A+C */ + saturn.PC += 2; + add_register( saturn.A, saturn.A, saturn.C, A_FIELD ); + break; + case 0xb: /* C=C+D */ + saturn.PC += 2; + add_register( saturn.C, saturn.C, saturn.D, A_FIELD ); + break; + case 0xc: /* A=A-1 */ + saturn.PC += 2; + dec_register( saturn.A, A_FIELD ); + break; + case 0xd: /* B=B-1 */ + saturn.PC += 2; + dec_register( saturn.B, A_FIELD ); + break; + case 0xe: /* C=C-1 */ + saturn.PC += 2; + dec_register( saturn.C, A_FIELD ); + break; + case 0xf: /* D=D-1 */ + saturn.PC += 2; + dec_register( saturn.D, A_FIELD ); + break; + default: + stop = true; + } + break; + case 0xd: + op1 = read_nibble( saturn.PC + 1 ); + switch ( op1 ) { + case 0: /* A=0 */ + saturn.PC += 2; + zero_register( saturn.A, A_FIELD ); + break; + case 1: /* B=0 */ + saturn.PC += 2; + zero_register( saturn.B, A_FIELD ); + break; + case 2: /* C=0 */ + saturn.PC += 2; + zero_register( saturn.C, A_FIELD ); + break; + case 3: /* D=0 */ + saturn.PC += 2; + zero_register( saturn.D, A_FIELD ); + break; + case 4: /* A=B */ + saturn.PC += 2; + copy_register( saturn.A, saturn.B, A_FIELD ); + break; + case 5: /* B=C */ + saturn.PC += 2; + copy_register( saturn.B, saturn.C, A_FIELD ); + break; + case 6: /* C=A */ + saturn.PC += 2; + copy_register( saturn.C, saturn.A, A_FIELD ); + break; + case 7: /* D=C */ + saturn.PC += 2; + copy_register( saturn.D, saturn.C, A_FIELD ); + break; + case 8: /* B=A */ + saturn.PC += 2; + copy_register( saturn.B, saturn.A, A_FIELD ); + break; + case 9: /* C=B */ + saturn.PC += 2; + copy_register( saturn.C, saturn.B, A_FIELD ); + break; + case 0xa: /* A=C */ + saturn.PC += 2; + copy_register( saturn.A, saturn.C, A_FIELD ); + break; + case 0xb: /* C=D */ + saturn.PC += 2; + copy_register( saturn.C, saturn.D, A_FIELD ); + break; + case 0xc: /* ABEX */ + saturn.PC += 2; + exchange_register( saturn.A, saturn.B, A_FIELD ); + break; + case 0xd: /* BCEX */ + saturn.PC += 2; + exchange_register( saturn.B, saturn.C, A_FIELD ); + break; + case 0xe: /* ACEX */ + saturn.PC += 2; + exchange_register( saturn.A, saturn.C, A_FIELD ); + break; + case 0xf: /* CDEX */ + saturn.PC += 2; + exchange_register( saturn.C, saturn.D, A_FIELD ); + break; + default: + stop = true; + } + break; + case 0xe: + op1 = read_nibble( saturn.PC + 1 ); + switch ( op1 ) { + case 0: /* A=A-B */ + saturn.PC += 2; + sub_register( saturn.A, saturn.A, saturn.B, A_FIELD ); + break; + case 1: /* B=B-C */ + saturn.PC += 2; + sub_register( saturn.B, saturn.B, saturn.C, A_FIELD ); + break; + case 2: /* C=C-A */ + saturn.PC += 2; + sub_register( saturn.C, saturn.C, saturn.A, A_FIELD ); + break; + case 3: /* D=D-C */ + saturn.PC += 2; + sub_register( saturn.D, saturn.D, saturn.C, A_FIELD ); + break; + case 4: /* A=A+1 */ + saturn.PC += 2; + inc_register( saturn.A, A_FIELD ); + break; + case 5: /* B=B+1 */ + saturn.PC += 2; + inc_register( saturn.B, A_FIELD ); + break; + case 6: /* C=C+1 */ + saturn.PC += 2; + inc_register( saturn.C, A_FIELD ); + break; + case 7: /* D=D+1 */ + saturn.PC += 2; + inc_register( saturn.D, A_FIELD ); + break; + case 8: /* B=B-A */ + saturn.PC += 2; + sub_register( saturn.B, saturn.B, saturn.A, A_FIELD ); + break; + case 9: /* C=C-B */ + saturn.PC += 2; + sub_register( saturn.C, saturn.C, saturn.B, A_FIELD ); + break; + case 0xa: /* A=A-C */ + saturn.PC += 2; + sub_register( saturn.A, saturn.A, saturn.C, A_FIELD ); + break; + case 0xb: /* C=C-D */ + saturn.PC += 2; + sub_register( saturn.C, saturn.C, saturn.D, A_FIELD ); + break; + case 0xc: /* A=B-A */ + saturn.PC += 2; + sub_register( saturn.A, saturn.B, saturn.A, A_FIELD ); + break; + case 0xd: /* B=C-B */ + saturn.PC += 2; + sub_register( saturn.B, saturn.C, saturn.B, A_FIELD ); + break; + case 0xe: /* C=A-C */ + saturn.PC += 2; + sub_register( saturn.C, saturn.A, saturn.C, A_FIELD ); + break; + case 0xf: /* D=C-D */ + saturn.PC += 2; + sub_register( saturn.D, saturn.C, saturn.D, A_FIELD ); + break; + default: + stop = true; + } + break; + case 0xf: + op1 = read_nibble( saturn.PC + 1 ); + switch ( op1 ) { + case 0: /* ASL */ + saturn.PC += 2; + shift_left_register( saturn.A, A_FIELD ); + break; + case 1: /* BSL */ + saturn.PC += 2; + shift_left_register( saturn.B, A_FIELD ); + break; + case 2: /* CSL */ + saturn.PC += 2; + shift_left_register( saturn.C, A_FIELD ); + break; + case 3: /* DSL */ + saturn.PC += 2; + shift_left_register( saturn.D, A_FIELD ); + break; + case 4: /* ASR */ + saturn.PC += 2; + shift_right_register( saturn.A, A_FIELD ); + break; + case 5: /* BSR */ + saturn.PC += 2; + shift_right_register( saturn.B, A_FIELD ); + break; + case 6: /* CSR */ + saturn.PC += 2; + shift_right_register( saturn.C, A_FIELD ); + break; + case 7: /* DSR */ + saturn.PC += 2; + shift_right_register( saturn.D, A_FIELD ); + break; + case 8: /* A=-A */ + saturn.PC += 2; + complement_2_register( saturn.A, A_FIELD ); + break; + case 9: /* B=-B */ + saturn.PC += 2; + complement_2_register( saturn.B, A_FIELD ); + break; + case 0xa: /* C=-C */ + saturn.PC += 2; + complement_2_register( saturn.C, A_FIELD ); + break; + case 0xb: /* D=-D */ + saturn.PC += 2; + complement_2_register( saturn.D, A_FIELD ); + break; + case 0xc: /* A=-A-1 */ + saturn.PC += 2; + complement_1_register( saturn.A, A_FIELD ); + break; + case 0xd: /* B=-B-1 */ + saturn.PC += 2; + complement_1_register( saturn.B, A_FIELD ); + break; + case 0xe: /* C=-C-1 */ + saturn.PC += 2; + complement_1_register( saturn.C, A_FIELD ); + break; + case 0xf: /* D=-D-1 */ + saturn.PC += 2; + complement_1_register( saturn.D, A_FIELD ); + break; + default: + stop = true; + } + break; + default: + stop = true; } instructions++;