This source file includes following definitions.
- cpu_show_config
- cpu_set_config
- cpu_show_nunits
- cpu_set_nunits
- cpu_show_kips
- cpu_set_kips
- cpu_show_stall
- cpu_set_stall
- setCPUConfigL68
- setCPUConfigDPS8M
- cycle_str
- set_cpu_cycle
- set_cpu_idx
- cpu_reset_unit_idx
- simh_cpu_reset_and_clear_unit
- simh_cpu_reset_unit
- str_SDW0
- cpu_boot
- setup_scbank_map
- lookup_cpu_mem_map
- get_serial_number
- do_stats
- ev_poll_cb
- cpu_init
- cpu_reset
- sim_cpu_reset
- cpu_ex
- cpu_dep
- printPtid
- get_highest_intr
- sample_interrupts
- simh_hooks
- panel_process_event
- sim_instr
- cpu_thread_main
- do_LUF_fault
- set_temporary_absolute_mode
- clear_temporary_absolute_mode
- threadz_sim_instr
- operand_size
- read_operand
- write_operand
- set_mem_watch
- nem_check
- core_read
- core_read_lock
- core_write
- core_write_unlock
- core_unlock_all
- core_write_zone
- core_read2
- core_write2
- decode_instruction
- is_priv_mode
- get_bar_mode
- get_addr_mode
- set_addr_mode
- get_BAR_address
- add_history
- add_history_force
- add_dps8m_CU_history
- add_dps8m_DU_OU_history
- add_dps8m_APU_history
- add_dps8m_EAPU_history
- add_l68_CU_history
- add_l68_DU_history
- add_l68_OU_history
- add_l68_APU_history
- get_dbg_verb
- dps8_sim_debug
- setupPROM
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 #include <stdio.h>
35 #include <unistd.h>
36 #include <ctype.h>
37
38 #include "dps8.h"
39 #include "dps8_addrmods.h"
40 #include "dps8_sys.h"
41 #include "dps8_faults.h"
42 #include "dps8_scu.h"
43 #include "dps8_iom.h"
44 #include "dps8_cable.h"
45 #include "dps8_cpu.h"
46 #include "dps8_append.h"
47 #include "dps8_ins.h"
48 #include "dps8_state.h"
49 #include "dps8_math.h"
50 #include "dps8_iefp.h"
51 #include "dps8_console.h"
52 #include "dps8_fnp2.h"
53 #include "dps8_socket_dev.h"
54 #include "dps8_crdrdr.h"
55 #include "dps8_absi.h"
56 #include "dps8_utils.h"
57 #ifdef M_SHARED
58 # include "shm.h"
59 #endif
60 #include "dps8_opcodetable.h"
61 #include "sim_defs.h"
62 #if defined(THREADZ) || defined(LOCKLESS)
63 # include "threadz.h"
64 __thread uint current_running_cpu_idx;
65 #endif
66
67 #include "ver.h"
68
69 #define DBG_CTR cpu.cycleCnt
70
71 #define ASSUME0 0
72
73 #ifdef TESTING
74 # undef FREE
75 # define FREE(p) free(p)
76 #endif
77
78
79
80 static UNIT cpu_unit [N_CPU_UNITS_MAX] = {
81 #ifdef NO_C_ELLIPSIS
82 { UDATA (NULL, UNIT_FIX|UNIT_BINK, MEMSIZE), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
83 { UDATA (NULL, UNIT_FIX|UNIT_BINK, MEMSIZE), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
84 { UDATA (NULL, UNIT_FIX|UNIT_BINK, MEMSIZE), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
85 { UDATA (NULL, UNIT_FIX|UNIT_BINK, MEMSIZE), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
86 { UDATA (NULL, UNIT_FIX|UNIT_BINK, MEMSIZE), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
87 { UDATA (NULL, UNIT_FIX|UNIT_BINK, MEMSIZE), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
88 { UDATA (NULL, UNIT_FIX|UNIT_BINK, MEMSIZE), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
89 { UDATA (NULL, UNIT_FIX|UNIT_BINK, MEMSIZE), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL }
90 #else
91 [0 ... N_CPU_UNITS_MAX - 1] = {
92 UDATA (NULL, UNIT_FIX|UNIT_BINK, MEMSIZE), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL
93 }
94 #endif
95 };
96
97 #define UNIT_IDX(uptr) ((uptr) - cpu_unit)
98
99
100 #define LOCKUP_KIPS 1000
101 static uint kips = LOCKUP_KIPS;
102 static uint64 luf_limits[] =
103 {
104 2000*LOCKUP_KIPS/1000,
105 4000*LOCKUP_KIPS/1000,
106 8000*LOCKUP_KIPS/1000,
107 16000*LOCKUP_KIPS/1000,
108 32000*LOCKUP_KIPS/1000
109 };
110
111 struct stall_point_s stall_points [N_STALL_POINTS];
112 bool stall_point_active = false;
113
114 #ifdef PANEL68
115 static void panel_process_event (void);
116 #endif
117
118 static t_stat simh_cpu_reset_and_clear_unit (UNIT * uptr,
119 UNUSED int32 value,
120 UNUSED const char * cptr,
121 UNUSED void * desc);
122 static char * cycle_str (cycles_e cycle);
123
124 static t_stat cpu_show_config (UNUSED FILE * st, UNIT * uptr,
125 UNUSED int val, UNUSED const void * desc)
126 {
127 long cpu_unit_idx = UNIT_IDX (uptr);
128 if (cpu_unit_idx < 0 || cpu_unit_idx >= N_CPU_UNITS_MAX)
129 {
130 sim_warn ("error: Invalid unit number %ld\n", (long) cpu_unit_idx);
131 return SCPE_ARG;
132 }
133
134 sim_msg ("CPU unit number %ld\n", (long) cpu_unit_idx);
135
136 sim_msg ("Fault base: %03o(8)\n",
137 cpus[cpu_unit_idx].switches.FLT_BASE);
138 sim_msg ("CPU number: %01o(8)\n",
139 cpus[cpu_unit_idx].switches.cpu_num);
140 sim_msg ("Data switches: %012llu(8)\n",
141 (unsigned long long)cpus[cpu_unit_idx].switches.data_switches);
142 sim_msg ("Address switches: %06o(8)\n",
143 cpus[cpu_unit_idx].switches.addr_switches);
144 for (int i = 0; i < (cpus[cpu_unit_idx].tweaks.l68_mode ? N_L68_CPU_PORTS : N_DPS8M_CPU_PORTS); i ++)
145 {
146 sim_msg ("Port%c enable: %01o(8)\n",
147 'A' + i, cpus[cpu_unit_idx].switches.enable [i]);
148 sim_msg ("Port%c init enable: %01o(8)\n",
149 'A' + i, cpus[cpu_unit_idx].switches.init_enable [i]);
150 sim_msg ("Port%c assignment: %01o(8)\n",
151 'A' + i, cpus[cpu_unit_idx].switches.assignment [i]);
152 sim_msg ("Port%c interlace: %01o(8)\n",
153 'A' + i, cpus[cpu_unit_idx].switches.interlace [i]);
154 sim_msg ("Port%c store size: %01o(8)\n",
155 'A' + i, cpus[cpu_unit_idx].switches.store_size [i]);
156 }
157 sim_msg ("Processor mode: %s [%o]\n",
158 cpus[cpu_unit_idx].switches.procMode == procModeMultics ? "Multics" : cpus[cpu_unit_idx].switches.procMode == procModeGCOS ? "GCOS" : "???",
159 cpus[cpu_unit_idx].switches.procMode);
160 sim_msg ("8K Cache: %s\n",
161 cpus[cpu_unit_idx].switches.enable_cache ? "Enabled" : "Disabled");
162 sim_msg ("SDWAM: %s\n",
163 cpus[cpu_unit_idx].switches.sdwam_enable ? "Enabled" : "Disabled");
164 sim_msg ("PTWAM: %s\n",
165 cpus[cpu_unit_idx].switches.ptwam_enable ? "Enabled" : "Disabled");
166
167 sim_msg ("Processor speed: %02o(8)\n",
168 cpus[cpu_unit_idx].options.proc_speed);
169 sim_msg ("DIS enable: %01o(8)\n",
170 cpus[cpu_unit_idx].tweaks.dis_enable);
171 sim_msg ("Steady clock: %01o(8)\n",
172 scu [0].steady_clock);
173 sim_msg ("Halt on unimplemented: %01o(8)\n",
174 cpus[cpu_unit_idx].tweaks.halt_on_unimp);
175 sim_msg ("Enable simulated SDWAM/PTWAM: %01o(8)\n",
176 cpus[cpu_unit_idx].tweaks.enable_wam);
177 sim_msg ("Report faults: %01o(8)\n",
178 cpus[cpu_unit_idx].tweaks.report_faults);
179 sim_msg ("TRO faults enabled: %01o(8)\n",
180 cpus[cpu_unit_idx].tweaks.tro_enable);
181 sim_msg ("Y2K enabled: %01o(8)\n",
182 scu [0].y2k);
183 sim_msg ("drl fatal enabled: %01o(8)\n",
184 cpus[cpu_unit_idx].tweaks.drl_fatal);
185 sim_msg ("useMap: %d\n",
186 cpus[cpu_unit_idx].tweaks.useMap);
187 sim_msg ("PROM installed: %01o(8)\n",
188 cpus[cpu_unit_idx].options.prom_installed);
189 sim_msg ("Hex mode installed: %01o(8)\n",
190 cpus[cpu_unit_idx].options.hex_mode_installed);
191 sim_msg ("8K cache installed: %01o(8)\n",
192 cpus[cpu_unit_idx].options.cache_installed);
193 sim_msg ("Clock slave installed: %01o(8)\n",
194 cpus[cpu_unit_idx].options.clock_slave_installed);
195 #ifdef AFFINITY
196 if (cpus[cpu_unit_idx].set_affinity)
197 sim_msg ("CPU affinity: %d\n", cpus[cpu_unit_idx].affinity);
198 else
199 sim_msg ("CPU affinity: not set\n");
200 #endif
201 sim_msg ("ISOLTS mode: %01o(8)\n", cpus[cpu_unit_idx].tweaks.isolts_mode);
202 sim_msg ("NODIS mode: %01o(8)\n", cpus[cpu_unit_idx].tweaks.nodis);
203 sim_msg ("6180 mode: %01o(8) [%s]\n", cpus[cpu_unit_idx].tweaks.l68_mode, cpus[cpu_unit_idx].tweaks.l68_mode ? "6180" : "DPS8/M");
204 return SCPE_OK;
205 }
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232 static config_value_list_t cfg_multics_fault_base [] =
233 {
234 { "multics", 2 },
235 { NULL, 0 }
236 };
237
238 static config_value_list_t cfg_on_off [] =
239 {
240 { "off", 0 },
241 { "on", 1 },
242 { "disable", 0 },
243 { "enable", 1 },
244 { NULL, 0 }
245 };
246
247 static config_value_list_t cfg_l68_mode [] = {
248 { "dps8/m", 0 },
249 { "dps8m", 0 },
250 { "dps8", 0 },
251 { "l68", 1 },
252 { "l6180", 1 },
253 { "6180", 1 },
254 };
255
256 static config_value_list_t cfg_cpu_mode [] =
257 {
258 { "gcos", 0 },
259 { "multics", 1 },
260 { NULL, 0 }
261 };
262
263 static config_value_list_t cfg_port_letter [] =
264 {
265 { "a", 0 },
266 { "b", 1 },
267 { "c", 2 },
268 { "d", 3 },
269 { "e", 4 },
270 { "f", 5 },
271 { "g", 6 },
272 { "h", 7 },
273 { NULL, 0 }
274 };
275
276 static config_value_list_t cfg_interlace [] =
277 {
278 { "off", 0 },
279 { "2", 2 },
280 { "4", 4 },
281 { NULL, 0 }
282 };
283
284 #ifdef AFFINITY
285 static config_value_list_t cfg_affinity [] =
286 {
287 { "off", -1 },
288 { NULL, 0 }
289 };
290 #endif
291
292 static config_value_list_t cfg_size_list [] =
293 {
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356 { "32", 8 },
357 { "32K", 8 },
358 { "64", 9 },
359 { "64K", 9 },
360 { "128", 10 },
361 { "128K", 10 },
362 { "256", 11 },
363 { "256K", 11 },
364 { "512", 12 },
365 { "512K", 12 },
366 { "1024", 13 },
367 { "1024K", 13 },
368 { "1M", 13 },
369 { "2048", 14 },
370 { "2048K", 14 },
371 { "2M", 14 },
372 { "4096", 15 },
373 { "4096K", 15 },
374 { "4M", 15 },
375 { NULL, 0 }
376 };
377
378 static config_list_t cpu_config_list [] =
379 {
380 { "faultbase", 0, 0177, cfg_multics_fault_base },
381 { "num", 0, 07, NULL },
382 { "data", 0, 0777777777777, NULL },
383 { "stopnum", 0, 999999, NULL },
384 { "mode", 0, 01, cfg_cpu_mode },
385 { "speed", 0, 017, NULL },
386 { "port", 0, N_CPU_PORTS - 1, cfg_port_letter },
387 { "assignment", 0, 7, NULL },
388 { "interlace", 0, 1, cfg_interlace },
389 { "enable", 0, 1, cfg_on_off },
390 { "init_enable", 0, 1, cfg_on_off },
391 { "store_size", 0, 7, cfg_size_list },
392 { "enable_cache", 0, 1, cfg_on_off },
393 { "sdwam", 0, 1, cfg_on_off },
394 { "ptwam", 0, 1, cfg_on_off },
395
396
397 { "dis_enable", 0, 1, cfg_on_off },
398
399 { "steady_clock", 0, 1, cfg_on_off },
400 { "halt_on_unimplemented", 0, 1, cfg_on_off },
401 { "enable_wam", 0, 1, cfg_on_off },
402 { "report_faults", 0, 1, cfg_on_off },
403 { "tro_enable", 0, 1, cfg_on_off },
404
405 { "y2k", 0, 1, cfg_on_off },
406 { "drl_fatal", 0, 1, cfg_on_off },
407 { "useMap", 0, 1, cfg_on_off },
408 { "address", 0, 0777777, NULL },
409 { "prom_installed", 0, 1, cfg_on_off },
410 { "hex_mode_installed", 0, 1, cfg_on_off },
411 { "cache_installed", 0, 1, cfg_on_off },
412 { "clock_slave_installed", 0, 1, cfg_on_off },
413 { "enable_emcall", 0, 1, cfg_on_off },
414
415
416 #ifdef AFFINITY
417 { "affinity", -1, 32767, cfg_affinity },
418 #endif
419 { "isolts_mode", 0, 1, cfg_on_off },
420 { "nodis", 0, 1, cfg_on_off },
421 { "l68_mode", 0, 1, cfg_l68_mode },
422 { NULL, 0, 0, NULL }
423 };
424
425 static t_stat cpu_set_config (UNIT * uptr, UNUSED int32 value,
426 const char * cptr, UNUSED void * desc)
427 {
428 long cpu_unit_idx = UNIT_IDX (uptr);
429 if (cpu_unit_idx < 0 || cpu_unit_idx >= N_CPU_UNITS_MAX)
430 {
431 sim_warn ("error: cpu_set_config: Invalid unit number %ld\n",
432 (long) cpu_unit_idx);
433 return SCPE_ARG;
434 }
435
436 static int port_num = 0;
437
438 config_state_t cfg_state = { NULL, NULL };
439
440 for (;;)
441 {
442 int64_t v;
443 int rc = cfg_parse (__func__, cptr, cpu_config_list,
444 & cfg_state, & v);
445 if (rc == -1)
446 {
447 break;
448 }
449 if (rc == -2)
450 {
451 cfg_parse_done (& cfg_state);
452 return SCPE_ARG;
453 }
454
455 const char * p = cpu_config_list [rc] . name;
456 if (strcmp (p, "faultbase") == 0)
457 cpus[cpu_unit_idx].switches.FLT_BASE = (uint) v;
458 else if (strcmp (p, "num") == 0)
459 cpus[cpu_unit_idx].switches.cpu_num = (uint) v;
460 else if (strcmp (p, "data") == 0)
461 cpus[cpu_unit_idx].switches.data_switches = (word36) v;
462 else if (strcmp (p, "stopnum") == 0)
463 {
464
465
466 int64_t d1 = (v / 1000) % 10;
467 int64_t d2 = (v / 100) % 10;
468 int64_t d3 = (v / 10) % 10;
469 int64_t d4 = (v / 1) % 10;
470 word36 d = 0123000000000;
471 putbits36_6 (& d, 9, (word4) d1);
472 putbits36_6 (& d, 15, (word4) d2);
473 putbits36_6 (& d, 21, (word4) d3);
474 putbits36_6 (& d, 27, (word4) d4);
475 cpus[cpu_unit_idx].switches.data_switches = d;
476 }
477 else if (strcmp (p, "address") == 0)
478 cpus[cpu_unit_idx].switches.addr_switches = (word18) v;
479 else if (strcmp (p, "mode") == 0)
480 cpus[cpu_unit_idx].switches.procMode = v ? procModeMultics : procModeGCOS;
481 else if (strcmp (p, "speed") == 0)
482 cpus[cpu_unit_idx].options.proc_speed = (uint) v;
483 else if (strcmp (p, "port") == 0) {
484 if ((! cpus[cpu_unit_idx].tweaks.l68_mode) && (int) v > 4) {
485 cfg_parse_done (& cfg_state);
486 return SCPE_ARG;
487 }
488 port_num = (int) v;
489 }
490 else if (strcmp (p, "assignment") == 0)
491 cpus[cpu_unit_idx].switches.assignment [port_num] = (uint) v;
492 else if (strcmp (p, "interlace") == 0)
493 cpus[cpu_unit_idx].switches.interlace [port_num] = (uint) v;
494 else if (strcmp (p, "enable") == 0)
495 cpus[cpu_unit_idx].switches.enable [port_num] = (uint) v;
496 else if (strcmp (p, "init_enable") == 0)
497 cpus[cpu_unit_idx].switches.init_enable [port_num] = (uint) v;
498 else if (strcmp (p, "store_size") == 0) {
499 if (v > 7) {
500 if (cpus[cpu_unit_idx].tweaks.l68_mode) {
501 switch (v) {
502 case 8: v = 0; break;
503 case 9: v = 1; break;
504 case 10: v = 3; break;
505 case 11: v = 7; break;
506 case 12: v = 4; break;
507 case 13: v = 5; break;
508 case 14: v = 6; break;
509 case 15: v = 2; break;
510 }
511 } else {
512 switch (v) {
513 case 8: v = 0; break;
514 case 9: v = 1; break;
515 case 10: v = 2; break;
516 case 11: v = 3; break;
517 case 12: v = 4; break;
518 case 13: v = 5; break;
519 case 14: v = 6; break;
520 case 15: v = 7; break;
521 }
522 }
523 }
524 cpus[cpu_unit_idx].switches.store_size [port_num] = (uint) v;
525 }
526 else if (strcmp (p, "enable_cache") == 0)
527 cpus[cpu_unit_idx].switches.enable_cache = (uint) v ? true : false;
528 else if (strcmp (p, "sdwam") == 0)
529 cpus[cpu_unit_idx].switches.sdwam_enable = (uint) v ? true : false;
530 else if (strcmp (p, "ptwam") == 0)
531 cpus[cpu_unit_idx].switches.ptwam_enable = (uint) v ? true : false;
532 else if (strcmp (p, "dis_enable") == 0)
533 cpus[cpu_unit_idx].tweaks.dis_enable = (uint) v;
534 else if (strcmp (p, "steady_clock") == 0)
535 scu [0].steady_clock = (uint) v;
536 else if (strcmp (p, "halt_on_unimplemented") == 0)
537 cpus[cpu_unit_idx].tweaks.halt_on_unimp = (uint) v;
538 else if (strcmp (p, "enable_wam") == 0)
539 cpus[cpu_unit_idx].tweaks.enable_wam = (uint) v;
540 else if (strcmp (p, "report_faults") == 0)
541 cpus[cpu_unit_idx].tweaks.report_faults = (uint) v;
542 else if (strcmp (p, "tro_enable") == 0)
543 cpus[cpu_unit_idx].tweaks.tro_enable = (uint) v;
544 else if (strcmp (p, "y2k") == 0)
545 scu [0].y2k = (uint) v;
546 else if (strcmp (p, "drl_fatal") == 0)
547 cpus[cpu_unit_idx].tweaks.drl_fatal = (uint) v;
548 else if (strcmp (p, "useMap") == 0)
549 cpus[cpu_unit_idx].tweaks.useMap = v;
550 else if (strcmp (p, "prom_installed") == 0)
551 cpus[cpu_unit_idx].options.prom_installed = v;
552 else if (strcmp (p, "hex_mode_installed") == 0)
553 cpus[cpu_unit_idx].options.hex_mode_installed = v;
554 else if (strcmp (p, "cache_installed") == 0)
555 cpus[cpu_unit_idx].options.cache_installed = v;
556 else if (strcmp (p, "clock_slave_installed") == 0)
557 cpus[cpu_unit_idx].options.clock_slave_installed = v;
558 else if (strcmp (p, "enable_emcall") == 0)
559 cpus[cpu_unit_idx].tweaks.enable_emcall = v;
560 #ifdef AFFINITY
561 else if (strcmp (p, "affinity") == 0)
562 if (v < 0)
563 {
564 cpus[cpu_unit_idx].set_affinity = false;
565 }
566 else
567 {
568 cpus[cpu_unit_idx].set_affinity = true;
569 cpus[cpu_unit_idx].affinity = (uint) v;
570 }
571 #endif
572 else if (strcmp (p, "isolts_mode") == 0)
573 {
574 cpus[cpu_unit_idx].tweaks.isolts_mode = v;
575 if (v)
576 {
577 uint store_sz;
578 if (cpus[cpu_unit_idx].tweaks.l68_mode)
579 store_sz = 3;
580 else
581 store_sz = 2;
582 cpus[cpu_unit_idx].isolts_switches_save = cpus[cpu_unit_idx].switches;
583 cpus[cpu_unit_idx].isolts_switches_saved = true;
584
585 cpus[cpu_unit_idx].switches.data_switches = 00000030714000;
586 cpus[cpu_unit_idx].switches.addr_switches = 0100150;
587 cpus[cpu_unit_idx].tweaks.useMap = true;
588 cpus[cpu_unit_idx].tweaks.enable_wam = true;
589 cpus[cpu_unit_idx].switches.assignment [0] = 0;
590 cpus[cpu_unit_idx].switches.interlace [0] = false;
591 cpus[cpu_unit_idx].switches.enable [0] = false;
592 cpus[cpu_unit_idx].switches.init_enable [0] = false;
593 cpus[cpu_unit_idx].switches.store_size [0] = store_sz;
594
595 cpus[cpu_unit_idx].switches.assignment [1] = 0;
596 cpus[cpu_unit_idx].switches.interlace [1] = false;
597 cpus[cpu_unit_idx].switches.enable [1] = true;
598 cpus[cpu_unit_idx].switches.init_enable [1] = false;
599 cpus[cpu_unit_idx].switches.store_size [1] = store_sz;
600
601 cpus[cpu_unit_idx].switches.assignment [2] = 0;
602 cpus[cpu_unit_idx].switches.interlace [2] = false;
603 cpus[cpu_unit_idx].switches.enable [2] = false;
604 cpus[cpu_unit_idx].switches.init_enable [2] = false;
605 cpus[cpu_unit_idx].switches.store_size [2] = store_sz;
606
607 cpus[cpu_unit_idx].switches.assignment [3] = 0;
608 cpus[cpu_unit_idx].switches.interlace [3] = false;
609 cpus[cpu_unit_idx].switches.enable [3] = false;
610 cpus[cpu_unit_idx].switches.init_enable [3] = false;
611 cpus[cpu_unit_idx].switches.store_size [3] = store_sz;
612
613 if (cpus[cpu_unit_idx].tweaks.l68_mode) {
614 cpus[cpu_unit_idx].switches.assignment [4] = 0;
615 cpus[cpu_unit_idx].switches.interlace [4] = false;
616 cpus[cpu_unit_idx].switches.enable [4] = false;
617 cpus[cpu_unit_idx].switches.init_enable [4] = false;
618 cpus[cpu_unit_idx].switches.store_size [4] = 3;
619
620 cpus[cpu_unit_idx].switches.assignment [5] = 0;
621 cpus[cpu_unit_idx].switches.interlace [5] = false;
622 cpus[cpu_unit_idx].switches.enable [5] = false;
623 cpus[cpu_unit_idx].switches.init_enable [5] = false;
624 cpus[cpu_unit_idx].switches.store_size [5] = 3;
625
626 cpus[cpu_unit_idx].switches.assignment [6] = 0;
627 cpus[cpu_unit_idx].switches.interlace [6] = false;
628 cpus[cpu_unit_idx].switches.enable [6] = false;
629 cpus[cpu_unit_idx].switches.init_enable [6] = false;
630 cpus[cpu_unit_idx].switches.store_size [6] = 3;
631
632 cpus[cpu_unit_idx].switches.assignment [7] = 0;
633 cpus[cpu_unit_idx].switches.interlace [7] = false;
634 cpus[cpu_unit_idx].switches.enable [7] = false;
635 cpus[cpu_unit_idx].switches.init_enable [7] = false;
636 cpus[cpu_unit_idx].switches.store_size [7] = 3;
637 }
638 cpu_reset_unit_idx ((uint) cpu_unit_idx, false);
639 simh_cpu_reset_and_clear_unit (cpu_unit + cpu_unit_idx, 0, NULL, NULL);
640 cpus[cpu_unit_idx].switches.enable [1] = true;
641 }
642 else
643 {
644 cpus[cpu_unit_idx].switches = cpus[cpu_unit_idx].isolts_switches_save;
645 cpus[cpu_unit_idx].isolts_switches_saved = false;
646
647 cpu_reset_unit_idx ((uint) cpu_unit_idx, false);
648 simh_cpu_reset_and_clear_unit (cpu_unit + cpu_unit_idx, 0, NULL, NULL);
649 }
650 }
651 else if (strcmp (p, "nodis") == 0)
652 cpus[cpu_unit_idx].tweaks.nodis = v;
653 else if (strcmp (p, "l68_mode") == 0)
654 cpus[cpu_unit_idx].tweaks.l68_mode= v;
655 else
656 {
657 sim_warn ("error: cpu_set_config: Invalid cfg_parse rc <%ld>\n",
658 (long) rc);
659 cfg_parse_done (& cfg_state);
660 return SCPE_ARG;
661 }
662 }
663 cfg_parse_done (& cfg_state);
664
665 return SCPE_OK;
666 }
667
668 static t_stat cpu_show_nunits (UNUSED FILE * st, UNUSED UNIT * uptr,
669 UNUSED int val, UNUSED const void * desc)
670 {
671 sim_msg ("Number of CPUs in system is %d\n", cpu_dev.numunits);
672 return SCPE_OK;
673 }
674
675 static t_stat cpu_set_nunits (UNUSED UNIT * uptr, UNUSED int32 value,
676 const char * cptr, UNUSED void * desc)
677 {
678 if (! cptr)
679 return SCPE_ARG;
680 int n = atoi (cptr);
681 if (n < 1 || n > N_CPU_UNITS_MAX)
682 return SCPE_ARG;
683 cpu_dev.numunits = (uint32) n;
684 return SCPE_OK;
685 }
686
687 static t_stat cpu_show_kips (UNUSED FILE * st, UNUSED UNIT * uptr,
688 UNUSED int val, UNUSED const void * desc)
689 {
690 sim_msg ("CPU KIPS %u\n", kips);
691 return SCPE_OK;
692 }
693
694 static t_stat cpu_set_kips (UNUSED UNIT * uptr, UNUSED int32 value,
695 const char * cptr, UNUSED void * desc)
696 {
697 if (! cptr)
698 return SCPE_ARG;
699 int n = atoi (cptr);
700 if (n < 1 || n > 1000000)
701 return SCPE_ARG;
702 kips = (uint) n;
703 luf_limits[0] = 2000*kips/1000;
704 luf_limits[1] = 4000*kips/1000;
705 luf_limits[2] = 8000*kips/1000;
706 luf_limits[3] = 16000*kips/1000;
707 luf_limits[4] = 32000*kips/1000;
708 return SCPE_OK;
709 }
710
711 static t_stat cpu_show_stall (UNUSED FILE * st, UNUSED UNIT * uptr,
712 UNUSED int val, UNUSED const void * desc)
713 {
714 if (! stall_point_active)
715 {
716 sim_printf ("No stall points\n");
717 return SCPE_OK;
718 }
719
720 sim_printf ("Stall points\n");
721 for (int i = 0; i < N_STALL_POINTS; i ++)
722 if (stall_points[i].segno || stall_points[i].offset)
723 {
724 sim_printf ("%2ld %05o:%06o %6lu\n", (long)i, stall_points[i].segno,
725 stall_points[i].offset, (unsigned long)stall_points[i].time);
726 }
727 return SCPE_OK;
728 }
729
730
731
732
733
734
735
736 static t_stat cpu_set_stall (UNUSED UNIT * uptr, UNUSED int32 value,
737 const char * cptr, UNUSED void * desc)
738 {
739 if (! cptr)
740 return SCPE_ARG;
741
742 long n, s, o, t;
743
744 char * end;
745 n = strtol (cptr, & end, 0);
746 if (* end != '=')
747 return SCPE_ARG;
748 if (n < 0 || n >= N_STALL_POINTS)
749 return SCPE_ARG;
750
751 s = strtol (end + 1, & end, 8);
752 if (* end != ':')
753 return SCPE_ARG;
754 if (s < 0 || s > MASK15)
755 return SCPE_ARG;
756
757 o = strtol (end + 1, & end, 8);
758 if (* end != '=')
759 return SCPE_ARG;
760 if (o < 0 || o > MASK18)
761 return SCPE_ARG;
762
763 t = strtol (end + 1, & end, 0);
764 if (* end != 0)
765 return SCPE_ARG;
766 if (t < 0 || t >= 1000000)
767 return SCPE_ARG;
768
769 stall_points[n].segno = (word15) s;
770 stall_points[n].offset = (word18) o;
771 stall_points[n].time = (unsigned int) t;
772 stall_point_active = false;
773
774 for (int i = 0; i < N_STALL_POINTS; i ++)
775 if (stall_points[n].segno && stall_points[n].offset)
776 stall_point_active = true;
777
778 return SCPE_OK;
779 }
780
781 static t_stat setCPUConfigL68 (UNIT * uptr, UNUSED int32 value, UNUSED const char * cptr, UNUSED void * desc) {
782 long cpuUnitIdx = UNIT_IDX (uptr);
783 if (cpuUnitIdx < 0 || cpuUnitIdx >= N_CPU_UNITS_MAX)
784 return SCPE_ARG;
785 cpu_state_t * cpun = cpus + cpuUnitIdx;
786
787 cpun->tweaks.l68_mode = 1;
788 cpun->options.hex_mode_installed = 0;
789 for (uint port_num = 0; port_num < N_DPS8M_CPU_PORTS; port_num ++) {
790 cpun->switches.assignment[port_num] = port_num;
791 cpun->switches.interlace[port_num] = 0;
792 cpun->switches.store_size[port_num] = 2;
793 cpun->switches.enable[port_num] = 1;
794 cpun->switches.init_enable[port_num] = 1;
795 }
796 for (uint port_num = N_DPS8M_CPU_PORTS; port_num < N_L68_CPU_PORTS; port_num ++) {
797 cpun->switches.assignment[port_num] = 0;
798 cpun->switches.interlace[port_num] = 0;
799 cpun->switches.store_size[port_num] = 0;
800 cpun->switches.enable[port_num] = 0;
801 cpun->switches.init_enable[port_num] = 0;
802 }
803 return SCPE_OK;
804 }
805
806 static t_stat setCPUConfigDPS8M (UNIT * uptr, UNUSED int32 value, UNUSED const char * cptr, UNUSED void * desc) {
807 long cpuUnitIdx = UNIT_IDX (uptr);
808 if (cpuUnitIdx < 0 || cpuUnitIdx >= N_CPU_UNITS_MAX)
809 return SCPE_ARG;
810 cpu_state_t * cpun = cpus + cpuUnitIdx;
811
812 cpun->tweaks.l68_mode = 0;
813 cpun->options.hex_mode_installed = 0;
814 for (uint port_num = 0; port_num < N_DPS8M_CPU_PORTS; port_num ++) {
815 cpun->switches.assignment[port_num] = port_num;
816 cpun->switches.interlace[port_num] = 0;
817 cpun->switches.store_size[port_num] = 7;
818 cpun->switches.enable[port_num] = 1;
819 cpun->switches.init_enable[port_num] = 1;
820 }
821 for (uint port_num = N_DPS8M_CPU_PORTS; port_num < N_L68_CPU_PORTS; port_num ++) {
822 cpun->switches.assignment[port_num] = 0;
823 cpun->switches.interlace[port_num] = 0;
824 cpun->switches.store_size[port_num] = 0;
825 cpun->switches.enable[port_num] = 0;
826 cpun->switches.init_enable[port_num] = 0;
827 }
828 return SCPE_OK;
829 }
830
831 static char * cycle_str (cycles_e cycle)
832 {
833 switch (cycle)
834 {
835
836
837 case FAULT_cycle:
838 return "FAULT_cycle";
839 case EXEC_cycle:
840 return "EXEC_cycle";
841 case FAULT_EXEC_cycle:
842 return "FAULT_EXEC_cycle";
843 case INTERRUPT_cycle:
844 return "INTERRUPT_cycle";
845 case INTERRUPT_EXEC_cycle:
846 return "INTERRUPT_EXEC_cycle";
847 case FETCH_cycle:
848 return "FETCH_cycle";
849 case PSEUDO_FETCH_cycle:
850 return "PSEUDO_FETCH_cycle";
851 case SYNC_FAULT_RTN_cycle:
852 return "SYNC_FAULT_RTN_cycle";
853 default:
854 return "unknown cycle";
855 }
856 }
857
858 static void set_cpu_cycle (cycles_e cycle)
859 {
860 sim_debug (DBG_CYCLE, & cpu_dev, "Setting cycle to %s\n",
861 cycle_str (cycle));
862 cpu.cycle = cycle;
863 }
864
865
866
867 #define MEM_UNINITIALIZED (1LLU<<62)
868
869 uint set_cpu_idx (UNUSED uint cpu_idx)
870 {
871 uint prev = current_running_cpu_idx;
872 #if defined(THREADZ) || defined(LOCKLESS)
873 current_running_cpu_idx = cpu_idx;
874 #endif
875 #ifdef ROUND_ROBIN
876 current_running_cpu_idx = cpu_idx;
877 #endif
878 cpup = & cpus [current_running_cpu_idx];
879 return prev;
880 }
881
882 void cpu_reset_unit_idx (UNUSED uint cpun, bool clear_mem)
883 {
884 uint save = set_cpu_idx (cpun);
885 if (clear_mem)
886 {
887 for (uint i = 0; i < MEMSIZE; i ++)
888 {
889
890 #ifdef LOCKLESS
891 M[i] = (M[i] & ~(MASK36 | MEM_LOCKED)) | MEM_UNINITIALIZED;
892 #else
893 M[i] = (M[i] & ~(MASK36)) | MEM_UNINITIALIZED;
894 #endif
895 }
896 }
897 cpu.rA = 0;
898 cpu.rQ = 0;
899
900 cpu.PPR.IC = 0;
901 cpu.PPR.PRR = 0;
902 cpu.PPR.PSR = 0;
903 cpu.PPR.P = 1;
904 cpu.RSDWH_R1 = 0;
905 cpu.rTR = MASK27;
906
907
908
909 if (cpu.tweaks.isolts_mode)
910 {
911 cpu.shadowTR = 0;
912 cpu.rTRlsb = 0;
913 }
914 cpu.rTRticks = 0;
915
916 set_addr_mode (ABSOLUTE_mode);
917 SET_I_NBAR;
918
919 cpu.CMR.luf = 3;
920 cpu.cu.SD_ON = cpu.switches.sdwam_enable ? 1 : 0;
921 cpu.cu.PT_ON = cpu.switches.ptwam_enable ? 1 : 0;
922
923 if (cpu.tweaks.nodis) {
924 set_cpu_cycle (FETCH_cycle);
925 } else {
926 set_cpu_cycle (EXEC_cycle);
927 cpu.cu.IWB = 0000000616000;
928 }
929 #ifdef PERF_STRIP
930 set_cpu_cycle (FETCH_cycle);
931 #endif
932 cpu.wasXfer = false;
933 cpu.wasInhibited = false;
934
935 cpu.interrupt_flag = false;
936 cpu.g7_flag = false;
937
938 cpu.faultRegister [0] = 0;
939 cpu.faultRegister [1] = 0;
940
941 #ifdef RAPRx
942 cpu.apu.lastCycle = UNKNOWN_CYCLE;
943 #endif
944
945 memset (& cpu.PPR, 0, sizeof (struct ppr_s));
946
947 setup_scbank_map ();
948
949 tidy_cu ();
950 set_cpu_idx (save);
951 }
952
953 static t_stat simh_cpu_reset_and_clear_unit (UNIT * uptr,
954 UNUSED int32 value,
955 UNUSED const char * cptr,
956 UNUSED void * desc)
957 {
958 long cpu_unit_idx = UNIT_IDX (uptr);
959 cpu_state_t * cpun = cpus + cpu_unit_idx;
960 if (cpun->tweaks.isolts_mode)
961 {
962
963 if (cpun->tweaks.useMap)
964 {
965 for (uint pgnum = 0; pgnum < N_SCBANKS; pgnum ++)
966 {
967 int base = cpun->sc_addr_map [pgnum];
968 if (base < 0)
969 continue;
970 for (uint addr = 0; addr < SCBANK_SZ; addr ++)
971 M [addr + (uint) base] = MEM_UNINITIALIZED;
972 }
973 }
974 }
975
976 cpu_reset_unit_idx ((uint) cpu_unit_idx, false);
977 return SCPE_OK;
978 }
979
980 static t_stat simh_cpu_reset_unit (UNIT * uptr,
981 UNUSED int32 value,
982 UNUSED const char * cptr,
983 UNUSED void * desc)
984 {
985 long cpu_unit_idx = UNIT_IDX (uptr);
986 cpu_reset_unit_idx ((uint) cpu_unit_idx, false);
987 return SCPE_OK;
988 }
989
990 #ifndef PERF_STRIP
991 static uv_loop_t * ev_poll_loop;
992 static uv_timer_t ev_poll_handle;
993 #endif
994
995 static MTAB cpu_mod[] =
996 {
997 {
998 MTAB_unit_value,
999 0,
1000 "CONFIG",
1001 "CONFIG",
1002 cpu_set_config,
1003 cpu_show_config,
1004 NULL,
1005 NULL
1006 },
1007
1008
1009
1010
1011 {
1012 MTAB_unit_value,
1013 0,
1014 "RESET",
1015 "RESET",
1016 simh_cpu_reset_unit,
1017 NULL,
1018 NULL,
1019 NULL
1020 },
1021
1022 {
1023 MTAB_unit_value,
1024 0,
1025 "INITIALIZE",
1026 "INITIALIZE",
1027 simh_cpu_reset_unit,
1028 NULL,
1029 NULL,
1030 NULL
1031 },
1032
1033
1034
1035
1036 {
1037 MTAB_unit_value,
1038 0,
1039 "INITIALIZEANDCLEAR",
1040 "INITIALIZEANDCLEAR",
1041 simh_cpu_reset_and_clear_unit,
1042 NULL,
1043 NULL,
1044 NULL
1045 },
1046
1047 {
1048 MTAB_unit_value,
1049 0,
1050 "IAC",
1051 "IAC",
1052 simh_cpu_reset_and_clear_unit,
1053 NULL,
1054 NULL,
1055 NULL
1056 },
1057
1058 {
1059 MTAB_dev_value,
1060 0,
1061 "NUNITS",
1062 "NUNITS",
1063 cpu_set_nunits,
1064 cpu_show_nunits,
1065 NULL,
1066 NULL
1067 },
1068
1069 {
1070 MTAB_dev_value,
1071 0,
1072 "KIPS",
1073 "KIPS",
1074 cpu_set_kips,
1075 cpu_show_kips,
1076 NULL,
1077 NULL
1078 },
1079
1080 {
1081 MTAB_dev_value,
1082 0,
1083 "STALL",
1084 "STALL",
1085 cpu_set_stall,
1086 cpu_show_stall,
1087 NULL,
1088 NULL
1089 },
1090
1091 {
1092 MTAB_unit_value,
1093 0,
1094 "DPS8M",
1095 "DPS8M",
1096 setCPUConfigDPS8M,
1097 NULL,
1098 NULL,
1099 NULL
1100 },
1101
1102 {
1103 MTAB_unit_value,
1104 0,
1105 "L68",
1106 "L68",
1107 setCPUConfigL68,
1108 NULL,
1109 NULL,
1110 NULL
1111 },
1112
1113 { 0, 0, NULL, NULL, NULL, NULL, NULL, NULL }
1114 };
1115
1116 static DEBTAB cpu_dt[] =
1117 {
1118 { "TRACE", DBG_TRACE, NULL },
1119 { "TRACEEXT", DBG_TRACEEXT, NULL },
1120 { "MESSAGES", DBG_MSG, NULL },
1121
1122 { "REGDUMPAQI", DBG_REGDUMPAQI, NULL },
1123 { "REGDUMPIDX", DBG_REGDUMPIDX, NULL },
1124 { "REGDUMPPR", DBG_REGDUMPPR, NULL },
1125 { "REGDUMPPPR", DBG_REGDUMPPPR, NULL },
1126 { "REGDUMPDSBR", DBG_REGDUMPDSBR, NULL },
1127 { "REGDUMPFLT", DBG_REGDUMPFLT, NULL },
1128
1129 { "REGDUMP", DBG_REGDUMP, NULL },
1130
1131 { "ADDRMOD", DBG_ADDRMOD, NULL },
1132 { "APPENDING", DBG_APPENDING, NULL },
1133
1134 { "NOTIFY", DBG_NOTIFY, NULL },
1135 { "INFO", DBG_INFO, NULL },
1136 { "ERR", DBG_ERR, NULL },
1137 { "WARN", DBG_WARN, NULL },
1138 { "DEBUG", DBG_DEBUG, NULL },
1139
1140 { "ALL", DBG_ALL, NULL },
1141
1142 { "FAULT", DBG_FAULT, NULL },
1143 { "INTR", DBG_INTR, NULL },
1144 { "CORE", DBG_CORE, NULL },
1145 { "CYCLE", DBG_CYCLE, NULL },
1146 { "CAC", DBG_CAC, NULL },
1147 { "FINAL", DBG_FINAL, NULL },
1148 { "AVC", DBG_AVC, NULL },
1149 { NULL, 0, NULL }
1150 };
1151
1152
1153 const char *sim_stop_messages[] =
1154 {
1155 "Unknown error",
1156 "Simulation stop",
1157 "Breakpoint",
1158 };
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188 #ifndef SPEED
1189 static bool watch_bits [MEMSIZE];
1190 #endif
1191
1192
1193
1194 char * str_SDW0 (char * buf, sdw0_s * SDW)
1195 {
1196 sprintf (buf, "ADDR=%06o R1=%o R2=%o R3=%o F=%o FC=%o BOUND=%o R=%o "
1197 "E=%o W=%o P=%o U=%o G=%o C=%o EB=%o",
1198 SDW->ADDR, SDW->R1, SDW->R2, SDW->R3, SDW->DF,
1199 SDW->FC, SDW->BOUND, SDW->R, SDW->E, SDW->W,
1200 SDW->P, SDW->U, SDW->G, SDW->C, SDW->EB);
1201 return buf;
1202 }
1203
1204 static t_stat cpu_boot (UNUSED int32 cpu_unit_idx, UNUSED DEVICE * dptr)
1205 {
1206 sim_warn ("Try 'BOOT IOMn'\n");
1207 return SCPE_ARG;
1208 }
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232 #define ZONE_SZ (MEM_SIZE_MAX / 4)
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246 void setup_scbank_map (void)
1247 {
1248
1249 for (uint pg = 0; pg < N_SCBANKS; pg ++)
1250 {
1251 cpu.sc_addr_map [pg] = -1;
1252 cpu.sc_scu_map [pg] = -1;
1253 }
1254 for (uint u = 0; u < N_SCU_UNITS_MAX; u ++)
1255 cpu.sc_num_banks[u] = 0;
1256
1257
1258 for (int port_num = 0; port_num < (cpu.tweaks.l68_mode ? N_L68_CPU_PORTS : N_DPS8M_CPU_PORTS); port_num ++)
1259 {
1260
1261 if (! cpu.switches.enable [port_num])
1262 continue;
1263
1264
1265
1266
1267 if (! cables->cpu_to_scu[current_running_cpu_idx][port_num].in_use)
1268 {
1269 continue;
1270 }
1271
1272
1273 uint store_size = cpu.switches.store_size [port_num];
1274 uint dps8m_store_table [8] =
1275 { 32768, 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304 };
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290 uint l68_store_table [8] =
1291 { 32768, 65536, 4194304, 131072, 524288, 1048576, 2097152, 262144 };
1292 uint l68_isolts_store_table [8] =
1293 { 32768, 65536, 4194304, 65536, 524288, 1048576, 2097152, 262144 };
1294
1295 uint sz_wds =
1296 cpu.tweaks.l68_mode ?
1297 cpu.tweaks.isolts_mode ?
1298 l68_isolts_store_table [store_size] :
1299 l68_store_table [store_size] :
1300 dps8m_store_table [store_size];
1301
1302
1303 uint base_addr_wds = sz_wds * cpu.switches.assignment[port_num];
1304
1305
1306 uint num_banks = sz_wds / SCBANK_SZ;
1307 cpu.sc_num_banks[port_num] = num_banks;
1308 uint base_addr_bks = base_addr_wds / SCBANK_SZ;
1309
1310
1311 for (uint pg = 0; pg < num_banks; pg ++)
1312 {
1313
1314 uint addr_bks = base_addr_bks + pg;
1315
1316 if (addr_bks < N_SCBANKS)
1317 {
1318
1319 if (cpu.sc_addr_map [addr_bks] != -1)
1320 {
1321 sim_warn ("scbank overlap addr_bks %d (%o) old port %d "
1322 "newport %d\n",
1323 addr_bks, addr_bks, cpu.sc_addr_map [addr_bks], port_num);
1324 }
1325 else
1326 {
1327
1328 cpu.sc_addr_map[addr_bks] = (int)((int)port_num * (int)ZONE_SZ + (int)pg * (int)SCBANK_SZ);
1329 cpu.sc_scu_map[addr_bks] = port_num;
1330 }
1331 }
1332 else
1333 {
1334 sim_warn ("addr_bks too big port %d addr_bks %d (%o), "
1335 "limit %d (%o)\n",
1336 port_num, addr_bks, addr_bks, N_SCBANKS, N_SCBANKS);
1337 }
1338 }
1339
1340 }
1341
1342
1343
1344 }
1345
1346 int lookup_cpu_mem_map (word24 addr)
1347 {
1348 uint scpg = addr / SCBANK_SZ;
1349 if (scpg < N_SCBANKS)
1350 {
1351 return cpu.sc_scu_map[scpg];
1352 }
1353 return -1;
1354 }
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364 #ifndef PERF_STRIP
1365 static void get_serial_number (void)
1366 {
1367 bool havesn = false;
1368 FILE * fp = fopen ("./serial.txt", "r");
1369 while (fp && ! feof (fp))
1370 {
1371 char buffer [81] = "";
1372 char * checksn = fgets (buffer, sizeof (buffer), fp);
1373 (void)checksn;
1374 uint cpun, sn;
1375 if (sscanf (buffer, "sn: %u", & cpu.switches.serno) == 1)
1376 {
1377 if (!sim_quiet)
1378 {
1379 sim_msg ("%s CPU serial number: %u\n", sim_name, cpu.switches.serno);
1380 }
1381 havesn = true;
1382 }
1383 else if (sscanf (buffer, "sn%u: %u", & cpun, & sn) == 2)
1384 {
1385 if (cpun < N_CPU_UNITS_MAX)
1386 {
1387 cpus[cpun].switches.serno = sn;
1388 if (!sim_quiet)
1389 {
1390 sim_msg ("%s CPU %u serial number: %u\n",
1391 sim_name, cpun, cpus[cpun].switches.serno);
1392 }
1393 havesn = true;
1394 }
1395 }
1396 }
1397 if (!havesn)
1398 {
1399 if (!sim_quiet)
1400 {
1401 sim_msg ("\r\nPlease register your system at "
1402 "https://ringzero.wikidot.com/wiki:register\n");
1403 sim_msg ("or create the file 'serial.txt' containing the line "
1404 "'sn: 0'.\r\n\r\n");
1405 }
1406 }
1407 if (fp)
1408 fclose (fp);
1409 }
1410 #endif
1411
1412 #ifdef STATS
1413 static void do_stats (void)
1414 {
1415 static struct timespec stats_time;
1416 static bool first = true;
1417 if (first)
1418 {
1419 first = false;
1420 clock_gettime (CLOCK_BOOTTIME, & stats_time);
1421 sim_msg ("stats started\r\n");
1422 }
1423 else
1424 {
1425 struct timespec now, delta;
1426 clock_gettime (CLOCK_BOOTTIME, & now);
1427 timespec_diff (& stats_time, & now, & delta);
1428 stats_time = now;
1429 sim_msg ("stats %6ld.%02ld\r\n", delta.tv_sec,
1430 delta.tv_nsec / 10000000);
1431
1432 sim_msg ("Instruction counts\r\n");
1433 for (uint i = 0; i < 8; i ++)
1434 {
1435 # ifdef WIN_STDIO
1436 sim_msg (" %9lld\r\n", (long long int) cpus[i].instrCnt);
1437 # else
1438 sim_msg (" %'9lld\r\n", (long long int) cpus[i].instrCnt);
1439 # endif
1440 cpus[i].instrCnt = 0;
1441 }
1442 sim_msg ("\r\n");
1443 }
1444 }
1445 #endif
1446
1447
1448
1449 #ifndef PERF_STRIP
1450 static void ev_poll_cb (UNUSED uv_timer_t * handle)
1451 {
1452
1453 static uint oneHz = 0;
1454 if (oneHz ++ >= sys_opts.sys_slow_poll_interval)
1455 {
1456 oneHz = 0;
1457 rdrProcessEvent ();
1458 # ifdef STATS
1459 do_stats ();
1460 # endif
1461 cpu.instrCntT0 = cpu.instrCntT1;
1462 cpu.instrCntT1 = cpu.instrCnt;
1463 }
1464 fnpProcessEvent ();
1465 # ifdef WITH_SOCKET_DEV
1466 # ifndef __MINGW64__
1467 # ifndef __MINGW32__
1468 # ifndef CROSS_MINGW32
1469 # ifndef CROSS_MINGW64
1470 sk_process_event ();
1471 # endif
1472 # endif
1473 # endif
1474 # endif
1475 # endif
1476 consoleProcess ();
1477 # ifdef IO_ASYNC_PAYLOAD_CHAN
1478 iomProcess ();
1479 # endif
1480 # ifdef WITH_ABSI_DEV
1481 # ifndef __MINGW32__
1482 # ifndef __MINGW64__
1483 # ifndef CROSS_MINGW32
1484 # ifndef CROSS_MINGW64
1485 absi_process_event ();
1486 # endif
1487 # endif
1488 # endif
1489 # endif
1490 # endif
1491 PNL (panel_process_event ());
1492 }
1493 #endif
1494
1495
1496
1497 void cpu_init (void)
1498 {
1499
1500
1501
1502
1503 M = system_state->M;
1504 #ifdef M_SHARED
1505 cpus = system_state->cpus;
1506 #endif
1507
1508 #ifndef SPEED
1509 memset (& watch_bits, 0, sizeof (watch_bits));
1510 #endif
1511
1512 set_cpu_idx (0);
1513
1514 memset (cpus, 0, sizeof (cpu_state_t) * N_CPU_UNITS_MAX);
1515 cpus [0].switches.FLT_BASE = 2;
1516
1517 #ifndef PERF_STRIP
1518 get_serial_number ();
1519
1520 ev_poll_loop = uv_default_loop ();
1521 uv_timer_init (ev_poll_loop, & ev_poll_handle);
1522
1523 uv_timer_start (& ev_poll_handle, ev_poll_cb, sys_opts.sys_poll_interval, sys_opts.sys_poll_interval);
1524 #endif
1525
1526
1527 cpu.instrCnt = 0;
1528 cpu.cycleCnt = 0;
1529 for (int i = 0; i < N_FAULTS; i ++)
1530 cpu.faultCnt [i] = 0;
1531
1532 #ifdef MATRIX
1533 initializeTheMatrix ();
1534 #endif
1535 }
1536
1537 static void cpu_reset (void)
1538 {
1539 for (uint i = 0; i < N_CPU_UNITS_MAX; i ++)
1540 {
1541 cpu_reset_unit_idx (i, true);
1542 }
1543
1544 set_cpu_idx (0);
1545
1546 sim_debug (DBG_INFO, & cpu_dev, "CPU reset: Running\n");
1547
1548 }
1549
1550 static t_stat sim_cpu_reset (UNUSED DEVICE *dptr)
1551 {
1552
1553
1554
1555
1556
1557 cpu_reset ();
1558 return SCPE_OK;
1559 }
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569 static t_stat cpu_ex (t_value *vptr, t_addr addr, UNUSED UNIT * uptr,
1570 UNUSED int32 sw)
1571 {
1572 if (addr>= MEMSIZE)
1573 return SCPE_NXM;
1574 if (vptr != NULL)
1575 {
1576 *vptr = M[addr] & DMASK;
1577 }
1578 return SCPE_OK;
1579 }
1580
1581
1582
1583 static t_stat cpu_dep (t_value val, t_addr addr, UNUSED UNIT * uptr,
1584 UNUSED int32 sw)
1585 {
1586 if (addr >= MEMSIZE) return SCPE_NXM;
1587 M[addr] = val & DMASK;
1588 return SCPE_OK;
1589 }
1590
1591
1592
1593
1594
1595 #ifdef M_SHARED
1596
1597 static word18 dummy_IC;
1598 #endif
1599
1600 static REG cpu_reg[] =
1601 {
1602
1603 #ifdef M_SHARED
1604 { ORDATA (IC, dummy_IC, VASIZE), 0, 0, 0 },
1605 #else
1606 { ORDATA (IC, cpus[0].PPR.IC, VASIZE), 0, 0, 0 },
1607 #endif
1608 { NULL, NULL, 0, 0, 0, 0, NULL, NULL, 0, 0, 0 }
1609 };
1610
1611
1612
1613
1614
1615 REG *sim_PC = & cpu_reg[0];
1616
1617
1618
1619 DEVICE cpu_dev =
1620 {
1621 "CPU",
1622 cpu_unit,
1623 cpu_reg,
1624 cpu_mod,
1625 N_CPU_UNITS,
1626 8,
1627 PASIZE,
1628 1,
1629 8,
1630 36,
1631 & cpu_ex,
1632 & cpu_dep,
1633 & sim_cpu_reset,
1634 & cpu_boot,
1635 NULL,
1636 NULL,
1637 NULL,
1638 DEV_DEBUG,
1639 0,
1640 cpu_dt,
1641 NULL,
1642 NULL,
1643 NULL,
1644 NULL,
1645 NULL,
1646 NULL,
1647 NULL
1648 };
1649
1650 void printPtid(pthread_t pt)
1651 {
1652 unsigned char *ptc = (unsigned char*)(void*)(&pt);
1653 sim_msg ("\r Thread ID: 0x");
1654 for (size_t i=0; i < sizeof( pt ); i++)
1655 {
1656 sim_msg ("%02x", (unsigned)(ptc[i]));
1657 }
1658 sim_msg ("\r\n");
1659 #ifdef __APPLE__
1660 sim_msg ("\r Mach TID: 0x%x\r\n",
1661 pthread_mach_thread_np( pt ));
1662 #endif
1663 }
1664
1665 #ifdef M_SHARED
1666 cpu_state_t * cpus = NULL;
1667 #else
1668 cpu_state_t cpus [N_CPU_UNITS_MAX];
1669 #endif
1670 #if defined(THREADZ) || defined(LOCKLESS)
1671 __thread cpu_state_t * restrict cpup;
1672 #else
1673 cpu_state_t * restrict cpup;
1674 #endif
1675 #ifdef ROUND_ROBIN
1676 uint current_running_cpu_idx;
1677 #endif
1678
1679
1680
1681
1682
1683
1684
1685 static uint get_highest_intr (void)
1686 {
1687 uint fp = 1;
1688 for (uint scu_unit_idx = 0; scu_unit_idx < N_SCU_UNITS_MAX; scu_unit_idx ++)
1689 {
1690 if (cpu.events.XIP [scu_unit_idx])
1691 {
1692 fp = scu_get_highest_intr (scu_unit_idx);
1693 if (fp != 1)
1694 break;
1695 }
1696 }
1697 return fp;
1698 }
1699
1700 bool sample_interrupts (void)
1701 {
1702 cpu.lufCounter = 0;
1703 for (uint scu_unit_idx = 0; scu_unit_idx < N_SCU_UNITS_MAX; scu_unit_idx ++)
1704 {
1705 if (cpu.events.XIP [scu_unit_idx])
1706 {
1707 return true;
1708 }
1709 }
1710 return false;
1711 }
1712
1713 t_stat simh_hooks (void)
1714 {
1715 int reason = 0;
1716
1717 if (breakEnable && stop_cpu)
1718 return STOP_STOP;
1719
1720 if (cpu.tweaks.isolts_mode == 0)
1721 {
1722
1723 if (sim_interval <= 0)
1724 {
1725 reason = sim_process_event ();
1726 if ((! breakEnable) && reason == SCPE_STOP)
1727 reason = SCPE_OK;
1728 if (reason)
1729 return reason;
1730 }
1731 }
1732
1733 sim_interval --;
1734
1735 #if !defined(THREADZ) && !defined(LOCKLESS)
1736
1737
1738
1739 if (sim_brk_summ &&
1740 sim_brk_test ((cpu.PPR.IC & 0777777) |
1741 ((((t_addr) cpu.PPR.PSR) & 037777) << 18),
1742 SWMASK ('E')))
1743 return STOP_BKPT;
1744 # ifndef SPEED
1745 if (sim_deb_break && cpu.cycleCnt >= sim_deb_break)
1746 return STOP_BKPT;
1747 # endif
1748 #endif
1749
1750 return reason;
1751 }
1752
1753 #ifdef PANEL68
1754 static void panel_process_event (void)
1755 {
1756
1757 if (cpu.panelInitialize && cpu.DATA_panel_s_trig_sw == 0)
1758 {
1759
1760 while (cpu.panelInitialize)
1761 ;
1762 if (cpu.DATA_panel_init_sw)
1763 cpu_reset_unit_idx (ASSUME0, true);
1764 else
1765 cpu_reset_unit_idx (ASSUME0, false);
1766
1767 do_boot ();
1768 }
1769
1770 if (cpu.DATA_panel_s_trig_sw == 0 &&
1771 cpu.DATA_panel_execute_sw &&
1772 cpu.DATA_panel_scope_sw &&
1773 cpu.DATA_panel_exec_sw == 0)
1774
1775 {
1776
1777 while (cpu.DATA_panel_execute_sw)
1778 ;
1779
1780 if (cpu.DATA_panel_exec_sw)
1781 {
1782 cpu_reset_unit_idx (ASSUME0, false);
1783 cpu.cu.IWB = cpu.switches.data_switches;
1784 set_cpu_cycle (EXEC_cycle);
1785 }
1786 else
1787 {
1788 setG7fault (current_running_cpu_idx, FAULT_EXF, fst_zero);
1789 }
1790 }
1791 }
1792 #endif
1793
1794 #if defined(THREADZ) || defined(LOCKLESS)
1795 bool bce_dis_called = false;
1796
1797
1798 t_stat sim_instr (void)
1799 {
1800 t_stat reason = 0;
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846 if (cpuThreadz[0].run == false)
1847 createCPUThread (0);
1848 do
1849 {
1850
1851 reason = simh_hooks ();
1852 if (reason)
1853 {
1854 break;
1855 }
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883 if (bce_dis_called)
1884 return STOP_STOP;
1885
1886 # ifndef PERF_STRIP
1887
1888
1889 # ifdef LOCKLESS
1890 lock_iom();
1891 # endif
1892 lock_libuv ();
1893 uv_run (ev_poll_loop, UV_RUN_NOWAIT);
1894 unlock_libuv ();
1895 # ifdef LOCKLESS
1896 unlock_iom();
1897 # endif
1898 PNL (panel_process_event ());
1899
1900 int con_unit_idx = check_attn_key ();
1901 if (con_unit_idx != -1)
1902 console_attn_idx (con_unit_idx);
1903 # endif
1904
1905 # ifdef IO_ASYNC_PAYLOAD_CHAN_THREAD
1906 struct timespec next_time;
1907 clock_gettime (CLOCK_REALTIME, & next_time);
1908 next_time.tv_nsec += 1000l * 1000l;
1909 if (next_time.tv_nsec >= 1000l * 1000l *1000l)
1910 {
1911 next_time.tv_nsec -= 1000l * 1000l *1000l;
1912 next_time.tv_sec += (time_t) 1;
1913 }
1914 struct timespec new_time;
1915 do
1916 {
1917 pthread_mutex_lock (& iom_start_lock);
1918 pthread_cond_timedwait (& iomCond,
1919 & iom_start_lock,
1920 & next_time);
1921 pthread_mutex_unlock (& iom_start_lock);
1922 lock_iom();
1923 lock_libuv ();
1924
1925 iomProcess ();
1926
1927 unlock_libuv ();
1928 unlock_iom ();
1929
1930 clock_gettime (CLOCK_REALTIME, & new_time);
1931 }
1932 while ((next_time.tv_sec == new_time.tv_sec) ? (next_time.tv_nsec > new_time.tv_nsec) : \
1933 (next_time.tv_sec > new_time.tv_sec));
1934 # else
1935 sim_usleep (1000);
1936 # endif
1937 }
1938 while (reason == 0);
1939 # ifdef TESTING
1940 HDBGPrint ();
1941 # endif
1942 return reason;
1943 }
1944 #endif
1945
1946 #if !defined(THREADZ) && !defined(LOCKLESS)
1947 static uint fast_queue_subsample = 0;
1948 #endif
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998 #if defined(THREADZ) || defined(LOCKLESS)
1999 void * cpu_thread_main (void * arg)
2000 {
2001 int myid = * (int *) arg;
2002 set_cpu_idx ((uint) myid);
2003 unsigned char umyid = (unsigned char)toupper('a' + (int)myid);
2004
2005 sim_msg ("\rCPU %c thread created.\r\n", (unsigned int)umyid);
2006 # ifdef TESTING
2007 printPtid(pthread_self());
2008 # endif
2009
2010 sim_os_set_thread_priority (PRIORITY_ABOVE_NORMAL);
2011 setSignals ();
2012 threadz_sim_instr ();
2013 return NULL;
2014 }
2015 #endif
2016
2017 static void do_LUF_fault (void)
2018 {
2019 CPT (cpt1U, 16);
2020 cpu.lufCounter = 0;
2021 cpu.lufOccurred = false;
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040 if (cpu.tweaks.isolts_mode)
2041 cpu.shadowTR = (word27) cpu.TR0 - (1024u << (is_priv_mode () ? 4 : cpu.CMR.luf));
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054 doFault (FAULT_LUF, fst_zero, "instruction cycle lockup");
2055 }
2056
2057 #if !defined(THREADZ) && !defined(LOCKLESS)
2058 # define threadz_sim_instr sim_instr
2059 #endif
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071 static void set_temporary_absolute_mode (void)
2072 {
2073 CPT (cpt1L, 20);
2074 cpu.secret_addressing_mode = true;
2075 cpu.cu.XSF = false;
2076 sim_debug (DBG_TRACEEXT, & cpu_dev, "set_temporary_absolute_mode bit 29 sets XSF to 0\n");
2077
2078 }
2079
2080 static bool clear_temporary_absolute_mode (void)
2081 {
2082 CPT (cpt1L, 21);
2083 cpu.secret_addressing_mode = false;
2084 return cpu.cu.XSF;
2085
2086 }
2087
2088 t_stat threadz_sim_instr (void)
2089 {
2090
2091
2092 t_stat reason = 0;
2093
2094 #if !defined(THREADZ) && !defined(LOCKLESS)
2095 set_cpu_idx (0);
2096 # ifdef M_SHARED
2097
2098
2099
2100
2101 cpus [0].PPR.IC = dummy_IC;
2102 # endif
2103
2104 # ifdef ROUND_ROBIN
2105 cpu.isRunning = true;
2106 set_cpu_idx (cpu_dev.numunits - 1);
2107
2108 setCPU:;
2109 uint current = current_running_cpu_idx;
2110 uint c;
2111 for (c = 0; c < cpu_dev.numunits; c ++)
2112 {
2113 set_cpu_idx (c);
2114 if (cpu.isRunning)
2115 break;
2116 }
2117 if (c == cpu_dev.numunits)
2118 {
2119 sim_msg ("All CPUs stopped\n");
2120 goto leave;
2121 }
2122 set_cpu_idx ((current + 1) % cpu_dev.numunits);
2123 if (! cpu . isRunning)
2124 goto setCPU;
2125 # endif
2126 #endif
2127
2128
2129 int val = setjmp (cpu.jmpMain);
2130
2131 switch (val)
2132 {
2133 case JMP_ENTRY:
2134 case JMP_REENTRY:
2135 reason = 0;
2136 break;
2137 case JMP_SYNC_FAULT_RETURN:
2138 set_cpu_cycle (SYNC_FAULT_RTN_cycle);
2139 break;
2140 case JMP_STOP:
2141 reason = STOP_STOP;
2142 goto leave;
2143 case JMP_REFETCH:
2144
2145
2146
2147
2148
2149
2150
2151 cpu.wasXfer = false;
2152
2153 set_cpu_cycle (FETCH_cycle);
2154 break;
2155 case JMP_RESTART:
2156 set_cpu_cycle (EXEC_cycle);
2157 break;
2158 default:
2159 sim_warn ("longjmp value of %d unhandled\n", val);
2160 goto leave;
2161 }
2162
2163
2164
2165 DCDstruct * ci = & cpu.currentInstruction;
2166
2167 if (cpu.restart)
2168 {
2169 set_cpu_cycle (FAULT_cycle);
2170 }
2171
2172 do
2173 {
2174 reason = 0;
2175
2176 #if !defined(THREADZ) && !defined(LOCKLESS)
2177
2178 reason = simh_hooks ();
2179 if (reason)
2180 {
2181 break;
2182 }
2183
2184
2185
2186
2187
2188
2189
2190
2191 if (fast_queue_subsample ++ > sys_opts.sys_poll_check_rate)
2192 {
2193 fast_queue_subsample = 0;
2194 # ifdef CONSOLE_FIX
2195 # if defined(THREADZ) || defined(LOCKLESS)
2196 lock_libuv ();
2197 # endif
2198 # endif
2199 uv_run (ev_poll_loop, UV_RUN_NOWAIT);
2200 # ifdef CONSOLE_FIX
2201 # if defined(THREADZ) || defined(LOCKLESS)
2202 unlock_libuv ();
2203 # endif
2204 # endif
2205 PNL (panel_process_event ());
2206 }
2207 #endif
2208
2209 cpu.cycleCnt ++;
2210
2211 #ifdef THREADZ
2212
2213 unlock_mem_force ();
2214
2215
2216 cpuRunningWait ();
2217 #endif
2218 #ifdef LOCKLESS
2219 core_unlock_all ();
2220 #endif
2221
2222 #ifdef LOCKLESS
2223 core_unlock_all();
2224 #endif
2225
2226 int con_unit_idx = check_attn_key ();
2227 if (con_unit_idx != -1)
2228 console_attn_idx (con_unit_idx);
2229
2230 #if !defined(THREADZ) && !defined(LOCKLESS)
2231 if (cpu.tweaks.isolts_mode)
2232 {
2233 if (cpu.cycle != FETCH_cycle)
2234 {
2235
2236 cpu.rTRlsb ++;
2237 if (cpu.rTRlsb >= 4)
2238 {
2239 cpu.rTRlsb = 0;
2240 cpu.shadowTR = (cpu.shadowTR - 1) & MASK27;
2241 if (cpu.shadowTR == 0)
2242 {
2243 if (cpu.tweaks.tro_enable)
2244 setG7fault (current_running_cpu_idx, FAULT_TRO, fst_zero);
2245 }
2246 }
2247 }
2248 }
2249 #endif
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263 # define TR_RATE 2
2264
2265
2266
2267 cpu.rTR = (word27) (((word27s) cpu.rTR) - (word27s) (cpu.rTRticks / TR_RATE));
2268 cpu.rTRticks %= TR_RATE;
2269
2270
2271
2272 if (cpu.rTR & ~MASK27)
2273 {
2274 cpu.rTR &= MASK27;
2275 if (cpu.tweaks.tro_enable) {
2276 setG7fault (current_running_cpu_idx, FAULT_TRO, fst_zero);
2277 }
2278 }
2279
2280 sim_debug (DBG_CYCLE, & cpu_dev, "Cycle is %s\n",
2281 cycle_str (cpu.cycle));
2282
2283 switch (cpu.cycle)
2284 {
2285 case INTERRUPT_cycle:
2286 {
2287 CPT (cpt1U, 0);
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299 uint intr_pair_addr = get_highest_intr ();
2300 #ifdef TESTING
2301 HDBGIntr (intr_pair_addr, "");
2302 #endif
2303 cpu.cu.FI_ADDR = (word5) (intr_pair_addr / 2);
2304 cu_safe_store ();
2305
2306
2307
2308 CPT (cpt1U, 1);
2309
2310 set_temporary_absolute_mode ();
2311
2312
2313 cpu.PPR.PRR = 0;
2314 cpu.TPR.TRR = 0;
2315
2316 sim_debug (DBG_INTR, & cpu_dev, "intr_pair_addr %u flag %d\n",
2317 intr_pair_addr, cpu.interrupt_flag);
2318 #ifndef SPEED
2319 if_sim_debug (DBG_INTR, & cpu_dev)
2320 traceInstruction (DBG_INTR);
2321 #endif
2322
2323 if (cpu.interrupt_flag)
2324 {
2325 CPT (cpt1U, 2);
2326
2327
2328
2329
2330
2331
2332 if (intr_pair_addr != 1)
2333 {
2334
2335 CPT (cpt1U, 3);
2336
2337
2338 core_read2 (intr_pair_addr,
2339 & cpu.cu.IWB, & cpu.cu.IRODD, __func__);
2340 #ifdef TESTING
2341 HDBGMRead (intr_pair_addr, cpu.cu.IWB, "intr even");
2342 HDBGMRead (intr_pair_addr + 1, cpu.cu.IRODD, "intr odd");
2343 #endif
2344 cpu.cu.xde = 1;
2345 cpu.cu.xdo = 1;
2346 cpu.isExec = true;
2347 cpu.isXED = true;
2348
2349 CPT (cpt1U, 4);
2350 cpu.interrupt_flag = false;
2351 set_cpu_cycle (INTERRUPT_EXEC_cycle);
2352 break;
2353 }
2354 }
2355
2356
2357
2358 CPT (cpt1U, 5);
2359 cpu.interrupt_flag = false;
2360 clear_temporary_absolute_mode ();
2361
2362 cu_safe_restore ();
2363
2364
2365 cpu.wasXfer = false;
2366
2367
2368 set_cpu_cycle (FETCH_cycle);
2369 }
2370 break;
2371
2372 case FETCH_cycle:
2373 #ifdef PANEL68
2374 memset (cpu.cpt, 0, sizeof (cpu.cpt));
2375 #endif
2376 CPT (cpt1U, 13);
2377
2378 PNL (L68_ (cpu.INS_FETCH = false;))
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415 if (get_bar_mode ())
2416 get_BAR_address (cpu.PPR.IC);
2417
2418
2419
2420
2421 bool tmp_priv_mode = is_priv_mode ();
2422 bool is_dis = cpu.currentInstruction.opcode == 0616 &&
2423 cpu.currentInstruction.opcodeX == 0;
2424 bool noCheckTR = tmp_priv_mode &&
2425 !(is_dis && GET_I (cpu.cu.IWB) == 0);
2426
2427 if (is_dis)
2428 {
2429
2430
2431 cpu.interrupt_flag = sample_interrupts ();
2432 cpu.g7_flag =
2433 noCheckTR ? bG7PendingNoTRO () : bG7Pending ();
2434 }
2435 else if (! (cpu.cu.xde | cpu.cu.xdo |
2436 cpu.cu.rpt | cpu.cu.rd | cpu.cu.rl))
2437 {
2438 if ((!cpu.wasInhibited) &&
2439 (cpu.PPR.IC & 1) == 0 &&
2440 (! cpu.wasXfer))
2441 {
2442 CPT (cpt1U, 14);
2443 cpu.interrupt_flag = sample_interrupts ();
2444 cpu.g7_flag =
2445 noCheckTR ? bG7PendingNoTRO () : bG7Pending ();
2446 }
2447 cpu.wasInhibited = false;
2448 }
2449 else
2450 {
2451
2452
2453
2454
2455
2456 if ((cpu.PPR.IC & 1) == 1)
2457 {
2458 cpu.wasInhibited = true;
2459 }
2460 }
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496 if (cpu.g7_flag)
2497 {
2498 cpu.g7_flag = false;
2499 cpu.interrupt_flag = false;
2500 sim_debug (DBG_CYCLE, & cpu_dev,
2501 "call doG7Fault (%d)\n", !noCheckTR);
2502 doG7Fault (!noCheckTR);
2503 }
2504 if (cpu.interrupt_flag)
2505 {
2506
2507
2508
2509 CPT (cpt1U, 15);
2510 set_cpu_cycle (INTERRUPT_cycle);
2511 break;
2512 }
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522 case PSEUDO_FETCH_cycle:
2523
2524 tmp_priv_mode = is_priv_mode ();
2525 if (! (luf_flag && tmp_priv_mode))
2526 cpu.lufCounter ++;
2527
2528 if (cpu.lufCounter > luf_limits[cpu.CMR.luf])
2529 {
2530 if (tmp_priv_mode)
2531 {
2532
2533 cpu.lufOccurred = true;
2534 }
2535 else
2536 {
2537 do_LUF_fault ();
2538 }
2539 }
2540
2541
2542 if (cpu.lufCounter > luf_limits[4])
2543 {
2544 do_LUF_fault ();
2545 }
2546
2547
2548
2549 if (! tmp_priv_mode && cpu.lufOccurred)
2550 {
2551 do_LUF_fault ();
2552 }
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585 if (cpu.cycle == PSEUDO_FETCH_cycle)
2586 {
2587 cpu.apu.lastCycle = INSTRUCTION_FETCH;
2588 cpu.cu.XSF = 0;
2589 cpu.cu.TSN_VALID [0] = 0;
2590 cpu.TPR.TSR = cpu.PPR.PSR;
2591 cpu.TPR.TRR = cpu.PPR.PRR;
2592 cpu.wasInhibited = false;
2593 }
2594 else
2595 {
2596 CPT (cpt1U, 20);
2597 cpu.isExec = false;
2598 cpu.isXED = false;
2599
2600
2601
2602 cpu.cu.XSF = 0;
2603 sim_debug (DBG_TRACEEXT, & cpu_dev, "fetchCycle bit 29 sets XSF to 0\n");
2604 cpu.cu.TSN_VALID [0] = 0;
2605 cpu.TPR.TSR = cpu.PPR.PSR;
2606 cpu.TPR.TRR = cpu.PPR.PRR;
2607 PNL (cpu.prepare_state = ps_PIA);
2608 PNL (L68_ (cpu.INS_FETCH = true;))
2609 fetchInstruction (cpu.PPR.IC);
2610 }
2611
2612 CPT (cpt1U, 21);
2613 advanceG7Faults ();
2614 set_cpu_cycle (EXEC_cycle);
2615 break;
2616
2617 case EXEC_cycle:
2618 case FAULT_EXEC_cycle:
2619 case INTERRUPT_EXEC_cycle:
2620 {
2621 CPT (cpt1U, 22);
2622
2623 #ifdef LOCKLESS
2624 if (stall_point_active)
2625 {
2626 for (int i = 0; i < N_STALL_POINTS; i ++)
2627 if (stall_points[i].segno && stall_points[i].segno == cpu.PPR.PSR &&
2628 stall_points[i].offset && stall_points[i].offset == cpu.PPR.IC)
2629 {
2630 # ifdef CTRACE
2631 fprintf (stderr, "%10lu %s stall %d\n", seqno (), cpunstr[current_running_cpu_idx], i);
2632 # endif
2633
2634 sim_usleep(stall_points[i].time);
2635 break;
2636 }
2637 }
2638 #endif
2639
2640
2641
2642
2643 if (GET_I (cpu.cu.IWB))
2644 cpu.wasInhibited = true;
2645
2646 t_stat ret = executeInstruction ();
2647 #ifdef TR_WORK_EXEC
2648 cpu.rTRticks ++;
2649 #endif
2650 CPT (cpt1U, 23);
2651
2652 if (cpu.tweaks.l68_mode)
2653 add_l68_CU_history ();
2654 else
2655 add_dps8m_CU_history ();
2656
2657 if (ret > 0)
2658 {
2659 reason = ret;
2660 break;
2661 }
2662
2663 if (ret == CONT_XEC)
2664 {
2665 CPT (cpt1U, 27);
2666 cpu.wasXfer = false;
2667 cpu.isExec = true;
2668 if (cpu.cu.xdo)
2669 cpu.isXED = true;
2670
2671 cpu.cu.XSF = 0;
2672 cpu.cu.TSN_VALID [0] = 0;
2673 cpu.TPR.TSR = cpu.PPR.PSR;
2674 cpu.TPR.TRR = cpu.PPR.PRR;
2675 break;
2676 }
2677
2678 if (ret == CONT_TRA || ret == CONT_RET)
2679 {
2680 CPT (cpt1U, 24);
2681 cpu.cu.xde = cpu.cu.xdo = 0;
2682 cpu.isExec = false;
2683 cpu.isXED = false;
2684
2685 cpu.wasXfer = true;
2686
2687 if (cpu.cycle != EXEC_cycle)
2688 {
2689
2690 clearFaultCycle ();
2691
2692
2693
2694
2695
2696 if (! (cpu.currentInstruction.opcode == 0715 &&
2697 cpu.currentInstruction.opcodeX == 0))
2698 {
2699 CPT (cpt1U, 9);
2700 SET_I_NBAR;
2701 }
2702
2703 if (!clear_temporary_absolute_mode ())
2704 {
2705
2706 sim_debug (DBG_TRACEEXT, & cpu_dev,
2707 "setting ABS mode\n");
2708 CPT (cpt1U, 10);
2709 set_addr_mode (ABSOLUTE_mode);
2710 }
2711 else
2712 {
2713
2714 sim_debug (DBG_TRACEEXT, & cpu_dev,
2715 "not setting ABS mode\n");
2716 }
2717
2718 }
2719
2720
2721 if (TST_I_ABS && cpu.cu.XSF)
2722 {
2723 set_addr_mode (APPEND_mode);
2724 }
2725
2726 if (ret == CONT_TRA)
2727 {
2728
2729 cpu.wasXfer = false;
2730 set_cpu_cycle (PSEUDO_FETCH_cycle);
2731 }
2732 else
2733 set_cpu_cycle (FETCH_cycle);
2734 break;
2735 }
2736
2737 if (ret == CONT_DIS)
2738 {
2739 CPT (cpt1U, 25);
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773 #ifndef ROUND_ROBIN
2774
2775
2776
2777
2778 # if defined(THREADZ) || defined(LOCKLESS)
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788 # ifdef NO_TIMEWAIT
2789
2790 struct timespec req, rem;
2791 uint ms = sys_opts.sys_poll_interval;
2792 long int nsec = (long int) ms * 1000 * 1000;
2793 req.tv_nsec = nsec;
2794 req.tv_sec += req.tv_nsec / 1000000000;
2795 req.tv_nsec %= 1000000000;
2796 int rc = nanosleep (& req, & rem);
2797
2798 if (rc == -1)
2799 {
2800 ms = (uint) (rem.tv_nsec / 1000 + req.tv_sec * 1000);
2801 }
2802 word27 ticks = ms * 512;
2803 if (cpu.rTR <= ticks)
2804 {
2805 if (cpu.tweaks.tro_enable) {
2806 setG7fault (current_running_cpu_idx, FAULT_TRO, fst_zero);
2807 }
2808 cpu.rTR = (cpu.rTR - ticks) & MASK27;
2809 }
2810 else
2811 cpu.rTR = (cpu.rTR - ticks) & MASK27;
2812
2813 if (cpu.rTR == 0)
2814 cpu.rTR = MASK27;
2815 # else
2816
2817
2818 unsigned long left = (unsigned long) ((uint64) (cpu.rTR) * 125u / 64u);
2819 unsigned long nowLeft = left;
2820 lock_scu ();
2821 if (!sample_interrupts ())
2822 {
2823 nowLeft = sleepCPU (left);
2824 }
2825 unlock_scu ();
2826 if (nowLeft)
2827 {
2828
2829
2830 if (nowLeft < left) {
2831 cpu.rTR = (word27) (left * 64 / 125);
2832 }
2833 }
2834 else
2835 {
2836
2837 if (cpu.tweaks.tro_enable)
2838 {
2839 lock_scu ();
2840 setG7fault (current_running_cpu_idx, FAULT_TRO, fst_zero);
2841 unlock_scu ();
2842 }
2843 cpu.rTR = MASK27;
2844 }
2845 # endif
2846 cpu.rTRticks = 0;
2847 break;
2848 # else
2849
2850 sim_usleep (sys_opts.sys_poll_interval * 1000);
2851
2852 # ifdef CONSOLE_FIX
2853 # if defined(THREADZ) || defined(LOCKLESS)
2854 lock_libuv ();
2855 # endif
2856 # endif
2857 uv_run (ev_poll_loop, UV_RUN_NOWAIT);
2858 # ifdef CONSOLE_FIX
2859 # if defined(THREADZ) || defined(LOCKLESS)
2860 unlock_libuv ();
2861 # endif
2862 # endif
2863 fast_queue_subsample = 0;
2864
2865 sim_interval = 0;
2866
2867
2868
2869
2870 cpu.rTRticks = 0;
2871
2872
2873
2874
2875
2876
2877 if (cpu.rTR <= sys_opts.sys_poll_interval * 512)
2878 {
2879 if (cpu.tweaks.tro_enable) {
2880 setG7fault (current_running_cpu_idx, FAULT_TRO,
2881 fst_zero);
2882 }
2883 cpu.rTR = (cpu.rTR - sys_opts.sys_poll_interval * 512) & MASK27;
2884 }
2885 else
2886 cpu.rTR = (cpu.rTR - sys_opts.sys_poll_interval * 512) & MASK27;
2887 if (cpu.rTR == 0)
2888 cpu.rTR = MASK27;
2889 # endif
2890 #endif
2891
2892 break;
2893 }
2894
2895 cpu.wasXfer = false;
2896
2897 if (ret < 0)
2898 {
2899 sim_warn ("executeInstruction returned %d?\n", ret);
2900 break;
2901 }
2902
2903 if ((! cpu.cu.repeat_first) &&
2904 (cpu.cu.rpt ||
2905 (cpu.cu.rd && (cpu.PPR.IC & 1)) ||
2906 cpu.cu.rl))
2907 {
2908 CPT (cpt1U, 26);
2909 if (cpu.cu.rd)
2910 -- cpu.PPR.IC;
2911 cpu.wasXfer = false;
2912 set_cpu_cycle (FETCH_cycle);
2913 break;
2914 }
2915
2916
2917 if (cpu.cycle == FAULT_EXEC_cycle &&
2918 !cpu.cu.xde && cpu.cu.xdo)
2919 {
2920 clear_temporary_absolute_mode ();
2921 cu_safe_restore ();
2922 CPT (cpt1U, 12);
2923 clearFaultCycle ();
2924
2925
2926
2927 cpu.wasXfer = false;
2928 cpu.isExec = false;
2929 cpu.isXED = false;
2930
2931 cpu.PPR.IC += ci->info->ndes;
2932 cpu.PPR.IC ++;
2933
2934 set_cpu_cycle (FETCH_cycle);
2935 break;
2936 }
2937
2938
2939 if (cpu.cycle == INTERRUPT_EXEC_cycle &&
2940 !cpu.cu.xde && cpu.cu.xdo)
2941 {
2942 clear_temporary_absolute_mode ();
2943 cu_safe_restore ();
2944
2945
2946
2947 CPT (cpt1U, 12);
2948 cpu.wasXfer = false;
2949 cpu.isExec = false;
2950 cpu.isXED = false;
2951
2952 set_cpu_cycle (FETCH_cycle);
2953 break;
2954 }
2955
2956
2957 if (cpu.cu.xde && cpu.cu.xdo)
2958 {
2959
2960 cpu.cu.IWB = cpu.cu.IRODD;
2961 cpu.cu.xde = 0;
2962 cpu.isExec = true;
2963 cpu.isXED = true;
2964 cpu.cu.XSF = 0;
2965 cpu.cu.TSN_VALID [0] = 0;
2966 cpu.TPR.TSR = cpu.PPR.PSR;
2967 cpu.TPR.TRR = cpu.PPR.PRR;
2968 break;
2969 }
2970
2971 if (cpu.cu.xde || cpu.cu.xdo)
2972 {
2973 cpu.cu.xde = cpu.cu.xdo = 0;
2974 cpu.isExec = false;
2975 cpu.isXED = false;
2976 CPT (cpt1U, 27);
2977 cpu.wasXfer = false;
2978 cpu.PPR.IC ++;
2979 if (ci->info->ndes > 0)
2980 cpu.PPR.IC += ci->info->ndes;
2981 cpu.wasInhibited = true;
2982 set_cpu_cycle (FETCH_cycle);
2983 break;
2984 }
2985
2986
2987 if (cpu.cycle != EXEC_cycle)
2988 sim_warn ("expected EXEC_cycle (%d)\n", cpu.cycle);
2989
2990 cpu.cu.xde = cpu.cu.xdo = 0;
2991 cpu.isExec = false;
2992 cpu.isXED = false;
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003 if ((cpu.PPR.IC & 1) == 0 &&
3004 ci->info->ndes == 0 &&
3005 !cpu.cu.repeat_first && !cpu.cu.rpt && !cpu.cu.rd && !cpu.cu.rl &&
3006 !(cpu.currentInstruction.opcode == 0616 && cpu.currentInstruction.opcodeX == 0) &&
3007 (cpu.PPR.IC & ~3u) != (cpu.last_write & ~3u))
3008 {
3009 cpu.PPR.IC ++;
3010 cpu.wasXfer = false;
3011 cpu.cu.IWB = cpu.cu.IRODD;
3012 set_cpu_cycle (PSEUDO_FETCH_cycle);
3013 break;
3014 }
3015
3016 cpu.PPR.IC ++;
3017 if (ci->info->ndes > 0)
3018 cpu.PPR.IC += ci->info->ndes;
3019
3020 CPT (cpt1U, 28);
3021 cpu.wasXfer = false;
3022 set_cpu_cycle (FETCH_cycle);
3023 }
3024 break;
3025
3026 case SYNC_FAULT_RTN_cycle:
3027 {
3028 CPT (cpt1U, 29);
3029
3030
3031
3032
3033 cpu.PPR.IC += ci->info->ndes;
3034 cpu.PPR.IC ++;
3035 cpu.wasXfer = false;
3036 set_cpu_cycle (FETCH_cycle);
3037 }
3038 break;
3039
3040 case FAULT_cycle:
3041 {
3042 CPT (cpt1U, 30);
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064 if ((cpu.cu.APUCycleBits & 060) || cpu.secret_addressing_mode)
3065 set_apu_status (apuStatus_FABS);
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077 if (cpu.faultNumber != FAULT_TRB || cpu.cu.xde == 0)
3078 {
3079 cu_safe_store ();
3080 }
3081 else
3082 {
3083 word36 tmpIRODD = cpu.scu_data[7];
3084 cu_safe_store ();
3085 cpu.scu_data[7] = tmpIRODD;
3086 }
3087 CPT (cpt1U, 31);
3088
3089
3090 set_temporary_absolute_mode ();
3091
3092
3093 cpu.PPR.PRR = 0;
3094 cpu.TPR.TRR = 0;
3095
3096
3097 uint fltAddress = (cpu.switches.FLT_BASE << 5) & 07740;
3098 L68_ (
3099 if (cpu.is_FFV)
3100 {
3101 cpu.is_FFV = false;
3102 CPTUR (cptUseMR);
3103
3104 fltAddress = (cpu.MR.FFV & MASK15) << 3;
3105 }
3106 )
3107
3108
3109 word24 addr = fltAddress + 2 * cpu.faultNumber;
3110
3111 if (cpu.restart)
3112 {
3113 cpu.restart = false;
3114 addr = cpu.restart_address;
3115 }
3116
3117 core_read2 (addr, & cpu.cu.IWB, & cpu.cu.IRODD, __func__);
3118 #ifdef TESTING
3119 HDBGMRead (addr, cpu.cu.IWB, "fault even");
3120 HDBGMRead (addr + 1, cpu.cu.IRODD, "fault odd");
3121 #endif
3122 cpu.cu.xde = 1;
3123 cpu.cu.xdo = 1;
3124 cpu.isExec = true;
3125 cpu.isXED = true;
3126
3127 CPT (cpt1U, 33);
3128 set_cpu_cycle (FAULT_EXEC_cycle);
3129
3130 break;
3131 }
3132
3133 }
3134 }
3135 #ifdef ROUND_ROBIN
3136 while (0);
3137 if (reason == 0)
3138 goto setCPU;
3139 #else
3140 while (reason == 0);
3141 #endif
3142
3143 leave:
3144 #ifdef TESTING
3145 HDBGPrint ();
3146 #endif
3147 sim_msg ("\r\n");
3148 #ifdef WIN_STDIO
3149 (void)fflush(stderr);
3150 (void)fflush(stdout);
3151 sim_msg ("cycles %15llu\r\n", (unsigned long long)cpu.cycleCnt);
3152 sim_msg ("instructions %15llu\r\n", (unsigned long long)cpu.instrCnt);
3153 sim_msg ("lockCnt %15llu\r\n", (unsigned long long)cpu.lockCnt);
3154 sim_msg ("lockImmediate %15llu\r\n", (unsigned long long)cpu.lockImmediate);
3155 sim_msg ("lockWait %15llu\r\n", (unsigned long long)cpu.lockWait);
3156 sim_msg ("lockWaitMax %15llu\r\n", (unsigned long long)cpu.lockWaitMax);
3157 # ifndef SCHED_NEVER_YIELD
3158 sim_msg ("lockYield %15llu\r\n", (unsigned long long)cpu.lockYield);
3159 # endif
3160 (void)fflush(stdout);
3161 (void)fflush(stderr);
3162 #else
3163 sim_msg ("cycles %'15llu\r\n", (unsigned long long)cpu.cycleCnt);
3164 sim_msg ("instructions %'15llu\r\n", (unsigned long long)cpu.instrCnt);
3165 sim_msg ("lockCnt %'15llu\r\n", (unsigned long long)cpu.lockCnt);
3166 sim_msg ("lockImmediate %'15llu\r\n", (unsigned long long)cpu.lockImmediate);
3167 sim_msg ("lockWait %'15llu\r\n", (unsigned long long)cpu.lockWait);
3168 sim_msg ("lockWaitMax %'15llu\r\n", (unsigned long long)cpu.lockWaitMax);
3169 # ifndef SCHED_NEVER_YIELD
3170 sim_msg ("lockYield %'15llu\r\n", (unsigned long long)cpu.lockYield);
3171 # endif
3172 #endif
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182 #if defined(THREADZ) || defined(LOCKLESS)
3183 stopCPUThread();
3184 #endif
3185
3186 #ifdef M_SHARED
3187
3188
3189
3190
3191 set_cpu_idx (0);
3192 dummy_IC = cpu.PPR.IC;
3193 #endif
3194
3195 return reason;
3196 }
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212 int operand_size (void)
3213 {
3214 DCDstruct * i = & cpu.currentInstruction;
3215 if (i->info->flags & (READ_OPERAND | STORE_OPERAND))
3216 return 1;
3217 else if (i->info->flags & (READ_YPAIR | STORE_YPAIR))
3218 return 2;
3219 else if (i->info->flags & (READ_YBLOCK8 | STORE_YBLOCK8))
3220 return 8;
3221 else if (i->info->flags & (READ_YBLOCK16 | STORE_YBLOCK16))
3222 return 16;
3223 else if (i->info->flags & (READ_YBLOCK32 | STORE_YBLOCK32))
3224 return 32;
3225 return 0;
3226 }
3227
3228
3229
3230 t_stat read_operand (word18 addr, processor_cycle_type cyctyp)
3231 {
3232 CPT (cpt1L, 6);
3233
3234 #ifdef THREADZ
3235 if (cyctyp == OPERAND_READ)
3236 {
3237 DCDstruct * i = & cpu.currentInstruction;
3238
3239 if (RMWOP (i))
3240
3241
3242
3243
3244
3245
3246
3247 {
3248 lock_rmw ();
3249 }
3250 }
3251 #endif
3252
3253 switch (operand_size ())
3254 {
3255 case 1:
3256 CPT (cpt1L, 7);
3257 Read (addr, & cpu.CY, cyctyp);
3258 return SCPE_OK;
3259 case 2:
3260 CPT (cpt1L, 8);
3261 addr &= 0777776;
3262 Read2 (addr, cpu.Ypair, cyctyp);
3263 break;
3264 case 8:
3265 CPT (cpt1L, 9);
3266 addr &= 0777770;
3267 Read8 (addr, cpu.Yblock8, cpu.currentInstruction.b29);
3268 break;
3269 case 16:
3270 CPT (cpt1L, 10);
3271 addr &= 0777770;
3272 Read16 (addr, cpu.Yblock16);
3273 break;
3274 case 32:
3275 CPT (cpt1L, 11);
3276 addr &= 0777740;
3277 for (uint j = 0 ; j < 32 ; j += 1)
3278 Read (addr + j, cpu.Yblock32 + j, cyctyp);
3279
3280 break;
3281 }
3282
3283
3284 return SCPE_OK;
3285
3286 }
3287
3288
3289
3290 t_stat write_operand (word18 addr, UNUSED processor_cycle_type cyctyp)
3291 {
3292 switch (operand_size ())
3293 {
3294 case 1:
3295 CPT (cpt1L, 12);
3296 Write (addr, cpu.CY, OPERAND_STORE);
3297 break;
3298 case 2:
3299 CPT (cpt1L, 13);
3300 addr &= 0777776;
3301 Write2 (addr + 0, cpu.Ypair, OPERAND_STORE);
3302 break;
3303 case 8:
3304 CPT (cpt1L, 14);
3305 addr &= 0777770;
3306 Write8 (addr, cpu.Yblock8, cpu.currentInstruction.b29);
3307 break;
3308 case 16:
3309 CPT (cpt1L, 15);
3310 addr &= 0777770;
3311 Write16 (addr, cpu.Yblock16);
3312 break;
3313 case 32:
3314 CPT (cpt1L, 16);
3315 addr &= 0777740;
3316
3317
3318 Write32 (addr, cpu.Yblock32);
3319 break;
3320 }
3321
3322 #ifdef THREADZ
3323 if (cyctyp == OPERAND_STORE)
3324 {
3325 DCDstruct * i = & cpu.currentInstruction;
3326 if (RMWOP (i))
3327 unlock_mem ();
3328 }
3329 #endif
3330 return SCPE_OK;
3331
3332 }
3333
3334 #ifndef SPEED
3335 t_stat set_mem_watch (int32 arg, const char * buf)
3336 {
3337 if (strlen (buf) == 0)
3338 {
3339 if (arg)
3340 {
3341 sim_warn ("no argument to watch?\n");
3342 return SCPE_ARG;
3343 }
3344 sim_msg ("Clearing all watch points\n");
3345 memset (& watch_bits, 0, sizeof (watch_bits));
3346 return SCPE_OK;
3347 }
3348 char * end;
3349 long int n = strtol (buf, & end, 0);
3350 if (* end || n < 0 || n >= MEMSIZE)
3351 {
3352 sim_warn ("Invalid argument to watch? %ld\n", (long) n);
3353 return SCPE_ARG;
3354 }
3355 watch_bits [n] = arg != 0;
3356 return SCPE_OK;
3357 }
3358 #endif
3359
3360
3361
3362
3363
3364 #ifndef SPEED
3365 static void nem_check (word24 addr, const char * context)
3366 {
3367 if (lookup_cpu_mem_map (addr) < 0)
3368 {
3369 doFault (FAULT_STR, fst_str_nea, context);
3370 }
3371 }
3372 #endif
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385 #if !defined(SPEED) || !defined(INLINE_CORE)
3386 int core_read (word24 addr, word36 *data, const char * ctx)
3387 {
3388 PNL (cpu.portBusy = true;)
3389 SC_MAP_ADDR (addr, addr);
3390 # ifndef LOCKLESS
3391 if (M[addr] & MEM_UNINITIALIZED)
3392 {
3393 sim_debug (DBG_WARN, & cpu_dev,
3394 "Uninitialized memory accessed at address %08o; "
3395 "IC is 0%06o:0%06o (%s(\n",
3396 addr, cpu.PPR.PSR, cpu.PPR.IC, ctx);
3397 }
3398 # endif
3399 # ifndef SPEED
3400 if (watch_bits [addr])
3401 {
3402 sim_msg ("WATCH [%llu] %05o:%06o read %08o %012llo (%s)\n",
3403 (long long unsigned int)cpu.cycleCnt, cpu.PPR.PSR, cpu.PPR.IC, addr,
3404 (long long unsigned int)M [addr], ctx);
3405 traceInstruction (0);
3406 }
3407 # endif
3408 # ifdef LOCKLESS
3409 # ifndef SUNLINT
3410 word36 v;
3411 LOAD_ACQ_CORE_WORD(v, addr);
3412 *data = v & DMASK;
3413 # endif
3414 # else
3415 *data = M[addr] & DMASK;
3416 # endif
3417
3418 # ifdef TR_WORK_MEM
3419 cpu.rTRticks ++;
3420 # endif
3421 sim_debug (DBG_CORE, & cpu_dev,
3422 "core_read %08o %012"PRIo64" (%s)\n",
3423 addr, * data, ctx);
3424 PNL (trackport (addr, * data));
3425 return 0;
3426 }
3427 #endif
3428
3429 #ifdef LOCKLESS
3430 int core_read_lock (word24 addr, word36 *data, UNUSED const char * ctx)
3431 {
3432 SC_MAP_ADDR (addr, addr);
3433 LOCK_CORE_WORD(addr);
3434 if (cpu.locked_addr != 0) {
3435 sim_warn ("core_read_lock: locked %08o locked_addr %08o %c %05o:%06o\n",
3436 addr, cpu.locked_addr, current_running_cpu_idx + 'A',
3437 cpu.PPR.PSR, cpu.PPR.IC);
3438 core_unlock_all ();
3439 }
3440 cpu.locked_addr = addr;
3441 # ifndef SUNLINT
3442 word36 v;
3443 LOAD_ACQ_CORE_WORD(v, addr);
3444 * data = v & DMASK;
3445 # endif
3446 return 0;
3447 }
3448 #endif
3449
3450 #if !defined(SPEED) || !defined(INLINE_CORE)
3451 int core_write (word24 addr, word36 data, const char * ctx)
3452 {
3453 PNL (cpu.portBusy = true;)
3454 SC_MAP_ADDR (addr, addr);
3455 if (cpu.tweaks.isolts_mode)
3456 {
3457 if (cpu.MR.sdpap)
3458 {
3459 sim_warn ("failing to implement sdpap\n");
3460 cpu.MR.sdpap = 0;
3461 }
3462 if (cpu.MR.separ)
3463 {
3464 sim_warn ("failing to implement separ\n");
3465 cpu.MR.separ = 0;
3466 }
3467 }
3468 # ifdef LOCKLESS
3469 LOCK_CORE_WORD(addr);
3470 # ifndef SUNLINT
3471 STORE_REL_CORE_WORD(addr, data);
3472 # endif
3473 # else
3474 M[addr] = data & DMASK;
3475 # endif
3476 # ifndef SPEED
3477 if (watch_bits [addr])
3478 {
3479 sim_msg ("WATCH [%llu] %05o:%06o write %08llo %012llo (%s)\n",
3480 (long long unsigned int)cpu.cycleCnt, cpu.PPR.PSR, cpu.PPR.IC,
3481 (long long unsigned int)addr, (unsigned long long int)M [addr], ctx);
3482 traceInstruction (0);
3483 }
3484 # endif
3485 # ifdef TR_WORK_MEM
3486 cpu.rTRticks ++;
3487 # endif
3488 sim_debug (DBG_CORE, & cpu_dev,
3489 "core_write %08o %012"PRIo64" (%s)\n",
3490 addr, data, ctx);
3491 PNL (trackport (addr, data));
3492 return 0;
3493 }
3494 #endif
3495
3496 #ifdef LOCKLESS
3497 int core_write_unlock (word24 addr, word36 data, UNUSED const char * ctx)
3498 {
3499 SC_MAP_ADDR (addr, addr);
3500 if (cpu.locked_addr != addr)
3501 {
3502 sim_warn ("core_write_unlock: locked %08o locked_addr %08o %c %05o:%06o\n",
3503 addr, cpu.locked_addr, current_running_cpu_idx + 'A',
3504 cpu.PPR.PSR, cpu.PPR.IC);
3505 core_unlock_all ();
3506 }
3507
3508 # ifndef SUNLINT
3509 STORE_REL_CORE_WORD(addr, data);
3510 # endif
3511 cpu.locked_addr = 0;
3512 return 0;
3513 }
3514
3515 int core_unlock_all (void)
3516 {
3517 if (cpu.locked_addr != 0) {
3518 sim_warn ("core_unlock_all: locked %08o %c %05o:%06o\n",
3519 cpu.locked_addr, current_running_cpu_idx + 'A',
3520 cpu.PPR.PSR, cpu.PPR.IC);
3521 # ifndef SUNLINT
3522 STORE_REL_CORE_WORD(cpu.locked_addr, M[cpu.locked_addr]);
3523 # endif
3524 cpu.locked_addr = 0;
3525 }
3526 return 0;
3527 }
3528 #endif
3529
3530 #if !defined(SPEED) || !defined(INLINE_CORE)
3531 int core_write_zone (word24 addr, word36 data, const char * ctx)
3532 {
3533 PNL (cpu.portBusy = true;)
3534 if (cpu.tweaks.isolts_mode)
3535 {
3536 if (cpu.MR.sdpap)
3537 {
3538 sim_warn ("failing to implement sdpap\n");
3539 cpu.MR.sdpap = 0;
3540 }
3541 if (cpu.MR.separ)
3542 {
3543 sim_warn ("failing to implement separ\n");
3544 cpu.MR.separ = 0;
3545 }
3546 }
3547 word24 mapAddr = 0;
3548 SC_MAP_ADDR (addr, mapAddr);
3549 # ifdef LOCKLESS
3550 word36 v;
3551 core_read_lock(addr, &v, ctx);
3552 v = (v & ~cpu.zone) | (data & cpu.zone);
3553 core_write_unlock(addr, v, ctx);
3554 # else
3555 M[mapAddr] = (M[mapAddr] & ~cpu.zone) | (data & cpu.zone);
3556 # endif
3557 cpu.useZone = false;
3558 # ifndef SPEED
3559 if (watch_bits [mapAddr])
3560 {
3561 sim_msg ("WATCH [%llu] %05o:%06o writez %08llo %012llo (%s)\n",
3562 (unsigned long long int)cpu.cycleCnt, cpu.PPR.PSR, cpu.PPR.IC,
3563 (unsigned long long int)mapAddr, (unsigned long long int)M [mapAddr], ctx);
3564 traceInstruction (0);
3565 }
3566 # endif
3567 # ifdef TR_WORK_MEM
3568 cpu.rTRticks ++;
3569 # endif
3570 sim_debug (DBG_CORE, & cpu_dev,
3571 "core_write_zone %08o %012"PRIo64" (%s)\n",
3572 mapAddr, data, ctx);
3573 PNL (trackport (mapAddr, data));
3574 return 0;
3575 }
3576 #endif
3577
3578 #if !defined(SPEED) || !defined(INLINE_CORE)
3579 int core_read2 (word24 addr, word36 *even, word36 *odd, const char * ctx)
3580 {
3581 PNL (cpu.portBusy = true;)
3582 # if defined(LOCKLESS)
3583
3584 word36 v;
3585 # endif
3586 if (addr & 1)
3587 {
3588 sim_debug (DBG_MSG, & cpu_dev,
3589 "warning: subtracting 1 from pair at %o in "
3590 "core_read2 (%s)\n", addr, ctx);
3591 addr &= (word24)~1;
3592 }
3593 SC_MAP_ADDR (addr, addr);
3594 # ifndef LOCKLESS
3595 if (M[addr] & MEM_UNINITIALIZED)
3596 {
3597 sim_debug (DBG_WARN, & cpu_dev,
3598 "Uninitialized memory accessed at address %08o; "
3599 "IC is 0%06o:0%06o (%s)\n",
3600 addr, cpu.PPR.PSR, cpu.PPR.IC, ctx);
3601 }
3602 # endif
3603 # ifndef SPEED
3604 if (watch_bits [addr])
3605 {
3606 sim_msg ("WATCH [%llu] %05o:%06o read2 %08llo %012llo (%s)\n",
3607 (unsigned long long int)cpu.cycleCnt, cpu.PPR.PSR, cpu.PPR.IC,
3608 (unsigned long long int)addr, (unsigned long long int)M [addr], ctx);
3609 traceInstruction (0);
3610 }
3611 # endif
3612 # ifdef LOCKLESS
3613 # ifndef SUNLINT
3614 LOAD_ACQ_CORE_WORD(v, addr);
3615 if (v & MEM_LOCKED)
3616 sim_warn ("core_read2: even locked %08o locked_addr %08o %c %05o:%06o\n",
3617 addr, cpu.locked_addr, current_running_cpu_idx + 'A',
3618 cpu.PPR.PSR, cpu.PPR.IC);
3619 *even = v & DMASK;
3620 addr++;
3621 # endif
3622 # else
3623 *even = M[addr++] & DMASK;
3624 # endif
3625 sim_debug (DBG_CORE, & cpu_dev,
3626 "core_read2 %08o %012"PRIo64" (%s)\n",
3627 addr - 1, * even, ctx);
3628
3629
3630
3631 # ifndef LOCKLESS
3632 if (M[addr] & MEM_UNINITIALIZED)
3633 {
3634 sim_debug (DBG_WARN, & cpu_dev,
3635 "Uninitialized memory accessed at address %08o; "
3636 "IC is 0%06o:0%06o (%s)\n",
3637 addr, cpu.PPR.PSR, cpu.PPR.IC, ctx);
3638 }
3639 # endif
3640 # ifndef SPEED
3641 if (watch_bits [addr])
3642 {
3643 sim_msg ("WATCH [%llu] %05o:%06o read2 %08llo %012llo (%s)\n",
3644 (unsigned long long int)cpu.cycleCnt, cpu.PPR.PSR, cpu.PPR.IC,
3645 (unsigned long long int)addr, (unsigned long long int)M [addr], ctx);
3646 traceInstruction (0);
3647 }
3648 # endif
3649 # ifdef LOCKLESS
3650 # ifndef SUNLINT
3651 LOAD_ACQ_CORE_WORD(v, addr);
3652 if (v & MEM_LOCKED)
3653 sim_warn ("core_read2: odd locked %08o locked_addr %08o %c %05o:%06o\n",
3654 addr, cpu.locked_addr, current_running_cpu_idx + 'A',
3655 cpu.PPR.PSR, cpu.PPR.IC);
3656 *odd = v & DMASK;
3657 # endif
3658 # else
3659 *odd = M[addr] & DMASK;
3660 # endif
3661 sim_debug (DBG_CORE, & cpu_dev,
3662 "core_read2 %08o %012"PRIo64" (%s)\n",
3663 addr, * odd, ctx);
3664 # ifdef TR_WORK_MEM
3665 cpu.rTRticks ++;
3666 # endif
3667 PNL (trackport (addr - 1, * even));
3668 return 0;
3669 }
3670 #endif
3671
3672 #if !defined(SPEED) || !defined(INLINE_CORE)
3673 int core_write2 (word24 addr, word36 even, word36 odd, const char * ctx) {
3674 PNL (cpu.portBusy = true;)
3675 if (addr & 1) {
3676 sim_debug (DBG_MSG, & cpu_dev,
3677 "warning: subtracting 1 from pair at %o in core_write2 " "(%s)\n",
3678 addr, ctx);
3679 addr &= (word24)~1;
3680 }
3681 SC_MAP_ADDR (addr, addr);
3682 if (cpu.tweaks.isolts_mode) {
3683 if (cpu.MR.sdpap) {
3684 sim_warn ("failing to implement sdpap\n");
3685 cpu.MR.sdpap = 0;
3686 }
3687 if (cpu.MR.separ) {
3688 sim_warn ("failing to implement separ\n");
3689 cpu.MR.separ = 0;
3690 }
3691 }
3692
3693 # ifndef SPEED
3694 if (watch_bits [addr]) {
3695 sim_msg ("WATCH [%llu] %05o:%06o write2 %08llo %012llo (%s)\n",
3696 (unsigned long long int)cpu.cycleCnt, cpu.PPR.PSR, cpu.PPR.IC,
3697 (unsigned long long int)addr, (unsigned long long int)even, ctx);
3698 traceInstruction (0);
3699 }
3700 # endif
3701 # ifdef LOCKLESS
3702 LOCK_CORE_WORD(addr);
3703 # ifndef SUNLINT
3704 STORE_REL_CORE_WORD(addr, even);
3705 # endif
3706 addr++;
3707 # else
3708 M[addr++] = even & DMASK;
3709 # endif
3710 sim_debug (DBG_CORE, & cpu_dev, "core_write2 %08o %012llo (%s)\n", addr - 1,
3711 (long long unsigned int)even, ctx);
3712
3713
3714
3715
3716 # ifndef SPEED
3717 if (watch_bits [addr]) {
3718 sim_msg ("WATCH [%llu] %05o:%06o write2 %08llo %012llo (%s)\n",
3719 (long long unsigned int)cpu.cycleCnt, cpu.PPR.PSR, cpu.PPR.IC,
3720 (long long unsigned int)addr, (long long unsigned int)odd, ctx);
3721 traceInstruction (0);
3722 }
3723 # endif
3724 # ifdef LOCKLESS
3725 LOCK_CORE_WORD(addr);
3726 # ifndef SUNLINT
3727 STORE_REL_CORE_WORD(addr, odd);
3728 # endif
3729 # else
3730 M[addr] = odd & DMASK;
3731 # endif
3732 # ifdef TR_WORK_MEM
3733 cpu.rTRticks ++;
3734 # endif
3735 PNL (trackport (addr - 1, even));
3736 sim_debug (DBG_CORE, & cpu_dev, "core_write2 %08o %012"PRIo64" (%s)\n", addr, odd, ctx);
3737 return 0;
3738 }
3739 #endif
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750 void decode_instruction (word36 inst, DCDstruct * p)
3751 {
3752 CPT (cpt1L, 17);
3753 memset (p, 0, sizeof (DCDstruct));
3754
3755 p->opcode = GET_OP (inst);
3756 p->opcodeX = GET_OPX(inst);
3757 p->opcode10 = p->opcode | (p->opcodeX ? 01000 : 0);
3758 p->address = GET_ADDR (inst);
3759 p->b29 = GET_A (inst);
3760 p->i = GET_I (inst);
3761 p->tag = GET_TAG (inst);
3762
3763 p->info = get_iwb_info (p);
3764
3765 if (p->info->flags & IGN_B29)
3766 p->b29 = 0;
3767
3768 if (p->info->ndes > 0)
3769 {
3770 p->b29 = 0;
3771 p->tag = 0;
3772 if (p->info->ndes > 1)
3773 {
3774 memset (& cpu.currentEISinstruction, 0,
3775 sizeof (cpu.currentEISinstruction));
3776 }
3777 }
3778 }
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799 int is_priv_mode (void)
3800 {
3801
3802
3803
3804
3805 if (get_bar_mode ())
3806 return 0;
3807
3808
3809 if (get_addr_mode () == ABSOLUTE_mode)
3810 return 1;
3811 else if (cpu.PPR.P)
3812 return 1;
3813
3814 return 0;
3815 }
3816
3817
3818
3819
3820
3821
3822
3823
3824 bool get_bar_mode (void)
3825 {
3826 return ! (cpu.secret_addressing_mode || TST_I_NBAR);
3827 }
3828
3829 addr_modes_e get_addr_mode (void)
3830 {
3831 if (cpu.secret_addressing_mode)
3832 return ABSOLUTE_mode;
3833
3834
3835
3836
3837
3838
3839
3840 if (TST_I_ABS)
3841 {
3842 return ABSOLUTE_mode;
3843 }
3844 else
3845 {
3846 return APPEND_mode;
3847 }
3848 }
3849
3850
3851
3852
3853
3854
3855
3856
3857 void set_addr_mode (addr_modes_e mode)
3858 {
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869 cpu.secret_addressing_mode = false;
3870 if (mode == ABSOLUTE_mode)
3871 {
3872 CPT (cpt1L, 22);
3873 sim_debug (DBG_DEBUG, & cpu_dev, "APU: Setting absolute mode.\n");
3874
3875 SET_I_ABS;
3876 cpu.PPR.P = 1;
3877 }
3878 else if (mode == APPEND_mode)
3879 {
3880 CPT (cpt1L, 23);
3881 if (! TST_I_ABS && TST_I_NBAR)
3882 sim_debug (DBG_DEBUG, & cpu_dev, "APU: Keeping append mode.\n");
3883 else
3884 sim_debug (DBG_DEBUG, & cpu_dev, "APU: Setting append mode.\n");
3885
3886 CLR_I_ABS;
3887 }
3888 else
3889 {
3890 sim_debug (DBG_ERR, & cpu_dev,
3891 "APU: Unable to determine address mode.\n");
3892 sim_warn ("APU: Unable to determine address mode. Can't happen!\n");
3893 }
3894 }
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922 word18 get_BAR_address (word18 addr)
3923 {
3924 if (cpu . BAR.BOUND == 0)
3925
3926 doFault (FAULT_STR, fst_str_oob, "BAR store fault; out of bounds");
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937 if (addr >= (((word18) cpu . BAR.BOUND) << 9))
3938
3939 doFault (FAULT_STR, fst_str_oob, "BAR store fault; out of bounds");
3940
3941 word18 barAddr = (addr + (((word18) cpu . BAR.BASE) << 9)) & 0777777;
3942 return barAddr;
3943 }
3944
3945
3946
3947 static void add_history (uint hset, word36 w0, word36 w1)
3948 {
3949
3950 {
3951 cpu.history [hset] [cpu.history_cyclic[hset]] [0] = w0;
3952 cpu.history [hset] [cpu.history_cyclic[hset]] [1] = w1;
3953 cpu.history_cyclic[hset] = (cpu.history_cyclic[hset] + 1) % N_MODEL_HIST_SIZE;
3954 }
3955 }
3956
3957 void add_history_force (uint hset, word36 w0, word36 w1)
3958 {
3959 cpu.history [hset] [cpu.history_cyclic[hset]] [0] = w0;
3960 cpu.history [hset] [cpu.history_cyclic[hset]] [1] = w1;
3961 cpu.history_cyclic[hset] = (cpu.history_cyclic[hset] + 1) % N_MODEL_HIST_SIZE;
3962 }
3963
3964 void add_dps8m_CU_history (void)
3965 {
3966 if (cpu.skip_cu_hist)
3967 return;
3968 if (! cpu.MR_cache.emr)
3969 return;
3970 if (! cpu.MR_cache.ihr)
3971 return;
3972 if (cpu.MR_cache.hrxfr && ! cpu.wasXfer)
3973 return;
3974
3975 word36 flags = 0;
3976 word5 proccmd = 0;
3977 word7 flags2 = 0;
3978 word36 w0 = 0, w1 = 0;
3979 w0 |= flags & 0777777000000;
3980 w0 |= IWB_IRODD & MASK18;
3981 w1 |= (cpu.iefpFinalAddress & MASK24) << 12;
3982 w1 |= (proccmd & MASK5) << 7;
3983 w1 |= flags2 & 0176;
3984 add_history (CU_HIST_REG, w0, w1);
3985 }
3986
3987 #ifndef QUIET_UNUSED
3988 void add_dps8m_DU_OU_history (word36 flags, word18 ICT, word9 RS_REG, word9 flags2)
3989 {
3990 word36 w0 = flags, w1 = 0;
3991 w1 |= (ICT & MASK18) << 18;
3992 w1 |= (RS_REG & MASK9) << 9;
3993 w1 |= flags2 & MASK9;
3994 add_history (DPS8M_DU_OU_HIST_REG, w0, w1);
3995 }
3996
3997 void add_dps8m_APU_history (word15 ESN, word21 flags, word24 RMA, word3 RTRR, word9 flags2)
3998 {
3999 word36 w0 = 0, w1 = 0;
4000 w0 |= (ESN & MASK15) << 21;
4001 w0 |= flags & MASK21;
4002 w1 |= (RMA & MASK24) << 12;
4003 w1 |= (RTRR & MASK3) << 9;
4004 w1 |= flags2 & MASK9;
4005 add_history (cpu.tweaks.l68_mode ? L68_APU_HIST_REG : DPS8M_APU_HIST_REG, w0, w1);
4006 }
4007
4008 void add_dps8m_EAPU_history (word18 ZCA, word18 opcode)
4009 {
4010 word36 w0 = 0;
4011 w0 |= (ZCA & MASK18) << 18;
4012 w0 |= opcode & MASK18;
4013 add_history (DPS8M_EAPU_HIST_REG, w0, 0);
4014
4015
4016
4017
4018 }
4019 #endif
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055 void add_l68_CU_history (void)
4056 {
4057 CPT (cpt1L, 24);
4058
4059 if (cpu.skip_cu_hist)
4060 return;
4061 if (! cpu.MR_cache.emr)
4062 return;
4063 if (! cpu.MR_cache.ihr)
4064 return;
4065
4066 word36 w0 = 0, w1 = 0;
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076 PNL (putbits36_8 (& w0, 0, cpu.prepare_state);)
4077
4078 putbits36_1 (& w0, 8, cpu.wasXfer);
4079
4080 putbits36_1 (& w0, 9, cpu.cu.xde);
4081
4082 putbits36_1 (& w0, 10, cpu.cu.xdo);
4083
4084 putbits36_1 (& w0, 11, USE_IRODD?1:0);
4085
4086 putbits36_1 (& w0, 12, cpu.cu.rpt);
4087
4088
4089 PNL (putbits36_1 (& w0, 14, cpu.AR_F_E);)
4090
4091 putbits36_1 (& w0, 15, cpu.cycle != INTERRUPT_cycle?1:0);
4092
4093 putbits36_1 (& w0, 16, cpu.cycle != FAULT_cycle?1:0);
4094
4095 putbits36_1 (& w0, 17, TSTF (cpu.cu.IR, I_NBAR)?1:0);
4096
4097 putbits36_18 (& w0, 18, (word18) (IWB_IRODD & MASK18));
4098
4099
4100 putbits36_18 (& w1, 0, cpu.TPR.CA);
4101
4102
4103 PNL (putbits36_1 (& w1, 59-36, (cpu.portSelect == 0)?1:0);)
4104 PNL (putbits36_1 (& w1, 60-36, (cpu.portSelect == 1)?1:0);)
4105 PNL (putbits36_1 (& w1, 61-36, (cpu.portSelect == 2)?1:0);)
4106 PNL (putbits36_1 (& w1, 62-36, (cpu.portSelect == 3)?1:0);)
4107
4108 putbits36_1 (& w1, 63-36, cpu.interrupt_flag?1:0);
4109
4110 PNL (putbits36_1 (& w1, 64-36, cpu.INS_FETCH?1:0);)
4111
4112
4113
4114
4115
4116
4117
4118
4119 add_history (CU_HIST_REG, w0, w1);
4120
4121
4122 CPTUR (cptUseMR);
4123 if (cpu.MR.hrhlt && cpu.history_cyclic[CU_HIST_REG] == 0)
4124 {
4125
4126 if (cpu.MR.ihrrs)
4127 {
4128 cpu.MR.ihr = 0;
4129 }
4130 set_FFV_fault (4);
4131 return;
4132 }
4133 }
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173 void add_l68_DU_history (void)
4174 {
4175 CPT (cpt1L, 25);
4176 PNL (add_history (L68_DU_HIST_REG, cpu.du.cycle1, cpu.du.cycle2);)
4177 }
4178
4179 void add_l68_OU_history (void)
4180 {
4181 CPT (cpt1L, 26);
4182 word36 w0 = 0, w1 = 0;
4183
4184
4185
4186 PNL (putbits36_9 (& w0, 0, cpu.ou.RS);)
4187
4188
4189 putbits36_1 (& w0, 9, cpu.ou.characterOperandSize ? 1 : 0);
4190
4191
4192 putbits36_3 (& w0, 10, cpu.ou.characterOperandOffset);
4193
4194
4195 putbits36_1 (& w0, 13, cpu.ou.crflag);
4196
4197
4198 putbits36_1 (& w0, 14, cpu.ou.directOperandFlag ? 1 : 0);
4199
4200
4201 putbits36_2 (& w0, 15, cpu.ou.eac);
4202
4203
4204
4205 PNL (putbits36_9 (& w0, 18, cpu.ou.RS);)
4206
4207
4208 putbits36_1 (& w0, 27, cpu.ou.RB1_FULL);
4209
4210
4211 putbits36_1 (& w0, 28, cpu.ou.RP_FULL);
4212
4213
4214 putbits36_1 (& w0, 29, cpu.ou.RS_FULL);
4215
4216
4217 putbits36_6 (& w0, 30, (word6) (cpu.ou.cycle >> 3));
4218
4219
4220 putbits36_3 (& w1, 36-36, (word3) cpu.ou.cycle);
4221
4222
4223 putbits36_1 (& w1, 39-36, cpu.ou.STR_OP);
4224
4225
4226
4227
4228 PNL (putbits36_10 (& w1, 41-36,
4229 (word10) ~opcodes10 [cpu.ou.RS].reg_use);)
4230
4231
4232
4233
4234 putbits36_18 (& w1, 54 - 36, cpu.PPR.IC);
4235
4236 add_history (L68_OU_HIST_REG, w0, w1);
4237 }
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288 void add_l68_APU_history (enum APUH_e op)
4289 {
4290 CPT (cpt1L, 28);
4291 word36 w0 = 0, w1 = 0;
4292
4293 w0 = op;
4294
4295
4296 putbits36_15 (& w0, 0, cpu.TPR.TSR);
4297
4298 PNL (putbits36_1 (& w0, 15, (cpu.apu.state & apu_ESN_SNR) ? 1 : 0);)
4299 PNL (putbits36_1 (& w0, 16, (cpu.apu.state & apu_ESN_TSR) ? 1 : 0);)
4300
4301 putbits36_1 (& w0, 25, cpu.cu.SDWAMM);
4302
4303 putbits36_4 (& w0, 26, (word4) cpu.SDWAMR);
4304
4305 putbits36_1 (& w0, 30, cpu.cu.PTWAMM);
4306
4307 putbits36_4 (& w0, 31, (word4) cpu.PTWAMR);
4308
4309 PNL (putbits36_1 (& w0, 35, (cpu.apu.state & apu_FLT) ? 1 : 0);)
4310
4311
4312 PNL (putbits36_24 (& w1, 0, cpu.APUMemAddr);)
4313
4314 putbits36_3 (& w1, 24, cpu.TPR.TRR);
4315
4316
4317 putbits36_1 (& w1, 34, cpu.SDW0.C);
4318
4319
4320 add_history (L68_APU_HIST_REG, w0, w1);
4321 }
4322
4323 #if defined(THREADZ) || defined(LOCKLESS)
4324
4325
4326 static const char * get_dbg_verb (uint32 dbits, DEVICE * dptr)
4327 {
4328 static const char * debtab_none = "DEBTAB_ISNULL";
4329 static const char * debtab_nomatch = "DEBTAB_NOMATCH";
4330 const char * some_match = NULL;
4331 int32 offset = 0;
4332
4333 if (dptr->debflags == 0)
4334 return debtab_none;
4335
4336 dbits &= dptr->dctrl;
4337
4338
4339 while ((offset < 32) && dptr->debflags[offset].name)
4340 {
4341 if (dptr->debflags[offset].mask == dbits)
4342 return dptr->debflags[offset].name;
4343 if (dptr->debflags[offset].mask & dbits)
4344 some_match = dptr->debflags[offset].name;
4345 offset ++;
4346 }
4347 return some_match ? some_match : debtab_nomatch;
4348 }
4349
4350 void dps8_sim_debug (uint32 dbits, DEVICE * dptr, unsigned long long cnt, const char* fmt, ...)
4351 {
4352
4353 if (sim_deb && dptr && (dptr->dctrl & dbits))
4354 {
4355 const char * debug_type = get_dbg_verb (dbits, dptr);
4356 char stackbuf[STACKBUFSIZE];
4357 int32 bufsize = sizeof (stackbuf);
4358 char * buf = stackbuf;
4359 va_list arglist;
4360 int32 i, j, len;
4361 struct timespec t;
4362 clock_gettime(CLOCK_REALTIME, &t);
4363
4364 buf [bufsize-1] = '\0';
4365
4366 while (1)
4367 {
4368 va_start (arglist, fmt);
4369 # if defined(NO_vsnprintf)
4370 len = vsprintf (buf, fmt, arglist);
4371 # else
4372 len = vsnprintf (buf, (int)((unsigned long)(bufsize)-1), fmt, arglist);
4373 # endif
4374 va_end (arglist);
4375
4376
4377
4378 if ((len < 0) || (len >= bufsize-1))
4379 {
4380 if (buf != stackbuf)
4381 FREE (buf);
4382 bufsize = bufsize * 2;
4383 if (bufsize < len + 2)
4384 bufsize = len + 2;
4385 buf = (char *) malloc ((unsigned long) bufsize);
4386 if (buf == NULL)
4387 return;
4388 buf[bufsize-1] = '\0';
4389 continue;
4390 }
4391 break;
4392 }
4393
4394
4395
4396 for (i = j = 0; i < len; ++i)
4397 {
4398 if ('\n' == buf[i])
4399 {
4400 if (i >= j)
4401 {
4402 if ((i != j) || (i == 0))
4403 {
4404 fprintf (sim_deb, "%lld.%06ld: DBG(%lld) %o: %s %s %.*s\r\n",
4405 (long long)t.tv_sec, t.tv_nsec/1000, cnt,
4406 current_running_cpu_idx, dptr->name, debug_type, i-j, &buf[j]);
4407 }
4408 }
4409 j = i + 1;
4410 }
4411 }
4412
4413
4414 if (buf != stackbuf)
4415 FREE (buf);
4416 }
4417
4418 }
4419 #endif
4420
4421 void setupPROM (uint cpuNo, unsigned char * PROM) {
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462 word36 rsw2 = 0;
4463
4464
4465
4466
4467
4468
4469
4470 putbits36_4 (& rsw2, 0, 0);
4471
4472 putbits36_2 (& rsw2, 4, 001);
4473
4474 putbits36_7 (& rsw2, 6, 2);
4475
4476 putbits36_1 (& rsw2, 13, 1);
4477
4478 putbits36_5 (& rsw2, 14, 0);
4479
4480 putbits36_1 (& rsw2, 19, 1);
4481
4482 putbits36_1 (& rsw2, 20, cpus[cpuNo].options.cache_installed ? 1 : 0);
4483
4484 putbits36_2 (& rsw2, 21, 0);
4485
4486 putbits36_1 (& rsw2, 23, 1);
4487
4488 putbits36_1 (& rsw2, 24, 0);
4489
4490 putbits36_4 (& rsw2, 25, 0);
4491
4492 putbits36_4 (& rsw2, 29, cpus[cpuNo].options.proc_speed & 017LL);
4493
4494 putbits36_3 (& rsw2, 33, cpus[cpuNo].switches.cpu_num & 07LL);
4495
4496 word4 rsw2Ext = 0;
4497 if (cpus[cpuNo].options.hex_mode_installed)
4498 rsw2Ext |= 010;
4499 if (cpus[cpuNo].options.clock_slave_installed)
4500 rsw2Ext |= 004;
4501
4502
4503 char serial[12];
4504 sprintf (serial, "%-11u", cpus[cpuNo].switches.serno);
4505
4506 #ifdef VER_H_PROM_SHIP
4507 char * ship = VER_H_PROM_SHIP;
4508 #else
4509 char * ship = "200101";
4510 #endif
4511
4512 #define BURN(offset, length, string) memcpy ((char *) PROM + (offset), string, length)
4513 #define BURN1(offset, byte) PROM[offset] = (char) (byte)
4514
4515 memset (PROM, 255, 1024);
4516
4517
4518 BURN ( 00, 11, "DPS 8/SIM M");
4519 BURN (013, 11, serial);
4520 BURN (026, 6, ship);
4521 BURN1 (034, getbits36_8 (rsw2, 0));
4522 BURN1 (035, getbits36_8 (rsw2, 8));
4523 BURN1 (036, getbits36_8 (rsw2, 16));
4524 BURN1 (037, getbits36_8 (rsw2, 24));
4525 BURN1 (040, ((getbits36_4 (rsw2, 32) << 4) | rsw2Ext));
4526 }