-
Notifications
You must be signed in to change notification settings - Fork 41
/
control.c
7371 lines (6062 loc) · 265 KB
/
control.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
/* CONTROL.C (c) Copyright Roger Bowler, 1994-2010 */
/* ESA/390 CPU Emulator */
/* Interpretive Execution - (c) Copyright Jan Jaeger, 1999-2009 */
/* z/Architecture support - (c) Copyright Jan Jaeger, 1999-2009 */
/*-------------------------------------------------------------------*/
/* This module implements all control instructions of the */
/* S/370 and ESA/390 architectures, as described in the manuals */
/* GA22-7000-03 System/370 Principles of Operation */
/* SA22-7201-06 ESA/390 Principles of Operation */
/*-------------------------------------------------------------------*/
/*-------------------------------------------------------------------*/
/* Additional credits: */
/* Bad frame support by Jan Jaeger */
/* Branch tracing by Jan Jaeger */
/* CSP instructions by Jan Jaeger */
/* Instruction decode by macros - Jan Jaeger */
/* Prevent TOD from going backwards in time - Jan Jaeger */
/* Instruction decode rework - Jan Jaeger */
/* PR may lose pending interrupts - Jan Jaeger */
/* Modifications for Interpretive Execution (SIE) by Jan Jaeger */
/* ESAME low-address protection - Roger Bowler */
/* ESAME linkage stack operations - Roger Bowler */
/* ESAME BSA instruction - Roger Bowler v209c*/
/* ASN-and-LX-reuse facility - Roger Bowler June 2004*/
/* SIGP orders 11,12.2,13,15 - Fish Oct 2005*/
/* Configuration topology facility fixes by PaoloG Oct 2013*/
/*-------------------------------------------------------------------*/
#include "hstdinc.h"
#if !defined(_HENGINE_DLL_)
#define _HENGINE_DLL_
#endif
#if !defined(_CONTROL_C_)
#define _CONTROL_C_
#endif
#include "hercules.h"
#include "opcode.h"
#include "inline.h"
#if defined(OPTION_FISHIO)
#include "w32chan.h"
#endif // defined(OPTION_FISHIO)
/* Temporary debug */
extern int ipending_cmd(int,void *,void *);
#if defined(FEATURE_BRANCH_AND_SET_AUTHORITY)
/*-------------------------------------------------------------------*/
/* B25A BSA - Branch and Set Authority [RRE] */
/*-------------------------------------------------------------------*/
DEF_INST(branch_and_set_authority)
{
int r1, r2; /* Values of R fields */
U32 ducto; /* DUCT origin */
U32 duct_pkrp; /* DUCT PKM/Key/RA/P word */
RADR duct_reta; /* DUCT return address/amode */
BYTE key; /* New PSW key */
#ifdef FEATURE_TRACING
CREG newcr12 = 0; /* CR12 upon completion */
#endif /*FEATURE_TRACING*/
RRE(inst, regs, r1, r2);
/* Special operation exception if ASF is not enabled */
if (!ASF_ENABLED(regs))
ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION);
#if defined(_FEATURE_SIE)
if(SIE_STATB(regs, IC1, BSA))
longjmp(regs->progjmp, SIE_INTERCEPT_INST);
#endif /*defined(_FEATURE_SIE)*/
/* Load real address of dispatchable unit control table */
ducto = regs->CR(2) & CR2_DUCTO;
/* Apply low-address protection to stores into the DUCT */
if (ARCH_DEP(is_low_address_protected) (ducto, regs))
{
#ifdef FEATURE_SUPPRESSION_ON_PROTECTION
regs->TEA = (ducto & STORAGE_KEY_PAGEMASK);
regs->excarid = 0;
#endif /*FEATURE_SUPPRESSION_ON_PROTECTION*/
ARCH_DEP(program_interrupt) (regs, PGM_PROTECTION_EXCEPTION);
}
/* Convert DUCT real address to absolute address */
ducto = APPLY_PREFIXING (ducto, regs->PX);
/* Program check if DUCT origin address is invalid */
if (ducto > regs->mainlim)
ARCH_DEP(program_interrupt) (regs, PGM_ADDRESSING_EXCEPTION);
#if defined(FEATURE_ESAME)
/* For ESAME, load the PKM/Key/RA/P from DUCT word 5, and load
the return address and amode from DUCT words 8 and 9
(note: the DUCT cannot cross a page boundary) */
duct_pkrp = ARCH_DEP(fetch_fullword_absolute) (ducto+20, regs);
duct_reta = ARCH_DEP(fetch_doubleword_absolute) (ducto+32, regs);
#else /*!defined(FEATURE_ESAME)*/
/* For ESA/390, load the PKM/Key/RA/P from DUCT word 9, and load
the return address and amode from DUCT word 8
(note: the DUCT cannot cross a page boundary) */
duct_pkrp = ARCH_DEP(fetch_fullword_absolute) (ducto+36, regs);
duct_reta = ARCH_DEP(fetch_fullword_absolute) (ducto+32, regs);
#endif /*!defined(FEATURE_ESAME)*/
/* Perform base authority or reduced authority operation */
if ((duct_pkrp & DUCT_RA) == 0)
{
/* In base authority state R2 cannot specify register zero */
if (r2 == 0)
ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION);
#ifdef FEATURE_TRACING
/* Perform tracing */
if (regs->CR(12) & CR12_BRTRACE)
newcr12 = ARCH_DEP(trace_br) (regs->GR_L(r2) & 0x80000000,
regs->GR_L(r2), regs);
#endif /*FEATURE_TRACING*/
/* Obtain the new PSW key from R1 register bits 24-27 */
key = regs->GR_L(r1) & 0x000000F0;
/* Privileged operation exception if in problem state and
current PSW key mask does not permit new key value */
if (PROBSTATE(®s->psw)
&& ((regs->CR(3) << (key >> 4)) & 0x80000000) == 0 )
ARCH_DEP(program_interrupt) (regs, PGM_PRIVILEGED_OPERATION_EXCEPTION);
/* Save current PSW amode and instruction address */
#if defined(FEATURE_ESAME)
if (regs->psw.amode64)
{
duct_reta = PSW_IA(regs, 0);
}
else
#endif /*!defined(FEATURE_ESAME)*/
{
duct_reta = PSW_IA(regs, 0) & DUCT_IA31;
if (regs->psw.amode) duct_reta |= DUCT_AM31;
}
/* Save current PSW key mask, PSW key, and problem state */
duct_pkrp = (regs->CR(3) & CR3_KEYMASK) | regs->psw.pkey;
if (PROBSTATE(®s->psw)) duct_pkrp |= DUCT_PROB;
/* Set the reduced authority bit */
duct_pkrp |= DUCT_RA;
#if defined(FEATURE_ESAME)
/* For ESAME, store the PKM/Key/RA/P into DUCT word 5, and
store the return address and amode into DUCT words 8 and 9
(note: the DUCT cannot cross a page boundary) */
ARCH_DEP(store_fullword_absolute) (duct_pkrp, ducto+20, regs);
ARCH_DEP(store_doubleword_absolute) (duct_reta, ducto+32, regs);
#else /*!defined(FEATURE_ESAME)*/
/* For ESA/390, store the PKM/Key/RA/P into DUCT word 9, and
store the return address and amode into DUCT word 8
(note: the DUCT cannot cross a page boundary) */
ARCH_DEP(store_fullword_absolute) (duct_pkrp, ducto+36, regs);
ARCH_DEP(store_fullword_absolute) (duct_reta, ducto+32, regs);
#endif /*!defined(FEATURE_ESAME)*/
/* Load new PSW key and PSW key mask from R1 register */
regs->psw.pkey = key;
regs->CR_LHH(3) &= regs->GR_LHH(r1);
/* Set the problem state bit in the current PSW */
regs->psw.states |= BIT(PSW_PROB_BIT);
/* Set the breaking event address register */
SET_BEAR_REG(regs, regs->ip - 4);
/* Set PSW instruction address and amode from R2 register */
#if defined(FEATURE_ESAME)
if (regs->psw.amode64)
{
UPD_PSW_IA(regs, regs->GR_G(r2));
}
else
#endif /*defined(FEATURE_ESAME)*/
if (regs->GR_L(r2) & 0x80000000)
{
#if defined(FEATURE_ESAME)
regs->psw.amode64 = 0;
#endif /*defined(FEATURE_ESAME)*/
regs->psw.amode = 1;
regs->psw.AMASK = AMASK31;
UPD_PSW_IA(regs, regs->GR_L(r2));
}
else
{
#if defined(FEATURE_ESAME)
regs->psw.amode64 =
#endif /*defined(FEATURE_ESAME)*/
regs->psw.amode = 0;
regs->psw.AMASK = AMASK24;
UPD_PSW_IA(regs, regs->GR_L(r2));
}
} /* end if(BSA-ba) */
else
{ /* BSA-ra */
/* In reduced authority state R2 must specify register zero */
if (r2 != 0)
ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION);
#ifdef FEATURE_TRACING
/* Perform tracing */
if (regs->CR(12) & CR12_BRTRACE)
newcr12 = ARCH_DEP(trace_br) (duct_reta & DUCT_AM31,
duct_reta &DUCT_IA31, regs);
#endif /*FEATURE_TRACING*/
/* Set the breaking event address register */
SET_BEAR_REG(regs, regs->ip - 4);
/* If R1 is non-zero, save the current PSW addressing mode
and instruction address in the R1 register */
if (r1 != 0)
{
#if defined(FEATURE_ESAME)
if (regs->psw.amode64)
{
regs->GR_G(r1) = PSW_IA(regs, 0);
}
else
#endif /*defined(FEATURE_ESAME)*/
{
regs->GR_L(r1) = PSW_IA(regs, 0);
if (regs->psw.amode) regs->GR_L(r1) |= 0x80000000;
}
}
/* Restore PSW amode and instruction address from the DUCT */
#if defined(FEATURE_ESAME)
if (regs->psw.amode64)
{
UPD_PSW_IA(regs, duct_reta);
}
else
#endif /*defined(FEATURE_ESAME)*/
{
regs->psw.amode = (duct_reta & DUCT_AM31) ? 1 : 0;
regs->psw.AMASK = regs->psw.amode ? AMASK31 : AMASK24;
UPD_PSW_IA(regs, duct_reta & DUCT_IA31);
}
/* Restore the PSW key mask from the DUCT */
regs->CR_L(3) &= 0x0000FFFF;
regs->CR_L(3) |= duct_pkrp & DUCT_PKM;
/* Restore the PSW key from the DUCT */
regs->psw.pkey = duct_pkrp & DUCT_KEY;
/* Restore the problem state bit from the DUCT */
if (duct_pkrp & DUCT_PROB)
regs->psw.states |= BIT(PSW_PROB_BIT);
else
regs->psw.states &= ~BIT(PSW_PROB_BIT);
/* Reset the reduced authority bit in the DUCT */
duct_pkrp &= ~DUCT_RA;
#if defined(FEATURE_ESAME)
ARCH_DEP(store_fullword_absolute) (duct_pkrp, ducto+20, regs);
#else /*!defined(FEATURE_ESAME)*/
ARCH_DEP(store_fullword_absolute) (duct_pkrp, ducto+36, regs);
#endif /*!defined(FEATURE_ESAME)*/
/* Specification exception if the PSW is now invalid. */
/* (Since UPD_PSW_IA used above masks off inval bits */
/* in psw.IA, test duct_reta for invalid bits). */
if ((duct_reta & 1)
#if defined(FEATURE_ESAME)
|| (regs->psw.amode64 == 0 && regs->psw.amode == 0
&& (duct_reta & 0x7F000000)))
#else /*!defined(FEATURE_ESAME)*/
|| (regs->psw.amode == 0 && duct_reta > 0x00FFFFFF))
#endif /*!defined(FEATURE_ESAME)*/
{
/* program_interrupt will invoke INVALIDATE_AIA which */
/* will apply address mask to psw.IA if aie valid. */
regs->aie = NULL;
regs->psw.IA = duct_reta;
regs->psw.zeroilc = 1;
ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);
}
} /* end if(BSA-ra) */
#ifdef FEATURE_TRACING
/* Update trace table address if branch tracing is on */
if (regs->CR(12) & CR12_BRTRACE)
regs->CR(12) = newcr12;
#endif /*FEATURE_TRACING*/
/* Check for Successful Branch PER event */
PER_SB(regs, regs->psw.IA);
} /* end DEF_INST(branch_and_set_authority) */
#endif /*defined(FEATURE_BRANCH_AND_SET_AUTHORITY)*/
#if defined(FEATURE_SUBSPACE_GROUP)
/*-------------------------------------------------------------------*/
/* B258 BSG - Branch in Subspace Group [RRE] */
/*-------------------------------------------------------------------*/
DEF_INST(branch_in_subspace_group)
{
int r1, r2; /* Values of R fields */
U32 alet; /* Destination subspace ALET */
U32 dasteo=0; /* Destination ASTE origin */
U32 daste[16]; /* ASN second table entry */
RADR ducto; /* DUCT origin */
U32 duct0; /* DUCT word 0 */
U32 duct1; /* DUCT word 1 */
U32 duct3; /* DUCT word 3 */
RADR abs; /* Absolute address */
BYTE *mn; /* Mainstor address */
VADR newia; /* New instruction address */
U16 xcode; /* Exception code */
#ifdef FEATURE_TRACING
CREG newcr12 = 0; /* CR12 upon completion */
#endif /*FEATURE_TRACING*/
CREG inst_cr; /* Instruction CR */
RRE(inst, regs, r1, r2);
SIE_XC_INTERCEPT(regs);
/* Special operation exception if DAT is off or ASF not enabled */
if (REAL_MODE(&(regs->psw))
|| !ASF_ENABLED(regs))
ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION);
inst_cr = regs->CR(regs->aea_ar[USE_INST_SPACE]);
#ifdef FEATURE_TRACING
/* Perform tracing */
if (regs->CR(12) & CR12_ASNTRACE)
newcr12 = ARCH_DEP(trace_bsg) ((r2 == 0) ? 0 : regs->AR(r2),
regs->GR_L(r2), regs);
else
if (regs->CR(12) & CR12_BRTRACE)
newcr12 = ARCH_DEP(trace_br) (regs->GR_L(r2) & 0x80000000,
regs->GR_L(r2), regs);
#endif /*FEATURE_TRACING*/
/* Load real address of dispatchable unit control table */
ducto = regs->CR(2) & CR2_DUCTO;
/* Apply low-address protection to stores into the DUCT */
if (ARCH_DEP(is_low_address_protected) (ducto, regs))
{
#ifdef FEATURE_SUPPRESSION_ON_PROTECTION
regs->TEA = (ducto & STORAGE_KEY_PAGEMASK);
regs->excarid = 0;
#endif /*FEATURE_SUPPRESSION_ON_PROTECTION*/
ARCH_DEP(program_interrupt) (regs, PGM_PROTECTION_EXCEPTION);
}
/* Convert DUCT real address to absolute address */
ducto = APPLY_PREFIXING (ducto, regs->PX);
/* Program check if DUCT origin address is invalid */
if (ducto > regs->mainlim)
ARCH_DEP(program_interrupt) (regs, PGM_ADDRESSING_EXCEPTION);
/* Fetch DUCT words 0, 1, and 3 from absolute storage
(note: the DUCT cannot cross a page boundary) */
mn = FETCH_MAIN_ABSOLUTE (ducto, regs, 16);
duct0 = fetch_fw (mn);
duct1 = fetch_fw (mn+4);
duct3 = fetch_fw (mn+12);
/* Special operation exception if the current primary ASTE origin
is not the same as the base ASTE for the dispatchable unit */
if ((regs->CR_L(5) & CR5_PASTEO) != (duct0 & DUCT0_BASTEO))
ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION);
/* Obtain the destination ALET from the R2 access register,
except that register zero means destination ALET is zero */
alet = (r2 == 0) ? 0 : regs->AR(r2);
/* Perform special ALET translation to obtain destination ASTE */
switch (alet) {
case ALET_PRIMARY: /* Branch to base space */
/* Load the base space ASTE origin from the DUCT */
dasteo = duct0 & DUCT0_BASTEO;
/* Convert the ASTE origin to an absolute address */
abs = APPLY_PREFIXING (dasteo, regs->PX);
/* Program check if ASTE origin address is invalid */
if (abs > regs->mainlim)
ARCH_DEP(program_interrupt) (regs, PGM_ADDRESSING_EXCEPTION);
/* Fetch destination ASTE words 2 and 3 from absolute storage
(note: the ASTE cannot cross a page boundary) */
mn = FETCH_MAIN_ABSOLUTE (abs, regs, 16);
daste[2] = fetch_fw (mn+8);
daste[3] = fetch_fw (mn+12);
break;
case ALET_SECONDARY: /* Branch to last-used subspace */
/* Load the subspace ASTE origin from the DUCT */
dasteo = duct1 & DUCT1_SSASTEO;
/* Special operation exception if SSASTEO is zero */
if (dasteo == 0)
ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION);
/* Convert the ASTE origin to an absolute address */
abs = APPLY_PREFIXING (dasteo, regs->PX);
/* Program check if ASTE origin address is invalid */
if (abs > regs->mainlim)
ARCH_DEP(program_interrupt) (regs, PGM_ADDRESSING_EXCEPTION);
/* Fetch subspace ASTE words 0, 2, 3, and 5 from absolute
storage (note: the ASTE cannot cross a page boundary) */
mn = FETCH_MAIN_ABSOLUTE (abs, regs, 24);
daste[0] = fetch_fw (mn);
daste[2] = fetch_fw (mn+8);
daste[3] = fetch_fw (mn+12);
daste[5] = fetch_fw (mn+20);
/* ASTE validity exception if ASTE invalid bit is one */
if (daste[0] & ASTE0_INVALID)
{
regs->excarid = r2;
ARCH_DEP(program_interrupt) (regs, PGM_ASTE_VALIDITY_EXCEPTION);
}
/* ASTE sequence exception if the subspace ASTE sequence
number does not match the sequence number in the DUCT */
if ((daste[5] & ASTE5_ASTESN) != (duct3 & DUCT3_SSASTESN))
{
regs->excarid = r2;
ARCH_DEP(program_interrupt) (regs, PGM_ASTE_SEQUENCE_EXCEPTION);
}
break;
default: /* ALET not 0 or 1 */
/* Perform special ART to obtain destination ASTE */
xcode = ARCH_DEP(translate_alet) (alet, 0, ACCTYPE_BSG, regs,
&dasteo, daste);
/* Program check if ALET translation error */
if (xcode != 0)
{
regs->excarid = r2;
ARCH_DEP(program_interrupt) (regs, xcode);
}
/* Special operation exception if the destination ASTE
is the base space of a different subspace group */
if (dasteo != (duct0 & DUCT0_BASTEO)
&& ((ASTE_AS_DESIGNATOR(daste) & SSGROUP_BIT) == 0
|| (daste[0] & ASTE0_BASE) ))
ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION);
} /* end switch(alet) */
/* Update the primary STD (or ASCE) from the destination ASTE */
if ((dasteo == (duct0 & DUCT0_BASTEO)) && (alet != ALET_SECONDARY))
{
/* When the destination ASTE is the base space, replace the
primary STD (or ASCE) by the STD (or ASCE) in the ASTE */
regs->CR(1) = ASTE_AS_DESIGNATOR(daste);
}
else
{
/* When the destination ASTE is a subspace, replace
the primary STD or ASCE by the STD or ASTE in the
ASTE, except for the space-switch event and storage
alteration event bits, which remain unchanged */
regs->CR(1) &= (SSEVENT_BIT | SAEVENT_BIT);
regs->CR(1) |= (ASTE_AS_DESIGNATOR(daste)
& ~((RADR)(SSEVENT_BIT | SAEVENT_BIT)));
}
/* Compute the branch address from the R2 operand */
newia = regs->GR(r2);
/* If R1 is non-zero, save the current PSW addressing mode
and instruction address in the R1 register */
if (r1 != 0)
{
#if defined(FEATURE_ESAME)
if (regs->psw.amode64)
regs->GR_G(r1) = PSW_IA(regs, 0);
else
#endif /*!defined(FEATURE_ESAME)*/
regs->GR_L(r1) = PSW_IA(regs, 0) |
(regs->psw.amode ? 0x80000000 : 0);
}
/* Update the breaking event address register */
SET_BEAR_REG(regs, regs->ip - 4);
#if defined(FEATURE_ESAME)
if (regs->psw.amode64 == 0 && (newia & 0x80000000))
#else /*!defined(FEATURE_ESAME)*/
if (newia & 0x80000000)
#endif /*!defined(FEATURE_ESAME)*/
{
regs->psw.amode = 1;
regs->psw.AMASK = AMASK31;
}
else
{
regs->psw.amode = 0;
regs->psw.AMASK = AMASK24;
}
/* Set mode and branch to address specified by R2 operand */
UPD_PSW_IA(regs, newia);
/* Set the SSTD (or SASCE) equal to PSTD (or PASCE) */
regs->CR(7) = regs->CR(1);
/* Set SASN equal to PASN */
regs->CR_LHL(3) = regs->CR_LHL(4);
/* When ASN-and-LX-reuse is installed and enabled by CR0,
set the SASTEIN in CR3 equal to the PASTEIN in CR4 */
if (ASN_AND_LX_REUSE_ENABLED(regs))
{
regs->CR_H(3) = regs->CR_H(4);
} /* end if (ASN_AND_LX_REUSE_ENABLED) */
/* Reset the subspace fields in the DUCT */
if (alet == ALET_SECONDARY)
{
/* When the destination ASTE specifies a subspace by means
of ALET 1, set the subspace active bit in the DUCT */
duct1 |= DUCT1_SA;
ARCH_DEP(store_fullword_absolute) (duct1, ducto+4, regs);
}
else if (dasteo == (duct0 & DUCT0_BASTEO))
{
/* When the destination ASTE is the base space,
reset the subspace active bit in the DUCT */
duct1 &= ~DUCT1_SA;
ARCH_DEP(store_fullword_absolute) (duct1, ducto+4, regs);
}
else
{
/* When the destination ASTE specifies a subspace by means
of an ALET other than ALET 1, set the subspace active
bit and store the subspace ASTE origin in the DUCT */
duct1 = DUCT1_SA | dasteo;
ARCH_DEP(store_fullword_absolute) (duct1, ducto+4, regs);
/* Set the subspace ASTE sequence number in the DUCT
equal to the destination ASTE sequence number */
duct3 = daste[5];
ARCH_DEP(store_fullword_absolute) (duct3, ducto+12, regs);
}
#ifdef FEATURE_TRACING
/* Update trace table address if ASN tracing or branch tracing */
if (regs->CR(12) & (CR12_ASNTRACE | CR12_BRTRACE))
regs->CR(12) = newcr12;
#endif /*FEATURE_TRACING*/
SET_AEA_COMMON(regs);
if (inst_cr != regs->CR(regs->aea_ar[USE_INST_SPACE]))
INVALIDATE_AIA(regs);
/* Check for Successful Branch PER event */
PER_SB(regs, regs->psw.IA);
} /* end DEF_INST(branch_in_subspace_group) */
#endif /*defined(FEATURE_SUBSPACE_GROUP)*/
#if defined(FEATURE_LINKAGE_STACK)
/*-------------------------------------------------------------------*/
/* B240 BAKR - Branch and Stack Register [RRE] */
/*-------------------------------------------------------------------*/
DEF_INST(branch_and_stack)
{
int r1, r2; /* Values of R fields */
VADR n1, n2; /* Operand values */
#ifdef FEATURE_TRACING
VADR n = 0; /* Work area */
#endif /*FEATURE_TRACING*/
RRE(inst, regs, r1, r2);
SIE_XC_INTERCEPT(regs);
#if defined(_FEATURE_SIE)
if(SIE_STATB(regs, IC3, BAKR))
longjmp(regs->progjmp, SIE_INTERCEPT_INST);
#endif /*defined(_FEATURE_SIE)*/
/* [5.12.3]/ Fig 10-2 Special operation exception if ASF is not enabled,
or if DAT is off, or if not primary-space mode or AR-mode */
if (!ASF_ENABLED(regs)
|| REAL_MODE(®s->psw)
|| SPACE_BIT(®s->psw))
ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION);
/* Obtain the return address and addressing mode from
the R1 register, or use updated PSW if R1 is zero */
if ( r1 != 0 )
{
n1 = regs->GR(r1);
#if defined(FEATURE_ESAME)
if ( (n1 & 0x01) == 0 )
n1 &= (n1 & 0x80000000) ? 0xFFFFFFFF : 0x00FFFFFF;
#else /*!defined(FEATURE_ESAME)*/
if ( (n1 & 0x80000000) == 0 )
n1 &= 0x00FFFFFF;
#endif /*!defined(FEATURE_ESAME)*/
}
else
{
n1 = PSW_IA(regs, 0);
#if defined(FEATURE_ESAME)
if ( regs->psw.amode64 )
n1 |= 0x01;
else
#endif /*defined(FEATURE_ESAME)*/
if ( regs->psw.amode )
n1 |= 0x80000000;
}
/* Obtain the branch address from the R2 register, or use
the updated PSW instruction address if R2 is zero */
n2 = (r2 != 0) ? regs->GR(r2) : PSW_IA(regs, 0);
n2 &= ADDRESS_MAXWRAP(regs);
/* Set the addressing mode bit in the branch address */
#if defined(FEATURE_ESAME)
if ( regs->psw.amode64 )
n2 |= 0x01;
else
#endif /*defined(FEATURE_ESAME)*/
if ( regs->psw.amode )
n2 |= 0x80000000;
#ifdef FEATURE_TRACING
/* Form the branch trace entry */
if((regs->CR(12) & CR12_BRTRACE) && (r2 != 0))
n = ARCH_DEP(trace_br)(regs->psw.amode, regs->GR_L(r2), regs);
#endif /*FEATURE_TRACING*/
/* Form the linkage stack entry */
ARCH_DEP(form_stack_entry) (LSED_UET_BAKR, n1, n2, 0, 0, regs);
#ifdef FEATURE_TRACING
/* Update CR12 to reflect the new branch trace entry */
if((regs->CR(12) & CR12_BRTRACE) && (r2 != 0))
regs->CR(12) = n;
#endif /*FEATURE_TRACING*/
/* Execute the branch unless R2 specifies register 0 */
if ( r2 != 0 )
{
UPDATE_BEAR(regs, -4);
UPD_PSW_IA(regs, regs->GR(r2));
PER_SB(regs, regs->psw.IA);
}
} /* end DEF_INST(branch_and_stack) */
#endif /*defined(FEATURE_LINKAGE_STACK)*/
#if defined(FEATURE_BROADCASTED_PURGING)
/*-------------------------------------------------------------------*/
/* B250 CSP - Compare and Swap and Purge [RRE] */
/*-------------------------------------------------------------------*/
DEF_INST(compare_and_swap_and_purge)
{
int r1, r2; /* Values of R fields */
U64 n2; /* virtual address of op2 */
BYTE *main2; /* mainstor address of op2 */
U32 old; /* old value */
RRE(inst, regs, r1, r2);
PRIV_CHECK(regs);
ODD_CHECK(r1, regs);
#if defined(_FEATURE_SIE)
if(SIE_STATB(regs,IC0, IPTECSP))
longjmp(regs->progjmp, SIE_INTERCEPT_INST);
#endif /*defined(_FEATURE_SIE)*/
#if defined(_FEATURE_SIE)
if(SIE_MODE(regs) && regs->sie_scao)
{
STORAGE_KEY(regs->sie_scao, regs) |= STORKEY_REF;
if(regs->mainstor[regs->sie_scao] & 0x80)
longjmp(regs->progjmp, SIE_INTERCEPT_INST);
}
#endif /*defined(_FEATURE_SIE)*/
/* Perform serialization before starting operation */
PERFORM_SERIALIZATION (regs);
/* Obtain 2nd operand address from r2 */
n2 = regs->GR(r2) & 0xFFFFFFFFFFFFFFFCULL & ADDRESS_MAXWRAP(regs);
main2 = MADDR (n2, r2, regs, ACCTYPE_WRITE, regs->psw.pkey);
old = CSWAP32 (regs->GR_L(r1));
/* Obtain main-storage access lock */
OBTAIN_MAINLOCK(regs);
/* Attempt to exchange the values */
regs->psw.cc = cmpxchg4 (&old, CSWAP32(regs->GR_L(r1+1)), main2);
/* Release main-storage access lock */
RELEASE_MAINLOCK(regs);
if (regs->psw.cc == 0)
{
/* Perform requested funtion specified as per request code in r2 */
if (regs->GR_L(r2) & 3)
{
OBTAIN_INTLOCK(regs);
SYNCHRONIZE_CPUS(regs);
if (regs->GR_L(r2) & 1)
ARCH_DEP(purge_tlb_all)();
if (regs->GR_L(r2) & 2)
ARCH_DEP(purge_alb_all)();
RELEASE_INTLOCK(regs);
}
}
else
{
PTT(PTT_CL_CSF,"*CSP",regs->GR_L(r1),regs->GR_L(r2),regs->psw.IA_L);
/* Otherwise yield */
regs->GR_L(r1) = CSWAP32(old);
if (sysblk.cpus > 1)
sched_yield();
}
/* Perform serialization after completing operation */
PERFORM_SERIALIZATION (regs);
} /* end DEF_INST(compare_and_swap_and_purge) */
#endif /*defined(FEATURE_BROADCASTED_PURGING)*/
/*-------------------------------------------------------------------*/
/* 83 DIAG - Diagnose [RS] */
/*-------------------------------------------------------------------*/
DEF_INST(diagnose)
{
int r1, r3; /* Register numbers */
int b2; /* Base of effective addr */
VADR effective_addr2; /* Effective address */
RS(inst, regs, r1, r3, b2, effective_addr2);
#if defined(FEATURE_ECPSVM)
if(ecpsvm_dodiag(regs,r1,r3,b2,effective_addr2)==0)
{
return;
}
#endif
#ifdef FEATURE_HERCULES_DIAGCALLS
if (
#if defined(_FEATURE_SIE)
!SIE_MODE(regs) &&
#endif /* defined(_FEATURE_SIE) */
effective_addr2 != 0xF08)
#endif
PRIV_CHECK(regs);
SIE_INTERCEPT(regs);
PTT(PTT_CL_INF,"DIAG",regs->GR_L(r1),regs->GR_L(r3),(U32)(effective_addr2 & 0xffffff));
/* Process diagnose instruction */
ARCH_DEP(diagnose_call) (effective_addr2, b2, r1, r3, regs);
/* Perform serialization and checkpoint-synchronization */
PERFORM_SERIALIZATION (regs);
PERFORM_CHKPT_SYNC (regs);
#ifdef FEATURE_HERCULES_DIAGCALLS
RETURN_INTCHECK(regs);
#endif
} /* end DEF_INST(diagnose) */
#if defined(FEATURE_DUAL_ADDRESS_SPACE)
/*-------------------------------------------------------------------*/
/* B226 EPAR - Extract Primary ASN [RRE] */
/*-------------------------------------------------------------------*/
DEF_INST(extract_primary_asn)
{
int r1, r2; /* Values of R fields */
RRE(inst, regs, r1, r2);
SIE_XC_INTERCEPT(regs);
/* Special operation exception if DAT is off */
if ( (regs->psw.sysmask & PSW_DATMODE) == 0 )
ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION);
/* Privileged operation exception if in problem state
and the extraction-authority control bit is zero */
if ( PROBSTATE(®s->psw)
&& (regs->CR(0) & CR0_EXT_AUTH) == 0 )
ARCH_DEP(program_interrupt) (regs, PGM_PRIVILEGED_OPERATION_EXCEPTION);
/* Load R1 bits 48-63 with PASN from control register 4 bits 48-63
and zeroize R1 bits 32-47 */
regs->GR_L(r1) = regs->CR_LHL(4);
} /* end DEF_INST(extract_primary_asn) */
#endif /*defined(FEATURE_DUAL_ADDRESS_SPACE)*/
#if defined(FEATURE_ASN_AND_LX_REUSE)
/*-------------------------------------------------------------------*/
/* B99A EPAIR - Extract Primary ASN and Instance [RRE] */
/*-------------------------------------------------------------------*/
DEF_INST(extract_primary_asn_and_instance)
{
int r1, r2; /* Values of R fields */
/* Operation exception if ASN-and-LX-reuse is not enabled */
if(!sysblk.asnandlxreuse)
{
ARCH_DEP(operation_exception)(inst,regs);
}
RRE(inst, regs, r1, r2);
SIE_XC_INTERCEPT(regs);
/* Special operation exception if DAT is off */
if ( (regs->psw.sysmask & PSW_DATMODE) == 0 )
ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION);
/* Privileged operation exception if in problem state
and the extraction-authority control bit is zero */
if ( PROBSTATE(®s->psw)
&& (regs->CR(0) & CR0_EXT_AUTH) == 0 )
ARCH_DEP(program_interrupt) (regs, PGM_PRIVILEGED_OPERATION_EXCEPTION);
/* Load R1 bits 48-63 with PASN from control register 4 bits 48-63
and zeroize R1 bits 32-47 */
regs->GR_L(r1) = regs->CR_LHL(4);
/* Load R1 bits 0-31 with PASTEIN from control register 4 bits 0-31 */
regs->GR_H(r1) = regs->CR_H(4);
} /* end DEF_INST(extract_primary_asn_and_instance) */
#endif /*defined(FEATURE_ASN_AND_LX_REUSE)*/
#if defined(FEATURE_DUAL_ADDRESS_SPACE)
/*-------------------------------------------------------------------*/
/* B227 ESAR - Extract Secondary ASN [RRE] */
/*-------------------------------------------------------------------*/
DEF_INST(extract_secondary_asn)
{
int r1, r2; /* Values of R fields */
RRE(inst, regs, r1, r2);
SIE_XC_INTERCEPT(regs);
/* Special operation exception if DAT is off */
if ( (regs->psw.sysmask & PSW_DATMODE) == 0 )
ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION);
/* Privileged operation exception if in problem state
and the extraction-authority control bit is zero */
if ( PROBSTATE(®s->psw)
&& (regs->CR(0) & CR0_EXT_AUTH) == 0 )
ARCH_DEP(program_interrupt) (regs, PGM_PRIVILEGED_OPERATION_EXCEPTION);
/* Load R1 bits 48-63 with SASN from control register 3 bits 48-63
and zeroize R1 bits 32-47 */
regs->GR_L(r1) = regs->CR_LHL(3);
} /* end DEF_INST(extract_secondary_asn) */
#endif /*defined(FEATURE_DUAL_ADDRESS_SPACE)*/
#if defined(FEATURE_ASN_AND_LX_REUSE)
/*-------------------------------------------------------------------*/
/* B99B ESAIR - Extract Secondary ASN and Instance [RRE] */
/*-------------------------------------------------------------------*/
DEF_INST(extract_secondary_asn_and_instance)
{
int r1, r2; /* Values of R fields */
/* Operation exception if ASN-and-LX-reuse is not enabled */
if(!sysblk.asnandlxreuse)
{
ARCH_DEP(operation_exception)(inst,regs);
}
RRE(inst, regs, r1, r2);
SIE_XC_INTERCEPT(regs);
/* Special operation exception if DAT is off */
if ( (regs->psw.sysmask & PSW_DATMODE) == 0 )
ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION);
/* Privileged operation exception if in problem state
and the extraction-authority control bit is zero */
if ( PROBSTATE(®s->psw)
&& (regs->CR(0) & CR0_EXT_AUTH) == 0 )
ARCH_DEP(program_interrupt) (regs, PGM_PRIVILEGED_OPERATION_EXCEPTION);
/* Load R1 bits 48-63 with SASN from control register 3 bits 48-63
and zeroize R1 bits 32-47 */
regs->GR_L(r1) = regs->CR_LHL(3);
/* Load R1 bits 0-31 with SASTEIN from control register 3 bits 0-31 */
regs->GR_H(r1) = regs->CR_H(3);
} /* end DEF_INST(extract_secondary_asn_and_instance) */
#endif /*defined(FEATURE_ASN_AND_LX_REUSE)*/
#if defined(FEATURE_LINKAGE_STACK)
/*-------------------------------------------------------------------*/
/* B249 EREG - Extract Stacked Registers [RRE] */
/*-------------------------------------------------------------------*/
DEF_INST(extract_stacked_registers)
{
int r1, r2; /* Values of R fields */
LSED lsed; /* Linkage stack entry desc. */
VADR lsea; /* Linkage stack entry addr */
RRE(inst, regs, r1, r2);
SIE_XC_INTERCEPT(regs);
/* Find the virtual address of the entry descriptor
of the current state entry in the linkage stack */
lsea = ARCH_DEP(locate_stack_entry) (0, &lsed, regs);
/* Load registers from the stack entry */
ARCH_DEP(unstack_registers) (0, lsea, r1, r2, regs);
}
#endif /*defined(FEATURE_LINKAGE_STACK)*/
#if defined(FEATURE_LINKAGE_STACK)
/*-------------------------------------------------------------------*/
/* B24A ESTA - Extract Stacked State [RRE] */
/*-------------------------------------------------------------------*/
DEF_INST(extract_stacked_state)
{
int r1, r2; /* Values of R fields */
BYTE code; /* Extraction code */
LSED lsed; /* Linkage stack entry desc. */
VADR lsea; /* Linkage stack entry addr */
int max_esta_code;
RRE(inst, regs, r1, r2);
SIE_XC_INTERCEPT(regs);
if (REAL_MODE(®s->psw)
|| SECONDARY_SPACE_MODE(®s->psw)
|| !ASF_ENABLED(regs))
ARCH_DEP(program_interrupt) (regs, PGM_SPECIAL_OPERATION_EXCEPTION);
/* Load the extraction code from low-order byte of R2 register */