1 /* INLINE.H     (c) Copyright Jan Jaeger, 2000-2009                  */
2 /*              Inline function definitions                          */
3 
4 /* Original author Roger Bowler, 1999                                */
5 /* Interpretive Execution - (c) Copyright Jan Jaeger, 1999-2009      */
6 /* z/Architecture support - (c) Copyright Jan Jaeger, 1999-2009      */
7 
8 /* Storage protection override fix               Jan Jaeger 31/08/00 */
9 /* ESAME low-address protection          v208d Roger Bowler 20/01/01 */
10 /* ESAME subspace replacement            v208e Roger Bowler 27/01/01 */
11 /* Multiply/Divide Logical instructions         Vic Cross 13/02/2001 */
12 
13 // #define INLINE_STORE_FETCH_ADDR_CHECK
14 
15 #if defined(FEATURE_DUAL_ADDRESS_SPACE)
16 _DAT_C_STATIC U16 ARCH_DEP(translate_asn) (U16 asn, REGS *regs,
17         U32 *asteo, U32 aste[]);
18 _DAT_C_STATIC int ARCH_DEP(authorize_asn) (U16 ax, U32 aste[],
19         int atemask, REGS *regs);
20 #endif
21 #if defined(FEATURE_ACCESS_REGISTERS)
22 _DAT_C_STATIC U16 ARCH_DEP(translate_alet) (U32 alet, U16 eax,
23         int acctype, REGS *regs, U32 *asteo, U32 aste[]);
24 _DAT_C_STATIC void ARCH_DEP(purge_alb_all) ();
25 _DAT_C_STATIC void ARCH_DEP(purge_alb) (REGS *regs);
26 #endif
27 _DAT_C_STATIC int ARCH_DEP(translate_addr) (VADR vaddr, int arn,
28         REGS *regs, int acctype);
29 _DAT_C_STATIC void ARCH_DEP(purge_tlb_all) ();
30 _DAT_C_STATIC void ARCH_DEP(purge_tlb) (REGS *regs);
31 _DAT_C_STATIC void ARCH_DEP(purge_tlbe_all) (RADR pfra);
32 _DAT_C_STATIC void ARCH_DEP(purge_tlbe) (REGS *regs, RADR pfra);
33 _DAT_C_STATIC void ARCH_DEP(invalidate_tlb) (REGS *regs, BYTE mask);
34 #if ARCH_MODE == ARCH_390 && defined(_900)
35 _DAT_C_STATIC void z900_invalidate_tlb (REGS *regs, BYTE mask);
36 #endif
37 _DAT_C_STATIC void ARCH_DEP(invalidate_tlbe) (REGS *regs, BYTE *main);
38 _DAT_C_STATIC void ARCH_DEP(invalidate_pte) (BYTE ibyte, RADR op1,
39         U32 op2, REGS *regs);
40 _LOGICAL_C_STATIC BYTE *ARCH_DEP(logical_to_main) (VADR addr, int arn,
41         REGS *regs, int acctype, BYTE akey);
42 
43 #if defined(_FEATURE_SIE) && ARCH_MODE != ARCH_900
44 _LOGICAL_C_STATIC BYTE *s390_logical_to_main (U32 addr, int arn, REGS *regs,
45         int acctype, BYTE akey);
46 _DAT_C_STATIC int s390_translate_addr (U32 vaddr, int arn, REGS *regs,
47         int acctype);
48 #endif /*defined(_FEATURE_SIE)*/
49 
50 #if defined(_FEATURE_ZSIE)
51 _LOGICAL_C_STATIC BYTE *z900_logical_to_main (U64 addr, int arn, REGS *regs,
52         int acctype, BYTE akey);
53 _DAT_C_STATIC int z900_translate_addr (U64 vaddr, int arn, REGS *regs,
54         int acctype);
55 #endif /*defined(_FEATURE_ZSIE)*/
56 
57 _VSTORE_C_STATIC void ARCH_DEP(vstorec) (void *src, BYTE len,
58         VADR addr, int arn, REGS *regs);
59 _VSTORE_C_STATIC void ARCH_DEP(vstoreb) (BYTE value, VADR addr,
60         int arn, REGS *regs);
61 _VSTORE_C_STATIC void ARCH_DEP(vstore2) (U16 value, VADR addr, int arn,
62         REGS *regs);
63 _VSTORE_C_STATIC void ARCH_DEP(vstore4) (U32 value, VADR addr, int arn,
64         REGS *regs);
65 _VSTORE_C_STATIC void ARCH_DEP(vstore8) (U64 value, VADR addr, int arn,
66         REGS *regs);
67 _VSTORE_C_STATIC void ARCH_DEP(vfetchc) (void *dest, BYTE len,
68         VADR addr, int arn, REGS *regs);
69 _VSTORE_C_STATIC BYTE ARCH_DEP(vfetchb) (VADR addr, int arn,
70         REGS *regs);
71 _VSTORE_C_STATIC U16 ARCH_DEP(vfetch2) (VADR addr, int arn,
72         REGS *regs);
73 _VSTORE_C_STATIC U32 ARCH_DEP(vfetch4) (VADR addr, int arn,
74         REGS *regs);
75 _VSTORE_C_STATIC U64 ARCH_DEP(vfetch8) (VADR addr, int arn,
76         REGS *regs);
77 _VSTORE_C_STATIC void ARCH_DEP(move_chars) (VADR addr1, int arn1,
78       BYTE key1, VADR addr2, int arn2, BYTE key2, int len, REGS *regs);
79 _VSTORE_C_STATIC void ARCH_DEP(validate_operand) (VADR addr, int arn,
80         int len, int acctype, REGS *regs);
81 _VFETCH_C_STATIC BYTE * ARCH_DEP(instfetch) (REGS *regs, int exec);
82 
83 #if defined(_FEATURE_SIE) && defined(_370) && !defined(_IEEE_C_)
84 _VFETCH_C_STATIC BYTE * s370_instfetch (REGS *regs, int exec);
85 #endif /*defined(_FEATURE_SIE)*/
86 
87 #if defined(_FEATURE_ZSIE) && defined(_900)
88 _VFETCH_C_STATIC BYTE * s390_instfetch (REGS *regs, int exec);
89 #endif /*defined(_FEATURE_ZSIE)*/
90 
91 #if !defined(_INLINE_H)
92 
93 #define _INLINE_H
94 
95 
96 /*-------------------------------------------------------------------*/
97 /* Add two unsigned fullwords giving an unsigned fullword result     */
98 /* and return the condition code for the AL or ALR instruction       */
99 /*-------------------------------------------------------------------*/
add_logical(U32 * result,U32 op1,U32 op2)100 static inline int add_logical(U32 *result, U32 op1, U32 op2)
101 {
102     *result = op1 + op2;
103     return (*result == 0 ? 0 : 1) | (op1 > *result ? 2 : 0);
104 } /* end function add_logical */
105 
106 
107 /*-------------------------------------------------------------------*/
108 /* Subtract two unsigned fullwords giving unsigned fullword result   */
109 /* and return the condition code for the SL or SLR instruction       */
110 /*-------------------------------------------------------------------*/
sub_logical(U32 * result,U32 op1,U32 op2)111 static inline int sub_logical(U32 *result, U32 op1, U32 op2)
112 {
113     *result = op1 - op2;
114     return (*result == 0 ? 0 : 1) | (op1 < *result ? 0 : 2);
115 } /* end function sub_logical */
116 
117 
118 /*-------------------------------------------------------------------*/
119 /* Add two signed fullwords giving a signed fullword result          */
120 /* and return the condition code for the A or AR instruction         */
121 /*-------------------------------------------------------------------*/
add_signed(U32 * result,U32 op1,U32 op2)122 static inline int add_signed(U32 *result, U32 op1, U32 op2)
123 {
124     *result = (S32)op1 + (S32)op2;
125 
126     return  ((S32)*result >  0) ?
127                 ((S32)op1 <  0 && (S32)op2 <  0) ? 3 : 2 :
128             ((S32)*result <  0) ?
129                 ((S32)op1 >= 0 && (S32)op2 >= 0) ? 3 : 1 :
130                 ((S32)op1 <  0 && (S32)op2 <  0) ? 3 : 0;
131 
132 /*    return (((S32)op1 < 0 && (S32)op2 < 0 && (S32)*result >= 0)
133       || ((S32)op1 >= 0 && (S32)op2 >= 0 && (S32)*result < 0)) ? 3 :
134                                               (S32)*result < 0 ? 1 :
135                                               (S32)*result > 0 ? 2 : 0; */
136 } /* end function add_signed */
137 
138 
139 /*-------------------------------------------------------------------*/
140 /* Subtract two signed fullwords giving a signed fullword result     */
141 /* and return the condition code for the S or SR instruction         */
142 /*-------------------------------------------------------------------*/
sub_signed(U32 * result,U32 op1,U32 op2)143 static inline int sub_signed(U32 *result, U32 op1, U32 op2)
144 {
145     *result = (S32)op1 - (S32)op2;
146 
147     return  ((S32)*result >  0) ?
148                 ((S32)op1 <  0 && (S32)op2 >= 0) ? 3 : 2 :
149             ((S32)*result <  0) ?
150                 ((S32)op1 >= 0 && (S32)op2 <  0) ? 3 : 1 :
151             ((S32)op1 <  0 && (S32)op2 >= 0) ? 3 : 0;
152 
153 /*    return (((S32)op1 < 0 && (S32)op2 >= 0 && (S32)*result >= 0)
154       || ((S32)op1 >= 0 && (S32)op2 < 0 && (S32)*result < 0)) ? 3 :
155                                              (S32)*result < 0 ? 1 :
156                                              (S32)*result > 0 ? 2 : 0; */
157 } /* end function sub_signed */
158 
159 
160 /*-------------------------------------------------------------------*/
161 /* Multiply two signed fullwords giving a signed doubleword result   */
162 /*-------------------------------------------------------------------*/
mul_signed(U32 * resulthi,U32 * resultlo,U32 op1,U32 op2)163 static inline void mul_signed ( U32 *resulthi, U32 *resultlo,
164                              U32 op1, U32 op2 )
165 {
166 S64 r;
167 
168     r = (S64)(S32)op1 * (S32)op2;
169     *resulthi = (U32)((U64)r >> 32);
170     *resultlo = (U32)((U64)r & 0xFFFFFFFF);
171 } /* end function mul_signed */
172 
173 
174 /*-------------------------------------------------------------------*/
175 /* Divide a signed doubleword dividend by a signed fullword divisor  */
176 /* giving a signed fullword remainder and a signed fullword quotient.*/
177 /* Returns 0 if successful, 1 if divide overflow.                    */
178 /*-------------------------------------------------------------------*/
div_signed(U32 * remainder,U32 * quotient,U32 dividendhi,U32 dividendlo,U32 divisor)179 static inline int div_signed ( U32 *remainder, U32 *quotient,
180               U32 dividendhi, U32 dividendlo, U32 divisor )
181 {
182 U64 dividend;
183 S64 quot, rem;
184 
185     if (divisor == 0) return 1;
186     dividend = (U64)dividendhi << 32 | dividendlo;
187     quot = (S64)dividend / (S32)divisor;
188     rem = (S64)dividend % (S32)divisor;
189     if (quot < -2147483648LL || quot > 2147483647LL) return 1;
190     *quotient = (U32)quot;
191     *remainder = (U32)rem;
192     return 0;
193 } /* end function div_signed */
194 
195 /*
196  * The following routines were moved from esame.c rev 1.139 21oct2005
197  */
198 
199 /*-------------------------------------------------------------------*/
200 /* Add two unsigned doublewords giving an unsigned doubleword result */
201 /* and return the condition code for the ALG or ALGR instruction     */
202 /*-------------------------------------------------------------------*/
add_logical_long(U64 * result,U64 op1,U64 op2)203 static inline int add_logical_long(U64 *result, U64 op1, U64 op2)
204 {
205     *result = op1 + op2;
206     return (*result == 0 ? 0 : 1) | (op1 > *result ? 2 : 0);
207 } /* end function add_logical_long */
208 
209 
210 /*-------------------------------------------------------------------*/
211 /* Subtract unsigned doublewords giving unsigned doubleword result   */
212 /* and return the condition code for the SLG or SLGR instruction     */
213 /*-------------------------------------------------------------------*/
sub_logical_long(U64 * result,U64 op1,U64 op2)214 static inline int sub_logical_long(U64 *result, U64 op1, U64 op2)
215 {
216     *result = op1 - op2;
217     return (*result == 0 ? 0 : 1) | (op1 < *result ? 0 : 2);
218 } /* end function sub_logical_long */
219 
220 
221 /*-------------------------------------------------------------------*/
222 /* Add two signed doublewords giving a signed doubleword result      */
223 /* and return the condition code for the AG or AGR instruction       */
224 /*-------------------------------------------------------------------*/
add_signed_long(U64 * result,U64 op1,U64 op2)225 static inline int add_signed_long(U64 *result, U64 op1, U64 op2)
226 {
227     *result = (S64)op1 + (S64)op2;
228 
229     return (((S64)op1 < 0 && (S64)op2 < 0 && (S64)*result >= 0)
230       || ((S64)op1 >= 0 && (S64)op2 >= 0 && (S64)*result < 0)) ? 3 :
231                                               (S64)*result < 0 ? 1 :
232                                               (S64)*result > 0 ? 2 : 0;
233 } /* end function add_signed_long */
234 
235 
236 /*-------------------------------------------------------------------*/
237 /* Subtract two signed doublewords giving signed doubleword result   */
238 /* and return the condition code for the SG or SGR instruction       */
239 /*-------------------------------------------------------------------*/
sub_signed_long(U64 * result,U64 op1,U64 op2)240 static inline int sub_signed_long(U64 *result, U64 op1, U64 op2)
241 {
242     *result = (S64)op1 - (S64)op2;
243 
244     return (((S64)op1 < 0 && (S64)op2 >= 0 && (S64)*result >= 0)
245       || ((S64)op1 >= 0 && (S64)op2 < 0 && (S64)*result < 0)) ? 3 :
246                                              (S64)*result < 0 ? 1 :
247                                              (S64)*result > 0 ? 2 : 0;
248 } /* end function sub_signed_long */
249 
250 
251 /*-------------------------------------------------------------------*/
252 /* Divide an unsigned 128-bit dividend by an unsigned 64-bit divisor */
253 /* giving unsigned 64-bit remainder and unsigned 64-bit quotient.    */
254 /* Returns 0 if successful, 1 if divide overflow.                    */
255 /*-------------------------------------------------------------------*/
div_logical_long(U64 * rem,U64 * quot,U64 high,U64 lo,U64 d)256 static inline int div_logical_long
257                   (U64 *rem, U64 *quot, U64 high, U64 lo, U64 d)
258 {
259     int i;
260 
261     *quot = 0;
262     if (high >= d) return 1;
263     for (i = 0; i < 64; i++)
264     {
265     int ovf;
266         ovf = high >> 63;
267         high = (high << 1) | (lo >> 63);
268         lo <<= 1;
269         *quot <<= 1;
270         if (high >= d || ovf)
271         {
272             *quot += 1;
273             high -= d;
274         }
275     }
276     *rem = high;
277     return 0;
278 } /* end function div_logical_long */
279 
280 
281 /*-------------------------------------------------------------------*/
282 /* Multiply two unsigned doublewords giving unsigned 128-bit result  */
283 /*-------------------------------------------------------------------*/
mult_logical_long(U64 * high,U64 * lo,U64 md,U64 mr)284 static inline int mult_logical_long
285                   (U64 *high, U64 *lo, U64 md, U64 mr)
286 {
287     int i;
288 
289     *high = 0; *lo = 0;
290     for (i = 0; i < 64; i++)
291     {
292     U64 ovf;
293         ovf = *high;
294         if (md & 1)
295             *high += mr;
296         md >>= 1;
297         *lo = (*lo >> 1) | (*high << 63);
298         if(ovf > *high)
299             *high = (*high >> 1) | 0x8000000000000000ULL;
300         else
301             *high >>= 1;
302     }
303     return 0;
304 } /* end function mult_logical_long */
305 
306 
307 #endif /*!defined(_INLINE_H)*/
308 
309 
310 /*-------------------------------------------------------------------*/
311 /* Test for fetch protected storage location.                        */
312 /*                                                                   */
313 /* Input:                                                            */
314 /*      addr    Logical address of storage location                  */
315 /*      skey    Storage key with fetch, reference, and change bits   */
316 /*              and one low-order zero appended                      */
317 /*      akey    Access key with 4 low-order zeroes appended          */
318 /*      regs    Pointer to the CPU register context                  */
319 /*      regs->dat.private  1=Location is in a private address space  */
320 /* Return value:                                                     */
321 /*      1=Fetch protected, 0=Not fetch protected                     */
322 /*-------------------------------------------------------------------*/
ARCH_DEP(is_fetch_protected)323 static inline int ARCH_DEP(is_fetch_protected) (VADR addr, BYTE skey,
324                     BYTE akey, REGS *regs)
325 {
326     UNREFERENCED_370(addr);
327     UNREFERENCED_370(regs);
328 
329     /* [3.4.1] Fetch is allowed if access key is zero, regardless
330        of the storage key and fetch protection bit */
331     /* [3.4.1] Fetch protection prohibits fetch if storage key fetch
332        protect bit is on and access key does not match storage key */
333     if (likely(akey == 0
334     || akey == (skey & STORKEY_KEY)
335     || !(skey & STORKEY_FETCH)))
336     return 0;
337 
338 #ifdef FEATURE_FETCH_PROTECTION_OVERRIDE
339     /* [3.4.1.2] Fetch protection override allows fetch from first
340        2K of non-private address spaces if CR0 bit 6 is set */
341     if (addr < 2048
342     && (regs->CR(0) & CR0_FETCH_OVRD)
343     && regs->dat.private == 0)
344     return 0;
345 #endif /*FEATURE_FETCH_PROTECTION_OVERRIDE*/
346 
347 #ifdef FEATURE_STORAGE_PROTECTION_OVERRIDE
348     /* [3.4.1.1] Storage protection override allows access to
349        locations with storage key 9, regardless of the access key,
350        provided that CR0 bit 7 is set */
351     if ((skey & STORKEY_KEY) == 0x90
352     && (regs->CR(0) & CR0_STORE_OVRD))
353     return 0;
354 #endif /*FEATURE_STORAGE_PROTECTION_OVERRIDE*/
355 
356     /* Return one if location is fetch protected */
357     return 1;
358 
359 } /* end function is_fetch_protected */
360 
361 /*-------------------------------------------------------------------*/
362 /* Test for low-address protection.                                  */
363 /*                                                                   */
364 /* Input:                                                            */
365 /*      addr    Logical address of storage location                  */
366 /*      regs    Pointer to the CPU register context                  */
367 /*      regs->dat.private  1=Location is in a private address space  */
368 /* Return value:                                                     */
369 /*      1=Low-address protected, 0=Not low-address protected         */
370 /*-------------------------------------------------------------------*/
ARCH_DEP(is_low_address_protected)371 static inline int ARCH_DEP(is_low_address_protected) (VADR addr,
372                                               REGS *regs)
373 {
374 #if defined (FEATURE_ESAME)
375     /* For ESAME, low-address protection applies to locations
376        0-511 (0000-01FF) and 4096-4607 (1000-11FF) */
377     if (addr & 0xFFFFFFFFFFFFEE00ULL)
378 #else /*!defined(FEATURE_ESAME)*/
379     /* For S/370 and ESA/390, low-address protection applies
380        to locations 0-511 only */
381     if (addr > 511)
382 #endif /*!defined(FEATURE_ESAME)*/
383         return 0;
384 
385     /* Low-address protection applies only if the low-address
386        protection control bit in control register 0 is set */
387     if ((regs->CR(0) & CR0_LOW_PROT) == 0)
388         return 0;
389 
390 #if defined(_FEATURE_SIE)
391     /* Host low-address protection is not applied to guest
392        references to guest storage */
393     if (regs->sie_active)
394         return 0;
395 #endif /*defined(_FEATURE_SIE)*/
396 
397     /* Low-address protection does not apply to private address
398        spaces */
399     if (regs->dat.private)
400         return 0;
401 
402     /* Return one if location is low-address protected */
403     return 1;
404 
405 } /* end function is_low_address_protected */
406 
407 /*-------------------------------------------------------------------*/
408 /* Test for store protected storage location.                        */
409 /*                                                                   */
410 /* Input:                                                            */
411 /*      addr    Logical address of storage location                  */
412 /*      skey    Storage key with fetch, reference, and change bits   */
413 /*              and one low-order zero appended                      */
414 /*      akey    Access key with 4 low-order zeroes appended          */
415 /*      regs    Pointer to the CPU register context                  */
416 /*      regs->dat.private  1=Location is in a private address space  */
417 /*      regs->dat.protect  1=Access list protected or page protected */
418 /* Return value:                                                     */
419 /*      1=Store protected, 0=Not store protected                         */
420 /*-------------------------------------------------------------------*/
ARCH_DEP(is_store_protected)421 static inline int ARCH_DEP(is_store_protected) (VADR addr, BYTE skey,
422                BYTE akey, REGS *regs)
423 {
424     /* [3.4.4] Low-address protection prohibits stores into certain
425        locations in the prefixed storage area of non-private address
426        address spaces, if the low-address control bit in CR0 is set,
427        regardless of the access key and storage key */
428     if (ARCH_DEP(is_low_address_protected) (addr, regs))
429         return 1;
430 
431     /* Access-list controlled protection prohibits all stores into
432        the address space, and page protection prohibits all stores
433        into the page, regardless of the access key and storage key */
434     if (regs->dat.protect)
435         return 1;
436 #if defined(_FEATURE_SIE)
437     if(SIE_MODE(regs) && regs->hostregs->dat.protect)
438         return 1;
439 #endif
440 
441     /* [3.4.1] Store is allowed if access key is zero, regardless
442        of the storage key */
443     if (akey == 0)
444         return 0;
445 
446 #ifdef FEATURE_STORAGE_PROTECTION_OVERRIDE
447     /* [3.4.1.1] Storage protection override allows access to
448        locations with storage key 9, regardless of the access key,
449        provided that CR0 bit 7 is set */
450     if ((skey & STORKEY_KEY) == 0x90
451         && (regs->CR(0) & CR0_STORE_OVRD))
452         return 0;
453 #endif /*FEATURE_STORAGE_PROTECTION_OVERRIDE*/
454 
455     /* [3.4.1] Store protection prohibits stores if the access
456        key does not match the storage key */
457     if (akey != (skey & STORKEY_KEY))
458         return 1;
459 
460     /* Return zero if location is not store protected */
461     return 0;
462 
463 } /* end function is_store_protected */
464 
465 
466 /*-------------------------------------------------------------------*/
467 /* Return mainstor address of absolute address.                      */
468 /* The caller is assumed to have already checked that the absolute   */
469 /* address is within the limit of main storage.                      */
470 /*-------------------------------------------------------------------*/
471 #if defined(INLINE_STORE_FETCH_ADDR_CHECK)
ARCH_DEP(fetch_main_absolute)472 static inline BYTE *ARCH_DEP(fetch_main_absolute) (RADR addr,
473                                 REGS *regs, int len)
474 #else
475 static inline BYTE *ARCH_DEP(fetch_main_absolute) (RADR addr,
476                                 REGS *regs)
477 #endif
478 {
479 #if defined(INLINE_STORE_FETCH_ADDR_CHECK)
480     if(addr > regs->mainlim - len)
481         regs->program_interrupt (regs, PGM_ADDRESSING_EXCEPTION);
482 #endif /*defined(INLINE_STORE_FETCH_ADDR_CHECK)*/
483 
484     SIE_TRANSLATE(&addr, ACCTYPE_READ, regs);
485 
486     /* Set the main storage reference bit */
487     STORAGE_KEY(addr, regs) |= STORKEY_REF;
488 
489     /* Return absolute storage mainstor address */
490     return (regs->mainstor + addr);
491 
492 } /* end function fetch_main_absolute */
493 
494 
495 /*-------------------------------------------------------------------*/
496 /* Fetch a doubleword from absolute storage.                         */
497 /* The caller is assumed to have already checked that the absolute   */
498 /* address is within the limit of main storage.                      */
499 /* All bytes of the word are fetched concurrently as observed by     */
500 /* other CPUs.  The doubleword is first fetched as an integer, then  */
501 /* the bytes are reversed into host byte order if necessary.         */
502 /*-------------------------------------------------------------------*/
ARCH_DEP(fetch_doubleword_absolute)503 static inline U64 ARCH_DEP(fetch_doubleword_absolute) (RADR addr,
504                                 REGS *regs)
505 {
506  // The change below affects 32 bit hosts that use something like
507  // cmpxchg8b to fetch the doubleword concurrently.
508  // This routine is mainly called by DAT in 64 bit guest mode
509  // to access DAT-related values.  In most `well-behaved' OS's,
510  // other CPUs should not be interfering with these values
511  #if !defined(OPTION_STRICT_ALIGNMENT)
512     return CSWAP64(*(U64 *)FETCH_MAIN_ABSOLUTE(addr, regs, 8));
513  #else
514     return fetch_dw(FETCH_MAIN_ABSOLUTE(addr, regs, 8));
515  #endif
516 } /* end function fetch_doubleword_absolute */
517 
518 
519 /*-------------------------------------------------------------------*/
520 /* Fetch a fullword from absolute storage.                           */
521 /* The caller is assumed to have already checked that the absolute   */
522 /* address is within the limit of main storage.                      */
523 /* All bytes of the word are fetched concurrently as observed by     */
524 /* other CPUs.  The fullword is first fetched as an integer, then    */
525 /* the bytes are reversed into host byte order if necessary.         */
526 /*-------------------------------------------------------------------*/
ARCH_DEP(fetch_fullword_absolute)527 static inline U32 ARCH_DEP(fetch_fullword_absolute) (RADR addr,
528                                 REGS *regs)
529 {
530     return fetch_fw(FETCH_MAIN_ABSOLUTE(addr, regs, 4));
531 } /* end function fetch_fullword_absolute */
532 
533 
534 /*-------------------------------------------------------------------*/
535 /* Fetch a halfword from absolute storage.                           */
536 /* The caller is assumed to have already checked that the absolute   */
537 /* address is within the limit of main storage.                      */
538 /* All bytes of the halfword are fetched concurrently as observed by */
539 /* other CPUs.  The halfword is first fetched as an integer, then    */
540 /* the bytes are reversed into host byte order if necessary.         */
541 /*-------------------------------------------------------------------*/
ARCH_DEP(fetch_halfword_absolute)542 static inline U16 ARCH_DEP(fetch_halfword_absolute) (RADR addr,
543                                 REGS *regs)
544 {
545     return fetch_hw(FETCH_MAIN_ABSOLUTE(addr, regs, 2));
546 } /* end function fetch_halfword_absolute */
547 
548 
549 /*-------------------------------------------------------------------*/
550 /* Store doubleword into absolute storage.                           */
551 /* All bytes of the word are stored concurrently as observed by      */
552 /* other CPUs.  The bytes of the word are reversed if necessary      */
553 /* and the word is then stored as an integer in absolute storage.    */
554 /*-------------------------------------------------------------------*/
ARCH_DEP(store_doubleword_absolute)555 static inline void ARCH_DEP(store_doubleword_absolute) (U64 value,
556                           RADR addr, REGS *regs)
557 {
558 #if defined(INLINE_STORE_FETCH_ADDR_CHECK)
559     if(addr > regs->mainlim - 8)
560         regs->program_interrupt (regs, PGM_ADDRESSING_EXCEPTION);
561 #endif /*defined(INLINE_STORE_FETCH_ADDR_CHECK)*/
562 
563     SIE_TRANSLATE(&addr, ACCTYPE_WRITE, regs);
564 
565     /* Set the main storage reference and change bits */
566     STORAGE_KEY(addr, regs) |= (STORKEY_REF | STORKEY_CHANGE);
567 
568     /* Store the doubleword into absolute storage */
569     store_dw(regs->mainstor + addr, value);
570 
571 } /* end function store_doubleword_absolute */
572 
573 
574 /*-------------------------------------------------------------------*/
575 /* Store a fullword into absolute storage.                           */
576 /* All bytes of the word are stored concurrently as observed by      */
577 /* other CPUs.  The bytes of the word are reversed if necessary      */
578 /* and the word is then stored as an integer in absolute storage.    */
579 /*-------------------------------------------------------------------*/
ARCH_DEP(store_fullword_absolute)580 static inline void ARCH_DEP(store_fullword_absolute) (U32 value,
581                           RADR addr, REGS *regs)
582 {
583 #if defined(INLINE_STORE_FETCH_ADDR_CHECK)
584     if(addr > regs->mainlim - 4)
585         regs->program_interrupt (regs, PGM_ADDRESSING_EXCEPTION);
586 #endif /*defined(INLINE_STORE_FETCH_ADDR_CHECK)*/
587 
588     SIE_TRANSLATE(&addr, ACCTYPE_WRITE, regs);
589 
590     /* Set the main storage reference and change bits */
591     STORAGE_KEY(addr, regs) |= (STORKEY_REF | STORKEY_CHANGE);
592 
593     /* Store the fullword into absolute storage */
594     store_fw(regs->mainstor + addr, value);
595 
596 } /* end function store_fullword_absolute */
597 
598 
599 /*-------------------------------------------------------------------*/
600 /* Perform subspace replacement                                      */
601 /*                                                                   */
602 /* Input:                                                            */
603 /*      std     Original segment table designation (STD) or ASCE     */
604 /*      asteo   ASTE origin obtained by ASN translation              */
605 /*      xcode   Pointer to field to receive exception code, or NULL  */
606 /*      regs    Pointer to the CPU register context                  */
607 /*                                                                   */
608 /* Output:                                                           */
609 /*      xcode   Exception code or zero (if xcode is not NULL)        */
610 /*                                                                   */
611 /* Return value:                                                     */
612 /*      On successful completion, the exception code field (if not   */
613 /*      NULL) is set to zero, and the function return value is the   */
614 /*      STD resulting from subspace replacement, or is the original  */
615 /*      STD if subspace replacement is not applicable.               */
616 /*                                                                   */
617 /* Operation:                                                        */
618 /*      If the ASF control is enabled, and the STD or ASCE is a      */
619 /*      member of a subspace-group (bit 22 is one), and the          */
620 /*      dispatchable unit is subspace active (DUCT word 1 bit 0 is   */
621 /*      one), and the ASTE obtained by ASN translation is the ASTE   */
622 /*      for the base space of the dispatchable unit, then the STD    */
623 /*      or ASCE is replaced (except for the event control bits) by   */
624 /*      the STD or ASCE from the ASTE for the subspace in which the  */
625 /*      dispatchable unit last had control; otherwise the STD or     */
626 /*      ASCE remains unchanged.                                      */
627 /*                                                                   */
628 /* Error conditions:                                                 */
629 /*      If an ASTE validity exception or ASTE sequence exception     */
630 /*      occurs, and the xcode parameter is a non-NULL pointer,       */
631 /*      then the exception code is returned in the xcode field       */
632 /*      and the function return value is zero.                       */
633 /*      For all other error conditions a program check is generated  */
634 /*      and the function does not return.                            */
635 /*                                                                   */
636 /*-------------------------------------------------------------------*/
ARCH_DEP(subspace_replace)637 static inline RADR ARCH_DEP(subspace_replace) (RADR std, U32 asteo,
638                         U16 *xcode, REGS *regs)
639 {
640 U32     ducto;                          /* DUCT origin               */
641 U32     duct0;                          /* DUCT word 0               */
642 U32     duct1;                          /* DUCT word 1               */
643 U32     duct3;                          /* DUCT word 3               */
644 U32     ssasteo;                        /* Subspace ASTE origin      */
645 U32     ssaste[16];                     /* Subspace ASTE             */
646 BYTE    *p;                             /* Mainstor pointer          */
647 
648     /* Clear the exception code field, if provided */
649     if (xcode != NULL) *xcode = 0;
650 
651     /* Return the original STD unchanged if the address-space function
652        control (CR0 bit 15) is zero, or if the subspace-group control
653        (bit 22 of the STD) is zero */
654     if (!ASF_ENABLED(regs)
655         || (std & SSGROUP_BIT) == 0)
656         return std;
657 
658     /* Load the DUCT origin address */
659     ducto = regs->CR(2) & CR2_DUCTO;
660     ducto = APPLY_PREFIXING (ducto, regs->PX);
661 
662     /* Program check if DUCT origin address is invalid */
663     if (ducto > regs->mainlim)
664         regs->program_interrupt (regs, PGM_ADDRESSING_EXCEPTION);
665 
666     /* Fetch DUCT words 0, 1, and 3 from absolute storage
667        (note: the DUCT cannot cross a page boundary) */
668     p = FETCH_MAIN_ABSOLUTE(ducto, regs, 16);
669     duct0 = fetch_fw(p);
670     duct1 = fetch_fw(p+4);
671     duct3 = fetch_fw(p+12);
672 
673     /* Return the original STD unchanged if the dispatchable unit is
674        not subspace active or if the ASTE obtained by ASN translation
675        is not the same as the base ASTE for the dispatchable unit */
676     if ((duct1 & DUCT1_SA) == 0
677         || asteo != (duct0 & DUCT0_BASTEO))
678         return std;
679 
680     /* Load the subspace ASTE origin from the DUCT */
681     ssasteo = duct1 & DUCT1_SSASTEO;
682     ssasteo = APPLY_PREFIXING (ssasteo, regs->PX);
683 
684     /* Program check if ASTE origin address is invalid */
685     if (ssasteo > regs->mainlim)
686         regs->program_interrupt (regs, PGM_ADDRESSING_EXCEPTION);
687 
688     /* Fetch subspace ASTE words 0, 2, 3, and 5 from absolute
689        storage (note: the ASTE cannot cross a page boundary) */
690     p = FETCH_MAIN_ABSOLUTE(ssasteo, regs, 24);
691     ssaste[0] = fetch_fw(p);
692     ssaste[2] = fetch_fw(p+8);
693 #if defined(FEATURE_ESAME)
694     ssaste[3] = fetch_fw(p+12);
695 #endif /*defined(FEATURE_ESAME)*/
696     ssaste[5] = fetch_fw(p+20);
697 
698     /* ASTE validity exception if subspace ASTE invalid bit is one */
699     if (ssaste[0] & ASTE0_INVALID)
700     {
701         regs->excarid = 0;
702         if (xcode == NULL)
703             regs->program_interrupt (regs, PGM_ASTE_VALIDITY_EXCEPTION);
704         else
705             *xcode = PGM_ASTE_VALIDITY_EXCEPTION;
706         return 0;
707     }
708 
709     /* ASTE sequence exception if the subspace ASTE sequence
710        number does not match the sequence number in the DUCT */
711     if ((ssaste[5] & ASTE5_ASTESN) != (duct3 & DUCT3_SSASTESN))
712     {
713         regs->excarid = 0;
714         if (xcode == NULL)
715             regs->program_interrupt (regs, PGM_ASTE_SEQUENCE_EXCEPTION);
716         else
717             *xcode = PGM_ASTE_SEQUENCE_EXCEPTION;
718         return 0;
719     }
720 
721     /* Replace the STD or ASCE with the subspace ASTE STD or ASCE,
722        except for the space switch event bit and the storage
723        alteration event bit, which remain unchanged */
724     std &= (SSEVENT_BIT | SAEVENT_BIT);
725     std |= (ASTE_AS_DESIGNATOR(ssaste)
726                 & ~((RADR)(SSEVENT_BIT | SAEVENT_BIT)));
727 
728     /* Return the STD resulting from subspace replacement */
729     return std;
730 
731 } /* end function subspace_replace */
732 
733 
734 #include "dat.h"
735 
736 #include "vstore.h"
737 
738 /* end of INLINE.H */
739