1 /* VECTOR.C     (c) Copyright Jan Jaeger, 1999-2009                  */
2 /*              S/370 and ESA/390 Vector Operations                  */
3 
4 /*-------------------------------------------------------------------*/
5 /* This module implements the Vector Facility instruction execution  */
6 /* function of the S/370 and ESA/390 architectures, as described in  */
7 /* SA22-7125-03 Vector Operations (S/370 & ESA/370)                  */
8 /* SA22-7207-00 Vector Operations (ESA/390)                          */
9 /*                                             28/05/2000 Jan Jaeger */
10 /*                                                                   */
11 /* Instruction decoding rework                 09/07/2000 Jan Jaeger */
12 /* Interpretive Execution - (c) Copyright Jan Jaeger, 1999-2009      */
13 /* z/Architecture support - (c) Copyright Jan Jaeger, 1999-2009      */
14 /*-------------------------------------------------------------------*/
15 
16 #include "hstdinc.h"
17 
18 #include "hercules.h"
19 
20 #include "opcode.h"
21 
22 #include "inline.h"
23 
24 #if defined(FEATURE_VECTOR_FACILITY)
25 
26 /* The vector save area must be aligned on a boundary 8 times the
27    section size, however VM stores at 4 times the section size.
28    I do not know if the book or VM is wrong.                     *JJ */
29 #define VSA_ALIGN       4
30 
31 /*-------------------------------------------------------------------*/
32 /* A640 VTVM  - Test VMR                                       [RRE] */
33 /*-------------------------------------------------------------------*/
DEF_INST(v_test_vmr)34 DEF_INST(v_test_vmr)
35 {
36 int     unused1, unused2;
37 U32     n, n1;
38 
39     RRE(inst, regs, unused1, unused2);
40 
41     VOP_CHECK(regs);
42 
43     /* Extract vector count (number of active bits in vmr) */
44     n = VECTOR_COUNT(regs);
45 
46     /* cc0 when the vector count is zero */
47     if( n == 0)
48     {
49         regs->psw.cc = 0;
50         return;
51     }
52 
53     /* Preset condition code according to first bit */
54     regs->psw.cc = VMR_SET(0, regs) ? 3 : 0;
55 
56     /* Check VMR bit to be equal to the first,
57        exit with cc1 if an unequal bit found */
58     for(n1 = 1; n1 < n; n1++)
59         if((regs->psw.cc == 0) != (VMR_SET(n1, regs) == 0))
60         {
61             regs->psw.cc = 1;
62             return;
63         }
64 
65 }
66 
67 
68 /*-------------------------------------------------------------------*/
69 /* A641 VCVM  - Complement VMR                                 [RRE] */
70 /*-------------------------------------------------------------------*/
DEF_INST(v_complement_vmr)71 DEF_INST(v_complement_vmr)
72 {
73 int     unused1, unused2;
74 U32     n, n1, n2;
75 
76     RRE(inst, regs, unused1, unused2);
77 
78     VOP_CHECK(regs);
79 
80     /* Extract vector count (number of active bits in vmr) */
81     n = VECTOR_COUNT(regs);
82 
83     /* Bytes - 1 */
84     n1 = n >> 3;
85 
86     /* Complement VMR */
87     for(n2 = 0; n2 <= n1; n2++)
88         regs->vf->vmr[n2] ^= 0xFF;
89 
90     /* zeroize remainder */
91     regs->vf->vmr[n1] &= 0x7F00 >> (n & 7);
92     for(n1++; n1 < sizeof(regs->vf->vmr); n1++)
93         regs->vf->vmr[n1] = 0;
94 
95 }
96 
97 
98 /*-------------------------------------------------------------------*/
99 /* A642 VCZVM - Count Left Zeros in VMR                        [RRE] */
100 /*-------------------------------------------------------------------*/
DEF_INST(v_count_left_zeros_in_vmr)101 DEF_INST(v_count_left_zeros_in_vmr)
102 {
103 int     gr1, unused2;
104 U32     n, n1;
105 
106     RRE(inst, regs, gr1, unused2);
107 
108     VOP_CHECK(regs);
109 
110     /* Extract vector count (number of active bits in vmr) */
111     n = VECTOR_COUNT(regs);
112 
113     /* cc0 when the vector count is zero */
114     if( n == 0)
115     {
116         regs->psw.cc = 0;
117         return;
118     }
119 
120     /* Preset condition code according to first bit */
121     regs->psw.cc = VMR_SET(0, regs) ? 3 : 0;
122 
123     /* If the VCT is 1 and the first bit is one
124        then exit wirh gr1 set to zero */
125     regs->GR_L(gr1) = 0;
126     if(n == 1 && VMR_SET(0, regs))
127         return;
128 
129     /* Count left zeros, set cc1 and exit if a one is found */
130     regs->GR_L(gr1) = 1;
131     for(n1 = 1; n1 < n; n1++)
132     {
133         if(!VMR_SET(n1, regs))
134             regs->GR_L(gr1)++;
135         else
136         {
137             regs->psw.cc = 1;
138             return;
139         }
140     }
141 
142 }
143 
144 
145 /*-------------------------------------------------------------------*/
146 /* A643 VCOVM - Count Ones In VMR                              [RRE] */
147 /*-------------------------------------------------------------------*/
DEF_INST(v_count_ones_in_vmr)148 DEF_INST(v_count_ones_in_vmr)
149 {
150 int     gr1, unused2;
151 U32     n, n1;
152 
153     RRE(inst, regs, gr1, unused2);
154 
155     VOP_CHECK(regs);
156 
157     /* Extract vector count (number of active bits in vmr) */
158     n = VECTOR_COUNT(regs);
159 
160     /* cc0 when the vector count is zero */
161     if( n == 0)
162     {
163         regs->psw.cc = 0;
164         return;
165     }
166 
167     /* Preset condition code according to first bit */
168     regs->psw.cc = VMR_SET(0, regs) ? 3 : 0;
169 
170     /* Check VMR bit to be equal to the first,
171        Count all ones, set cc1 if a bit is unequal */
172     regs->GR_L(gr1) = 0;
173     for(n1 = 0; n1 < n; n1++)
174     {
175         if(VMR_SET(n1, regs))
176         {
177             regs->GR_L(gr1)++;
178             if(!VMR_SET(0, regs))
179                 regs->psw.cc = 1;
180         }
181         else
182             if(VMR_SET(0, regs))
183                 regs->psw.cc = 1;
184     }
185 
186 }
187 
188 
189 /*-------------------------------------------------------------------*/
190 /* A644 VXVC  - Exctract VCT                                   [RRE] */
191 /*-------------------------------------------------------------------*/
DEF_INST(v_extract_vct)192 DEF_INST(v_extract_vct)
193 {
194 int     gr1, unused2;
195 
196     RRE(inst, regs, gr1, unused2);
197 
198     VOP_CHECK(regs);
199 
200     regs->GR_L(gr1) = VECTOR_COUNT(regs);
201 
202 }
203 
204 
205 /*-------------------------------------------------------------------*/
206 /* A646 VXVMM - Extract Vector Modes                           [RRE] */
207 /*-------------------------------------------------------------------*/
DEF_INST(v_extract_vector_modes)208 DEF_INST(v_extract_vector_modes)
209 {
210 int     gr1, unused2;
211 
212     RRE(inst, regs, gr1, unused2);
213 
214     VOP_CHECK(regs);
215 
216     regs->GR_L(gr1) = (regs->vf->vsr >> 48);
217 
218 }
219 
220 
221 /*-------------------------------------------------------------------*/
222 /* A648 VRRS  - Restore VR                                     [RRE] */
223 /*-------------------------------------------------------------------*/
DEF_INST(v_restore_vr)224 DEF_INST(v_restore_vr)
225 {
226 int     gr1, unused2;
227 U32     n, n1, n2;
228 U64     d;
229 
230     RRE(inst, regs, gr1, unused2);
231 
232     VOP_CHECK(regs);
233 
234     ODD_CHECK(gr1, regs);
235 
236     /* n contrains the current save area address */
237     n = regs->GR_L(gr1) & ADDRESS_MAXWRAP(regs);
238 
239     /* n1 contains the starting element number */
240     if((n1 = regs->GR_L(gr1 + 1) >> 16) >= VECTOR_SECTION_SIZE)
241         ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION);
242 
243     /* Starting address must be eight times the section size aligned */
244     if((n - (8 * n1)) & ((VECTOR_SECTION_SIZE * VSA_ALIGN) - 1) )
245         ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION);
246 
247     /* n2 contains VR pair, which must be an even reg */
248     if((n2 = regs->GR_L(gr1 + 1) & 0x0000FFFF) & 0x0000FFF1)
249         ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION);
250 
251     if( VR_INUSE(n2, regs) )
252     {
253         /* Set the vector changed bit if in problem state */
254         if( PROBSTATE(&regs->psw) )
255             SET_VR_CHANGED(n2, regs);
256 
257         for(; n1 < VECTOR_SECTION_SIZE; n1++)
258         {
259             /* Fetch vr pair from central storage */
260             d = ARCH_DEP(vfetch8)(n, gr1, regs);
261             regs->vf->vr[n2][n1] = d >> 32;
262             regs->vf->vr[n2+1][n1] = d;
263 
264             /* Increment element number */
265             n1++;
266             regs->GR_L(gr1 + 1) &= 0x0000FFFF;
267             regs->GR_L(gr1 + 1) |= n1 << 16;
268             /* Update savearea address */
269             regs->GR_L(gr1) += 8;
270 #if 0
271             /* This is where the instruction may be interrupted */
272             UPD_PSW_IA(regs, PSW_IA(regs, -4));
273             return;
274 #endif
275         }
276 
277         /* Indicate vr pair restored */
278         regs->psw.cc = 2;
279     }
280     else
281     {
282         regs->GR_L(gr1) += 8 * (VECTOR_SECTION_SIZE - n1);
283         /* indicate v2 pair not restored */
284         regs->psw.cc = 0;
285     }
286 
287     /* Set 2 if vr 14 is restored, 0 if not restored,
288        3 and 1 for other VR's respectively */
289     if(n2 != 14) regs->psw.cc++;
290 
291     /* Update the vector pair number, and zero element number */
292     n2 += 2;
293     regs->GR_L(gr1 + 1) = n2;
294 
295 }
296 
297 
298 /*-------------------------------------------------------------------*/
299 /* A649 VRSVC - Save Changed VR                                [RRE] */
300 /*-------------------------------------------------------------------*/
DEF_INST(v_save_changed_vr)301 DEF_INST(v_save_changed_vr)
302 {
303 int     gr1, unused2;
304 U32     n, n1, n2;
305 U64     d;
306 
307     RRE(inst, regs, gr1, unused2);
308 
309     VOP_CHECK(regs);
310 
311     PRIV_CHECK(regs);
312 
313     ODD_CHECK(gr1, regs);
314 
315     /* n contrains the current save area address */
316     n = regs->GR_L(gr1) & ADDRESS_MAXWRAP(regs);
317 
318     /* n1 contains the starting element number */
319     if((n1 = regs->GR_L(gr1 + 1) >> 16) >= VECTOR_SECTION_SIZE)
320         ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION);
321 
322     /* Starting address must be eight times the section size aligned */
323     if((n - (8 * n1)) & ((VECTOR_SECTION_SIZE * VSA_ALIGN) - 1) )
324         ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION);
325 
326     /* n2 contains VR pair, which must be an even reg */
327     if((n2 = regs->GR_L(gr1 + 1) & 0x0000FFFF) & 0x0000FFF1)
328         ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION);
329 
330     if( VR_CHANGED(n2, regs) )
331     {
332         for(; n1 < VECTOR_SECTION_SIZE; n1++)
333         {
334             /* Store vr pair in savearea */
335             d = ((U64)regs->vf->vr[n2][n1] << 32)
336               | regs->vf->vr[n2+1][n1];
337             ARCH_DEP(vstore8)(d, n, gr1, regs);
338 
339             /* Update element number */
340             n1++;
341             regs->GR_L(gr1 + 1) &= 0x0000FFFF;
342             regs->GR_L(gr1 + 1) |= n1 << 16;
343             regs->GR_L(gr1) += 8;
344 #if 0
345             /* This is where the instruction may be interrupted */
346             UPD_PSW_IA(regs, PSW_IA(regs, -4));
347             return;
348 #endif
349         }
350 
351         /* Indicate vr pair saved */
352         regs->psw.cc = 2;
353 
354         /* Reset the VR changed bit */
355         RESET_VR_CHANGED(n2, regs);
356     }
357     else
358     {
359         regs->GR_L(gr1) += 8 * (VECTOR_SECTION_SIZE - n1);
360         /* vr pair not saved */
361         regs->psw.cc = 0;
362     }
363 
364     /* Set 2 if vr 14 is restored, 0 if not restored,
365        3 and 1 for other VR's respectively */
366     if(n2 != 14) regs->psw.cc++;
367 
368     /* Update the vector pair number, and zero element number */
369     n2 += 2;
370     regs->GR_L(gr1 + 1) = n2;
371 
372 }
373 
374 
375 /*-------------------------------------------------------------------*/
376 /* A64A VRSV  - Save VR                                        [RRE] */
377 /*-------------------------------------------------------------------*/
DEF_INST(v_save_vr)378 DEF_INST(v_save_vr)
379 {
380 int     gr1, unused2;
381 U32     n, n1, n2;
382 U64     d;
383 
384     RRE(inst, regs, gr1, unused2);
385 
386     VOP_CHECK(regs);
387 
388     ODD_CHECK(gr1, regs);
389 
390     /* n contrains the current save area address */
391     n = regs->GR_L(gr1) & ADDRESS_MAXWRAP(regs);
392 
393     /* n1 contains the starting element number */
394     if((n1 = regs->GR_L(gr1 + 1) >> 16) >= VECTOR_SECTION_SIZE)
395         ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION);
396 
397     /* Starting address must be eight times the section size aligned */
398     if((n - (8 * n1)) & ((VECTOR_SECTION_SIZE * VSA_ALIGN) - 1) )
399         ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION);
400 
401     /* n2 contains VR pair, which must be an even reg */
402     if((n2 = regs->GR_L(gr1 + 1) & 0x0000FFFF) & 0x0000FFF1)
403         ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION);
404 
405     if( VR_INUSE(n2, regs) )
406     {
407         for(; n1 < VECTOR_SECTION_SIZE; n1++)
408         {
409             /* Store vr pair in savearea */
410             d = ((U64)regs->vf->vr[n2][n1] << 32)
411               | regs->vf->vr[n2+1][n1];
412             ARCH_DEP(vstore8)(d, n, gr1, regs);
413 
414             /* Update element number */
415             n1++;
416             regs->GR_L(gr1 + 1) &= 0x0000FFFF;
417             regs->GR_L(gr1 + 1) |= n1 << 16;
418             regs->GR_L(gr1) += 8;
419 #if 0
420             /* This is where the instruction may be interrupted */
421             UPD_PSW_IA(regs, PSW_IA(regs, -4));
422             return;
423 #endif
424         }
425 
426         /* Indicate vr pair restored */
427         regs->psw.cc = 2;
428     }
429     else
430     {
431         regs->GR_L(gr1) += 8 * (VECTOR_SECTION_SIZE - n1);
432         /* Indicate vr pair not restored */
433         regs->psw.cc = 0;
434     }
435 
436     /* Set 2 if vr 14 is restored, 0 if not restored,
437        3 and 1 for other VR's respectively */
438     if(n2 != 14) regs->psw.cc++;
439 
440     /* Update the vector pair number, and zero element number */
441     n2 += 2;
442     regs->GR_L(gr1 + 1) = n2;
443 
444 }
445 
446 
447 /*-------------------------------------------------------------------*/
448 /* A680 VLVM  - Load VMR                                        [VS] */
449 /*-------------------------------------------------------------------*/
DEF_INST(v_load_vmr)450 DEF_INST(v_load_vmr)
451 {
452 int     rs2;
453 U32     n, n1;
454 
455     VS(inst, regs, rs2);
456 
457     VOP_CHECK(regs);
458 
459     /* Extract vector count (number of active bits in vmr) */
460     n = VECTOR_COUNT(regs);
461     n1 = n >> 3;
462 
463     ARCH_DEP(vfetchc)(regs->vf->vmr, n1,
464         regs->GR_L(rs2) & ADDRESS_MAXWRAP(regs), rs2, regs);
465 
466     /* Set the inactive bits to zero */
467     regs->vf->vmr[n1] &= 0x7F00 >> (n & 7);
468     for(n1++; n1 < sizeof(regs->vf->vmr); n1++)
469         regs->vf->vmr[n1] = 0;
470 
471 }
472 
473 
474 /*-------------------------------------------------------------------*/
475 /* A681 VLCVM - Load VMR Complement                             [VS] */
476 /*-------------------------------------------------------------------*/
DEF_INST(v_load_vmr_complement)477 DEF_INST(v_load_vmr_complement)
478 {
479 int     rs2;
480 U32     n, n1, n2;
481 
482     VS(inst, regs, rs2);
483 
484     VOP_CHECK(regs);
485 
486     /* Extract vector count (number of active bits in vmr) */
487     n = VECTOR_COUNT(regs);
488 
489     /* Number of bytes - 1 */
490     n1 = n >> 3;
491 
492     ARCH_DEP(vfetchc)(regs->vf->vmr, n1,
493         regs->GR_L(rs2) & ADDRESS_MAXWRAP(regs), rs2, regs);
494 
495     /* Complement all bits loaded */
496     for(n2 = 0; n2 <= n1; n2++)
497         regs->vf->vmr[n2] ^= 0xFF;
498 
499     /* Set the inactive bits to zero */
500     regs->vf->vmr[n1] &= 0x7F00 >> (n & 7);
501     for(n1++; n1 < sizeof(regs->vf->vmr); n1++)
502         regs->vf->vmr[n1] = 0;
503 
504 }
505 
506 
507 /*-------------------------------------------------------------------*/
508 /* A682 VSTVM - Store VMR                                       [VS] */
509 /*-------------------------------------------------------------------*/
DEF_INST(v_store_vmr)510 DEF_INST(v_store_vmr)
511 {
512 int     rs2;
513 U32     n;
514 
515     VS(inst, regs, rs2);
516 
517     VOP_CHECK(regs);
518 
519     /* Extract vector count (number of active bits in vmr) */
520     n = VECTOR_COUNT(regs);
521 
522     ARCH_DEP(vstorec)(regs->vf->vmr, n >> 3,
523             regs->GR_L(rs2) & ADDRESS_MAXWRAP(regs), rs2, regs);
524 
525 }
526 
527 
528 /*-------------------------------------------------------------------*/
529 /* A684 VNVM  - AND To VMR                                      [VS] */
530 /*-------------------------------------------------------------------*/
DEF_INST(v_and_to_vmr)531 DEF_INST(v_and_to_vmr)
532 {
533 int     rs2;
534 U32     n, n1, n2;
535 BYTE    workvmr[VECTOR_SECTION_SIZE/8];
536 
537     VS(inst, regs, rs2);
538 
539     VOP_CHECK(regs);
540 
541     /* Extract vector count (number of active bits in vmr) */
542     n = VECTOR_COUNT(regs);
543 
544     /* Number of bytes - 1 */
545     n1 = n >> 3;
546 
547     ARCH_DEP(vfetchc)(workvmr, n1,
548         regs->GR_L(rs2) & ADDRESS_MAXWRAP(regs), rs2, regs);
549 
550     /* And VMR with workvmr */
551     for(n2 = 0; n2 <= n1; n2++)
552         regs->vf->vmr[n2] &= workvmr[n2];
553 
554     /* zeroize remainder */
555     regs->vf->vmr[n1] &= 0x7F00 >> (n & 7);
556     for(n1++; n1 < sizeof(regs->vf->vmr); n1++)
557         regs->vf->vmr[n1] = 0;
558 
559 }
560 
561 
562 /*-------------------------------------------------------------------*/
563 /* A685 VOVM  - OR To VMR                                       [VS] */
564 /*-------------------------------------------------------------------*/
DEF_INST(v_or_to_vmr)565 DEF_INST(v_or_to_vmr)
566 {
567 int     rs2;
568 U32     n, n1, n2;
569 BYTE    workvmr[VECTOR_SECTION_SIZE/8];
570 
571     VS(inst, regs, rs2);
572 
573     VOP_CHECK(regs);
574 
575     /* Extract vector count (number of active bits in vmr) */
576     n = VECTOR_COUNT(regs);
577 
578     /* Number of bytes - 1 */
579     n1 = n >> 3;
580 
581     ARCH_DEP(vfetchc)(workvmr, n1,
582         regs->GR_L(rs2) & ADDRESS_MAXWRAP(regs), rs2, regs);
583 
584     /* OR VMR with workvmr */
585     for(n2 = 0; n2 <= n1; n2++)
586         regs->vf->vmr[n2] |= workvmr[n2];
587 
588     /* zeroize remainder */
589     regs->vf->vmr[n1] &= 0x7F00 >> (n & 7);
590     for(n1++; n1 < sizeof(regs->vf->vmr); n1++)
591         regs->vf->vmr[n1] = 0;
592 
593 }
594 
595 
596 /*-------------------------------------------------------------------*/
597 /* A686 VXVM  - Exclusive OR To VMR                             [VS] */
598 /*-------------------------------------------------------------------*/
DEF_INST(v_exclusive_or_to_vmr)599 DEF_INST(v_exclusive_or_to_vmr)
600 {
601 int     rs2;
602 U32     n, n1, n2;
603 BYTE    workvmr[VECTOR_SECTION_SIZE/8];
604 
605     VS(inst, regs, rs2);
606 
607     VOP_CHECK(regs);
608 
609     /* Extract vector count (number of active bits in vmr) */
610     n = VECTOR_COUNT(regs);
611 
612     /* Number of bytes - 1 */
613     n1 = n >> 3;
614 
615     ARCH_DEP(vfetchc)(workvmr, n1,
616         regs->GR_L(rs2) & ADDRESS_MAXWRAP(regs), rs2, regs);
617 
618     /* OR VMR with workvmr */
619     for(n2 = 0; n2 <= n1; n2++)
620         regs->vf->vmr[n2] ^= workvmr[n2];
621 
622     /* zeroize remainder */
623     regs->vf->vmr[n1] &= 0x7F00 >> (n & 7);
624     for(n1++; n1 < sizeof(regs->vf->vmr); n1++)
625         regs->vf->vmr[n1] = 0;
626 
627 }
628 
629 
630 /*-------------------------------------------------------------------*/
631 /* A6C0 VSRSV - Save VSR                                         [S] */
632 /*-------------------------------------------------------------------*/
DEF_INST(v_save_vsr)633 DEF_INST(v_save_vsr)
634 {
635 int     b2;                             /* Base of effective addr    */
636 VADR    effective_addr2;                /* Effective address         */
637 
638     S(inst, regs, b2, effective_addr2);
639 
640     VOP_CHECK(regs);
641 
642     DW_CHECK(effective_addr2, regs);
643 
644     ARCH_DEP(vstore8)(regs->vf->vsr, effective_addr2, b2, regs);
645 
646 }
647 
648 
649 /*-------------------------------------------------------------------*/
650 /* A6C1 VMRSV - Save VMR                                         [S] */
651 /*-------------------------------------------------------------------*/
DEF_INST(v_save_vmr)652 DEF_INST(v_save_vmr)
653 {
654 int     b2;                             /* Base of effective addr    */
655 VADR    effective_addr2;                /* Effective address         */
656 
657     S(inst, regs, b2, effective_addr2);
658 
659     VOP_CHECK(regs);
660 
661     ARCH_DEP(vstorec)(regs->vf->vmr, sizeof(regs->vf->vmr) - 1,
662         effective_addr2, b2, regs);
663 
664 }
665 
666 
667 /*-------------------------------------------------------------------*/
668 /* A6C2 VSRRS - Restore VSR                                      [S] */
669 /*-------------------------------------------------------------------*/
DEF_INST(v_restore_vsr)670 DEF_INST(v_restore_vsr)
671 {
672 int     b2;                             /* Base of effective addr    */
673 VADR    effective_addr2;                /* Effective address         */
674 U32     n1, n2;
675 U64     d;
676 
677     S(inst, regs, b2, effective_addr2);
678 
679     VOP_CHECK(regs);
680 
681     DW_CHECK(effective_addr2, regs);
682 
683     /* Fetch operand */
684     d = ARCH_DEP(vfetch8)(effective_addr2, b2, regs);
685 
686     /* Check for reserved bits nonzero,
687        vector count not greater then section size and
688        vector interruption index not greater then section size */
689     if((d & VSR_RESV)
690         || ((d & VSR_VCT) >> 32) > VECTOR_SECTION_SIZE
691         || ((d & VSR_VIX) >> 16) >= VECTOR_SECTION_SIZE)
692         ARCH_DEP(program_interrupt)(regs, PGM_SPECIFICATION_EXCEPTION);
693 
694     /* In problem state the change bit are set corresponding
695        the inuse bits */
696     if(PROBSTATE(&regs->psw))
697     {
698         d &= ~VSR_VCH;
699         d |= (d & VSR_VIU) >> 8;
700     }
701 
702     /* Clear any VRs whose inuse bits are being set to zero */
703     for(n1 = 0; n1 < 16; n1 += 2)
704     {
705         if( VR_INUSE(n1, regs)
706             && !((d & VSR_VIU) & (VSR_VCH0 >> (n1 >> 1))) )
707             for(n2 = 0; n2 < VECTOR_SECTION_SIZE; n2++)
708             {
709                 regs->vf->vr[n1][n2] = 0;
710                 regs->vf->vr[n1+1][n2] = 0;
711             }
712     }
713 
714     /* Update the vector status register */
715     regs->vf->vsr = d;
716 
717 }
718 
719 
720 /*-------------------------------------------------------------------*/
721 /* A6C3 VMRRS - Restore VMR                                      [S] */
722 /*-------------------------------------------------------------------*/
DEF_INST(v_restore_vmr)723 DEF_INST(v_restore_vmr)
724 {
725 int     b2;                             /* Base of effective addr    */
726 VADR    effective_addr2;                /* Effective address         */
727 
728     S(inst, regs, b2, effective_addr2);
729 
730     VOP_CHECK(regs);
731 
732     ARCH_DEP(vfetchc)(regs->vf->vmr, sizeof(regs->vf->vmr) - 1,
733         effective_addr2, b2, regs);
734 
735 }
736 
737 
738 /*-------------------------------------------------------------------*/
739 /* A6C4 VLVCA - Load VCT from Address                            [S] */
740 /*-------------------------------------------------------------------*/
DEF_INST(v_load_vct_from_address)741 DEF_INST(v_load_vct_from_address)
742 {
743 int     b2;                             /* Base of effective addr    */
744 VADR    effective_addr2;                /* Effective address         */
745 U32     n;
746 
747     S_NW(inst, regs, b2, effective_addr2);
748 
749     VOP_CHECK(regs);
750 
751     regs->psw.cc = ((S32)effective_addr2 == 0) ? 0 :
752                    ((S32)effective_addr2 < 0) ? 1 :
753                    ((S32)effective_addr2 > VECTOR_SECTION_SIZE) ? 2 : 3;
754 
755     n = (S32)effective_addr2 < 0 ? 0 :
756         (S32)effective_addr2 > VECTOR_SECTION_SIZE ?
757                  VECTOR_SECTION_SIZE : (S32)effective_addr2;
758 
759     regs->vf->vsr &= ~VSR_VCT;
760     regs->vf->vsr |= (U64)n << 32;
761 
762 }
763 
764 
765 /*-------------------------------------------------------------------*/
766 /* A6C5 VRCL  - Clear VR                                         [S] */
767 /*-------------------------------------------------------------------*/
DEF_INST(v_clear_vr)768 DEF_INST(v_clear_vr)
769 {
770 int     b2;                             /* Base of effective addr    */
771 VADR    effective_addr2;                /* Effective address         */
772 U32     n, n1, n2;
773 
774     S(inst, regs, b2, effective_addr2);
775 
776     VOP_CHECK(regs);
777 
778     /* Set vector interruption index to zero */
779     regs->vf->vsr &= ~VSR_VIX;
780 
781     /* Clear vr's identified in the bit mask
782        n1 contains the vr number
783        n2 contains the bitmask identifying the vr number
784        n contains the element number */
785     for(n1 = 0, n2 = 0x80; n1 <= 14; n1 += 2, n2 >>= 1)
786         if(effective_addr2 & n2)
787         {
788             for(n = 0; n < VECTOR_SECTION_SIZE; n++)
789             {
790                 regs->vf->vr[n1][n] = 0;
791                 regs->vf->vr[n1+1][n] = 0;
792             }
793             RESET_VR_INUSE(n1, regs);
794         }
795 
796 }
797 
798 
799 /*-------------------------------------------------------------------*/
800 /* A6C6 VSVMM - Set Vector Mask Mode                             [S] */
801 /*-------------------------------------------------------------------*/
DEF_INST(v_set_vector_mask_mode)802 DEF_INST(v_set_vector_mask_mode)
803 {
804 int     b2;                             /* Base of effective addr    */
805 VADR    effective_addr2;                /* Effective address         */
806 
807     S(inst, regs, b2, effective_addr2);
808 
809     VOP_CHECK(regs);
810 
811     if(effective_addr2 & 1)
812         regs->vf->vsr |= VSR_M;
813     else
814         regs->vf->vsr &= ~VSR_M;
815 
816 }
817 
818 
819 /*-------------------------------------------------------------------*/
820 /* A6C7 VLVXA - Load VIX from Address                            [S] */
821 /*-------------------------------------------------------------------*/
DEF_INST(v_load_vix_from_address)822 DEF_INST(v_load_vix_from_address)
823 {
824 int     b2;                             /* Base of effective addr    */
825 VADR    effective_addr2;                /* Effective address         */
826 U32     n;
827 
828     S_NW(inst, regs, b2, effective_addr2);
829 
830     VOP_CHECK(regs);
831 
832     regs->psw.cc = ((S32)effective_addr2 == 0) ? 0 :
833                    ((S32)effective_addr2 < 0) ? 1 :
834                    ((S32)effective_addr2 < VECTOR_COUNT(regs)) ? 2 : 3;
835 
836     n = (S32)effective_addr2 < 0 ? 0 :
837         (S32)effective_addr2 > VECTOR_SECTION_SIZE ?
838                  VECTOR_SECTION_SIZE : (S32)effective_addr2;
839 
840     regs->vf->vsr &= ~VSR_VIX;
841     regs->vf->vsr |= (U64)n << 16;
842 
843 }
844 
845 
846 /*-------------------------------------------------------------------*/
847 /* A6C8 VSTVP - Store Vector Parameters                          [S] */
848 /*-------------------------------------------------------------------*/
DEF_INST(v_store_vector_parameters)849 DEF_INST(v_store_vector_parameters)
850 {
851 int     b2;                             /* Base of effective addr    */
852 VADR    effective_addr2;                /* Effective address         */
853 
854     S(inst, regs, b2, effective_addr2);
855 
856     VOP_CHECK(regs);
857 
858     FW_CHECK(effective_addr2, regs);
859 
860     /* Store the section size and partial sum number */
861     ARCH_DEP(vstore4)(VECTOR_SECTION_SIZE << 16 | VECTOR_PARTIAL_SUM_NUMBER,
862                                   effective_addr2, b2, regs);
863 
864 }
865 
866 
867 /*-------------------------------------------------------------------*/
868 /* A6CA VACSV - Save VAC                                         [S] */
869 /*-------------------------------------------------------------------*/
DEF_INST(v_save_vac)870 DEF_INST(v_save_vac)
871 {
872 int     b2;                             /* Base of effective addr    */
873 VADR    effective_addr2;                /* Effective address         */
874 
875     S(inst, regs, b2, effective_addr2);
876 
877     VOP_CHECK(regs);
878 
879     PRIV_CHECK(regs);
880 
881     DW_CHECK(effective_addr2, regs);
882 
883 #if defined(_FEATURE_SIE)
884     if(SIE_STATB(regs, IC3, VACSV))
885         longjmp(regs->progjmp, SIE_INTERCEPT_INST);
886 #endif /*defined(_FEATURE_SIE)*/
887 
888     ARCH_DEP(vstore8)(regs->vf->vac, effective_addr2, b2, regs);
889 
890 }
891 
892 
893 /*-------------------------------------------------------------------*/
894 /* A6CB VACRS - Restore VAC                                      [S] */
895 /*-------------------------------------------------------------------*/
DEF_INST(v_restore_vac)896 DEF_INST(v_restore_vac)
897 {
898 int     b2;                             /* Base of effective addr    */
899 VADR    effective_addr2;                /* Effective address         */
900 
901     S(inst, regs, b2, effective_addr2);
902 
903     VOP_CHECK(regs);
904 
905     PRIV_CHECK(regs);
906 
907     DW_CHECK(effective_addr2, regs);
908 
909 #if defined(_FEATURE_SIE)
910     if(SIE_STATB(regs, IC3, VACRS))
911         longjmp(regs->progjmp, SIE_INTERCEPT_INST);
912 #endif /*defined(_FEATURE_SIE)*/
913 
914     regs->vf->vac = ARCH_DEP(vfetch8)(effective_addr2, b2, regs) & VAC_MASK;
915 
916 }
917 
918 
919 #endif /*defined(FEATURE_VECTOR_FACILITY)*/
920 
921 
922 #if !defined(_GEN_ARCH)
923 
924 #if defined(_ARCHMODE2)
925  #define  _GEN_ARCH _ARCHMODE2
926  #include "vector.c"
927 #endif
928 
929 #if defined(_ARCHMODE3)
930  #undef   _GEN_ARCH
931  #define  _GEN_ARCH _ARCHMODE3
932  #include "vector.c"
933 #endif
934 
935 #endif /*!defined(_GEN_ARCH)*/
936