diff --git a/scp.c b/scp.c index 68887aae..eb61bc61 100644 --- a/scp.c +++ b/scp.c @@ -24,6 +24,9 @@ in this Software without prior written authorization from Robert M Supnik. 21-Oct-21 RMS Fixed bug in byte deposits if aincr > 1 + 16-Feb-21 JDB Rewrote get_rval, put_rval to support arrays of structures + 25-Jan-21 JDB REG "size" field now determines access size + REG "maxval" field now determines maximum allowed value 08-Mar-16 RMS Added shutdown flag for detach_all 20-Mar-12 MP Fixes to "SHOW SHOW" commands 06-Jan-12 JDB Fixed "SHOW DEVICE" with only one enabled unit (Dave Bryan) @@ -8710,7 +8713,7 @@ void *mbuf = NULL; int32 j, blkcnt, limit, unitno, time, flg; uint32 us, depth; t_addr k, high, old_capac; -t_value val, mask; +t_value val, max; t_stat r; size_t sz; t_bool v40, v35, v32; @@ -8979,10 +8982,13 @@ for ( ;; ) { /* device loop */ if (depth > rptr->depth) depth = rptr->depth; } - mask = width_mask[rptr->width]; /* get mask */ + if (rptr->maxval > 0) /* if a maximum value is defined */ + max = rptr->maxval; /* then use it */ + else /* otherwise */ + max = width_mask[rptr->width]; /* the mask defines the maximum value */ for (us = 0; us < depth; us++) { /* loop thru values */ READ_I (val); /* read value */ - if (val > mask) { /* value ok? */ + if (val > max) { /* value ok? */ sim_printf ("Invalid register value: %s %s\n", sim_dname (dptr), buf); } else { @@ -9133,7 +9139,9 @@ if ((flag == RU_RUN) || (flag == RU_GO)) { /* run or go */ else new_pcv = strtotv (gbuf, &tptr, sim_PC->radix);/* parse PC */ if ((tptr == gbuf) || (*tptr != 0) || /* error? */ - (new_pcv > width_mask[sim_PC->width])) + (new_pcv > ((sim_PC->maxval > 0) + ? sim_PC->maxval + : (width_mask[sim_PC->width])))) return SCPE_ARG; new_pc = TRUE; } @@ -9822,53 +9830,50 @@ return SCPE_OK; idx = index Outputs: return = register value + + Implementation notes: + + 1. The stride is the size of the element spacing for arrays, which is + equivalent to the addressing increment for array subscripting. For + scalar registers, the stride will be zero (as will the idx value), so the + access pointer is same as the specified location pointer. + + 2. The size of the t_value type is determined by the USE_INT64 symbol and + will be either a 32-bit or a 64-bit type. It represents the largest + value that can be returned and so is the default if one of the smaller + sizes is not indicated. If USE_INT64 is not defined, t_value will be + identical to uint32. In this case, compilers are generally smart enough + to eliminate the 32-bit size test and combine the two assignments into a + single default assignment. */ t_value get_rval (REG *rptr, uint32 idx) { -size_t sz; t_value val; -uint32 *ptr; +void *ptr; -sz = SZ_R (rptr); -if ((rptr->depth > 1) && (rptr->flags & REG_CIRC)) { - idx = idx + rptr->qptr; - if (idx >= rptr->depth) idx = idx - rptr->depth; +if ((rptr->depth > 1) && (rptr->flags & REG_CIRC)) { /* if the register is a circular queue */ + idx = idx + rptr->qptr; /* then adjust the index relative to the queue */ + if (idx >= rptr->depth) /* if the index is beyond the end of the array */ + idx = idx - rptr->depth; /* then wrap it around */ } -if ((rptr->depth > 1) && (rptr->flags & REG_UNIT)) { - ptr = (uint32 *)(((UNIT *) rptr->loc) + idx); -#if defined (USE_INT64) - if (sz <= sizeof (uint32)) - val = *ptr; - else val = *((t_uint64 *) ptr); -#else - val = *ptr; -#endif - } -else if ((rptr->depth > 1) && (rptr->flags & REG_STRUCT)) { - ptr = (uint32 *)(((size_t) rptr->loc) + (idx * rptr->str_size)); -#if defined (USE_INT64) - if (sz <= sizeof (uint32)) - val = *ptr; - else val = *((t_uint64 *) ptr); -#else - val = *ptr; -#endif - } -else if (((rptr->depth > 1) || (rptr->flags & REG_FIT)) && - (sz == sizeof (uint8))) - val = *(((uint8 *) rptr->loc) + idx); -else if (((rptr->depth > 1) || (rptr->flags & REG_FIT)) && - (sz == sizeof (uint16))) - val = *(((uint16 *) rptr->loc) + idx); -#if defined (USE_INT64) -else if (sz <= sizeof (uint32)) - val = *(((uint32 *) rptr->loc) + idx); -else val = *(((t_uint64 *) rptr->loc) + idx); -#else -else val = *(((uint32 *) rptr->loc) + idx); -#endif -val = (val >> rptr->offset) & width_mask[rptr->width]; + +ptr = ((char *) rptr->loc) + (idx * rptr->stride); /* point at the starting byte of the item */ + +if (rptr->size == sizeof (uint8)) /* get the value */ + val = *((uint8 *) ptr); /* using a size */ + /* appropriate to */ +else if (rptr->size == sizeof (uint16)) /* the size of */ + val = *((uint16 *) ptr); /* the underlying type */ + +else if (rptr->size == sizeof (uint32)) + val = *((uint32 *) ptr); + +else /* if the element size is non-standard */ + val = *((t_value *) ptr); /* then access using the largest size permitted */ + +val = (val >> rptr->offset) & width_mask[rptr->width]; /* shift and mask to obtain the final value */ + return val; } @@ -9886,7 +9891,7 @@ return val; t_stat dep_reg (int32 flag, CONST char *cptr, REG *rptr, uint32 idx) { t_stat r; -t_value val, mask; +t_value val, max; int32 rdx; CONST char *tptr; char gbuf[CBUFSIZE]; @@ -9898,24 +9903,27 @@ if (rptr->flags & REG_RO) if (flag & EX_I) { cptr = read_line (gbuf, sizeof(gbuf), stdin); if (sim_log) - fprintf (sim_log, "%s\n", cptr? cptr: ""); + fprintf (sim_log, "%s\n", cptr? cptr: ""); /* fix clang error */ if (cptr == NULL) /* force exit */ return 1; if (*cptr == 0) /* success */ return SCPE_OK; } -mask = width_mask[rptr->width]; +if (rptr->maxval > 0) /* if a maximum value is defined */ + max = rptr->maxval; /* then use it */ +else /* otherwise */ + max = width_mask[rptr->width]; /* the mask defines the maximum value */ GET_RADIX (rdx, rptr->radix); if ((rptr->flags & REG_VMAD) && sim_vm_parse_addr) { /* address form? */ val = sim_vm_parse_addr (sim_dflt_dev, cptr, &tptr); - if ((tptr == cptr) || (*tptr != 0) || (val > mask)) + if ((tptr == cptr) || (*tptr != 0) || (val > max)) return SCPE_ARG; } else if (!(rptr->flags & REG_VMFLAGS) || /* dont use sym? */ (parse_sym ((CONST char *)cptr, (rptr->flags & REG_UFMASK) | rdx, NULL, &val, sim_switches | SIM_SW_REG) > SCPE_OK)) { - val = get_uint (cptr, rdx, mask, &r); + val = get_uint (cptr, rdx, max, &r); if (r != SCPE_OK) return SCPE_ARG; } @@ -9934,76 +9942,59 @@ return SCPE_OK; mask = mask Outputs: none + + + Implementation notes: + + 1. mask and val are of type t_value, so an explicit cast is not needed for + that type of assignment. + + 2. See the notes for the get_rval routine for additional information + regarding the stride calculation and the t_value default assignment, */ void put_rval_pcchk (REG *rptr, uint32 idx, t_value val, t_bool pc_chk) { -size_t sz; t_value mask; -uint32 *ptr; +void *ptr; t_value prev_val = 0; 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) \ - *(((sz *) rp->loc) + id) = \ - (sz)((*(((sz *) rp->loc) + id) & \ - ~((m) << (rp)->offset)) | ((v) << (rp)->offset)) +if (pc_chk && (rptr == sim_PC)) /* if the PC is changing */ + sim_brk_npc (0); /* then notify the breakpoint package */ -if (pc_chk && (rptr == sim_PC)) - sim_brk_npc (0); -sz = SZ_R (rptr); -mask = width_mask[rptr->width]; -if ((rptr->depth > 1) && (rptr->flags & REG_CIRC)) { - idx = idx + rptr->qptr; - if (idx >= rptr->depth) - idx = idx - rptr->depth; +mask = ~(width_mask [rptr->width] << rptr->offset); /* set up a mask to produce a hole in the element */ +val = val << rptr->offset; /* and position the new value to fit the hole */ + +if ((rptr->depth > 1) && (rptr->flags & REG_CIRC)) { /* if the register is a circular queue */ + idx = idx + rptr->qptr; /* then adjust the index relative to the queue */ + if (idx >= rptr->depth) /* if the index is beyond the end of the array */ + idx = idx - rptr->depth; /* then wrap it around */ } -if ((rptr->depth > 1) && (rptr->flags & REG_UNIT)) { - ptr = (uint32 *)(((UNIT *) rptr->loc) + idx); -#if defined (USE_INT64) - if (sz <= sizeof (uint32)) - *ptr = (*ptr & - ~(((uint32) mask) << rptr->offset)) | - (((uint32) val) << rptr->offset); - else *((t_uint64 *) ptr) = (*((t_uint64 *) ptr) - & ~(mask << rptr->offset)) | (val << rptr->offset); -#else - *ptr = (*ptr & - ~(((uint32) mask) << rptr->offset)) | - (((uint32) val) << rptr->offset); -#endif - } -else if ((rptr->depth > 1) && (rptr->flags & REG_STRUCT)) { - ptr = (uint32 *)(((size_t)rptr->loc) + (idx * rptr->str_size)); -#if defined (USE_INT64) - if (sz <= sizeof (uint32)) - *((uint32 *) ptr) = (*((uint32 *) ptr) & - ~(((uint32) mask) << rptr->offset)) | - (((uint32) val) << rptr->offset); - else *((t_uint64 *) ptr) = (*((t_uint64 *) ptr) - & ~(mask << rptr->offset)) | (val << rptr->offset); -#else - *ptr = (*ptr & - ~(((uint32) mask) << rptr->offset)) | - (((uint32) val) << rptr->offset); -#endif - } -else if (((rptr->depth > 1) || (rptr->flags & REG_FIT)) && - (sz == sizeof (uint8))) - PUT_RVAL (uint8, rptr, idx, (uint32) val, (uint32) mask); -else if (((rptr->depth > 1) || (rptr->flags & REG_FIT)) && - (sz == sizeof (uint16))) - PUT_RVAL (uint16, rptr, idx, (uint32) val, (uint32) mask); -#if defined (USE_INT64) -else if (sz <= sizeof (uint32)) - PUT_RVAL (uint32, rptr, idx, (int32) val, (uint32) mask); -else PUT_RVAL (t_uint64, rptr, idx, val, mask); -#else -else PUT_RVAL (uint32, rptr, idx, val, mask); -#endif + +ptr = ((char *) rptr->loc) + (idx * rptr->stride); /* point at the starting byte of the item */ + +if (rptr->size == sizeof (uint8)) /* store the value */ + *((uint8 *) ptr) = /* using a size */ + (uint8) (*((uint8 *) ptr) & mask | val); /* appropriate to */ + /* the size of */ +else + if (rptr->size == sizeof (uint16)) /* the underlying type */ + *((uint16 *) ptr) = + (uint16) (*((uint16 *) ptr) & mask | val); + + else + if (rptr->size == sizeof (uint32)) + *((uint32 *) ptr) = + (uint32) (*((uint32 *) ptr) & mask | val); + + else /* if the element size is non-standard */ + *((t_value *) ptr) = /* then access using the largest size permitted */ + *((t_value *) ptr) & mask | val; + if ((!(sim_switches & SWMASK ('Z'))) && (rptr->flags & REG_DEPOSIT) && sim_vm_reg_update) sim_vm_reg_update (rptr, idx, prev_val, val); @@ -16084,19 +16075,8 @@ for (i = 0; (dptr = devices[i]) != NULL; i++) { bytes <<= 1; if (rptr->depth > 1) - bytes = rptr->ele_size; + bytes = rptr->size; - if (rptr->flags & REG_UNIT) { - DEVICE **d; - - for (d = devices; *d != NULL; d++) { - if (((UNIT *)rptr->loc >= (*d)->units) && - ((UNIT *)rptr->loc < (*d)->units + (*d)->numunits)) { - udptr = *d; - break; - } - } - } if (((rptr->width + rptr->offset + CHAR_BIT - 1) / CHAR_BIT) >= sizeof(size_map) / sizeof(size_map[0])) { Bad = TRUE; rsz = 0; @@ -16107,10 +16087,10 @@ for (i = 0; (dptr = devices[i]) != NULL; i++) { } if (sim_switches & SWMASK ('R')) /* Debug output */ - sim_printf ("%5s:%-9.9s %s(rdx=%u, wd=%u, off=%u, dep=%u, strsz=%u, objsz=%u, elesz=%u, rsz=%u, %s %s%s%s membytes=%u)\n", dptr->name, rptr->name, rptr->macro, - rptr->radix, rptr->width, rptr->offset, rptr->depth, (uint32)rptr->str_size, (uint32)rptr->obj_size, (uint32)rptr->ele_size, rsz, rptr->desc ? rptr->desc : "", - (rptr->flags & REG_FIT) ? "REG_FIT" : "", (rptr->flags & REG_VMIO) ? " REG_VMIO" : "", (rptr->flags & REG_STRUCT) ? " REG_STRUCT" : "", - memsize); + sim_printf ("%5s:%-9.9s %s(rdx=%u, wd=%u, off=%u, dep=%u, strsz=%u, objsz=%u, elesz=%u, rsz=%u, %s %s%s membytes=%u, macro=%s)\n", dptr->name, rptr->name, rptr->macro, + rptr->radix, rptr->width, rptr->offset, rptr->depth, (uint32)rptr->stride, (uint32)rptr->obj_size, (uint32)rptr->size, rsz, rptr->desc ? rptr->desc : "", + (rptr->flags & REG_FIT) ? "REG_FIT" : "", (rptr->flags & REG_VMIO) ? " REG_VMIO" : "", + memsize, rptr->macro ? rptr->macro : ""); MFlush (f); if (rptr->depth == 1) { @@ -16129,42 +16109,6 @@ for (i = 0; (dptr = devices[i]) != NULL; i++) { Bad = TRUE; Mprintf (f, "a 0 bit wide register is meaningless\n"); } - if ((rptr->obj_size != 0) && (rptr->ele_size != 0) && (rptr->depth != 0) && (rptr->macro != NULL)) { - if (rptr->flags & REG_UNIT) { - if (udptr == NULL) { - Bad = TRUE; - Mprintf (f, "\tthe indicated UNIT can't be found for this %u depth array\n", rptr->depth); - } - else { - if (rptr->depth > udptr->numunits) { - Bad = TRUE; - Mprintf (f, "\tthe depth of the UNIT array exceeds the number of units on the %s device which is %u\n", dptr->name, udptr->numunits); - } - if (rptr->obj_size > sizeof (t_value)) { - Bad = TRUE; - Mprintf (f, "\t%u is larger than the size of the t_value type (%u)\n", (uint32)rptr->obj_size, (uint32)sizeof (t_value)); - } - } - } - else { - bytes *= rptr->depth; - if (!Bad) - if ((rsz * rptr->depth == rptr->obj_size) || - ((rptr->flags & REG_STRUCT) && (rsz <= rptr->obj_size)) || - ((rptr->depth == 1) && - ((rptr->obj_size == sizeof (t_value)) || (rsz < rptr->obj_size))) || - ((rptr->depth != 1) && (bytes == rptr->obj_size)) || - ((rptr->depth != 1) && (rptr->offset == 0) && (rptr->width == 8) && - ((rptr->depth == rptr->obj_size) || (rptr->depth == rptr->obj_size - 1))) || - ((rptr->depth != 1) && (rptr->offset == 0) && (rptr->obj_size == rptr->ele_size))) - continue; - Bad = TRUE; - Mprintf (f, "\ttherefore SAVE/RESTORE operations will affect %u byte%s of memory\n", bytes, (bytes != 1) ? "s" : ""); - Mprintf (f, "\twhile the variable lives in %u bytes of memory\n", (uint32)rptr->obj_size); - } - } - else - Mprintf (f, "\tthis register entry is not properly initialized\n"); if (Bad) { FMwrite (stdout, f); stat = SCPE_IERR; diff --git a/sim_defs.h b/sim_defs.h index dddc9290..86d0f117 100644 --- a/sim_defs.h +++ b/sim_defs.h @@ -694,9 +694,9 @@ struct REG { const char *desc; /* description */ BITFIELD *fields; /* bit fields */ uint32 qptr; /* circ q ptr */ - size_t str_size; /* structure size */ + size_t stride; /* structure/object size (for indexing) */ size_t obj_size; /* sizeof(*loc) */ - size_t ele_size; /* sizeof(**loc) or sizeof(*loc) if depth == 1 */ + size_t size; /* sizeof(**loc) or sizeof(*loc) if depth == 1 */ const char *macro; /* Initializer Macro Name */ /* NOTE: Flags and maxval MUST always be last since they are initialized outside of macro definitions */ uint32 flags; /* flags */ @@ -709,12 +709,10 @@ struct REG { #define REG_RO 00004 /* read only */ #define REG_HIDDEN 00010 /* hidden */ #define REG_NZ 00020 /* must be non-zero */ -#define REG_UNIT 00040 /* in unit struct */ -#define REG_STRUCT 00100 /* in structure array */ #define REG_CIRC 00200 /* circular array */ #define REG_VMIO 00400 /* use VM data print/parse */ #define REG_VMAD 01000 /* use VM addr print/parse */ -#define REG_FIT 02000 /* fit access to size */ +#define REG_FIT 00000 /* fit access to size (obsolete) */ #define REG_DEPOSIT 04000 /* call VM routine after update */ #define REG_HRO (REG_RO | REG_HIDDEN) /* hidden, read only */ @@ -893,6 +891,7 @@ struct MEMFILE { size_t size; /* size */ size_t pos; /* data used */ }; + /* The following macros exist to help populate structure contents @@ -903,91 +902,208 @@ struct MEMFILE { #define UDATA(act,fl,cap) NULL,act,NULL,NULL,NULL,NULL,0,0,(fl),0,(cap),0,NULL,0,0 +/* Register initialization macros. + + The following macros should be used to initialize the elements of a + simulator's register array. The macros provide simplified initialization, + ensure that unspecified fields are set appropriately, and insulate the + simulator writer from changes in the underlying REG structure. + + The macros take varying numbers of parameters with the following meanings: + + Param Meaning + ----- ------------------------------------------ + nm Register symbolic name + loc Location of the associated variable + aloc Location of the associated array + floc Location of the associated structure field + rdx Display and entry radix + wd Field width in bits + off Field offset in bits from LSB + dep Number of array elements + siz Element size in bytes + str Array element spacing in bytes + + The macros have the following uses: + + Macro Use with + -------- --------------------------------------------------------------- + ORDATA Scalar with octal display/entry + DRDATA Scalar with decimal display/entry + HRDATA Scalar with hexadecimal display/entry + BINRDATA Scalar with binary display/entry + FLDATA Scalar with single bit display/entry + GRDATA Scalar with with specification of radix/width/offset parameters + + BRDATA Singly-subscripted array + CRDATA Doubly-subscripted array + + SRDATA Singly-subscripted array of general structure fields + URDATA Singly-subscripted array of UNIT structure fields + + XRDATA Generic type with specification of all parameters + SAVEDATA Generic type used only for persistence across SAVE/RESTORE + + Normally, scalar and array locations specify the variable name; the names are + converted internally to pointers as needed. However, the starting point of + a partial array may be specified by passing a pointer to the desired element. + For example: + + BRDATA (SYM, array, ...) + + ...specifies a register starting with array element zero, while: + + BRDATA (SYM, &array[3], ...) + + ...specifies a register starting with array element three. + + For arrays of general structures, the names of the array and selected field + are given: + + SRDATA (SYM, array, field, ...) + + This specifies a arrayed register whose elements are array[0].field, + array[1].field, etc. + + All above macro names from ORDATA through XRDATA have two additional + precisely related macros. The first it the above name with D appended and + has an additional parameter which is a quoted string describing the purpose + of the register which is visible when displaying HELP about a device's + registers. The second related macro has the above name with DF appended + and has two additional parameters. The first parameter is the register + description, and the second is the name of a BITFIELD array which describes + the fields in the register's contents. This info is used to display the + register contents (via EXAMINE) along with the detailed bitfield data. + For example: + + { HRDATA (KSP, KSP, 32) }, + { HRDATAD (KSP, KSP, 32, "kernel stack pointer") }, + { HRDATADF(PSL, PSL, 32, "processor status longword", cpu_psl_bits) }, + or + { ORDATA (PSW, PSW, 16) }, + { ORDATAD (PSW, PSW, 16, "Processor Status Word") }, + { ORDATADF(PSW, PSW, 16, "Processor Status Word", psw_bits) }, + + + Implementation notes: + + 1. The "_RegCheck" macro is used to ensure that each of the user macros has + the correct number of parameters. This improves maintenance reliability, + as changes to the REG structure need to be reflected only in the + "_RegCheck" macro. + + 2. "Stringization" must occur at the first macro call level to support + register names that are themselves macros. Otherwise, macro expansion + will occur before stringization, resulting in the wrong register name. + + 3. Additional REG initialization values may be supplied after a macro + invocation. If present, these begin with the "flags" field which is, + for the most part, not specified as a macro parameter. + + 4. The URDATA macro is obsolescent and present for backward-compatibility. + It is a special case of the generic SRDATA macro, which provides the same + functionality. Note also that URDATA requires a "flags" parameter value, + which is optional for all other macros. + + 5. The SAVEDATA macro is useful to indicate global variables whose values + must persist across a SAVE and RESTORE. Such data is hidden from the + register user interface. +*/ + /* Internal use ONLY (see below) Generic Register declaration for all fields */ -#define _REGDATANF(nm,loc,rdx,wd,off,dep,desc,flds,qptr,siz,elesiz,macro) \ +#define _RegCheck(nm,loc,rdx,wd,off,dep,desc,flds,qptr,siz,elesiz,macro) \ nm, (loc), (rdx), (wd), (off), (dep), (desc), (flds), (qptr), (siz), sizeof(*(loc)), (elesiz), #macro -#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 internal macro will be provided that populates the new register structure */ #define REGDATA(nm,loc,rdx,wd,off,dep,desc,flds,fl,qptr,siz) \ - _REGDATANF(#nm,&(loc),rdx,wd,off,dep,desc,flds,qptr,siz,sizeof((loc)),REGDATA),(fl) -#define REGDATAC(nm,loc,rdx,wd,off,dep,desc,flds,fl,qptr,siz) \ - _REGDATANF(#nm,&(loc),rdx,wd,off,dep,desc,flds,qptr,siz,sizeof((loc)),REGDATAC),(fl) + _RegCheck(#nm,&(loc),rdx,wd,off,dep,desc,flds,qptr,siz,sizeof((loc)),REGDATA),(fl) +/* v3 compatible macro */ +#define XRDATA(nm,loc,rdx,wd,off,dep,siz,str) \ + _RegCheck(#nm,loc,rdx,wd,off,dep,NULL,NULL,0,siz,sizeof((loc)),XRDATA),(fl) + /* Right Justified Octal Register Data */ #define ORDATA(nm,loc,wd) \ - _REGDATANF(#nm,&(loc),8,wd,0,1,NULL,NULL,0,0,sizeof((loc)),ORDATA) + _RegCheck(#nm,&(loc),8,wd,0,1,NULL,NULL,0,0,sizeof((loc)),ORDATA) #define ORDATAD(nm,loc,wd,desc) \ - _REGDATANF(#nm,&(loc),8,wd,0,1,desc,NULL,0,0,sizeof((loc)),ORDATAD) + _RegCheck(#nm,&(loc),8,wd,0,1,desc,NULL,0,0,sizeof((loc)),ORDATAD) #define ORDATADF(nm,loc,wd,desc,flds) \ - _REGDATANF(#nm,&(loc),8,wd,0,1,desc,flds,0,0,sizeof((loc)),ORDATADF) + _RegCheck(#nm,&(loc),8,wd,0,1,desc,flds,0,0,sizeof((loc)),ORDATADF) /* Right Justified Decimal Register Data */ #define DRDATA(nm,loc,wd) \ - _REGDATANF(#nm,&(loc),10,wd,0,1,NULL,NULL,0,0,sizeof((loc)),DRDATA) + _RegCheck(#nm,&(loc),10,wd,0,1,NULL,NULL,0,0,sizeof((loc)),DRDATA) #define DRDATAD(nm,loc,wd,desc) \ - _REGDATANF(#nm,&(loc),10,wd,0,1,desc,NULL,0,0,sizeof((loc)),DRDATAD) + _RegCheck(#nm,&(loc),10,wd,0,1,desc,NULL,0,0,sizeof((loc)),DRDATAD) #define DRDATADF(nm,loc,wd,desc,flds) \ - _REGDATANF(#nm,&(loc),10,wd,0,1,desc,flds,0,0,sizeof((loc)),DRDATADF) + _RegCheck(#nm,&(loc),10,wd,0,1,desc,flds,0,0,sizeof((loc)),DRDATADF) /* Right Justified Hexadecimal Register Data */ #define HRDATA(nm,loc,wd) \ - _REGDATANF(#nm,&(loc),16,wd,0,1,NULL,NULL,0,0,sizeof((loc)),HRDATA) + _RegCheck(#nm,&(loc),16,wd,0,1,NULL,NULL,0,0,sizeof((loc)),HRDATA) #define HRDATAD(nm,loc,wd,desc) \ - _REGDATANF(#nm,&(loc),16,wd,0,1,desc,NULL,0,0,sizeof((loc)),HRDATAD) + _RegCheck(#nm,&(loc),16,wd,0,1,desc,NULL,0,0,sizeof((loc)),HRDATAD) #define HRDATADF(nm,loc,wd,desc,flds) \ - _REGDATANF(#nm,&(loc),16,wd,0,1,desc,flds,0,0,sizeof((loc)),HRDATADF) + _RegCheck(#nm,&(loc),16,wd,0,1,desc,flds,0,0,sizeof((loc)),HRDATADF) /* Right Justified Binary Register Data */ #define BINRDATA(nm,loc,wd) \ - _REGDATANF(#nm,&(loc),2,wd,0,1,NULL,NULL,0,0,sizeof((loc)),BINRDATA) + _RegCheck(#nm,&(loc),2,wd,0,1,NULL,NULL,0,0,sizeof((loc)),BINRDATA) #define BINRDATAD(nm,loc,wd,desc) \ - _REGDATANF(#nm,&(loc),2,wd,0,1,desc,NULL,0,0,sizeof((loc)),BINRDATAD) + _RegCheck(#nm,&(loc),2,wd,0,1,desc,NULL,0,0,sizeof((loc)),BINRDATAD) #define BINRDATADF(nm,loc,wd,desc,flds) \ - _REGDATANF(#nm,&(loc),2,wd,0,1,desc,flds,0,0,sizeof((loc)),BINRDATADF) + _RegCheck(#nm,&(loc),2,wd,0,1,desc,flds,0,0,sizeof((loc)),BINRDATADF) /* One-bit binary flag at an arbitrary offset in a 32-bit word Register */ #define FLDATA(nm,loc,pos) \ - _REGDATANF(#nm,&(loc),2,1,pos,1,NULL,NULL,0,0,sizeof((loc)),FLDATA) + _RegCheck(#nm,&(loc),2,1,pos,1,NULL,NULL,0,0,sizeof((loc)),FLDATA) #define FLDATAD(nm,loc,pos,desc) \ - _REGDATANF(#nm,&(loc),2,1,pos,1,desc,NULL,0,0,sizeof((loc)),FLDATAD) + _RegCheck(#nm,&(loc),2,1,pos,1,desc,NULL,0,0,sizeof((loc)),FLDATAD) #define FLDATADF(nm,loc,pos,desc,flds) \ - _REGDATANF(#nm,&(loc),2,1,pos,1,desc,flds,0,0,sizeof((loc)),FLDATADF) + _RegCheck(#nm,&(loc),2,1,pos,1,desc,flds,0,0,sizeof((loc)),FLDATADF) /* Arbitrary location and Radix Register */ #define GRDATA(nm,loc,rdx,wd,pos) \ - _REGDATANF(#nm,&(loc),rdx,wd,pos,1,NULL,NULL,0,0,sizeof((loc)),GRDATA) + _RegCheck(#nm,&(loc),rdx,wd,pos,1,NULL,NULL,0,0,sizeof((loc)),GRDATA) #define GRDATAD(nm,loc,rdx,wd,pos,desc) \ - _REGDATANF(#nm,&(loc),rdx,wd,pos,1,desc,NULL,0,0,sizeof((loc)),GRDATAD) + _RegCheck(#nm,&(loc),rdx,wd,pos,1,desc,NULL,0,0,sizeof((loc)),GRDATAD) #define GRDATADF(nm,loc,rdx,wd,pos,desc,flds) \ - _REGDATANF(#nm,&(loc),rdx,wd,pos,1,desc,flds,0,0,sizeof((loc)),GRDATADF) + _RegCheck(#nm,&(loc),rdx,wd,pos,1,desc,flds,0,0,sizeof((loc)),GRDATADF) /* Arrayed register whose data is kept in a standard C array Register */ -#define BRDATA(nm,loc,rdx,wd,dep) \ - _REGDATANF(#nm,&(loc),rdx,wd,0,dep,NULL,NULL,0,0,sizeof(*(loc)),BRDATA) -#define BRDATAD(nm,loc,rdx,wd,dep,desc) \ - _REGDATANF(#nm,&(loc),rdx,wd,0,dep,desc,NULL,0,0,sizeof(*(loc)),BRDATAD) -#define BRDATADF(nm,loc,rdx,wd,dep,desc,flds) \ - _REGDATANF(#nm,&(loc),rdx,wd,0,dep,desc,flds,0,0,sizeof(*(loc)),BRDATADF) +#define BRDATA(nm,aloc,rdx,wd,dep) \ + _RegCheck(#nm,aloc,rdx,wd,0,dep,NULL,NULL,0,0,sizeof(*(aloc)),BRDATA) +#define BRDATAD(nm,aloc,rdx,wd,dep,desc) \ + _RegCheck(#nm,aloc,rdx,wd,0,dep,desc,NULL,0,0,sizeof(*(aloc)),BRDATAD) +#define BRDATADF(nm,aloc,rdx,wd,dep,desc,flds) \ + _RegCheck(#nm,aloc,rdx,wd,0,dep,desc,flds,0,0,sizeof(*(aloc)),BRDATADF) +/* Arrayed register whose data is kept in a standard C array Register */ +#define CRDATA(nm,aloc,rdx,wd,dep) \ + _RegCheck(#nm,aloc,rdx,wd,0,dep,NULL,NULL,0,0,sizeof(**(aloc)),CRDATA) +#define CRDATAD(nm,aloc,rdx,wd,dep,desc) \ + _RegCheck(#nm,aloc,rdx,wd,0,dep,desc,NULL,0,0,sizeof(**(aloc)),CRDATAD) +#define CRDATADF(nm,aloc,rdx,wd,dep,desc,flds) \ + _RegCheck(#nm,aloc,rdx,wd,0,dep,desc,flds,0,0,sizeof(**(aloc)),CRDATADF) + /* Range of memory whose data is successive scalar values accessed like an array Register */ #define VBRDATA(nm,loc,rdx,wd,dep) \ - _REGDATANF(#nm,&(loc),rdx,wd,0,dep,NULL,NULL,0,0,sizeof(loc),VBRDATA) + _RegCheck(#nm,&(loc),rdx,wd,0,dep,NULL,NULL,0,0,sizeof(loc),VBRDATA) #define VBRDATAD(nm,loc,rdx,wd,dep,desc) \ - _REGDATANF(#nm,&(loc),rdx,wd,0,dep,desc,NULL,0,0,sizeof(loc),VBRDATAD) + _RegCheck(#nm,&(loc),rdx,wd,0,dep,desc,NULL,0,0,sizeof(loc),VBRDATAD) #define VBRDATADF(nm,loc,rdx,wd,dep,desc,flds) \ - _REGDATANF(#nm,&(loc),rdx,wd,0,dep,desc,flds,0,0,sizeof(loc),VBRDATADF) + _RegCheck(#nm,&(loc),rdx,wd,0,dep,desc,flds,0,0,sizeof(loc),VBRDATADF) /* Arrayed register whose data is part of the UNIT structure */ #define URDATA(nm,loc,rdx,wd,off,dep,fl) \ - _REGDATANF(#nm,&(loc),rdx,wd,off,dep,NULL,NULL,0,0,sizeof((loc)),URDATA),((fl) | REG_UNIT) + _RegCheck(#nm,&(loc),rdx,wd,off,dep,NULL,NULL,0,sizeof(UNIT),sizeof((loc)),URDATA),(fl) #define URDATAD(nm,loc,rdx,wd,off,dep,fl,desc) \ - _REGDATANF(#nm,&(loc),rdx,wd,off,dep,desc,NULL,0,0,sizeof((loc)),URDATAD),((fl) | REG_UNIT) + _RegCheck(#nm,&(loc),rdx,wd,off,dep,desc,NULL,0,sizeof(UNIT),sizeof((loc)),URDATAD),(fl) #define URDATADF(nm,loc,rdx,wd,off,dep,fl,desc,flds) \ - _REGDATANF(#nm,&(loc),rdx,wd,off,dep,desc,flds,0,0,sizeof((loc)),URDATADF),((fl) | REG_UNIT) + _RegCheck(#nm,&(loc),rdx,wd,off,dep,desc,flds,0,sizeof(UNIT),sizeof((loc)),URDATADF),(fl) /* Arrayed register whose data is part of an arbitrary structure */ #define STRDATA(nm,loc,rdx,wd,off,dep,siz,fl) \ - _REGDATANF(#nm,&(loc),rdx,wd,off,dep,NULL,NULL,0,siz,sizeof((loc)),STRDATA),((fl) | REG_STRUCT) + _RegCheck(#nm,&(loc),rdx,wd,off,dep,NULL,NULL,0,siz,sizeof((loc)),STRDATA),(fl) #define STRDATAD(nm,loc,rdx,wd,off,dep,siz,fl,desc) \ - _REGDATANF(#nm,&(loc),rdx,wd,off,dep,desc,NULL,0,siz,sizeof((loc)),STRDATAD),((fl) | REG_STRUCT) + _RegCheck(#nm,&(loc),rdx,wd,off,dep,desc,NULL,0,siz,sizeof((loc)),STRDATAD),(fl) #define STRDATADF(nm,loc,rdx,wd,off,dep,siz,fl,desc,flds) \ - _REGDATANF(#nm,&(loc),rdx,wd,off,dep,desc,flds,0,siz,sizeof((loc)),STRDATADF),((fl) | REG_STRUCT) + _RegCheck(#nm,&(loc),rdx,wd,off,dep,desc,flds,0,siz,sizeof((loc)),STRDATADF),(fl) /* Hidden Blob of Data - Only used for SAVE/RESTORE */ #define SAVEDATA(nm,loc) \ - _REGDATANF(#nm,&(loc),0,8,0,1,NULL,NULL,0,sizeof(loc),sizeof(loc),SAVEDATA),(REG_HRO) + _RegCheck(#nm,&(loc),0,8,0,1,NULL,NULL,0,sizeof(loc),sizeof(loc),SAVEDATA),(REG_HRO) #define STARTBIT {"", 0x00000000, 0, NULL, NULL} /* Start at beginning bit */ #define BIT(nm) {#nm, 0xffffffff, 1, NULL, NULL} /* Single Bit definition */ #define BITNC {"", 0xffffffff, 1, NULL, NULL} /* Don't care Bit definition */ @@ -995,95 +1111,6 @@ struct MEMFILE { #define BITNCF(sz) {"", 0xffffffff, sz, NULL, NULL} /* 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,NULL} /* Bit Field definition with value->name map */ -#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) \ - _REGDATANF("nm",&(loc),rdx,wd,off,dep,desc,flds,qptr,siz,sizeof((loc)),REGDATA),(fl) -#define REGDATAC(nm,loc,rdx,wd,off,dep,desc,flds,fl,qptr,siz) \ - _REGDATANF("nm",&(loc),rdx,wd,off,dep,desc,flds,qptr,siz,sizeof((loc)),REGDATAC),(fl) -/* Right Justified Octal Register Data */ -#define ORDATA(nm,loc,wd) \ - _REGDATANF("nm",&(loc),8,wd,0,1,NULL,NULL,0,0,sizeof((loc)),ORDATA) -#define ORDATAD(nm,loc,wd,desc) \ - _REGDATANF("nm",&(loc),8,wd,0,1,desc,NULL,0,0,sizeof((loc)),ORDATAD) -#define ORDATADF(nm,loc,wd,desc,flds) \ - _REGDATANF("nm",&(loc),8,wd,0,1,desc,flds,0,0,sizeof((loc)),ORDATADF) -/* Right Justified Decimal Register Data */ -#define DRDATA(nm,loc,wd) \ - _REGDATANF("nm",&(loc),10,wd,0,1,NULL,NULL,0,0,sizeof((loc)),DRDATA) -#define DRDATAD(nm,loc,wd,desc) \ - _REGDATANF("nm",&(loc),10,wd,0,1,desc,NULL,0,0,sizeof((loc)),DRDATAD) -#define DRDATADF(nm,loc,wd,desc,flds) \ - _REGDATANF("nm",&(loc),10,wd,0,1,desc,flds,0,0,sizeof((loc)),DRDATADF) -/* Right Justified Hexadecimal Register Data */ -#define HRDATA(nm,loc,wd) \ - _REGDATANF("nm",&(loc),16,wd,0,1,NULL,NULL,0,0,sizeof((loc)),HRDATA) -#define HRDATAD(nm,loc,wd,desc) \ - _REGDATANF("nm",&(loc),16,wd,0,1,desc,NULL,0,0,sizeof((loc)),HRDATAD) -#define HRDATADF(nm,loc,wd,desc,flds) \ - _REGDATANF("nm",&(loc),16,wd,0,1,desc,flds,0,0,sizeof((loc)),HRDATADF) -/* Right Justified Binary Register Data */ -#define BINRDATA(nm,loc,wd) \ - _REGDATANF("nm",&(loc),2,wd,0,1,NULL,NULL,0,0,sizeof((loc)),BINRDATA) -#define BINRDATAD(nm,loc,wd,desc) \ - _REGDATANF("nm",&(loc),2,wd,0,1,desc,NULL,0,0,sizeof((loc)),BINRDATAD) -#define BINRDATADF(nm,loc,wd,desc,flds) \ - _REGDATANF("nm",&(loc),2,wd,0,1,desc,flds,0,0,sizeof((loc)),BINRDATADF) -/* One-bit binary flag at an arbitrary offset in a 32-bit word Register */ -#define FLDATA(nm,loc,pos) \ - _REGDATANF("nm",&(loc),2,1,pos,1,NULL,NULL,0,0,sizeof((loc)),FLDATA) -#define FLDATAD(nm,loc,pos,desc) \ - _REGDATANF("nm",&(loc),2,1,pos,1,desc,NULL,0,0,sizeof((loc)),FLDATAD) -#define FLDATADF(nm,loc,pos,desc,flds) \ - _REGDATANF("nm",&(loc),2,1,pos,1,desc,flds,0,0,sizeof((loc)),FLDATADF) -/* Arbitrary location and Radix Register */ -#define GRDATA(nm,loc,rdx,wd,pos) \ - _REGDATANF("nm",&(loc),rdx,wd,pos,1,NULL,NULL,0,0,sizeof((loc)),GRDATA) -#define GRDATAD(nm,loc,rdx,wd,pos,desc) \ - _REGDATANF("nm",&(loc),rdx,wd,pos,1,desc,NULL,0,0,sizeof((loc)),GRDATAD) -#define GRDATADF(nm,loc,rdx,wd,pos,desc,flds) \ - _REGDATANF("nm",&(loc),rdx,wd,pos,1,desc,flds,0,0,sizeof((loc)),GRDATADF) -/* Arrayed register whose data is kept in a standard C array Register */ -#define BRDATA(nm,loc,rdx,wd,dep) \ - _REGDATANF("nm",&(loc),rdx,wd,0,dep,NULL,NULL,0,0,sizeof(*(loc)),BRDATA) -#define BRDATAD(nm,loc,rdx,wd,dep,desc) \ - _REGDATANF("nm",&(loc),rdx,wd,0,dep,desc,NULL,0,0,sizeof(*(loc)),BRDATAD) -#define BRDATADF(nm,loc,rdx,wd,dep,desc,flds) \ - _REGDATANF("nm",&(loc),rdx,wd,0,dep,desc,flds,0,0,sizeof(*(loc)),BRDATADF) -/* Range of memory whose data is successive scalar values accessed like an array Register */ -#define VBRDATA(nm,loc,rdx,wd,dep) \ - _REGDATANF("nm",&(loc),rdx,wd,0,dep,NULL,NULL,0,0,sizeof(loc),VBRDATA) -#define VBRDATAD(nm,loc,rdx,wd,dep,desc) \ - _REGDATANF("nm",&(loc),rdx,wd,0,dep,desc,NULL,0,0,sizeof(loc),VBRDATAD) -#define VBRDATADF(nm,loc,rdx,wd,dep,desc,flds) \ - _REGDATANF("nm",&(loc),rdx,wd,0,dep,desc,flds,0,0,sizeof(loc),VBRDATADF) -/* Arrayed register whose data is part of the UNIT structure */ -#define URDATA(nm,loc,rdx,wd,off,dep,fl) \ - _REGDATANF("nm",&(loc),rdx,wd,off,dep,NULL,NULL,0,0,sizeof((loc)),URDATA),((fl) | REG_UNIT) -#define URDATAD(nm,loc,rdx,wd,off,dep,fl,desc) \ - _REGDATANF("nm",&(loc),rdx,wd,off,dep,desc,NULL,0,0,sizeof((loc)),URDATAD),((fl) | REG_UNIT) -#define URDATADF(nm,loc,rdx,wd,off,dep,fl,desc,flds) \ - _REGDATANF("nm",&(loc),rdx,wd,off,dep,desc,flds,0,0,sizeof((loc)),URDATADF),((fl) | REG_UNIT) -/* Arrayed register whose data is part of an arbitrary structure */ -#define STRDATA(nm,loc,rdx,wd,off,dep,siz,fl) \ - _REGDATANF("nm",&(loc),rdx,wd,off,dep,NULL,NULL,0,siz,sizeof((loc)),STRDATA),((fl) | REG_STRUCT) -#define STRDATAD(nm,loc,rdx,wd,off,dep,siz,fl,desc) \ - _REGDATANF("nm",&(loc),rdx,wd,off,dep,desc,NULL,0,siz,sizeof((loc)),STRDATAD),((fl) | REG_STRUCT) -#define STRDATADF(nm,loc,rdx,wd,off,dep,siz,fl,desc,flds) \ - _REGDATANF("nm",&(loc),rdx,wd,off,dep,desc,flds,0,siz,sizeof((loc)),STRDATADF),((fl) | REG_STRUCT) -/* Hidden Blob of Data - Only used for SAVE/RESTORE */ -#define SAVEDATA(nm,loc) \ - _REGDATANF("nm",&(loc),0,8,0,1,NULL,NULL,0,sizeof(loc),sizeof(loc)),SAVEDATA),(REG_HRO) -#define STARTBIT {"", 0x00000000, 0, NULL, NULL} /* Start at beginning bit */ -#define BIT(nm) {"nm", 0xffffffff, 1, NULL, NULL} /* Single Bit definition */ -#define BITNC {"", 0xffffffff, 1, NULL, NULL} /* Don't care Bit definition */ -#define BITF(nm,sz) {"nm", 0xffffffff, sz, NULL, NULL} /* Bit Field definition */ -#define BITNCF(sz) {"", 0xffffffff, sz, NULL, NULL} /* 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,NULL} /* Bit Field definition with value->name map */ -#endif #define ENDBITS {NULL} /* end of bitfield list */