-
Notifications
You must be signed in to change notification settings - Fork 23
Expand file tree
/
Copy pathcpu_details.mac
More file actions
2146 lines (2145 loc) · 84.7 KB
/
cpu_details.mac
File metadata and controls
2146 lines (2145 loc) · 84.7 KB
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
; $Id: cpu_details.mac 1385 2023-03-23 08:27:44Z mueller $
; SPDX-License-Identifier: GPL-3.0-or-later
; Copyright 2022-2023 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
;
; Revision History:
; Date Rev Version Comment
; 2023-03-22 1385 1.1.3 add A3.6, verify PSW after vector push abort
; 2023-03-21 1384 1.1.2 remove e11 exemptions for A2.3, A2.5-9,
; A3.2 part 2+3; A3.3, A4.4 part 3+4;
; A4.4 part 5: skip on e11 (SPL in u mode handling)
; 2023-02-17 1374 1.1.1 use pushm,popm
; 2023-01-27 1359 1.1 use .mcall and mlib; use rt?jmp, hta??? macros
; 2023-01-11 1349 1.0 Initial version
; 2022-07-18 1259 0.1 First draft
;
; Test CPU details
; Section A: CPU registers
; Section B: stress and flow tests
; Section C: 11/70 specifics
;
.include |lib/tcode_std_base.mac|
.include |lib/defs_mmu.mac|
;
.mcall push,pop,push2,pushm,popm
.mcall hcmpeq,htsteq,htstne,htstge,hbiteq,hbitne
.mcall vecset,vecclr
.mcall rtijmp,rttjmp
.mcall htabuf,htaadd,htaini,htacmp
;
; Preface: set up MMU for kernel mode (for some tests) =======================
;
mov #kipdr,r0
mov #<127.*md.plf>!md.arw,r1 ; plf=127; ed=0(up); acf=6(w/r)
mov r1,(r0)+ ; kipdr0
mov r1,(r0)+ ; kipdr1
mov r1,(r0)+ ; kipdr2
mov r1,(r0)+ ; kipdr3
mov r1,(r0)+ ; kipdr4
mov r1,(r0)+ ; kipdr5
mov r1,(r0)+ ; kipdr6
mov r1,(r0)+ ; kipdr7
mov #kipar,r0
mov #000000,(r0)+ ; kipar0 000000 base
mov #000200,(r0)+ ; kipar1 020000 base
mov #000400,(r0)+ ; kipar2 040000 base
mov #000600,(r0)+ ; kipar3 060000 base
mov #001000,(r0)+ ; kipar4 100000 base
mov #001200,(r0)+ ; kipar5 120000 base
mov #001400,(r0)+ ; kipar6 140000 base
mov #177600,(r0)+ ; kipar7 (map I/O page)
;
; some useful definitions
kipdr5 = kipdr+12
kipdr6 = kipdr+14
kipar6 = kipar+14
p6base = <6*20000> ; page 6
;
; Section A: CPU registers ===================================================
; A1 PIRQ
; A1.1 PIRQ + spl
; A1.2 PIRQ and immediate interrupt
; A2 CPUERR
; A2.1 CPUERR cp.hlt
; A2.2 CPUERR cp.odd
; A2.3 CPUERR cp.nxm
; A2.4 CPUERR cp.iot
; A2.5 CPUERR cp.ysv
; A2.6 CPUERR cp.rsv
; A2.7 CPUERR cp.odd + stack error
; A2.8 CPUERR cp.nxm + stack error
; A2.9 CPUERR cp.ito + stack error
; A2.10 CPUERR mmu abort + stack error
; A3 STKLIM + stack traps and aborts
; A3.1 STKLIM write/read test
; A3.2 yellow trap + red abort boundary
; part 1: sequence of yellow traps and a final red stack abort
; part 2: check that red zone does not have yellow islands
; part 3: check red zone PSW protection
; A3.3 stack trap conditions
; part 1: test instructions that should trap
; part 2: test instructions that should not trap
; part 3: test that interrupt (from PIRQ) vector push traps
; A3.4 red stack abort conditions
; A3.5 vector push abort recovery - saved PS
; A3.6 vector push abort recovery - restored PSW
; A4 PSW + tbit traps
; A4.1 PSW direct write/read test
; part 1: all bits except register set (cp.ars)
; part 2: PSW(11) - register set
; part 3: PSW(cm) and stack registers
; A4.2 PSW write/read via RTI/RTT
; part 1: from cm=0,rset=0: set cm=11 and rset=1 (fine!)
; part 2: from cm=s,rset=1 mode: set cm=0 and rset=0 (fail!)
; part 3: from cm=s,rset=0 mode: set cm=u and rset=1 (fine!)
; part 4: from cm=u,rset=1 mode: set cm=0 and rset=0 (fail!)
; part 5: from cm=k,pri=0: set pri=6 (fine!)
; part 6: from cm=s,pri=0: set pri=6 (fail!)
; part 7: from cm=u,pri=0: set pri=6 (fail!)
; A4.3 RTI/RTT tbit basics
; part 1: tbit after RTI
; part 2: tbit after RTT
; A4.4 tbit trace tests
; part 0: traced TRAP that clears tbit
; part 1: simple instruction sequence
; part 2: tracing of trap instructions (EMT tested)
; part 3: tbit vs interrupt precedence (via PIRQ)
; part 4: traced WAIT and tbit
; part 5: WAIT and SPL in user mode
; part 6: tbit trap after continuation over s_idle
; part 7: no tbit trap after an abort
; part 8: traced RTI that clears tbit
; part 9: EMT that sets tbit
; part 10: PIRQ that sets tbit
; A5 MBRK
;
; Test A1: PIRQ +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; This sub-section verifies operation of PIRQ register
;
; Test A1.1 -- PIRQ + spl ++++++++++++++++++++++++++++++++++++++++++++
; This test will exercise all 7 pirq interrupt levels:
; set 1+3 -> handle 3, set 7
; -> handle 7, set 6+4
; -> handle 6
; -> handle 4, set 5+2
; -> handle 5
; -> handle 2
; -> handle 1
;
; some useful definitions
pi.r00=bit08 ; pir 0 bit
pi.r01=bit09 ; pir 1 bit
pi.r02=bit10 ; pir 2 bit
pi.r03=bit11 ; pir 3 bit
pi.r04=bit12 ; pir 4 bit
pi.r05=bit13 ; pir 5 bit
pi.r06=bit14 ; pir 6 bit
pi.r07=bit15 ; pir 7 bit
pi.n00=0. ; lsb for no pir pending
pi.n01=1*042 ; lsb for pir 1 next
pi.n02=2*042 ; lsb for pir 2 next
pi.n03=3*042 ; lsb for pir 3 next
pi.n04=4*042 ; lsb for pir 4 next
pi.n05=5*042 ; lsb for pir 5 next
pi.n06=6*042 ; lsb for pir 6 next
pi.n07=7*042 ; lsb for pir 7 next
;
ta0101: vecset v..pir,1000$,cp.pr7 ; set up PIRQ handler at pr7
mov #cp.pir,r3 ; ptr to PIRQ
mov #cp.psw,r4 ; ptr to PSW
mov #1200$,r5 ; ptr to check data
clr 1300$ ; clear nesting counter
;
spl 7 ; lockout interrupts
bisb #bit01,1(r3) ; set PIRQ 1
hcmpeq (r3),#<pi.r01!pi.n01> ; check set 1
bisb #bit03,1(r3) ; set PIRQ 3
hcmpeq (r3),#<pi.r01!pi.r03!pi.n03> ; check set 1+3
spl 2
nop ; allow interrupts to happen
spl 0
nop ; allow interrupts to happen
htsteq (r3) ; PIRQ should clear now
vecclr v..pir ; restore pirq vector catcher
jmp 9999$
;
; PIRQ interrupt handler
; - it starts at pr7 from the vector
; - quickly lowers the priority to what is currently processed
; - new pirq bits are set at lowered priority
; - that leads to nested interrupts (tracked by a level counter)
;
1000$: inc 1300$ ; up level counter
mov (r3),r0 ; get PIRQ value
hcmpeq 1300$,(r5)+ ; check nesting level
hcmpeq r0,(r5)+ ; check pirq value
movb r0,(r4) ; PSW=PIRQ (sets priority)
bic #177761,r0 ; mask out index bits
mov r0,r1 ; r0 is word index (pri*2)
asr r1 ; r1 is byte index (pri*1)
mov #pi.r00,r2
ash r1,r2 ; r2 = pi.r00 <<(pri)
bic r2,(r3) ; clear current level in pirq
bis 1100$(r0),(r3) ; trigger new pirqs
nop ; allow nested interrupts to happen
nop ;
dec 1300$ ; down level counter
rti
;
; table with new pirqs triggered at a level
1100$: .word 0 ; new pirq @ level 0
.word 0 ; new pirq @ level 1
.word 0 ; new pirq @ level 2
.word pi.r07 ; new pirq @ level 3 -> 7
.word pi.r05!pi.r02 ; new pirq @ level 4 -> 5+2
.word 0 ; new pirq @ level 5
.word 0 ; new pirq @ level 6
.word pi.r06!pi.r04 ; new pirq @ level 7 -> 6+4
;
; table with expected values of pirq register in interrupt sequence
1200$: .word 1,pi.r01!pi.r03!pi.n03 ; set 1+3 -> handle 3, set 7
.word 2,pi.r01!pi.r07!pi.n07 ; set 1+7 -> handle 7, set 6+4
.word 2,pi.r01!pi.r04!pi.r06!pi.n06 ; set 1+4+6 -> handle 6
.word 2,pi.r01!pi.r04!pi.n04 ; set 1+4 -> handle 4, set 5+2
.word 3,pi.r01!pi.r02!pi.r05!pi.n05 ; set 1+2+5 -> handle 5
.word 1,pi.r01!pi.r02!pi.n02 ; set 1+2 -> handle 2
.word 1,pi.r01!pi.n01 ; set 1 -> handle 1
; nesting level counter
1300$: .word 0
;
9999$: iot ; end of test A1.1
;
; Test A1.2 -- PIRQ and immediate interrupt ++++++++++++++++++++++++++
; This test verifies that an interrupt is taken immediately after the
; write of the PIRQ register
;
ta0102: spl 0 ; ensure execution at PR0
vecset v..pir,1000$,cp.pr7 ; set up PIRQ handler at pr7
mov #pi.r03,cp.pir ; request PIRQ 3
halt ; halt if not taken immediatly
;
1000$: clr cp.pir ; cancel all PIRQ levels
mov #1100$,(sp) ; continue
rti
;
1100$: vecclr v..pir ; restore pirq vector catcher
;
9999$: iot ; end of test A1.2
;
; Test A2: CPUERR +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; This sub-section verifies operation of CPUERR register
;
; setup for all A2.* tests
mov #cp.err,r0 ; ptr tp CPUERR
vecset v..iit,vhugen ; set iit handler at pr0
;
; Test A2.1 -- CPUERR cp.hlt +++++++++++++++++++++++++++++++++++++++++
; Test cp.hlt: halt in non-kernel mode
;
ta0201: mov #177777,(r0) ; clear CPUERR (any write should)
htsteq (r0) ; ensure that CPUERR is zero
;
mov #4000$,r2 ; mode list (user,supervisor)
mov #2,r3 ; number of modes
;
1000$: clr r1 ; clear tracer
mov #3000$,vhustp ; continuation address
push2 (r2)+,#2000$ ; frame: psw,address
rti ; start user mode code
halt
;
2000$: inc r1 ; proof of execution
halt ; that will abort
inc r1
tst @#001 ; that must abort
;
3000$: hcmpeq r1,#1 ; check tracer
hcmpeq (r0),#cp.hlt ; check CPUERR
mov #cp.rsv,(r0) ; clear CPUERR (any write should)
htsteq (r0) ; check CPUERR
;
sob r3,1000$ ; go for next mode
;
br 9999$
;
4000$: .word <cp.cmu!cp.pmu> ; user mode
.word <cp.cms!cp.pms> ; supervisor mode
;
9999$: iot ; end of test A2.1
;
; Test A2.2 -- CPUERR cp.odd +++++++++++++++++++++++++++++++++++++++++
; Test cp.odd: odd address error abort
;
ta0202: mov #1000$,vhustp ; continuation address
tst @#001 ; odd address access
halt
1000$: hcmpeq (r0),#cp.odd ; check CPUERR
clr (r0) ; clear CPUERR (any write should)
htsteq (r0) ; check CPUERR
;
9999$: iot ; end of test A2.2
;
; Test A2.3 -- CPUERR cp.nxm +++++++++++++++++++++++++++++++++++++++++
; Test cp.nxm: non-existent memory abort
; Use unibus map address space (248kB) below the I/O page, the w11
; will return a non-existent memory abort even in a maximum memory
; configuration.
;
ta0203: push kipar6 ; save kipar6
mov #177400,kipar6
mov #m3.e22,mmr3 ; 22-bit mode
mov #m0.ena,mmr0 ; enable mmu ;! MMU 22
;
mov #1000$,vhustp ; continuation address
tst p6base ; access non-existing memory
halt
1000$: hcmpeq (r0),#cp.nxm ; check CPUERR
com (r0) ; clear CPUERR (any write should)
htsteq (r0) ; check CPUERR
;
reset ; disable mmu ;! MMU off
pop kipar6 ; restore kipar6
9999$: iot ; end of test A2.3
;
; Test A2.4 -- CPUERR cp.ito +++++++++++++++++++++++++++++++++++++++++
; Test cp.ito: unibus timeout abort
; Use first address in I/O page (160000), always unused in w11
;
ta0204: mov #1000$,vhustp ; continuation address
tst @#160000 ; access non-existing unibus device
halt
1000$: hcmpeq (r0),#cp.ito ; check CPUERR
clr (r0) ; clear CPUERR (any write should)
htsteq (r0) ; check CPUERR
;
9999$: iot ; end of test A2.4
;
; Test A2.5 -- CPUERR cp.ysv +++++++++++++++++++++++++++++++++++++++++
; Test cp.ysv: yellow stack trap
; Since stack is still usable after the trap, the vhugen handler can be used.
;
ta0205: mov #1000$,vhustp ; continuation address
mov #400,sp
clr -(sp) ; should trap (not abort)
halt ; not executed, handler continues at 1000$
1000$: hcmpeq (r0),#cp.ysv ; check CPUERR
clr (r0) ; clear CPUERR (any write should)
htsteq (r0) ; check CPUERR
;
mov #stack,sp
9999$: iot ; end of test A2.5
;
; Test A2.6 -- CPUERR cp.rsv +++++++++++++++++++++++++++++++++++++++++
; Test cp.rsv: red stack trap - simple low stack case
;
ta0206: mov #1000$,v..iit ; setup direct iit handler
mov #340,sp
clr -(sp) ; should abort (not trap)
halt
1000$: htsteq sp ; check SP=0
hcmpeq (r0),#cp.rsv ; check CPUERR
clr (r0) ; clear CPUERR (any write should)
htsteq (r0) ; check CPUERR
mov #stack,sp ; restore stack
;
9999$: iot ; end of test A2.6
;
; Test A2.7 -- CPUERR cp.odd + stack error +++++++++++++++++++++++++++
; Test cp.odd: fatal stack error after odd stack
;
ta0207: cmpb systyp,#sy.sih ; SimH uses J11 behavior
bne 100$
mov #<cp.rsv+cp.odd>,1010$+2 ; and sets rsv for all stack errors
;
100$: mov #1000$,v..iit ; setup direct iit handler
mov #stack-1,sp
clr -(sp) ; odd-address abort, fatal stack error
halt
1000$: htsteq sp ; check SP=0
1010$: hcmpeq (r0),#cp.odd ; check CPUERR
clr (r0) ; clear CPUERR (any write should)
htsteq (r0) ; check CPUERR
mov #stack,sp ; restore stack
;
9999$: iot ; end of test A2.7
;
; Test A2.8 -- CPUERR cp.nxm + stack error +++++++++++++++++++++++++++
; Test cp.nxm: fatal stack error after non-existent memory abort
; Setup like in A2.3, put stack at p6base+4
;
ta0208: cmpb systyp,#sy.sih ; SimH uses J11 behavior
bne 100$
mov #<cp.rsv+cp.nxm>,1010$+2 ; and sets rsv for all stack errors
;
100$: mov #1000$,v..iit ; setup direct iit handler
mov #177400,kipar6
mov #m3.e22,mmr3 ; 22-bit mode
mov #m0.ena,mmr0 ; enable mmu ;! MMU 22
;
mov #p6base+4,sp ; stack in non-existing memory
clr -(sp) ; non-existing memory, fatal stack error
halt
1000$: htsteq sp ; check SP=0
1010$: hcmpeq (r0),#cp.nxm ; check CPUERR
clr (r0) ; clear CPUERR (any write should)
htsteq (r0) ; check CPUERR
mov #stack,sp ; restore stack
;
reset ;! MMU off
mov #001400,kipar6 ; restore kipar6
;
9999$: iot ; end of test A2.8
;
; Test A2.9 -- CPUERR cp.ito + stack error +++++++++++++++++++++++++++
; Test cp.ito: fatal stack error after unibus timeout
; Setup like in A2.4, put stack at 160004
;
ta0209: cmpb systyp,#sy.sih ; SimH uses J11 behavior
bne 100$
mov #<cp.rsv+cp.ito>,1010$+2 ; and sets rsv for all stack errors
;
100$: mov #1000$,v..iit ; setup direct iit handler
mov #160004,sp ; stack at non-existing unibus device
clr -(sp) ; non-existing memory, fatal stack error
halt
1000$: htsteq sp ; check SP=0
1010$: hcmpeq (r0),#cp.ito ; check CPUERR
clr (r0) ; clear CPUERR (any write should)
htsteq (r0) ; check CPUERR
mov #stack,sp ; restore stack
;
9999$: iot ; end of test A2.9
;
; Test A2.10 -- CPUERR mmu abort + stack error +++++++++++++++++++++++
; Test cp.rsv: fatal stack error after mmu abort
; Set kernel I page 6 to non-resident
;
ta0210: cmpb systyp,#sy.sih ; SimH uses J11 behavior
bne 100$
mov #cp.rsv,1010$+2 ; and sets rsv for all stack errors
;
100$: mov #1000$,v..iit ; setup direct iit handler
clr kipdr6 ; set non-resident
mov #m3.e22,mmr3 ; 22-bit mode
mov #m0.ena,mmr0 ; enable mmu ;! MMU 22
;
mov #p6base+4,sp ; stack in non-resident memory
clr -(sp) ; MMU abort, fatal stack error
halt
1000$: htsteq sp ; check SP=0
1010$: hcmpeq (r0),#0 ; check CPUERR (none set on w11)
clr (r0) ; clear CPUERR (any write should)
htsteq (r0) ; check CPUERR
mov #stack,sp ; restore stack
;
reset ;! MMU off
mov kipdr5,kipdr6 ; restore kipdr6 (default kipdr are identical)
;
9999$: iot ; end of test A2.10
;
; -----------------------------------------------
; end of A2.* tests, restore iit handler
vecclr v..iit ; restore iit catcher
;
; Test A3: STKLIM + stack traps and aborts ++++++++++++++++++++++++++++++++++
; This sub-section verifies operation of STKLIM register,
; the yellow stack trap, and the red stack abort functionality.
;
; Test A3.1 -- STKLIM write/read test ++++++++++++++++++++++++++++++++
; STKLIM is a 16 bit register, upper byte is retained, lower reads always 0
;
ta0301:
;
; part 1: word access ------------------------------------------------
;
mov #1000$,r0 ; ptr to value list
mov #<1010$-1000$>/2,r1 ; # of values
mov #377,r2 ; LSB byte mask
mov #cp.slr,r3 ; ptr to STKLIM
;
100$: mov (r0)+,r4 ; get value
mov r4,(r3) ; load STKLIM
bic r2,r4 ; clear LSB
hcmpeq r4,(r3) ; read and ckeck STKLIM
sob r1,100$ ; go for next STKLIM value
br 2000$
;
1000$: .word ^b0101010101010101
.word ^b1010101010101010
.word ^b0000000011001100 ; STKLIM = 0 at end of test
1010$:
;
; part 2: byte access ------------------------------------------------
;
2000$: movb #7,1(r3) ; write MSB
hcmpeq #3400,(r3) ; check MSB written
movb #70,(r3) ; write LSB
hcmpeq #3400,(r3) ; check MSB unchanged
clr (r3) ; STKLIM to default
;
9999$: iot ; end of test A3.1
;
; Test A3.2 -- yellow trap + red abort boundary ++++++++++++++++++++++
;
ta0302:
;
; part 1: sequence of yellow traps and a final red stack abort -------
; Verifies that push to STKLIM+376 to STKLIM+344 causes a yellow stack
; trap and a push to STKLIM+342 succeeds, but the yellow stack trap flow
; fails and causes a red stack trap. Done for
; 0 yellow below 000400
; 1400 yellow below 002000
; 157400 yellow below 156000
;
; Note: SimH has simplified stack limit testing in vector flows.
; The stack is checked at end of flow. SimH will happily
; do yellow trap after push to +342 and write into +336.
; This part is therefore skipped for SimH
;
cmpb systyp,#sy.sih ; on SimH ?
bne 10$ ; if not, execute
jmp 2000$ ; if yes, skip
;
10$: mov #1200$,r0 ; ptr to value list
mov #<1210$-1200$>/2,r1 ; # of values
vecset v..iit,1000$,cp.pr3 ; set up iit handler, pr3 as signature
;
100$: spl 6 ; use pr6 as code signature
mov (r0)+,r5 ; get value
mov r5,cp.slr ; load STKLIM
clr 336(r5) ; clear word on red boundary
mov r5,sp ; load SP
add #400,sp ; to yellow boundary
clr r2 ; clear yellow trap counter
mov #1.,-(sp) ; push to STKLIM+376 -> trap
mov #2.,-(sp) ; push to STKLIM+374 -> trap
mov #3.,-(sp) ; push to STKLIM+372 -> trap
mov #4.,-(sp) ; push to STKLIM+370 -> trap
mov #5.,-(sp) ; push to STKLIM+366 -> trap
mov #6.,-(sp) ; push to STKLIM+364 -> trap
mov #7.,-(sp) ; push to STKLIM+362 -> trap
mov #8.,-(sp) ; push to STKLIM+360 -> trap
mov #9.,-(sp) ; push to STKLIM+356 -> trap
mov #10.,-(sp) ; push to STKLIM+354 -> trap
mov #11.,-(sp) ; push to STKLIM+352 -> trap
mov #12.,-(sp) ; push to STKLIM+350 -> trap
mov #13.,-(sp) ; push to STKLIM+346 -> trap
mov #14.,-(sp) ; push to STKLIM+344 -> trap
mov #15.,-(sp) ; push to STKLIM+342 -> try trap->abort
200$: halt
halt
;
1000$: tst sp ; red abort seen ?
beq 1010$ ; if yes, check status
inc r2 ; if no, got for next push
rti
;
1010$: hcmpeq #14.,r2 ; all traps taken ?
hcmpeq #13.,346(r5) ; check 13th push
hcmpeq #14.,344(r5) ; check 14th push
hcmpeq #15.,342(r5) ; check 15th push (was done)
hcmpeq #cp.pr6,340(r5) ; saved PS of attempted yellow trap
htsteq 336(r5) ; red zone border clean ?
hcmpeq #cp.pr6,@#2 ; saved PS of red abort
hcmpeq #200$,@#0 ; saved PC of red abort
dec r1 ; too far for sob
beq 1020$
jmp 100$ ; go for next STKLIM value
;
1020$: clr cp.slr ; STKLIM to default
mov #stack,sp ; SP to default
vecclr v..iit ; v..iit to catcher
spl 0 ; prio to default
br 2000$
;
1200$: .word 000000
.word 001400
.word 157400
1210$:
;
; part 2: check that red zone does not have yellow islands -----------
;
2000$: mov #2300$,r0 ; ptr to values
mov #<2310$-2300$>/2,r1 ; # of values
vecset v..iit,2200$ ; set up iit handler
mov #1400,cp.slr ; set yellow limit to 1776
;
2100$: mov (r0)+,sp ; set SP to test value
clr -(sp) ; expect red abort, not yellow trap
halt
;
2200$: htsteq sp ; check SP=0
sob r1,2100$
;
clr cp.slr ; STKLIM to default
mov #stack,sp ; SP to default
vecclr v..iit ; v..iit to catcher
br 3000$
;
2300$: .word 001400 ; probe 1376 (possible yellow mirror)
.word 001340 ; probe 1336
.word 001000 ; probe 0776 (possible yellow mirror)
.word 000400 ; probe 0376 (possible yellow mirror)
2310$:
;
; part 3: check red zone PSW protection ------------------------------
; push to 177776 should also cause a red stack abort
; w11 and e11 implement this, SimH doesnt
;
3000$: cmpb systyp,#sy.sih ; skip on SimH
beq 9999$
;
mov #1400,cp.slr ; set STKLIM
mov #1300,sp ; SP deep in red zone
vecset v..iit,3100$ ; set up iit handler
clr -(sp) ; expect red abort
halt
3100$: htsteq sp ; check SP=0, on emergency stack
vecset v..iit,3200$ ; set up iit handler
clr -(sp) ; expect red abort again
halt
3200$: htsteq sp ; check SP=0 because of PSW protection
clr cp.slr ; STKLIM to default
mov #stack,sp ; SP to default
vecclr v..iit ; v..iit to catcher
;
9999$: iot ; end of test A3.2
;
; Test A3.3 -- stack trap conditions +++++++++++++++++++++++++++++++++
; Verifies that mode 1,2,4,6 trap for dstw flows and dstr when rmw
; Verifies that mode 3,5,7 writes do not trap
; Verifies that mode 1-7 reads do not trap
; Verifies that implict pushes (JSR,MFPI) trap
; Verifies that vector push of trap instructions (EMT,TRAP tested) traps
; Verifies that vector push of an interrupt (PIRQ tested) traps
; Notes:
; - dstw (mov,clr,..) and dstr (add,bis,...) flows write to stack -> test both
; - inspired by eqkce0 test 041 that verifies do/dont trap instruction cases
; - SimH currently does not support full 11/70 mode behaviour
;
ta0303: cmpb systyp,#sy.sih ; skip on SimH
bne 100$
jmp 9999$
;
100$: mov #1400,cp.slr ; set yellow limit to 1776
;
; part 1: test instructions that should trap -------------------------
;
vecset v..iit,1000$ ; set up iit handler
vecset v..emt,1100$ ; set up emt handler
vecset v..trp,1200$ ; set up trap handler
clr r2 ; clear trap counter
;
; dstw mode 1,2,4,6
mov #1000,-(sp) ; dstw mode 4: SP now 1776 (1)
clr -(sp) ; dstw mode 4: SP now 1774 (2)
mov (sp),(sp) ; dstw mode 1: SP now 1774 (3)
clr (sp) ; dstw mode 1: SP now 1774 (4)
mov (sp),(sp)+ ; dstw mode 2: SP now 1776 (5)
clr 0(sp) ; dstw mode 6: SP now 1776 (6)
mov (sp),0(sp) ; dstw mode 6: SP now 1776 (7)
; implied push
jsr pc,1300$ ; implied push: SP now 1176 (8)
mfpi r0 ; implied push: SP now 1774 (9)
; trap instrunctions
emt 100 ; trap push: SP now 1174 (10)
trap 200 ; trap push: SP now 1174 (11)
; dstr mode 1,2,4,6 when rmw
add (sp),(sp) ; dstr mode 1: SP now 1174 (12)
bis (sp),-(sp) ; dstr mode 4: SP now 1172 (13)
incb (sp)+ ; dstr mode 2: SP now 1174 (14)
dec 0(sp) ; dstr mode 6: SP now 1174 (15)
;
br 1500$
;
1000$: htstne sp ; no red stack aborts expected
inc r2
rti
;
1100$: rti ; dummy emt handler
1200$: rti ; dummy trap handler
1300$: rts pc ; dummy routine
;
1500$: hcmpeq #15.,r2 ; all traps taken ?
vecclr v..iit ; v..iit to catcher
vecclr v..emt ; v..emt to catcher
vecclr v..trp ; v..trp to catcher
;
; part 2: test instructions that should not trap ---------------------
;
2000$: mov #stack-2,r2 ; in yellow zone
mov r2,(r2) ; load on stack (not using SP)
mov r2,sp ; SP in yellow zone
; dstw mode 3,5,7
mov (sp)+,@-(sp) ; dstw mode 5: SP now 1176
mov @(sp),@(sp)+ ; dstw mode 3: SP now 1200
mov -(sp),@(sp) ; dstw mode 7: SP now 1176
; dstr mode 3,5,7 when rmw
bis (sp)+,@-(sp) ; dstw mode 5: SP now 1176
bis @(sp),@(sp)+ ; dstw mode 3: SP now 1200
bis -(sp),@(sp) ; dstw mode 7: SP now 1176
; dstr mode 1,2,4,6 in read-only
tst (sp) ; dstr mode 1: SP now 1176
cmp (sp),-(sp) ; dstr mode 4: SP now 1174
cmp (sp),(sp)+ ; dstr mode 2: SP now 1176
cmp (sp),0(sp) ; dstr mode 6: SP now 1176
; dstr mode 3,5,7 in read-only
cmp (sp),@(sp)+ ; dstr mode 3: SP now 1200
cmp (sp),@-(sp) ; dstr mode 5: SP now 1176
cmp (sp),@(sp) ; dstr mode 7: SP now 1176
; check that EA is compared against STKLIM
clr sp
mov @#2000,2000(sp) ; SP=0, EA=2000 -> no trap
;
; part 3: test that interrupt (from PIRQ) vector push traps ----------
; Triggers 3 PIRQ interrupts at PR1, PR3, and PR6.
; The PIRQ interrupt vector push will issue a ysv trap.
; That trap executes before the first instruction of the pir handler.
; The iit handler must therefore execute at PR7 to lockout interrupts.
; When the iit handler returns, the pir hander will execute.
;
3000$: vecset v..iit,3100$,cp.pr7 ; set up iit handler, lockout interrupts
vecset v..pir,3200$,cp.pr7 ; set up pir handler, lockout interrupts
mov #stack,sp ; SP to default (STKLIM still 1400)
clr r2 ; clear trap counter
mov #cp.pir,r3 ; ptr to cp.pir
mov #3500$,r5 ; ptr to probe data
;
spl 0
movb #bit06!bit03!bit01,1(r3) ; request PIRQ 6+3+1
nop
br 3900$
;
; iit handler
3100$: htstne sp ; no red stack aborts expected
hcmpeq #177777,(r5)+ ; check state
inc r2
rti
;
; pir handler
3200$: mov (r3),r0 ; get PIRQ
bic #177761,r0 ; mask out index bits (is pri*2)
asr r0 ; now pri*1
hcmpeq r0,(r5)+ ; check state
mov #pi.r00,r1
ash r0,r1 ; pi.r00 <<(pri)
bic r1,(r3) ; clear PIRQ request
rti
;
; state check data
3500$: .word 177777,6. ; iit marker + pr6 pirq
.word 177777,3. ; iit marker + pr3 pirq
.word 177777,1. ; iit marker + pr1 pirq
;
3900$: hcmpeq #3.,r2 ; all traps taken ?
vecclr v..iit ; v..iit to catcher
vecclr v..pir ; v..pir to catcher
;
; final cleanup
clr cp.slr ; STKLIM to default
mov #stack,sp ; SP to default
;
9999$: iot ; end of test A3.3
;
; Test A3.4 -- red stack abort conditions ++++++++++++++++++++++++++++
; Verifies that instruction writes abort
; Verifies that implict pushes (JSR,MFPI) abort
; Verifies that vector push after trap instructions and interrupts abort
; Abort on 1st and 2nd push is tested.
;
ta0304: vecset v..iit,1000$,cp.pr7 ; set up iit handler, lockout interrupts
mov #1400,cp.slr ; yellow <=1776 and red <= 1736
clr @#1736 ; ensure top red word zero
clr cp.err ; clear CPUERR
;
; dstw flow
mov #1740,sp ; SP at red border
mov #100$,r5
mov #123456,-(sp)
halt
;
; dstr flow (rmw)
100$: mov #200$,r5
add (sp),-(sp)
halt
;
; implicit push instructions
200$: mov #300$,r5
jsr pc,210$
halt
210$: halt
;
300$: mov #400$,r5
mfpi r0
halt
;
; vector flow abort in 2nd push, 1st push in yellow (use EMT for test)
; Note: SimH scribbles into red zone, therefore test skipped for SimH
400$: cmpb systyp,#sy.sih ; skip section on SimH
beq 500$
mov sp,r0
mov #123456,(r0)+ ; write marker to 1740, r0 to avoid ysv
mov r0,sp ; SP now 1402 -> abort on 2nd push
mov #cp.pr3,cp.psw ; set pr3 as marker
mov #420$,r5 ; leaves NZVC = 0000
emt 100
410$: halt
420$: hcmpeq #cp.pr3,@#1740 ; check that PS written
;
; vector flow abort in 1st push (use PIRQ for test)
500$: spl 0
mov #600$,r5
mov #pi.r04,cp.pir ; request PIRQ 4
halt
600$: clr cp.pir
br 9000$
;
1000$: htsteq sp ; check SP=0
htsteq @#1736 ; check stack clean
hcmpeq #cp.rsv,cp.err ; check CPUERR.rsv (and no ysv)
clr cp.err ; clear CPUERR
mov #1740,sp ; restore SP
jmp (r5) ; continue
;
9000$: clr cp.slr ; STKLIM to default
vecclr v..iit ; v..iit to catcher
mov #stack,sp ; SP to default
spl 0 ; back to PR0
;
9999$: iot ; end of test A3.4
;
; Test A3.5 -- vector push abort recovery - saved PS +++++++++++++++++
; Verify that the frame pushed to the emergency stack after a vector push
; abort has the PS and PC values at entry into the initial vector flow and
; not the values read in the vector fetch of the failed vector flow.
; Test abort on 2nd and 1st push after a TRAP instruction.
; Skipped on SimH that has different vector flow stack limit check logic.
; See also cpu_mmu tests C2.5,C2.6, they check vector push abort by mmu.
;
ta0305: cmpb systyp,#sy.sih ; skip on SimH (different stklim logic)
beq 9999$
;
vecset v..iit,200$,cp.pr5!cp0z0c ; set up iit handler, PR5+0Z0C as sig
vecset v..trp,110$,cp.pr6!cpn0v0 ; set up TRAP handler,PR6+N0V0 as sig
mov #1400,cp.slr ; yellow <=1776 and red <= 1736
;
; on abort 2nd push ------------------------------
mov #1742,sp ; 2nd push will fail
spl 3 ; use PR3 as signature code
ccc ; clear all ccs
trap 100 ; will fail
100$: halt ; label after trap
110$: halt ; trap catcher
;
200$: htsteq sp ; check emergency stack done
hcmpeq (sp),#100$ ; PC: return after trap
hcmpeq 2(sp),#cp.pr3 ; PS: should be code signature
;
; on abort 1st push ------------------------------
mov #400$,v..iit ; set up iit handler
mov #1740,sp ; 1st push will fail
spl 4 ; use PR4 as signature code
ccc ; clear all ccs
sec ; and set C
trap 200 ; will fail
300$: halt
;
400$: htsteq sp ; check emergency stack done
hcmpeq (sp),#300$ ; PC: return after trap
hcmpeq 2(sp),#cp.pr4!cp000c ; PS: should be code signature
;
; trap without error -----------------------------
clr cp.slr ; STKLIM to default
mov #600$,v..trp ; set up TRAP handler (continuation)
mov #stack,sp ; SP to default
spl 2 ; use PR2 as signature code
ccc ; clear all ccs
sez ; and set z
trap 300 ; will work
500$: halt
;
600$: hcmpeq #stack-4,sp ; check stack, 1 frame
hcmpeq (sp),#500$ ; PC: return after trap
hcmpeq 2(sp),#cp.pr2!cp0z00 ; PS: should be code signature
;
; restore
vecclr v..iit ; v..iit to catcher
vecclr v..trp ; v..trp to catcher
mov #stack,sp ; SP to default
spl 0 ; back to PR0
;
9999$: iot ; end of test A3.5
;
; Test A3.6 -- vector push abort recovery - restored PSW +++++++++++++
; Verify that the PSW is restored when a vector flow is aborted during a push.
; The previous test A3.5 checks that the correct PS is saved on stack. This
; test verifies that the PSW is restored before the new vector is fetched.
; This affects the previous mode bits because they are taken from the PSW
; at the time the new PS is fetched. To test this, PIRQ is set up with a
; handler in supervisor space and an odd SP value. That will cause a vector 4
; abort during first push. A PIRQ is requested from kernel mode. The PSW
; seen by the vector 4 handler should see a previous mode of kernel, and not
; supervisor.
; See also cpu_mmu tests C2.5,C2.6, they check vector push abort by mmu.
;
ta0306: vecset v..pir,200$,cp.cms!cp.pr6 ; set up PIRQ handler
vecset v..iit,300$,cp.pr5 ; set up iit handler
;
mov #cp.pms,cp.psw ; supervisor now previous mode
push #1777 ; use odd address
mtpi sp ; for supervisor stack
mov #cp.pr1,cp.psw ; code signature PR1, back to kernel
movb #bit04,cp.pir+1 ; request PIRQ 4
100$: halt
200$: halt ; PIRQ handler, should not be called
;
300$: hcmpeq #cp.pr5,cp.psw ; CM=PM=kernel
hcmpeq #stack-4,sp ; 1 frame pushed
hcmpeq #100$,(sp) ; saved PC
hcmpeq #cp.pr1,2(sp) ; saved PC
;
; restore
vecclr v..pir ; v..pir to catcher
vecclr v..iit ; v..iit to catcher
mov #stack,sp ; SP to default
clr cp.pir ; cancel PIRQ
clr cp.psw ; back to kernel PR0
;
9999$: iot ; end of test A3.6
; Test A4: PSW + tbit traps +++++++++++++++++++++++++++++++++++++++++++++++++
; This sub-section verifies operation of PSW register and tbit traps.
;
; Test A4.1 -- PSW direct write/read test ++++++++++++++++++++++++++++
;
ta0401:
;
; part 1: all bits except register set (cp.ars) ----------------------
; Note: In a direct PSW write the cc of the write prevail.
; This part tests dstw flow via MOV. Part 4 will test dstr flow.
;
mov #cp.psw,r0 ; ptr to PSW
mov #200$,r1 ; ptr to data
mov #cpnzvc,r2 ; NZVC mask
100$: mov (r1)+,r3 ; next value
beq 2000$ ; if 0 end of test
mov r3,(r0) ; write PSW
cmp (r0),(r1)+ ; check PSW
beq 100$
clr (r0) ; if error force kernel
halt ; and halt
;
200$: .word cp.c,cp.c ; C cc
.word cp.v,cp.v ; V cc
.word cp.z,cp.z ; Z cc
.word cp.n,cp.n ; N cc
.word cp.t,0 ; tbit (not direct writable)
.word cp.pr7,cp.pr7 ; prio bits
.word bit10!bit09!bit08,0 ; bit 10:8 unused
.word bit12,bit12 ; pm(0)
.word bit13,bit13 ; pm(1)
.word bit14,bit14 ; cm(0)
.word bit15,bit15 ; cm(1)
.word 0
;
; part 2: PSW(11) - register set -------------------------------------
;
2000$: clr cp.psw ; select set 0
mov #1000,r0 ; write to set 0
mov #1001,r1
mov #1002,r2
mov #1003,r3
mov #1004,r4
mov #1005,r5
mov #cp.ars,cp.psw ; select set 1
hbitne #cp.ars,cp.psw ; check PSW write
mov #1010,r0 ; write to set 1
mov #1011,r1
mov #1012,r2
mov #1013,r3
mov #1014,r4
mov #1015,r5
clr cp.psw ; select set 0
hbiteq #cp.ars,cp.psw ; check PSW write
hcmpeq #1000,r0 ; check set 0
hcmpeq #1001,r1
hcmpeq #1002,r2
hcmpeq #1003,r3
hcmpeq #1004,r4
hcmpeq #1005,r5
mov #cp.ars,cp.psw ; select set 1
hcmpeq #1010,r0 ; check set 0
hcmpeq #1011,r1
hcmpeq #1012,r2
hcmpeq #1013,r3
hcmpeq #1014,r4
hcmpeq #1015,r5
clr cp.psw ; select set 0
;
; part 3: PSW(cm) and stack registers --------------------------------
;
mov #cp.psw,r0 ; ptr to PSW
clr (r0) ; cm=k
mov #0006,sp
mov #cp.cms,(r0) ; cm=s
mov #0106,sp
mov #cp.cmu,(r0) ; cm=u
mov #1106,sp
clr (r0) ; cm=k
hcmpeq #0006,sp ; check
mov #cp.cms,(r0) ; cm=s
mov sp,r1
mov #cp.cmu,(r0) ; cm=u
mov sp,r2
clr (r0) ; cm=k
hcmpeq #0106,r1 ; check in kernel to allow halt
hcmpeq #1106,r2 ; check in kernel to allow halt
;
clr (r0)
mov #stack,sp
;