diff --git a/doc/simh.doc b/doc/simh.doc index 97014662..87369297 100644 Binary files a/doc/simh.doc and b/doc/simh.doc differ diff --git a/scp.c b/scp.c index 0effafdc..ba0f0aab 100644 --- a/scp.c +++ b/scp.c @@ -7637,6 +7637,7 @@ void put_rval (REG *rptr, uint32 idx, t_value val) { size_t sz; t_value mask; +t_value old_val; uint32 *ptr; #define PUT_RVAL(sz,rp,id,v,m) \ @@ -7644,6 +7645,8 @@ uint32 *ptr; (sz)((*(((sz *) rp->loc) + id) & \ ~((m) << (rp)->offset)) | ((v) << (rp)->offset)) +if (rptr->write_callback) + old_val = get_rval (rptr, idx); if (rptr == sim_PC) sim_brk_npc (0); sz = SZ_R (rptr); @@ -7696,6 +7699,8 @@ else PUT_RVAL (t_uint64, rptr, idx, val, mask); #else else PUT_RVAL (uint32, rptr, idx, val, mask); #endif +if ((rptr->write_callback) && (!(sim_switches & SIM_SW_REST))) + rptr->write_callback (old_val, rptr, idx); return; } diff --git a/sim_defs.h b/sim_defs.h index 88dafd90..c76d2125 100644 --- a/sim_defs.h +++ b/sim_defs.h @@ -648,9 +648,12 @@ struct REG { uint32 depth; /* save depth */ const char *desc; /* description */ BITFIELD *fields; /* bit fields */ - uint32 flags; /* flags */ uint32 qptr; /* circ q ptr */ size_t str_size; /* structure size */ + void (*write_callback)(t_value old_value, REG *rptr, int idx); + /* called during DEPOSIT */ + /* NOTE: Flags MUST always be last since it is initialized outside of macro definitions */ + uint32 flags; /* flags */ }; /* Register flags */ @@ -855,111 +858,113 @@ struct MEMFILE { #define UDATA(act,fl,cap) NULL,act,NULL,NULL,NULL,0,0,(fl),0,(cap),0,NULL,0,0 +/* Internal use ONLY (see below) Generic Register declaration for all fields */ +#define _REGDATANF(nm,loc,rdx,wd,off,dep,desc,flds,qptr,siz,cbak) \ + nm, (loc), (rdx), (wd), (off), (dep), (desc), (flds), (qptr), (siz), (cbak) + +/* Right Justified Octal Register Data */ +#define ORDATA(nm,loc,wd) ORDATAD(nm,loc,wd,NULL) +/* Right Justified Decimal Register Data */ +#define DRDATA(nm,loc,wd) DRDATAD(nm,loc,wd,NULL) +/* Right Justified Hexadecimal Register Data */ +#define HRDATA(nm,loc,wd) HRDATAD(nm,loc,wd,NULL) +/* Right Justified Binary Register Data */ +#define BINRDATA(nm,loc,wd) BINRDATAD(nm,loc,wd,NULL) +/* One-bit binary flag at an arbitrary offset in a 32-bit word Register */ +#define FLDATA(nm,loc,pos) FLDATAD(nm,loc,pos,NULL) +/* Arbitrary location and Radix Register */ +#define GRDATA(nm,loc,rdx,wd,pos) GRDATAD(nm,loc,rdx,wd,pos,NULL) +/* Arrayed register whose data is kept in a standard C array Register */ +#define BRDATA(nm,loc,rdx,wd,dep) BRDATAD(nm,loc,rdx,wd,dep,NULL) +/* Arrayed register whose data is part of the UNIT structure */ +#define URDATA(nm,loc,rdx,wd,off,dep,fl) URDATAD(nm,loc,rdx,wd,off,dep,fl,NULL) +/* Arrayed register whose data is part of an arbitrary structure */ +#define STRDATA(nm,loc,rdx,wd,off,dep,siz,fl) STRDATAD(nm,loc,rdx,wd,off,dep,siz,fl,NULL) +/* Same as above, but with additional description initializer */ +#define ORDATAD(nm,loc,wd,desc) ORDATADF(nm,loc,wd,desc,NULL) +#define DRDATAD(nm,loc,wd,desc) DRDATADF(nm,loc,wd,desc,NULL) +#define HRDATAD(nm,loc,wd,desc) HRDATADF(nm,loc,wd,desc,NULL) +#define BINRDATAD(nm,loc,wd,desc) BINRDATADF(nm,loc,wd,desc,NULL) +#define FLDATAD(nm,loc,pos,desc) FLDATADF(nm,loc,pos,desc,NULL) +#define GRDATAD(nm,loc,rdx,wd,pos,desc) GRDATADF(nm,loc,rdx,wd,pos,desc,NULL) +#define BRDATAD(nm,loc,rdx,wd,dep,desc) BRDATADF(nm,loc,rdx,wd,dep,desc,NULL) +#define URDATAD(nm,loc,rdx,wd,off,dep,fl,desc) URDATADF(nm,loc,rdx,wd,off,dep,fl,desc,NULL) +#define STRDATAD(nm,loc,rdx,wd,off,dep,siz,fl,desc) STRDATADF(nm,loc,rdx,wd,off,dep,siz,fl,desc,NULL) +/* Same as above, but with additional description initializer, and bitfields */ +#define ORDATADF(nm,loc,wd,desc,flds) ORDATADFC(nm,loc,wd,desc,flds,NULL) +#define DRDATADF(nm,loc,wd,desc,flds) DRDATADFC(nm,loc,wd,desc,flds,NULL) +#define HRDATADF(nm,loc,wd,desc,flds) HRDATADFC(nm,loc,wd,desc,flds,NULL) +#define BINRDATADF(nm,loc,wd,desc,flds) BINRDATADFC(nm,loc,wd,desc,flds,NULL) +#define FLDATADF(nm,loc,pos,desc,flds) FLDATADFC(nm,loc,pos,desc,flds,NULL) +#define GRDATADF(nm,loc,rdx,wd,pos,desc,flds) GRDATADFC(nm,loc,rdx,wd,pos,desc,flds,NULL) +#define BRDATADF(nm,loc,rdx,wd,dep,desc,flds) BRDATADFC(nm,loc,rdx,wd,dep,desc,flds,NULL) +#define URDATADF(nm,loc,rdx,wd,off,dep,fl,desc,flds) URDATADFC(nm,loc,rdx,wd,off,dep,fl,desc,flds,NULL) +#define STRDATADF(nm,loc,rdx,wd,off,dep,siz,fl,desc,flds) STRDATADFC(nm,loc,rdx,wd,off,dep,siz,fl,desc,flds,NULL) + #if defined (__STDC__) || defined (_WIN32) /* Variants which depend on how macro arguments are convered to strings */ /* Generic Register declaration for all fields. If the register structure is extended, this macro will be retained and a new macro will be provided that populates the new register structure */ #define REGDATA(nm,loc,rdx,wd,off,dep,desc,flds,fl,qptr,siz) \ - #nm, &(loc), (rdx), (wd), (off), (dep), (desc), (flds), (fl), (qptr), (siz) -/* Internal use ONLY (see below) Generic Register declaration for all fields */ -#define _REGDATA(nm,loc,rdx,wd,off,dep,desc,flds,fl,qptr,siz) \ - nm, &(loc), (rdx), (wd), (off), (dep), (desc), (flds), (fl), (qptr), (siz) -/* Right Justified Octal Register Data */ -#define ORDATA(nm,loc,wd) #nm, &(loc), 8, (wd), 0, 1, NULL, NULL -/* Right Justified Decimal Register Data */ -#define DRDATA(nm,loc,wd) #nm, &(loc), 10, (wd), 0, 1, NULL, NULL -/* Right Justified Hexadecimal Register Data */ -#define HRDATA(nm,loc,wd) #nm, &(loc), 16, (wd), 0, 1, NULL, NULL -/* Right Justified Binary Register Data */ -#define BINRDATA(nm,loc,wd) #nm, &(loc), 2, (wd), 0, 1, NULL, NULL -/* One-bit binary flag at an arbitrary offset in a 32-bit word Register */ -#define FLDATA(nm,loc,pos) #nm, &(loc), 2, 1, (pos), 1, NULL, NULL -/* Arbitrary location and Radix Register */ -#define GRDATA(nm,loc,rdx,wd,pos) #nm, &(loc), (rdx), (wd), (pos), 1, NULL, NULL -/* Arrayed register whose data is kept in a standard C array Register */ -#define BRDATA(nm,loc,rdx,wd,dep) #nm, (loc), (rdx), (wd), 0, (dep), NULL, NULL -/* Same as above, but with additional description initializer */ -#define ORDATAD(nm,loc,wd,desc) #nm, &(loc), 8, (wd), 0, 1, (desc), NULL -#define DRDATAD(nm,loc,wd,desc) #nm, &(loc), 10, (wd), 0, 1, (desc), NULL -#define HRDATAD(nm,loc,wd,desc) #nm, &(loc), 16, (wd), 0, 1, (desc), NULL -#define BINRDATAD(nm,loc,wd,desc) #nm, &(loc), 2, (wd), 0, 1, (desc), NULL -#define FLDATAD(nm,loc,pos,desc) #nm, &(loc), 2, 1, (pos), 1, (desc), NULL -#define GRDATAD(nm,loc,rdx,wd,pos,desc) #nm, &(loc), (rdx), (wd), (pos), 1, (desc), NULL -#define BRDATAD(nm,loc,rdx,wd,dep,desc) #nm, (loc), (rdx), (wd), 0, (dep), (desc), NULL -/* Same as above, but with additional description initializer, and bitfields */ -#define ORDATADF(nm,loc,wd,desc,flds) #nm, &(loc), 8, (wd), 0, 1, (desc), (flds) -#define DRDATADF(nm,loc,wd,desc,flds) #nm, &(loc), 10, (wd), 0, 1, (desc), (flds) -#define HRDATADF(nm,loc,wd,desc,flds) #nm, &(loc), 16, (wd), 0, 1, (desc), (flds) -#define BINRDATADF(nm,loc,wd) #nm, &(loc), 2, (wd), 0, 1, NULL, NULL -#define FLDATADF(nm,loc,pos,desc,flds) #nm, &(loc), 2, 1, (pos), 1, (desc), (flds) -#define GRDATADF(nm,loc,rdx,wd,pos,desc,flds) #nm, &(loc), (rdx), (wd), (pos), 1, (desc), (flds) -#define BRDATADF(nm,loc,rdx,wd,dep,desc,flds) #nm, (loc), (rdx), (wd), 0, (dep), (desc), (flds) + _REGDATANF(#nm,&(loc),rdx,wd,off,dep,desc,flds,qptr,siz,NULL),(fl) +/* Same as above, but with callback initializer */ +#define ORDATADFC(nm,loc,wd,desc,flds,cbk) \ + _REGDATANF(#nm,&(loc),8,wd,0,1,desc,flds,0,0,cbk) +#define DRDATADFC(nm,loc,wd,desc,flds,cbk) \ + _REGDATANF(#nm,&(loc),10,wd,0,1,desc,flds,0,0,cbk) +#define HRDATADFC(nm,loc,wd,desc,flds,cbk) \ + _REGDATANF(#nm,&(loc),16,wd,0,1,desc,flds,0,0,cbk) +#define BINRDATADFC(nm,loc,wd,desc,flds,cbk) \ + _REGDATANF(#nm,&(loc),2,wd,0,1,desc,flds,0,0,cbk) +#define FLDATADFC(nm,loc,pos,desc,flds,cbk) \ + _REGDATANF(#nm,&(loc),2,1,pos,1,desc,flds,0,0,cbk) +#define GRDATADFC(nm,loc,rdx,wd,pos,desc,flds,cbk) \ + _REGDATANF(#nm,&(loc),rdx,wd,pos,1,desc,flds,0,0,cbk) +#define BRDATADFC(nm,loc,rdx,wd,dep,desc,flds,cbk) \ + _REGDATANF(#nm,loc,rdx,wd,0,dep,desc,flds,0,0,cbk) +#define URDATADFC(nm,loc,rdx,wd,off,dep,fl,desc,flds,cbk) \ + _REGDATANF(#nm,&(loc),rdx,wd,off,dep,desc,flds,0,0,cbk),((fl) | REG_UNIT) +#define STRDATADFC(nm,loc,rdx,wd,off,dep,siz,fl,desc,flds,cbk) \ + _REGDATANF(#nm,&(loc),rdx,wd,off,dep,desc,flds,0,siz,cbk),((fl) | REG_STRUCT) #define BIT(nm) {#nm, 0xffffffff, 1} /* Single Bit definition */ #define BITNC {"", 0xffffffff, 1} /* Don't care Bit definition */ #define BITF(nm,sz) {#nm, 0xffffffff, sz} /* Bit Field definition */ #define BITNCF(sz) {"", 0xffffffff, sz} /* Don't care Bit Field definition */ #define BITFFMT(nm,sz,fmt) {#nm, 0xffffffff, sz, NULL, #fmt}/* Bit Field definition with Output format */ #define BITFNAM(nm,sz,names) {#nm, 0xffffffff, sz, names} /* Bit Field definition with value->name map */ -/* Arrayed register whose data is part of the UNIT structure */ -#define URDATA(nm,loc,rdx,wd,off,dep,fl) \ - _REGDATA(#nm,(loc),(rdx),(wd),(off),(dep),NULL,NULL,((fl) | REG_UNIT),0,0) -/* Arrayed register whose data is part of an arbitrary structure */ -#define STRDATA(nm,loc,rdx,wd,off,dep,siz,fl) \ - _REGDATA(#nm,(loc),(rdx),(wd),(off),(dep),NULL,NULL,((fl) | REG_STRUCT),0,(siz)) -/* Same as above, but with additional description initializer */ -#define URDATAD(nm,loc,rdx,wd,off,dep,fl,desc) \ - _REGDATA(#nm,(loc),(rdx),(wd),(off),(dep),(desc),NULL,((fl) | REG_UNIT),0,0) -#define STRDATAD(nm,loc,rdx,wd,off,dep,siz,fl,desc) \ - _REGDATA(#nm,(loc),(rdx),(wd),(off),(dep),(desc),NULL,((fl) | REG_STRUCT),0,(siz)) -/* Same as above, but with additional description initializer, and bitfields */ -#define URDATADF(nm,loc,rdx,wd,off,dep,fl,desc,flds) \ - _REGDATA(#nm,(loc),(rdx),(wd),(off),(dep),(desc),(flds),((fl) | REG_UNIT),0,0) -#define STRDATADF(nm,loc,rdx,wd,off,dep,siz,fl,desc,flds) \ - _REGDATA(#nm,(loc),(rdx),(wd),(off),(dep),(desc),(flds),((fl) | REG_STRUCT),0,(siz)) #else /* For non-STD-C compiler which can't stringify macro arguments with # */ +/* Generic Register declaration for all fields. + If the register structure is extended, this macro will be retained and a + new macro will be provided that populates the new register structure */ #define REGDATA(nm,loc,rdx,wd,off,dep,desc,flds,fl,qptr,siz) \ - "nm", &(loc), (rdx), (wd), (off), (dep), (desc), (flds), (fl), (qptr), (siz) -#define _REGDATA(nm,loc,rdx,wd,off,dep,desc,flds,fl,qptr,siz) \ - nm, &(loc), (rdx), (wd), (off), (dep), (desc), (flds), (fl), (qptr), (siz) -#define ORDATA(nm,loc,wd) "nm", &(loc), 8, (wd), 0, 1, NULL, NULL -#define DRDATA(nm,loc,wd) "nm", &(loc), 10, (wd), 0, 1, NULL, NULL -#define HRDATA(nm,loc,wd) "nm", &(loc), 16, (wd), 0, 1, NULL, NULL -#define BINRDATA(nm,loc,wd) "nm", &(loc), 2, (wd), 0, 1, NULL, NULL -#define FLDATA(nm,loc,pos) "nm", &(loc), 2, 1, (pos), 1, NULL, NULL -#define GRDATA(nm,loc,rdx,wd,pos) "nm", &(loc), (rdx), (wd), (pos), 1, NULL, NULL -#define BRDATA(nm,loc,rdx,wd,dep) "nm", (loc), (rdx), (wd), 0, (dep), NULL, NULL -#define ORDATAD(nm,loc,wd,desc) "nm", &(loc), 8, (wd), 0, 1, (desc), NULL -#define DRDATAD(nm,loc,wd,desc) "nm", &(loc), 10, (wd), 0, 1, (desc), NULL -#define HRDATAD(nm,loc,wd,desc) "nm", &(loc), 16, (wd), 0, 1, (desc), NULL -#define BINRDATAD(nm,loc,wd,desc) "nm", &(loc), 2, (wd), 0, 1, (desc), NULL -#define FLDATAD(nm,loc,pos,desc) "nm", &(loc), 2, 1, (pos), 1, (desc), NULL -#define GRDATAD(nm,loc,rdx,wd,pos,desc) "nm", &(loc), (rdx), (wd), (pos), 1, (desc), NULL -#define BRDATAD(nm,loc,rdx,wd,dep,desc) "nm", (loc), (rdx), (wd), 0, (dep), (desc), NULL -#define ORDATADF(nm,loc,wd,desc,flds) "nm", &(loc), 8, (wd), 0, 1, (desc), (flds) -#define DRDATADF(nm,loc,wd,desc,flds) "nm", &(loc), 10, (wd), 0, 1, (desc), (flds) -#define HRDATADF(nm,loc,wd,desc,flds) "nm", &(loc), 16, (wd), 0, 1, (desc), (flds) -#define BINRDATADF(nm,loc,wd,desc,flds) "nm", &(loc), 2, (wd), 0, 1, (desc), (flds) -#define FLDATADF(nm,loc,pos,desc,flds) "nm", &(loc), 2, 1, (pos), 1, (desc), (flds) -#define GRDATADF(nm,loc,rdx,wd,pos,desc,flds) "nm", &(loc), (rdx), (wd), (pos), 1, (desc), (flds) -#define BRDATADF(nm,loc,rdx,wd,dep,desc,flds) "nm", (loc), (rdx), (wd), 0, (dep), (desc), (flds) + _REGDATANF("nm",&(loc),rdx,wd,off,dep,desc,flds,qptr,siz,NULL),(fl) +/* Same as above, but with callback initializer */ +#define ORDATADFC(nm,loc,wd,desc,flds,cbk) \ + _REGDATANF("nm",&(loc),8,wd,0,1,desc,flds,0,0,cbk) +#define DRDATADFC(nm,loc,wd,desc,flds,cbk) \ + _REGDATANF("nm",&(loc),10,wd,0,1,desc,flds,0,0,cbk) +#define HRDATADFC(nm,loc,wd,desc,flds,cbk) \ + _REGDATANF("nm",&(loc),16,wd,0,1,desc,flds,0,0,cbk) +#define BINRDATADFC(nm,loc,wd,cbk) \ + _REGDATANF("nm",&(loc),2,wd,0,1,desc,flds,0,0,cbk) +#define FLDATADFC(nm,loc,pos,desc,flds,cbk) \ + _REGDATANF("nm",&(loc),2,1,pos,1,desc,flds,0,0,cbk) +#define GRDATADFC(nm,loc,rdx,wd,pos,desc,flds,cbk) \ + _REGDATANF("nm",&(loc),rdx,wd,pos,1,desc,flds,0,0,cbk) +#define BRDATADFC(nm,loc,rdx,wd,dep,desc,flds,cbk) \ + _REGDATANF("nm",loc,rdx,wd,0,dep,desc,flds,0,0,cbk) +#define URDATADFC(nm,loc,rdx,wd,off,dep,fl,desc,flds,cbk) \ + _REGDATANF("nm",&(loc),rdx,wd,off,dep,desc,flds,0,0,cbk),((fl) | REG_UNIT) +#define STRDATADFC(nm,loc,rdx,wd,off,dep,siz,fl,desc,flds,cbk) \ + _REGDATANF("nm",&(loc),rdx,wd,off,dep,desc,flds,0,siz,cbk),((fl) | REG_STRUCT) +#define REGDATA(nm,loc,rdx,wd,off,dep,desc,flds,fl,qptr,siz) \ + "nm", &(loc), (rdx), (wd), (off), (dep), (desc), (flds), (qptr), (siz), NULL, (fl) #define BIT(nm) {"nm", 0xffffffff, 1} /* Single Bit definition */ #define BITNC {"", 0xffffffff, 1} /* Don't care Bit definition */ #define BITF(nm,sz) {"nm", 0xffffffff, sz} /* Bit Field definition */ #define BITNCF(sz) {"", 0xffffffff, sz} /* Don't care Bit Field definition */ #define BITFFMT(nm,sz,fmt) {"nm", 0xffffffff, sz, NULL, "fmt"}/* Bit Field definition with Output format */ #define BITFNAM(nm,sz,names) {"nm", 0xffffffff, sz, names} /* Bit Field definition with value->name map */ -#define URDATA(nm,loc,rdx,wd,off,dep,fl) \ - _REGDATA("nm",(loc),(rdx),(wd),(off),(dep),NULL,NULL,((fl) | REG_UNIT),0,0) -#define STRDATA(nm,loc,rdx,wd,off,dep,siz,fl) \ - _REGDATA("nm",(loc),(rdx),(wd),(off),(dep),NULL,NULL,((fl) | REG_STRUCT),0,(siz)) -#define URDATAD(nm,loc,rdx,wd,off,dep,fl,desc) \ - _REGDATA("nm",(loc),(rdx),(wd),(off),(dep),(desc),NULL,((fl) | REG_UNIT),0,0) -#define STRDATAD(nm,loc,rdx,wd,off,dep,siz,fl,desc) \ - _REGDATA("nm",(loc),(rdx),(wd),(off),(dep),(desc),NULL,((fl) | REG_STRUCT),0,(siz)) -#define URDATADF(nm,loc,rdx,wd,off,dep,fl,desc,flds) \ - _REGDATA("nm",(loc),(rdx),(wd),(off),(dep),(desc),(flds),((fl) | REG_UNIT),0,0) -#define STRDATADF(nm,loc,rdx,wd,off,dep,siz,fl,desc,flds) \ - _REGDATA("nm",(loc),(rdx),(wd),(off),(dep),(desc),(flds),((fl) | REG_STRUCT),0,(siz)) #endif #define ENDBITS {NULL} /* end of bitfield list */