forked from open-simh/simh
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpdp10_cpu.c
2607 lines (2348 loc) · 111 KB
/
pdp10_cpu.c
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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
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
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
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
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/* pdp10_cpu.c: PDP-10 CPU simulator
Copyright (c) 1993-2017, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of Robert M Supnik shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
cpu KS10 central processor
07-Sep-17 RMS Fixed sim_eval declaration in history routine (COVERITY)
14-Jan-17 RMS Fixed bugs in 1-proceed
09-Feb-16 RMS Fixed nested indirects and executes (Tim Litt)
25-Mar-12 RMS Added missing parameters to prototypes (Mark Pizzolato)
17-Jul-07 RMS Fixed non-portable usage in SHOW HISTORY
28-Apr-07 RMS Removed clock initialization
22-Sep-05 RMS Fixed declarations (Sterling Garwood)
Fixed warning in MOVNI
16-Aug-05 RMS Fixed C++ declaration and cast problems
10-Nov-04 RMS Added instruction history
08-Oct-02 RMS Revised to build dib_tab dynamically
Added SHOW IOSPACE
30-Dec-01 RMS Added old PC queue
25-Dec-01 RMS Cleaned up sim_inst declarations
07-Dec-01 RMS Revised to use new breakpoint package
21-Nov-01 RMS Implemented ITS 1-proceed hack
31-Aug-01 RMS Changed int64 to t_int64 for Windoze
10-Aug-01 RMS Removed register in declarations
17-Jul-01 RMS Moved function prototype
19-May-01 RMS Added workaround for TOPS-20 V4.1 boot bug
29-Apr-01 RMS Fixed modifier naming conflict
Fixed XCTR/XCTRI, UMOVE/UMOVEM, BLTUB/BLTBU for ITS
Added CLRCSH for ITS
The 36b system family had six different implementions: PDP-6, KA10, KI10,
L10, KL10 extended, and KS10. This simulator implements the KS10.
The register state for the KS10 is:
AC[8][16] accumulators
PC program counter
flags<0:11> state flags
pi_enb<1:7> enabled PI levels
pi_act<1:7> active PI levels
pi_prq<1:7> program PI requests
apr_enb<0:7> enabled system flags
apr_flg<0:7> system flags
ebr executive base register
ubr user base register
hsb halt status block address
spt SPT base
cst CST base
pur process use register
cstm CST mask
The PDP-10 had just two instruction formats: memory reference
and I/O.
000000000 0111 1 1111 112222222222333333
012345678 9012 3 4567 890123456789012345
+---------+----+-+----+------------------+
| opcode | ac |i| idx| address | memory reference
+---------+----+-+----+------------------+
000 0000000 111 1 1111 112222222222333333
012 3456789 012 3 4567 890123456789012345
+---+-------+---+-+----+------------------+
|111|device |iop|i| idx| address | I/O
+---+-------+---+-+----+------------------+
This routine is the instruction decode routine for the PDP-10.
It is called from the simulator control program to execute
instructions in simulated memory, starting at the simulated PC.
It runs until an abort occurs.
General notes:
1. Reasons to stop. The simulator can be stopped by:
HALT instruction
MUUO instruction in executive mode
pager error in interrupt sequence
invalid vector table in interrupt sequence
illegal instruction in interrupt sequence
breakpoint encountered
nested indirects exceeding limit
nested XCT's exceeding limit
I/O error in I/O simulator
2. Interrupts. PDP-10's have a seven level priority interrupt
system. Interrupt requests can come from internal sources,
such as APR program requests, or external sources, such as
I/O devices. The requests are stored in pi_prq for program
requests, pi_apr for other internal flags, and pi_ioq for
I/O device flags. Internal and device (but not program)
interrupts must be enabled on a level by level basis. When
an interrupt is granted on a level, interrupts at that level
and below are masked until the interrupt is dismissed.
The I/O device interrupt system is taken from the PDP-11.
int_req stores the interrupt requests for Unibus I/O devices.
Routines in the Unibus adapter map requests in int_req to
PDP-10 levels. The Unibus adapter also calculates which
device to get a vector from when a PDP-10 interrupt is granted.
3. Arithmetic. The PDP-10 is a 2's complement system.
4. Adding I/O devices. These modules must be modified:
pdp10_defs.h add device address and interrupt definitions
pdp10_sys.c add sim_devices table entry
A note on ITS 1-proceed. The simulator follows the implementation
on the KS10, keeping 1-proceed as a side flag (its_1pr) rather than
as flags<8>. This simplifies the flag saving instructions, which
don't have to clear flags<8> before saving it. Instead, the page
fail and interrupt code must restore flags<8> from its_1pr. Unlike
the KS10, the simulator will not lose the 1-proceed trap if the
1-proceeded instructions clears 1-proceed.
*/
#include "pdp10_defs.h"
#include <setjmp.h>
#define PCQ_SIZE 64 /* must be 2**n */
#define PCQ_MASK (PCQ_SIZE - 1)
#define PCQ_ENTRY pcq[pcq_p = (pcq_p - 1) & PCQ_MASK] = PC
#define HIST_PC 0x40000000
#define HIST_MIN 64
#define HIST_MAX 65536
typedef struct {
a10 pc;
a10 ea;
d10 ir;
d10 ac;
} InstHistory;
extern a10 fe_xct; /* Front-end forced XCT */
extern DEVICE pag_dev;
extern t_stat pag_reset (DEVICE *dptr);
d10 *M = NULL; /* memory */
d10 acs[AC_NBLK * AC_NUM] = { 0 }; /* AC blocks */
d10 *ac_cur, *ac_prv; /* AC cur, prv (dyn) */
a10 epta, upta; /* proc tbl addr (dyn) */
a10 saved_PC = 0; /* scp: saved PC */
d10 pager_word = 0; /* pager: error word */
a10 pager_PC = 0; /* pager: saved PC */
int32 pager_flags = 0; /* pager: trap flags */
t_bool pager_pi = FALSE; /* pager: in pi seq */
t_bool pager_tc = FALSE; /* pager: trap cycle */
d10 ebr = 0; /* exec base reg */
d10 ubr = 0; /* user base reg */
d10 hsb = 0; /* halt status block */
d10 spt = 0; /* TOPS20 paging regs */
d10 cst = 0;
d10 pur = 0;
d10 cstm = 0;
a10 dbr1 = 0; /* ITS paging regs */
a10 dbr2 = 0;
a10 dbr3 = 0;
a10 dbr4 = 0;
d10 pcst = 0; /* ITS PC sampling */
int32 pi_on = 0; /* pi system enable */
int32 pi_enb = 0; /* pi enabled levels */
int32 pi_act = 0; /* pi active levels */
int32 pi_ioq = 0; /* pi io requests */
int32 pi_apr = 0; /* pi apr requests */
int32 pi_prq = 0; /* pi prog requests */
int32 apr_enb = 0; /* apr enables */
int32 apr_flg = 0; /* apr flags */
int32 apr_lvl = 0; /* apr level */
int32 qintr = 0; /* interrupt pending */
int32 flags = 0; /* flags */
int32 its_1pr = 0; /* ITS 1-proceed */
int32 stop_op0 = 0; /* stop on 0 */
int32 rlog = 0; /* extend fixup log */
int32 ind_max = 0; /* nested ind limit */
int32 xct_max = 0; /* nested XCT limit */
a10 pcq[PCQ_SIZE] = { 0 }; /* PC queue */
int32 pcq_p = 0; /* PC queue ptr */
REG *pcq_r = NULL; /* PC queue reg ptr */
jmp_buf save_env;
int32 hst_p = 0; /* history pointer */
int32 hst_lnt = 0; /* history length */
InstHistory *hst = NULL; /* instruction history */
int32 apr_serial = -1; /* CPU Serial number */
/* Forward and external declarations */
t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw);
t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw);
t_stat cpu_reset (DEVICE *dptr);
t_bool cpu_is_pc_a_subroutine_call (t_addr **ret_addrs);
t_stat cpu_set_hist (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
t_stat cpu_set_serial (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
t_stat cpu_show_serial (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
d10 adjsp (d10 val, a10 ea);
void ibp (a10 ea, int32 pflgs);
d10 ldb (a10 ea, int32 pflgs);
void dpb (d10 val, a10 ea, int32 pflgs);
void adjbp (int32 ac, a10 ea, int32 pflgs);
d10 add (d10 val, d10 mb);
d10 sub (d10 val, d10 mb);
void dadd (int32 ac, d10 *rs);
void dsub (int32 ac, d10 *rs);
int32 jffo (d10 val);
d10 lsh (d10 val, a10 ea);
d10 rot (d10 val, a10 ea);
d10 ash (d10 val, a10 ea);
void lshc (int32 ac, a10 ea);
void rotc (int32 ac, a10 ea);
void ashc (int32 ac, a10 ea);
void circ (int32 ac, a10 ea);
void blt (int32 ac, a10 ea, int32 pflgs);
void bltu (int32 ac, a10 ea, int32 pflgs, int dir);
a10 calc_ea (d10 inst, int32 prv);
a10 calc_ioea (d10 inst, int32 prv);
d10 calc_jrstfea (d10 inst, int32 pflgs);
void pi_dismiss (void);
void set_newflags (d10 fl, t_bool jrst);
extern t_bool aprid (a10 ea, int32 prv);
t_bool wrpi (a10 ea, int32 prv);
t_bool rdpi (a10 ea, int32 prv);
t_bool czpi (a10 ea, int32 prv);
t_bool copi (a10 ea, int32 prv);
t_bool wrapr (a10 ea, int32 prv);
t_bool rdapr (a10 ea, int32 prv);
t_bool czapr (a10 ea, int32 prv);
t_bool coapr (a10 ea, int32 prv);
int32 pi_eval (void);
int32 test_int (void);
void set_ac_display (d10 *acbase);
extern t_stat build_dib_tab (void);
extern t_stat show_iospace (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
extern void set_dyn_ptrs (void);
extern a10 conmap (a10 ea, int32 mode, int32 sw);
extern void fe_intr ();
extern void dfad (int32 ac, d10 *rs, int32 inv);
extern void dfmp (int32 ac, d10 *rs);
extern void dfdv (int32 ac, d10 *rs);
extern void dmul (int32 ac, d10 *rs);
extern void ddiv (int32 ac, d10 *rs);
extern void fix (int32 ac, d10 mb, t_bool rnd);
extern d10 fad (d10 val, d10 mb, t_bool rnd, int32 inv);
extern d10 fmp (d10 val, d10 mb, t_bool rnd);
extern t_bool fdv (d10 val, d10 mb, d10 *rs, t_bool rnd);
extern d10 fsc (d10 val, a10 ea);
extern d10 fltr (d10 mb);
extern int xtend (int32 ac, a10 ea, int32 pflgs);
extern void xtcln (int32 rlog);
extern d10 map (a10 ea, int32 prv);
extern d10 imul (d10 val, d10 mb);
extern t_bool idiv (d10 val, d10 mb, d10 *rs);
extern void mul (d10 val, d10 mb, d10 *rs);
extern t_bool divi (int32 ac, d10 mb, d10 *rs);
extern t_bool io710 (int32 ac, a10 ea);
extern t_bool io711 (int32 ac, a10 ea);
extern d10 io712 (a10 ea);
extern void io713 (d10 val, a10 ea);
extern void io714 (d10 val, a10 ea);
extern void io715 (d10 val, a10 ea);
extern t_bool io720 (int32 ac, a10 ea);
extern t_bool io721 (int32 ac, a10 ea);
extern d10 io722 (a10 ea);
extern void io723 (d10 val, a10 ea);
extern void io724 (d10 val, a10 ea);
extern void io725 (d10 val, a10 ea);
extern t_bool clrcsh (a10 ea, int32 prv);
extern t_bool clrpt (a10 ea, int32 prv);
extern t_bool wrubr (a10 ea, int32 prv);
extern t_bool wrebr (a10 ea, int32 prv);
extern t_bool wrhsb (a10 ea, int32 prv);
extern t_bool wrspb (a10 ea, int32 prv);
extern t_bool wrcsb (a10 ea, int32 prv);
extern t_bool wrpur (a10 ea, int32 prv);
extern t_bool wrcstm (a10 ea, int32 prv);
extern t_bool ldbr1 (a10 ea, int32 prv);
extern t_bool ldbr2 (a10 ea, int32 prv);
extern t_bool ldbr3 (a10 ea, int32 prv);
extern t_bool ldbr4 (a10 ea, int32 prv);
extern t_bool rdubr (a10 ea, int32 prv);
extern t_bool rdebr (a10 ea, int32 prv);
extern t_bool rdhsb (a10 ea, int32 prv);
extern t_bool rdspb (a10 ea, int32 prv);
extern t_bool rdcsb (a10 ea, int32 prv);
extern t_bool rdpur (a10 ea, int32 prv);
extern t_bool rdcstm (a10 ea, int32 prv);
extern t_bool sdbr1 (a10 ea, int32 prv);
extern t_bool sdbr2 (a10 ea, int32 prv);
extern t_bool sdbr3 (a10 ea, int32 prv);
extern t_bool sdbr4 (a10 ea, int32 prv);
extern t_bool rdtim (a10 ea, int32 prv);
extern t_bool rdint (a10 ea, int32 prv);
extern t_bool wrtim (a10 ea, int32 prv);
extern t_bool wrint (a10 ea, int32 prv);
extern t_bool rdpcst (a10 ea, int32 prv);
extern t_bool wrpcst (a10 ea, int32 prv);
extern t_bool spm (a10 ea, int32 prv);
extern t_bool lpmr (a10 ea, int32 prv);
extern int32 pi_ub_vec (int32 lvl, int32 *uba);
extern t_stat tim_set_mod (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
/* CPU data structures
cpu_dev CPU device descriptor
cpu_unit CPU unit
cpu_reg CPU register list
cpu_mod CPU modifier list
*/
UNIT cpu_unit = { UDATA (NULL, UNIT_FIX + UNIT_BINK, MAXMEMSIZE) };
REG cpu_reg[] = {
{ ORDATAD (PC, saved_PC, VASIZE, "program counter") },
{ ORDATAD (FLAGS, flags, 18, "processor flags (<13:17> unused") },
{ ORDATAD (AC0, acs[0], 36, "active register 0") }, /* addr in memory */
{ ORDATAD (AC1, acs[1], 36, "active register 1") }, /* modified at exit */
{ ORDATAD (AC2, acs[2], 36, "active register 2") }, /* to SCP */
{ ORDATAD (AC3, acs[3], 36, "active register 3") },
{ ORDATAD (AC4, acs[4], 36, "active register 4") },
{ ORDATAD (AC5, acs[5], 36, "active register 5") },
{ ORDATAD (AC6, acs[6], 36, "active register 6") },
{ ORDATAD (AC7, acs[7], 36, "active register 7") },
{ ORDATAD (AC10, acs[10], 36, "active register 10") },
{ ORDATAD (AC11, acs[11], 36, "active register 11") },
{ ORDATAD (AC12, acs[12], 36, "active register 12") },
{ ORDATAD (AC13, acs[13], 36, "active register 13") },
{ ORDATAD (AC14, acs[14], 36, "active register 14") },
{ ORDATAD (AC15, acs[15], 36, "active register 15") },
{ ORDATAD (AC16, acs[16], 36, "active register 16") },
{ ORDATAD (AC17, acs[17], 36, "active register 17") },
{ ORDATAD (PFW, pager_word, 36, "pager word register") },
{ ORDATAD (EBR, ebr, EBR_N_EBR, "executive base register") },
{ FLDATAD (PGON, ebr, EBR_V_PGON, "paging enabled flag") },
{ FLDATAD (T20P, ebr, EBR_V_T20P, "TOPS-20 paging") },
{ ORDATAD (UBR, ubr, 36, "user base register") },
{ GRDATAD (CURAC, ubr, 8, 3, UBR_V_CURAC, "current AC block"), REG_RO },
{ GRDATAD (PRVAC, ubr, 8, 3, UBR_V_PRVAC, "previous AC block") },
{ ORDATAD (SPT, spt, 36, "shared pointer table") },
{ ORDATAD (CST, cst, 36, "core status table") },
{ ORDATAD (PUR, pur, 36, "process update register") },
{ ORDATAD (CSTM, cstm, 36, "CST mask") },
{ ORDATAD (HSB, hsb, 36, "halt status block address") },
{ ORDATAD (DBR1, dbr1, PASIZE, "descriptor base register 1 (ITS)") },
{ ORDATAD (DBR2, dbr2, PASIZE, "descriptor base register 2 (ITS)") },
{ ORDATAD (DBR3, dbr3, PASIZE, "descriptor base register 3 (ITS)") },
{ ORDATAD (DBR4, dbr4, PASIZE, "descriptor base register 4 (ITS)") },
{ ORDATAD (PCST, pcst, 36, "ITS PC sampling register") },
{ ORDATAD (PIENB, pi_enb, 7, "PI levels enabled") },
{ FLDATAD (PION, pi_on, 0, "PI system enable") },
{ ORDATAD (PIACT, pi_act, 7, "PI levels active") },
{ ORDATAD (PIPRQ, pi_prq, 7, "PI levels with program requests") },
{ ORDATAD (PIIOQ, pi_ioq, 7, "PI levels with I/O requests"), REG_RO },
{ ORDATAD (PIAPR, pi_apr, 7, "PI levels with APR requests"), REG_RO },
{ ORDATAD (APRENB, apr_enb, 8, "APR flags enabled") },
{ ORDATAD (APRFLG, apr_flg, 8, "APR flags active") },
{ ORDATAD (APRLVL, apr_lvl, 3, "PI level for APR interrupt") },
{ ORDATAD (RLOG, rlog, 10, "extend fix up log") },
{ FLDATAD (F1PR, its_1pr, 0, "ITS 1-proceed") },
{ BRDATAD (PCQ, pcq, 8, VASIZE, PCQ_SIZE, "PC prior to last jump or interrupt; most recent PC change first"), REG_RO+REG_CIRC },
{ ORDATA (PCQP, pcq_p, 6), REG_HRO },
{ DRDATAD (INDMAX, ind_max, 8, "indirect address nesting limit; if 0, no limit"), PV_LEFT },
{ DRDATAD (XCTMAX, xct_max, 8, "execute chaining limit; if 0, no limit"), PV_LEFT },
{ ORDATAD (WRU, sim_int_char, 8, "interrupt character") },
{ FLDATA (STOP_ILL, stop_op0, 0) },
{ BRDATAD (REG, acs, 8, 36, AC_NUM * AC_NBLK, "register sets") },
{ NULL }
};
MTAB cpu_mod[] = {
{ UNIT_KLAD+UNIT_ITS+UNIT_T20, 0, "TOPS-10", "TOPS-10", &tim_set_mod },
{ UNIT_KLAD+UNIT_ITS+UNIT_T20, 0, NULL , "TOPS10", &tim_set_mod },
{ UNIT_KLAD+UNIT_ITS+UNIT_T20, UNIT_T20, "TOPS-20", "TOPS-20", &tim_set_mod },
{ UNIT_KLAD+UNIT_ITS+UNIT_T20, UNIT_T20, NULL, "TOPS20", &tim_set_mod },
{ UNIT_KLAD+UNIT_ITS+UNIT_T20, UNIT_ITS, "ITS", "ITS", &tim_set_mod },
{ UNIT_KLAD+UNIT_ITS+UNIT_T20, UNIT_KLAD, "diagnostic mode", "KLAD", &tim_set_mod },
{ MTAB_XTD|MTAB_VDV, 0, "IDLE", "IDLE", &sim_set_idle, &sim_show_idle },
{ MTAB_XTD|MTAB_VDV, 0, NULL, "NOIDLE", &sim_clr_idle, NULL },
{ MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "IOSPACE", NULL,
NULL, &show_iospace },
{ MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP, 0, "HISTORY", "HISTORY",
&cpu_set_hist, &cpu_show_hist },
{ MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "SERIAL", "SERIAL", &cpu_set_serial, &cpu_show_serial },
{ 0 }
};
DEVICE cpu_dev = {
"CPU", &cpu_unit, cpu_reg, cpu_mod,
1, 8, PASIZE, 1, 8, 36,
&cpu_ex, &cpu_dep, &cpu_reset,
NULL, NULL, NULL
};
/* Data arrays */
const int32 pi_l2bit[8] = {
0, 0100, 0040, 0020, 0010, 0004, 0002, 0001
};
const int32 pi_m2lvl[128] = {
0, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
};
const d10 bytemask[64] = { 0,
INT64_C(01), INT64_C(03), INT64_C(07), INT64_C(017), INT64_C(037), INT64_C(077),
INT64_C(0177), INT64_C(0377), INT64_C(0777), INT64_C(01777), INT64_C(03777), INT64_C(07777),
INT64_C(017777), INT64_C(037777), INT64_C(077777),
INT64_C(0177777), INT64_C(0377777), INT64_C(0777777),
INT64_C(01777777), INT64_C(03777777), INT64_C(07777777),
INT64_C(017777777), INT64_C(037777777), INT64_C(077777777),
INT64_C(0177777777), INT64_C(0377777777), INT64_C(0777777777),
INT64_C(01777777777), INT64_C(03777777777), INT64_C(07777777777),
INT64_C(017777777777), INT64_C(037777777777), INT64_C(077777777777),
INT64_C(0177777777777), INT64_C(0377777777777), INT64_C(0777777777777),
ONES, ONES, ONES, ONES, ONES, ONES, ONES, ONES, ONES,
ONES, ONES, ONES, ONES, ONES, ONES, ONES, ONES, ONES,
ONES, ONES, ONES, ONES, ONES, ONES, ONES, ONES, ONES
};
static t_bool (*io700d[16])(a10, int32) = {
&aprid, NULL, NULL, NULL, &wrapr, &rdapr, &czapr, &coapr,
NULL, NULL, NULL, NULL, &wrpi, &rdpi, &czpi, &copi
};
static t_bool (*io701d[16])(a10, int32) = {
NULL, &rdubr, &clrpt, &wrubr, &wrebr, &rdebr, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
};
static t_bool (*io702d[16])(a10, int32) = {
&rdspb, &rdcsb, &rdpur, &rdcstm, &rdtim, &rdint, &rdhsb, NULL,
&wrspb, &wrcsb, &wrpur, &wrcstm, &wrtim, &wrint, &wrhsb, NULL
};
#define io700i io700d
static t_bool (*io701i[16])(a10, int32) = {
&clrcsh, &rdubr, &clrpt, &wrubr, &wrebr, &rdebr, NULL, NULL,
NULL, &rdpcst, NULL, &wrpcst, NULL, NULL, NULL, NULL
};
static t_bool (*io702i[16])(a10, int32) = {
&sdbr1, &sdbr2, &sdbr3, &sdbr4, &rdtim, &rdint, &rdhsb, &spm,
&ldbr1, &ldbr2, &ldbr3, &ldbr4, &wrtim, &wrint, &wrhsb, &lpmr
};
/* JRST classes and validation table */
#define JRST_U 1 /* ok anywhere */
#define JRST_E 2 /* ok exec mode */
#define JRST_UIO 3 /* ok user I/O mode */
static t_stat jrst_tab[16] = {
JRST_U, JRST_U, JRST_U, 0, JRST_E, JRST_U, JRST_E, JRST_E,
JRST_UIO, 0, JRST_UIO, 0, JRST_E, JRST_U, 0, 0
};
/* Address operations */
#define IM ((d10) ea)
#define IMS (((d10) ea) << 18)
#define JUMP(x) PCQ_ENTRY, PC = ((a10) (x)) & AMASK
#define SUBJ(x) CLRF (F_AFI | F_FPD | F_TR); JUMP (x)
#define INCPC PC = INCA (PC)
/* AC operations */
#define AOBAC AC(ac) = AOB (AC(ac))
#define SOBAC AC(ac) = SOB (AC(ac))
#define G2AC rs[0] = AC(ac), rs[1] = AC(P1)
#define S1AC AC(ac) = rs[0]
#define S2AC S1AC, AC(P1) = rs[1]
#define LAC if (ac) AC(ac) = mb
/* Memory operations */
#define RD mb = Read (ea, MM_OPND)
#define RDAC AC(ac) = Read (ea, MM_OPND)
#define RM mb = ReadM (ea, MM_OPND)
#define RMAC AC(ac) = ReadM (ea, MM_OPND)
#define RDP mb = Read (((a10) AC(ac)) & AMASK, MM_BSTK)
#define RD2 rs[0] = Read (ea, MM_OPND); \
rs[1] = Read (INCA (ea), MM_OPND)
#define WR Write (ea, mb, MM_OPND)
#define WRAC Write (ea, AC(ac), MM_OPND)
#define WRP(x) Write (((a10) INCA (AC(ac))), (x), MM_BSTK)
#define WR1 Write (ea, rs[0], MM_OPND)
#define WR2 ReadM (INCA (ea), MM_OPND); \
Write (ea, rs[0], MM_OPND); \
Write (INCA (ea), rs[1], MM_OPND)
/* Tests and compares */
#define TL(a) (TSTS (a) != 0)
#define TE(a) ((a) == 0)
#define TLE(a) (TL (a) || TE (a))
#define TGE(a) (TSTS (a) == 0)
#define TN(a) ((a) != 0)
#define TG(a) (TGE (a) && TN (a))
#define CL(a) ((TSTS (AC(ac) ^ a))? (a < AC(ac)): (AC(ac) < a))
#define CE(a) (AC(ac) == a)
#define CLE(a) (CL (a) || CE (a))
#define CGE(a) (!CL (a))
#define CN(a) (AC(ac) != a)
#define CG(a) (CGE (a) && CN (a))
/* Word assemblies */
#define FLPC XWD (flags, PC)
#define UUOWORD (((d10) op) << INST_V_OP) | (((d10) ac) << INST_V_AC) | ea
#define APRHWORD ((apr_flg << APR_V_FLG) | (apr_lvl & APR_M_LVL) | \
((apr_flg & apr_enb)? APR_IRQ: 0))
#define APRWORD ((apr_enb << (APR_V_FLG + 18)) | APRHWORD)
#define PIHWORD ((pi_act << PI_V_ACT) | (pi_on << PI_V_ON) | \
(pi_enb << PI_V_ENB))
#define PIWORD ((pi_prq << PI_V_PRQ) | PIHWORD)
/* Instruction operations */
#define CIBP if (!TSTF (F_FPD)) { ibp (ea, pflgs); SETF (F_FPD); }
#define LDB AC(ac) = ldb (ea, pflgs)
#define DPB dpb (AC(ac), ea, pflgs)
#define FAD(s) fad (AC(ac), s, FALSE, 0)
#define FADR(s) fad (AC(ac), s, TRUE, 0)
#define FSB(s) fad (AC(ac), s, FALSE, 1)
#define FSBR(s) fad (AC(ac), s, TRUE, 1)
#define FMP(s) fmp (AC(ac), s, FALSE)
#define FMPR(s) fmp (AC(ac), s, TRUE)
#define FDV(s) fdv (AC(ac), s, rs, FALSE)
#define FDVR(s) fdv (AC(ac), s, rs, TRUE)
#define MOVN(s) NEG (s); MOVNF(s)
#define MOVM(s) ABS (s); MOVMF(s)
#define ADD(s) add (AC(ac), s)
#define SUB(s) sub (AC(ac), s)
#define IMUL(s) imul (AC(ac), s)
#define IDIV(s) idiv (AC(ac), s, rs)
#define MUL(s) mul (AC(ac), s, rs)
#define DIV(s) divi (ac, s, rs)
#define AOJ AC(ac) = INC (AC(ac)); INCF (AC(ac))
#define AOS RM; mb = INC (mb); WR; INCF (mb); LAC
#define SOJ AC(ac) = DEC (AC(ac)); DECF (AC(ac))
#define SOS RM; mb = DEC (mb); WR; DECF (mb); LAC
#define SETCA(s) ~AC(ac) & DMASK
#define SETCM(s) ~(s) & DMASK;
#define AND(s) AC(ac) & (s)
#define ANDCA(s) ~AC(ac) & (s)
#define ANDCM(s) AC(ac) & ~(s)
#define ANDCB(s) (~AC(ac) & ~(s)) & DMASK
#define IOR(s) AC(ac) | (s)
#define ORCA(s) (~AC(ac) | (s)) & DMASK
#define ORCM(s) (AC(ac) | ~(s)) & DMASK
#define ORCB(s) (~AC(ac) | ~(s)) & DMASK
#define XOR(s) AC(ac) ^ (s)
#define EQV(s) (~(AC(ac) ^ (s))) & DMASK
#define LL(s,d) ((s) & LMASK) | ((d) & RMASK)
#define RL(s,d) (((s) << 18) & LMASK) | ((d) & RMASK)
#define RR(s,d) ((s) & RMASK) | ((d) & LMASK)
#define LR(s,d) (((s) >> 18) & RMASK) | ((d) & LMASK)
#define LLO(s) ((s) & LMASK) | RMASK
#define RLO(s) (((s) << 18) & LMASK) | RMASK
#define RRO(s) ((s) & RMASK) | LMASK
#define LRO(s) (((s) >> 18) & RMASK) | LMASK
#define LLE(s) ((s) & LMASK) | (((s) & LSIGN)? RMASK: 0)
#define RLE(s) (((s) << 18) & LMASK) | (((s) & RSIGN)? RMASK: 0)
#define RRE(s) ((s) & RMASK) | (((s) & RSIGN)? LMASK: 0)
#define LRE(s) (((s) >> 18) & RMASK) | (((s) & LSIGN)? LMASK: 0)
#define TD_ RD
#define TS_ RD; mb = SWP (mb)
#define TL_ mb = IMS
#define TR_ mb = IM
#define T_Z AC(ac) = AC(ac) & ~mb
#define T_O AC(ac) = AC(ac) | mb
#define T_C AC(ac) = AC(ac) ^ mb
#define T__E if ((AC(ac) & mb) == 0) INCPC
#define T__N if ((AC(ac) & mb) != 0) INCPC
#define T__A INCPC
#define IOC if (TSTF (F_USR) && !TSTF (F_UIO)) goto MUUO;
#define IO7(x,y) IOC; fptr = ((Q_ITS)? x[ac]: y[ac]); \
if (fptr == NULL) goto MUUO; \
if (fptr (ea, MM_OPND)) INCPC; break;
#define IOA IOC; if (!Q_ITS) ea = calc_ioea (inst, pflgs)
#define IOAM IOC; ea = ((Q_ITS)? ((a10) Read (ea, MM_OPND)): \
calc_ioea (inst, pflgs))
/* Flag tests */
#define MOVNF(x) if ((x) == MAXNEG) SETF (F_C1 | F_AOV | F_T1); \
else if ((x) == 0) SETF (F_C0 | F_C1)
#define MOVMF(x) if ((x) == MAXNEG) SETF (F_C1 | F_AOV | F_T1)
#define INCF(x) if ((x) == 0) SETF (F_C0 | F_C1); \
else if ((x) == MAXNEG) SETF (F_C1 | F_AOV | F_T1)
#define DECF(x) if ((x) == MAXPOS) SETF (F_C0 | F_AOV | F_T1); \
else if ((x) != ONES) SETF (F_C0 | F_C1)
#define PUSHF if (LRZ (AC(ac)) == 0) SETF (F_T2)
#define POPF if (LRZ (AC(ac)) == RMASK) SETF (F_T2)
#define DMOVNF if (rs[1] == 0) { MOVNF (rs[0]); }
t_value pdp10_pc_value (void)
{
return (t_value)pager_PC;
}
t_stat sim_instr (void)
{
a10 PC; /* set by setjmp */
int abortval = 0; /* abort value */
t_stat r;
/* Restore register state */
if ((r = build_dib_tab ()) != SCPE_OK) /* build, chk dib_tab */
return r;
pager_PC = PC = saved_PC & AMASK; /* load local PC */
set_dyn_ptrs (); /* set up local ptrs */
pager_tc = FALSE; /* not in trap cycle */
pager_pi = FALSE; /* not in pi sequence */
rlog = 0; /* not in extend */
pi_eval (); /* eval pi system */
if (!Q_ITS) /* ~ITS, clr 1-proc */
its_1pr = 0;
/* Abort handling
Aborts may come from within the simulator to stop simulation (values > 0),
for page fails (values < 0), or for an interrupt check (value = 0).
*/
abortval = setjmp (save_env); /* set abort hdlr */
if ((abortval > 0) || pager_pi) { /* stop or pi err? */
if (pager_pi && (abortval == PAGE_FAIL))
abortval = STOP_PAGINT; /* stop for pi err */
saved_PC = pager_PC & AMASK; /* failing instr PC */
set_ac_display (ac_cur); /* set up AC display */
pcq_r->qptr = pcq_p; /* update pc q ptr */
return abortval; /* return to SCP */
}
/* Page fail - checked against KS10 ucode
All state variables MUST be declared global for GCC optimization to work
*/
else if (abortval == PAGE_FAIL) { /* page fail */
d10 mb;
if (rlog) /* clean up extend */
xtcln (rlog);
rlog = 0; /* clear log */
if (pager_tc) /* trap? get flags */
flags = pager_flags;
if (T20PAG) { /* TOPS-20 paging? */
WriteP (upta + UPT_T20_PFL, pager_word); /* write page fail wd */
WriteP (upta + UPT_T20_OFL, XWD (flags, 0));
WriteP (upta + UPT_T20_OPC, pager_PC);
mb = ReadP (upta + UPT_T20_NPC);
}
else {
a10 ea; /* TOPS-10 or ITS */
if (Q_ITS) { /* ITS? */
ea = epta + EPT_ITS_PAG + (pi_m2lvl[pi_act] * 3);
if (its_1pr) /* store 1-proc */
flags = flags | F_1PR;
its_1pr = 0; /* clear 1-proc */
}
else ea = upta + UPT_T10_PAG;
WriteP (ea, pager_word); /* write page fail wd */
WriteP (ADDA (ea, 1), XWD (flags, pager_PC));
mb = ReadP (ADDA (ea, 2));
}
JUMP (mb); /* set new PC */
set_newflags (mb, FALSE); /* set new flags */
pi_eval (); /* eval pi system */
}
else PC = pager_PC; /* intr, restore PC */
/* Main instruction fetch/decode loop: check clock queue, intr, trap, bkpt */
for ( ;; ) { /* loop until ABORT */
int32 op, ac, i, st, xr, xct_cnt, its_2pr, pflgs;
a10 ea;
d10 inst, mb, indrct, rs[2];
t_bool (*fptr)(int32, int32);
pager_PC = PC; /* update pager PC */
pager_tc = FALSE; /* not in trap cycle */
pflgs = 0; /* not in PXCT */
xct_cnt = 0; /* count XCT's */
if (sim_interval <= 0) { /* check clock queue */
/* make sure all useful state is in simh registers while processing events */
saved_PC = pager_PC & AMASK; /* failing instr PC */
set_ac_display (ac_cur); /* set up AC display */
pcq_r->qptr = pcq_p; /* update pc q ptr */
if ((i = sim_process_event ())) /* error? stop sim */
ABORT (i);
if (fe_xct)
qintr = -1;
else
pi_eval (); /* eval pi system */
}
/* PI interrupt (Unibus or system flags).
On the KS10, only JSR and XPCW are allowed as interrupt instructions.
Because of exec mode addressing, and unconditional processing of flags,
they are explicitly emulated here. Note that the KS microcode does not
perform an EA calc on interrupt instructions, which this emulation does.
This is an implementation restriction of the KS. The KS does not restrict
the CONSOLE EXECUTE function which is merged into this path in SimH.
On a keep-alive failure, the console (fe) forces the CPU 'XCT' the
instruction at exec 71. This is close enough to an interrupt that it is
treated as one here. TOPS-10 and TOPS-20 use JSR or XPCW, which are
really the only sensible instructions, as diagnosing a KAF requires the
PC/FLAGS of the fault.
On a reload-request from the OS, the fe loads the bootstrap code and sets
saved_PC. Here, the CPU is partially reset and redirected. (Preserving
PC history, among other things.) The FE has already reset IO.
*/
if (qintr) {
int32 vec, uba;
pager_pi = TRUE; /* flag in pi seq */
if (fe_xct) { /* Console forced execute? */
qintr = 0;
if (fe_xct == 1) { /* Forced reload */
PC = saved_PC; /* Bootstrap PC */
pager_pi = FALSE;
ebr = ubr = 0; /* Exec mode, paging & PI off */
pag_reset (&pag_dev);
pi_on = pi_enb = pi_act= pi_prq =
apr_enb = apr_flg = apr_lvl = its_1pr = 0;
rlog = 0;
set_newflags (0, FALSE);
fe_xct = 0;
continue;
}
inst = ReadE(fe_xct); /* Exec address of instruction */
} else if ((vec = pi_ub_vec (qintr, &uba))) { /* Unibus interrupt? */
mb = ReadP (epta + EPT_UBIT + uba); /* get dispatch table */
if (mb == 0) /* invalid? stop */
ABORT (STOP_ZERINT);
inst = ReadE ((((a10) mb) + (vec / 4)) & AMASK);
if (inst == 0)
ABORT (STOP_ZERINT);
}
else inst = ReadP (epta + EPT_PIIT + (2 * qintr));
op = GET_OP (inst); /* get opcode */
ac = GET_AC (inst); /* get ac */
if (its_1pr && Q_ITS) { /* 1-proc set? */
flags = flags | F_1PR; /* store 1-proc */
its_1pr = 0; /* clear 1-proc */
}
if (op == OP_JSR) { /* JSR? */
d10 flpc = FLPC;
set_newflags (0, FALSE); /* set new flags */
ea = calc_ea (inst, MM_CUR); /* calc ea, cur mode */
WriteE (ea, flpc); /* save flags+PC, exec */
JUMP (INCA (ea)); /* PC = ea + 1 */
}
else if ((op == OP_JRST) && (ac == AC_XPCW)) { /* XPCW? */
d10 flz = XWD (flags, 0);
set_newflags (0, FALSE); /* set exec flags */
ea = calc_ea (inst, MM_CUR); /* calc ea, cur mode */
WriteE (ea, flz); /* write flags, exec */
WriteE (ADDA (ea, 1), PC); /* write PC, exec */
rs[0] = ReadE (ADDA (ea, 2)); /* read new flags */
rs[1] = ReadE (ADDA (ea, 3)); /* read new PC */
JUMP (rs[1]); /* set new PC */
set_newflags (rs[0], FALSE); /* set new flags */
}
else {
fe_xct = 0;
ABORT (STOP_ILLINT); /* invalid instr */
}
if (fe_xct)
fe_xct = 0;
else {
pi_act = pi_act | pi_l2bit[qintr]; /* set level active */
pi_eval (); /* eval pi system */
}
pager_pi = FALSE; /* end of sequence */
if (sim_interval) /* charge for instr */
sim_interval--;
continue;
} /* end if interrupt */
/* Traps fetch and execute an instruction from the current mode process table.
On the KS10, the fetch of the next instruction has started, and a page fail
trap on the instruction fetch takes precedence over the trap. During a trap,
flags are cleared before the execute, but if the execute aborts, they must
be restored. Also, the MUUO processor needs to know whether we are in a
trap sequence. Hence, trap in progress is recorded in pflgs, and the
traps for pager restoration are recorded in pager_flags.
*/
if (TSTF (F_T1 | F_T2) && PAGING) {
Read (pager_PC = PC, MM_CUR); /* test fetch */
pager_tc = TRUE; /* in a trap sequence */
pager_flags = flags; /* save flags */
ea = (TSTF (F_USR)? upta + UPT_TRBASE: epta + EPT_TRBASE)
+ GET_TRAPS (flags);
inst = ReadP (ea); /* get trap instr */
CLRF (F_T1 | F_T2); /* clear flags */
}
/* Test for instruction breakpoint */
else {
if (sim_brk_summ &&
sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */
ABORT (STOP_IBKPT); /* stop simulation */
}
/* Ready (at last) to get an instruction */
inst = Read (pager_PC = PC, MM_CUR); /* get instruction */
INCPC;
sim_interval = sim_interval - 1;
}
its_2pr = its_1pr; /* save 1-proc flag */
/* Execute instruction. XCT and PXCT also return here. */
XCT:
op = GET_OP (inst); /* get opcode */
ac = GET_AC (inst); /* get AC */
for (indrct = inst, i = 0; ; i++) { /* calc eff addr */
ea = GET_ADDR (indrct);
xr = GET_XR (indrct);
if (xr)
ea = (ea + ((a10) XR (xr, MM_EA))) & AMASK;
if (TST_IND (indrct)) { /* indirect? */
if (i != 0) { /* not first cycle? */
int32 t = test_int (); /* test for intr */
if (t != 0) /* err or intr? */
ABORT (t);
if ((ind_max != 0) && (i >= ind_max)) /* limit exceeded? */
ABORT (STOP_IND);
}
indrct = Read (ea, MM_EA); /* fetch indirect */
}
else break;
}
if (hst_lnt) { /* history enabled? */
hst_p = (hst_p + 1); /* next entry */
if (hst_p >= hst_lnt)
hst_p = 0;
hst[hst_p].pc = pager_PC | HIST_PC;
hst[hst_p].ea = ea;
hst[hst_p].ir = inst;
hst[hst_p].ac = AC(ac);
}
switch (op) { /* case on opcode */
/* UUO's (0000 - 0077) - checked against KS10 ucode */
case 0000: if (stop_op0) {
ABORT (STOP_ILLEG);
}
goto MUUO;
case 0001: /* local UUO's */
case 0002:
case 0003:
case 0004:
case 0005:
case 0006:
case 0007:
case 0010:
case 0011:
case 0012:
case 0013:
case 0014:
case 0015:
case 0016:
case 0017:
case 0020:
case 0021:
case 0022:
case 0023:
case 0024:
case 0025:
case 0026:
case 0027:
case 0030:
case 0031:
case 0032:
case 0033:
case 0034:
case 0035:
case 0036:
case 0037: Write (040, UUOWORD, MM_CUR); /* store op, ac, ea */
inst = Read (041, MM_CUR); /* get new instr */
goto XCT;
/* case 0040 - 0077: MUUO's, handled by default at end of case */
/* Floating point, bytes, multiple precision (0100 - 0177) */
/* case 0100: MUUO *//* UJEN */
/* case 0101: MUUO *//* unassigned */
case 0102: if (Q_ITS && !TSTF (F_USR)) { /* GFAD (KL), XCTRI (ITS) */
inst = Read (ea, MM_OPND);
pflgs = pflgs | ac;
goto XCT;
}
goto MUUO;
case 0103: if (Q_ITS && !TSTF (F_USR)) { /* GFSB (KL), XCTR (ITS) */
inst = Read (ea, MM_OPND);
pflgs = pflgs | ac;
goto XCT;
}
goto MUUO;
/* case 0104: MUUO *//* JSYS (T20) */
case 0105: AC(ac) = adjsp (AC(ac), ea); break; /* ADJSP */
/* case 0106: MUUO *//* GFMP (KL)*/
/* case 0107: MUUO *//* GFDV (KL) */
case 0110: RD2; dfad (ac, rs, 0); break; /* DFAD */
case 0111: RD2; dfad (ac, rs, 1); break; /* DFSB */
case 0112: RD2; dfmp (ac, rs); break; /* DFMP */
case 0113: RD2; dfdv (ac, rs); break; /* DFDV */
case 0114: RD2; dadd (ac, rs); break; /* DADD */
case 0115: RD2; dsub (ac, rs); break; /* DSUB */
case 0116: RD2; dmul (ac, rs); break; /* DMUL */
case 0117: RD2; ddiv (ac, rs); break; /* DDIV */
case 0120: RD2; S2AC; break; /* DMOVE */
case 0121: RD2; DMOVN (rs); S2AC; DMOVNF; break; /* DMOVN */
case 0122: RD; fix(ac, mb, 0); break; /* FIX */
case 0123: st = xtend (ac, ea, pflgs); /* EXTEND */
rlog = 0; /* clear log */
switch (st) {
case XT_SKIP:
INCPC;
case XT_NOSK:
break;
default:
goto MUUO;
}
break;
case 0124: G2AC; WR2; break; /* DMOVEM */
case 0125: G2AC; DMOVN (rs); WR2; DMOVNF; break; /* DMOVNM */
case 0126: RD; fix (ac, mb, 1); break; /* FIXR */
case 0127: RD; AC(ac) = fltr (mb); break; /* FLTR */
/* case 0130: MUUO *//* UFA */
/* case 0131: MUUO *//* DFN */
case 0132: AC(ac) = fsc (AC(ac), ea); break; /* FSC */
case 0133: if (!ac) ibp (ea, pflgs); /* IBP */
else adjbp (ac, ea, pflgs);
break;
case 0134: CIBP; LDB; CLRF (F_FPD); break; /* ILBP */
case 0135: LDB; break; /* LDB */
case 0136: CIBP; DPB; CLRF (F_FPD); break; /* IDBP */
case 0137: DPB; break; /* DPB */
case 0140: RD; AC(ac) = FAD (mb); break; /* FAD */
/* case 0141: MUUO *//* FADL */
case 0142: RM; mb = FAD (mb); WR; break; /* FADM */
case 0143: RM; AC(ac) = FAD (mb); WRAC; break; /* FADB */
case 0144: RD; AC(ac) = FADR (mb); break; /* FADR */
case 0145: AC(ac) = FADR (IMS); break; /* FADRI */
case 0146: RM; mb = FADR (mb); WR; break; /* FADRM */
case 0147: RM; AC(ac) = FADR (mb); WRAC; break; /* FADRB */
case 0150: RD; AC(ac) = FSB (mb); break; /* FSB */
/* case 0151: MUUO *//* FSBL */
case 0152: RM; mb = FSB (mb); WR; break; /* FSBM */
case 0153: RM; AC(ac) = FSB (mb); WRAC; break; /* FSBB */
case 0154: RD; AC(ac) = FSBR (mb); break; /* FSBR */
case 0155: AC(ac) = FSBR (IMS); break; /* FSBRI */
case 0156: RM; mb = FSBR (mb); WR; break; /* FSBRM */
case 0157: RM; AC(ac) = FSBR (mb); WRAC; break; /* FSBRB */
case 0160: RD; AC(ac) = FMP (mb); break; /* FMP */
/* case 0161: MUUO *//* FMPL */
case 0162: RM; mb = FMP (mb); WR; break; /* FMPM */
case 0163: RM; AC(ac) = FMP (mb); WRAC; break; /* FMPB */
case 0164: RD; AC(ac) = FMPR (mb); break; /* FMPR */
case 0165: AC(ac) = FMPR (IMS); break; /* FMPRI */