merge emu_actions.c into emu_emulate.c
This commit is contained in:
parent
f2d9fc67b4
commit
84328c19ae
5 changed files with 491 additions and 547 deletions
1
Makefile
1
Makefile
|
@ -36,7 +36,6 @@ endif
|
|||
DOTOS = src/emu_serial.o \
|
||||
src/emu_emulate.o \
|
||||
src/emu_init.o \
|
||||
src/emu_actions.o \
|
||||
src/emu_keyboard.o \
|
||||
src/emu_memory.o \
|
||||
src/emu_register.o \
|
||||
|
|
|
@ -1,498 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "runtime_options.h" /* only for inhibit_shutdown in do_shutdown() */
|
||||
#include "emulator.h"
|
||||
#include "emulator_inner.h"
|
||||
#include "romio.h"
|
||||
#include "ui.h" /* ui_get_event(); ui_update_LCD(); */
|
||||
|
||||
#include "debugger.h" /* in_debugger, enter_debugger */
|
||||
|
||||
static bool interrupt_called = false;
|
||||
extern long nibble_masks[ 16 ];
|
||||
|
||||
bool sigalarm_triggered = false;
|
||||
|
||||
bool first_press = true; // PATCH
|
||||
|
||||
int conf_bank1 = 0x00000;
|
||||
int conf_bank2 = 0x00000;
|
||||
|
||||
short conf_tab[] = { 1, 2, 2, 2, 2, 0 };
|
||||
|
||||
void do_in( void )
|
||||
{
|
||||
int i, in = 0, out = 0;
|
||||
|
||||
for ( i = 2; i >= 0; i-- ) {
|
||||
out <<= 4;
|
||||
out |= saturn.OUT[ i ];
|
||||
}
|
||||
|
||||
for ( i = 0; i < 9; i++ )
|
||||
if ( out & ( 1 << i ) )
|
||||
in |= saturn.keybuf.rows[ i ];
|
||||
|
||||
// PATCH
|
||||
// http://svn.berlios.de/wsvn/x48?op=comp&compare[]=/trunk@12&compare[]=/trunk@13
|
||||
// PAS TERRIBLE VISIBLEMENT
|
||||
|
||||
if ( saturn.PC == 0x00E31 && !first_press &&
|
||||
( ( out & 0x10 && in & 0x1 ) || // keys are Backspace
|
||||
( out & 0x40 && in & 0x7 ) || // right, left & down
|
||||
( out & 0x80 && in & 0x2 ) ) ) // up arrows
|
||||
{
|
||||
for ( i = 0; i < 9; i++ )
|
||||
if ( out & ( 1 << i ) )
|
||||
saturn.keybuf.rows[ i ] = 0;
|
||||
first_press = true;
|
||||
} else
|
||||
first_press = false;
|
||||
|
||||
// FIN PATCH
|
||||
|
||||
for ( i = 0; i < 4; i++ ) {
|
||||
saturn.IN[ i ] = in & 0xf;
|
||||
in >>= 4;
|
||||
}
|
||||
}
|
||||
|
||||
void clear_program_stat( int n ) { saturn.PSTAT[ n ] = 0; }
|
||||
|
||||
void set_program_stat( int n ) { saturn.PSTAT[ n ] = 1; }
|
||||
|
||||
int get_program_stat( int n ) { return saturn.PSTAT[ n ]; }
|
||||
|
||||
void register_to_status( unsigned char* r )
|
||||
{
|
||||
for ( int i = 0; i < 12; i++ ) {
|
||||
saturn.PSTAT[ i ] = ( r[ i / 4 ] >> ( i % 4 ) ) & 1;
|
||||
}
|
||||
}
|
||||
|
||||
void status_to_register( unsigned char* r )
|
||||
{
|
||||
for ( int i = 0; i < 12; i++ ) {
|
||||
if ( saturn.PSTAT[ i ] ) {
|
||||
r[ i / 4 ] |= 1 << ( i % 4 );
|
||||
} else {
|
||||
r[ i / 4 ] &= ~( 1 << ( i % 4 ) ) & 0xf;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void swap_register_status( unsigned char* r )
|
||||
{
|
||||
int tmp;
|
||||
|
||||
for ( int i = 0; i < 12; i++ ) {
|
||||
tmp = saturn.PSTAT[ i ];
|
||||
saturn.PSTAT[ i ] = ( r[ i / 4 ] >> ( i % 4 ) ) & 1;
|
||||
if ( tmp )
|
||||
r[ i / 4 ] |= 1 << ( i % 4 );
|
||||
else
|
||||
r[ i / 4 ] &= ~( 1 << ( i % 4 ) ) & 0xf;
|
||||
}
|
||||
}
|
||||
|
||||
void clear_status( void )
|
||||
{
|
||||
for ( int i = 0; i < 12; i++ )
|
||||
saturn.PSTAT[ i ] = 0;
|
||||
}
|
||||
|
||||
void set_register_nibble( unsigned char* reg, int n, unsigned char val ) { reg[ n ] = val; }
|
||||
|
||||
unsigned char get_register_nibble( unsigned char* reg, int n ) { return reg[ n ]; }
|
||||
|
||||
void set_register_bit( unsigned char* reg, int n ) { reg[ n / 4 ] |= ( 1 << ( n % 4 ) ); }
|
||||
|
||||
void clear_register_bit( unsigned char* reg, int n ) { reg[ n / 4 ] &= ~( 1 << ( n % 4 ) ); }
|
||||
|
||||
int get_register_bit( unsigned char* reg, int n ) { return ( ( int )( reg[ n / 4 ] & ( 1 << ( n % 4 ) ) ) > 0 ) ? 1 : 0; }
|
||||
|
||||
void do_reset( void )
|
||||
{
|
||||
for ( int i = 0; i < 6; i++ ) {
|
||||
saturn.mem_cntl[ i ].unconfigured = conf_tab[ i ];
|
||||
|
||||
saturn.mem_cntl[ i ].config[ 0 ] = 0x0;
|
||||
saturn.mem_cntl[ i ].config[ 1 ] = 0x0;
|
||||
}
|
||||
}
|
||||
|
||||
void do_inton( void ) { saturn.kbd_ien = true; }
|
||||
|
||||
void do_intoff( void ) { saturn.kbd_ien = false; }
|
||||
|
||||
void do_return_interupt( void )
|
||||
{
|
||||
if ( saturn.int_pending ) {
|
||||
saturn.int_pending = false;
|
||||
saturn.interruptable = false;
|
||||
saturn.PC = 0xf;
|
||||
} else {
|
||||
saturn.PC = pop_return_addr();
|
||||
saturn.interruptable = true;
|
||||
|
||||
if ( adj_time_pending ) {
|
||||
schedule_event = 0;
|
||||
sched_adjtime = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void do_interupt( void )
|
||||
{
|
||||
interrupt_called = true;
|
||||
if ( saturn.interruptable ) {
|
||||
push_return_addr( saturn.PC );
|
||||
saturn.PC = 0xf;
|
||||
saturn.interruptable = false;
|
||||
}
|
||||
}
|
||||
|
||||
void do_kbd_int( void )
|
||||
{
|
||||
do_interupt();
|
||||
if ( !saturn.interruptable )
|
||||
saturn.int_pending = true;
|
||||
}
|
||||
|
||||
void do_reset_interrupt_system( void )
|
||||
{
|
||||
saturn.kbd_ien = true;
|
||||
int gen_intr = 0;
|
||||
for ( int i = 0; i < 9; i++ ) {
|
||||
if ( saturn.keybuf.rows[ i ] != 0 ) {
|
||||
gen_intr = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( gen_intr )
|
||||
do_kbd_int();
|
||||
}
|
||||
|
||||
void do_unconfigure( void )
|
||||
{
|
||||
int i;
|
||||
unsigned int conf = 0;
|
||||
|
||||
for ( i = 4; i >= 0; i-- ) {
|
||||
conf <<= 4;
|
||||
conf |= saturn.C[ i ];
|
||||
}
|
||||
|
||||
for ( i = 0; i < 6; i++ ) {
|
||||
if ( saturn.mem_cntl[ i ].config[ 0 ] == conf ) {
|
||||
saturn.mem_cntl[ i ].unconfigured = conf_tab[ i ];
|
||||
|
||||
saturn.mem_cntl[ i ].config[ 0 ] = 0x0;
|
||||
saturn.mem_cntl[ i ].config[ 1 ] = 0x0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void do_configure( void )
|
||||
{
|
||||
int i;
|
||||
unsigned long conf = 0;
|
||||
|
||||
for ( i = 4; i >= 0; i-- ) {
|
||||
conf <<= 4;
|
||||
conf |= saturn.C[ i ];
|
||||
}
|
||||
|
||||
for ( i = 0; i < 6; i++ ) {
|
||||
if ( saturn.mem_cntl[ i ].unconfigured ) {
|
||||
saturn.mem_cntl[ i ].unconfigured--;
|
||||
saturn.mem_cntl[ i ].config[ saturn.mem_cntl[ i ].unconfigured ] = conf;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int get_identification( void )
|
||||
{
|
||||
int i;
|
||||
static int chip_id[] = { 0, 0, 0, 0, 0x05, 0xf6, 0x07, 0xf8, 0x01, 0xf2, 0, 0 };
|
||||
|
||||
for ( i = 0; i < 6; i++ )
|
||||
if ( saturn.mem_cntl[ i ].unconfigured )
|
||||
break;
|
||||
|
||||
int id = ( i < 6 ) ? chip_id[ 2 * i + ( 2 - saturn.mem_cntl[ i ].unconfigured ) ] : 0;
|
||||
|
||||
for ( i = 0; i < 3; i++ ) {
|
||||
saturn.C[ i ] = id & 0x0f;
|
||||
id >>= 4;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void do_shutdown( void )
|
||||
{
|
||||
if ( inhibit_shutdown )
|
||||
return;
|
||||
|
||||
/***************************/
|
||||
/* hpemu/src/opcodes.c:367 */
|
||||
/***************************/
|
||||
/* static void op807( byte* opc ) // SHUTDN */
|
||||
/* { */
|
||||
/* // TODO: Fix SHUTDN */
|
||||
/* if ( !cpu.in[ 0 ] && !cpu.in[ 1 ] && !cpu.in[ 3 ] ) { */
|
||||
/* cpu.shutdown = true; */
|
||||
/* } */
|
||||
/* cpu.pc += 3; */
|
||||
/* cpu.cycles += 5; */
|
||||
/* } */
|
||||
|
||||
/***********************************/
|
||||
/* saturn_bertolotti/src/cpu.c:364 */
|
||||
/***********************************/
|
||||
/* static void ExecSHUTDN( void ) */
|
||||
/* { */
|
||||
/* debug1( DEBUG_C_TRACE, CPU_I_CALLED, "SHUTDN" ); */
|
||||
|
||||
/* #ifdef CPU_SPIN_SHUTDN */
|
||||
/* /\* If the CPU_SPIN_SHUTDN symbol is defined, the CPU module implements */
|
||||
/* SHUTDN as a spin loop; the program counter is reset to the starting */
|
||||
/* nibble of the SHUTDN opcode. */
|
||||
/* *\/ */
|
||||
/* cpu_status.PC -= 3; */
|
||||
/* #endif */
|
||||
|
||||
/* /\* Set shutdown flag *\/ */
|
||||
/* cpu_status.shutdn = 1; */
|
||||
|
||||
/* #ifndef CPU_SPIN_SHUTDN */
|
||||
/* /\* If the CPU_SPIN_SHUTDN symbol is not defined, the CPU module implements */
|
||||
/* SHUTDN signalling the condition CPU_I_SHUTDN */
|
||||
/* *\/ */
|
||||
/* ChfCondition CPU_I_SHUTDN, CHF_INFO ChfEnd; */
|
||||
/* ChfSignal(); */
|
||||
/* #endif */
|
||||
/* } */
|
||||
|
||||
if ( device.display_touched ) {
|
||||
device.display_touched = 0;
|
||||
ui_refresh_LCD();
|
||||
}
|
||||
|
||||
stop_timer( RUN_TIMER );
|
||||
start_timer( IDLE_TIMER );
|
||||
|
||||
if ( is_zero_register( saturn.OUT, OUT_FIELD ) ) {
|
||||
saturn.interruptable = true;
|
||||
saturn.int_pending = false;
|
||||
}
|
||||
|
||||
bool wake = in_debugger;
|
||||
t1_t2_ticks ticks;
|
||||
|
||||
do {
|
||||
pause();
|
||||
|
||||
if ( sigalarm_triggered ) {
|
||||
sigalarm_triggered = false;
|
||||
|
||||
ui_refresh_LCD();
|
||||
|
||||
ticks = get_t1_t2();
|
||||
if ( saturn.t2_ctrl & 0x01 )
|
||||
saturn.timer2 = ticks.t2_ticks;
|
||||
|
||||
saturn.timer1 = set_t1 - ticks.t1_ticks;
|
||||
set_t1 = ticks.t1_ticks;
|
||||
|
||||
interrupt_called = false;
|
||||
ui_get_event();
|
||||
if ( interrupt_called )
|
||||
wake = true;
|
||||
|
||||
if ( saturn.timer2 <= 0 ) {
|
||||
if ( saturn.t2_ctrl & 0x04 )
|
||||
wake = true;
|
||||
|
||||
if ( saturn.t2_ctrl & 0x02 ) {
|
||||
wake = true;
|
||||
saturn.t2_ctrl |= 0x08;
|
||||
do_interupt();
|
||||
}
|
||||
}
|
||||
|
||||
if ( saturn.timer1 <= 0 ) {
|
||||
saturn.timer1 &= 0x0f;
|
||||
if ( saturn.t1_ctrl & 0x04 )
|
||||
wake = true;
|
||||
|
||||
if ( saturn.t1_ctrl & 0x03 ) {
|
||||
wake = true;
|
||||
saturn.t1_ctrl |= 0x08;
|
||||
do_interupt();
|
||||
}
|
||||
}
|
||||
|
||||
if ( !wake ) {
|
||||
interrupt_called = false;
|
||||
receive_char();
|
||||
if ( interrupt_called )
|
||||
wake = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( enter_debugger )
|
||||
wake = true;
|
||||
} while ( !wake );
|
||||
|
||||
stop_timer( IDLE_TIMER );
|
||||
start_timer( RUN_TIMER );
|
||||
}
|
||||
|
||||
void clear_hardware_stat( int op )
|
||||
{
|
||||
if ( op & 1 )
|
||||
saturn.XM = 0;
|
||||
if ( op & 2 )
|
||||
saturn.SB = 0;
|
||||
if ( op & 4 )
|
||||
saturn.SR = 0;
|
||||
if ( op & 8 )
|
||||
saturn.MP = 0;
|
||||
}
|
||||
|
||||
int is_zero_hardware_stat( int op )
|
||||
{
|
||||
if ( op & 1 )
|
||||
if ( saturn.XM != 0 )
|
||||
return 0;
|
||||
if ( op & 2 )
|
||||
if ( saturn.SB != 0 )
|
||||
return 0;
|
||||
if ( op & 4 )
|
||||
if ( saturn.SR != 0 )
|
||||
return 0;
|
||||
if ( op & 8 )
|
||||
if ( saturn.MP != 0 )
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void push_return_addr( long addr )
|
||||
{
|
||||
if ( ++saturn.rstkp >= NB_RSTK ) {
|
||||
for ( int i = 1; i < NB_RSTK; i++ )
|
||||
saturn.rstk[ i - 1 ] = saturn.rstk[ i ];
|
||||
|
||||
saturn.rstkp--;
|
||||
}
|
||||
saturn.rstk[ saturn.rstkp ] = addr;
|
||||
}
|
||||
|
||||
long pop_return_addr( void )
|
||||
{
|
||||
if ( saturn.rstkp < 0 )
|
||||
return 0;
|
||||
|
||||
return saturn.rstk[ saturn.rstkp-- ];
|
||||
}
|
||||
|
||||
void load_constant( unsigned char* reg, int n, long addr )
|
||||
{
|
||||
int p = saturn.P;
|
||||
|
||||
for ( int i = 0; i < n; i++ ) {
|
||||
reg[ p ] = read_nibble( addr + i );
|
||||
p = ( p + 1 ) & 0xf;
|
||||
}
|
||||
}
|
||||
|
||||
void load_addr( word_20* dat, long addr, int n )
|
||||
{
|
||||
for ( int i = 0; i < n; i++ ) {
|
||||
*dat &= ~nibble_masks[ i ];
|
||||
*dat |= read_nibble( addr + i ) << ( i * 4 );
|
||||
}
|
||||
}
|
||||
|
||||
void register_to_address( unsigned char* reg, word_20* dat, int s )
|
||||
{
|
||||
int n = ( s ) ? 4 : 5;
|
||||
|
||||
for ( int i = 0; i < n; i++ ) {
|
||||
*dat &= ~nibble_masks[ i ];
|
||||
*dat |= ( reg[ i ] & 0x0f ) << ( i * 4 );
|
||||
}
|
||||
}
|
||||
|
||||
long dat_to_addr( unsigned char* dat )
|
||||
{
|
||||
long addr = 0;
|
||||
|
||||
for ( int i = 4; i >= 0; i-- ) {
|
||||
addr <<= 4;
|
||||
addr |= ( dat[ i ] & 0xf );
|
||||
}
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
void addr_to_dat( long addr, unsigned char* dat )
|
||||
{
|
||||
for ( int i = 0; i < 5; i++ ) {
|
||||
dat[ i ] = ( addr & 0xf );
|
||||
addr >>= 4;
|
||||
}
|
||||
}
|
||||
|
||||
void add_address( word_20* dat, int add )
|
||||
{
|
||||
*dat += add;
|
||||
|
||||
if ( *dat & ( word_20 )0xfff00000 )
|
||||
saturn.CARRY = 1;
|
||||
else
|
||||
saturn.CARRY = 0;
|
||||
|
||||
*dat &= 0xfffff;
|
||||
}
|
||||
|
||||
void store( word_20 dat, unsigned char* reg, int code )
|
||||
{
|
||||
int s = get_start( code );
|
||||
int e = get_end( code );
|
||||
|
||||
for ( int i = s; i <= e; i++ )
|
||||
write_nibble( dat++, reg[ i ] );
|
||||
}
|
||||
|
||||
void store_n( word_20 dat, unsigned char* reg, int n )
|
||||
{
|
||||
for ( int i = 0; i < n; i++ )
|
||||
write_nibble( dat++, reg[ i ] );
|
||||
}
|
||||
|
||||
void recall( unsigned char* reg, word_20 dat, int code )
|
||||
{
|
||||
int s = get_start( code );
|
||||
int e = get_end( code );
|
||||
|
||||
for ( int i = s; i <= e; i++ )
|
||||
reg[ i ] = read_nibble_crc( dat++ );
|
||||
}
|
||||
|
||||
void recall_n( unsigned char* reg, word_20 dat, int n )
|
||||
{
|
||||
for ( int i = 0; i < n; i++ )
|
||||
reg[ i ] = read_nibble_crc( dat++ );
|
||||
}
|
||||
|
||||
/************/
|
||||
/* keyboard */
|
||||
/************/
|
|
@ -9,6 +9,8 @@
|
|||
#include "runtime_options.h" /* throttle */
|
||||
#include "ui.h" /* ui_get_event(); ui_adjust_contrast(); ui_update_LCD(); ui_draw_annunc(); */
|
||||
|
||||
#include "debugger.h" /* in_debugger, enter_debugger */
|
||||
|
||||
/* #define P_FIELD 0 /\* unused? *\/ */
|
||||
/* #define WP_FIELD 1 /\* unused? *\/ */
|
||||
/* #define XS_FIELD 2 /\* unused? *\/ */
|
||||
|
@ -34,6 +36,18 @@
|
|||
|
||||
#define NB_SAMPLES 10
|
||||
|
||||
static bool interrupt_called = false;
|
||||
extern long nibble_masks[ 16 ];
|
||||
|
||||
bool sigalarm_triggered = false;
|
||||
|
||||
bool first_press = true; // PATCH
|
||||
|
||||
int conf_bank1 = 0x00000;
|
||||
int conf_bank2 = 0x00000;
|
||||
|
||||
short conf_tab[] = { 1, 2, 2, 2, 2, 0 };
|
||||
|
||||
static long jumpaddr;
|
||||
|
||||
unsigned long instructions = 0;
|
||||
|
@ -76,6 +90,474 @@ saturn_t saturn;
|
|||
|
||||
device_t device;
|
||||
|
||||
static inline void push_return_addr( long addr )
|
||||
{
|
||||
if ( ++saturn.rstkp >= NB_RSTK ) {
|
||||
for ( int i = 1; i < NB_RSTK; i++ )
|
||||
saturn.rstk[ i - 1 ] = saturn.rstk[ i ];
|
||||
|
||||
saturn.rstkp--;
|
||||
}
|
||||
saturn.rstk[ saturn.rstkp ] = addr;
|
||||
}
|
||||
|
||||
static inline long pop_return_addr( void )
|
||||
{
|
||||
if ( saturn.rstkp < 0 )
|
||||
return 0;
|
||||
|
||||
return saturn.rstk[ saturn.rstkp-- ];
|
||||
}
|
||||
|
||||
static inline void do_in( void )
|
||||
{
|
||||
int i, in = 0, out = 0;
|
||||
|
||||
for ( i = 2; i >= 0; i-- ) {
|
||||
out <<= 4;
|
||||
out |= saturn.OUT[ i ];
|
||||
}
|
||||
|
||||
for ( i = 0; i < 9; i++ )
|
||||
if ( out & ( 1 << i ) )
|
||||
in |= saturn.keybuf.rows[ i ];
|
||||
|
||||
// PATCH
|
||||
// http://svn.berlios.de/wsvn/x48?op=comp&compare[]=/trunk@12&compare[]=/trunk@13
|
||||
// PAS TERRIBLE VISIBLEMENT
|
||||
|
||||
if ( saturn.PC == 0x00E31 && !first_press &&
|
||||
( ( out & 0x10 && in & 0x1 ) || // keys are Backspace
|
||||
( out & 0x40 && in & 0x7 ) || // right, left & down
|
||||
( out & 0x80 && in & 0x2 ) ) ) // up arrows
|
||||
{
|
||||
for ( i = 0; i < 9; i++ )
|
||||
if ( out & ( 1 << i ) )
|
||||
saturn.keybuf.rows[ i ] = 0;
|
||||
first_press = true;
|
||||
} else
|
||||
first_press = false;
|
||||
|
||||
// FIN PATCH
|
||||
|
||||
for ( i = 0; i < 4; i++ ) {
|
||||
saturn.IN[ i ] = in & 0xf;
|
||||
in >>= 4;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void clear_program_stat( int n ) { saturn.PSTAT[ n ] = 0; }
|
||||
|
||||
static inline void set_program_stat( int n ) { saturn.PSTAT[ n ] = 1; }
|
||||
|
||||
static inline int get_program_stat( int n ) { return saturn.PSTAT[ n ]; }
|
||||
|
||||
static inline void register_to_status( unsigned char* r )
|
||||
{
|
||||
for ( int i = 0; i < 12; i++ )
|
||||
saturn.PSTAT[ i ] = ( r[ i / 4 ] >> ( i % 4 ) ) & 1;
|
||||
}
|
||||
|
||||
static inline void status_to_register( unsigned char* r )
|
||||
{
|
||||
for ( int i = 0; i < 12; i++ )
|
||||
if ( saturn.PSTAT[ i ] )
|
||||
r[ i / 4 ] |= 1 << ( i % 4 );
|
||||
else
|
||||
r[ i / 4 ] &= ~( 1 << ( i % 4 ) ) & 0xf;
|
||||
}
|
||||
|
||||
static inline void swap_register_status( unsigned char* r )
|
||||
{
|
||||
int tmp;
|
||||
|
||||
for ( int i = 0; i < 12; i++ ) {
|
||||
tmp = saturn.PSTAT[ i ];
|
||||
saturn.PSTAT[ i ] = ( r[ i / 4 ] >> ( i % 4 ) ) & 1;
|
||||
if ( tmp )
|
||||
r[ i / 4 ] |= 1 << ( i % 4 );
|
||||
else
|
||||
r[ i / 4 ] &= ~( 1 << ( i % 4 ) ) & 0xf;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void clear_status( void )
|
||||
{
|
||||
for ( int i = 0; i < 12; i++ )
|
||||
saturn.PSTAT[ i ] = 0;
|
||||
}
|
||||
|
||||
static inline void set_register_nibble( unsigned char* reg, int n, unsigned char val ) { reg[ n ] = val; }
|
||||
|
||||
static inline unsigned char get_register_nibble( unsigned char* reg, int n ) { return reg[ n ]; }
|
||||
|
||||
static inline void set_register_bit( unsigned char* reg, int n ) { reg[ n / 4 ] |= ( 1 << ( n % 4 ) ); }
|
||||
|
||||
static inline void clear_register_bit( unsigned char* reg, int n ) { reg[ n / 4 ] &= ~( 1 << ( n % 4 ) ); }
|
||||
|
||||
static inline int get_register_bit( unsigned char* reg, int n ) { return ( ( int )( reg[ n / 4 ] & ( 1 << ( n % 4 ) ) ) > 0 ) ? 1 : 0; }
|
||||
|
||||
static inline void do_reset( void )
|
||||
{
|
||||
for ( int i = 0; i < 6; i++ ) {
|
||||
saturn.mem_cntl[ i ].unconfigured = conf_tab[ i ];
|
||||
|
||||
saturn.mem_cntl[ i ].config[ 0 ] = 0x0;
|
||||
saturn.mem_cntl[ i ].config[ 1 ] = 0x0;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void do_inton( void ) { saturn.kbd_ien = true; }
|
||||
|
||||
static inline void do_intoff( void ) { saturn.kbd_ien = false; }
|
||||
|
||||
static inline void do_return_interupt( void )
|
||||
{
|
||||
if ( saturn.int_pending ) {
|
||||
saturn.int_pending = false;
|
||||
saturn.interruptable = false;
|
||||
saturn.PC = 0xf;
|
||||
} else {
|
||||
saturn.PC = pop_return_addr();
|
||||
saturn.interruptable = true;
|
||||
|
||||
if ( adj_time_pending ) {
|
||||
schedule_event = 0;
|
||||
sched_adjtime = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void do_interupt( void )
|
||||
{
|
||||
interrupt_called = true;
|
||||
if ( saturn.interruptable ) {
|
||||
push_return_addr( saturn.PC );
|
||||
saturn.PC = 0xf;
|
||||
saturn.interruptable = false;
|
||||
}
|
||||
}
|
||||
|
||||
void do_kbd_int( void )
|
||||
{
|
||||
do_interupt();
|
||||
if ( !saturn.interruptable )
|
||||
saturn.int_pending = true;
|
||||
}
|
||||
|
||||
static inline void do_reset_interrupt_system( void )
|
||||
{
|
||||
saturn.kbd_ien = true;
|
||||
int gen_intr = 0;
|
||||
for ( int i = 0; i < 9; i++ ) {
|
||||
if ( saturn.keybuf.rows[ i ] != 0 ) {
|
||||
gen_intr = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( gen_intr )
|
||||
do_kbd_int();
|
||||
}
|
||||
|
||||
static inline void do_unconfigure( void )
|
||||
{
|
||||
int i;
|
||||
unsigned int conf = 0;
|
||||
|
||||
for ( i = 4; i >= 0; i-- ) {
|
||||
conf <<= 4;
|
||||
conf |= saturn.C[ i ];
|
||||
}
|
||||
|
||||
for ( i = 0; i < 6; i++ ) {
|
||||
if ( saturn.mem_cntl[ i ].config[ 0 ] == conf ) {
|
||||
saturn.mem_cntl[ i ].unconfigured = conf_tab[ i ];
|
||||
|
||||
saturn.mem_cntl[ i ].config[ 0 ] = 0x0;
|
||||
saturn.mem_cntl[ i ].config[ 1 ] = 0x0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void do_configure( void )
|
||||
{
|
||||
int i;
|
||||
unsigned long conf = 0;
|
||||
|
||||
for ( i = 4; i >= 0; i-- ) {
|
||||
conf <<= 4;
|
||||
conf |= saturn.C[ i ];
|
||||
}
|
||||
|
||||
for ( i = 0; i < 6; i++ ) {
|
||||
if ( saturn.mem_cntl[ i ].unconfigured ) {
|
||||
saturn.mem_cntl[ i ].unconfigured--;
|
||||
saturn.mem_cntl[ i ].config[ saturn.mem_cntl[ i ].unconfigured ] = conf;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline int get_identification( void )
|
||||
{
|
||||
int i;
|
||||
static int chip_id[] = { 0, 0, 0, 0, 0x05, 0xf6, 0x07, 0xf8, 0x01, 0xf2, 0, 0 };
|
||||
|
||||
for ( i = 0; i < 6; i++ )
|
||||
if ( saturn.mem_cntl[ i ].unconfigured )
|
||||
break;
|
||||
|
||||
int id = ( i < 6 ) ? chip_id[ 2 * i + ( 2 - saturn.mem_cntl[ i ].unconfigured ) ] : 0;
|
||||
|
||||
for ( i = 0; i < 3; i++ ) {
|
||||
saturn.C[ i ] = id & 0x0f;
|
||||
id >>= 4;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void do_shutdown( void )
|
||||
{
|
||||
if ( inhibit_shutdown )
|
||||
return;
|
||||
|
||||
/***************************/
|
||||
/* hpemu/src/opcodes.c:367 */
|
||||
/***************************/
|
||||
/* static void op807( byte* opc ) // SHUTDN */
|
||||
/* { */
|
||||
/* // TODO: Fix SHUTDN */
|
||||
/* if ( !cpu.in[ 0 ] && !cpu.in[ 1 ] && !cpu.in[ 3 ] ) { */
|
||||
/* cpu.shutdown = true; */
|
||||
/* } */
|
||||
/* cpu.pc += 3; */
|
||||
/* cpu.cycles += 5; */
|
||||
/* } */
|
||||
|
||||
/***********************************/
|
||||
/* saturn_bertolotti/src/cpu.c:364 */
|
||||
/***********************************/
|
||||
/* static void ExecSHUTDN( void ) */
|
||||
/* { */
|
||||
/* debug1( DEBUG_C_TRACE, CPU_I_CALLED, "SHUTDN" ); */
|
||||
|
||||
/* #ifdef CPU_SPIN_SHUTDN */
|
||||
/* /\* If the CPU_SPIN_SHUTDN symbol is defined, the CPU module implements */
|
||||
/* SHUTDN as a spin loop; the program counter is reset to the starting */
|
||||
/* nibble of the SHUTDN opcode. */
|
||||
/* *\/ */
|
||||
/* cpu_status.PC -= 3; */
|
||||
/* #endif */
|
||||
|
||||
/* /\* Set shutdown flag *\/ */
|
||||
/* cpu_status.shutdn = 1; */
|
||||
|
||||
/* #ifndef CPU_SPIN_SHUTDN */
|
||||
/* /\* If the CPU_SPIN_SHUTDN symbol is not defined, the CPU module implements */
|
||||
/* SHUTDN signalling the condition CPU_I_SHUTDN */
|
||||
/* *\/ */
|
||||
/* ChfCondition CPU_I_SHUTDN, CHF_INFO ChfEnd; */
|
||||
/* ChfSignal(); */
|
||||
/* #endif */
|
||||
/* } */
|
||||
|
||||
if ( device.display_touched ) {
|
||||
device.display_touched = 0;
|
||||
ui_refresh_LCD();
|
||||
}
|
||||
|
||||
stop_timer( RUN_TIMER );
|
||||
start_timer( IDLE_TIMER );
|
||||
|
||||
if ( is_zero_register( saturn.OUT, OUT_FIELD ) ) {
|
||||
saturn.interruptable = true;
|
||||
saturn.int_pending = false;
|
||||
}
|
||||
|
||||
bool wake = in_debugger;
|
||||
t1_t2_ticks ticks;
|
||||
|
||||
do {
|
||||
pause();
|
||||
|
||||
if ( sigalarm_triggered ) {
|
||||
sigalarm_triggered = false;
|
||||
|
||||
ui_refresh_LCD();
|
||||
|
||||
ticks = get_t1_t2();
|
||||
if ( saturn.t2_ctrl & 0x01 )
|
||||
saturn.timer2 = ticks.t2_ticks;
|
||||
|
||||
saturn.timer1 = set_t1 - ticks.t1_ticks;
|
||||
set_t1 = ticks.t1_ticks;
|
||||
|
||||
interrupt_called = false;
|
||||
ui_get_event();
|
||||
if ( interrupt_called )
|
||||
wake = true;
|
||||
|
||||
if ( saturn.timer2 <= 0 ) {
|
||||
if ( saturn.t2_ctrl & 0x04 )
|
||||
wake = true;
|
||||
|
||||
if ( saturn.t2_ctrl & 0x02 ) {
|
||||
wake = true;
|
||||
saturn.t2_ctrl |= 0x08;
|
||||
do_interupt();
|
||||
}
|
||||
}
|
||||
|
||||
if ( saturn.timer1 <= 0 ) {
|
||||
saturn.timer1 &= 0x0f;
|
||||
if ( saturn.t1_ctrl & 0x04 )
|
||||
wake = true;
|
||||
|
||||
if ( saturn.t1_ctrl & 0x03 ) {
|
||||
wake = true;
|
||||
saturn.t1_ctrl |= 0x08;
|
||||
do_interupt();
|
||||
}
|
||||
}
|
||||
|
||||
if ( !wake ) {
|
||||
interrupt_called = false;
|
||||
receive_char();
|
||||
if ( interrupt_called )
|
||||
wake = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( enter_debugger )
|
||||
wake = true;
|
||||
} while ( !wake );
|
||||
|
||||
stop_timer( IDLE_TIMER );
|
||||
start_timer( RUN_TIMER );
|
||||
}
|
||||
|
||||
static inline void clear_hardware_stat( int op )
|
||||
{
|
||||
if ( op & 1 )
|
||||
saturn.XM = 0;
|
||||
if ( op & 2 )
|
||||
saturn.SB = 0;
|
||||
if ( op & 4 )
|
||||
saturn.SR = 0;
|
||||
if ( op & 8 )
|
||||
saturn.MP = 0;
|
||||
}
|
||||
|
||||
static inline int is_zero_hardware_stat( int op )
|
||||
{
|
||||
if ( op & 1 )
|
||||
if ( saturn.XM != 0 )
|
||||
return 0;
|
||||
if ( op & 2 )
|
||||
if ( saturn.SB != 0 )
|
||||
return 0;
|
||||
if ( op & 4 )
|
||||
if ( saturn.SR != 0 )
|
||||
return 0;
|
||||
if ( op & 8 )
|
||||
if ( saturn.MP != 0 )
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline void load_constant( unsigned char* reg, int n, long addr )
|
||||
{
|
||||
int p = saturn.P;
|
||||
|
||||
for ( int i = 0; i < n; i++ ) {
|
||||
reg[ p ] = read_nibble( addr + i );
|
||||
p = ( p + 1 ) & 0xf;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void register_to_address( unsigned char* reg, word_20* dat, int s )
|
||||
{
|
||||
int n = ( s ) ? 4 : 5;
|
||||
|
||||
for ( int i = 0; i < n; i++ ) {
|
||||
*dat &= ~nibble_masks[ i ];
|
||||
*dat |= ( reg[ i ] & 0x0f ) << ( i * 4 );
|
||||
}
|
||||
}
|
||||
|
||||
static inline long dat_to_addr( unsigned char* dat )
|
||||
{
|
||||
long addr = 0;
|
||||
|
||||
for ( int i = 4; i >= 0; i-- ) {
|
||||
addr <<= 4;
|
||||
addr |= ( dat[ i ] & 0xf );
|
||||
}
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
static inline void addr_to_dat( long addr, unsigned char* dat )
|
||||
{
|
||||
for ( int i = 0; i < 5; i++ ) {
|
||||
dat[ i ] = ( addr & 0xf );
|
||||
addr >>= 4;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void add_address( word_20* dat, int add )
|
||||
{
|
||||
*dat += add;
|
||||
|
||||
if ( *dat & ( word_20 )0xfff00000 )
|
||||
saturn.CARRY = 1;
|
||||
else
|
||||
saturn.CARRY = 0;
|
||||
|
||||
*dat &= 0xfffff;
|
||||
}
|
||||
|
||||
static inline void store( word_20 dat, unsigned char* reg, int code )
|
||||
{
|
||||
int s = get_start( code );
|
||||
int e = get_end( code );
|
||||
|
||||
for ( int i = s; i <= e; i++ )
|
||||
write_nibble( dat++, reg[ i ] );
|
||||
}
|
||||
|
||||
static inline void store_n( word_20 dat, unsigned char* reg, int n )
|
||||
{
|
||||
for ( int i = 0; i < n; i++ )
|
||||
write_nibble( dat++, reg[ i ] );
|
||||
}
|
||||
|
||||
static inline void recall( unsigned char* reg, word_20 dat, int code )
|
||||
{
|
||||
int s = get_start( code );
|
||||
int e = get_end( code );
|
||||
|
||||
for ( int i = s; i <= e; i++ )
|
||||
reg[ i ] = read_nibble_crc( dat++ );
|
||||
}
|
||||
|
||||
static inline void recall_n( unsigned char* reg, word_20 dat, int n )
|
||||
{
|
||||
for ( int i = 0; i < n; i++ )
|
||||
reg[ i ] = read_nibble_crc( dat++ );
|
||||
}
|
||||
|
||||
void load_addr( word_20* dat, long addr, int n )
|
||||
{
|
||||
for ( int i = 0; i < n; i++ ) {
|
||||
*dat &= ~nibble_masks[ i ];
|
||||
*dat |= read_nibble( addr + i ) << ( i * 4 );
|
||||
}
|
||||
}
|
||||
|
||||
int decode_group_80( void )
|
||||
{
|
||||
int t, op3, op4, op5, op6;
|
||||
|
|
|
@ -347,12 +347,6 @@ extern int ( *read_nibble )( long addr );
|
|||
/****************/
|
||||
extern long read_nibbles( long addr, int len );
|
||||
|
||||
/*****************/
|
||||
/* emu_actions.c */
|
||||
/*****************/
|
||||
extern void load_addr( word_20* dat, long addr, int n );
|
||||
extern void do_kbd_int( void );
|
||||
|
||||
/******************/
|
||||
/* emu_keyboard.c */
|
||||
/******************/
|
||||
|
@ -368,8 +362,10 @@ extern int init_serial( void );
|
|||
/*****************/
|
||||
/* emu_emulate.c */
|
||||
/*****************/
|
||||
extern void emulate( void );
|
||||
extern void load_addr( word_20* dat, long addr, int n );
|
||||
extern void do_kbd_int( void );
|
||||
extern int step_instruction( void );
|
||||
extern void schedule( void );
|
||||
extern void emulate( void );
|
||||
|
||||
#endif /* !_EMULATOR_H */
|
||||
|
|
|
@ -20,8 +20,13 @@ extern void reset_timer( int timer );
|
|||
extern void restart_timer( int timer );
|
||||
extern word_64 get_timer( int timer );
|
||||
|
||||
/*****************/
|
||||
/* emu_emulate.c */
|
||||
/*****************/
|
||||
extern void do_interupt( void );
|
||||
|
||||
/********************/
|
||||
/* hp48emu_memory.c */
|
||||
/* emu_memory.c */
|
||||
/********************/
|
||||
extern void ( *write_nibble )( long addr, int val );
|
||||
extern int ( *read_nibble_crc )( long addr );
|
||||
|
@ -31,46 +36,6 @@ extern int ( *read_nibble_crc )( long addr );
|
|||
/****************/
|
||||
extern void dev_memory_init( void ); /* */
|
||||
|
||||
/*****************/
|
||||
/* emu_actions.c */
|
||||
/*****************/
|
||||
void push_return_addr( long addr );
|
||||
long pop_return_addr( void );
|
||||
void register_to_status( unsigned char* r );
|
||||
void status_to_register( unsigned char* r );
|
||||
void swap_register_status( unsigned char* r );
|
||||
void clear_status( void );
|
||||
void set_program_stat( int n );
|
||||
void clear_program_stat( int n );
|
||||
int get_program_stat( int n );
|
||||
void clear_hardware_stat( int op );
|
||||
int is_zero_hardware_stat( int op );
|
||||
void set_register_bit( unsigned char* reg, int n );
|
||||
void clear_register_bit( unsigned char* reg, int n );
|
||||
int get_register_bit( unsigned char* reg, int n );
|
||||
void set_register_nibble( unsigned char* reg, int n, unsigned char val );
|
||||
unsigned char get_register_nibble( unsigned char* reg, int n );
|
||||
void register_to_address( unsigned char* reg, word_20* dat, int s );
|
||||
void add_address( word_20* dat, int add );
|
||||
void load_constant( unsigned char* reg, int n, long addr );
|
||||
void store( word_20 dat, unsigned char* reg, int code );
|
||||
void store_n( word_20 dat, unsigned char* reg, int n );
|
||||
void recall( unsigned char* reg, word_20 dat, int code );
|
||||
void recall_n( unsigned char* reg, word_20 dat, int n );
|
||||
long dat_to_addr( unsigned char* dat );
|
||||
void addr_to_dat( long addr, unsigned char* dat );
|
||||
void do_interupt( void );
|
||||
void do_in( void );
|
||||
void do_reset( void );
|
||||
void do_configure( void );
|
||||
void do_unconfigure( void );
|
||||
void do_inton( void );
|
||||
void do_intoff( void );
|
||||
void do_return_interupt( void );
|
||||
void do_reset_interrupt_system( void );
|
||||
void do_shutdown( void );
|
||||
int get_identification( void );
|
||||
|
||||
/******************/
|
||||
/* emu_register.c */
|
||||
/******************/
|
||||
|
|
Loading…
Reference in a new issue