SCP: Add optional VM routine that is invoked on specific REGister updates
The new REG_DEPOSIT register flag bit indicates that updates to a REGister with this flag specified will invoke the sim_vm_reg_update routine after the data has been updated.
This commit is contained in:
parent
1a54a2515d
commit
a1785ac1d0
4 changed files with 25 additions and 3 deletions
BIN
doc/simh.doc
BIN
doc/simh.doc
Binary file not shown.
26
scp.c
26
scp.c
|
@ -451,6 +451,7 @@ void (*sim_vm_fprint_addr) (FILE *st, DEVICE *dptr, t_addr addr) = NULL;
|
||||||
t_addr (*sim_vm_parse_addr) (DEVICE *dptr, CONST char *cptr, CONST char **tptr) = NULL;
|
t_addr (*sim_vm_parse_addr) (DEVICE *dptr, CONST char *cptr, CONST char **tptr) = NULL;
|
||||||
t_value (*sim_vm_pc_value) (void) = NULL;
|
t_value (*sim_vm_pc_value) (void) = NULL;
|
||||||
t_bool (*sim_vm_is_subroutine_call) (t_addr **ret_addrs) = NULL;
|
t_bool (*sim_vm_is_subroutine_call) (t_addr **ret_addrs) = NULL;
|
||||||
|
void (*sim_vm_reg_update) (REG *rptr, uint32 idx, t_value prev_val, t_value new_val) = NULL;
|
||||||
t_bool (*sim_vm_fprint_stopped) (FILE *st, t_stat reason) = NULL;
|
t_bool (*sim_vm_fprint_stopped) (FILE *st, t_stat reason) = NULL;
|
||||||
const char *sim_vm_release = NULL;
|
const char *sim_vm_release = NULL;
|
||||||
const char *sim_vm_release_message = NULL;
|
const char *sim_vm_release_message = NULL;
|
||||||
|
@ -3148,11 +3149,13 @@ DEVICE *tdptr;
|
||||||
CONST char *tptr;
|
CONST char *tptr;
|
||||||
char *namebuf;
|
char *namebuf;
|
||||||
char rangebuf[32];
|
char rangebuf[32];
|
||||||
|
int side_effects = 0;
|
||||||
|
|
||||||
if (dptr->registers)
|
if (dptr->registers)
|
||||||
for (rptr = dptr->registers; rptr->name != NULL; rptr++) {
|
for (rptr = dptr->registers; rptr->name != NULL; rptr++) {
|
||||||
if (rptr->flags & REG_HIDDEN)
|
if (rptr->flags & REG_HIDDEN)
|
||||||
continue;
|
continue;
|
||||||
|
side_effects += ((rptr->flags & REG_DEPOSIT) != 0);
|
||||||
if (rptr->depth > 1)
|
if (rptr->depth > 1)
|
||||||
sprintf (rangebuf, "[%d:%d]", 0, rptr->depth-1);
|
sprintf (rangebuf, "[%d:%d]", 0, rptr->depth-1);
|
||||||
else
|
else
|
||||||
|
@ -3172,8 +3175,11 @@ else {
|
||||||
namebuf = (char *)calloc (max_namelen + 1, sizeof (*namebuf));
|
namebuf = (char *)calloc (max_namelen + 1, sizeof (*namebuf));
|
||||||
fprintf (st, "\nThe %s device implements these registers:\n\n", dptr->name);
|
fprintf (st, "\nThe %s device implements these registers:\n\n", dptr->name);
|
||||||
for (rptr = dptr->registers; rptr->name != NULL; rptr++) {
|
for (rptr = dptr->registers; rptr->name != NULL; rptr++) {
|
||||||
|
char note[2];
|
||||||
|
|
||||||
if (rptr->flags & REG_HIDDEN)
|
if (rptr->flags & REG_HIDDEN)
|
||||||
continue;
|
continue;
|
||||||
|
strlcpy (note, (side_effects != 0) ? ((rptr->flags & REG_DEPOSIT) ? "+" : " ") : "", sizeof (note));
|
||||||
if (rptr->depth <= 1)
|
if (rptr->depth <= 1)
|
||||||
sprintf (namebuf, "%*s", -((int)max_namelen), rptr->name);
|
sprintf (namebuf, "%*s", -((int)max_namelen), rptr->name);
|
||||||
else {
|
else {
|
||||||
|
@ -3181,16 +3187,22 @@ else {
|
||||||
sprintf (namebuf, "%s%*s", rptr->name, (int)(strlen(rptr->name))-((int)max_namelen), rangebuf);
|
sprintf (namebuf, "%s%*s", rptr->name, (int)(strlen(rptr->name))-((int)max_namelen), rangebuf);
|
||||||
}
|
}
|
||||||
if (all_unique) {
|
if (all_unique) {
|
||||||
fprintf (st, " %s %4d %s\n", namebuf, rptr->width, rptr->desc ? rptr->desc : "");
|
fprintf (st, " %s %4d %s %s\n", namebuf, rptr->width, note, rptr->desc ? rptr->desc : "");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
trptr = find_reg_glob (rptr->name, &tptr, &tdptr);
|
trptr = find_reg_glob (rptr->name, &tptr, &tdptr);
|
||||||
if ((trptr == NULL) || (tdptr != dptr))
|
if ((trptr == NULL) || (tdptr != dptr))
|
||||||
fprintf (st, " %s %s %4d %s\n", dptr->name, namebuf, rptr->width, rptr->desc ? rptr->desc : "");
|
fprintf (st, " %s %s %4d %s %s\n", dptr->name, namebuf, rptr->width, note, rptr->desc ? rptr->desc : "");
|
||||||
else
|
else
|
||||||
fprintf (st, " %*s %s %4d %s\n", (int)strlen(dptr->name), "", namebuf, rptr->width, rptr->desc ? rptr->desc : "");
|
fprintf (st, " %*s %s %4d %s %s\n", (int)strlen(dptr->name), "", namebuf, rptr->width, note, rptr->desc ? rptr->desc : "");
|
||||||
}
|
}
|
||||||
free (namebuf);
|
free (namebuf);
|
||||||
|
if (side_effects)
|
||||||
|
fprintf (st, "\n + Deposits to %s register%s will have some additional\n"
|
||||||
|
" side effects which can be suppressed if the deposit is\n"
|
||||||
|
" done with the -Z switch specified\n",
|
||||||
|
(side_effects == 1) ? "this" : "these",
|
||||||
|
(side_effects == 1) ? "" : "s");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9441,6 +9453,11 @@ void put_rval_pcchk (REG *rptr, uint32 idx, t_value val, t_bool pc_chk)
|
||||||
size_t sz;
|
size_t sz;
|
||||||
t_value mask;
|
t_value mask;
|
||||||
uint32 *ptr;
|
uint32 *ptr;
|
||||||
|
t_value prev_val;
|
||||||
|
|
||||||
|
if ((!(sim_switches & SWMASK ('Z'))) &&
|
||||||
|
(rptr->flags & REG_DEPOSIT) && sim_vm_reg_update)
|
||||||
|
prev_val = get_rval (rptr, idx);
|
||||||
|
|
||||||
#define PUT_RVAL(sz,rp,id,v,m) \
|
#define PUT_RVAL(sz,rp,id,v,m) \
|
||||||
*(((sz *) rp->loc) + id) = \
|
*(((sz *) rp->loc) + id) = \
|
||||||
|
@ -9499,6 +9516,9 @@ else PUT_RVAL (t_uint64, rptr, idx, val, mask);
|
||||||
#else
|
#else
|
||||||
else PUT_RVAL (uint32, rptr, idx, val, mask);
|
else PUT_RVAL (uint32, rptr, idx, val, mask);
|
||||||
#endif
|
#endif
|
||||||
|
if ((!(sim_switches & SWMASK ('Z'))) &&
|
||||||
|
(rptr->flags & REG_DEPOSIT) && sim_vm_reg_update)
|
||||||
|
sim_vm_reg_update (rptr, idx, prev_val, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
void put_rval (REG *rptr, uint32 idx, t_value val)
|
void put_rval (REG *rptr, uint32 idx, t_value val)
|
||||||
|
|
1
scp.h
1
scp.h
|
@ -371,6 +371,7 @@ extern t_addr (*sim_vm_parse_addr) (DEVICE *dptr, CONST char *cptr, CONST char *
|
||||||
extern t_bool (*sim_vm_fprint_stopped) (FILE *st, t_stat reason);
|
extern t_bool (*sim_vm_fprint_stopped) (FILE *st, t_stat reason);
|
||||||
extern t_value (*sim_vm_pc_value) (void);
|
extern t_value (*sim_vm_pc_value) (void);
|
||||||
extern t_bool (*sim_vm_is_subroutine_call) (t_addr **ret_addrs);
|
extern t_bool (*sim_vm_is_subroutine_call) (t_addr **ret_addrs);
|
||||||
|
extern void (*sim_vm_reg_update) (REG *rptr, uint32 idx, t_value prev_val, t_value new_val);
|
||||||
extern const char **sim_clock_precalibrate_commands;
|
extern const char **sim_clock_precalibrate_commands;
|
||||||
extern int32 sim_vm_initial_ips; /* base estimate of simulated instructions per second */
|
extern int32 sim_vm_initial_ips; /* base estimate of simulated instructions per second */
|
||||||
extern const char *sim_vm_interval_units; /* Simulator can change this - default "instructions" */
|
extern const char *sim_vm_interval_units; /* Simulator can change this - default "instructions" */
|
||||||
|
|
|
@ -710,6 +710,7 @@ struct REG {
|
||||||
#define REG_VMIO 00400 /* use VM data print/parse */
|
#define REG_VMIO 00400 /* use VM data print/parse */
|
||||||
#define REG_VMAD 01000 /* use VM addr print/parse */
|
#define REG_VMAD 01000 /* use VM addr print/parse */
|
||||||
#define REG_FIT 02000 /* fit access to size */
|
#define REG_FIT 02000 /* fit access to size */
|
||||||
|
#define REG_DEPOSIT 04000 /* call VM routine after update */
|
||||||
#define REG_HRO (REG_RO | REG_HIDDEN) /* hidden, read only */
|
#define REG_HRO (REG_RO | REG_HIDDEN) /* hidden, read only */
|
||||||
|
|
||||||
#define REG_V_UF 16 /* device specific */
|
#define REG_V_UF 16 /* device specific */
|
||||||
|
|
Loading…
Add table
Reference in a new issue