SCP, HP2100, HP3000, I650: Move one time initialization activities to cpu_reset

The paradigm of using a "weak" linker reference to find what was
previously the vm_init_routine() doesn't work reliably on all compile
environments supported by the simulators.  This has been reported
in #794 and it came up again in #862.  This change assures that
it will not come up again AND it reliably solves the problem with
Visual Studio compilers (and linker) that randomly chooses whether
to have the desired effect or not.

Of the 82 simulators which are currently part of simh, only these
three used the sim_vm_init() interface, so removing it had relatively
minor impact.
This commit is contained in:
Mark Pizzolato 2020-05-26 06:25:01 -07:00
parent 6b5d3d0c7e
commit f519513f50
13 changed files with 62 additions and 38 deletions

View file

@ -3504,6 +3504,9 @@ static t_stat cpu_reset (DEVICE *dptr)
t_stat status;
if (sim_PC == NULL) { /* if this is the first call after simulator start */
hp_one_time_init(); /* perform one time initializations (previously defined as sim_vm_init() */
status = mem_initialize (PA_MAX); /* then allocate main memory */
if (status == SCPE_OK) { /* if memory initialization succeeds */

View file

@ -934,3 +934,5 @@ extern void hp_initialize_trace (uint32 device_max, uint32 flag_max);
extern void hp_trace (DEVICE *dptr, uint32 flag, ...);
extern void hp_enbdis_pair (DEVICE *ccptr, DEVICE *dcptr);
extern int32 hp_sync_poll (POLLMODE poll_mode);
extern void hp_one_time_init (void); /* One time initialization activities now called in cpu_reset() */

View file

@ -117,8 +117,8 @@
/* Global release string */
const char *sim_vm_release = "29"; /* HP 2100 simulator release number */
const char *sim_vm_release_message =
const char *hp_vm_release = "29"; /* HP 2100 simulator release number */
const char *hp_vm_release_message =
"This is the last version of this simulator which is API compatible\n"
"with the 4.x version of the simh framework. A supported version of\n"
"this simulator can be found at: http://simh.trailing-edge.com/hp\n";
@ -1868,7 +1868,7 @@ static DEVICE poll_dev = {
/* System interface local SCP support routines */
static void one_time_init (void);
void hp_one_time_init (void);
static t_bool fprint_stopped (FILE *st, t_stat reason);
static void fprint_addr (FILE *st, DEVICE *dptr, t_addr addr);
static t_addr parse_addr (DEVICE *dptr, CONST char *cptr, CONST char **tptr);
@ -1934,8 +1934,6 @@ char sim_name [] = "HP 2100"; /* the simulator name */
int32 sim_emax = MAX_INSTR_LENGTH; /* the maximum number of words in any instruction */
void (*sim_vm_init) (void) = &one_time_init; /* a pointer to the one-time initializer */
DEVICE *sim_devices [] = { /* an array of pointers to the simulated devices */
&cpu_dev, /* CPU (must be first) */
&dma1_dev, &dma2_dev, /* DMA/DCPC */
@ -3503,9 +3501,17 @@ return;
breakpoint types.
*/
static void one_time_init (void)
void hp_one_time_init (void)
{
CTAB *systab, *auxtab = aux_cmds;
static int inited = 0;
if (inited == 1) /* Be sure to only do these things once */
return;
inited = 1;
sim_vm_release = hp_vm_release;
sim_vm_release_message = hp_vm_release_message;
while (auxtab->name != NULL) { /* loop through the auxiliary command table */
systab = find_cmd (auxtab->name); /* find the corresponding system command table entry */

View file

@ -3431,6 +3431,9 @@ return SCPE_OK; /* return the success of
static t_stat cpu_reset (DEVICE *dptr)
{
if (sim_PC == NULL) { /* if this is the first call after simulator start */
hp_one_time_init(); /* perform one time initializations (previously defined as sim_vm_init() */
if (mem_initialize (PA_MAX)) {
set_model (&cpu_unit [0], UNIT_SERIES_III, /* so establish the initial CPU model */
NULL, NULL);

View file

@ -719,3 +719,5 @@ extern const char *fmt_bitset (uint32 bitset, const BITSET_FORMAT bitfmt);
extern void hp_debug (DEVICE *dptr, uint32 flag, ...);
extern t_bool hp_device_conflict (void);
extern void hp_one_time_init (void); /* One time initialization activities now called in cpu_reset() */

View file

@ -84,8 +84,8 @@
/* Global release string */
const char *sim_vm_release = "8"; /* HP 3000 simulator release number */
const char *sim_vm_release_message =
const char *hp_vm_release = "8"; /* HP 3000 simulator release number */
const char *hp_vm_release_message =
"This is the last version of this simulator which is API compatible\n"
"with the 4.x version of the simh framework. A supported version of\n"
"this simulator can be found at: http://simh.trailing-edge.com/hp\n";
@ -974,7 +974,7 @@ static const char *const edit_ops [] = { /* EDIT operation names */
/* System interface local SCP support routines */
static void one_time_init (void);
void hp_one_time_init (void);
static t_bool fprint_stopped (FILE *st, t_stat reason);
static void fprint_addr (FILE *st, DEVICE *dptr, t_addr addr);
static t_addr parse_addr (DEVICE *dptr, CONST char *cptr, CONST char **tptr);
@ -1082,8 +1082,6 @@ char sim_name [] = "HP 3000"; /* the simulator name */
int32 sim_emax = 2; /* the maximum number of words in any instruction */
void (*sim_vm_init) (void) = &one_time_init; /* a pointer to the one-time initializer */
DEVICE *sim_devices [] = { /* an array of pointers to the simulated devices */
&cpu_dev, /* CPU (must be first) */
&iop_dev, /* I/O Processor */
@ -2673,9 +2671,17 @@ return (conflict_is != None); /* return TRUE if any co
breakpoint types.
*/
static void one_time_init (void)
void hp_one_time_init (void)
{
CTAB *contab, *systab, *auxtab = aux_cmds;
static int inited = 0;
if (inited == 1) /* Be sure to only do these things once */
return;
inited = 1;
sim_vm_release = hp_vm_release;
sim_vm_release_message = hp_vm_release_message;
contab = find_cmd ("CONT"); /* find the entry for the CONTINUE command */

View file

@ -2039,6 +2039,9 @@ cpu_reset(DEVICE * dptr)
IR[0] = IR[1] = IR[2] = 0;
sim_brk_types = sim_brk_dflt = SWMASK('E');
vm_init ();
return SCPE_OK;
}

View file

@ -371,5 +371,6 @@ extern int Get_HiDigit(t_int64 d);
extern int Shift_Digits(t_int64 * d, int nDigits);
extern char * word_to_ascii(char * buf, int CharStart, int CharLen, t_int64 d);
extern void vm_init(void); /* One time initialization activities now called in cpu_reset() */

View file

@ -209,6 +209,12 @@ char sim_hol_to_ascii(uint16 hol)
void
vm_init(void) {
int i;
static int inited = 0;
if (inited == 1) /* Be sure to only do these things once */
return;
inited = 1;
// Initialize vm memory to all plus zero
for(i = 0; i < MAXDRUMSIZE; i++) DRUM[i] = DRUM_NegativeZeroFlag[i] = 0;
for(i = 0; i < 60; i++) IAS[i] = IAS_NegativeZeroFlag[i] = 0;
@ -218,8 +224,6 @@ vm_init(void) {
}
void (*sim_vm_init) (void) = &vm_init;
/* Load a card image file into memory. */
t_stat

Binary file not shown.

15
scp.c
View file

@ -439,9 +439,16 @@ t_bool sim_asynch_enabled = FALSE;
#endif
/* The per-simulator init routine is a weak global that defaults to NULL
The other per-simulator pointers can be overrriden by the init routine */
The other per-simulator pointers can be overrriden by the init routine
WEAK void (*sim_vm_init) (void);
This routine is no longer invoked this way since it doesn't work reliably
on all simh supported compile environments. A simulator that needs these
initializations can perform them in the CPU device reset routine which will
always be called before anything else can be processed.
*/
char* (*sim_vm_read) (char *ptr, int32 size, FILE *stream) = NULL;
void (*sim_vm_post) (t_bool from_scp) = NULL;
CTAB *sim_vm_cmd = NULL;
@ -451,8 +458,8 @@ t_addr (*sim_vm_parse_addr) (DEVICE *dptr, CONST char *cptr, CONST char **tptr)
t_value (*sim_vm_pc_value) (void) = NULL;
t_bool (*sim_vm_is_subroutine_call) (t_addr **ret_addrs) = NULL;
t_bool (*sim_vm_fprint_stopped) (FILE *st, t_stat reason) = NULL;
const char *sim_vm_release;
const char *sim_vm_release_message;
const char *sim_vm_release = NULL;
const char *sim_vm_release_message = NULL;
const char **sim_clock_precalibrate_commands = NULL;
@ -2726,8 +2733,6 @@ sim_on_inherit = sim_switches & SWMASK ('O'); /* -o means inherit on s
sim_init_sock (); /* init socket capabilities */
AIO_INIT; /* init Asynch I/O */
if (sim_vm_init != NULL) /* call once only */
(*sim_vm_init)();
sim_finit (); /* init fio package */
setenv ("SIM_NAME", sim_name, 1); /* Publish simulator name */
stop_cpu = FALSE;

9
scp.h
View file

@ -418,9 +418,16 @@ extern t_stat parse_sym (CONST char *cptr, t_addr addr, UNIT *uptr, t_value *val
int32 sw);
/* The per-simulator init routine is a weak global that defaults to NULL
The other per-simulator pointers can be overrriden by the init routine */
The other per-simulator pointers can be overrriden by the init routine
extern void (*sim_vm_init) (void);
This routine is no longer invoked this way since it doesn't work reliably
on all simh supported compile environments. A simulator that needs these
initializations can perform them in the CPU device reset routine which will
always be called before anything else can be processed.
*/
extern char *(*sim_vm_read) (char *ptr, int32 size, FILE *stream);
extern void (*sim_vm_post) (t_bool from_scp);
extern CTAB *sim_vm_cmd;

View file

@ -330,24 +330,6 @@ typedef uint32 t_addr;
#endif
/* Storage class modifier for weak link definition for sim_vm_init() */
#if defined(__cplusplus)
#if defined(__GNUC__)
#define WEAK __attribute__((weak))
#elif defined(_MSC_VER)
#define WEAK __declspec(selectany)
#else /* !defined(__GNUC__) && !defined(_MSC_VER) */
#define WEAK
#endif /* __GNUC__ */
#else /* !defined(__cplusplus) */
#if defined(__GNUC__)
#define WEAK __attribute__((common))
#else /* !defined(__GNUC__) */
#define WEAK
#endif /* defined(__GNUC__) */
#endif /* defined(__cplusplus) */
/* System independent definitions */
#define FLIP_SIZE (1 << 16) /* flip buf size */