1 /* EXTERNAL.C   (c) Copyright Roger Bowler, 1999-2009                */
2 /*              ESA/390 External Interrupt and Timer                 */
3 
4 /* Interpretive Execution - (c) Copyright Jan Jaeger, 1999-2009      */
5 /* z/Architecture support - (c) Copyright Jan Jaeger, 1999-2009      */
6 
7 /*-------------------------------------------------------------------*/
8 /* This module implements external interrupt, timer, and signalling  */
9 /* functions for the Hercules ESA/390 emulator.                      */
10 /*-------------------------------------------------------------------*/
11 
12 /*-------------------------------------------------------------------*/
13 /* Additional credits:                                               */
14 /*      TOD clock offset contributed by Jay Maynard                  */
15 /*      Correction to timer interrupt by Valery Pogonchenko          */
16 /*      TOD clock drag factor contributed by Jan Jaeger              */
17 /*      CPU timer and clock comparator interrupt improvements by     */
18 /*          Jan Jaeger, after a suggestion by Willem Koynenberg      */
19 /*      Prevent TOD clock and CPU timer from going back - Jan Jaeger */
20 /*      Use longjmp on all interrupt types - Jan Jaeger              */
21 /*      Fix todclock - Jay Maynard                                   */
22 /*      Modifications for Interpretive Execution (SIE) by Jan Jaeger */
23 /*-------------------------------------------------------------------*/
24 
25 #include "hstdinc.h"
26 
27 #if !defined(_HENGINE_DLL_)
28 #define _HENGINE_DLL_
29 #endif
30 
31 #if !defined(_EXTERNAL_C_)
32 #define _EXTERNAL_C_
33 #endif
34 
35 #include "hercules.h"
36 #include "opcode.h"
37 #include "inline.h"
38 
39 /*-------------------------------------------------------------------*/
40 /* Load external interrupt new PSW                                   */
41 /*-------------------------------------------------------------------*/
ARCH_DEP(external_interrupt)42 static void ARCH_DEP(external_interrupt) (int code, REGS *regs)
43 {
44 RADR    pfx;
45 PSA     *psa;
46 int     rc;
47 
48     PTT(PTT_CL_SIG,"*EXTINT",code,regs->cpuad,regs->psw.IA_L);
49 
50 #if defined(_FEATURE_SIE)
51     /* Set the main storage reference and change bits */
52     if(SIE_MODE(regs)
53 #if defined(_FEATURE_EXPEDITED_SIE_SUBSET)
54                        && !SIE_FEATB(regs, S, EXP_TIMER)
55 #endif /*defined(_FEATURE_EXPEDITED_SIE_SUBSET)*/
56 #if defined(_FEATURE_EXTERNAL_INTERRUPT_ASSIST)
57                        && !SIE_FEATB(regs, EC0, EXTA)
58 #endif
59                                                             )
60     {
61         /* Point to SIE copy of PSA in state descriptor */
62         psa = (void*)(regs->hostregs->mainstor + SIE_STATE(regs) + SIE_IP_PSA_OFFSET);
63         STORAGE_KEY(SIE_STATE(regs), regs->hostregs) |= (STORKEY_REF | STORKEY_CHANGE);
64     }
65     else
66 #endif /*defined(_FEATURE_SIE)*/
67     {
68         /* Point to PSA in main storage */
69         pfx = regs->PX;
70 #if defined(_FEATURE_EXPEDITED_SIE_SUBSET)
71         SIE_TRANSLATE(&pfx, ACCTYPE_SIE, regs);
72 #endif /*defined(_FEATURE_EXPEDITED_SIE_SUBSET)*/
73         psa = (void*)(regs->mainstor + pfx);
74         STORAGE_KEY(pfx, regs) |= (STORKEY_REF | STORKEY_CHANGE);
75     }
76 
77     /* Store the interrupt code in the PSW */
78     regs->psw.intcode = code;
79 
80 
81     /* Zero extcpuad field unless extcall or ems signal or blockio */
82     if(code != EXT_EXTERNAL_CALL_INTERRUPT
83 #if defined(FEATURE_VM_BLOCKIO)
84     && code != EXT_BLOCKIO_INTERRUPT
85 #endif /* defined(FEATURE_VM_BLOCKIO) */
86     && code != EXT_EMERGENCY_SIGNAL_INTERRUPT)
87         STORE_HW(psa->extcpad,0);
88 
89 #if defined(FEATURE_BCMODE)
90     /* For ECMODE, store external interrupt code at PSA+X'86' */
91     if ( ECMODE(&regs->psw) )
92 #endif /*defined(FEATURE_BCMODE)*/
93         STORE_HW(psa->extint,code);
94 
95     if ( !SIE_MODE(regs)
96 #if defined(_FEATURE_EXPEDITED_SIE_SUBSET)
97                        || SIE_FEATB(regs, S, EXP_TIMER)
98 #endif /*defined(_FEATURE_EXPEDITED_SIE_SUBSET)*/
99 #if defined(_FEATURE_EXTERNAL_INTERRUPT_ASSIST)
100                        || SIE_FEATB(regs, EC0, EXTA)
101 #endif
102        )
103     {
104         /* Store current PSW at PSA+X'18' */
105         ARCH_DEP(store_psw) (regs, psa->extold);
106 
107         /* Load new PSW from PSA+X'58' */
108         rc = ARCH_DEP(load_psw) (regs, psa->extnew);
109 
110         if ( rc )
111         {
112             RELEASE_INTLOCK(regs);
113             ARCH_DEP(program_interrupt)(regs, rc);
114         }
115     }
116 
117 #if defined(FEATURE_INTERVAL_TIMER)
118     /* Ensure the interval timer is uptodate */
119     ARCH_DEP(store_int_timer_nolock) (regs);
120 #endif
121     RELEASE_INTLOCK(regs);
122 
123 
124     if ( SIE_MODE(regs)
125 #if defined(_FEATURE_EXPEDITED_SIE_SUBSET)
126                        && !SIE_FEATB(regs, S, EXP_TIMER)
127 #endif /*defined(_FEATURE_EXPEDITED_SIE_SUBSET)*/
128 #if defined(_FEATURE_EXTERNAL_INTERRUPT_ASSIST)
129                        && !SIE_FEATB(regs, EC0, EXTA)
130 #endif
131        )
132         longjmp (regs->progjmp, SIE_INTERCEPT_EXT);
133     else
134         longjmp (regs->progjmp, SIE_NO_INTERCEPT);
135 
136 } /* end function external_interrupt */
137 
138 /*-------------------------------------------------------------------*/
139 /* Perform external interrupt if pending                             */
140 /*                                                                   */
141 /* This function is called by the CPU to check whether any           */
142 /* external interrupt conditions are pending, and to perform         */
143 /* an external interrupt if so.  If multiple external interrupts     */
144 /* are pending, then only the highest priority interrupt is taken,   */
145 /* and any other interrupts remain pending.  Remaining interrupts    */
146 /* will be processed one-by-one during subsequent calls.             */
147 /*                                                                   */
148 /* Important notes:                                                  */
149 /* (i)  This function must NOT be called if the CPU is disabled      */
150 /*      for external interrupts (PSW bit 7 is zero).                 */
151 /* (ii) The caller MUST hold the interrupt lock (sysblk.intlock)     */
152 /*      to ensure correct serialization of interrupt pending bits.   */
153 /*-------------------------------------------------------------------*/
ARCH_DEP(perform_external_interrupt)154 void ARCH_DEP(perform_external_interrupt) (REGS *regs)
155 {
156 PSA    *psa;                            /* -> Prefixed storage area  */
157 U16     cpuad;                          /* Originating CPU address   */
158 #if defined(FEATURE_VM_BLOCKIO)
159 #if defined(FEATURE_ESAME)
160 RADR    servpadr;      /* Address of 64-bit block I/O interrupt */
161 #endif
162 U16     servcode;      /* Service Signal or Block I/O Interrupt code */
163 #endif /* defined(FEATURE_VM_BLOCKIO) */
164 
165     /* External interrupt if console interrupt key was depressed */
166     if ( OPEN_IC_INTKEY(regs) && !SIE_MODE(regs) )
167     {
168         logmsg (_("HHCCP023I External interrupt: Interrupt key\n"));
169 
170         /* Reset interrupt key pending */
171         OFF_IC_INTKEY;
172 
173         /* Generate interrupt key interrupt */
174         ARCH_DEP(external_interrupt) (EXT_INTERRUPT_KEY_INTERRUPT, regs);
175     }
176 
177     /* External interrupt if malfunction alert is pending */
178     if (OPEN_IC_MALFALT(regs))
179     {
180         /* Find first CPU which generated a malfunction alert */
181         for (cpuad = 0; regs->malfcpu[cpuad] == 0; cpuad++)
182         {
183             if (cpuad >= MAX_CPU)
184             {
185                 OFF_IC_MALFALT(regs);
186                 return;
187             }
188         } /* end for(cpuad) */
189 
190 // /*debug*/ logmsg (_("External interrupt: Malfuction Alert from CPU %d\n"),
191 // /*debug*/    cpuad);
192 
193         /* Reset the indicator for the CPU which was found */
194         regs->malfcpu[cpuad] = 0;
195 
196         /* Store originating CPU address at PSA+X'84' */
197         psa = (void*)(regs->mainstor + regs->PX);
198         STORE_HW(psa->extcpad,cpuad);
199 
200         /* Reset emergency signal pending flag if there are
201            no other CPUs which generated emergency signal */
202         OFF_IC_MALFALT(regs);
203         while (++cpuad < MAX_CPU)
204         {
205             if (regs->malfcpu[cpuad])
206             {
207                 ON_IC_MALFALT(regs);
208                 break;
209             }
210         } /* end while */
211 
212         /* Generate emergency signal interrupt */
213         ARCH_DEP(external_interrupt) (EXT_MALFUNCTION_ALERT_INTERRUPT, regs);
214     }
215 
216 
217     /* External interrupt if emergency signal is pending */
218     if (OPEN_IC_EMERSIG(regs))
219     {
220         /* Find first CPU which generated an emergency signal */
221         for (cpuad = 0; regs->emercpu[cpuad] == 0; cpuad++)
222         {
223             if (cpuad >= MAX_CPU)
224             {
225                 OFF_IC_EMERSIG(regs);
226                 return;
227             }
228         } /* end for(cpuad) */
229 
230 // /*debug*/ logmsg (_("External interrupt: Emergency Signal from CPU %d\n"),
231 // /*debug*/    cpuad);
232 
233         /* Reset the indicator for the CPU which was found */
234         regs->emercpu[cpuad] = 0;
235 
236         /* Store originating CPU address at PSA+X'84' */
237         psa = (void*)(regs->mainstor + regs->PX);
238         STORE_HW(psa->extcpad,cpuad);
239 
240         /* Reset emergency signal pending flag if there are
241            no other CPUs which generated emergency signal */
242         OFF_IC_EMERSIG(regs);
243         while (++cpuad < MAX_CPU)
244         {
245             if (regs->emercpu[cpuad])
246             {
247                 ON_IC_EMERSIG(regs);
248                 break;
249             }
250         } /* end while */
251 
252         /* Generate emergency signal interrupt */
253         ARCH_DEP(external_interrupt) (EXT_EMERGENCY_SIGNAL_INTERRUPT, regs);
254     }
255 
256     /* External interrupt if external call is pending */
257     if (OPEN_IC_EXTCALL(regs))
258     {
259 //  /*debug*/logmsg (_("External interrupt: External Call from CPU %d\n"),
260 //  /*debug*/       regs->extccpu);
261 
262         /* Reset external call pending */
263         OFF_IC_EXTCALL(regs);
264 
265         /* Store originating CPU address at PSA+X'84' */
266         psa = (void*)(regs->mainstor + regs->PX);
267         STORE_HW(psa->extcpad,regs->extccpu);
268 
269         /* Generate external call interrupt */
270         ARCH_DEP(external_interrupt) (EXT_EXTERNAL_CALL_INTERRUPT, regs);
271     }
272 
273     /* External interrupt if TOD clock exceeds clock comparator */
274     if ( tod_clock(regs) > regs->clkc
275         && OPEN_IC_CLKC(regs) )
276     {
277         if (CPU_STEPPING_OR_TRACING_ALL)
278         {
279             logmsg (_("HHCCP024I External interrupt: Clock comparator\n"));
280         }
281         ARCH_DEP(external_interrupt) (EXT_CLOCK_COMPARATOR_INTERRUPT, regs);
282     }
283 
284     /* External interrupt if CPU timer is negative */
285     if ( CPU_TIMER(regs) < 0
286         && OPEN_IC_PTIMER(regs) )
287     {
288         if (CPU_STEPPING_OR_TRACING_ALL)
289         {
290             logmsg (_("HHCCP025I External interrupt: CPU timer=%16.16" I64_FMT "X\n"),
291                     (long long)CPU_TIMER(regs) << 8);
292         }
293         ARCH_DEP(external_interrupt) (EXT_CPU_TIMER_INTERRUPT, regs);
294     }
295 
296     /* External interrupt if interval timer interrupt is pending */
297 #if defined(FEATURE_INTERVAL_TIMER)
298     if (OPEN_IC_ITIMER(regs)
299 #if defined(_FEATURE_SIE)
300         && !(SIE_STATB(regs, M, ITMOF))
301 #endif /*defined(_FEATURE_SIE)*/
302         )
303     {
304         if (CPU_STEPPING_OR_TRACING_ALL)
305         {
306             logmsg (_("HHCCP026I External interrupt: Interval timer\n"));
307         }
308         OFF_IC_ITIMER(regs);
309         ARCH_DEP(external_interrupt) (EXT_INTERVAL_TIMER_INTERRUPT, regs);
310     }
311 
312 #if defined(FEATURE_ECPSVM)
313     if ( OPEN_IC_ECPSVTIMER(regs) )
314     {
315         OFF_IC_ECPSVTIMER(regs);
316         ARCH_DEP(external_interrupt) (EXT_VINTERVAL_TIMER_INTERRUPT,regs);
317     }
318 #endif /*FEATURE_ECPSVM*/
319 #endif /*FEATURE_INTERVAL_TIMER*/
320 
321     /* External interrupt if service signal is pending */
322     if ( OPEN_IC_SERVSIG(regs) && !SIE_MODE(regs) )
323     {
324 
325 #if defined(FEATURE_VM_BLOCKIO)
326 
327         /* Note: Both Block I/O and Service Signal are enabled by the */
328         /* the same CR0 bit.  Hence they are handled in the same code */
329         switch(sysblk.servcode)
330         {
331         case EXT_BLOCKIO_INTERRUPT:  /* VM Block I/O Interrupt */
332 
333            if (sysblk.biodev->ccwtrace)
334            {
335            logmsg (_("%4.4X:HHCCP031I Processing Block I/O interrupt: "
336                 "code=%4.4X parm=%16.16X status=%2.2X subcode=%2.2X\n"),
337                 sysblk.biodev->devnum,
338                 sysblk.servcode,
339                 sysblk.bioparm,
340                 sysblk.biostat,
341                 sysblk.biosubcd
342                 );
343            }
344 
345            servcode = EXT_BLOCKIO_INTERRUPT;
346 
347 #if defined(FEATURE_ESAME)
348 /* Real address used to store the 64-bit interrupt parameter */
349 #define VM_BLOCKIO_INT_PARM 0x11B8
350            if (sysblk.biosubcd == 0x07)
351            {
352            /* 8-byte interrupt parm */
353 
354                if (CPU_STEPPING_OR_TRACING_ALL)
355                {
356                   logmsg (_("HHCCP028I External interrupt: Block I/O %16.16X\n"),
357                      sysblk.bioparm);
358                }
359 
360                /* Set the main storage reference and change bits   */
361                /* for 64-bit interruption parameter.               */
362                /* Note: This is handled for the first 4K page in   */
363                /* ARCH_DEP(external_interrupt), but not for the    */
364                /* the second 4K page used for the 64-bit interrupt */
365                /* parameter.                                       */
366 
367                /* Point to 2nd page of PSA in main storage */
368                servpadr=APPLY_PREFIXING(VM_BLOCKIO_INT_PARM,regs->PX);
369 
370                STORAGE_KEY(servpadr, regs)
371                      |= (STORKEY_REF | STORKEY_CHANGE);
372 
373 #if 0
374                /* Store the 64-bit interrupt parameter */
375                logmsg (_("Saving 64-bit Block I/O interrupt parm at "
376                          "%16.16X: %16.16X\n"),
377                          servpadr,
378                          sysblk.bioparm
379                       );
380 #endif
381 
382                STORE_DW(regs->mainstor + servpadr,sysblk.bioparm);
383                psa = (void*)(regs->mainstor + regs->PX);
384            }
385            else
386            {
387 #endif  /* defined(FEATURE_ESAME) */
388 
389            /* 4-byte interrupt parm */
390 
391               if (CPU_STEPPING_OR_TRACING_ALL)
392               {
393                  logmsg (_("HHCCP028I External interrupt: Block I/O %8.8X\n"),
394                        (U32)sysblk.bioparm);
395               }
396 
397               /* Store Block I/O parameter at PSA+X'80' */
398               psa = (void*)(regs->mainstor + regs->PX);
399               STORE_FW(psa->extparm,(U32)sysblk.bioparm);
400 
401 #if defined(FEATURE_ESAME)
402            }
403 #endif
404 
405            /* Store sub-interruption code and status at PSA+X'84' */
406            STORE_HW(psa->extcpad,(sysblk.biosubcd<<8)|sysblk.biostat);
407 
408            /* Reset interruption data */
409            sysblk.bioparm  = 0;
410            sysblk.biosubcd = 0;
411            sysblk.biostat  = 0;
412 
413            break;
414 
415         case EXT_SERVICE_SIGNAL_INTERRUPT: /* Service Signal */
416         default:
417              servcode = EXT_SERVICE_SIGNAL_INTERRUPT;
418 
419             /* Apply prefixing if the parameter is a storage address */
420             if ( (sysblk.servparm & SERVSIG_ADDR) )
421                 sysblk.servparm =
422                      APPLY_PREFIXING (sysblk.servparm, regs->PX);
423 
424              if (CPU_STEPPING_OR_TRACING_ALL)
425              {
426                  logmsg (_("HHCCP027I External interrupt: Service signal %8.8X\n"),
427                     sysblk.servparm);
428              }
429 
430              /* Store service signal parameter at PSA+X'80' */
431              psa = (void*)(regs->mainstor + regs->PX);
432              STORE_FW(psa->extparm,sysblk.servparm);
433 
434         }  /* end switch(sysblk.servcode) */
435         /* Reset service parameter */
436         sysblk.servparm = 0;
437 
438         /* Reset service code */
439         sysblk.servcode = 0;
440 
441         /* Reset service signal pending */
442         OFF_IC_SERVSIG;
443 
444         /* Generate service signal interrupt */
445         ARCH_DEP(external_interrupt) (servcode, regs);
446 
447 #else /* defined(FEATURE_VM_BLOCKIO) */
448 
449         /* Apply prefixing if the parameter is a storage address */
450         if ( (sysblk.servparm & SERVSIG_ADDR) )
451             sysblk.servparm =
452                 APPLY_PREFIXING (sysblk.servparm, regs->PX);
453 
454         if (CPU_STEPPING_OR_TRACING_ALL)
455         {
456             logmsg (_("HHCCP027I External interrupt: Service signal %8.8X\n"),
457                     sysblk.servparm);
458         }
459 
460         /* Store service signal parameter at PSA+X'80' */
461         psa = (void*)(regs->mainstor + regs->PX);
462         STORE_FW(psa->extparm,sysblk.servparm);
463 
464         /* Reset service parameter */
465         sysblk.servparm = 0;
466 
467         /* Reset service signal pending */
468         OFF_IC_SERVSIG;
469 
470         /* Generate service signal interrupt */
471         ARCH_DEP(external_interrupt) (EXT_SERVICE_SIGNAL_INTERRUPT, regs);
472 
473 #endif /* defined(FEATURE_VM_BLOCKIO) */
474 
475     }  /* end OPEN_IC_SERVSIG(regs) */
476 
477 } /* end function perform_external_interrupt */
478 
479 
480 /*-------------------------------------------------------------------*/
481 /* Store Status                                                      */
482 /* Input:                                                            */
483 /*      sregs   Register context of CPU whose status is to be stored */
484 /*      aaddr   A valid absolute address of a 512-byte block into    */
485 /*              which status is to be stored                         */
486 /*              For an implicit store status, or an operator         */
487 /*              initiated store status the absolute address will be  */
488 /*              zero, for a store status at address order the        */
489 /*              supplied address will be nonzero                     */
490 /*-------------------------------------------------------------------*/
ARCH_DEP(store_status)491 void ARCH_DEP(store_status) (REGS *ssreg, RADR aaddr)
492 {
493 int     i;                              /* Array subscript           */
494 PSA     *sspsa;                         /* -> Store status area      */
495 
496     /* Set reference and change bits */
497     STORAGE_KEY(aaddr, ssreg) |= (STORKEY_REF | STORKEY_CHANGE);
498 #if defined(FEATURE_ESAME)
499     /* The ESAME PSA is two pages in size */
500     if(!aaddr)
501         STORAGE_KEY(aaddr + 4096, ssreg) |= (STORKEY_REF | STORKEY_CHANGE);
502 #endif /*defined(FEATURE_ESAME)*/
503 
504 #if defined(FEATURE_ESAME)
505     /* For store status at address, we must adjust the PSA offset */
506     /* ZZ THIS TEST IS NOT CONCLUSIVE */
507     if(aaddr != 0 && aaddr != ssreg->PX)
508         aaddr -= 512 + 4096 ;
509 #endif
510 
511     aaddr &= 0x7FFFFE00;
512 
513     /* Point to the PSA into which status is to be stored */
514     sspsa = (void*)(ssreg->mainstor + aaddr);
515 
516     /* Store CPU timer in bytes 216-223 */
517     STORE_DW(sspsa->storeptmr, cpu_timer(ssreg));
518 
519     /* Store clock comparator in bytes 224-231 */
520 #if defined(FEATURE_ESAME)
521     STORE_DW(sspsa->storeclkc, ssreg->clkc);
522 #else /*defined(FEATURE_ESAME)*/
523     STORE_DW(sspsa->storeclkc, ssreg->clkc << 8);
524 #endif /*defined(FEATURE_ESAME)*/
525 
526     /* Store PSW in bytes 256-263 */
527     ARCH_DEP(store_psw) (ssreg, sspsa->storepsw);
528 
529     /* Store prefix register in bytes 264-267 */
530     STORE_FW(sspsa->storepfx,ssreg->PX);
531 
532 #if defined(FEATURE_ESAME)
533     /* Store Floating Point Control Register */
534     STORE_FW(sspsa->storefpc,ssreg->fpc);
535 
536     /* Store TOD Programable register */
537     STORE_FW(sspsa->storetpr,ssreg->todpr);
538 #endif /*defined(FEATURE_ESAME)*/
539 
540 #if defined(_900)
541     /* Only store the arch mode indicator for a PSA type store status */
542     if(!aaddr)
543 #if defined(FEATURE_ESAME)
544         sspsa->arch = 1;
545 #else /*defined(FEATURE_ESAME)*/
546         sspsa->arch = 0;
547 #endif /*defined(FEATURE_ESAME)*/
548 #endif /*defined(_900)*/
549 
550     /* Store access registers in bytes 288-351 */
551     for (i = 0; i < 16; i++)
552         STORE_FW(sspsa->storear[i],ssreg->AR(i));
553 
554     /* Store floating-point registers in bytes 352-383 */
555 #if defined(FEATURE_ESAME)
556     for (i = 0; i < 32; i++)
557 #else /*!defined(FEATURE_ESAME)*/
558     for (i = 0; i < 8; i++)
559 #endif /*!defined(FEATURE_ESAME)*/
560         STORE_FW(sspsa->storefpr[i],ssreg->fpr[i]);
561 
562     /* Store general-purpose registers in bytes 384-447 */
563     for (i = 0; i < 16; i++)
564         STORE_W(sspsa->storegpr[i],ssreg->GR(i));
565 
566     /* Store control registers in bytes 448-511 */
567     for (i = 0; i < 16; i++)
568         STORE_W(sspsa->storecr[i],ssreg->CR(i));
569 
570 } /* end function store_status */
571 
572 
573 #if !defined(_GEN_ARCH)
574 
575 #if defined(_ARCHMODE2)
576  #define  _GEN_ARCH _ARCHMODE2
577  #include "external.c"
578 #endif
579 
580 #if defined(_ARCHMODE3)
581  #undef   _GEN_ARCH
582  #define  _GEN_ARCH _ARCHMODE3
583  #include "external.c"
584 #endif
585 
586 
store_status(REGS * ssreg,U64 aaddr)587 void store_status (REGS *ssreg, U64 aaddr)
588 {
589     switch(ssreg->arch_mode) {
590 #if defined(_370)
591         case ARCH_370:
592             aaddr &= 0x7FFFFFFF;
593             s370_store_status (ssreg, aaddr);
594             break;
595 #endif
596 #if defined(_390)
597         case ARCH_390:
598             aaddr &= 0x7FFFFFFF;
599             s390_store_status (ssreg, aaddr);
600             break;
601 #endif
602 #if defined(_900)
603         case ARCH_900:
604             z900_store_status (ssreg, aaddr);
605             break;
606 #endif
607     }
608 }
609 #endif /*!defined(_GEN_ARCH)*/
610