1 /*
2 * Copyright (c) 2016 Charles Anthony
3 * Copyright (c) 2021 The DPS8M Development Team
4 *
5 * All rights reserved.
6 *
7 * This software is made available under the terms of the ICU
8 * License, version 1.8.1 or later. For more details, see the
9 * LICENSE.md file at the top-level directory of this distribution.
10 */
11
12 // history debugging
13
14 #ifdef TESTING
15
16 # include <unistd.h>
17 # include <sys/types.h>
18 # include <sys/stat.h>
19 # include <fcntl.h>
20
21 # include "dps8.h"
22 # include "dps8_sys.h"
23 # include "dps8_cpu.h"
24 # include "dps8_utils.h"
25 # include "hdbg.h"
26
27 # include "dps8_faults.h"
28
29 enum hevtType {
30 hevtEmpty = 0,
31 hevtTrace,
32 hevtM,
33 hevtAPU,
34 hevtFault,
35 hevtIntrSet,
36 hevtIntr,
37 hevtReg,
38 hevtPAReg,
39 hevtDSBRReg,
40 hevtIEFP,
41 hevtNote,
42 };
43
44 struct hevt {
45 enum hevtType type;
46 uint64 time;
47 uint cpu_idx;
48 char ctx[16];
49 bool rw; // F: read T: write
50 union {
51 struct {
52 addr_modes_e addrMode;
53 word15 segno;
54 word18 ic;
55 word3 ring;
56 word36 inst;
57 } trace;
58
59 struct {
60 word24 addr;
61 word36 data;
62 } memref;
63
64 struct {
65 _fault faultNumber;
66 _fault_subtype subFault;
67 char faultMsg [64];
68 } fault;
69
70 struct {
71 uint inum;
72 uint cpuUnitIdx;
73 uint scuUnitIdx;
74 } intrSet;
75
76 struct {
77 uint intr_pair_addr;
78 } intr;
79
80 struct {
81 enum hregs_t type;
82 word36 data;
83 } reg;
84
85 struct {
86 enum hregs_t type;
87 struct par_s data;
88 } par;
89
90 struct {
91 enum hdbgIEFP_e type;
92 word15 segno;
93 word18 offset;
94 } iefp;
95
96 struct {
97 enum hregs_t type;
98 struct dsbr_s data;
99 } dsbr;
100
101 struct {
102 enum hregs_t type;
103 word15 segno;
104 word18 offset;
105 word24 final;
106 word36 data;
107 } apu;
108 struct {
109 # define NOTE_SZ 64
110 char noteBody [NOTE_SZ];
111 } note;
112 };
113 };
114
115 static struct hevt * hevents = NULL;
116 static long hdbgSize = 0;
117 static long hevtPtr = 0;
118 static long hevtMark = 0;
119 static long hdbgSegNum = -1;
120 static bool blacklist[MAX18];
121 static long hdbgCPUMask = 0;
122
createBuffer(void)123 static void createBuffer (void) {
124 if (hevents) {
125 free (hevents);
126 hevents = NULL;
127 }
128 if (hdbgSize <= 0)
129 return;
130 hevents = malloc (sizeof (struct hevt) * hdbgSize);
131 if (! hevents) {
132 sim_printf ("hdbg createBuffer failed\n");
133 return;
134 }
135 memset (hevents, 0, sizeof (struct hevt) * hdbgSize);
136
137 hevtPtr = 0;
138 }
139
hdbg_inc(void)140 static long hdbg_inc (void) {
141 //hevtPtr = (hevtPtr + 1) % hdbgSize;
142 long ret = __sync_fetch_and_add (& hevtPtr, 1l) % hdbgSize;
143
144 if (hevtMark > 0) {
145 long ret = __sync_fetch_and_sub (& hevtMark, 1l);
146 if (ret <= 0)
147 hdbgPrint ();
148 }
149 return ret;
150 }
151
152 # define hev(t, tf, filter) \
153 if (! hevents) \
154 goto done; \
155 if (filter && hdbgSegNum >= 0 && hdbgSegNum != cpu.PPR.PSR) \
156 goto done; \
157 if (filter && hdbgSegNum > 0 && blacklist[cpu.PPR.IC]) \
158 goto done; \
159 if (hdbgCPUMask && (hdbgCPUMask & (1 << current_running_cpu_idx))) \
160 goto done; \
161 unsigned long p = hdbg_inc (); \
162 hevents[p].type = t; \
163 hevents[p].cpu_idx = current_running_cpu_idx; \
164 hevents[p].time = cpu.cycleCnt; \
165 strncpy (hevents[p].ctx, ctx, 15); \
166 hevents[p].ctx[15] = 0; \
167 hevents[p].rw = tf;
168
169
170 # define FILTER true
171 # define NO_FILTER false
172
173 # define WR true
174 # define RD false
175
hdbgTrace(const char * ctx)176 void hdbgTrace (const char * ctx) {
177 hev (hevtTrace, RD, FILTER);
178 hevents[p].trace.addrMode = get_addr_mode ();
179 hevents[p].trace.segno = cpu.PPR.PSR;
180 hevents[p].trace.ic = cpu.PPR.IC;
181 hevents[p].trace.ring = cpu.PPR.PRR;
182 hevents[p].trace.inst = IWB_IRODD;
183 done: ;
184 }
185
hdbgMRead(word24 addr,word36 data,const char * ctx)186 void hdbgMRead (word24 addr, word36 data, const char * ctx) {
187 hev (hevtM, RD, FILTER);
188 hevents[p].memref.addr = addr;
189 hevents[p].memref.data = data;
190 done: ;
191 }
192
hdbgMWrite(word24 addr,word36 data,const char * ctx)193 void hdbgMWrite (word24 addr, word36 data, const char * ctx) {
194 hev (hevtM, WR, FILTER);
195 hevents[p].memref.addr = addr;
196 hevents[p].memref.data = data;
197 done: ;
198 }
199
hdbgAPURead(word15 segno,word18 offset,word24 final,word36 data,const char * ctx)200 void hdbgAPURead (word15 segno, word18 offset, word24 final, word36 data, const char * ctx) {
201 hev (hevtAPU, RD, FILTER);
202 hevents[p].apu.segno = segno;
203 hevents[p].apu.offset = offset;
204 hevents[p].apu.final = final;
205 hevents[p].apu.data = data;
206 done: ;
207 }
208
hdbgAPUWrite(word15 segno,word18 offset,word24 final,word36 data,const char * ctx)209 void hdbgAPUWrite (word15 segno, word18 offset, word24 final, word36 data, const char * ctx) {
210 hev (hevtAPU, WR, FILTER);
211 hevents[p].apu.segno = segno;
212 hevents[p].apu.offset = offset;
213 hevents[p].apu.final = final;
214 hevents[p].apu.data = data;
215 done: ;
216 }
217
hdbgFault(_fault faultNumber,_fault_subtype subFault,const char * faultMsg,const char * ctx)218 void hdbgFault (_fault faultNumber, _fault_subtype subFault, const char * faultMsg, const char * ctx) {
219 hev (hevtFault, RD, FILTER);
220 hevents[p].fault.faultNumber = faultNumber;
221 hevents[p].fault.subFault = subFault;
222 strncpy (hevents[p].fault.faultMsg, faultMsg, 63);
223 hevents[p].fault.faultMsg[63] = 0;
224 done: ;
225 }
226
hdbgIntrSet(uint inum,uint cpuUnitIdx,uint scuUnitIdx,const char * ctx)227 void hdbgIntrSet (uint inum, uint cpuUnitIdx, uint scuUnitIdx, const char * ctx) {
228 hev (hevtIntrSet, RD, FILTER);
229 hevents[p].intrSet.inum = inum;
230 hevents[p].intrSet.cpuUnitIdx = cpuUnitIdx;
231 hevents[p].intrSet.scuUnitIdx = scuUnitIdx;
232 done: ;
233 }
234
hdbgIntr(uint intr_pair_addr,const char * ctx)235 void hdbgIntr (uint intr_pair_addr, const char * ctx) {
236 hev (hevtIntr, RD, FILTER);
237 hevents[p].cpu_idx = current_running_cpu_idx;
238 hevents[p].time = cpu.cycleCnt;
239 strncpy (hevents[p].ctx, ctx, 15);
240 hevents[p].ctx[15] = 0;
241 hevents[p].intr.intr_pair_addr = intr_pair_addr;
242 done: ;
243 }
244
hdbgRegR(enum hregs_t type,word36 data,const char * ctx)245 void hdbgRegR (enum hregs_t type, word36 data, const char * ctx) {
246 hev (hevtReg, RD, FILTER);
247 hevents[p].reg.type = type;
248 hevents[p].reg.data = data;
249 done: ;
250 }
251
252
hdbgRegW(enum hregs_t type,word36 data,const char * ctx)253 void hdbgRegW (enum hregs_t type, word36 data, const char * ctx) {
254 hev (hevtReg, WR, FILTER);
255 hevents[p].reg.type = type;
256 hevents[p].reg.data = data;
257 done: ;
258 }
259
260
hdbgPARegR(enum hregs_t type,struct par_s * data,const char * ctx)261 void hdbgPARegR (enum hregs_t type, struct par_s * data, const char * ctx) {
262 hev (hevtPAReg, RD, FILTER);
263 hevents[p].par.type = type;
264 hevents[p].par.data = * data;
265 done: ;
266 }
267
hdbgPARegW(enum hregs_t type,struct par_s * data,const char * ctx)268 void hdbgPARegW (enum hregs_t type, struct par_s * data, const char * ctx) {
269 hev (hevtPAReg, WR, FILTER);
270 hevents[p].par.type = type;
271 hevents[p].par.data = * data;
272 done: ;
273 }
274
275 # if 0
276 void hdbgDSBRRegR (enum hregs_t type, struct dsbr_s * data, const char * ctx) {
277 hev (hevtDSBRReg, RD, FILTER);
278 hevents[p].dsbr.type = type;
279 hevents[p].dsbr.data = * data;
280 done: ;
281 }
282
283 void hdbgDSBRRegW (enum hregs_t type, struct dsbr_s * data, const char * ctx) {
284 hev (hevtDSBRReg, WR, FILTER);
285 hevents[p].dsbr.type = type;
286 hevents[p].dsbr.data = * data;
287 done: ;
288 }
289 # endif
290
hdbgIEFP(enum hdbgIEFP_e type,word15 segno,word18 offset,const char * ctx)291 void hdbgIEFP (enum hdbgIEFP_e type, word15 segno, word18 offset, const char * ctx) {
292 hev (hevtIEFP, RD, FILTER);
293 hevents [p].iefp.type = type;
294 hevents [p].iefp.segno = segno;
295 hevents [p].iefp.offset = offset;
296 done: ;
297 }
298
hdbgNote(const char * ctx,const char * fmt,...)299 void hdbgNote (const char * ctx, const char * fmt, ...) {
300 hev (hevtNote, RD, NO_FILTER);
301 va_list arglist;
302 va_start (arglist, fmt);
303 vsnprintf (hevents [p].note.noteBody, NOTE_SZ - 1, fmt, arglist);
304 va_end (arglist);
305 done: ;
306 }
307
308 static FILE * hdbgOut = NULL;
309
printM(struct hevt * p)310 static void printM (struct hevt * p) {
311 fprintf (hdbgOut, "DBG(%"PRId64")> CPU %d FINAL: %s %s %08o %012"PRIo64"\n",
312 p->time,
313 p->cpu_idx,
314 p->ctx,
315 p->rw ? "write" : "read ",
316 p->memref.addr,
317 p->memref.data);
318 }
319
printAPU(struct hevt * p)320 static void printAPU (struct hevt * p) {
321 fprintf (hdbgOut, "DBG(%"PRId64")> CPU %d APU: %s %s %05o:%06o %08o %012"PRIo64"\n",
322 p->time,
323 p->cpu_idx,
324 p->ctx,
325 p->rw ? "write" : "read ",
326 p->apu.segno,
327 p->apu.offset,
328 p->apu.final,
329 p->apu.data);
330 }
331
printTrace(struct hevt * p)332 static void printTrace (struct hevt * p) {
333 char buf[256];
334 if (p -> trace.addrMode == ABSOLUTE_mode) {
335 fprintf (hdbgOut, "DBG(%"PRId64")> CPU %d TRACE: %s %06o %o %012"PRIo64" (%s)\n",
336 p->time,
337 p->cpu_idx,
338 p->ctx,
339 p->trace.ic,
340 p->trace.ring,
341 p->trace.inst,
342 disassemble (buf, p->trace.inst));
343 } else {
344 fprintf (hdbgOut, "DBG(%"PRId64")> CPU %d TRACE: %s %05o:%06o %o %012"PRIo64" (%s)\n",
345 p->time,
346 p->cpu_idx,
347 p->ctx,
348 p->trace.segno,
349 p->trace.ic,
350 p->trace.ring,
351 p->trace.inst,
352 disassemble (buf, p->trace.inst));
353 }
354 }
355
printFault(struct hevt * p)356 static void printFault (struct hevt * p) {
357 fprintf (hdbgOut, "DBG(%"PRId64")> CPU %d FAULT: %s Fault %d(0%o), sub %"PRId64"(0%"PRIo64"), '%s'\n",
358 p->time,
359 p->cpu_idx,
360 p->ctx,
361 p->fault.faultNumber,
362 p->fault.faultNumber,
363 p->fault.subFault.bits,
364 p->fault.subFault.bits,
365 p->fault.faultMsg);
366 }
367
printIntrSet(struct hevt * p)368 static void printIntrSet (struct hevt * p) {
369 fprintf (hdbgOut, "DBG(%"PRId64")> CPU %d INTR_SET: %s number %d(0%o), CPU %u SCU %u\n",
370 p->time,
371 p->cpu_idx,
372 p->ctx,
373 p->intrSet.inum,
374 p->intrSet.inum,
375 p->intrSet.cpuUnitIdx,
376 p->intrSet.scuUnitIdx);
377 }
378
printIntr(struct hevt * p)379 static void printIntr (struct hevt * p) {
380 fprintf (hdbgOut, "DBG(%"PRId64")> CPU %d INTR: %s Interrupt pair address %o\n",
381 p->time,
382 p->cpu_idx,
383 p->ctx,
384 p->intr.intr_pair_addr);
385 }
386
387 // Keep sync'd with hregs_t
388 static char * regNames[] = {
389 "A ",
390 "Q ",
391 "X0", "X1", "X2", "X3", "X4", "X5", "X6", "X7",
392 "AR0", "AR1", "AR2", "AR3", "AR4", "AR5", "AR6", "AR7",
393 "PR0", "PR1", "PR2", "PR3", "PR4", "PR5", "PR6", "PR7",
394 "Y ", "Z ",
395 "IR ",
396 "DSBR",
397 };
398
printReg(struct hevt * p)399 static void printReg (struct hevt * p) {
400 if (p->reg.type == hreg_IR)
401 fprintf (hdbgOut, "DBG(%"PRId64")> CPU %d REG: %s %s %s %012"PRIo64" Z%o N%o C %o O%o T%o \n",
402 p->time,
403 p->cpu_idx,
404 p->ctx,
405 p->rw ? "write" : "read ",
406 regNames[p->reg.type],
407 p->reg.data,
408 TSTF (p->reg.data, I_ZERO),
409 TSTF (p->reg.data, I_NEG),
410 TSTF (p->reg.data, I_CARRY),
411 TSTF (p->reg.data, I_OFLOW),
412 TSTF (p->reg.data, I_TALLY));
413 else if (p->reg.type >= hreg_X0 && p->reg.type <= hreg_X7)
414 fprintf (hdbgOut, "DBG(%"PRId64")> CPU %d REG: %s %s %s %06"PRIo64"\n",
415 p->time,
416 p->cpu_idx,
417 p->ctx,
418 p->rw ? "write" : "read ",
419 regNames[p->reg.type],
420 p->reg.data);
421 else
422 fprintf (hdbgOut, "DBG(%"PRId64")> CPU %d REG: %s %s %s %012"PRIo64"\n",
423 p->time,
424 p->cpu_idx,
425 p->ctx,
426 p->rw ? "write" : "read ",
427 regNames[p->reg.type],
428 p->reg.data);
429 }
430
printPAReg(struct hevt * p)431 static void printPAReg (struct hevt * p)
432 {
433 if (p->reg.type >= hreg_PR0 && p->reg.type <= hreg_PR7)
434 fprintf (hdbgOut, "DBG(%"PRId64")> CPU %d REG: %s %s %s %05o:%06o BIT %2o RNR %o\n",
435 p->time,
436 p->cpu_idx,
437 p->ctx,
438 p->rw ? "write" : "read ",
439 regNames[p->reg.type],
440 p->par.data.SNR,
441 p->par.data.WORDNO,
442 p->par.data.PR_BITNO,
443 p->par.data.RNR);
444 else
445 fprintf (hdbgOut, "DBG(%"PRId64")> CPU %d REG: %s write %s %05o:%06o CHAR %o BIT %2o RNR %o\n",
446 p->time,
447 p->cpu_idx,
448 p->ctx,
449 regNames[p->reg.type],
450 p->par.data.SNR,
451 p->par.data.WORDNO,
452 p->par.data.AR_CHAR,
453 p->par.data.AR_BITNO,
454 p->par.data.RNR);
455 }
456
printDSBRReg(struct hevt * p)457 static void printDSBRReg (struct hevt * p) {
458 fprintf (hdbgOut, "DBG(%"PRId64")> CPU %d REG: %s %s %s %05o:%06o BIT %2o RNR %o\n",
459 p->time,
460 p->cpu_idx,
461 p->ctx,
462 p->rw ? "write" : "read ",
463 regNames[p->reg.type],
464 p->par.data.SNR,
465 p->par.data.WORDNO,
466 p->par.data.PR_BITNO,
467 p->par.data.RNR);
468 }
469
printIEFP(struct hevt * p)470 static void printIEFP (struct hevt * p) {
471 switch (p->iefp.type) {
472 case hdbgIEFP_abs_bar_read:
473 fprintf (hdbgOut, "DBG(%"PRId64")> CPU %d IEFP ABS BAR READ: |%06o\n",
474 p->time,
475 p->cpu_idx,
476 p->iefp.offset);
477 break;
478
479 case hdbgIEFP_abs_read:
480 fprintf (hdbgOut, "DBG(%"PRId64")> CPU %d IEFP ABS READ: :%06o\n",
481 p->time,
482 p->cpu_idx,
483 p->iefp.offset);
484 break;
485
486 case hdbgIEFP_bar_read:
487 fprintf (hdbgOut, "DBG(%"PRId64")> CPU %d IEFP APP BAR READ: %05o|%06o\n",
488 p->time,
489 p->cpu_idx,
490 p->iefp.segno,
491 p->iefp.offset);
492 break;
493
494 case hdbgIEFP_read:
495 fprintf (hdbgOut, "DBG(%"PRId64")> CPU %d IEFP APP READ: %05o:%06o\n",
496 p->time,
497 p->cpu_idx,
498 p->iefp.segno,
499 p->iefp.offset);
500 break;
501
502 case hdbgIEFP_abs_bar_write:
503 fprintf (hdbgOut, "DBG(%"PRId64")> CPU %d IEFP ABS BAR WRITE: |%06o\n",
504 p->time,
505 p->cpu_idx,
506 p->iefp.offset);
507 break;
508
509 case hdbgIEFP_abs_write:
510 fprintf (hdbgOut, "DBG(%"PRId64")> CPU %d IEFP ABS WRITE: :%06o\n",
511 p->time,
512 p->cpu_idx,
513 p->iefp.offset);
514 break;
515
516 case hdbgIEFP_bar_write:
517 fprintf (hdbgOut, "DBG(%"PRId64")> CPU %d IEFP APP BAR WRITE: %05o|%06o\n",
518 p->time,
519 p->cpu_idx,
520 p->iefp.segno,
521 p->iefp.offset);
522 break;
523
524 case hdbgIEFP_write:
525 fprintf (hdbgOut, "DBG(%"PRId64")> CPU %d IEFP APP WRITE: %05o:%06o\n",
526 p->time,
527 p->cpu_idx,
528 p->iefp.segno,
529 p->iefp.offset);
530 break;
531
532 default:
533 fprintf (hdbgOut, "DBG(%"PRId64")> CPU %d IEFP ??? ??? WRITE: %05o?%06o\n",
534 p->time,
535 p->cpu_idx,
536 p->iefp.segno,
537 p->iefp.offset);
538 break;
539 }
540 }
541
printNote(struct hevt * p)542 static void printNote (struct hevt * p) {
543 fprintf (hdbgOut, "DBG(%"PRId64")> Note: %s\n",
544 p->time,
545 p->note.noteBody);
546 }
547
hdbgPrint(void)548 void hdbgPrint (void) {
549 sim_printf ("hdbg print\n");
550 if (! hevents)
551 goto done;
552 struct hevt * t = hevents;
553 hevents = NULL;
554 hdbgOut = fopen ("hdbg.list", "w");
555 if (! hdbgOut) {
556 sim_printf ("can't open hdbg.list\n");
557 goto done;
558 }
559 time_t curtime;
560 time (& curtime);
561 fprintf (hdbgOut, "%s\n", ctime (& curtime));
562
563 for (unsigned long p = 0; p < hdbgSize; p ++) {
564 unsigned long q = (hevtPtr + p) % hdbgSize;
565 struct hevt * evtp = t + q;
566 switch (evtp -> type) {
567 case hevtEmpty:
568 break;
569
570 case hevtTrace:
571 printTrace (evtp);
572 break;
573
574 case hevtM:
575 printM (evtp);
576 break;
577
578 case hevtAPU:
579 printAPU (evtp);
580 break;
581
582 # if 0
583 case hevtIWBUpdate:
584 printIWBUpdate (evtp);
585 break;
586 # endif
587
588 # if 0
589 case hevtRegs:
590 printRegs (evtp);
591 break;
592 # endif
593
594 case hevtFault:
595 printFault (evtp);
596 break;
597
598 case hevtIntrSet:
599 printIntrSet (evtp);
600 break;
601
602 case hevtIntr:
603 printIntr (evtp);
604 break;
605
606 case hevtReg:
607 printReg (evtp);
608 break;
609
610 case hevtPAReg:
611 printPAReg (evtp);
612 break;
613
614 case hevtDSBRReg:
615 printDSBRReg (evtp);
616 break;
617
618 case hevtIEFP:
619 printIEFP (evtp);
620 break;
621
622 case hevtNote:
623 printNote (evtp);
624 break;
625
626 default:
627 fprintf (hdbgOut, "hdbgPrint ? %d\n", evtp -> type);
628 break;
629 }
630 }
631 fclose (hdbgOut);
632
633 int fd = open ("M.dump", O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
634 if (fd == -1) {
635 sim_printf ("can't open M.dump\n");
636 goto done;
637 }
638 // cast discards volatile
639 /* ssize_t n = */ write (fd, (const void *) M, MEMSIZE * sizeof (word36));
640 close (fd);
641 done: ;
642 }
643
644 # if 0
645 void hdbg_mark (void) {
646 hevtMark = hdbgSize;
647 sim_printf ("hdbg mark set to %ld\n", hevtMark);
648 }
649 # endif
650
hdbg_cpu_mask(UNUSED int32 arg,const char * buf)651 t_stat hdbg_cpu_mask (UNUSED int32 arg, const char * buf)
652 {
653 hdbgCPUMask = strtoul (buf, NULL, 0);
654 sim_printf ("hdbg CPU mask set to %ld\n", hdbgCPUMask);
655 return SCPE_OK;
656 }
657
658 // set buffer size
hdbg_size(UNUSED int32 arg,const char * buf)659 t_stat hdbg_size (UNUSED int32 arg, const char * buf) {
660 hdbgSize = strtoul (buf, NULL, 0);
661 sim_printf ("hdbg size set to %ld\n", hdbgSize);
662 createBuffer ();
663 return SCPE_OK;
664 }
665
666 // set target segment number
hdbgSegmentNumber(UNUSED int32 arg,const char * buf)667 t_stat hdbgSegmentNumber (UNUSED int32 arg, const char * buf) {
668 hdbgSegNum = strtoul (buf, NULL, 8);
669 sim_printf ("hdbg target segment number set to %lu\n", hdbgSize);
670 createBuffer ();
671 return SCPE_OK;
672 }
673
hdbgBlacklist(UNUSED int32 arg,const char * buf)674 t_stat hdbgBlacklist (UNUSED int32 arg, const char * buf) {
675 char work[strlen (buf) + 1];
676 if (sscanf (buf, "%s", work) != 1)
677 return SCPE_ARG;
678 if (strcasecmp (work, "init") == 0) {
679 memset (blacklist, 0, sizeof (blacklist));
680 return SCPE_OK;
681 }
682 uint low, high;
683 if (sscanf (work, "%o-%o", & low, & high) != 2)
684 return SCPE_ARG;
685 if (low > MAX18 || high > MAX18)
686 return SCPE_ARG;
687 for (uint addr = low; addr <= high; addr ++)
688 blacklist[addr] = true;
689 return SCPE_OK;
690 }
691
hdbg_print(UNUSED int32 arg,const char * buf)692 t_stat hdbg_print (UNUSED int32 arg, const char * buf) {
693 hdbgPrint ();
694 return SCPE_OK;
695 }
696
697 #endif // TESTING
698